#pragma once
#include "controller.h"

typedef int (*fnCUser_CheckMoveTown)(void *CUser, unsigned int a2);
typedef int (*fnWongWork_CDungeonClear_getClearedDungeonDiff)(void *thisC, short a2);
typedef signed int (*fnCUser_use_stackable)(void *CUser, short a2, void *a3, int a4, int a5);
typedef int (*fnWongWork_CItemUpgrade_Separate__DoProcUpgrade)(void *thisC, void *CUser, void *a3, void *a4);
typedef int (*fnCUserCharacInfo_incCurCharacUsedFatigue)(void *thisC, unsigned short a2);
typedef int (*fnDisPatcher_BuyItem_get_data)(void *a1, void *a2, int a3, void *a4);
typedef bool (*fnDispatcher_BuyCeraShopItem_useCountDownCoinInFreeCoinDungeon)(int a1, void *CUser, int a3);
typedef int (*fnCParty_get_item)(void *thisC, void *CUser, int a4, bool a5, char a6, int *a7, unsigned char *a8, bool *a9);
typedef int (*fnCInventory_insertItemIntoInventory)(void **a1, __int64 a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, char a16, int a17, unsigned char a18, unsigned char a19);
typedef int (*fnCParty__onGetItem)(void *thisC, void *a2, unsigned int a3, int a4);
typedef int (*fnCUser_get_unique_id)(void *thisC);
typedef int (*fnCHackLog_OverDamage_GetDungeonLimitDamageAndHackType)(void *a1, _DWORD *a2, _DWORD *a3);
typedef int (*fnCDungeon_get_index)(void *CDungeon);
typedef int (*fnCUserCharacInfo_get_charac_level)(void *thisC);
typedef int (*fnCParty_getMonsterTotalExp)(void *thisC, unsigned int a2, char a3, int a4, float a5, float a6, bool a7);
typedef char *(*fnCParty_set_clear_reward_exp_parameter)(long double ExpAffectRate, void *thisC, void *a3, int a4, void *a5);
typedef int (*fnBingoEvent_sendOneMatchLineReward)(void *thisC, void *a2);
typedef int (*fnBingoEvent_sendMaxMatchLineReward)(void *thisC, void *a2);
typedef int (*fnCBattle_Field_add_monsters_current_map)(void *a1, int a2, int a3, void *a4, _DWORD *a5, int *a6, _DWORD *a7);
typedef int (*fnCDungeon_get_standard_level)(void *thisC);
typedef int (*fnCUser_isHumanCertified)(void *CUser);
typedef void (*fnDispatcher_ChangeAnotherSkillTree_send)(void *thisC, void *a2, void *a3);
typedef void (*fnCUser_AddDailyItem)(void *thisC);
typedef int (*fnGameWorld_leave_game_world)(int a1, void *thisC, void *a3);
typedef int (*fnCGameManager_user_exit)(int a1, void *mutex, void **a3);
typedef void (*fnGameWorld_send_chat_msg)(void *a1, void *a2, char a3, unsigned short a4, int a5, char *dest, size_t n, void *src, size_t a9, int a10);
typedef int (*fnGameWorld_IsForbiddenChat)(void *thisC, char *s);
typedef void (*fnCUser_quest_action)(void **thisC, int a2, void *a3, int a4, int a5);
typedef int (*fnCParty_get_dungeon_clear_state)(void *thisC);
typedef int (*fnCParty_SetPlayResult)(void *thisC, void *a2);
typedef int (*fnBestClearTime_getBestClearTime)(void *thisC, char a2, int a3);

