Closed tuyilmaz closed 3 months ago
Okay, I will work on it for my upcoming PR
It's possible to add gold, cash, xp, loot tables, and collectibles instantly with script functions.
How exactly?
It's possible to add gold, cash, xp, loot tables, and collectibles instantly with script functions.
How exactly?
Script: net_main_offline Signature: 22 05 24 Args: {AwardHash, false, 255, 0, false}
What's the function name? And can you give me an example award hash?
Currently I don't have the latest decompiled scripts, but here is the function:
BOOL func_531(int iParam0, BOOL bParam1, Player plParam2, int iParam3, BOOL bParam4) // Position - 0x23A3F Signature - 22 05 24
{
var unk;
var unk13;
var unk26;
unk.f_1 = 10;
unk13.f_1 = 11;
return func_1940(iParam0, &unk26, &unk13, &unk, bParam1, plParam2, iParam3, bParam4);
}
And for award hashes: 315612159 (250 cash) -1306394522 (1 gold)
UnkByteData_program RDR2.exe+0x59B29E0
UnkByteData_script_vm RDR2.exe+0x59B2940
get_script_program(int8_t*,Hash) RDR2.exe+0x2AFF0B8
void script_function_call(const Hash scriptHash, uint32_t ip, std::initializer_list<uint64_t> args)
{
auto thread = rdr_util::FindScriptThread(scriptHash);
auto program = get_script_program(UnkByteData_program, scriptHash);
if (thread && program)
{
auto tls_ctx = rage::tlsContext::Get();
auto stack = (uint64_t*)thread->m_Stack;
auto og_thread = *Pointers.CurrentScriptThread;
auto og_running_in_scrthread = rage::tlsContext::Get()->m_RunningScript;
*Pointers.CurrentScriptThread = thread;
rage::tlsContext::Get()->m_RunningScript = true;
rage::scrThreadContext ctx = thread->m_Context;
for (auto& arg : args)
stack[ctx.m_StackPointer++] = arg;
stack[ctx.m_StackPointer++] = 0;
ctx.m_ProgramCounter = ip;
ctx.m_State = rage::eThreadState::idle;
*Pointers.ScriptVM(stack, *Pointers.ScriptGlobals, UnkByteData_script_vm, program, &ctx);
rage::tlsContext::Get()->m_RunningScript = og_running_in_scrthread;
*Pointers.CurrentScriptThread = og_thread;
}
}
Added CHEAT_XP example
script_function_call(rage::joaat("net_main_offline"),0x23A3F,{0xED1FAB28, false, 0, 0, false});
Maybe there will be a lot of skid menus added soon lol
Nice work!
@AAA-ALR From what I can tell from your code, you're basically hijacking a (random?) script, forcing its Instruction Pointer to the function you want to call? I'm assuming FindScriptThread finds a non-running script thread? Why can't you simply just allocate a new script for the thread runner and use it? There's always a chance if you use something like freemode (IDK what RDR2 calls it), that some script will do GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH and have it return non-zero, and it thinks that the script is running, when in actuality it's just us doing script schenanigns.
tl;dr: Is there a more efficient way to create a script in the thread stack?
I don't know much about the game scripts,But this net_main_offline is like a freemod of GTA
After a little research I've discovered there are award hashes located in:
update_4.rpf/x64/data/itemdatabase/catalog_awards_mp.rpf/catalog_awards_mp.ymt
This file contains award multipliers, too. However there is another file called 'AwardsDatabase_****' which is downloaded from the servers when you join RDO. I'm pretty sure this file contains latest gold, xp, cash multipliers for missions. It also contains all the outlaw pass unlocks, but they're server only. I'm not good at RE, so I don't know if it's possible to trigger those transactions.
@AAA-ALR nice work, but I don't think we need the script thread for this function. We can just create our own thread and stack call the ScriptVM function then delete them.
UnkByteData_program RDR2.exe+0x59B29E0 UnkByteData_script_vm RDR2.exe+0x59B2940 get_script_program(int8_t*,Hash) RDR2.exe+0x2AFF0B8 void script_function_call(const Hash scriptHash, uint32_t ip, std::initializer_list<uint64_t> args) { auto thread = rdr_util::FindScriptThread(scriptHash); auto program = get_script_program(UnkByteData_program, scriptHash); if (thread && program) { auto tls_ctx = rage::tlsContext::Get(); auto stack = (uint64_t*)thread->m_Stack; auto og_thread = *Pointers.CurrentScriptThread; auto og_running_in_scrthread = rage::tlsContext::Get()->m_RunningScript; *Pointers.CurrentScriptThread = thread; rage::tlsContext::Get()->m_RunningScript = true; rage::scrThreadContext ctx = thread->m_Context; for (auto& arg : args) stack[ctx.m_StackPointer++] = arg; stack[ctx.m_StackPointer++] = 0; ctx.m_ProgramCounter = ip; ctx.m_State = rage::eThreadState::idle; *Pointers.ScriptVM(stack, *Pointers.ScriptGlobals, UnkByteData_script_vm, program, &ctx); rage::tlsContext::Get()->m_RunningScript = og_running_in_scrthread; *Pointers.CurrentScriptThread = og_thread; } }
Added CHEAT_XP example
script_function_call(rage::joaat("net_main_offline"),0x23A3F,{0xED1FAB28, false, 0, 0, false});
Maybe there will be a lot of skid menus added soon lol
UnkByteData_script_vm seems to indicate if globals are enabled or not. Incredible work on this though!
@Rxann If you haven't started working on this. I wrote a function wrapper using YimMenu and @AAA-ALR's reply. I can create a PR.
@Rxann If you haven't started working on this. I wrote a function wrapper using YimMenu and @AAA-ALR's reply. I can create a PR.
@maybegreat48 has already made an implementation that will be included into the menu soon. Thank you for asking before creating a PR though.
@maybegreat48 has already made an implementation that will be included into the menu soon. Thank you for asking before creating a PR though.
To add some context, our development workflow now involves a private development repository to prevent certain paid menu grifters (especially a menu named "Fortitude") from stealing our source before it makes it to HorseMenu
@maybegreat48 I understand. May I ask if you're just implementing the function wrapper or are you doing more research on this give award thing? Thanks for your efforts btw.
I've reversed the file containing the award hashes, but many of them don't seem to work as intended, likely due to the lack of proper YMT parsing support for RDR2
Here is an award item from that file:
`
<maxclaims value="-1"/>
<ignoresmodifiers value="false"/>
<debugonly value="false"/>
<serveronly value="false"/>
<awarditems>
<experience value="0"/>
<items>
<Item>
<key>currency_cash</key>
<path>0x96F2DE61</path>
<qty value="25000"/>
</Item>
</items>
<unlocks/>
</awarditems>
` And from what I tried I found out that debugonly and serveronly awards can't be given using that script function. Can you please give more context about what made you think that they don't work as intended?
Here is an award item from that file:
<Item key="0x12CFDBFF"> <key>0x12CFDBFF</key> <maxclaims value="-1"/> <ignoresmodifiers value="false"/> <debugonly value="false"/> <serveronly value="false"/> <awarditems> <experience value="0"/> <items> <Item> <key>currency_cash</key> <path>0x96F2DE61</path> <qty value="25000"/> </Item> </items> <unlocks/> </awarditems> </Item>
And from what I tried I found out that debugonly and serveronly awards can't be given using that script function. Can you please give more context about what made you think that they don't work as intended?
NETWORK::NETWORK_AWARD_HAS_REACHED_MAXCLAIM
I guess
Can you please give more context about what made you think that they don't work as intended?
Anything that's supposed to give you gold doesn't actually give you gold This is how the file looks for me
<Item type="ItemDatabaseAward" key="hash_12CFDBFF">
<key>hash_12CFDBFF</key>
<maxclaims value="-1" />
<ignoresmodifiers value="false" />
<debugonly value="false" />
<serveronly value="false" />
<awarditems>
<experience value="0" />
<items itemType="ItemDatabaseAwardItem">
<Item>
<key>hash_00000001</key>
<path />
<qty value="0" />
</Item>
</items>
<unlocks itemType="ItemDatabaseAwardUnlock" />
</awarditems>
</Item>
Problem
No response
Solution
Writing a script function wrapper as in YimMenu
Reason
It's possible to add gold, cash, xp, loot tables, and collectibles instantly with script functions.
Additional context
No response