找回密码
 register

QQ登录

只需一步,快速开始

查看: 1830|回复: 0

[系统函数] LuaFnCreateMonster 创建一只怪物 创建怪物 生成怪物

[复制链接]

[系统函数] LuaFnCreateMonster 创建一只怪物 创建怪物 生成怪物

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

主题

0

回帖

1万

积分

仙帝

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

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

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

×

函数名称LuaFnCreateMonster
注册函数LuaFnCreateMonster ***付费内容***
IDA伪代码(地址:4270D9C)

int __cdecl LuaFnTbl::LuaFnCreateMonster(lua_State *L)
{
  int i; // 用于检查参数是否有效的循环计数器
  __int16 v2; // 场景 ID(从 Lua 获取的第一个参数)
  unsigned int v3; // 数据 ID(从 Lua 获取的第二个参数)
  int j; // 用于初始化 Monster 的额外变量
  ObjID_t TempMonster; // 创建的临时怪物对象 ID
  Scene_2 *pScene; // 场景对象,指向当前场景
  ScriptID_t ScriptID; // 脚本 ID(从 Lua 获取的第七个参数)
  int iAIScript; // AI 脚本 ID(从 Lua 获取的第六个参数)
  int iAIType; // AI 类型(从 Lua 获取的第五个参数)
  float z; // 怪物生成的 Z 坐标(从 Lua 获取的第四个参数)
  float x; // 怪物生成的 X 坐标(从 Lua 获取的第三个参数)
  _OBJ_MONSTER_INIT_1 init; // 存储怪物初始化数据的结构体
  CHAR msg[1048]; // 用于存储错误信息的缓冲区

  // 循环检查传入的 7 个参数是否为有效数字
  for (i = 1; i <= 7; ++i)
  {
    // 确保 Lua 状态存在
    if (L)
    {
      // 检查每个参数是否为有效数字
      if (lua_isnumber((lua_State_0 *)L, i) == 1)
        continue; // 如果是有效数字,继续检查下一个参数
      // 如果参数无效,记录错误信息
      sub_804AC20(msg, 512, "ERROR: [%s]Param %d is illegal!", "LuaFnCreateMonster", i);
    }
    else
    {
      // 如果 Lua 状态为 NULL,记录错误信息
      sub_804AC20(msg, 512, "ERROR: [%s] Lua_State==NULL!", "LuaFnCreateMonster");
    }
    CacheLog(3, msg); // 打印错误信息到日志
  }

  // 从 Lua 获取怪物创建所需的参数
  v2 = (__int16)lua_tonumber((lua_State_0 *)L, 1); // 获取场景 ID
  v3 = (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 坐标
  iAIType = (int)lua_tonumber((lua_State_0 *)L, 5); // 获取 AI 类型
  iAIScript = (int)lua_tonumber((lua_State_0 *)L, 6); // 获取 AI 脚本 ID
  ScriptID = (int)lua_tonumber((lua_State_0 *)L, 7); // 获取脚本 ID

  // 获取场景对象,如果场景无效则触发断言错误
  pScene = (Scene_2 *)SceneManager::GetScene((SceneManager_1 *const)v2, SceneID);
  if (!pScene)
  {
    // 如果场景无效,触发断言并输出错误信息
    __assertex__(
      "./Script/LuaFnTbl_Ability.h",
      0xE44u,
      "int LuaFnTbl::LuaFnCreateMonster(lua_State*)",
      "pScene",
      "Scene ID Error LuaFnCreateMonster");
  }

  // 检查当前线程 ID 是否与场景线程 ID 匹配
  if (ThreadValueManager::GetCurrentThreadID() != pScene->m_ThreadID)
  {
    // 如果线程不匹配,触发断言并输出错误信息
    __assertex__(
      "./Script/LuaFnTbl_Ability.h",
      0xE44u,
      "int LuaFnTbl::LuaFnCreateMonster(lua_State*)",
      "ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadID",
      "ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadIDLuaFnCreateMonster");
  }

  // 初始化怪物的默认值
  init.m_Pos.m_fX = 0.0;
  init.m_Pos.m_fZ = 0.0;
  init.m_Dir = 3.1400001; // 默认方向(大约是 π)
  init.m_ScriptTimer = 0; // 初始化脚本定时器
  init.m_GUID = -1; // 初始化 GUID
  init.m_uDataID = -1; // 初始化数据 ID
  init.m_szName[0] = 0; // 初始化名称为空
  init.m_szTitle[0] = 0; // 初始化标题为空
  init.m_RespawnTime = 60000; // 默认重生时间(60秒)
  memset(&init.m_uGroupID, 255, 12); // 初始化组 ID 为 255
  init.m_BaseAI = 0; // 默认 AI 类型
  init.m_ExtAIScript = -1; // 扩展 AI 脚本初始化
  init.m_idScript = -1; // 初始化脚本 ID
  init.m_nPatrolID = -1; // 默认巡逻 ID
  init.m_LeaderID = -1; // 默认领导者 ID
  init.m_nReputationID = -1; // 默认声望 ID
  init.m_bPet = 0; // 默认不是宠物

  // 初始化商店信息
  for (j = 0; j <= 3; ++j)
    init.m_nShop[j] = -1; // 商店 ID 初始化为 -1

  // 更新怪物的坐标、AI 类型和其他信息
  init.m_Dir = 3.1400001; // 设置方向为 π
  init.m_Pos.m_fX = x; // 设置怪物的 X 坐标
  init.m_Pos.m_fZ = z; // 设置怪物的 Z 坐标
  init.m_ScriptTimer = 0; // 重置脚本定时器
  init.m_BaseAI = iAIType; // 设置 AI 类型
  init.m_nCommisionShop = -1; // 初始化委托商店 ID
  init.m_Level = -1; // 默认等级为 -1
  init.m_ExtAIScript = iAIScript; // 设置扩展 AI 脚本 ID
  init.m_uDataID = v3; // 设置数据 ID
  init.m_RespawnTime = -1; // 重生时间设置为 -1
  init.m_idScript = ScriptID; // 设置脚本 ID

  // 创建怪物并返回其临时对象 ID
  TempMonster = Scene::CreateTempMonster(pScene, (const _OBJ_MONSTER_INIT *)&init);

  // 将创建的怪物 ID 推送到 Lua 栈上
  lua_pushnumber((lua_State_0 *)L, (double)TempMonster);

  // 返回 1,表示返回了一个值(怪物 ID)
  return 1;
}

注释说明:

  • 参数检查:前 7 个参数需要是数字类型,函数通过 lua_isnumber 来验证。如果发现参数无效,会记录错误信息并打印日志。
  • 参数获取:从 Lua 栈中获取 7 个参数,分别是场景 ID、数据 ID、怪物的 X 和 Z 坐标、AI 类型、AI 脚本 ID 和脚本 ID。
  • 场景和线程检查:通过 SceneManager::GetScene 获取场景对象,并确保当前线程 ID 与场景的线程 ID 匹配。如果不匹配或场景无效,触发断言。
  • 怪物初始化:初始化怪物对象的多个属性,如位置、方向、AI 类型、脚本 ID 等。许多默认值被设置为合适的初始值。
  • 创建怪物:通过 Scene::CreateTempMonster 创建临时怪物,并返回一个怪物 ID。
  • 返回值:将创建的怪物 ID 推送到 Lua 栈上,并返回 1,表示成功返回一个值(怪物 ID)。
付费看帖
剩余 11% 内容需要支付 5.00 金币 后可完整阅读
支持付费阅读,激励作者创作更好的作品。
您需要登录后才可以回帖 登录 | register

本版积分规则

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

GMT+8, 2025-1-18 16:02 , Processed in 0.106549 second(s), 10 queries , Redis On.

Powered by XueWu Licensed

Copyright © Tencent Cloud.

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