SUBHOOK_INIT(CUser_CheckMoveTown, 0x8678526);
SUBHOOK_INIT(WongWork_CDungeonClear_getClearedDungeonDiff, 0x85BF96C);
SUBHOOK_INIT(CUser_use_stackable, 0x865E0AE);
SUBHOOK_INIT(WongWork_CItemUpgrade_Separate__DoProcUpgrade, 0x811E468);
SUBHOOK_INIT(CUserCharacInfo_incCurCharacUsedFatigue, 0x8696422);
SUBHOOK_INIT(DisPatcher_BuyItem_get_data, 0x81BE658);
SUBHOOK_INIT(Dispatcher_BuyCeraShopItem_useCountDownCoinInFreeCoinDungeon, 0x81FE4B8);
SUBHOOK_INIT(CParty_get_item, 0x85A3B98);
SUBHOOK_INIT(CInventory_insertItemIntoInventory, 0x8502D86);
SUBHOOK_INIT(CParty__onGetItem, 0x85B949C);
SUBHOOK_INIT(CUser_get_unique_id, 0x80DA37C);
SUBHOOK_INIT(CHackLog_OverDamage_GetDungeonLimitDamageAndHackType, 0x8286790);
SUBHOOK_INIT(CDungeon_get_index, 0x80FDCF0);
SUBHOOK_INIT(CUserCharacInfo_get_charac_level, 0x80DA2B8);
SUBHOOK_INIT(CParty_getMonsterTotalExp, 0x85A23DC);
SUBHOOK_INIT(CParty_set_clear_reward_exp_parameter, 0x85ADB00);
SUBHOOK_INIT(BingoEvent_sendOneMatchLineReward, 0x80CA3D4);
SUBHOOK_INIT(BingoEvent_sendMaxMatchLineReward, 0x80CA622);
SUBHOOK_INIT(CBattle_Field_add_monsters_current_map, 0x830162E);
SUBHOOK_INIT(CDungeon_get_standard_level, 0x80F9810);
SUBHOOK_INIT(CUser_isHumanCertified, 0x823021A);
SUBHOOK_INIT(Dispatcher_ChangeAnotherSkillTree_send, 0x81D2134);
SUBHOOK_INIT(CUser_AddDailyItem, 0x8656CAA);
SUBHOOK_INIT(GameWorld_leave_game_world, 0x86C5288);
SUBHOOK_INIT(CGameManager_user_exit, 0x82985A8);
SUBHOOK_INIT(GameWorld_send_chat_msg, 0x86C975E);
SUBHOOK_INIT(GameWorld_IsForbiddenChat, 0x86CD908);
SUBHOOK_INIT(CUser_quest_action, 0x866DA8A);
SUBHOOK_INIT(CParty_get_dungeon_clear_state, 0x822D89C);
SUBHOOK_INIT(CParty_SetPlayResult, 0x85B2412);
SUBHOOK_INIT(BestClearTime_getBestClearTime, 0x80C8AC0);

int _CUser_CheckMoveTown(void *CUser, unsigned int a2)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    // 执行虚拟机 Main 函数
    SQInteger Ret = -99;
    SQInteger top = sq_gettop(v); // saves the stack size before the call
    sq_pushroottable(v);          // pushes the global table
    sq_pushstring(v, _SC("Cb_CUser_CheckMoveTown"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {                        // gets the fie123oo' from the global table
        sq_pushroottable(v); // push the 'this' (in this case is the global table)
        sq_pushuserpointer(v, CUser);
        sq_pushinteger(v, a2);
        sq_call(v, 3, SQTrue, SQTrue); // calls the function
        sq_getinteger(v, -1, &Ret);
    }
    sq_settop(v, top); // restores the original stack size
    if (Ret == -99)
        return CUser_CheckMoveTown(CUser, a2);
    else
        return Ret;
}

int _WongWork_CDungeonClear_getClearedDungeonDiff(void *thisC, short a2)
{
    int OldRet = WongWork_CDungeonClear_getClearedDungeonDiff(thisC, a2);
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    SQInteger Ret = -99;
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_WongWork_CDungeonClear_getClearedDungeonDiff"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushinteger(v, a2);
        sq_pushinteger(v, OldRet);
        sq_call(v, 4, SQTrue, SQTrue);
        sq_getinteger(v, -1, &Ret);
    }
    sq_settop(v, top);

    if (Ret == -99)
        return OldRet;
    else
        return Ret;
}

signed int _CUser_use_stackable(void *CUser, short a2, void *a3, int a4, int a5)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CUser_use_stackable"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, CUser);
        sq_pushinteger(v, a2);
        sq_pushuserpointer(v, a3);
        sq_pushinteger(v, a4);
        sq_pushinteger(v, a5);
        sq_call(v, 6, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CUser_use_stackable(CUser, a2, a3, a4, a5);
}

int _WongWork_CItemUpgrade_Separate__DoProcUpgrade(void *thisC, void *CUser, void *a3, void *a4)
{
    int OldRet = WongWork_CItemUpgrade_Separate__DoProcUpgrade(thisC, CUser, a3, a4);
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger Ret = -99;
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_WongWork_CItemUpgrade_Separate__DoProcUpgrade"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushuserpointer(v, CUser);
        sq_pushinteger(v, OldRet);
        sq_pushuserpointer(v, a3);
        sq_pushuserpointer(v, a4);
        sq_call(v, 6, SQTrue, SQTrue);
        sq_getinteger(v, -1, &Ret);
    }
    sq_settop(v, top);

    if (Ret == -99)
        return OldRet;
    else
        return Ret;
}

