В общем не так давно решил пересмотреть свои функции и нашел интересную вещь, как оказалось WebZen не стали особо мудрить с ценами на вещи и менять их оказалось намного проще, чем я думал раньше.
1. Все начинается с функции, которая определяет цену предмета и возвращает long long значение
__int64 SetItemPrice(ObjItem * gItem, int Mode);
Название я сам придумал

И так, что есть ItemStruct и что есть Mode:
-
ObjItem * gItem это структура передаваемая функции, в которой клиент хранит такие данные, как Defense / Damage / требования по статам и прочее.
Не полная структура:
CODE
struct ObjItem
{
/*0*/ WORD ItemID;
/*2*/ DWORD Level;
/*6*/ BYTE Unknown6;
/*7*/ BYTE Unknown7;
/*8*/ BYTE Unknown8;
/*9*/ WORD DamageMin;
/*11*/ WORD DamageMax;
/*13*/ BYTE Unknown13;
/*14*/ WORD Unknown14;
/*16*/ WORD Unknown16;
/*18*/ BYTE Unknown18;
/*19*/ BYTE Unknown19;
/*20*/ WORD Unknown20;
/*22*/ BYTE Durability;
/*23*/ WORD Attribute2;
/*25*/ WORD RequireStrenght;
/*27*/ WORD RequireDextirity;
/*29*/ WORD RequireEnergy;
/*31*/ WORD RequireVitality;
/*33*/ WORD RequireCommand;
/*35*/ WORD RequireLevel;
/*37*/ BYTE Unknown37;
/*38*/ BYTE Unknown38;
};
- int
Mode это тип с которым функция должна вернуть цену, 0 - Покупка, 1 - Продажа
2. Самый гибкий и простой вариант установки своих цен:
2.1. Создаем свою функцию, которая будет выполнять нужные нам действия перед оригинальной, пример:
CODE
__int64 gSetItemPrice(ObjItem * gItem, int Mode)
{
__int64 Money = -1;
// ----
if( (int)gItem == -1 )
{
return 0;
}
// ----
switch(gItem->ItemID)
{
case ITEM(14, 13): //-> Jewel Of Bless
case ITEM(14, 14): //-> Jewel Of Soul
{
Money = 15000000;
}
break;
}
// ----
if( Money != -1 )
{
if( Mode == 1 )
{
Money /= 3;
}
// ----
return Money;
}
// ----
return SetItemPrice(gItem, Mode);
}
В данной случае наша функция проверяет поинтер по ItemID на Jewel Of Soul и Jewel Of Bless, возвращает цену равную 15000000 Zen, если вещь лежит в магазине (покупка) и 1/3 от суммы, если вещь лежит в инвентаре (продажа), следом проверяет изменение цены, если она была изменена то возвращает ее, если нет - вызывает оригинальную функцию
CODE
#define SetItemPrice ((__int64(*)(ObjItem * gItem, int Mode)) 0x53D725)
2.2. Перехватываем все вызовы оригинальной функции на нашу собственную, делается это довольно просто:
- Открывает main.exe в Ollydbg, идем на адрес функции (
53D725) и нажимаем
CTR+R, после чего к нам выходит список всех вызовов функции
Пример перехвата:
CODE
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x004D8E03, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x004F27E0, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x0053A820, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x0053A87C, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x0053A8D0, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x005BF62F, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x005BF9B8, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x005C1ABC, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x005C1AF1, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x005C1B56, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x005CC10E, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x00753437, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x007A4570, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x007A45E8, ASM::CALL);
SetHook((LPVOID)gSetItemPrice, (LPVOID)0x007A4F0E, ASM::CALL);
Вот и все, теперь мы можем легко ставить любые цены на любые вещи, при этом применять сложные проверки на вроде Excellent опций и многое другое, тут уже все от фантазии.
Структура ObjItem может оказаться уникальной для 1.03.28 GMO, но я думаю, что она универсальна как минимум с 3.2 по 5.4 сезоны.
В случае, если возникнут проблемы с вызовом функции можно делать все немного иначе, заменить все ObjItem * gItem аргументы на int ItemStruct, и вызывать нужные аргументы в формате:
*(WORD*)(ItemStruct) //-> ItemID
*(BYTE*)(ItemStruct + 22) //-> Durability
И т.д.
Собственно конец, может кому будет интересно или даже пригодиться.
P.S.: Все оффсеты для
1.03.28 GMO
Сообщение отредактировал DarkSim - 9.11.2013, 23:26