函数用法说明
函数名称:LuaFnSetBagItemParam
注册函数:SetBagItemParam
功能说明:设置背包中物品的参数 ***付费内容***
C++源代码(武侠世界)
VOID _ITEM::SetItemParam(UINT start,ItemParamValue& ipv,INT value)
{
INT TotalSize = sizeof(INT)*MAX_ITEM_PARAM;
INT size;
switch(ipv)
{
case IPV_CHAR:
{
size = 1;
if( start > ( (UINT)TotalSize - (UINT)size ) )
{
Assert(FALSE);
}
*((CHAR*)m_Param+start) = (CHAR)value;
}
break;
case IPV_SHORT:
{
size = 2;
if(start>((UINT)TotalSize - (UINT)size))
{
Assert(FALSE);
}
*((SHORT*)((CHAR*)m_Param+start)) = (SHORT)value;
}
break;
case IPV_INT:
{
size = 4;
if(start>((UINT)TotalSize - (UINT)size))
{
Assert(FALSE);
}
*((INT*)((CHAR*)m_Param+start)) = (INT)value;
}
break;
default:
Assert(FALSE);
}
}
IDA伪代码(0.85.0600)
void __cdecl _ITEM::SetItemParam(_ITEM *const this, UINT start, const ItemParamValue *const ipv, INT value)
{
ItemParamValue v4; // eax
v4 = *ipv;
if ( *ipv == ItemParamValue::IPV_SHORT )
{
if ( start > 0xA )
__assert__(
"../../Common/GameStruct.cpp",
0x213u,
"void _ITEM::SetItemParam(UINT, const ItemParamValue&, INT)",
"FALSE");
*(_WORD *)((char *)this->m_Param + start) = value;
}
else if ( *(int *)ipv <= 1 )
{
if ( v4 )
LABEL_4:
__assert__(
"../../Common/GameStruct.cpp",
0x223u,
"void _ITEM::SetItemParam(UINT, const ItemParamValue&, INT)",
"FALSE");
if ( start > 0xB )
__assert__(
"../../Common/GameStruct.cpp",
0x209u,
"void _ITEM::SetItemParam(UINT, const ItemParamValue&, INT)",
"FALSE");
*((_BYTE *)this->m_Param + start) = value;
}
else
{
if ( v4 != ItemParamValue::IPV_INT )
goto LABEL_4;
if ( start > 8 )
__assert__(
"../../Common/GameStruct.cpp",
0x21Du,
"void _ITEM::SetItemParam(UINT, const ItemParamValue&, INT)",
"FALSE");
*(INT *)((char *)this->m_Param + start) = value;
}
}
C++模拟(非游戏环境,外部模拟)
#include <iostream>
#include <cassert>
#include <cstring>
enum ItemParamValue
{
IPV_CHAR = 0,
IPV_SHORT = 1,
IPV_INT = 2
};
#define MAX_ITEM_PARAM 3 // 相当于12字节的存储空间
struct _ITEM
{
char m_Param[sizeof(int) * MAX_ITEM_PARAM]; // 12字节空间
void SetItemParam(unsigned int start, ItemParamValue ipv, int value)
{
int TotalSize = sizeof(int) * MAX_ITEM_PARAM; // 12字节
int size = 0;
switch (ipv)
{
case IPV_CHAR: size = 1; break;
case IPV_SHORT: size = 2; break;
case IPV_INT: size = 4; break;
default: assert(false);
}
if (start > (unsigned int)(TotalSize - size))
{
assert(false);
}
switch (ipv)
{
case IPV_CHAR:
*((char*)(m_Param + start)) = (char)value;
break;
case IPV_SHORT:
*((short*)(m_Param + start)) = (short)value;
break;
case IPV_INT:
*((int*)(m_Param + start)) = (int)value;
break;
}
}
int GetItemParamValue(unsigned int start, ItemParamValue ipv)
{
int TotalSize = sizeof(int) * MAX_ITEM_PARAM;
int size = 0;
switch (ipv)
{
case IPV_CHAR: size = 1; break;
case IPV_SHORT: size = 2; break;
case IPV_INT: size = 4; break;
default: assert(false);
}
if (start > (unsigned int)(TotalSize - size))
{
assert(false);
}
switch (ipv)
{
case IPV_CHAR:
return *((char*)(m_Param + start));
case IPV_SHORT:
return *((short*)(m_Param + start));
case IPV_INT:
return *((int*)(m_Param + start));
}
return -1; // 理论上不会执行到这里
}
};
int main()
{
_ITEM item;
memset(item.m_Param, 0, sizeof(item.m_Param));
// 存储一个CHAR类型(值65)、一个SHORT类型(值300)、一个INT类型(99999)
item.SetItemParam(0, IPV_CHAR, 65);
item.SetItemParam(2, IPV_SHORT, 300);
item.SetItemParam(4, IPV_INT, 99999);
// 读取并打印,只显示数值
int cVal = item.GetItemParamValue(0, IPV_CHAR); // 读取CHAR存储的值 IPV_CHAR
int sVal = item.GetItemParamValue(2, IPV_SHORT); // 读取SHORT存储的值 IPV_SHORT
int iVal = item.GetItemParamValue(4, IPV_INT); // 读取INT存储的值 IPV_INT
std::cout << "CHAR Value at offset 0: " << cVal << std::endl;
std::cout << "SHORT Value at offset 2: " << sVal << std::endl;
std::cout << "INT Value at offset 4: " << iVal << std::endl;
return 0;
}
模拟函数的原理解释
一、固定大小的连续内存块:
m_Param
是一个字节数组,为物品的参数预留了一段连续内存空间。例如,如果 MAX_ITEM_PARAM = 3
,则 m_Param
的大小是 sizeof(int)*3 = 12
个字节。可以把 m_Param
想象成一条长为 12
的字节格子序列,从索引0到11。
二、类型占用字节数不同:
IPV_CHAR
:占用1字节
IPV_SHORT
:占用2字节
IPV_INT
:占用4字节
写入时需要根据类型确定将多少字节的数据写入到 m_Param
中。
三、偏移量(start)的含义:
start 指定了从 m_Param
的第几个字节(索引)开始存储该参数的值。
例如:
- 若
start=0
,表示从 m_Param[0]
开始存数据。
- 若类型为
IPV_SHORT
,则在 m_Param[0]
和 m_Param[1]
两个字节中存放这个参数的值。
四、写入操作(SetItemParam):
当执行 SetItemParam(start, ipv, value)
时,函数会:
- 根据
ipv
确定要写入的字节数(1、2或4字节)。
- 检查
start
和数据长度是否越过 m_Param
的边界(即不能超出总的12字节)。
- 将传入的 value 强制转换成相应类型
(char/short/int)
,然后以对应类型的指针将值写入到(m_Param + start)
处的内存中。
五、读取操作(GetItemParamValue):
当执行 GetItemParamValue(start, ipv)
时:
- 根据
ipv
确定要读取几字节并如何解释这些字节。
- 从
(m_Param + start)
开始读取对应字节数量的数据。
- 将这段数据解释为指定类型
(char/short/int)
的值,并以 int
类型返回。
六、不重叠、不越界存储:
由于不同类型占用的空间不同,为确保数据不会重叠和破坏之前存放的值,调用者需要合理分配每个参数的 start 值。
- 比如存3个
int
类型数据(每个4字节),就应将它们存放在start=0, start=4, start=8
的位置,刚好12字节排满,不会出现重叠和越界。
相关函数
GetBagItemParam 获取背包中物品的参数 物品信息 物品数据 道具信息
剩余 36% 内容需要支付 188.00
金币 后可完整阅读
支持付费阅读,激励作者创作更好的作品。