int _CUserCharacInfo_incCurCharacUsedFatigue(void *thisC, unsigned short a2)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CUserCharacInfo_incCurCharacUsedFatigue"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushinteger(v, a2);
        sq_call(v, 3, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CUserCharacInfo_incCurCharacUsedFatigue(thisC, a2);
}

int _DisPatcher_BuyItem_get_data(void *a1, void *a2, int a3, void *a4)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_DisPatcher_BuyItem_get_data"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, a1);
        sq_pushuserpointer(v, a2);
        sq_pushinteger(v, a3);
        sq_pushuserpointer(v, a4);
        sq_call(v, 5, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return DisPatcher_BuyItem_get_data(a1, a2, a3, a4);
}

bool _Dispatcher_BuyCeraShopItem_useCountDownCoinInFreeCoinDungeon(int a1, void *CUser, int a3)
{
    int OldRet = Dispatcher_BuyCeraShopItem_useCountDownCoinInFreeCoinDungeon(a1, CUser, a3);
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger Ret = -99;
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_Dispatcher_BuyCeraShopItem_useCountDownCoinInFreeCoinDungeon"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushinteger(v, a1);
        sq_pushuserpointer(v, CUser);
        sq_pushinteger(v, a3);
        sq_pushinteger(v, OldRet);
        sq_call(v, 5, SQTrue, SQTrue);
        sq_getinteger(v, -1, &Ret);
    }
    sq_settop(v, top);

    if (Ret == -99)
        return OldRet;
    else
        return Ret;
}

int _CParty_get_item(void *thisC, void *CUser, int a4, bool a5, char a6, int *a7, unsigned char *a8, bool *a9)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CParty_get_item"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushuserpointer(v, CUser);
        sq_pushinteger(v, a4);
        sq_pushbool(v, a5);
        sq_pushinteger(v, a6);
        sq_pushuserpointer(v, a7);
        sq_pushuserpointer(v, a8);
        sq_pushuserpointer(v, a9);
        sq_call(v, 9, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CParty_get_item(thisC, CUser, a4, a5, a6, a7, a8, a9);
}

int _CInventory_insertItemIntoInventory(void **a1, __int64 a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, char a16, int a17, unsigned char a18, unsigned char a19)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CInventory_insertItemIntoInventory"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, a1);
        sq_pushinteger(v, a2);
        sq_pushinteger(v, a3);
        sq_pushinteger(v, a4);
        sq_pushinteger(v, a5);
        sq_pushinteger(v, a6);
        sq_pushinteger(v, a7);
        sq_pushinteger(v, a8);
        sq_pushinteger(v, a9);
        sq_pushinteger(v, a10);
        sq_pushinteger(v, a11);
        sq_pushinteger(v, a12);
        sq_pushinteger(v, a13);
        sq_pushinteger(v, a14);
        sq_pushinteger(v, a15);
        sq_pushinteger(v, a16);
        sq_pushinteger(v, a17);
        sq_pushinteger(v, a18);
        sq_pushinteger(v, a19);
        sq_call(v, 20, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CInventory_insertItemIntoInventory(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19);
}

int _CParty__onGetItem(void *thisC, void *a2, unsigned int a3, int a4)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CParty__onGetItem"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushuserpointer(v, a2);
        sq_pushinteger(v, a3);
        sq_pushinteger(v, a4);
        sq_call(v, 5, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CParty__onGetItem(thisC, a2, a3, a4);
}

int _CUser_get_unique_id(void *thisC)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CUser_get_unique_id"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_call(v, 2, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CUser_get_unique_id(thisC);
}

int _CHackLog_OverDamage_GetDungeonLimitDamageAndHackType(void *a1, _DWORD *a2, _DWORD *a3)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CHackLog_OverDamage_GetDungeonLimitDamageAndHackType"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, a1);
        sq_pushuserpointer(v, a2);
        sq_pushuserpointer(v, a3);
        sq_call(v, 4, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CHackLog_OverDamage_GetDungeonLimitDamageAndHackType(a1, a2, a3);
}

int _CDungeon_get_index(void *CDungeon)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CDungeon_get_index"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, CDungeon);
        sq_call(v, 2, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CDungeon_get_index(CDungeon);
}

