void WeaponBase::Fire(glm::vec3 fireOrigin, glm::vec3 fireDirection) { fireAttempt = true; if (CanFire()) { storedAmmo -= GetRequiredAmmoToFire(); firingTime = fireRateInSeconds; coolingTime = cooldownInSeconds; FireInternal(fireOrigin, fireDirection); } else if (continualFire && firingTime > 0.0f) { // Continue fire weapons we can fire until firing time == 0, at which point we have to wait for the cooldown. FireInternal(fireOrigin, fireDirection); } }
void CBeamLaser::Update(void) { if(targetType!=Target_None){ weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x; if(!onlyForward){ wantedDir=targetPos-weaponPos; wantedDir.Normalize(); } predict=salvoSize/2; } CWeapon::Update(); if(lastFireFrame > gs->frameNum - 18 && lastFireFrame != gs->frameNum && weaponDef->sweepFire) { if (gs->Team(owner->team)->metal>=metalFireCost && gs->Team(owner->team)->energy>=energyFireCost) { owner->UseEnergy(energyFireCost / salvoSize); owner->UseMetal(metalFireCost / salvoSize); std::vector<int> args; args.push_back(0); owner->cob->Call(COBFN_QueryPrimary+weaponNum,args); CMatrix44f weaponMat = owner->localmodel->GetPieceMatrix(args[0]); float3 relWeaponPos = weaponMat.GetPos(); weaponPos=owner->pos+owner->frontdir*-relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*-relWeaponPos.x; float3 dir = owner->frontdir * weaponMat[10] + owner->updir * weaponMat[6] + -owner->rightdir * weaponMat[2]; FireInternal(dir, true); } } }
void CBeamLaser::Fire(void) { float3 dir; if (onlyForward && dynamic_cast<CAirMoveType*>(owner->moveType)) { // the taairmovetype can't align itself properly, change back when that is fixed dir = owner->frontdir; } else { if (salvoLeft == salvoSize - 1) { if (fireSoundId) sound->PlaySample(fireSoundId, owner, fireSoundVolume); dir = targetPos - weaponMuzzlePos; dir.Normalize(); oldDir = dir; } else if (weaponDef->beamburst) { if (fireSoundId && !weaponDef->soundTrigger) sound->PlaySample(fireSoundId, owner, fireSoundVolume); dir = targetPos-weaponMuzzlePos; dir.Normalize(); } else { dir = oldDir; } } dir += (salvoError) * (1 - owner->limExperience * 0.7f); dir.Normalize(); FireInternal(dir, false); }
void CBeamLaser::FireImpl(bool scriptCall) { // sweepfire must exclude regular fire (!) if (sweepFireState.IsSweepFiring()) return; FireInternal(GetFireDir(false, scriptCall)); }
void CBeamLaser::Update(void) { if (targetType != Target_None) { weaponPos = owner->pos + owner->frontdir * relWeaponPos.z + owner->updir * relWeaponPos.y + owner->rightdir * relWeaponPos.x; weaponMuzzlePos = owner->pos + owner->frontdir * relWeaponMuzzlePos.z + owner->updir * relWeaponMuzzlePos.y + owner->rightdir * relWeaponMuzzlePos.x; if (!onlyForward) { wantedDir = targetPos - weaponPos; wantedDir.ANormalize(); } if (!weaponDef->beamburst) { predict = salvoSize / 2; } else { // beamburst tracks the target during the burst so there's no need to lead predict = 0; } } CWeapon::Update(); if (lastFireFrame > gs->frameNum - 18 && lastFireFrame != gs->frameNum && weaponDef->sweepFire) { if (teamHandler->Team(owner->team)->metal >= metalFireCost && teamHandler->Team(owner->team)->energy >= energyFireCost) { owner->UseEnergy(energyFireCost / salvoSize); owner->UseMetal(metalFireCost / salvoSize); std::vector<int> args; args.push_back(0); owner->cob->Call(COBFN_QueryPrimary + weaponNum, args); CMatrix44f weaponMat = owner->cob->GetPieceMatrix(args[0]); const float3 relWeaponPos = weaponMat.GetPos(); const float3 dir = owner->frontdir * weaponMat[10] + owner->updir * weaponMat[ 6] + owner->rightdir * -weaponMat[ 2]; weaponPos = owner->pos + owner->frontdir * -relWeaponPos.z + owner->updir * relWeaponPos.y + owner->rightdir * -relWeaponPos.x; FireInternal(dir, true); } } }
void CBeamLaser::UpdateSweep() { // sweeping always happens between targets if (targetType == Target_None) { sweepFireState.SetSweepFiring(false); return; } if (!weaponDef->sweepFire) return; #if (!SWEEPFIRE_ENABLED) return; #endif // if current target position changed, start sweeping through a new arc if (sweepFireState.StartSweep(targetPos)) sweepFireState.Init(targetPos, weaponMuzzlePos); if (sweepFireState.IsSweepFiring()) sweepFireState.Update(GetFireDir(true, false)); // TODO: // also stop sweep if angle no longer changes, spawn // more intermediate beams for large angle and range? if (sweepFireState.StopSweep()) sweepFireState.SetSweepFiring(false); if (!sweepFireState.IsSweepFiring()) return; if (reloadStatus > gs->frameNum) return; if (teamHandler->Team(owner->team)->metal < metalFireCost) { return; } if (teamHandler->Team(owner->team)->energy < energyFireCost) { return; } owner->UseEnergy(energyFireCost / salvoSize); owner->UseMetal(metalFireCost / salvoSize); FireInternal(sweepFireState.GetSweepCurrDir()); // FIXME: // reloadStatus is normally only set in UpdateFire and only if CanFire // (which is not true during sweeping, the integration should be better) reloadStatus = gs->frameNum + int(reloadTime / owner->reloadSpeed); }
void CBeamLaser::FireImpl(void) { float3 dir; if (onlyForward && dynamic_cast<CStrafeAirMoveType*>(owner->moveType)) { // HoverAirMoveType cannot align itself properly, change back when that is fixed dir = owner->frontdir; } else { if (salvoLeft == salvoSize - 1) { dir = targetPos - weaponMuzzlePos; dir.SafeNormalize(); oldDir = dir; } else if (weaponDef->beamburst) { dir = targetPos - weaponMuzzlePos; dir.SafeNormalize(); } else { dir = oldDir; } } dir += ((salvoError) * (1.0f - owner->limExperience * weaponDef->ownerExpAccWeight)); dir.SafeNormalize(); FireInternal(dir, false); }