Skip to content

Commit 104538d

Browse files
authored
(Re-)Add second parameter 'withExplosion' for blowVehicle (#2102)
1 parent 9c3411c commit 104538d

20 files changed

+321
-148
lines changed

Client/mods/deathmatch/logic/CClientExplosionManager.cpp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ bool CClientExplosionManager::Hook_ExplosionCreation(CEntity* pGameExplodingEnti
4949
if (!pResponsibleGameEntity)
5050
return false;
5151

52-
CClientEntity* const pResponsible = pPools->GetClientEntity(reinterpret_cast<DWORD*>(pResponsibleGameEntity->GetInterface()));;
52+
CClientEntity* const pResponsible = pPools->GetClientEntity(reinterpret_cast<DWORD*>(pResponsibleGameEntity->GetInterface()));
5353

5454
if (!pResponsible)
5555
return false;
@@ -89,13 +89,25 @@ bool CClientExplosionManager::Hook_ExplosionCreation(CEntity* pGameExplodingEnti
8989

9090
if (pResponsible->IsLocalEntity() || (bHasModel && CClientObjectManager::IsBreakableModel(usModel)))
9191
{
92-
CLuaArguments Arguments;
93-
Arguments.PushNumber(vecPosition.fX);
94-
Arguments.PushNumber(vecPosition.fY);
95-
Arguments.PushNumber(vecPosition.fZ);
96-
Arguments.PushNumber(explosionWeaponType);
97-
const bool bAllowExplosion = pResponsible->CallEvent("onClientExplosion", Arguments, true);
98-
return bAllowExplosion;
92+
CLuaArguments arguments;
93+
arguments.PushNumber(vecPosition.fX);
94+
arguments.PushNumber(vecPosition.fY);
95+
arguments.PushNumber(vecPosition.fZ);
96+
arguments.PushNumber(explosionWeaponType);
97+
bool allowExplosion = pResponsible->CallEvent("onClientExplosion", arguments, true);
98+
99+
// Check if the exploding entity is a client-only vehicle that exploded
100+
if (pGameExplodingEntity != nullptr && pResponsible->GetType() == CCLIENTVEHICLE)
101+
{
102+
auto vehicle = reinterpret_cast<CClientVehicle*>(pResponsible);
103+
104+
// Create an explosion if the vehicle was intact or awaiting this explosion
105+
allowExplosion = allowExplosion && (vehicle->GetBlowState() != VehicleBlowState::BLOWN);
106+
107+
vehicle->SetBlowState(VehicleBlowState::BLOWN);
108+
}
109+
110+
return allowExplosion;
99111
}
100112

101113
// All explosions are handled server side (ATTENTION: always 'return false;' below)
@@ -112,14 +124,15 @@ bool CClientExplosionManager::Hook_ExplosionCreation(CEntity* pGameExplodingEnti
112124
CClientEntity* pOriginSource = nullptr;
113125

114126
// Is this an exploding vehicle?
115-
if (pGameExplodingEntity && pGameExplodingEntity->GetEntityType() == ENTITY_TYPE_VEHICLE)
127+
if (pGameExplodingEntity != nullptr && pResponsible->GetType() == CCLIENTVEHICLE)
116128
{
117-
// Set our origin-source to the vehicle
118-
SClientEntity<CVehicleSA>* pVehicleClientEntity = pPools->GetVehicle(reinterpret_cast<DWORD*>(pGameExplodingEntity->GetInterface()));
129+
auto vehicle = reinterpret_cast<CClientVehicle*>(pResponsible);
130+
pOriginSource = vehicle;
119131

120-
if (pVehicleClientEntity)
132+
// Create an explosion, if the vehicle was not blown by us directly (CClientVehicle::Blow)
133+
if (vehicle->GetBlowState() == VehicleBlowState::INTACT)
121134
{
122-
pOriginSource = pVehicleClientEntity->pClientEntity;
135+
vehicle->SetBlowState(VehicleBlowState::AWAITING_EXPLOSION_SYNC);
123136
}
124137
}
125138
// If theres other players, sync it relative to the closest (lag compensation)

Client/mods/deathmatch/logic/CClientGame.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5080,6 +5080,22 @@ void CClientGame::SendExplosionSync(const CVector& vecPosition, eExplosionType T
50805080
pBitStream->WriteBit(true);
50815081
pBitStream->Write(pOrigin->GetID());
50825082

5083+
// Because we use this packet to notify the server of blown vehicles,
5084+
// we include a bit, whether the vehicle was blown without an explosion
5085+
if (pBitStream->Can(eBitStreamVersion::VehicleBlowStateSupport))
5086+
{
5087+
if (pOrigin->GetType() == CCLIENTVEHICLE)
5088+
{
5089+
auto vehicle = reinterpret_cast<CClientVehicle*>(pOrigin);
5090+
pBitStream->WriteBit(1);
5091+
pBitStream->WriteBit(vehicle->GetBlowState() == VehicleBlowState::BLOWN);
5092+
}
5093+
else
5094+
{
5095+
pBitStream->WriteBit(0);
5096+
}
5097+
}
5098+
50835099
// Convert position
50845100
CVector vecTemp;
50855101
pOrigin->GetPosition(vecTemp);

Client/mods/deathmatch/logic/CClientVehicle.cpp

Lines changed: 45 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,9 @@ CClientVehicle::CClientVehicle(CClientManager* pManager, ElementID ID, unsigned
137137
m_bJustBlewUp = false;
138138
m_ucAlpha = 255;
139139
m_bAlphaChanged = false;
140-
m_bBlowNextFrame = false;
140+
m_blowAfterStreamIn = false;
141141
m_bIsOnGround = false;
142142
m_ulIllegalTowBreakTime = 0;
143-
m_bBlown = false;
144143
m_LastSyncedData = new SLastSyncedVehData;
145144
m_bIsDerailed = false;
146145
m_bIsDerailable = true;
@@ -812,10 +811,6 @@ void CClientVehicle::SetDoorsUndamageable(bool bUndamageable)
812811

813812
float CClientVehicle::GetHealth() const
814813
{
815-
// If we're blown, return 0
816-
if (m_bBlown)
817-
return 0.0f;
818-
819814
if (m_pVehicle)
820815
{
821816
return m_pVehicle->GetHealth();
@@ -824,36 +819,36 @@ float CClientVehicle::GetHealth() const
824819
return m_fHealth;
825820
}
826821

827-
void CClientVehicle::SetHealth(float fHealth)
822+
void CClientVehicle::SetHealth(float health)
828823
{
824+
if (health < 0.0f || IsBlown())
825+
health = 0.0f;
826+
827+
m_fHealth = health;
828+
829829
if (m_pVehicle)
830830
{
831-
// Is the car is dead and we want to un-die it?
832-
if (fHealth > 0.0f && GetHealth() <= 0.0f)
833-
{
834-
Destroy();
835-
m_fHealth = fHealth; // NEEDS to be here!
836-
Create();
837-
}
838-
else
839-
{
840-
m_pVehicle->SetHealth(fHealth);
841-
}
831+
m_pVehicle->SetHealth(health);
842832
}
843-
m_fHealth = fHealth;
844833
}
845834

846835
void CClientVehicle::Fix()
847836
{
848-
m_bBlown = false;
849-
m_bBlowNextFrame = false;
850837
if (m_pVehicle)
851838
{
852839
m_pVehicle->Fix();
853840
// Make sure its visible, if its supposed to be
854841
m_pVehicle->SetVisible(m_bVisible);
855842
}
856843

844+
m_blowAfterStreamIn = false;
845+
846+
if (m_blowState != VehicleBlowState::INTACT)
847+
{
848+
m_blowState = VehicleBlowState::INTACT;
849+
ReCreate();
850+
}
851+
857852
SetHealth(DEFAULT_VEHICLE_HEALTH);
858853

859854
SFixedArray<unsigned char, MAX_DOORS> ucDoorStates;
@@ -932,8 +927,14 @@ void CClientVehicle::Fix()
932927
}
933928
}
934929

935-
void CClientVehicle::Blow(bool bAllowMovement)
930+
void CClientVehicle::Blow(VehicleBlowFlags blow)
936931
{
932+
if (m_blowState != VehicleBlowState::INTACT)
933+
return;
934+
935+
m_blowState = (blow.withExplosion ? VehicleBlowState::AWAITING_EXPLOSION_SYNC : VehicleBlowState::BLOWN);
936+
m_fHealth = 0.0f;
937+
937938
if (m_pVehicle)
938939
{
939940
// Make sure it can be damaged
@@ -952,13 +953,19 @@ void CClientVehicle::Blow(bool bAllowMovement)
952953

953954
m_pVehicle->BlowUp(NULL, 0);
954955

956+
// Blowing up a vehicle will cause an explosion in the original game code, but we have a hook in place,
957+
// which will prevent the explosion and forward the information to the server to relay it to everyone from there.
958+
// That hook may call further Lua events, which could result in a fixed vehicle and we have to check for that here.
959+
if (m_blowState == VehicleBlowState::INTACT)
960+
return;
961+
955962
// And force the wheel states to "burst"
956963
SetWheelStatus(FRONT_LEFT_WHEEL, DT_WHEEL_BURST);
957964
SetWheelStatus(FRONT_RIGHT_WHEEL, DT_WHEEL_BURST);
958965
SetWheelStatus(REAR_LEFT_WHEEL, DT_WHEEL_BURST);
959966
SetWheelStatus(REAR_RIGHT_WHEEL, DT_WHEEL_BURST);
960967

961-
if (!bAllowMovement)
968+
if (!blow.withMovement)
962969
{
963970
// Make sure it doesn't change speeds (slightly cleaner for syncing)
964971
SetMoveSpeed(vecMoveSpeed);
@@ -968,8 +975,6 @@ void CClientVehicle::Blow(bool bAllowMovement)
968975
// Restore the old can be damaged state
969976
CalcAndUpdateCanBeDamagedFlag();
970977
}
971-
m_fHealth = 0.0f;
972-
m_bBlown = true;
973978
}
974979

975980
CVehicleColor& CClientVehicle::GetColor()
@@ -1342,12 +1347,6 @@ bool CClientVehicle::IsUpsideDown() const
13421347
return false;
13431348
}
13441349

1345-
bool CClientVehicle::IsBlown() const
1346-
{
1347-
// Game layer functions aren't reliable
1348-
return m_bBlown;
1349-
}
1350-
13511350
bool CClientVehicle::IsSirenOrAlarmActive()
13521351
{
13531352
if (m_pVehicle)
@@ -2304,10 +2303,20 @@ void CClientVehicle::StreamedInPulse()
23042303
m_bJustStreamedIn = false;
23052304
}
23062305

2307-
if (m_bBlowNextFrame)
2306+
if (m_blowAfterStreamIn)
23082307
{
2309-
Blow(false);
2310-
m_bBlowNextFrame = false;
2308+
m_blowAfterStreamIn = false;
2309+
2310+
VehicleBlowState previousBlowState = m_blowState;
2311+
m_blowState = VehicleBlowState::INTACT;
2312+
2313+
VehicleBlowFlags blow;
2314+
blow.withMovement = false;
2315+
blow.withExplosion = (previousBlowState == VehicleBlowState::AWAITING_EXPLOSION_SYNC);
2316+
Blow(blow);
2317+
2318+
if (m_blowState != VehicleBlowState::INTACT)
2319+
m_blowState = previousBlowState;
23112320
}
23122321

23132322
// Handle door ratio auto reallowment
@@ -2328,7 +2337,7 @@ void CClientVehicle::StreamedInPulse()
23282337
}
23292338

23302339
// Are we an unmanned, invisible, blown-up plane?
2331-
if (!GetOccupant() && m_eVehicleType == CLIENTVEHICLE_PLANE && m_bBlown && !m_pVehicle->IsVisible())
2340+
if (!GetOccupant() && m_eVehicleType == CLIENTVEHICLE_PLANE && IsBlown() && !m_pVehicle->IsVisible())
23322341
{
23332342
// Disable our collisions
23342343
m_pVehicle->SetUsesCollision(false);
@@ -2441,20 +2450,6 @@ void CClientVehicle::StreamedInPulse()
24412450
}
24422451
}
24432452

2444-
/*
2445-
// Are we blown?
2446-
if ( m_bBlown )
2447-
{
2448-
// Has our engine status been reset to on_fire somewhere?
2449-
CDamageManager* pDamageManager = m_pVehicle->GetDamageManager ();
2450-
if ( pDamageManager->GetEngineStatus () == DT_ENGINE_ON_FIRE )
2451-
{
2452-
// Change it back to fucked
2453-
pDamageManager->SetEngineStatus ( DT_ENGINE_ENGINE_PIPES_BURST );
2454-
}
2455-
}
2456-
*/
2457-
24582453
// Limit burnout turn speed to ensure smoothness
24592454
if (m_pDriver)
24602455
{
@@ -2766,9 +2761,7 @@ void CClientVehicle::Create()
27662761
m_pVehicle->SetAlpha(m_ucAlpha);
27672762

27682763
m_pVehicle->SetHealth(m_fHealth);
2769-
2770-
if (m_bBlown || m_fHealth == 0.0f)
2771-
m_bBlowNextFrame = true;
2764+
m_blowAfterStreamIn = IsBlown();
27722765

27732766
CalcAndUpdateCanBeDamagedFlag();
27742767

Client/mods/deathmatch/logic/CClientVehicle.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ enum eWindow
6464
MAX_WINDOWS
6565
};
6666

67+
enum class VehicleBlowState : unsigned char
68+
{
69+
INTACT,
70+
AWAITING_EXPLOSION_SYNC,
71+
BLOWN,
72+
};
73+
74+
struct VehicleBlowFlags
75+
{
76+
bool withMovement : 1;
77+
bool withExplosion : 1;
78+
79+
constexpr VehicleBlowFlags() : withMovement(true), withExplosion(true) {}
80+
};
81+
6782
namespace EComponentBase
6883
{
6984
enum EComponentBaseType
@@ -195,10 +210,13 @@ class CClientVehicle : public CClientStreamElement
195210
void SetDoorsUndamageable(bool bUndamageable);
196211

197212
float GetHealth() const;
198-
void SetHealth(float fHealth);
213+
void SetHealth(float health);
199214
void Fix();
200-
void Blow(bool bAllowMovement = false);
201-
bool IsVehicleBlown() const noexcept { return m_bBlown; };
215+
216+
void Blow(VehicleBlowFlags blow);
217+
bool IsBlown() const noexcept { return m_blowState != VehicleBlowState::INTACT; }
218+
void SetBlowState(VehicleBlowState state) { m_blowState = state; }
219+
VehicleBlowState GetBlowState() const noexcept { return m_blowState; }
202220

203221
CVehicleColor& GetColor();
204222
void SetColor(const CVehicleColor& color);
@@ -235,7 +253,6 @@ class CClientVehicle : public CClientStreamElement
235253
bool IsDrowning() const;
236254
bool IsDriven() const;
237255
bool IsUpsideDown() const;
238-
bool IsBlown() const;
239256

240257
bool IsSirenOrAlarmActive();
241258
void SetSirenOrAlarmActive(bool bActive);
@@ -619,7 +636,7 @@ class CClientVehicle : public CClientStreamElement
619636
unsigned char m_ucAlpha;
620637
bool m_bAlphaChanged;
621638
double m_dLastRotationTime;
622-
bool m_bBlowNextFrame;
639+
bool m_blowAfterStreamIn;
623640
bool m_bIsOnGround;
624641
bool m_bHeliSearchLightVisible;
625642
float m_fHeliRotorSpeed;
@@ -675,9 +692,10 @@ class CClientVehicle : public CClientStreamElement
675692

676693
unsigned long m_ulIllegalTowBreakTime;
677694

678-
bool m_bBlown;
679695
bool m_bHasDamageModel;
680696

697+
VehicleBlowState m_blowState = VehicleBlowState::INTACT;
698+
681699
bool m_bTaxiLightOn;
682700
std::list<CClientProjectile*> m_Projectiles;
683701

0 commit comments

Comments
 (0)