#pragma once #include "squirrel.h" #include "sqstdaux.h" #include "sqstdblob.h" #include "sqstdio.h" #include "sqstdmath.h" #include "sqstdstring.h" #include "sqstdsystem.h" #include #include "frida-gum.h" typedef void *(*__GetGameManagerVoid)(); static SQInteger GameManager_GameManager(HSQUIRRELVM v) { void *GameManager = ((__GetGameManagerVoid)0x080CC18E)(); sq_pushuserpointer(v, GameManager); return 1; } typedef void *(*__GameManagerByThis)(void *GameManager); static SQInteger GameManager_GetParty(HSQUIRRELVM v) { SQUserPointer P; sq_getuserpointer(v, 2, &P); void *CParty = ((__GameManagerByThis)0x08294E10)(P); if (CParty) sq_pushuserpointer(v, CParty); else sq_pushinteger(v, 0); return 1; } typedef int (*cdeclCall2P)(int *a1, int a2); static cdeclCall2P SkillSlot__get_skillslot_buf = (cdeclCall2P)0x086067DE; static cdeclCall2P SkillSlot__gcheckComboSkillInsertQuickSlot = (cdeclCall2P)0x08608D58; #define RDWORD(addr, offset) (*(DWORD *)((char *)(addr) + (offset))) int __attribute__((cdecl)) hookCSkill__reform_ui_group_no(int *thisP, int *skillClassP, bool isTpSkill, int a4) { int p = (int)skillClassP; if (RDWORD(skillClassP, -0x60) == 197) { // cout << " fix skill197 class to 4!" << endl; *skillClassP = 4; } return 0; } int __attribute__((cdecl)) hookSkillSlot__get_skillslot_group(int *thisP, int slot) { // DWORD retAddr = (DWORD)gum_invocation_context_get_return_address(NULL); // cout<< retAddr << " get_skillslot_group:" << slot << endl; if (slot < 8 || slot >= 198) return -1; else if (slot >= 160) return 4; else if (slot >= 122) return 3; else if (slot >= 84) return 2; else if (slot >= 46) return 1; else return 0; } int __attribute__((cdecl)) hookSkillSlot__get_skillslot_no(int *thisP, int skillId, int group, int slot, char is_active_skill) { if (!thisP || !*thisP) return -1; BYTE *buf = (BYTE *)SkillSlot__get_skillslot_buf(thisP, slot); if (!buf) return -1; if (is_active_skill && SkillSlot__gcheckComboSkillInsertQuickSlot(thisP, skillId)) { int end = skillId ? 7 : 5; for (int i = 0; i <= end; ++i) { if (buf[2 * i] == skillId) { return i; } } for (int i = 198; i <= 203; ++i) { if (buf[2 * i] == skillId) { return i; } } } int pos = 8 + group * 38; for (int i = 0; i < 38; ++i) { if (buf[2 * (i + pos)] == skillId) { return i + pos; } } return -1; } int __attribute__((cdecl)) hookSkillSlot__get_skillslot_no2(int *thisP, BYTE *buf, int skillId, int group, char is_active_skill) { if (!thisP || !*thisP || !buf) return -1; if (is_active_skill) { int end = skillId ? 7 : 5; for (int i = 0; i <= end; ++i) { if (buf[2 * i] == skillId) { return i; } } for (int i = 198; i <= 203; ++i) { if (buf[2 * i] == skillId) { return i; } } } int pos = 8 + group * 38; for (int i = 0; i < 38; ++i) { if (buf[2 * (i + pos)] == skillId) { return i + pos; } } return -1; } static SQInteger GameManager_FixA4Skill(HSQUIRRELVM vm) { GumInterceptor *v = gum_interceptor_obtain(); gum_interceptor_begin_transaction(v); gum_interceptor_replace_fast(v, (gpointer)0x083507E8, (gpointer)hookCSkill__reform_ui_group_no, NULL); gum_interceptor_replace_fast(v, (gpointer)0x086049FC, (gpointer)hookSkillSlot__get_skillslot_group, NULL); gum_interceptor_replace_fast(v, (gpointer)0x08604A86, (gpointer)hookSkillSlot__get_skillslot_no, NULL); gum_interceptor_replace_fast(v, (gpointer)0x08607DBA, (gpointer)hookSkillSlot__get_skillslot_no2, NULL); gum_interceptor_end_transaction(v); return 0; } static SQInteger register_GameManager_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname) { sq_pushroottable(v); sq_pushstring(v, fname, -1); sq_newclosure(v, f, 0); // create a new function sq_newslot(v, -3, SQFalse); sq_pop(v, 1); // pops the root table } static void RegisterGameManager(HSQUIRRELVM v) { // 获得GameManager对象 register_GameManager_func(v, GameManager_GameManager, _SC("Sq_GameManager_GameManager")); // 获得队伍对象 register_GameManager_func(v, GameManager_GetParty, _SC("Sq_GameManager_GetParty")); // 修复A4技能 register_GameManager_func(v, GameManager_FixA4Skill, _SC("Sq_FixA4Skill")); }