找回密码
 register

QQ登录

只需一步,快速开始

查看: 78|回复: 0

[系统函数] ZengDian 赠点函数、绑定元宝函数 查询、增加、扣除

[复制链接]

[系统函数] ZengDian 赠点函数、绑定元宝函数 查询、增加、扣除

[复制链接]
彩虹屁

主题

0

回帖

230

积分

金仙

积分
230
彩虹屁 2022-10-11 08:20 | 显示全部楼层 |阅读模式

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

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

×

整理人员:雪舞
整理时间:2024-12-4


介绍

赠点,在某些仿官服里,这个叫做绑定元宝哦。
案例: ***付费内容***

IDA伪代码(085原版)

// 函数: LuaFnZengDian
// 描述: Lua绑定函数,用于操作赠点(游戏内另一种货币)
// 参数: 
//   lua_State *L - 包含函数参数的Lua状态
int __cdecl LuaFnTbl::LuaFnZengDian(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_Human *v7; // 玩家对象
int v9; // 临时变量,用于赠点数量
int v10; // 临时变量,用于赠点数量
int v11; // 减少后新的赠点数量
int ZengDian; // 当前赠点数量
int v13; // 添加后的新赠点数量
Packet *Packet; // 网络通信的包
Packet *v15; // 临时包变量
int (**vptr_Packet)(...); // 包的虚函数指针
const CHAR *v17; // 错误字段名称
const CHAR *v18; // 错误信息
double v19; // 返回值
GUID_t v20; // 日志记录用的GUID
GUID_t v21; // 日志记录用的GUID
GUID_t GUID; // 日志记录用的GUID
GUID_t v23; // 日志记录用的GUID
GUID_t v24; // 日志记录用的GUID
GUID_t v25; // 日志记录用的GUID
GUID_t v26; // 日志记录用的GUID
GUID_t v27; // 日志记录用的GUID
GUID_t v28; // 日志记录用的GUID
unsigned int v29; // 操作后的赠点数量
unsigned int v30; // 操作后的赠点数量
unsigned int v31; // 操作后的赠点数量
unsigned int v32; // 操作后的赠点数量
unsigned int Param; // 操作的参数(金额)
SceneID_t sceneId; // Lua参数中的场景ID
MONEY_OP_TYPE nOpType; // 操作类型枚举(用于减少)
GUID_t gTargetGuid; // 操作的目标GUID
MONEY_OP_TYPE v37; // 操作类型枚举(用于添加)
GUID_t v38; // 操作的目标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!", "LuaFnZengDian", i);
}
else
{
  // 如果Lua状态为空,准备错误信息
  snprintf(s, 0x200u, "ERROR: [%s] Lua_State==NULL!", "LuaFnZengDian");
}
// 以级别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, "LuaFnZengDian:: begin sceneId=%d selfId=%d targetId=%d opttype=%d Param=%d", sceneId, v2, v3, v4, Param);

// 从场景管理器获取当前场景
Scene = SceneManager::GetScene(v5, g_pSceneManager);
if ( !Scene )
{
// 如果场景不存在,准备错误信息并断言
v18 = "Scene ID ErrorLuaFnZengDian";
v17 = "pScene";
LABEL_16:
__assertex__("./Script/LuaFnTbl_Shop.h", 0x402u, "int LuaFnTbl::LuaFnZengDian(lua_State*)", v17, v18);
}

// 检查当前线程ID是否与场景的线程ID匹配,确保线程安全
if ( ThreadValueManager::GetCurrentThreadID() != Scene->m_ThreadID )
__assertex__(
  "./Script/LuaFnTbl_Shop.h",
  0x402u,
  "int LuaFnTbl::LuaFnZengDian(lua_State*)",
  "ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadID",
  "ThreadValueManager::GetCurrentThreadID()==pScene->m_ThreadIDLuaFnZengDian");

// 验证selfId是否在有效范围内,并获取对应的对象
if ( v2 > 0x752F || (v7 = (Obj_Human *)Scene->m_pObjManager->m_pObj[v2]) == 0 )
{
// 如果selfId无效或对象不存在,准备错误信息并断言
v18 = "selfId ErrorLuaFnZengDian";
v17 = "pObj";
goto LABEL_16;
}

// 检查对象是否为人类类型(可能是通过虚函数表的第二个函数)
if ( (*((int (__cdecl **)(Obj_Human *))v7->_vptr_Obj + 2))(v7) != 1 )
goto LABEL_12; // 如果不是,跳转到默认情况

// 检查人类对象是否可以进行逻辑操作
if ( !Obj_Human::IsCanLogic(v7) )
__assertex__(
  "./Script/LuaFnTbl_Shop.h",
  0x402u,
  "int LuaFnTbl::LuaFnZengDian(lua_State*)",
  "pHuman->IsCanLogic()",
  "IsCanLogic() test return falseLuaFnZengDian");

// 验证操作类型是否有效:1(添加)、2(减少)、3(获取)
if ( (unsigned int)(v4 - 1) > 2 )
{
// 如果操作类型无效,记录错误日志
GUID = Obj_Human::GetGUID(v7);
CacheLog(1, "LuaFnZengDian::ObjGUID=%X Invalid opttype=%d", GUID, v4);
goto LABEL_25;
}

