bool CLightningCannon::TryTarget(const float3& pos, bool userTarget, CUnit* unit) { if (!CWeapon::TryTarget(pos, userTarget, unit)) return false; if (!weaponDef->waterweapon && TargetUnitOrPositionInWater(pos, unit)) return false; float3 dir = pos - weaponMuzzlePos; float length = dir.Length(); if (length == 0) return true; dir /= length; if (!HaveFreeLineOfFire(weaponMuzzlePos, dir, length, unit)) { return false; } if (avoidFeature && TraceRay::LineFeatureCol(weaponMuzzlePos, dir, length)) { return false; } if (avoidFriendly && TraceRay::TestAllyCone(weaponMuzzlePos, dir, length, (accuracy + sprayAngle), owner->allyteam, owner)) { return false; } if (avoidNeutral && TraceRay::TestNeutralCone(weaponMuzzlePos, dir, length, (accuracy + sprayAngle), owner)) { return false; } return true; }
bool CBeamLaser::TryTarget(const float3& pos, bool userTarget, CUnit* unit) { if (!CWeapon::TryTarget(pos, userTarget, unit)) return false; if (!weaponDef->waterweapon) { if (unit) { if (unit->isUnderWater) return false; } else { if (pos.y < 0) return false; } } float3 dir = pos - weaponMuzzlePos; float length = dir.Length(); if (length == 0) return true; dir /= length; if (!onlyForward) { if (!HaveFreeLineOfFire(weaponMuzzlePos, dir, length, unit)) { return false; } } const float spread = (accuracy + sprayAngle) * (1.0f - owner->limExperience * weaponDef->ownerExpAccWeight); if (avoidFeature && TraceRay::LineFeatureCol(weaponMuzzlePos, dir, length)) { return false; } if (avoidFriendly && TraceRay::TestAllyCone(weaponMuzzlePos, dir, length, spread, owner->allyteam, owner)) { return false; } if (avoidNeutral && TraceRay::TestNeutralCone(weaponMuzzlePos, dir, length, spread, owner)) { return false; } return true; }
bool CMissileLauncher::TryTarget(const float3& pos, bool userTarget, CUnit* unit) { if (!CWeapon::TryTarget(pos, userTarget, unit)) return false; if (!weaponDef->waterweapon) { if (unit) { if (unit->isUnderWater) { return false; } } else { if (pos.y < 0) return false; } } float3 dir = pos - weaponMuzzlePos; if (weaponDef->trajectoryHeight > 0) { // do a different test depending on if the missile has a high trajectory or not float3 flatdir(dir.x, 0, dir.z); dir.Normalize(); 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 gc = ((collisionFlags & Collision::NOGROUND) == 0)? ground->TrajectoryGroundCol(weaponMuzzlePos, flatdir, flatlength - 30, linear, quadratic): -1.0f; if (gc > 0.0f) return false; if (avoidFriendly && TraceRay::TestTrajectoryAllyCone(weaponMuzzlePos, flatdir, flatlength - 30, linear, quadratic, 0, 8, owner->allyteam, owner)) { return false; } if (avoidNeutral && TraceRay::TestTrajectoryNeutralCone(weaponMuzzlePos, flatdir, flatlength - 30, linear, quadratic, 0, 8, owner)) { return false; } } else { float length = dir.Length(); if (length == 0) return true; dir /= length; if (!onlyForward) { if (!HaveFreeLineOfFire(weaponMuzzlePos, dir, length)) { return false; } } else { float3 goaldir = pos - owner->pos; goaldir.Normalize(); if (owner->frontdir.dot(goaldir) < maxAngleDif) return false; } if (avoidFriendly && TraceRay::TestAllyCone(weaponMuzzlePos, dir, length, (accuracy + sprayAngle), owner->allyteam, owner)) { return false; } if (avoidNeutral && TraceRay::TestNeutralCone(weaponMuzzlePos, dir, length, (accuracy + sprayAngle), owner)) { return false; } } return true; }