函数名称: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
金币 后可完整阅读
支持付费阅读,激励作者创作更好的作品。
|