feat(recovery): Allow Saving Vehicles During Missions (#77)

* feat(recovery): Allow Saving Vehicles During Missions

* Fix

* Fix 2
This commit is contained in:
Arthur authored and GitHub committed 2025-04-01 23:35:58 +00:00
1 parent 1bf8a5eb94
commit a42889a321
4 files changed
+81 -24

No files matched your search

@@ -12,43 +12,79 @@ namespace YimMenu
bool GiveVehicleReward::IsSafeToRunScript()
{
return Self::GetVehicle().IsValid() && *Pointers.IsSessionStarted && SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("AM_MP_VEHICLE_REWARD"_J) > 0;
return Self::GetVehicle().IsValid() && *Pointers.IsSessionStarted;
}
void GiveVehicleReward::RunScriptImpl()
{
while (g_Running)
{
if (m_ShouldRunScript)
ScriptMgr::Yield();
if (!m_ShouldRunScript)
continue;
if (!IsSafeToRunScript())
{
if (IsSafeToRunScript())
if (m_StartedByUs && m_Thread)
{
if (auto thread = Scripts::FindScriptThread("AM_MP_VEHICLE_REWARD"_J))
{
if (auto VehicleRewardData = VEHICLE_REWARD_DATA::Get(thread))
{
auto VehicleMenuData = ScriptLocal(thread, 176).As<PINT>(); // TO-DO: add struct for this?
if (giveVehicleReward.Call<bool>(Self::GetVehicle().GetHandle(), VehicleMenuData, &VehicleRewardData->TransactionStatus, &VehicleRewardData->Garage, &VehicleRewardData->GarageOffset, &VehicleRewardData->ControlStatus, false, true, true, false, 0, -1))
{
if (VehicleRewardData->ControlStatus != 3)
{
VehicleRewardData->TransactionStatus = 0;
VehicleRewardData->Garage = 0;
VehicleRewardData->GarageOffset = 0;
VehicleRewardData->ControlStatus = 0;
m_ShouldRunScript = false;
}
}
}
}
m_Thread->m_Context.m_State = rage::scrThread::State::KILLED;
m_StartedByUs = false;
}
m_Thread = nullptr;
m_ShouldRunScript = false;
continue;
}
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("AM_MP_VEHICLE_REWARD"_J) == 0)
{
SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH("AM_MP_VEHICLE_REWARD"_J);
if (SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED("AM_MP_VEHICLE_REWARD"_J))
{
int id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH("AM_MP_VEHICLE_REWARD"_J, 2050);
m_Thread = Scripts::FindScriptThreadByID(id);
if (m_Thread)
m_Thread->m_Context.m_State = rage::scrThread::State::PAUSED;
SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED("AM_MP_VEHICLE_REWARD"_J);
m_StartedByUs = true;
}
else
{
m_ShouldRunScript = false;
continue;
}
}
else
{
m_Thread = Scripts::FindScriptThread("AM_MP_VEHICLE_REWARD"_J);
}
ScriptMgr::Yield();
if (!m_Thread)
{
m_ShouldRunScript = false;
continue;
}
if (auto VehicleRewardData = VEHICLE_REWARD_DATA::Get(m_Thread))
{
auto VehicleMenuData = ScriptLocal(m_Thread, 176).As<int*>(); // TO-DO: add struct for this?
if (giveVehicleReward.Call<bool>(Self::GetVehicle().GetHandle(), VehicleMenuData, &VehicleRewardData->TransactionStatus, &VehicleRewardData->Garage, &VehicleRewardData->GarageOffset, &VehicleRewardData->ControlStatus, false, true, true, false, 0, -1))
{
if (VehicleRewardData->ControlStatus != 3)
{
VehicleRewardData->TransactionStatus = 0;
VehicleRewardData->Garage = 0;
VehicleRewardData->GarageOffset = 0;
VehicleRewardData->ControlStatus = 0;
if (m_StartedByUs)
{
m_Thread->m_Context.m_State = rage::scrThread::State::KILLED;
m_StartedByUs = false;
}
m_Thread = nullptr;
m_ShouldRunScript = false;
}
}
}
}
}
}
@@ -1,5 +1,10 @@
#pragma once
namespace rage
{
class scrThread;
}
namespace YimMenu
{
class GiveVehicleReward
@@ -12,7 +17,9 @@ namespace YimMenu
void RunScriptImpl();
bool m_ShouldRunScript = false;
bool m_ShouldRunScript = false;
bool m_StartedByUs = false;
rage::scrThread* m_Thread = nullptr;
public:
static bool IsSafeToRunScript();
+13
View File
@@ -28,6 +28,19 @@ namespace YimMenu::Scripts
return nullptr;
}
rage::scrThread* FindScriptThreadByID(std::uint32_t id)
{
for (auto& thread : *Pointers.ScriptThreads)
{
if (thread && thread->m_Context.m_ThreadId == id)
{
return thread;
}
}
return nullptr;
}
rage::scrProgram* FindScriptProgram(joaat_t hash)
{
for (int i = 0; i < 176; i++)
+1
View File
@@ -12,6 +12,7 @@ class SimplePattern;
namespace YimMenu::Scripts
{
extern rage::scrThread* FindScriptThread(joaat_t hash);
extern rage::scrThread* FindScriptThreadByID(std::uint32_t id);
extern rage::scrProgram* FindScriptProgram(joaat_t hash);
extern void RunAsScript(rage::scrThread* thread, std::function<void()> callback);
extern void RunWithSpoofedThreadName(std::uint32_t name, std::function<void()> callback); // consider using RunAsScript if possible