Skip to content

Commit a744cd1

Browse files
authored
Fix custom weapon issue #4072 (#4076)
1 parent a8bf644 commit a744cd1

File tree

4 files changed

+125
-78
lines changed

4 files changed

+125
-78
lines changed

Client/game_sa/CWeaponSA.cpp

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
extern CGameSA* pGame;
2121

22-
CWeaponInfo* CWeaponSA::GetInfo(const eWeaponSkill& skill) const
22+
CWeaponInfo* CWeaponSA::GetInfo(eWeaponSkill skill) const
2323
{
2424
return m_interface ? pGame->GetWeaponInfo(m_interface->m_eWeaponType, skill) : nullptr;
2525
}
@@ -55,42 +55,41 @@ void CWeaponSA::Remove()
5555
}
5656
}
5757

58-
void CWeaponSA::Initialize(const eWeaponType& type, std::uint32_t ammo, CPed* ped)
58+
void CWeaponSA::Initialize(eWeaponType type, std::uint32_t ammo, CPed* ped)
5959
{
6060
if (m_interface)
61-
m_interface->Initialize(type, ammo, ped);
62-
}
63-
64-
void CWeaponSA::Update(CPed* ped)
65-
{
66-
// Note: CWeapon::Update is called mainly to check for reload
67-
if (m_interface)
68-
m_interface->Update(ped);
61+
m_interface->Initialize(type, ammo, ped ? ped->GetPedInterface() : nullptr);
6962
}
7063

7164
void CWeaponSA::AddGunshell(CEntity* firingEntity, const CVector& vecOrigin, const CVector2D& vecDirection, float size) const
7265
{
7366
if (m_interface && firingEntity)
74-
m_interface->AddGunshell(firingEntity, vecOrigin, vecDirection, size);
67+
m_interface->AddGunshell(firingEntity->GetInterface(), vecOrigin, vecDirection, size);
7568
}
7669

77-
void CWeaponSA::DoBulletImpact(CEntity* firingEntity, CEntitySAInterface* hitEntityInterface, const CVector& vecOrigin, const CVector& vecTarget, const CColPoint& colPoint, int incrementalHit) const
70+
void CWeaponSA::DoBulletImpact(CEntity* firingEntity, CEntitySAInterface* hitEntityInterface, const CVector& vecOrigin, const CVector& vecTarget,
71+
const CColPointSAInterface& colPoint, int incrementalHit) const
7872
{
7973
if (m_interface)
80-
m_interface->DoBulletImpact(firingEntity, hitEntityInterface, vecOrigin, vecTarget, colPoint, incrementalHit);
74+
m_interface->DoBulletImpact(firingEntity ? firingEntity->GetInterface() : nullptr, hitEntityInterface, vecOrigin, vecTarget, colPoint, incrementalHit);
8175
}
8276

8377
bool CWeaponSA::Fire(CEntity* firingEntity, CVector* vecOrigin, CVector* vecEffectPos, CEntity* targetEntity, CVector* vecTarget, CVector* vecAlt)
8478
{
85-
if (!firingEntity)
79+
if (!firingEntity || !m_interface)
8680
return false;
8781

88-
return m_interface ? m_interface->Fire(firingEntity, vecOrigin, vecEffectPos, targetEntity, vecTarget, vecAlt) : false;
82+
return m_interface->Fire(firingEntity->GetInterface(), vecOrigin, vecEffectPos, targetEntity ? targetEntity->GetInterface() : nullptr, vecTarget, vecAlt);
8983
}
9084

91-
bool CWeaponSA::FireInstantHit(CEntity* firingEntity, const CVector* vecOrigin, const CVector* vecMuzzle, CEntity* targetEntity, const CVector* vecTarget, const CVector* vecForDriveby, bool crossHairGun, bool createGunFx)
85+
bool CWeaponSA::FireInstantHit(CEntity* firingEntity, CVector* vecOrigin, CVector* vecMuzzle, CEntity* targetEntity, CVector* vecTarget, CVector* vecForDriveby,
86+
bool crossHairGun, bool createGunFx)
9287
{
93-
return m_interface ? m_interface->FireInstantHit(firingEntity, const_cast<CVector*>(vecOrigin), const_cast<CVector*>(vecMuzzle), targetEntity, const_cast<CVector*>(vecTarget), const_cast<CVector*>(vecForDriveby), crossHairGun, createGunFx) : false;
88+
if (!m_interface)
89+
return false;
90+
91+
return m_interface->FireInstantHit(firingEntity ? firingEntity->GetInterface() : nullptr, vecOrigin, vecMuzzle,
92+
targetEntity ? targetEntity->GetInterface() : nullptr, vecTarget, vecForDriveby, crossHairGun, createGunFx);
9493
}
9594

