找回密码
 register

QQ登录

只需一步,快速开始

查看: 1587|回复: 0

[系统函数] GetMonsterDataID 怪物的索引ID

[复制链接]

[系统函数] GetMonsterDataID 怪物的索引ID

[复制链接]
  • 打卡等级:热心大叔
  • 打卡总天数:94
  • 打卡月天数:17
  • 打卡总奖励:94
  • 最近打卡:2025-01-18 01:28:20
Waylee

主题

0

回帖

1万

积分

仙帝

积分
11929
Waylee 2020-8-8 21:25 | 显示全部楼层 |阅读模式

马上注册,查看网站隐藏内容!!

您需要 登录 才可以下载或查看,没有账号?register

×

***付费内容***
IDA伪代码(地址:82E76EC)

int __cdecl LuaFnTbl::LuaFnGetMonsterDataID(lua_State_0 *L)
{
    int i;                // 循环索引,用于参数检查
    long double v2;       // 用于存储Lua参数(场景中的对象ID)
    SceneManager *const v3; // 临时变量(存放在寄存器中), 这里由于反编译导致类型诡异,用于后续传参
    Scene *Scene;         // 指向当前场景的指针
    Obj *v5;              // 指向场景中的对象(可能是怪物、NPC或玩家对象)的指针
    int v7;               // 临时变量,用于存储怪物的数据ID
    unsigned int selfId;  // 存储Lua传入的怪物ID(场景中的对象ID)
    char v9;              // 临时变量(无特别意义,反编译可能产生的占位)
    CHAR msg[1048];       // 存放错误消息的缓冲区

    // 对Lua传入的前两个参数进行检查
    // 从函数逻辑推测,第一个参数应该是SceneID或类似标识,第二个参数是selfId(对象ID)
    // 函数期望两个参数都是number类型,如果不是,则记录错误日志。

    for (i = 1; i <= 2; ++i)
    {
        if (L) // 确保Lua状态不为空
        {
            // lua_isnumber(L, i) == 1 表示第i个参数是数字类型,否则记录错误日志
            if (lua_isnumber(L, i) == 1)
                continue;
            sub_804AC20(msg, 512, "ERROR: [%s]Param %d is illegal!", "LuaFnGetMonsterDataID", i);
        }
        else
        {
            // 如果L为NULL,表示Lua状态无效,记录错误信息
            sub_804AC20(msg, 512, "ERROR: [%s] Lua_State==NULL!", "LuaFnGetMonsterDataID");
        }
        // 记录错误日志
        CacheLog(3, msg);
    }

    // 提取Lua参数
    // 第一个参数(可能是场景ID):由于此处仅调用了 lua_tonumber(L, 1),但没有赋值给变量,说明实际逻辑可能只用第二个参数
    lua_tonumber(L, 1);

    // 获取第二个参数(对象ID)
    v2 = lua_tonumber(L, 2);
    // LOBYTE(v3) = v9; BYTE1(v3) = 12; 是反编译器的错误解析,实际场景ID通过SceneID全局变量获取
    // selfId最终保存第二个参数的值(对象ID)
    selfId = (int)v2;

    // 获取场景指针
    // 这里的调用: Scene = SceneManager::GetScene(v3, SceneID);
    // v3和SceneID都是全局或静态变量/参数,SceneID应该为全局变量或静态上下文参数
    Scene = SceneManager::GetScene(v3, SceneID);
    if (!Scene)
        __assertex__(
            "./Script/LuaFnTbl_Team.h",
            0x502u,
            "int LuaFnTbl::LuaFnGetMonsterDataID(lua_State*)",
            "pScene",
            "Scene ID ErrorLuaFnGetMonsterDataID");

    // 确认当前线程ID与场景绑定线程ID一致,保证线程安全
    if (ThreadValueManager::GetCurrentThreadID() != Scene->m_ThreadID)
        __assertex__(
            "./Script/LuaFnTbl_Team.h",
            0x502u,
            "int LuaFnTbl::LuaFnGetMonsterDataID(lua_State*)",
            "ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadID",
            "ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadIDLuaFnGetMonsterDataID");

    // 检查对象ID(selfId)是否在合法范围内,0x752F(29999)可能是场景中对象ID的上限
    // 同时检查该ID对应的对象指针是否存在
    if (selfId > 0x752F || (v5 = Scene->m_pObjManager->m_pObj[selfId]) == 0)
        __assertex__(
            "./Script/LuaFnTbl_Team.h",
            0x502u,
            "int LuaFnTbl::LuaFnGetMonsterDataID(lua_State*)",
            "pObj",
            "selfId Error LuaFnGetMonsterDataID");

    // (*((int (__cdecl **)(Obj *))v5->_vptr_Obj + 2))(v5) == 2
    // 这段看似是虚函数调用,检查对象类型(例如:2 表示怪物类型)
    // 如果返回值为2,表示该对象是怪物
    if (((int (__cdecl *)(Obj *))v5->_vptr_Obj[2])(v5) == 2)
    {
        // 调用对象的第115个虚函数(v5->_vptr_Obj + 115)获取MonsterDataID
        v7 = ((int (__cdecl *)(Obj *))v5->_vptr_Obj[115])(v5);

        // 将获得的MonsterDataID推入Lua栈作为返回值
        lua_pushnumber(L, (double)(unsigned int)v7);
    }
    else
    {
        // 如果不是怪物对象,则返回 -1 表示无效
        lua_pushnumber(L, -1.0);
    }

    return 1; // 返回1个值给Lua
}
付费看帖
剩余 14% 内容需要支付 1.00 金币 后可完整阅读
支持付费阅读,激励作者创作更好的作品。
您需要登录后才可以回帖 登录 | register

本版积分规则

雪舞知识库 | 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 |天天打卡

GMT+8, 2025-1-18 14:36 , Processed in 0.099209 second(s), 7 queries , Redis On.

Powered by XueWu Licensed

Copyright © Tencent Cloud.

快速回复 返回顶部 返回列表