// Fire an anti-missile. Returns true if the missile should be killed. bool Armament::Weapon::FireAntiMissile(Ship &ship, const Projectile &projectile, list<Effect> &effects) { int strength = outfit->AntiMissile(); if(!strength) return false; double range = outfit->Velocity(); // Check if the missile is in range. Point start = ship.Position() + ship.Facing().Rotate(point); Point offset = projectile.Position() - start; if(offset.Length() > range) return false; // Figure out where the effect should be placed. Anti-missiles do not create // projectiles; they just create a blast animation. start += (.5 * range) * offset.Unit(); Angle aim = TO_DEG * atan2(offset.X(), -offset.Y()); for(const auto &eit : outfit->HitEffects()) for(int i = 0; i < eit.second; ++i) { effects.push_back(*eit.first); effects.back().Place(start, ship.Velocity(), aim); } Fire(ship); return (Random::Int(strength) > Random::Int(projectile.MissileStrength())); }
double AsteroidField::Asteroid::Collide(const Projectile &projectile, int step) const { Point pos = location - projectile.Position(); pos = Point(-remainder(pos.X(), WRAP), -remainder(pos.Y(), WRAP)); return animation.GetMask(step).Collide(pos, projectile.Velocity(), angle); }
// This ship just got hit by the given projectile. Take damage according to // what sort of weapon the projectile it. int Ship::TakeDamage(const Projectile &projectile, bool isBlast) { int type = 0; const Outfit &weapon = projectile.GetWeapon(); double shieldDamage = weapon.ShieldDamage(); double hullDamage = weapon.HullDamage(); double hitForce = weapon.HitForce(); double heatDamage = weapon.HeatDamage(); double ionDamage = weapon.IonDamage(); bool wasDisabled = IsDisabled(); bool wasDestroyed = IsDestroyed(); if(shields > shieldDamage) { shields -= shieldDamage; heat += .5 * heatDamage; ionization += .5 * ionDamage; } else if(!shields || shieldDamage) { if(shieldDamage) { hullDamage *= (1. - (shields / shieldDamage)); shields = 0.; } hull -= hullDamage; heat += heatDamage; ionization += ionDamage; } if(hitForce && !IsHyperspacing()) { Point d = position - projectile.Position(); double distance = d.Length(); if(distance) ApplyForce((hitForce / distance) * d); } if(!wasDisabled && IsDisabled()) type |= ShipEvent::DISABLE; if(!wasDestroyed && IsDestroyed()) type |= ShipEvent::DESTROY; // If this ship was hit directly and did not consider itself an enemy of the // ship that hit it, it is now "provoked" against that government. if(!isBlast && projectile.GetGovernment() && !projectile.GetGovernment()->IsEnemy(government) && (Shields() < .9 || Hull() < .9 || !personality.IsForbearing()) && !personality.IsPacifist()) type |= ShipEvent::PROVOKE; return type; }