Skip to content

Commit

Permalink
feat(enhancement): Added tags that stop projectiles from colliding wi…
Browse files Browse the repository at this point in the history
…th different object types (#9823)
  • Loading branch information
Amazinite committed Feb 25, 2024
1 parent dcce48a commit 340479a
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 12 deletions.
29 changes: 17 additions & 12 deletions source/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2147,12 +2147,15 @@ void Engine::DoCollisions(Projectile &projectile)
// shields the ship (unless the projectile has a blast radius).
vector<Collision> collisions;
const Government *gov = projectile.GetGovernment();
const Weapon &weapon = projectile.GetWeapon();

if(projectile.ShouldExplode())
collisions.emplace_back(nullptr, CollisionType::NONE, 0.);
else if(projectile.GetWeapon().IsPhasing() && projectile.Target())
else if(weapon.IsPhasing() && projectile.Target())
{
// "Phasing" projectiles that have a target will never hit any other ship.
// They also don't care whether the weapon has "no ship collisions" on, as
// otherwise a phasing projectile would never hit anything.
shared_ptr<Ship> target = projectile.TargetPtr();
if(target)
{
Expand All @@ -2165,7 +2168,7 @@ void Engine::DoCollisions(Projectile &projectile)
else
{
// For weapons with a trigger radius, check if any detectable object will set it off.
double triggerRadius = projectile.GetWeapon().TriggerRadius();
double triggerRadius = weapon.TriggerRadius();
if(triggerRadius)
for(const Body *body : shipCollisions.Circle(projectile.Position(), triggerRadius))
if(body == projectile.Target() || (gov->IsEnemy(body->GetGovernment())
Expand All @@ -2178,16 +2181,18 @@ void Engine::DoCollisions(Projectile &projectile)
// If nothing triggered the projectile, check for collisions with ships and asteroids.
if(collisions.empty())
{
const vector<Collision> &newShipHits = shipCollisions.Line(projectile);
collisions.insert(collisions.end(), newShipHits.begin(), newShipHits.end());

// "Phasing" projectiles can pass through asteroids. For all other
// projectiles, check if they've hit an asteroid.
if(!projectile.GetWeapon().IsPhasing())
if(weapon.CanCollideShips())
{
const vector<Collision> &newShipHits = shipCollisions.Line(projectile);
collisions.insert(collisions.end(), newShipHits.begin(), newShipHits.end());
}
if(weapon.CanCollideAsteroids())
{
const vector<Collision> &newAsteroidHits = asteroids.CollideAsteroids(projectile);
collisions.insert(collisions.end(), newAsteroidHits.begin(), newAsteroidHits.end());

}
if(weapon.CanCollideMinables())
{
const vector<Collision> &newMinableHits = asteroids.CollideMinables(projectile);
collisions.insert(collisions.end(), newMinableHits.begin(), newMinableHits.end());
}
Expand All @@ -2197,7 +2202,7 @@ void Engine::DoCollisions(Projectile &projectile)
// Sort the Collisions by increasing range so that the closer collisions are evaluated first.
sort(collisions.begin(), collisions.end());

// Run all collisiions until either the projectile dies or there are no more collisions left.
// Run all collisions until either the projectile dies or there are no more collisions left.
for(Collision &collision : collisions)
{
Body *hit = collision.HitBody();
Expand All @@ -2217,13 +2222,13 @@ void Engine::DoCollisions(Projectile &projectile)
// If this projectile has a blast radius, find all ships within its
// radius. Otherwise, only one is damaged.
// TODO: Also deal blast damage to minables?
double blastRadius = projectile.GetWeapon().BlastRadius();
double blastRadius = weapon.BlastRadius();
if(blastRadius)
{
// Even friendly ships can be hit by the blast, unless it is a
// "safe" weapon.
Point hitPos = projectile.Position() + range * projectile.Velocity();
bool isSafe = projectile.GetWeapon().IsSafe();
bool isSafe = weapon.IsSafe();
for(Body *body : shipCollisions.Circle(hitPos, blastRadius))
{
Ship *ship = reinterpret_cast<Ship *>(body);
Expand Down
12 changes: 12 additions & 0 deletions source/Weapon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ void Weapon::LoadWeapon(const DataNode &node)
else if(key == "safe")
isSafe = true;
else if(key == "phasing")
{
isPhasing = true;
// Phasing projectiles implicitly have no asteroid collisions
// for reverse compatibility.
canCollideAsteroids = false;
canCollideMinables = false;
}
else if(key == "no damage scaling")
isDamageScaled = false;
else if(key == "parallel")
Expand All @@ -60,6 +66,12 @@ void Weapon::LoadWeapon(const DataNode &node)
isGravitational = true;
else if(key == "fused")
isFused = true;
else if(key == "no ship collisions")
canCollideShips = false;
else if(key == "no asteroid collisions")
canCollideAsteroids = false;
else if(key == "no minable collisions")
canCollideMinables = false;
else if(child.Size() < 2)
child.PrintTrace("Skipping weapon attribute with no value specified:");
else if(key == "sprite")
Expand Down
10 changes: 10 additions & 0 deletions source/Weapon.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ class Weapon {
// instead of simply disappearing or only creating a die effect. Blast radius
// weapons will cause a blast at the end of their lifetime.
bool IsFused() const;
// Whether projectiles from this weapon can directly collide with objects.
bool CanCollideShips() const;
bool CanCollideAsteroids() const;
bool CanCollideMinables() const;

// These values include all submunitions:
// Normal damage types:
Expand Down Expand Up @@ -244,6 +248,9 @@ class Weapon {
bool isDamageScaled = true;
bool isGravitational = false;
bool isFused = false;
bool canCollideShips = true;
bool canCollideAsteroids = true;
bool canCollideMinables = true;
// Guns and missiles are by default aimed a converged point at the
// maximum weapons range in front of the ship. When either the installed
// weapon or the gun-port (or both) have the isParallel attribute set
Expand Down Expand Up @@ -426,6 +433,9 @@ inline bool Weapon::IsPhasing() const { return isPhasing; }
inline bool Weapon::IsDamageScaled() const { return isDamageScaled; }
inline bool Weapon::IsGravitational() const { return isGravitational; }
inline bool Weapon::IsFused() const { return isFused; }
inline bool Weapon::CanCollideShips() const { return canCollideShips; }
inline bool Weapon::CanCollideAsteroids() const { return canCollideAsteroids; }
inline bool Weapon::CanCollideMinables() const { return canCollideMinables; }

inline double Weapon::ShieldDamage() const { return TotalDamage(SHIELD_DAMAGE); }
inline double Weapon::HullDamage() const { return TotalDamage(HULL_DAMAGE); }
Expand Down

0 comments on commit 340479a

Please sign in to comment.