int _CUserCharacInfo_get_charac_level(void *thisC)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CUserCharacInfo_get_charac_level"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_call(v, 2, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CUserCharacInfo_get_charac_level(thisC);
}

int _CParty_getMonsterTotalExp(void *thisC, unsigned int a2, char a3, int a4, float a5, float a6, bool a7)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CParty_getMonsterTotalExp"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushinteger(v, a2);
        sq_pushinteger(v, a3);
        sq_pushinteger(v, a4);
        sq_pushfloat(v, a5);
        sq_pushfloat(v, a6);
        sq_pushbool(v, a7);
        sq_call(v, 8, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CParty_getMonsterTotalExp(thisC, a2, a3, a4, a5, a6, a7);
}

char *_CParty_set_clear_reward_exp_parameter(long double ExpAffectRate, void *thisC, void *a3, int a4, void *a5)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CParty_set_clear_reward_exp_parameter"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushinteger(v, ExpAffectRate);
        sq_pushuserpointer(v, thisC);
        sq_pushuserpointer(v, a3);
        sq_pushinteger(v, a4);
        sq_pushuserpointer(v, a5);
        sq_call(v, 6, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CParty_set_clear_reward_exp_parameter(ExpAffectRate, thisC, a3, a4, a5);
}

int _BingoEvent_sendOneMatchLineReward(void *thisC, void *a2)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_BingoEvent_sendOneMatchLineReward"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushuserpointer(v, a2);
        sq_call(v, 3, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return BingoEvent_sendOneMatchLineReward(thisC, a2);
}

int _BingoEvent_sendMaxMatchLineReward(void *thisC, void *a2)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_BingoEvent_sendMaxMatchLineReward"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushuserpointer(v, a2);
        sq_call(v, 3, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return BingoEvent_sendMaxMatchLineReward(thisC, a2);
}

int _CBattle_Field_add_monsters_current_map(void *a1, int a2, int a3, void *a4, _DWORD *a5, int *a6, _DWORD *a7)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CBattle_Field_add_monsters_current_map"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, a1);
        sq_pushinteger(v, a2);
        sq_pushinteger(v, a3);
        sq_pushuserpointer(v, a4);
        sq_pushuserpointer(v, a5);
        sq_pushuserpointer(v, a6);
        sq_pushuserpointer(v, a7);
        sq_call(v, 8, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CBattle_Field_add_monsters_current_map(a1, a2, a3, a4, a5, a6, a7);
}

int _CDungeon_get_standard_level(void *thisC)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CDungeon_get_standard_level"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_call(v, 2, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CDungeon_get_standard_level(thisC);
}

int _CUser_isHumanCertified(void *CUser)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CUser_isHumanCertified"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, CUser);
        sq_call(v, 2, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CUser_isHumanCertified(CUser);
}

void _Dispatcher_ChangeAnotherSkillTree_send(void *thisC, void *a2, void *a3)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_Dispatcher_ChangeAnotherSkillTree_send"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushuserpointer(v, a2);
        sq_pushuserpointer(v, a3);
        sq_call(v, 4, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    Dispatcher_ChangeAnotherSkillTree_send(thisC, a2, a3);
    return;
}

void _CUser_AddDailyItem(void *thisC)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CUser_AddDailyItem"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_call(v, 2, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    CUser_AddDailyItem(thisC);
    return;
}

int _GameWorld_leave_game_world(int a1, void *thisC, void *a3)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_GameWorld_leave_game_world"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushinteger(v, a1);
        sq_pushuserpointer(v, thisC);
        sq_pushuserpointer(v, a3);
        sq_call(v, 4, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return GameWorld_leave_game_world(a1, thisC, a3);
}

int _CGameManager_user_exit(int a1, void *mutex, void **a3)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CGameManager_user_exit"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushinteger(v, a1);
        sq_pushuserpointer(v, mutex);
        sq_pushuserpointer(v, a3);
        sq_call(v, 4, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CGameManager_user_exit(a1, mutex, a3);
}

void _GameWorld_send_chat_msg(void *a1, void *a2, char a3, unsigned __int16 a4, int a5, char *dest, size_t n, void *src, size_t a9, int a10)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_GameWorld_send_chat_msg"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, a1);
        sq_pushuserpointer(v, a2);
        sq_pushinteger(v, a3);
        sq_pushinteger(v, a4);
        sq_pushinteger(v, a5);
        sq_pushuserpointer(v, dest);
        sq_pushinteger(v, n);
        sq_pushuserpointer(v, src);
        sq_pushinteger(v, a9);
        sq_pushinteger(v, a10);
        sq_call(v, 11, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    GameWorld_send_chat_msg(a1, a2, a3, a4, a5, dest, n, src, a9, a10);
    return;
}

