mirror of
https://github.com/YimMenu/YimMenuV2.git
synced 2026-10-10 20:03:17 +08:00
Merge branch 'enhanced' of https://github.com/YimMenu/YimMenuV2 into enhanced
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
#include "GiveVehicleReward.hpp"
|
||||
#include "core/backend/ScriptMgr.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "game/gta/Natives.hpp"
|
||||
#include "game/gta/ScriptFunction.hpp"
|
||||
#include "game/gta/ScriptLocal.hpp"
|
||||
#include "types/script/locals/VehicleRewardData.hpp"
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
static ScriptFunction giveVehicleReward("GVR", "AM_MP_VEHICLE_REWARD"_J, "2D 0C 1E 00 00");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void GiveVehicleReward::RunScriptImpl()
|
||||
{
|
||||
while (g_Running)
|
||||
{
|
||||
if (m_ShouldRunScript)
|
||||
{
|
||||
if (IsSafeToRunScript())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ShouldRunScript = false;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptMgr::Yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
class GiveVehicleReward
|
||||
{
|
||||
static GiveVehicleReward& GetInstance()
|
||||
{
|
||||
static GiveVehicleReward instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void RunScriptImpl();
|
||||
|
||||
bool m_ShouldRunScript = false;
|
||||
|
||||
public:
|
||||
static bool IsSafeToRunScript();
|
||||
|
||||
static void RunScript()
|
||||
{
|
||||
GetInstance().RunScriptImpl();
|
||||
}
|
||||
|
||||
static void SetShouldRunScript(bool run)
|
||||
{
|
||||
GetInstance().m_ShouldRunScript = run;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "submenus/Teleport.hpp"
|
||||
#include "submenus/Network.hpp"
|
||||
#include "submenus/Players.hpp"
|
||||
#include "submenus/Recovery.hpp"
|
||||
#include "submenus/Settings.hpp"
|
||||
#include "submenus/Debug.hpp"
|
||||
#include "submenus/World.hpp"
|
||||
@@ -25,6 +26,7 @@ namespace YimMenu
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::World>());
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Network>());
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Players>());
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Recovery>());
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Settings>());
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Debug>());
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "Recovery.hpp"
|
||||
#include "game/frontend/items/Items.hpp"
|
||||
#include "game/features/recovery/GiveVehicleReward.hpp"
|
||||
|
||||
namespace YimMenu::Submenus
|
||||
{
|
||||
Recovery::Recovery() :
|
||||
Submenu::Submenu("Recovery")
|
||||
{
|
||||
auto shopping = std::make_shared<Category>("Shopping");
|
||||
auto vehiclesGroup = std::make_shared<Group>("Vehicles");
|
||||
|
||||
vehiclesGroup->AddItem(std::make_unique<ImGuiItem>([] {
|
||||
if (ImGui::Button("Save This Vehicle as Personal Vehicle"))
|
||||
{
|
||||
if (GiveVehicleReward::IsSafeToRunScript())
|
||||
{
|
||||
GiveVehicleReward::SetShouldRunScript(true);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
shopping->AddItem(vehiclesGroup);
|
||||
AddCategory(std::move(shopping));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "core/frontend/manager/UIManager.hpp"
|
||||
|
||||
namespace YimMenu::Submenus
|
||||
{
|
||||
class Recovery : public Submenu
|
||||
{
|
||||
public:
|
||||
Recovery();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "ScriptFunction.hpp"
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
ScriptFunction::ScriptFunction(const std::string& name, const joaat_t script, const SimplePattern& pattern) :
|
||||
m_Name(name),
|
||||
m_Script(script),
|
||||
m_Pattern(pattern),
|
||||
m_PC(0)
|
||||
{
|
||||
}
|
||||
|
||||
std::uint32_t ScriptFunction::GetPC(rage::scrProgram* program)
|
||||
{
|
||||
if (m_PC != 0)
|
||||
return m_PC;
|
||||
|
||||
if (auto location = Scripts::GetCodeLocationByPattern(program, m_Pattern))
|
||||
{
|
||||
m_PC = location.value();
|
||||
LOG(INFO) << "Found pattern for " << m_Name << " at " << HEX(m_PC) << " in script " << program->m_Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(FATAL) << "Failed to find pattern for " << m_Name << " in script " << program->m_Name;
|
||||
}
|
||||
|
||||
return m_PC;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
#include "core/util/Joaat.hpp"
|
||||
#include "core/memory/Pattern.hpp"
|
||||
#include "game/pointers/Pointers.hpp"
|
||||
#include "game/gta/Scripts.hpp"
|
||||
#include "types/script/scrThread.hpp"
|
||||
#include "types/script/scrProgram.hpp"
|
||||
#include "types/rage/tlsContext.hpp"
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
class ScriptFunction
|
||||
{
|
||||
joaat_t m_Script;
|
||||
const SimplePattern m_Pattern;
|
||||
std::uint32_t m_PC;
|
||||
std::string m_Name;
|
||||
|
||||
std::uint32_t GetPC(rage::scrProgram* program);
|
||||
|
||||
template<typename Arg>
|
||||
void PushArg(std::uint64_t* stack, std::uint32_t& stackPtr, Arg&& value)
|
||||
{
|
||||
*reinterpret_cast<std::remove_cv_t<std::remove_reference_t<Arg>>*>(reinterpret_cast<std::uint64_t*>(stack) + (stackPtr++)) = std::forward<Arg>(value);
|
||||
}
|
||||
|
||||
public:
|
||||
ScriptFunction(const std::string& name, const joaat_t script, const SimplePattern& pattern);
|
||||
|
||||
template<typename Ret, typename... Args>
|
||||
Ret Call(Args... args)
|
||||
{
|
||||
auto thread = Scripts::FindScriptThread(m_Script);
|
||||
auto program = Scripts::FindScriptProgram(m_Script);
|
||||
|
||||
if (!thread || !program)
|
||||
return Ret();
|
||||
|
||||
auto pc = GetPC(program);
|
||||
if (!pc)
|
||||
return Ret();
|
||||
|
||||
auto tlsCtx = rage::tlsContext::Get();
|
||||
auto stack = (std::uint64_t*)thread->m_Stack;
|
||||
auto ogThread = tlsCtx->m_CurrentScriptThread;
|
||||
tlsCtx->m_CurrentScriptThread = thread;
|
||||
tlsCtx->m_ScriptThreadActive = true;
|
||||
rage::scrThread::Context ctx = thread->m_Context;
|
||||
auto topStack = ctx.m_StackPointer;
|
||||
|
||||
(PushArg(stack, ctx.m_StackPointer, std::forward<Args>(args)), ...);
|
||||
|
||||
stack[ctx.m_StackPointer++] = 0;
|
||||
ctx.m_ProgramCounter = pc;
|
||||
ctx.m_State = rage::scrThread::State::IDLE;
|
||||
|
||||
Pointers.ScriptVM(stack, Pointers.ScriptGlobals, program, &ctx);
|
||||
|
||||
tlsCtx->m_CurrentScriptThread = ogThread;
|
||||
tlsCtx->m_ScriptThreadActive = ogThread != nullptr;
|
||||
|
||||
if constexpr (!std::is_same_v<Ret, void>)
|
||||
{
|
||||
return *reinterpret_cast<Ret*>(stack + topStack);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -6,4 +6,9 @@ namespace YimMenu
|
||||
{
|
||||
return reinterpret_cast<uintptr_t*>((uintptr_t)m_StackPtr + (m_Index * sizeof(uintptr_t)));
|
||||
}
|
||||
|
||||
bool ScriptLocal::CanAccess() const
|
||||
{
|
||||
return m_StackPtr != nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <types/script/scrThread.hpp>
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
@@ -25,12 +26,11 @@ namespace YimMenu
|
||||
|
||||
}
|
||||
|
||||
// TODO: Uncomment when GTAV-Classes have been added
|
||||
// constexpr ScriptLocal(rage::scrThread* thread, std::size_t index) :
|
||||
// ScriptLocal(thread->m_stack, index)
|
||||
// {
|
||||
constexpr ScriptLocal(rage::scrThread* thread, std::size_t index) :
|
||||
ScriptLocal(thread->m_Stack, index)
|
||||
{
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
constexpr ScriptLocal At(std::ptrdiff_t offset) const
|
||||
{
|
||||
@@ -65,6 +65,8 @@ namespace YimMenu
|
||||
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(Get());
|
||||
}
|
||||
|
||||
bool CanAccess() const;
|
||||
|
||||
private:
|
||||
void* Get() const;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "types/rage/atArray.hpp"
|
||||
#include "types/rage/tlsContext.hpp"
|
||||
#include "types/script/GtaThread.hpp"
|
||||
#include "types/script/scrProgram.hpp"
|
||||
#include "types/script/CGameScriptHandler.hpp"
|
||||
#include "types/script/CGameScriptHandlerNetComponent.hpp"
|
||||
#include "types/script/CGameScriptId.hpp"
|
||||
@@ -10,6 +11,7 @@
|
||||
#include "game/gta/Packet.hpp"
|
||||
#include "game/backend/Players.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "core/memory/Pattern.hpp"
|
||||
|
||||
namespace YimMenu::Scripts
|
||||
{
|
||||
@@ -26,6 +28,16 @@ namespace YimMenu::Scripts
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rage::scrProgram* FindScriptProgram(joaat_t hash)
|
||||
{
|
||||
for (int i = 0; i < 176; i++)
|
||||
{
|
||||
if (Pointers.ScriptPrograms[i] && Pointers.ScriptPrograms[i]->m_NameHash == hash)
|
||||
return Pointers.ScriptPrograms[i];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RunAsScript(rage::scrThread* thread, std::function<void()> callback)
|
||||
{
|
||||
@@ -82,6 +94,24 @@ namespace YimMenu::Scripts
|
||||
return false;
|
||||
}
|
||||
|
||||
std::optional<std::uint32_t> GetCodeLocationByPattern(rage::scrProgram* program, SimplePattern pattern)
|
||||
{
|
||||
uint32_t codeSize = program->m_CodeSize;
|
||||
for (uint32_t i = 0; i < (codeSize - pattern.m_Bytes.size()); i++)
|
||||
{
|
||||
for (uint32_t j = 0; j < pattern.m_Bytes.size(); j++)
|
||||
if (pattern.m_Bytes[j].has_value())
|
||||
if (pattern.m_Bytes[j].value() != *program->GetCodeAddress(i + j))
|
||||
goto incorrect;
|
||||
|
||||
return i;
|
||||
incorrect:
|
||||
continue;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void ForceScriptHost(rage::scrThread* thread)
|
||||
{
|
||||
if (auto net_component = reinterpret_cast<GtaThread*>(thread)->m_NetComponent)
|
||||
|
||||
@@ -7,11 +7,15 @@ namespace rage
|
||||
class scrProgram;
|
||||
}
|
||||
|
||||
class SimplePattern;
|
||||
|
||||
namespace YimMenu::Scripts
|
||||
{
|
||||
extern rage::scrThread* FindScriptThread(joaat_t hash);
|
||||
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
|
||||
extern bool SafeToModifyFreemodeBroadcastGlobals(); // TODO: find a better method for this that works for all scripts
|
||||
extern std::optional<std::uint32_t> GetCodeLocationByPattern(rage::scrProgram* program, SimplePattern pattern);
|
||||
extern void ForceScriptHost(rage::scrThread* thread); // likely unstable, beware!
|
||||
}
|
||||
@@ -204,7 +204,7 @@ namespace YimMenu
|
||||
|
||||
constexpr auto scriptVMPtrn = Pattern<"49 63 41 1C">("ScriptVM");
|
||||
scanner.Add(scriptVMPtrn, [this](PointerCalculator ptr) {
|
||||
ScriptVM = ptr.Sub(0x24).As<PVOID>();
|
||||
ScriptVM = ptr.Sub(0x24).As<Functions::ScriptVM>();
|
||||
});
|
||||
|
||||
constexpr auto prepareMetricForSendingPtrn = Pattern<"48 89 F9 FF 50 20 48 8D 15">("PrepareMetricForSending");
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace YimMenu
|
||||
using RequestControl = void(*)(rage::netObject* object);
|
||||
using EventAck = bool(*)(uintptr_t data, CNetGamePlayer* target_player, uint32_t event_index, uint32_t event_handled_bitset);
|
||||
using SendEventAck = void(*)(rage::netEventMgr* event_manager, CNetGamePlayer* source_player);
|
||||
using ScriptVM = int (*)(uint64_t* stack, int64_t** scr_globals, rage::scrProgram* program, void* ctx);
|
||||
}
|
||||
|
||||
struct PointerData
|
||||
@@ -85,7 +86,7 @@ namespace YimMenu
|
||||
Functions::SendEventAck SendEventAck;
|
||||
PVOID QueueDependency;
|
||||
PVOID SigScanMemory;
|
||||
PVOID ScriptVM;
|
||||
Functions::ScriptVM ScriptVM;
|
||||
PVOID PrepareMetricForSending;
|
||||
int* BERestartStatus;
|
||||
bool* NeedsBERestart;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "game/backend/NativeHooks.hpp"
|
||||
#include "game/frontend/GUI.hpp"
|
||||
#include "game/pointers/Pointers.hpp"
|
||||
#include "game/features/recovery/GiveVehicleReward.hpp"
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
@@ -55,6 +56,7 @@ namespace YimMenu
|
||||
FiberPool::Init(16);
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&HotkeySystem::RunScript));
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&Commands::RunScript));
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&GiveVehicleReward::RunScript));
|
||||
|
||||
Notifications::Show("YimMenuV2", "Loaded succesfully", NotificationType::Success);
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "VehicleRewardData.hpp"
|
||||
#include "game/gta/ScriptLocal.hpp"
|
||||
|
||||
#define DEFINE_LOCAL_ACCESSOR(str, local) \
|
||||
str* str::Get(rage::scrThread* thread) \
|
||||
{ \
|
||||
auto lcl = YimMenu::ScriptLocal(thread, local); \
|
||||
if (!lcl.CanAccess()) \
|
||||
return nullptr; \
|
||||
return lcl.As<str*>(); \
|
||||
}
|
||||
|
||||
DEFINE_LOCAL_ACCESSOR(VEHICLE_REWARD_DATA, 129);
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "../types.hpp"
|
||||
|
||||
namespace rage
|
||||
{
|
||||
class scrThread;
|
||||
}
|
||||
|
||||
struct VEHICLE_REWARD_DATA
|
||||
{
|
||||
uint64_t PAD_0000[3];
|
||||
SCR_INT TransactionStatus; // 4
|
||||
SCR_INT Garage; // 5
|
||||
SCR_INT GarageOffset; // 6
|
||||
SCR_INT ControlStatus; // 7
|
||||
uint64_t PAD_0008[40];
|
||||
|
||||
static VEHICLE_REWARD_DATA* Get(rage::scrThread* thread);
|
||||
};
|
||||
static_assert(sizeof(VEHICLE_REWARD_DATA) == 47 * 8);
|
||||
Reference in New Issue
Block a user