float3 CCannon::GetWantedDir(const float3& diff) { // try to cache results, sacrifice some (not much too much even for a pewee) accuracy // it saves a dozen or two expensive calculations per second when 5 guardians // are shooting at several slow- and fast-moving targets if (math::fabs(diff.x - lastDiff.x) < (SQUARE_SIZE / 4.0f) && math::fabs(diff.y - lastDiff.y) < (SQUARE_SIZE / 4.0f) && math::fabs(diff.z - lastDiff.z) < (SQUARE_SIZE / 4.0f)) { return lastDir; } const float3 dir = GetWantedDir2(diff); lastDiff = diff; lastDir = dir; return dir; }
bool CCannon::HaveFreeLineOfFire(const float3& pos, bool userTarget, const CUnit* unit) const { if (!weaponDef->waterweapon && TargetUnitOrPositionInUnderWater(pos, unit)) return false; if (projectileSpeed == 0) { return true; } float3 dif(pos - weaponMuzzlePos); float3 dir(GetWantedDir2(dif)); if (dir.SqLength() == 0) { return false; } float3 flatDir(dif.x, 0, dif.z); float flatLength = flatDir.Length(); if (flatLength == 0) { return true; } flatDir /= flatLength; const float linear = dir.y; const float quadratic = gravity / (projectileSpeed * projectileSpeed) * 0.5f; const float gc = ((collisionFlags & Collision::NOGROUND) == 0)? ground->TrajectoryGroundCol(weaponMuzzlePos, flatDir, flatLength - 10, linear, quadratic): -1.0f; if (gc > 0.0f) { return false; } const float spread = ((accuracy + sprayAngle) * 0.6f) * ((1.0f - owner->limExperience * weaponDef->ownerExpAccWeight) * 0.9f); const float modFlatLength = flatLength - 30.0f; //FIXME add a forcedUserTarget (a forced fire mode enabled with meta key or something) and skip the test below then if (TraceRay::TestTrajectoryCone(weaponMuzzlePos, flatDir, modFlatLength, dir.y, quadratic, spread, owner->allyteam, avoidFlags, owner)) { return false; } return true; }
bool CCannon::HaveFreeLineOfFire(const float3& pos, bool userTarget, const CUnit* unit) const { // assume we can still fire at partially submerged targets if (!weaponDef->waterweapon && TargetUnitOrPositionUnderWater(pos, unit)) return false; if (projectileSpeed == 0) { return true; } float3 dif(pos - weaponMuzzlePos); float3 dir(GetWantedDir2(dif)); if (dir.SqLength() == 0) { return false; } float3 flatDir(dif.x, 0, dif.z); float flatLength = flatDir.Length(); if (flatLength == 0) { return true; } flatDir /= flatLength; const float linear = dir.y; const float quadratic = gravity / (projectileSpeed * projectileSpeed) * 0.5f; const float groundDist = ((avoidFlags & Collision::NOGROUND) == 0)? CGround::TrajectoryGroundCol(weaponMuzzlePos, flatDir, flatLength - 10, linear, quadratic): -1.0f; const float spread = (AccuracyExperience() + SprayAngleExperience()) * 0.6f * 0.9f; if (groundDist > 0.0f) { return false; } //FIXME add a forcedUserTarget (a forced fire mode enabled with meta key or something) and skip the test below then if (TraceRay::TestTrajectoryCone(weaponMuzzlePos, flatDir, flatLength, dir.y, quadratic, spread, owner->allyteam, avoidFlags, owner)) { return false; } return true; }