int _GameWorld_IsForbiddenChat(void *thisC, char *s)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_GameWorld_IsForbiddenChat"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushstring(v, s, -1);
        sq_call(v, 3, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return GameWorld_IsForbiddenChat(thisC, s);
}

void _CUser_quest_action(void **thisC, int a2, void *a3, int a4, int a5)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CUser_quest_action"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushinteger(v, a2);
        sq_pushuserpointer(v, a3);
        sq_pushinteger(v, a4);
        sq_pushinteger(v, a5);
        sq_call(v, 6, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    CUser_quest_action(thisC, a2, a3, a4, a5);
    return;
}

int _CParty_get_dungeon_clear_state(void *thisC)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CParty_get_dungeon_clear_state"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_call(v, 2, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CParty_get_dungeon_clear_state(thisC);
}

int _CParty_SetPlayResult(void *thisC, void *a2)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_CParty_SetPlayResult"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushuserpointer(v, a2);
        sq_call(v, 3, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return CParty_SetPlayResult(thisC, a2);
}

int _BestClearTime_getBestClearTime(void *thisC, char a2, int a3)
{
    std::lock_guard<std::recursive_mutex> lock(SqMtx);
    SQInteger top = sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v, _SC("Cb_BestClearTime_getBestClearTime"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {
        sq_pushroottable(v);
        sq_pushuserpointer(v, thisC);
        sq_pushinteger(v, a2);
        sq_pushinteger(v, a3);
        sq_call(v, 4, SQFalse, SQTrue);
    }
    sq_settop(v, top);
    return BestClearTime_getBestClearTime(thisC, a2, a3);
}

void OpenHook1()
{
    SUBHOOK_SETUP(CUser_CheckMoveTown);
    SUBHOOK_SETUP(WongWork_CDungeonClear_getClearedDungeonDiff);
    SUBHOOK_SETUP(CUser_use_stackable);
    SUBHOOK_SETUP(WongWork_CItemUpgrade_Separate__DoProcUpgrade);
    SUBHOOK_SETUP(CUserCharacInfo_incCurCharacUsedFatigue);
    SUBHOOK_SETUP(DisPatcher_BuyItem_get_data);
    SUBHOOK_SETUP(Dispatcher_BuyCeraShopItem_useCountDownCoinInFreeCoinDungeon);
    SUBHOOK_SETUP(CParty_get_item);
    SUBHOOK_SETUP(CInventory_insertItemIntoInventory);
    SUBHOOK_SETUP(CParty__onGetItem);
    // SUBHOOK_SETUP(CUser_get_unique_id);
    SUBHOOK_SETUP(CHackLog_OverDamage_GetDungeonLimitDamageAndHackType);
    SUBHOOK_SETUP(CDungeon_get_index);
    SUBHOOK_SETUP(CUserCharacInfo_get_charac_level);
    SUBHOOK_SETUP(CParty_getMonsterTotalExp);
    SUBHOOK_SETUP(CParty_set_clear_reward_exp_parameter);
    SUBHOOK_SETUP(BingoEvent_sendOneMatchLineReward);
    SUBHOOK_SETUP(BingoEvent_sendMaxMatchLineReward);
    SUBHOOK_SETUP(CBattle_Field_add_monsters_current_map);
    SUBHOOK_SETUP(CDungeon_get_standard_level);
    SUBHOOK_SETUP(CUser_isHumanCertified);
    SUBHOOK_SETUP(Dispatcher_ChangeAnotherSkillTree_send);
    SUBHOOK_SETUP(CUser_AddDailyItem);
    SUBHOOK_SETUP(GameWorld_leave_game_world);
    SUBHOOK_SETUP(CGameManager_user_exit);
    SUBHOOK_SETUP(GameWorld_send_chat_msg);
    SUBHOOK_SETUP(GameWorld_IsForbiddenChat);
    SUBHOOK_SETUP(CUser_quest_action);
    SUBHOOK_SETUP(CParty_get_dungeon_clear_state);
    SUBHOOK_SETUP(CParty_SetPlayResult);
    SUBHOOK_SETUP(BestClearTime_getBestClearTime);
}