9695
bool CWeaponSA::FireBullet(CEntity* firingEntity, const CVector& vecOrigin, const CVector& vecTarget)
@@ -130,7 +129,7 @@ bool CWeaponSA::FireBullet(CEntity* firingEntity, const CVector& vecOrigin, cons
130129
firingPlayerPed->GetTransformedBonePosition(BONE_RIGHTWRIST, &vecGunMuzzle);
131130

132131
// Bullet trace
133-
FireInstantHit(firingEntity, &vecOrigin, &vecGunMuzzle, nullptr, &vecTarget, nullptr, false, true);
132+
FireInstantHit(firingEntity, const_cast<CVector*>(&vecOrigin), &vecGunMuzzle, nullptr, const_cast<CVector*>(&vecTarget), nullptr, false, true);
134133

135134
// Fire sound
136135
if (firingPlayerPed)
@@ -156,23 +155,26 @@ bool CWeaponSA::GenerateDamageEvent(CPed* ped, CEntity* responsible, eWeaponType
156155
if (!ped || !m_interface)
157156
return false;
158157

159-
return m_interface->GenerateDamageEvent(ped, responsible, weaponType, damagePerHit, hitZone, dir);
158+
return m_interface->GenerateDamageEvent(ped ? ped->GetPedInterface() : nullptr, responsible ? responsible->GetInterface() : nullptr, weaponType,
159+
damagePerHit, hitZone, dir);
160160
}
161161

162-
bool CWeaponSA::ProcessLineOfSight(const CVector* vecStart, const CVector* vecEnd, CColPoint** colCollision, CEntity** collisionEntity, const SLineOfSightFlags& flags, SLineOfSightBuildingResult* buildingResult, const eWeaponType& weaponType, CEntitySAInterface** entity)
162+
bool CWeaponSA::ProcessLineOfSight(const CVector& vecStart, const CVector& vecEnd, CColPoint** colCollision, CEntity*& collisionEntity,
163+
const SLineOfSightFlags& flags, SLineOfSightBuildingResult* buildingResult, eWeaponType weaponType,
164+
CEntitySAInterface** entity)
163165
{
164166
// Call CBirds::HandleGunShot
165-
((void(__cdecl*)(CVector*, CVector*))FUNC_CBirds_CheckForHit)(const_cast<CVector*>(vecStart), const_cast<CVector*>(vecEnd));
167+
((void(__cdecl*)(const CVector*, const CVector*))FUNC_CBirds_CheckForHit)(&vecStart, &vecEnd);
166168

167169
// Call CShadows::GunShotSetsOilOnFire
168-
((void(__cdecl*)(CVector*, CVector*))FUNC_CShadows_CheckForHit)(const_cast<CVector*>(vecStart), const_cast<CVector*>(vecEnd));
170+
((void(__cdecl*)(const CVector&, const CVector&))FUNC_CShadows_CheckForHit)(vecStart, vecEnd);
169171

170-
bool hit = pGame->GetWorld()->ProcessLineOfSight(vecStart, vecEnd, colCollision, collisionEntity, flags, buildingResult);
172+
bool hit = pGame->GetWorld()->ProcessLineOfSight(&vecStart, &vecEnd, colCollision, &collisionEntity, flags, buildingResult);
171173

172174
if (hit)
173175
{
174-
if (*collisionEntity)
175-
*entity = (*collisionEntity)->GetInterface();
176+
if (collisionEntity)
177+
*entity = collisionEntity->GetInterface();
176178
else
177179
{
178180
if (buildingResult->bValid)
@@ -182,7 +184,8 @@ bool CWeaponSA::ProcessLineOfSight(const CVector* vecStart, const CVector* vecEn
182184

183185
// Call CWeapon::CheckForShootingVehicleOccupant
184186
if (*entity && (*entity)->nType == ENTITY_TYPE_VEHICLE)
185-
((void(__cdecl*)(CEntitySAInterface*, CColPointSAInterface*, eWeaponType, CVector*, CVector*))FUNC_CWeapon_CheckForShootingVehicleOccupant)(*entity, (*colCollision)->GetInterface(), weaponType, const_cast<CVector*>(vecStart), const_cast<CVector*>(vecEnd));
187+
((bool(__cdecl*)(CEntitySAInterface**, CColPointSAInterface*, eWeaponType, const CVector&,
188+
const CVector&))FUNC_CWeapon_CheckForShootingVehicleOccupant)(entity, (*colCollision)->GetInterface(), weaponType, vecStart, vecEnd);
186189

187190
return hit;
188191
}
@@ -199,6 +202,6 @@ int CWeaponSA::GetWeaponReloadTime(CWeaponStat* weaponStat) const
199202
int CWeaponSA::GetWeaponFireTime(CWeaponStat* weaponStat)
200203
{
201204
std::uint32_t timer = pGame->GetSystemTime();
202-
float weaponFireTime = (weaponStat->GetWeaponAnimLoopStop() - weaponStat->GetWeaponAnimLoopStart()) * 1000.0f;
205+
float weaponFireTime = (weaponStat->GetWeaponAnimLoopStop() - weaponStat->GetWeaponAnimLoopStart()) * 1000.0f;
203206
return static_cast<int>(weaponFireTime);
204207
}

Client/game_sa/CWeaponSA.h

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,9 @@
1111

1212
#pragma once
1313

14-
#define FUNC_CWeapon_Shutdown 0x73A380
15-
#define FUNC_CWeapon_CheckForShootingVehicleOccupant 0x73f480
16-
#define FUNC_CWeapon_Initialize 0x73b4a0
17-
#define FUNC_CWeapon_Update 0x73db40
18-
#define FUNC_CWeapon_Fire 0x742300
19-
#define FUNC_CWeapon_AddGunshell 0x73a3e0
20-
#define FUNC_CWeapon_DoBulletImpact 0x73b550
21-
#define FUNC_CWeapon_GenerateDamageEvent 0x73a530
22-
#define FUNC_CWeapon_FireInstantHit 0x73FB10
23-
#define FUNC_CBirds_CheckForHit 0x712E40
24-
#define FUNC_CShadows_CheckForHit 0x707550
14+
#define FUNC_CWeapon_CheckForShootingVehicleOccupant 0x73f480
15+
#define FUNC_CBirds_CheckForHit 0x712E40
16+
#define FUNC_CShadows_CheckForHit 0x707550
2517

2618
class CWeaponSAInterface
2719
{
@@ -31,64 +23,111 @@ class CWeaponSAInterface
3123
std::uint32_t m_ammoInClip{0};
3224
std::uint32_t m_ammoTotal{0};
3325
std::uint32_t m_timeToNextShootInMS{0};
34-
bool m_firstPersonEnabled{false}; // Unused
35-
bool m_dontPlaceInHand{false}; // Used in case of goggles
36-
FxSystem_c* m_fxSystem{nullptr}; // Fx system (flamethrower, spraycan, extinguisher)
37-
38-
void Shutdown() { ((void(__thiscall*)(CWeaponSAInterface*))FUNC_CWeapon_Shutdown)(this); }
39-
void Initialize(const eWeaponType& weaponType, std::uint32_t ammo, CPed* ped) { ((void(__thiscall*)(CWeaponSAInterface*, eWeaponType, std::uint32_t, CPedSAInterface*))FUNC_CWeapon_Initialize)(this, weaponType, ammo, ped ? ped->GetPedInterface() : nullptr); }
40-
void Update(CPed* ped) { ((void(__thiscall*)(CWeaponSAInterface*, CPedSAInterface*))FUNC_CWeapon_Update)(this, ped ? ped->GetPedInterface() : nullptr); }
41-
void AddGunshell(CEntity* firingEntity, const CVector& vecOrigin, const CVector2D& vecDirection, float size) { ((void(__thiscall*)(CWeaponSAInterface*, CEntitySAInterface*, const CVector&, const CVector2D&, float))FUNC_CWeapon_AddGunshell)(this, firingEntity ? firingEntity->GetInterface() : nullptr, vecOrigin, vecDirection, size); }
42-
void DoBulletImpact(CEntity* firingEntity, CEntitySAInterface* hitEntityInterface, const CVector& vecOrigin, const CVector& vecTarget, const CColPoint& colPoint, int incrementalHit) { ((void(__thiscall*)(CWeaponSAInterface*, CEntitySAInterface*, CEntitySAInterface*, const CVector&, const CVector&, const CColPoint&, int))FUNC_CWeapon_DoBulletImpact)(this, firingEntity ? firingEntity->GetInterface() : nullptr, hitEntityInterface, vecOrigin, vecTarget, colPoint, incrementalHit); }
43-
bool Fire(CEntity* firingEntity, CVector* vecOrigin, CVector* vecEffectPos, CEntity* targetEntity, CVector* vecTarget, CVector* vecAlt) { return ((bool(__thiscall*)(CWeaponSAInterface*, CEntitySAInterface*, CVector*, CVector*, CEntitySAInterface*, CVector*, CVector*))FUNC_CWeapon_Fire)(this, firingEntity ? firingEntity->GetInterface() : nullptr, vecOrigin, vecEffectPos, targetEntity ? targetEntity->GetInterface() : nullptr, vecTarget, vecAlt); }
44-
bool FireInstantHit(CEntity* firingEntity, CVector* vecOrigin, CVector* vecMuzzle, CEntity* targetEntity, CVector* vecTarget, CVector* vecForDriveby, bool crossHairGun, bool createGunFx) { return ((bool(__thiscall*)(CWeaponSAInterface*, CEntitySAInterface*, CVector*, CVector*, CEntitySAInterface*, CVector*, CVector*, bool, bool))FUNC_CWeapon_FireInstantHit)(this, firingEntity ? firingEntity->GetInterface() : nullptr, vecOrigin, vecMuzzle, targetEntity ? targetEntity->GetInterface() : nullptr, vecTarget, vecForDriveby, crossHairGun, createGunFx); }
45-
bool GenerateDamageEvent(CPed* ped, CEntity* responsible, eWeaponType weaponType, int damagePerHit, ePedPieceTypes hitZone, std::uint8_t dir) { return ((bool(__thiscall*)(CWeaponSAInterface*, CPedSAInterface*, CEntitySAInterface*, eWeaponType, int, ePedPieceTypes, std::uint8_t))FUNC_CWeapon_GenerateDamageEvent)(this, ped ? ped->GetPedInterface() : nullptr, responsible ? responsible->GetInterface() : nullptr, weaponType, damagePerHit, hitZone, dir); }
26+
bool m_firstPersonEnabled{false}; // Unused
27+
bool m_dontPlaceInHand{false}; // Used in case of goggles
28+
FxSystem_c* m_fxSystem{nullptr}; // Fx system (flamethrower, spraycan, extinguisher)
29+
30+
void Shutdown() { ((void(__thiscall*)(CWeaponSAInterface*))0x73A380)(this); }
31+
void Initialize(eWeaponType weaponType, std::uint32_t ammo, CPedSAInterface* ped)
32+
{
33+
((void(__thiscall*)(CWeaponSAInterface*, eWeaponType, std::uint32_t, CPedSAInterface*))0x73B4A0)(this, weaponType, ammo, ped);
34+
}
35+
void AddGunshell(CEntitySAInterface* firingEntity, const CVector& vecOrigin, const CVector2D& vecDirection, float size)
36+
{
37+
((void(__thiscall*)(CWeaponSAInterface*, CEntitySAInterface*, const CVector&, const CVector2D&, float))0x73A3E0)(this, firingEntity, vecOrigin,
38+
vecDirection, size);
39+
}
40+
void DoBulletImpact(CEntitySAInterface* firingEntity, CEntitySAInterface* hitEntityInterface, const CVector& vecOrigin, const CVector& vecTarget,
41+
const CColPointSAInterface& colPoint, int incrementalHit)
42+
{
43+
((void(__thiscall*)(CWeaponSAInterface*, CEntitySAInterface*, CEntitySAInterface*, const CVector&, const CVector&, const CColPointSAInterface&,
44+
int))0x73B550)(this, firingEntity, hitEntityInterface, vecOrigin, vecTarget, colPoint, incrementalHit);
45+
}
46+
bool Fire(CEntitySAInterface* firingEntity, CVector* vecOrigin, CVector* vecEffectPos, CEntitySAInterface* targetEntity, CVector* vecTarget,
47+
CVector* vecAlt)
48+
{
49+
return ((bool(__thiscall*)(CWeaponSAInterface*, CEntitySAInterface*, CVector*, CVector*, CEntitySAInterface*, CVector*, CVector*))0x742300)(
50+
this, firingEntity, vecOrigin, vecEffectPos, targetEntity, vecTarget, vecAlt);
51+
}
52+
bool FireInstantHit(CEntitySAInterface* firingEntity, CVector* vecOrigin, CVector* vecMuzzle, CEntitySAInterface* targetEntity, CVector* vecTarget,
53+
CVector* vecForDriveby, bool crossHairGun, bool createGunFx)
54+
{
55+
return ((bool(__thiscall*)(CWeaponSAInterface*, CEntitySAInterface*, CVector*, CVector*, CEntitySAInterface*, CVector*, CVector*, bool, bool))0x73FB10)(
56+
this, firingEntity, vecOrigin, vecMuzzle, targetEntity, vecTarget, vecForDriveby, crossHairGun, createGunFx);
57+
}
58+
bool GenerateDamageEvent(CPedSAInterface* ped, CEntitySAInterface* responsible, eWeaponType weaponType, int damagePerHit, ePedPieceTypes hitZone,
59+
std::uint8_t dir)
60+
{
61+
return ((bool(__thiscall*)(CWeaponSAInterface*, CPedSAInterface*, CEntitySAInterface*, eWeaponType, int, ePedPieceTypes, std::uint8_t))0x73A530)(
62+
this, ped, responsible, weaponType, damagePerHit, hitZone, dir);
63+
}
4664
};
4765
static_assert(sizeof(CWeaponSAInterface) == 0x1C, "Invalid size for CWeaponSAInterface");
4866

4967
class CWeaponSA : public CWeapon
5068
{
5169
public:
52-
CWeaponSA(CWeaponSAInterface* weaponInterface, CPed* owner, eWeaponSlot weaponSlot) : m_interface(weaponInterface), m_owner(owner), m_weaponSlot(weaponSlot) {}
70+
CWeaponSA(CWeaponSAInterface* weaponInterface, CPed* owner, eWeaponSlot weaponSlot) : m_interface(weaponInterface), m_owner(owner), m_weaponSlot(weaponSlot)
71+
{
72+
}
5373
CWeaponSAInterface* GetInterface() { return m_interface; }
5474
CWeaponSAInterface* GetInterface() const { return m_interface; }
5575

5676
eWeaponType GetType() const override { return m_interface ? m_interface->m_eWeaponType : eWeaponType::WEAPONTYPE_UNIDENTIFIED; }
57-
void SetType(const eWeaponType& type) override { if (m_interface) m_interface->m_eWeaponType = type; }
77+
void SetType(eWeaponType type) override
78+
{
79+
if (m_interface)
80+
m_interface->m_eWeaponType = type;
81+
}
5882

5983
eWeaponState GetState() const override { return m_interface ? m_interface->m_eState : eWeaponState::WEAPONSTATE_READY; }
60-
void SetState(const eWeaponState& state) override { if (m_interface) m_interface->m_eState = state; }
84+
void SetState(eWeaponState state) override
85+
{
86+
if (m_interface)
87+
m_interface->m_eState = state;
88+
}
6189

6290
std::uint32_t GetAmmoInClip() const override { return m_interface ? m_interface->m_ammoInClip : 0; }
63-
void SetAmmoInClip(std::uint32_t ammoInClip) override { if (m_interface) m_interface->m_ammoInClip = ammoInClip; }
91+
void SetAmmoInClip(std::uint32_t ammoInClip) override
92+
{
93+
if (m_interface)
94+
m_interface->m_ammoInClip = ammoInClip;
95+
}
6496

6597
std::uint32_t GetAmmoTotal() const override { return m_interface ? m_interface->m_ammoTotal : 0; }
66-
void SetAmmoTotal(std::uint32_t ammoTotal) override { if (m_interface) m_interface->m_ammoTotal = ammoTotal; }
98+
void SetAmmoTotal(std::uint32_t ammoTotal) override
99+
{
100+
if (m_interface)
101+
m_interface->m_ammoTotal = ammoTotal;
102+
}
67103

68-
CPed* GetPed() const noexcept override { return m_owner; }
69-
eWeaponSlot GetSlot() const noexcept override { return m_weaponSlot; }
70-
CWeaponInfo* GetInfo(const eWeaponSkill& skill) const override;
104+
CPed* GetPed() const noexcept override { return m_owner; }
105+
eWeaponSlot GetSlot() const noexcept override { return m_weaponSlot; }
106+
CWeaponInfo* GetInfo(eWeaponSkill skill) const override;
71107

72108
void SetAsCurrentWeapon() override;
73109

74110
void Destroy() override;
75111
void Remove() override;
76-
void Initialize(const eWeaponType& type, std::uint32_t ammo, CPed* ped) override;
77-
void Update(CPed* ped) override;
112+
void Initialize(eWeaponType type, std::uint32_t ammo, CPed* ped) override;
78113

79114
void AddGunshell(CEntity* firingEntity, const CVector& vecOrigin, const CVector2D& vecDirection, float size) const override;
80-
void DoBulletImpact(CEntity* firingEntity, CEntitySAInterface* hitEntityInterface, const CVector& vecOrigin, const CVector& vecTarget, const CColPoint& colPoint, int incrementalHit) const override;
115+
void DoBulletImpact(CEntity* firingEntity, CEntitySAInterface* hitEntityInterface, const CVector& vecOrigin, const CVector& vecTarget,
116+
const CColPointSAInterface& colPoint, int incrementalHit) const override;
81117
bool Fire(CEntity* firingEntity, CVector* vecOrigin, CVector* vecEffectPos, CEntity* targetEntity, CVector* vecTarget, CVector* vecAlt) override;
82-
bool FireInstantHit(CEntity* firingEntity, const CVector* vecOrigin, const CVector* vecMuzzle, CEntity* targetEntity, const CVector* vecTarget, const CVector* vecForDriveby, bool crossHairGun, bool createGunFx) override;
118+
bool FireInstantHit(CEntity* firingEntity, CVector* vecOrigin, CVector* vecMuzzle, CEntity* targetEntity, CVector* vecTarget, CVector* vecForDriveby,
119+
bool crossHairGun, bool createGunFx) override;
83120
bool FireBullet(CEntity* firingEntity, const CVector& vecOrigin, const CVector& vecTarget) override;
84121

85-
bool GenerateDamageEvent(CPed* ped, CEntity* responsible, eWeaponType weaponType, int damagePerHit, ePedPieceTypes hitZone, std::uint8_t dir) const override;
122+
bool GenerateDamageEvent(CPed* ped, CEntity* responsible, eWeaponType weaponType, int damagePerHit, ePedPieceTypes hitZone,
123+
std::uint8_t dir) const override;
86124

87-
bool ProcessLineOfSight(const CVector* vecStart, const CVector* vecEnd, CColPoint** colCollision, CEntity** collisionEntity, const SLineOfSightFlags& flags, SLineOfSightBuildingResult* buildingResult, const eWeaponType& weaponType, CEntitySAInterface** entity) override;
125+
bool ProcessLineOfSight(const CVector& vecStart, const CVector& vecEnd, CColPoint** colCollision, CEntity*& collisionEntity, const SLineOfSightFlags& flags,
126+
SLineOfSightBuildingResult* buildingResult, eWeaponType weaponType, CEntitySAInterface** entity) override;
88127

89-
int GetWeaponReloadTime(CWeaponStat* weaponStat) const override;
128+
int GetWeaponReloadTime(CWeaponStat* weaponStat) const override;
90129
static int GetWeaponFireTime(CWeaponStat* weaponStat);
91-
130+
92131
private:
93132
CWeaponSAInterface* m_interface{nullptr};
94133
CPed* m_owner{nullptr};

0 commit comments

Comments
 (0)