Add vehicleexplosions world special property - #5123
Conversation
Prompt & Goals:
- Add a new world special property 'vehicleexplosions' to allow disabling vehicle explosions.
Motivation & Reasoning:
- Enables gamemode developers to prevent vehicles from exploding upon reaching 0 HP via setWorldSpecialPropertyEnabled('vehicleexplosions', false).
Implementation Details:
- Added WorldSpecialProperty::VEHICLEEXPLOSIONS enum in Shared.
- Added vehicleexplosions bitfield to SWorldSpecialPropertiesStateSync bitstream structure.
- Handled sync via CMapInfoPacket on server and CPacketHandler on client.
- Applied GTA SA memory patch at CVehicle::BlowUpCar (0x6B8F80) using ret 8 (0xC2, 0x08, 0x00) when property is disabled.
|
Seems pretty useful, at least most roleplay servers have to prevent it manually |
FileEX
left a comment
There was a problem hiding this comment.
The corresponding changes in SyncMisc_Tests.cpp are missing as well.
|
|
||
| if (isEnabled) | ||
| { | ||
| MemCpy((void*)0x6B8F80, "\x56\x8B\xF1", 3); // CVehicle::BlowUpCar |
There was a problem hiding this comment.
You're right, thanks for identifying what that address actually is. I dropped the memory patch entirely — details in my comment below.
| bool flyingcomponents : 1; | ||
| bool vehicleburnexplosions : 1; | ||
| bool vehicleEngineAutoStart : 1; | ||
| bool vehicleexplosions : 1; |
There was a problem hiding this comment.
Another sign that you didn't test your changes. You need to increase BITCOUNT for this to work.
There was a problem hiding this comment.
Fixed, though with a version-gated second block rather than bumping BITCOUNT — reasoning in my comment below.
There was a problem hiding this comment.
Since version 1.7 hasn't had an official release yet, we don't have to worry about the bitstream. So just increase the BITCOUNT and revert the changes in bitstream.h and the tests.
There was a problem hiding this comment.
Done, moved it back into data, BITCOUNT is 21 now, and bitstream.h is reverted. The round-trip test keeps the updated bit count and a check for the new flag; the version-gate test is gone with the gate.
The property was never transmitted: BITCOUNT was left at 20 while the new bit was added as the 21st, so the client always kept its default. Rather than bumping BITCOUNT, which would shift the stream by one bit for peers built before this change, the flag now lives in a separate data2 block gated on a new eBitStreamVersion entry. The memory patch at 0x6B8F80 has been dropped. That address is CBike::VehicleDamage, not CVehicle::BlowUpCar, and BlowUpCar is virtual anyway, so every overriding class would have needed its own patch. The property is now enforced in CClientGame::VehicleDamageHandler, which holds a damaged vehicle at VEHICLE_BURNING_HEALTH. Below that health the game sets the vehicle on fire and blows it up on its own, so the floor prevents both for every vehicle type without patching code. CVehicleSA::SetHealth cast every vehicle to CAutomobileSAInterface* to clear m_fBurningTime, which only exists on automobiles; for bikes, boats and trains that wrote past the end of the interface. The health floor calls SetHealth on every lethal hit, so it hit that path constantly. The automobile-only field moved to a CAutomobileSA::SetHealth override. Updated the SWorldSpecialPropertiesStateSync round-trip test for the extra bit and added a test covering a peer older than the new bitstream version.

Summary
Adds a new world special property
vehicleexplosions, which stops the game fromdestroying vehicles on its own:
setWorldSpecialPropertyEnabled("vehicleexplosions", false).WorldSpecialProperty::VEHICLEEXPLOSIONSenum in Shared.a new data2 block, gated on a new eBitStreamVersion entry
so peers built before this change keep working.
CMapInfoPacketon the server andCPacketHandleron theclient.
CClientGame::VehicleDamageHandler, which holds a damaged vehicleat
VEHICLE_BURNING_HEALTH(250). Below that health the game sets the vehicleon fire and blows it up once the delayed explosion timer expires, so keeping
health at that floor prevents both — for every vehicle type, without patching
game code.
blowVehicle()still works while theproperty is disabled, since the property only suppresses what the game does by
itself.
This also fixes a pre-existing bug that the change would otherwise make hot:
CVehicleSA::SetHealthcast every vehicle toCAutomobileSAInterface*in orderto clear
m_fBurningTime, a field that only exists on automobiles. For bikes,boats and trains that wrote past the end of the interface. The automobile-only
field moved to a
CAutomobileSA::SetHealthoverride.Motivation
Lets gamemode developers keep vehicles alive instead of having them explode and
disappear once they run out of health.
Test plan
setWorldSpecialPropertyEnabled("vehicleexplosions", false)on resource start,firing an RPG and a minigun at cars, planes and boats. Health stops at 250, the
vehicles neither catch fire nor explode, and damage and deformation still apply
above that.
blowVehicle()still destroys a vehicle while the property is disabled.SWorldSpecialPropertiesStateSyncround-trip test for the extrabit and added
LegacyPeerOmitsSecondBlock, which covers a peer older than thenew bitstream version. Full client test suite passes (305 tests).
Checklist