1
- #include " core/commands/BoolCommand .hpp"
1
+ #include " core/commands/LoopedCommand .hpp"
2
2
#include " game/backend/ScriptPatches.hpp"
3
+ #include " game/gta/Natives.hpp"
3
4
4
5
namespace YimMenu ::Features
5
6
{
6
- class PlayAllMissionsSolo : public BoolCommand
7
+ class PlayAllMissionsSolo : public LoopedCommand
7
8
{
8
- using BoolCommand::BoolCommand ;
9
+ using LoopedCommand::LoopedCommand ;
9
10
10
11
ScriptPatch m_CanLaunchJobPatch{};
11
12
ScriptPatch m_MissionRequestPatch1{}; // TODO: do we need these patches?
@@ -19,16 +20,21 @@ namespace YimMenu::Features
19
20
ScriptPatch m_ShouldFailMissionPatch1{}; // god I hate this function
20
21
std::vector<ScriptPatch> m_ShouldFailMissionPatches{};
21
22
ScriptPatch m_ShouldFailMissionPatch2{};
22
- ScriptPatch m_EnsureMissionPassedPatch{};
23
+ ScriptPatch m_ShouldFailMissionPatch3{};
24
+ ScriptPatch m_NotEnoughTeamsPatch{};
25
+ ScriptPatch m_IsTeamValidPatch{}; // TODO: probably has many unintended side effects
26
+ ScriptPatch m_EnsureMissionPassedPatch{};
27
+ ScriptPatch m_ProcessPhoneHackingPatch{};
23
28
24
29
virtual void OnEnable () override
25
30
{
26
31
if (!m_CanLaunchJobPatch)
27
32
{
28
- m_CanLaunchJobPatch = ScriptPatches::AddPatch (" fmmc_launcher" _J, " 2D 05 0C 00 00 71" , 5 , {0x72 , 0x2E , 0x05 , 0x01 });
33
+ m_CanLaunchJobPatch = ScriptPatches::AddPatch (" fmmc_launcher" _J, " 2D 05 0C 00 00 71" , 5 , {0x72 , 0x2E , 0x05 , 0x01 }); // the main patch that bypasses the not enough players alert
29
34
}
30
35
m_CanLaunchJobPatch->Enable ();
31
36
37
+ // these patches allow the mission request system to launch fm_mission_controller with insufficent players
32
38
if (!m_MissionRequestPatch1)
33
39
{
34
40
m_MissionRequestPatch1 = ScriptPatches::AddPatch (" freemode" _J, " 38 00 72 5D ? ? ? 38 00 5D ? ? ? 2E 02 00 38 00 38 01" , 0 , std::vector<std::uint8_t >(14 , 0x0 ));
@@ -55,7 +61,7 @@ namespace YimMenu::Features
55
61
56
62
if (!m_PlayerCountWatchdogPatch1)
57
63
{
58
- m_PlayerCountWatchdogPatch1 = ScriptPatches::AddPatch (" fmmc_launcher" _J, " 2D 02 09 00 00 25 A4" , 5 , {0x71 , 0x2E , 0x02 , 0x01 });
64
+ m_PlayerCountWatchdogPatch1 = ScriptPatches::AddPatch (" fmmc_launcher" _J, " 2D 02 09 00 00 25 A4" , 5 , {0x71 , 0x2E , 0x02 , 0x01 }); // instant kick if this check fails
59
65
}
60
66
m_PlayerCountWatchdogPatch1->Enable ();
61
67
@@ -67,10 +73,10 @@ namespace YimMenu::Features
67
73
68
74
if (!m_HeistTeamsPatch1)
69
75
{
70
- m_HeistTeamsPatch1 = ScriptPatches::AddPatch (" fmmc_launcher" _J, " 47 ? ? 5B 7B 00 38 04" , 0 , {0x2B , 0x2B , 0x00 , 0x55 });
76
+ m_HeistTeamsPatch1 = ScriptPatches::AddPatch (" fmmc_launcher" _J, " 47 ? ? 5B 7B 00 38 04" , 0 , {0x2B , 0x2B , 0x00 , 0x55 }); // TODO: doesn't work for doomsday heist
71
77
}
72
78
m_HeistTeamsPatch1->Enable ();
73
-
79
+
74
80
if (!m_HeistTeamsPatch2)
75
81
{
76
82
m_HeistTeamsPatch2 = ScriptPatches::AddPatch (" fmmc_launcher" _J, " 2D 01 05 00 00 25 5D" , 5 , {0x72 , 0x2E , 0x01 , 0x01 });
@@ -86,6 +92,7 @@ namespace YimMenu::Features
86
92
if (m_ShouldFailMissionPatches.empty ())
87
93
{
88
94
// TODO: this is a very bad idea that can break anytime
95
+ // for some reason, Rockstar thought it's a good idea to copy-paste the same failure check in four different branches, "just in case"
89
96
for (int i = 0 ; i < 4 ; i++)
90
97
m_ShouldFailMissionPatches.push_back (ScriptPatches::AddPatch (" fm_mission_controller" _J, " 38 02 5D ? ? ? 71 09 2A 56 07 00 71 5D ? ? ? 06 1F 56" , 0 , {0x71 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 }));
91
98
}
@@ -95,15 +102,50 @@ namespace YimMenu::Features
95
102
96
103
if (!m_ShouldFailMissionPatch2)
97
104
{
98
- m_ShouldFailMissionPatch2 = ScriptPatches::AddPatch (" fm_mission_controller" _J, " 56 07 00 38 02 5D ? ? ? 20 56 BC 01" , 0 , {0x2B , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x2B , 0x71 });
105
+ m_ShouldFailMissionPatch2 = ScriptPatches::AddPatch (" fm_mission_controller" _J, " 56 07 00 38 02 5D ? ? ? 20 56 BC 01" , 0 , {0x2B , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x2B , 0x71 }); // some heist check, more or less same as above
99
106
}
100
107
m_ShouldFailMissionPatch2->Enable ();
108
+
109
+ if (!m_ShouldFailMissionPatch3)
110
+ {
111
+ m_ShouldFailMissionPatch3 = ScriptPatches::AddPatch (" fm_mission_controller" _J, " 50 ? ? 78 82 06 1F 56 2E 01" , 0 , {0x00 , 0x00 , 0x00 , 0x00 , 0x72 });
112
+ }
113
+ m_ShouldFailMissionPatch3->Enable ();
114
+
115
+ if (!m_NotEnoughTeamsPatch)
116
+ {
117
+ m_NotEnoughTeamsPatch = ScriptPatches::AddPatch (" fm_mission_controller" _J, " 2D 00 02 00 00 61 ? ? ? 47 ? ? 72 57 04 00 72 2E 00 01 4F" , 5 , {0x71 , 0x2E , 0x00 , 0x01 });
118
+ }
119
+ m_NotEnoughTeamsPatch->Enable ();
120
+
121
+ if (!m_IsTeamValidPatch)
122
+ {
123
+ m_IsTeamValidPatch = ScriptPatches::AddPatch (" fm_mission_controller" _J, " 2D 01 03 00 00 38 00 71 57 1D 00" , 5 , {0x72 , 0x2E , 0x01 , 0x01 });
124
+ }
125
+ m_IsTeamValidPatch->Enable ();
101
126
102
127
if (!m_EnsureMissionPassedPatch)
103
128
{
104
- m_EnsureMissionPassedPatch = ScriptPatches::AddPatch (" fm_mission_controller" _J, " 55 C8 FF 61" , 3 , {0x2E , 0x00 , 0x00 });
129
+ m_EnsureMissionPassedPatch = ScriptPatches::AddPatch (" fm_mission_controller" _J, " 55 C8 FF 61" , 3 , {0x2E , 0x00 , 0x00 }); // the game does one final check to ensure all players exist before the mission is passed
105
130
}
106
131
m_EnsureMissionPassedPatch->Enable ();
132
+
133
+ if (!m_ProcessPhoneHackingPatch)
134
+ {
135
+ m_ProcessPhoneHackingPatch = ScriptPatches::AddPatch (" fm_mission_controller" _J, " 58 13 00 38 00 4F ? ? 48" , 0 , {0x2B , 0x00 , 0x00 });
136
+ }
137
+ }
138
+
139
+ virtual void OnTick () override
140
+ {
141
+ if (m_ProcessPhoneHackingPatch)
142
+ {
143
+ // the patch transfers the hacking minigame from the passenger to the driver, so we only want it applied when we're playing solo
144
+ if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH (" fm_mission_controller" _J) && NETWORK::NETWORK_GET_TOTAL_NUM_PLAYERS () == 1 )
145
+ m_ProcessPhoneHackingPatch->Enable ();
146
+ else
147
+ m_ProcessPhoneHackingPatch->Disable ();
148
+ }
107
149
}
108
150
109
151
virtual void OnDisable () override
@@ -166,10 +208,30 @@ namespace YimMenu::Features
166
208
m_ShouldFailMissionPatch2->Disable ();
167
209
}
168
210
211
+ if (m_ShouldFailMissionPatch3)
212
+ {
213
+ m_ShouldFailMissionPatch3->Disable ();
214
+ }
215
+
216
+ if (m_NotEnoughTeamsPatch)
217
+ {
218
+ m_NotEnoughTeamsPatch->Disable ();
219
+ }
220
+
221
+ if (m_IsTeamValidPatch)
222
+ {
223
+ m_IsTeamValidPatch->Disable ();
224
+ }
225
+
169
226
if (m_EnsureMissionPassedPatch)
170
227
{
171
228
m_EnsureMissionPassedPatch->Disable ();
172
229
}
230
+
231
+ if (m_ProcessPhoneHackingPatch)
232
+ {
233
+ m_ProcessPhoneHackingPatch->Disable ();
234
+ }
173
235
}
174
236
};
175
237
0 commit comments