// 根据操作类型执行相应操作
switch ( v4 )
{
case 1: // 添加赠点
  if ( Param <= 0xBEBC200 )
  {
    ZengDian = Obj_Human::GetZengDian(v7); // 获取当前赠点数量
    v13 = Param + ZengDian; // 计算添加后的新赠点数量
    if ( Param + ZengDian > 0xBEBC200 )
    {
      v32 = Param + ZengDian;
      v28 = Obj_Human::GetGUID(v7);
      // 记录超出范围的添加尝试
      CacheLog(
        1,
        "LuaFnZengDian::ObjGUID=%X OPT_ZENGDIAN_ADD OUTRANGE(0, amount, MAX_ZENGDIAN) amount=%d",
        v28,
        v32);
      goto LABEL_25;
    }
    // 检查对象中的某个标志(可能用于防止重复更新)
    if ( (v7->m_szGuildLeagueName[29] & 0x10) != 0 )
    {
      v30 = Param + ZengDian;
      v24 = Obj_Human::GetGUID(v7);
      // 记录已经在进行更新的日志
      CacheLog(1, "LuaFnZengDian::ObjGUID=%X OPT_ZENGDIAN_ADD BLT_ZENGDIAN_OPT amount=%d", v24, v30);
      goto LABEL_25;
    }
    // 执行添加赠点操作
    Obj_Human::GetZengDian(v7); // (冗余?可能有副作用)
    v38 = -1;
    v37 = MONEY_OP_TYPE::ZENGDIAN_SCRIPT_ADD; // 定义操作类型为添加
    Obj_Human::SetZengDian(v7, v13, &v37, 0, &v38); // 更新赠点数量
    // 创建一个网络包以通知客户端
    Packet = PacketFactoryManager::CreatePacket(g_pPacketFactoryManager, 0x263u);
    v15 = Packet;
    if ( Packet )
    {
      // 这里看起来是在设置包的内容
      *((_BYTE *)Packet[1]._vptr_Packet + (unsigned int)Packet + 16) = 1;
      vptr_Packet = Packet[1]._vptr_Packet;
      *((_DWORD *)&v15[6]._vptr_Packet + (_DWORD)vptr_Packet) = 34;
      *((_DWORD *)&v15[24]._vptr_Packet + (_DWORD)vptr_Packet) = Param;
      v15[1]._vptr_Packet = (int (**)(...))((char *)vptr_Packet + 1);
      // 发送包到所有客户端
      ServerManager::SendPacket(*(ServerManager *const *)&g_pServerManager, v15, -1, 0);
    }
    // 记录成功添加的日志
    v27 = Obj_Human::GetGUID(v7);
    CacheLog(1, "LuaFnZengDian::ObjGUID=%X OPT_ZENGDIAN_ADD success amount=%d", v27);
    goto LABEL_43;
  }
  // 如果参数超过最大允许值
  v21 = Obj_Human::GetGUID(v7);
  CacheLog(1, "LuaFnZengDian::ObjGUID=%X OPT_ZENGDIAN_ADD OUTRANGE(0, Param, MAX_ZENGDIAN) Param=%d", v21, Param);
LABEL_25:
  HIDWORD(v19) = -1074790400; // 设置返回值的高位,表示错误
LABEL_26:
  LODWORD(v19) = 0; // 设置返回值的低位为0
  lua_pushnumber((lua_State_0 *)L, v19); // 将返回值推入Lua栈
  return 1; // 返回1个值给Lua
case 2: // 减少赠点
  if ( Param > 0xBEBC200 )
  {
    v20 = Obj_Human::GetGUID(v7);
    // 记录超出范围的减少尝试
    CacheLog(1, "LuaFnZengDian::ObjGUID=%X OPT_ZENGDIAN_SUB OUTRANGE(0, Param, MAX_ZENGDIAN) Param=%d", v20, Param);
    goto LABEL_25;
  }
  v10 = Obj_Human::GetZengDian(v7); // 获取当前赠点数量
  v11 = v10 - Param; // 计算减少后的新赠点数量
  if ( v10 - Param > 0xBEBC200 )
  {
    v31 = v10 - Param;
    v26 = Obj_Human::GetGUID(v7);
    // 记录超出范围的减少结果
    CacheLog(1, "LuaFnZengDian::ObjGUID=%X OPT_ZENGDIAN_SUB OUTRANGE(0, amount, MAX_ZENGDIAN) amount=%d", v26, v31);
    goto LABEL_25;
  }
  // 检查对象中的某个标志(可能用于防止重复更新)
  if ( (v7->m_szGuildLeagueName[29] & 0x10) != 0 )
  {
    v29 = v10 - Param;
    v23 = Obj_Human::GetGUID(v7);
    // 记录已经在进行更新的日志
    CacheLog(1, "LuaFnZengDian::ObjGUID=%X OPT_ZENGDIAN_SUB BLT_ZENGDIAN_OPT amount=%d", v23, v29);
    goto LABEL_25;
  }
  // 执行减少赠点操作
  Obj_Human::GetZengDian(v7); // (冗余?可能有副作用)
  gTargetGuid = -1;
  nOpType = MONEY_OP_TYPE::ZENGDIAN_SCRIPT_COST; // 定义操作类型为减少
  Obj_Human::SetZengDian(v7, v11, &nOpType, 0, &gTargetGuid); // 更新赠点数量
  v25 = Obj_Human::GetGUID(v7);
  // 记录成功减少的日志
  CacheLog(1, "LuaFnZengDian::ObjGUID=%X OPT_ZENGDIAN_SUB success amount=%d", v25);
LABEL_43:
  HIDWORD(v19) = 0; // 设置返回值的高位,表示成功
  goto LABEL_26; // 准备返回成功
case 3: // 获取赠点
  v9 = Obj_Human::GetZengDian(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
}
付费看帖
剩余 10% 内容需要支付 10.00 金币 后可完整阅读
支持付费阅读,激励作者创作更好的作品。
您需要登录后才可以回帖 登录 | register

本版积分规则

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

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

Powered by XueWu Licensed

Copyright © Tencent Cloud.

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