找回密码
 register

QQ登录

只需一步,快速开始

查看: 1874|回复: 0

[系统函数] SetPos 角色的同场景转移

[复制链接]

[系统函数] SetPos 角色的同场景转移

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

主题

0

回帖

1万

积分

仙帝

积分
11929
Waylee 2020-10-21 14:38 | 显示全部楼层 |阅读模式

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

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

×

***付费内容***
IDA伪代码(085)

// 定义 LuaFnTbl 类中的 LuaFnSetPos 函数,使用 __cdecl 调用约定
int __cdecl LuaFnTbl::LuaFnSetPos(lua_State *L)
{
    // 声明局部变量
    int i; // 循环计数器
    unsigned int v2; // 存储对象 ID
    Scene_3 *Scene; // 指向 Scene_3 对象的指针
    Obj_Human *v4; // 指向 Obj_Human 对象的指针
    long double v5; // 临时变量,用于存储 Z 坐标
    Map *m_pMap; // 指向 Map 对象的指针
    long double m_fX; // 临时变量,用于存储 X 坐标
    long double v8; // 临时变量,用于存储 X 坐标的处理结果
    long double m_CX; // 地图的最大 X 坐标
    long double v10; // 处理后的 X 坐标
    long double v11; // 临时变量,用于存储 Z 坐标的处理结果
    long double v12; // 地图的最大 Z 坐标
    long double v13; // 处理后的 Z 坐标
    ORESULT v14; // 操作结果
    Obj_Human *CanLogic; // 检查是否可以进行逻辑处理
    AI_Human *HumanAI; // 指向 AI_Human 对象的指针
    const CHAR *v18; // 指向错误描述的指针
    SceneManager_1 *const v19; // 指向 SceneManager_1 对象的常量指针
    const CHAR *v20; // 指向错误信息的指针
    __int64 m_CZ; // 地图的最大 Z 坐标
    float z; // 目标 Z 坐标
    float x; // 目标 X 坐标
    WORLD_POS New; // 新的世界坐标位置
    char s[1048]; // 用于存储错误日志信息的缓冲区

    // 参数验证:确保传递给 Lua 函数的前四个参数都是数字
    for (i = 1; i <= 4; ++i)
    {
        if (L) // 如果 Lua 状态指针有效
        {
            // 检查第 i 个参数是否为数字
            if (lua_isnumber((lua_State_0 *)L, i) == 1)
                continue; // 如果是数字,继续循环

            // 如果第 i 个参数不是数字,格式化错误信息
            snprintf(s, 0x200u, "ERROR: [%s]Param %d is illegal!", "LuaFnSetPos", i);
        }
        else // 如果 Lua 状态指针为空
        {
            // 格式化错误信息
            snprintf(s, 0x200u, "ERROR: [%s] Lua_State==NULL!", "LuaFnSetPos");
        }

        // 记录错误日志,错误级别为 3
        CacheLog(3, s);
    }

    // 从 Lua 栈中获取参数并转换为相应的类型
    lua_tonumber((lua_State_0 *)L, 1); // 获取第一个参数(场景 ID),但未使用
    v2 = (unsigned int)lua_tonumber((lua_State_0 *)L, 2); // 获取第二个参数,对象 ID
    x = lua_tonumber((lua_State_0 *)L, 3); // 获取第三个参数,目标 X 坐标
    z = lua_tonumber((lua_State_0 *)L, 4); // 获取第四个参数,目标 Z 坐标

    // 获取当前场景对象
    Scene = SceneManager::GetScene(v19, g_pSceneManager);
    if (!Scene) // 如果未找到场景
    {
        v20 = "Scene ID Error LuaFnSetPos"; // 设置错误信息
        v18 = "pScene"; // 设置错误指针
    LABEL_27:
        // 断言失败,输出错误信息并终止程序
        __assertex__("./Script/LuaFnTbl_Attr.h", 0x55u, "int LuaFnTbl::LuaFnSetPos(lua_State*)", v18, v20);
    }

    // 检查当前线程 ID 是否与场景的线程 ID 一致
    if (ThreadValueManager::GetCurrentThreadID() != Scene->m_ThreadID)
        __assertex__(
            "./Script/LuaFnTbl_Attr.h",
            0x55u,
            "int LuaFnTbl::LuaFnSetPos(lua_State*)",
            "ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadID",
            "ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadIDLuaFnSetPos");

    // 检查对象 ID 是否在有效范围内,并获取对应的 Obj_Human 对象
    if (v2 > 0x752F || (v4 = (Obj_Human *)Scene->m_pObjManager->m_pObj[v2]) == 0)
    {
        v20 = "selfId Error LuaFnSetPos"; // 设置错误信息
        v18 = "pObj"; // 设置错误指针
        goto LABEL_27; // 跳转到断言失败处理
    }

    // 调用 Obj_Human 对象的第三个虚函数,检查其状态
    if ( (unsigned int)((*((int (__cdecl **)(Obj_Human *))v4->_vptr_Obj + 2))(v4) - 1) <= 2 )
    {
        // 设置新的 X 坐标
        New.m_fX = x;
        v5 = 0.0; // 初始化 Z 坐标
        m_pMap = Scene->m_pMap; // 获取地图对象
        m_fX = 0.0; // 初始化临时变量

        // 确保 X 坐标非负
        if (x >= 0.0)
            m_fX = New.m_fX;

        // 确保 Z 坐标非负
        if (z >= 0.0)
            v5 = z;

        v8 = m_fX; // 处理后的 X 坐标
        m_CX = (long double)m_pMap->m_CX; // 获取地图的最大 X 坐标

        // 确保 X 坐标不超过地图边界,保留一定余量
        v10 = v8 <= m_CX ? v8 : m_CX - 0.1;

        m_CZ = m_pMap->m_CZ; // 获取地图的最大 Z 坐标
        New.m_fX = v10; // 设置新的 X 坐标

        v11 = v5; // 处理后的 Z 坐标
        v12 = (long double)m_CZ; // 地图的最大 Z 坐标

        // 确保 Z 坐标不超过地图边界,保留一定余量
        v13 = v11 <= v12 ? v11 : v12 - 0.1;
        New.m_fZ = v13; // 设置新的 Z 坐标

        // 检查新的位置是否可以到达
        if (Map::IsCanGo(m_pMap, &New))
        {
            // 再次调用第三个虚函数,获取操作结果
            v14 = (*((int (__cdecl **)(Obj_Human *))v4->_vptr_Obj + 2))(v4) - 1;

            if (v14)
                goto LABEL_23; // 如果操作结果满足条件,跳转到后续处理

            // 检查对象是否可以进行逻辑处理
            CanLogic = (Obj_Human *)Obj_Human::IsCanLogic(v4);
            if (CanLogic)
            {
                // 获取 AI 对象,并推送空闲命令
                HumanAI = Obj_Human::GetHumanAI(CanLogic);
                v14 = AI_Human::PushCommand_Idle(HumanAI);
            LABEL_23:
                // 调用第 14 个虚函数,执行传送操作
                (*((void (__cdecl **)(Obj_Human *, WORLD_POS *, _DWORD, ORESULT))v4->_vptr_Obj + 14))(v4, &New, 0, v14);
            }
        }
    }
    return 0; // 返回 0,表示函数执行完成,但不向 Lua 返回任何值
}
付费看帖
剩余 9% 内容需要支付 1.00 金币 后可完整阅读
支持付费阅读,激励作者创作更好的作品。
您需要登录后才可以回帖 登录 | register

本版积分规则

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

GMT+8, 2025-1-18 16:04 , Processed in 0.100960 second(s), 7 queries , Redis On.

Powered by XueWu Licensed

Copyright © Tencent Cloud.

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