bugfix: Occupants killed by their containers now kill their occupants#2239
bugfix: Occupants killed by their containers now kill their occupants#2239Stubbjax wants to merge 6 commits intoTheSuperHackers:mainfrom
Conversation
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp | Reordered death logic to kill non-free riders before damage processing in non-retail builds; uses percentDamage parameter for nested container damage propagation |
| Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TransportContain.cpp | Added check for parent container being held, but missing null pointer check on getContainedBy() |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp | Reordered death logic to kill non-free riders before damage processing in non-retail builds; optimized repeated float comparison with cached killContained boolean |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TransportContain.cpp | Added check for parent container being held and improved death type handling, but missing null pointer check on getContainedBy() |
Last reviewed commit: d4588e0
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
Outdated
Show resolved
Hide resolved
Additional Comments (1)
Prompt To Fix With AIThis is a comment left during a code review.
Path: Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
Line: 1307:1307
Comment:
Should use `percentDamage` parameter instead of `data->m_damagePercentageToUnits` to match the GeneralsMD implementation and ensure nested containers receive the correct damage value.
```suggestion
Real damage = object->getBodyModule()->getMaxHealth() * percentDamage;
```
How can I resolve this? If you propose a fix, please make it concise. |
61f80fa to
b1aaa96
Compare
b1aaa96 to
05dc39e
Compare
|
Does this also happen with Troopcrawler in helix? |
A Troop Crawler takes up eight slots and thus cannot fit inside a Helix. But we can demonstrate the same behaviour with a Helix by loading an Ambulance or Technical. AMBO_LIX.mp4 |
xezon
left a comment
There was a problem hiding this comment.
This change will need to be Merged With Rebase, because the unify commit needs to be kept separate. The commit titles need to be fit to standard.
| @@ -1364,8 +1359,16 @@ void OpenContain::processDamageToContained() | |||
|
|
|||
| DEBUG_ASSERTCRASH( object, ("Contain list must not contain null element") ); | |||
|
|
|||
| // TheSuperHackers @bugfix Stubbjax 02/02/2026 If the parent container kills its occupants | |||
| // on death, then those occupants also kill their occupants, and so on. | |||
| if (killContained) | |||
There was a problem hiding this comment.
Is this condition correct? What if the damage dealt to occupants is just 0.5? Shouldn't that also transfer the damage?
There was a problem hiding this comment.
Why? If a Humvee could be stored inside an Overlord, and the Overlord was destroyed, would it make sense to apply that 0.5 damage to the Humvee's passengers in addition to the Humvee itself? There is no precedent for this.
There was a problem hiding this comment.
Yes if the health of the contained transport is 0.4 and the damage is 0.5, then we want to kill the passengers of the transport as well right? Or will they be killed anyway? If they are, then it begs the question why is the damage applied in that event but not when applying 1.0 damage?
There was a problem hiding this comment.
Upon further investigation, it turns out that the DamagePercentToUnits defined in the Chinook / Helix TransportContain modules is a red herring. Setting either of these fields to a value < 100% still results in the contained units dying, which is due to a call to killRidersWhoAreNotFreeToExit (though this causes the infantry corpses to drop out like vehicles do due to the lack of the burned death type via this logic path).
Only the direct occupants of airborne containers are considered not FREE_TO_EXIT (see ChinookAIUpdate::getAiFreeToExit), which prevents the killRidersWhoAreNotFreeToExit logic from triggering for successive occupants of contained transports such as those inside contained Troop Crawlers. It would seem killRidersWhoAreNotFreeToExit was never called in retail anyway due to the DamagePercentToUnits applying first, which is always set to 100% for airborne containers (where the FREE_TO_EXIT status applies).
I've solved this by returning false if the parent container has the held status in the isSpecificRiderFreeToExit function. I've also swapped the order of killRidersWhoAreNotFreeToExit and processDamageToContained, which avoids calling redundant logic in cases where riders are not FREE_TO_EXIT and DamagePercentToUnits < 100%.
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
Outdated
Show resolved
Hide resolved
| #if !RETAIL_COMPATIBLE_CRC | ||
| // TheSuperHackers @bugfix Stubbjax 02/03/2026 If our parent container is held, then we | ||
| // are not free to exit. | ||
| if (specificObject->getContainedBy()->isDisabledByType(DISABLED_HELD)) |
There was a problem hiding this comment.
Missing null check before dereferencing getContainedBy(). While objects in the contain list should have a valid container, defensive programming suggests checking for nullptr to prevent potential crashes.
| if (specificObject->getContainedBy()->isDisabledByType(DISABLED_HELD)) | |
| if (specificObject->getContainedBy() && specificObject->getContainedBy()->isDisabledByType(DISABLED_HELD)) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TransportContain.cpp
Line: 462
Comment:
Missing null check before dereferencing `getContainedBy()`. While objects in the contain list should have a valid container, defensive programming suggests checking for nullptr to prevent potential crashes.
```suggestion
if (specificObject->getContainedBy() && specificObject->getContainedBy()->isDisabledByType(DISABLED_HELD))
```
How can I resolve this? If you propose a fix, please make it concise.| #if !RETAIL_COMPATIBLE_CRC | ||
| // TheSuperHackers @bugfix Stubbjax 02/03/2026 If our parent container is held, then we | ||
| // are not free to exit. | ||
| if (specificObject->getContainedBy()->isDisabledByType(DISABLED_HELD)) |
There was a problem hiding this comment.
Missing null check before dereferencing getContainedBy(). While objects in the contain list should have a valid container, defensive programming suggests checking for nullptr to prevent potential crashes.
| if (specificObject->getContainedBy()->isDisabledByType(DISABLED_HELD)) | |
| if (specificObject->getContainedBy() && specificObject->getContainedBy()->isDisabledByType(DISABLED_HELD)) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TransportContain.cpp
Line: 573
Comment:
Missing null check before dereferencing `getContainedBy()`. While objects in the contain list should have a valid container, defensive programming suggests checking for nullptr to prevent potential crashes.
```suggestion
if (specificObject->getContainedBy() && specificObject->getContainedBy()->isDisabledByType(DISABLED_HELD))
```
How can I resolve this? If you propose a fix, please make it concise.
Closes #184
This change fixes an issue where occupants killed via the destruction of their container do not kill their occupants, and so on. For example, if a Chinook containing a Troop Crawler dies, the Red Guards inside the Troop Crawler survive and fall to the ground, which looks silly and can leave them floating in the air.
Before
A Troop Crawler dies inside a Chinook, but its occupants survive and fall to the ground or float in the air
YES_SURVIVORS.mp4
After
A Troop Crawler dies inside a Chinook, and kills its own occupants as a result
NO_SURVIVORS.mp4