***付费内容***
IDA伪代码(085原版)
// 函数: LuaFnYuanBao
// 描述: Lua绑定函数,用于操作元宝(游戏内货币)
// 参数:
// lua_State *L - 包含函数参数的Lua状态
int __cdecl LuaFnTbl::LuaFnYuanBao(lua_State *L)
{
// 变量声明
int i; // 循环索引,用于参数验证
unsigned int v2; // selfId(玩家ID)
int v3; // targetId(目标玩家ID)
int v4; // optType(操作类型:添加、减少、获取)
SceneManager_1 *const v5; // 场景管理器实例
Scene_3 *Scene; // 当前场景
Obj *v7; // 对应selfId的对象
int v9; // 临时变量,用于元宝数量
int v10; // 临时变量,用于元宝数量
int v11; // 减少后新的元宝数量
int YuanBao; // 当前元宝数量
int v13; // 添加后的新元宝数量
Packet *v14; // 网络通信的包
IODataStream *v15; // 包的数据流
GUID_t v16; // 对象的GUID
bool v17; // 检查数据流操作的标志
int n; // 临时循环变量
INT v19; // 数据流的临时变量
int ii; // 临时循环变量
INT v21; // 数据流的临时变量
int jj; // 临时循环变量
INT v23; // 数据流的临时变量
Packet *Packet; // 网络通信的包
IODataStream *v25; // 包的数据流
GUID_t v26; // 对象的GUID
int j; // 临时循环变量
INT m_CurNum; // 数据流中的当前编号
int k; // 临时循环变量
INT v30; // 数据流的临时变量
int m; // 临时循环变量
INT v32; // 数据流的临时变量
const CHAR *v33; // 错误字段名称
const CHAR *v34; // 错误信息
double v35; // 返回值
GUID_t v36; // 日志记录用的GUID
GUID_t v37; // 日志记录用的GUID
GUID_t GUID; // 日志记录用的GUID
GUID_t v39; // 日志记录用的GUID
GUID_t v40; // 日志记录用的GUID
GUID_t v41; // 日志记录用的GUID
GUID_t v42; // 日志记录用的GUID
GUID_t v43; // 日志记录用的GUID
GUID_t v44; // 日志记录用的GUID
unsigned int v45; // 操作后的元宝数量
unsigned int v46; // 操作后的元宝数量
unsigned int v47; // 操作后的元宝数量
Packets::GWYuanBao *pMsgYuanBao_0; // 元宝操作的包消息(减少)
Packets::GWYuanBao *pMsgYuanBao; // 元宝操作的包消息(添加)
Obj_Human *v50; // 人类对象
unsigned int Param; // 操作的参数(金额)
SceneID_t sceneId; // Lua参数中的场景ID
__int16 v53; // 数据流的临时变量
unsigned int v54; // 数据流的参数值
_DWORD v55[2]; // GUID的临时存储
MONEY_OP_TYPE nOpType; // 操作类型枚举(用于减少)
GUID_t gTargetGuid; // 操作的目标GUID
unsigned int v58; // 数据流的参数值
_DWORD v59[2]; // GUID的临时存储
MONEY_OP_TYPE v60; // 操作类型枚举(用于添加)
GUID_t v61; // 操作的目标GUID
char s[1048]; // 错误信息的缓冲区
// 验证前5个Lua参数是否为数字
for (i = 1; i <= 5; ++i)
{
if (L)
{
if (lua_isnumber((lua_State_0 *)L, i) == 1)
continue; // 如果参数是数字,继续下一个参数
// 如果参数不是数字,准备错误信息
snprintf(s, 0x200u, "ERROR: [%s]Param %d is illegal!", "LuaFnYuanBao", i);
}
else
{
// 如果Lua状态为空,准备错误信息
snprintf(s, 0x200u, "ERROR: [%s] Lua_State==NULL!", "LuaFnYuanBao");
}
// 以级别3记录错误信息
CacheLog(3, s);
}
// 获取Lua参数
sceneId = (__int16)lua_tonumber((lua_State_0 *)L, 1); // 第一个参数:场景ID
v2 = (int)lua_tonumber((lua_State_0 *)L, 2); // 第二个参数:self ID(玩家ID)
v3 = (int)lua_tonumber((lua_State_0 *)L, 3); // 第三个参数:目标ID
v4 = (int)lua_tonumber((lua_State_0 *)L, 4); // 第四个参数:操作类型
Param = (int)lua_tonumber((lua_State_0 *)L, 5); // 第五个参数:参数(金额)
// 记录函数调用开始的信息
CacheLog(1, "LuaFnYuanBao:: begin sceneId=%d selfId=%d targetId=%d opttype=%d Param=%d", sceneId, v2, v3, v4, Param);
// 从场景管理器获取当前场景
Scene = SceneManager::GetScene(v5, g_pSceneManager);
if (!Scene)
{
// 如果场景不存在,准备错误信息并断言
v34 = "Scene ID ErrorLuaFnYuanBao";
v33 = "pScene";
LABEL_16:
__assertex__("./Script/LuaFnTbl_Shop.h", 0x25Fu, "int LuaFnTbl::LuaFnYuanBao(lua_State*)", v33, v34);
}
// 检查当前线程ID是否与场景的线程ID匹配,确保线程安全
if (ThreadValueManager::GetCurrentThreadID() != Scene->m_ThreadID)
__assertex__(
"./Script/LuaFnTbl_Shop.h",
0x25Fu,
"int LuaFnTbl::LuaFnYuanBao(lua_State*)",
"ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadID",
"ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadIDLuaFnYuanBao");
// 验证selfId是否在有效范围内,并获取对应的对象
if (v2 > 0x752F || (v7 = Scene->m_pObjManager->m_pObj[v2], (v50 = (Obj_Human *)v7) == 0))
{
// 如果selfId无效或对象不存在,准备错误信息并断言
v34 = "selfId ErrorLuaFnYuanBao";
v33 = "pObj";
goto LABEL_16;
}
// 检查对象是否为人类类型(可能是通过虚函数表的第二个函数)
if ((*((int (__cdecl **)(Obj *))v7->_vptr_Obj + 2))(v7) != 1)
goto LABEL_12; // 如果不是,跳转到默认情况
// 检查人类对象是否可以进行逻辑操作
if (!Obj_Human::IsCanLogic((Obj_Human *const)v7))
__assertex__(
"./Script/LuaFnTbl_Shop.h",
0x25Fu,
"int LuaFnTbl::LuaFnYuanBao(lua_State*)",
"pHuman->IsCanLogic()",
"IsCanLogic() test return falseLuaFnYuanBao");
// 验证操作类型是否有效:1(添加)、2(减少)、3(获取)
if ((unsigned int)(v4 - 1) > 2)
{
// 如果操作类型无效,记录错误日志
GUID = Obj_Human::GetGUID((const Obj_Human *const)v7);
CacheLog(1, "LuaFnYuanBao::ObjGUID=%X Invalid opttype=%d", GUID, v4);
goto LABEL_25; // 准备返回错误
}
// 根据操作类型执行相应操作
switch (v4)
{
case 1: // 添加元宝
if (Param <= 0xBEBC200) // 检查添加金额是否在允许范围内
{
YuanBao = Obj_Human::GetYuanBao((Obj_Human *const)v7); // 获取当前元宝数量
v13 = Param + YuanBao; // 计算添加后的新元宝数量
if (Param + YuanBao > 0xBEBC200) // 检查新元宝数量是否超过最大限制
{
v47 = Param + YuanBao;
v44 = Obj_Human::GetGUID((const Obj_Human *const)v7);
// 记录超出范围的添加尝试
CacheLog(
1,
"LuaFnYuanBao::ObjGUID=%X OPT_YUANBAO_ADD OUTRANGE(0, yuanbaoamount, MAX_YUANBAO) yuanbaoamount=%d",
v44,
v47);
goto LABEL_25; // 准备返回错误
}
// 检查对象位置数据中的某个标志(可能用于防止重复更新)
if ((BYTE1(v7[1518].m_Pos.m_fZ) & 8) != 0)
{
v40 = Obj_Human::GetGUID((const Obj_Human *const)v7);
// 记录已经在进行更新的日志
CacheLog(1, "LuaFnYuanBao::ObjGUID=%X OPT_YUANBAO_ADD BLT_YUANBAO_OPT yuanbaoamount=%d", v40, v13);
goto LABEL_25; // 准备返回错误
}
// 执行添加操作
Obj_Human::GetYuanBao((Obj_Human *const)v7); // (冗余?可能有副作用)
v61 = -1;
v60 = MONEY_OP_TYPE::YUANBAO_SCRIPT_ADD; // 定义操作类型为添加
Obj_Human::SetYuanBao((Obj_Human *const)v7, v13, &v60, 0, &v61, 0); // 更新元宝数量
LODWORD(v7[1518].m_Pos.m_fZ) |= 0x800u; // 在对象位置数据中设置标志(表示更新)
// 创建一个网络包以通知客户端
Packet = PacketFactoryManager::CreatePacket(g_pPacketFactoryManager, 0x17Eu); // 创建GWYuanBao包
v25 = (IODataStream *)&Packet[1]; // 从包中获取数据流
pMsgYuanBao = (Packets::GWYuanBao *)Packet; // 转换为特定包类型
IODataStream::Begin((IODataStream *const)&Packet[1], IODataStream::OPT_TYPE::OPT_WRITE); // 开始写入数据流
v26 = Obj_Human::GetGUID((const Obj_Human *const)v7); // 获取对象的GUID
v17 = v25->m_Opt == 1; // 检查数据流是否处于写入模式
v59[1] = v26; // 存储GUID
if (!v17)
__assertex__(
"../../Common/DataStream.h",
0x1B0u,
"IODataStream& IODataStream::operator<<(T) [with T = unsigned int]",
"0",
"m_Opt != IODataStream::OPT_WRITE");
// 如果数据流有空间,写入GUID
if (v25->m_CurNum <= 0x13u)
{
for (j = 4; j > 0; --j)
(*((void (__cdecl **)(IODataStream *, _DWORD))v25->_vptr_InputStream + 3))(
v25,
*((unsigned __int8 *)v59 + j + 3));
// 设置数据类型和长度
m_CurNum = v25->m_CurNum;
v25->m_DataT[m_CurNum] = 3;
v25->m_DataL[m_CurNum] = 4;
v25->m_CurNum = m_CurNum + 1;
}
v17 = v25->m_Opt == 1; // 检查写入模式
v59[0] = 1; // 操作类型标识符
if (!v17)
__assertex__(
"../../Common/DataStream.h",
0x1B0u,
"IODataStream& IODataStream::operator<<(T) [with T = int]",
"0",
"m_Opt != IODataStream::OPT_WRITE");
// 写入操作类型到数据流
if (v25->m_CurNum <= 0x13u)
{
for (k = 4; k > 0; --k)
(*((void (__cdecl **)(IODataStream *, _DWORD))v25->_vptr_InputStream + 3))(
v25,
*((unsigned __int8 *)&v58 + k + 3));
// 设置数据类型和长度
v30 = v25->m_CurNum;
v25->m_DataT[v30] = 2;
v25->m_DataL[v30] = 4;
v25->m_CurNum = v30 + 1;
}
v17 = v25->m_Opt == 1; // 检查写入模式
v58 = Param; // 存储参数值
if (!v17)
__assertex__(
"../../Common/DataStream.h",
0x1B0u,
"IODataStream& IODataStream::operator<<(T) [with T = unsigned int]",
"0",
"m_Opt != IODataStream::OPT_WRITE");
// 写入参数到数据流
if (v25->m_CurNum <= 0x13u)
{
for (m = 4; m > 0; --m)
(*((void (__cdecl **)(IODataStream *, _DWORD))v25->_vptr_InputStream + 3))(
v25,
*((unsigned __int8 *)&gTargetGuid + m + 3));
// 设置数据类型和长度
v32 = v25->m_CurNum;
v25->m_DataT[v32] = 3;
v25->m_DataL[v32] = 4;
v25->m_CurNum = v32 + 1;
}
// 完成数据流写入
IODataStream::End(v25, IODataStream::OPT_TYPE::OPT_WRITE);
// 发送包到所有客户端
ServerManager::SendPacket(*(ServerManager *const *)&g_pServerManager, pMsgYuanBao, -1, 0);
// 记录成功添加的日志
v43 = Obj_Human::GetGUID(v50);
CacheLog(1, "LuaFnYuanBao::ObjGUID=%X OPT_YUANBAO_ADD success yuanbaoamount=%d", v43);
goto LABEL_76; // 准备返回成功
}
// 如果参数超过最大允许值
v37 = Obj_Human::GetGUID((const Obj_Human *const)v7);
CacheLog(1, "LuaFnYuanBao::ObjGUID=%X OPT_YUANBAO_ADD OUTRANGE(0, Param, MAX_YUANBAO) Param=%d", v37, Param);
LABEL_25:
HIDWORD(v35) = -1074790400; // 设置返回值的高位,表示错误
LABEL_26:
LODWORD(v35) = 0; // 设置返回值的低位为0
lua_pushnumber((lua_State_0 *)L, v35); // 将返回值推入Lua栈
return 1; // 返回1个值给Lua
case 2: // 减少元宝
if (Param > 0xBEBC200) // 检查减少金额是否在允许范围内
{
v36 = Obj_Human::GetGUID((const Obj_Human *const)v7);
// 记录超出范围的减少尝试
CacheLog(1, "LuaFnYuanBao::ObjGUID=%X OPT_YUANBAO_SUB OUTRANGE(0, Param, MAX_YUANBAO) Param=%d", v36, Param);
goto LABEL_25; // 准备返回错误
}
v10 = Obj_Human::GetYuanBao((Obj_Human *const)v7); // 获取当前元宝数量
v11 = v10 - Param; // 计算减少后的新元宝数量
if (v10 - Param > 0xBEBC200) // 检查减少后的元宝数量是否超过最大限制(减少操作通常不会超过)
{
v46 = v10 - Param;
v42 = Obj_Human::GetGUID((const Obj_Human *const)v7);
// 记录超出范围的减少结果
CacheLog(
1,
"LuaFnYuanBao::ObjGUID=%X OPT_YUANBAO_SUB OUTRANGE(0, yuanbaoamount, MAX_YUANBAO) yuanbaoamount=%d",
v42,
v46);
goto LABEL_25; // 准备返回错误
}
// 检查对象位置数据中的某个标志(可能用于防止重复更新)
if ((BYTE1(v7[1518].m_Pos.m_fZ) & 8) != 0)
{
v45 = v10 - Param;
v39 = Obj_Human::GetGUID((const Obj_Human *const)v7);
// 记录已经在进行更新的日志
CacheLog(1, "LuaFnYuanBao::ObjGUID=%X OPT_YUANBAO_SUB BLT_YUANBAO_OPT yuanbaoamount=%d", v39, v45);
goto LABEL_25; // 准备返回错误
}
// 执行减少操作
Obj_Human::GetYuanBao((Obj_Human *const)v7); // (冗余?可能有副作用)
gTargetGuid = -1;
nOpType = MONEY_OP_TYPE::YUANBAO_SCRIPT_COST; // 定义操作类型为减少
Obj_Human::SetYuanBao((Obj_Human *const)v7, v11, &nOpType, 0, &gTargetGuid, 0); // 更新元宝数量
LODWORD(v7[1518].m_Pos.m_fZ) |= 0x800u; // 在对象位置数据中设置标志(表示更新)
// 创建一个网络包以通知客户端
v14 = PacketFactoryManager::CreatePacket(g_pPacketFactoryManager, 0x17Eu); // 创建GWYuanBao包
v15 = (IODataStream *)&v14[1]; // 从包中获取数据流
pMsgYuanBao_0 = (Packets::GWYuanBao *)v14; // 转换为特定包类型
IODataStream::Begin((IODataStream *const)&v14[1], IODataStream::OPT_TYPE::OPT_WRITE); // 开始写入数据流
v16 = Obj_Human::GetGUID((const Obj_Human *const)v7); // 获取对象的GUID
v17 = v15->m_Opt == 1; // 检查数据流是否处于写入模式
v55[1] = v16; // 存储GUID
if (!v17)
__assertex__(
"../../Common/DataStream.h",
0x1B0u,
"IODataStream& IODataStream::operator<<(T) [with T = unsigned int]",
"0",
"m_Opt != IODataStream::OPT_WRITE");
// 如果数据流有空间,写入GUID
if (v15->m_CurNum <= 0x13u)
{
for (n = 4; n > 0; --n)
(*((void (__cdecl **)(IODataStream *, _DWORD))v15->_vptr_InputStream + 3))(
v15,
*((unsigned __int8 *)v55 + n + 3));
// 设置数据类型和长度
v19 = v15->m_CurNum;
v15->m_DataT[v19] = 3;
v15->m_DataL[v19] = 4;
v15->m_CurNum = v19 + 1;
}
v17 = v15->m_Opt == 1; // 检查写入模式
v55[0] = -1; // 操作类型标识符为减少
if (!v17)
__assertex__(
"../../Common/DataStream.h",
0x1B0u,
"IODataStream& IODataStream::operator<<(T) [with T = int]",
"0",
"m_Opt != IODataStream::OPT_WRITE");
// 写入操作类型到数据流
if (v15->m_CurNum <= 0x13u)
{
for (ii = 4; ii > 0; --ii)
(*((void (__cdecl **)(IODataStream *, _DWORD))v15->_vptr_InputStream + 3))(
v15,
*((unsigned __int8 *)&v54 + ii + 3));
// 设置数据类型和长度
v21 = v15->m_CurNum;
v15->m_DataT[v21] = 2;
v15->m_DataL[v21] = 4;
v15->m_CurNum = v21 + 1;
}
v17 = v15->m_Opt == 1; // 检查写入模式
v54 = Param; // 存储参数值
if (!v17)
__assertex__(
"../../Common/DataStream.h",
0x1B0u,
"IODataStream& IODataStream::operator<<(T) [with T = unsigned int]",
"0",
"m_Opt != IODataStream::OPT_WRITE");
// 写入参数到数据流
if (v15->m_CurNum <= 0x13u)
{
for (jj = 4; jj > 0; --jj)
(*((void (__cdecl **)(IODataStream *, _DWORD))v15->_vptr_InputStream + 3))(
v15,
*((unsigned __int8 *)&v53 + jj + 1));
// 设置数据类型和长度
v23 = v15->m_CurNum;
v15->m_DataT[v23] = 3;
v15->m_DataL[v23] = 4;
v15->m_CurNum = v23 + 1;
}
// 完成数据流写入
IODataStream::End(v15, IODataStream::OPT_TYPE::OPT_WRITE);
// 发送包到所有客户端
ServerManager::SendPacket(*(ServerManager *const *)&g_pServerManager, pMsgYuanBao_0, -1, 0);
// 记录成功减少的日志
v41 = Obj_Human::GetGUID(v50);
CacheLog(1, "LuaFnYuanBao::ObjGUID=%X OPT_YUANBAO_SUB success yuanbaoamount=%d", v41);
LABEL_76:
HIDWORD(v35) = 0; // 设置返回值的高位,表示成功
goto LABEL_26; // 准备返回成功
case 3: // 获取元宝
v9 = Obj_Human::GetYuanBao((Obj_Human *const)v7); // 获取当前元宝数量
if ((unsigned int)v9 > 0xBEBC200) // 检查元宝数量是否超过最大值
goto LABEL_25; // 准备返回错误
lua_pushnumber((lua_State_0 *)L, (double)v9); // 将元宝数量推入Lua栈
break;
default:
LABEL_12:
lua_pushnumber((lua_State_0 *)L, -1.0); // 推入-1.0,表示失败
break;
}
return 1; // 返回1个值给Lua
}
剩余 6% 内容需要支付 10.00
金币 后可完整阅读
支持付费阅读,激励作者创作更好的作品。