-
Notifications
You must be signed in to change notification settings - Fork 241
bugfix(neutronmissile): Fix and improve Nuke Missile damage for large objects inside the outer blast radius #3161
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -312,11 +312,21 @@ void NeutronMissileSlowDeathBehavior::doBlast( const BlastInfo *blastInfo ) | |
| damageInfo.in.m_amount = blastInfo->minDamage; | ||
|
|
||
| // scan objects around us and do damage to objects we have "passed over" and are behind us | ||
| // TheSuperHackers @todo Optimize this function. Iterates through the blasts even if they apply zero damage. | ||
| if( blastInfo->outerRadius ) | ||
| { | ||
|
|
||
| #if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_NUKE_MISSILE_OUTER_RADIUS_SEARCH | ||
| const DistanceCalculationType dc = FROM_CENTER_2D; | ||
| #else | ||
| // TheSuperHackers @bugfix xezon 16/08/2026 From FROM_CENTER_2D, | ||
| // because objects that reach into the outer radius should also receive damage. | ||
| const DistanceCalculationType dc = FROM_BOUNDINGSPHERE_2D; | ||
| #endif | ||
|
|
||
| ObjectIterator *iter = ThePartitionManager->iterateObjectsInRange( missilePos, | ||
| blastInfo->outerRadius, | ||
| FROM_CENTER_2D, | ||
| dc, | ||
| nullptr ); | ||
| MemoryPoolObjectHolder hold( iter ); | ||
| Object *other; | ||
|
|
@@ -329,10 +339,31 @@ void NeutronMissileSlowDeathBehavior::doBlast( const BlastInfo *blastInfo ) | |
| // get other position | ||
| otherPos = other->getPosition(); | ||
|
|
||
| #if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_NUKE_MISSILE_OUTER_RADIUS_DAMAGE | ||
| // compute vector from the missile to other object | ||
| forceVector.x = otherPos->x - missilePos->x; | ||
| forceVector.y = otherPos->y - missilePos->y; | ||
| forceVector.z = otherPos->z - missilePos->z; | ||
| #else | ||
| // compute vector from the missile to other object | ||
| // TheSuperHackers @tweak xezon 16/08/2026 No longer calculate the force vector to the center of the object, | ||
| // but to half way between the closest edge and the center of the object. This way a more appropriate | ||
| // damage value is sampled for a large structure inside the damage fall off range. | ||
| Coord2D toCenterVector; | ||
| toCenterVector.x = otherPos->x - missilePos->x; | ||
| toCenterVector.y = otherPos->y - missilePos->y; | ||
|
|
||
| ThePartitionManager->getVectorTo(other, missilePos, FROM_BOUNDINGSPHERE_2D, forceVector); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer a fromBoundVector rather than reusing the forceVector variable. |
||
|
|
||
| // flip direction | ||
| forceVector.x = -forceVector.x; | ||
| forceVector.y = -forceVector.y; | ||
|
|
||
| // take average between min and max force | ||
| forceVector.x = (forceVector.x + toCenterVector.x) * 0.5f; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the proper comment (and renaming to fromBoundVector, the flipping and average can be consolidated into one statement.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like to keep the flip separate, because it is only necessary because |
||
| forceVector.y = (forceVector.y + toCenterVector.y) * 0.5f; | ||
| forceVector.z = 0.0f; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Helicopters and planes that are within the outer radius at ground level now always receive damage, while previously, they could have been undamaged due to still being outside the sphere. If this change is intentional, it may need documentation.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The nuke missile explodes 15 units or so above the ground. I dediced to model the damage as 2D, because everything else is 2D here, and if not treated as 2D, then the damage radii are not perfectly accurate on the ground. I have not considered aircraft. I will think about whether it needs returning to sphere. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have no problem with a cylinder. Probably easier for players as well. But it is a balance change. |
||
| #endif | ||
|
Comment on lines
+363
to
+366
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. Z dropped from distance When the non-retail outer-radius damage path is enabled, doBlast() forces forceVector.z = 0, so damage falloff (dist = forceVector.length()) becomes purely 2D and differs from the retail path that includes Z. This can over-apply damage/topple to airborne or differently-elevated objects compared to the existing behavior. Agent Prompt
|
||
|
|
||
| // try to topple other object | ||
| other->topple( &forceVector, blastInfo->toppleSpeed, TOPPLE_OPTIONS_NO_BOUNCE | | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.