诛仙挂机外挂拣物分析
本文仅为探讨。使用数据为7月10号更新的35版。
http://www.cnblogs.com/birdshover/
拣物方式有两类,模拟按键和CALL。模拟按键没什么好说的,不能保证一定能把自己的东西全部捡取。而CALL的方式也存在是否全部捡取了和捡取效率的问题。
本文介绍的内容不采用诛仙内存地址自带的地面物品数量,而让自己来计算地面物品数量。算法为取自身5距离内的地面物品,每个捡一次。
oid AddressMap::GetAllAddress(void)
{
if(!Gobal::ReadAddressError)
{
//7月10号基址
BaseAddress = (LPVOID)0x90664c;
SecondAddress = (LPVOID)(Gobal::ReadMemoryAddress(BaseAddress) + 0x28);
ItemBase = (LPVOID)Gobal::ReadMemoryAddress((LPVOID)(Gobal::ReadMemoryAddress((LPVOID)(Gobal::ReadMemoryAddress(BaseAddress) + 0x8)) + 0x24));
ItemCount = (LPVOID)((DWORD)ItemBase + 0x14);
}
}
//物品结构
struct Items{
DWORD ItemID; //物品ID
DWORD ItemSystemID; //物品系统ID
CString ItemName; //物品名称
float ItemX; //X坐标
float ItemY; //Y坐标
};
//物品信息
AddressMap::Items AddressMap::GetItem(int i)
{
AddressMap::Items item;
DWORD dmbase = Gobal::ReadMemoryAddress((LPVOID)(Gobal::ReadMemoryAddress((LPVOID)((DWORD)ItemBase + 0x18)) + 0x4 * i));
if(dmbase <= 0)
{
item.ItemID = 0;
item.ItemSystemID = 0;
return item;
}
DWORD theAddress = Gobal::ReadMemoryAddress((LPVOID)(dmbase + 0x4));
item.ItemID = Gobal::ReadMemoryValue((LPVOID)(theAddress + 0x110));
item.ItemSystemID = Gobal::ReadMemoryValue((LPVOID)(theAddress + 0x10C));
item.ItemName = Gobal::ReadMemoryTextValueL((LPVOID)Gobal::ReadMemoryAddress((LPVOID)(theAddress + 0x164)));
item.ItemX = Gobal::ReadMemoryFloatValue((LPVOID)(theAddress + 0x3C));
item.ItemY = Gobal::ReadMemoryFloatValue((LPVOID)(theAddress + 0x44));
return item;
//return Items();
}
捡取物品CALL
void MyCall::CallPickItem(DWORD itemID, DWORD itemSysID)
{
DWORD address = 0x578ca0;
__asm
{
pushad
mov ecx, dword ptr ds:[0x902b3c]
mov edx, itemID
push edx
mov ecx, dword ptr ds:[ecx+0x20]
mov eax, itemSysID
push eax
add ecx, 0xD4
call address
popad
}
}
读取内存
DWORD Gobal::ReadMemoryAddress(LPVOID address)
{
DWORD dwValue = 0;
DWORD length = 0;
bool read = (ReadProcessMemory(Gobal::hProcess,address,&dwValue,sizeof(DWORD),&length) == 1);
if(read && length == sizeof(DWORD))
{
Gobal::ReadAddressError = true;
return dwValue;
}
else
{
Gobal::ReadAddressError = false;
return 0;
}
}
主过程:
公用变量申明
//////////////////////////////////////////////////////////////////////////////////////
//捡取状态,0为计数,1为捡取
int baseItemMy = 0;
//当前计算所得物品数量
int itemAllNum = 0;
//存放物品信息的数组,供拣物CALL使用
DWORD itemArray[10][2];
//当前人物坐标
float nowx = 0;float nowy = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
过程内操作:
//读取地址
AddressMap::GetAllAddress();
DWORD second = Gobal::ReadMemoryAddress(AddressMap::SecondAddress);
//当前人物坐标
nowx = Gobal::ReadMemoryFloatValue(LPVOID(second + 0x3d8));
nowy = Gobal::ReadMemoryFloatValue(LPVOID(second + 0x3e0));
//baseItemMy 计算物品数量
if(baseItemMy == 0)
{
for(int i = 0;i<768;i++)
{
//取得物品信息
AddressMap::Items items = AddressMap::GetItem(i);
if(items.ItemID > 0)
{
//如果距离人物距离不超过5,并且数量小于10的时候
if(abs((float)items.ItemX - nowx) < 5 && abs((float)items.ItemY - nowy) < 5 && itemAllNum < 10)
{
//存入物品ID和物品系统ID
itemArray[itemAllNum][0] = items.ItemID;
itemArray[itemAllNum][1] = items.ItemSystemID;
//物品数量增加1
itemAllNum++;
}
}
}
//计数完毕,切换状态
baseItemMy = 1;
}
//进入拣物状态
if(itemAllNum > 0)
{
//调用拣物CALL
MyCall::CallPickItem(itemArray[itemAllNum - 1][0],itemArray[itemAllNum - 1][1]);
//物品数量减少1
itemAllNum--;
}
else
{
//没有物品,重置状态
Gobal::UserState = 1;
itemAllNum = 0;
baseItemMy = 0;
}
//int itemCount = (int)Gobal::ReadMemoryValue(AddressMap::ItemCount);
到此,就完成了。
http://www.cnblogs.com/birdshover/