163 lines
4.7 KiB
C++
163 lines
4.7 KiB
C++
#pragma once
|
|
#include "squirrel.h"
|
|
#include "sqstdaux.h"
|
|
#include "sqstdblob.h"
|
|
#include "sqstdio.h"
|
|
#include "sqstdmath.h"
|
|
#include "sqstdstring.h"
|
|
#include "sqstdsystem.h"
|
|
#include <iostream>
|
|
#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"));
|
|
} |