|
10 | 10 |
|
11 | 11 | #include <ScriptEngine.h> |
12 | 12 | #include <Hooking.h> |
| 13 | +#include "Hooking.Stubs.h" |
13 | 14 | #include <scrEngine.h> |
14 | 15 | #include <CrossBuildRuntime.h> |
15 | 16 | #include "RageParser.h" |
16 | 17 | #include "ScriptWarnings.h" |
17 | 18 | #include <EntitySystem.h> |
| 19 | +#include <CoreConsole.h> |
18 | 20 | #include <vector> |
19 | 21 |
|
20 | 22 | static bool* g_textCentre; |
21 | 23 | static bool* g_textDropshadow; |
22 | 24 |
|
| 25 | +static bool g_skipScenarioMaleCheck = false; |
| 26 | +static bool g_skipScenarioFemaleCheck = false; |
| 27 | + |
23 | 28 | struct netObject |
24 | 29 | { |
25 | 30 | char pad[64]; // +0 |
@@ -149,6 +154,44 @@ static void FixPedCombatAttributes() |
149 | 154 | }); |
150 | 155 | } |
151 | 156 |
|
| 157 | +static InitFunction initFunction([]() |
| 158 | +{ |
| 159 | + static ConVar<bool> g_skipScenarioMaleCheckConVar("sv_skipScenarioMaleCheck", ConVar_Replicated, false, &g_skipScenarioMaleCheck); |
| 160 | + static ConVar<bool> g_skipScenarioFemaleCheckConVar("sv_skipScenarioFemaleCheck", ConVar_Replicated, false, &g_skipScenarioFemaleCheck); |
| 161 | +}); |
| 162 | + |
| 163 | +static hook::cdecl_stub<bool(CPed* ped)> hasPlayerComponent([]() |
| 164 | +{ |
| 165 | + return hook::get_pattern("0F 95 C0 C3 48 83 EC ? 83 F9", -40); |
| 166 | +}); |
| 167 | + |
| 168 | + |
| 169 | +static bool (*g_origCAIConditionIsMale)(void* self, void* context); |
| 170 | +static bool CAIConditionIsMale(void* self, void* context) |
| 171 | +{ |
| 172 | + int v3 = *(int*)((char*)self + 16); |
| 173 | + CPed* ped = *(CPed**)((char*)context + 192 + (8 * v3)); |
| 174 | + |
| 175 | + if (g_skipScenarioMaleCheck && ped && hasPlayerComponent(ped)) |
| 176 | + { |
| 177 | + return true; |
| 178 | + } |
| 179 | + return g_origCAIConditionIsMale(self, context); |
| 180 | +} |
| 181 | + |
| 182 | +static bool (*g_origCAIConditionIsFemale)(void* self, void* context); |
| 183 | +static bool CAIConditionIsFemale(void* self, void* context) |
| 184 | +{ |
| 185 | + int v3 = *(int*)((char*)self + 16); |
| 186 | + CPed* ped = *(CPed**)((char*)context + 192 + (8 * v3)); |
| 187 | + |
| 188 | + if (g_skipScenarioFemaleCheck && ped && hasPlayerComponent(ped)) |
| 189 | + { |
| 190 | + return true; |
| 191 | + } |
| 192 | + return g_origCAIConditionIsFemale(self, context); |
| 193 | +} |
| 194 | + |
152 | 195 | static HookFunction hookFunction([]() |
153 | 196 | { |
154 | 197 | { |
@@ -216,4 +259,10 @@ static HookFunction hookFunction([]() |
216 | 259 | // mov rax, [r14] (restore rax value from r14) |
217 | 260 | hook::put((char*)location + 10, 0x068B49); |
218 | 261 | } |
| 262 | + |
| 263 | + { |
| 264 | + // Allow players to use scenario without checking the gender |
| 265 | + g_origCAIConditionIsFemale = hook::trampoline(hook::get_pattern("48 F7 DA 48 1B C0 48 23 C1 8A 40 ? C0 E8 ? F6 D0 24 ? EB ? 49 8B C8", -0x30), CAIConditionIsFemale); |
| 266 | + g_origCAIConditionIsMale = hook::trampoline(hook::get_pattern("48 F7 DA 48 1B C0 48 23 C1 8A 40 ? C0 E8 ? 24 ? EB", -0x4F), CAIConditionIsMale); |
| 267 | + } |
219 | 268 | }); |
0 commit comments