Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missile.cpp: yield based damage #4927

Closed
wants to merge 2 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 37 additions & 10 deletions src/Missile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,24 +172,51 @@ bool Missile::OnDamage(Object *attacker, float kgDamage, const CollisionContact
return true;
}

double calcAreaSphere(const double r) {
return 4.0*M_PI*r*r;
}

double calcAreaCircle(const double r) {
return M_PI*r*r;
}

void Missile::Explode()
{
Pi::game->GetSpace()->KillBody(this);

const double damageRadius = 200.0;
const double kgDamage = 10000.0;
double kgYield = 200.0; // yield of the used explosive in kg
const double jEnergyPerKgExplosive = 4.184e6; // energy density of explosive, here it's TNT

const double jYield = kgYield * jEnergyPerKgExplosive; // how much energy was converted in the explosion?

double queryRadius = 2000.0; // hardcoded to 2 km, this is sufficient for most explosions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why such a large distance compared to the old one?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just the query distance, not the "real" explosion distance. There is no real explosion distance due to the nature of an explosion in empty space. The spatial data structure which is queried has to know a maximum query distance.
I've chosen a relatively large distance to allow for a bigger yield without modifying the queryDistance too.
Note here that this doesn't have any effect on the performance because the query is done once and because space is relatively empty anyways. Not an issue in my opinion here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May I suggest adding a comment to that effect?

Suggested change
double queryRadius = 2000.0; // hardcoded to 2 km, this is sufficient for most explosions
// The radius in which to search for possible recipients of the damages
// Hardcoded to 2 km, this should be sufficient for most explosions
const double queryRadius = 2000.0;

CollisionContact dummy;
Space::BodyNearList nearby = Pi::game->GetSpace()->GetBodiesMaybeNear(this, damageRadius);
Space::BodyNearList nearby = Pi::game->GetSpace()->GetBodiesMaybeNear(this, queryRadius);
for (Body *body : nearby) {
if (body->GetFrame() != GetFrame()) continue;
double dist = (body->GetPosition() - GetPosition()).Length();
if (dist < damageRadius) {
// linear damage decay with distance
body->OnDamage(m_owner, kgDamage * (damageRadius - dist) / damageRadius, dummy);
if (body->IsType(Object::SHIP))
LuaEvent::Queue("onShipHit", dynamic_cast<Ship *>(body), m_owner);
}
double dist = (body->GetPosition() - GetPosition()).Length(); // distance from explosion in meter

double targetRadius = 6.0; // radius of the hit target in meter
fluffyfreak marked this conversation as resolved.
Show resolved Hide resolved

double areaSphere = calcAreaSphere(dist);
double crossSectionTarget = calcAreaCircle(targetRadius);
double ratioArea = crossSectionTarget / areaSphere; // compute ratio of areas to know how much energy was transfered to target
ratioArea = std::min(ratioArea, 1.0); // we must limit received energy to finite amount

double jReceivedEnergy = ratioArea * jYield; // compute received energy by blast

//Output("dist %f\n", dist);
//Output("area sphere %f\n", areaSphere);
//Output("crossSectionTarget %f\n", crossSectionTarget);
//Output("ratio %f\n", ratioArea);
//Output("received energy %f\n", jReceivedEnergy);

double kgDamage = jReceivedEnergy * 0.000022; // received energy back to damage in pioneer "kg" unit
//Output("dmg %f\n", kgDamage);

body->OnDamage(m_owner, kgDamage, dummy);
if (body->IsType(Object::SHIP))
LuaEvent::Queue("onShipHit", dynamic_cast<Ship *>(body), m_owner);
}

SfxManager::Add(this, TYPE_EXPLOSION);
Expand Down