Skip to content

Commit c2e52a2

Browse files
committed
Weapon Stats Randomizer: Crash fixes
* Fixed a crash because of missing null pointer check in phInst for projectile pre-physics simulation function * Removed problematic weapons from the gun groups in WeaponModels that would previously cause a crash. Alternatively, once ScriptHook hooks are working, there's an implementation for fixing that in-code with a hook (we want to ensure compatibility with Chaos effects that use this native).
1 parent 800dfa6 commit c2e52a2

File tree

3 files changed

+76
-9
lines changed

3 files changed

+76
-9
lines changed

data/WeaponModels.txt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ w_pi_flaregun
6868
w_ar_heavyrifleh
6969
w_sb_microsmg_las
7070
w_sg_pumpshotgun_chs
71-
prop_space_pistol
72-
prop_space_rifle
73-
ch_prop_collectibles_limb_01a
7471

7572
w_ar_advancedrifle
7673
w_ar_advancedrifle_luxe
@@ -226,9 +223,6 @@ w_lr_firework
226223
w_lr_homing
227224
w_lr_rpg
228225
w_pi_flaregun
229-
prop_space_pistol
230-
prop_space_rifle
231-
ch_prop_collectibles_limb_01a
232226

233227
w_me_bat
234228
w_me_battleaxe
@@ -6048,4 +6042,4 @@ w_am_jerrycan_sf
60486042
w_ar_heavyrifleh
60496043
w_pi_appistol_sts
60506044
w_sb_microsmg_las
6051-
w_sg_pumpshotgun_chs
6045+
w_sg_pumpshotgun_chs

lib/CEntity.hh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
class CEntity
99
{
1010
public:
11-
void * vft;
12-
void * m_pRefHolder;
11+
void *vft;
12+
void *m_pRefHolder;
1313
fwExtensionList m_List;
1414
CBaseModelInfo *m_pModelInfo;
1515
uint32_t m_Type;
16+
class phInst *m_phInst;
1617
};
1718

1819
static_assert (offsetof (CEntity, m_pModelInfo) == 32);

src/weapons/stats.cc

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1+
#include "CEntity.hh"
12
#include "CItemInfo.hh"
3+
#include "CModelInfo.hh"
24
#include "CStreaming.hh"
35
#include "Utils.hh"
46
#include "common/events.hh"
57
#include "common/config.hh"
8+
#include "common/minhook.hh"
69
#include "common/parser.hh"
710
#include "common/logger.hh"
11+
#include "scrThread.hh"
812
#include <cstdint>
13+
#include <ctime>
914
#include <utility>
1015

16+
#include <CTheScripts.hh>
17+
1118
#ifdef ENABLE_DEBUG_MENU
1219
#include <debug/base.hh>
1320
#endif
1421

22+
using namespace NativeLiterals;
23+
1524
// Ammo Info Randomizer
1625
// *******************************************************
1726
using CAmmoInfoRandomizer = ParserRandomHelper<
@@ -115,9 +124,68 @@ class WeaponStatsRandomizer
115124
HandleItemInfoRandomization (false);
116125
}
117126

127+
/*******************************************************/
128+
template <auto &CProjectileEntity__PreSim>
129+
static int
130+
ProjectilePhysicsFix (CEntity *p1, float p2, bool p3, int p4)
131+
{
132+
/* Fixes a crash caused by delayed loading of the physics object for a
133+
* rocket projectile. This adds a null pointer check that R* forgot ..
134+
*/
135+
136+
if (!p1->m_phInst)
137+
{
138+
Rainbomizer::Logger::LogMessage (
139+
"Projectile Physics Instance not loaded: %x",
140+
p1->m_pModelInfo->m_nHash);
141+
142+
return 2;
143+
}
144+
145+
return CProjectileEntity__PreSim (p1, p2, p3, p4);
146+
}
147+
148+
/*******************************************************/
149+
static void
150+
FixShootsAtCoord (scrThread::Info *ctx)
151+
{
152+
auto ped = ctx->GetArg (0);
153+
154+
uint32_t weap = "GET_SELECTED_PED_WEAPON"_n(ped);
155+
auto *weapModel = CStreaming::GetModelByHash (weap);
156+
157+
static constexpr std::array BlackListedWeapons
158+
= {"prop_space_pistol"_joaat, "prop_space_rifle"_joaat,
159+
"ch_prop_collectibles_limb_01a"_joaat};
160+
161+
// We know this can happen with these weapons, so exit without logging
162+
if (DoesElementExist (BlackListedWeapons, weap))
163+
return;
164+
165+
// In all other cases (e.g., it gets called for melee weapons randomized
166+
// into props), exit with a log message at a cooldown (so as to not spam
167+
// the log more than necessary).
168+
if (!weapModel
169+
|| weapModel->GetType () != eModelInfoType::MODEL_INFO_WEAPON)
170+
{
171+
const int LOG_COOLDOWN = 5;
172+
static auto lastPrint = 0;
173+
174+
if (time (NULL) - lastPrint > LOG_COOLDOWN)
175+
Rainbomizer::Logger::LogMessage (
176+
"SET_PED_SHOOTS_AT_COORD called for non-weapon model: "
177+
"%x %p",
178+
weap, weapModel);
179+
return;
180+
}
181+
182+
NativeManager::InvokeNative ("SET_PED_SHOOTS_AT_COORD"_joaat, ctx);
183+
}
184+
118185
/*******************************************************/
119186
WeaponStatsRandomizer ()
120187
{
188+
121189
if (!ConfigManager::ReadConfig ("WeaponStatsRandomizer"))
122190
return;
123191

@@ -128,6 +196,10 @@ class WeaponStatsRandomizer
128196
DebugInterfaceManager::AddAction ("Randomize Weapon Stats",
129197
RandomizeWeaponStats);
130198
#endif
199+
REGISTER_MH_HOOK (
200+
"? 0f 28 e1 ? 8b 41 30 b9 ff ff 00 00 66 39 48 18 75 ?", -0x56,
201+
ProjectilePhysicsFix, int, CEntity *, float, bool, int);
202+
131203
InitialiseAllComponents ();
132204
}
133205
} _stats;

0 commit comments

Comments
 (0)