mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2025-06-16 22:37:22 +08:00

* Added ability to resolve WCT_INVALID attachments at runtime from the achievement_controller script, such as the game does. * Improved component information extraction to also retrieve the descriptions from the scripts. Redesigned Ammunation to now only display proper components. Added a tooltip of the component description to Ammunation. * Refactored script_function::call to fail gracefully if called out of lockstep when the scripts are running.
84 lines
3.1 KiB
C++
84 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include "gta_util.hpp"
|
|
#include "pointers.hpp"
|
|
#include "util/scripts.hpp"
|
|
|
|
#include <script/scrProgram.hpp>
|
|
|
|
namespace big
|
|
{
|
|
class script_function
|
|
{
|
|
rage::joaat_t m_script;
|
|
const memory::pattern m_pattern;
|
|
uint32_t m_ip;
|
|
std::string m_name;
|
|
|
|
public:
|
|
script_function(const std::string& name, const rage::joaat_t script, const std::string& pattern);
|
|
uint32_t get_ip(rage::scrProgram* program);
|
|
|
|
template<typename Arg>
|
|
void push_arg(uint64_t* stack, uint32_t& stack_pointer, Arg&& value)
|
|
{
|
|
*reinterpret_cast<std::remove_cv_t<std::remove_reference_t<Arg>>*>(reinterpret_cast<uint64_t*>(stack) + (stack_pointer++)) = std::forward<Arg>(value);
|
|
}
|
|
|
|
template<typename Ret, typename... Args>
|
|
Ret call(Args... args)
|
|
{
|
|
auto thread = gta_util::find_script_thread(m_script);
|
|
auto program = gta_util::find_script_program(m_script);
|
|
|
|
if (!thread || !program)
|
|
{
|
|
LOG(FATAL) << m_name << " failed to find its associated script running.";
|
|
return Ret();
|
|
}
|
|
|
|
auto ip = get_ip(program);
|
|
if (!ip)
|
|
{
|
|
return Ret();
|
|
}
|
|
|
|
auto tls_ctx = rage::tlsContext::get();
|
|
auto stack = (uint64_t*)thread->m_stack;
|
|
auto og_thread = tls_ctx->m_script_thread;
|
|
tls_ctx->m_script_thread = thread;
|
|
tls_ctx->m_is_script_thread_active = true;
|
|
rage::scrThreadContext ctx = thread->m_context;
|
|
auto top_stack = ctx.m_stack_pointer; // This will be the top item in the stack after the args and return address are cleaned off
|
|
|
|
(push_arg(stack, ctx.m_stack_pointer, std::forward<Args>(args)), ...);
|
|
|
|
stack[ctx.m_stack_pointer++] = 0;
|
|
ctx.m_instruction_pointer = ip;
|
|
ctx.m_state = rage::eThreadState::idle;
|
|
|
|
g_pointers->m_gta.m_script_vm(stack, g_pointers->m_gta.m_script_globals, program, &ctx);
|
|
|
|
tls_ctx->m_script_thread = og_thread;
|
|
tls_ctx->m_is_script_thread_active = og_thread != nullptr;
|
|
|
|
if constexpr (!std::is_same_v<Ret, void>)
|
|
{
|
|
return *reinterpret_cast<Ret*>(stack + top_stack);
|
|
}
|
|
}
|
|
};
|
|
|
|
namespace scr_functions
|
|
{
|
|
inline script_function set_as_ceo("SAC", "freemode"_J, "2D 04 1D 00 00 5D");
|
|
inline script_function set_freemode_session_active("SFSA", "freemode"_J, "2D 00 02 00 00 75 5D ? ? ? 50");
|
|
inline script_function save_to_datafile("STD", "fm_race_creator"_J, "2D 01 03 00 00 71 2C");
|
|
inline script_function load_from_datafile("LFD", "fm_race_creator"_J, "2D 03 0C 00 00 71 2C");
|
|
inline script_function reset_session_data("RSD", "main_persistent"_J, "2D 02 7D 00 00");
|
|
inline script_function add_clan_logo_to_vehicle("ACLTV", "main_persistent"_J, "2D 02 04 00 00 5D ? ? ? 61");
|
|
inline script_function vehicle_cannot_accept_clan_logo("CVACL", "main_persistent"_J, "2D 01 03 00 00 2C 01 00 A1 06 ? 04");
|
|
inline script_function get_component_name_string("GCNS", "mp_weapons"_J, "2D 02 43 00 00 38 01");
|
|
inline script_function get_component_desc_string("GCDS", "mp_weapons"_J, "2D 02 43 00 00 38 00");
|
|
}
|
|
} |