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; }
bool CMissileLauncher::HaveFreeLineOfFire(const float3& pos, bool userTarget, const CUnit* unit) const { // do a different test depending on if the missile has high // trajectory (parabolic vs. linear ground intersection) if (weaponDef->trajectoryHeight <= 0.0f) return CWeapon::HaveFreeLineOfFire(pos, userTarget, unit); float3 dir(pos - weaponMuzzlePos); float3 flatDir(dir.x, 0, dir.z); dir.SafeNormalize(); float flatLength = flatDir.Length(); if (flatLength == 0) return true; flatDir /= flatLength; const float linear = dir.y + weaponDef->trajectoryHeight; const float quadratic = -weaponDef->trajectoryHeight / flatLength; const float groundDist = ((avoidFlags & Collision::NOGROUND) == 0)? ground->TrajectoryGroundCol(weaponMuzzlePos, flatDir, flatLength - 30, linear, quadratic): -1.0f; // FIXME: _WHY_ the 30-elmo subtraction? const float modFlatLength = flatLength - 30.0f; if (groundDist > 0.0f) return false; if (TraceRay::TestTrajectoryCone(weaponMuzzlePos, flatDir, modFlatLength, linear, quadratic, 0, owner->allyteam, avoidFlags, owner)) { return false; } return true; }