Been doing some adds to the code - based off 0.2.0 , added lots of stuff for merchant interaction, but it's far from complete. I coulnd't figure out how to do the database stuff right, so basicly the item list is hardcoded for all merchants, they all sell the same 2 items, and no matter what you buy, you get grapes. You can sell stuff and get money though.. and the client no longer locks up when you try to interact with a merchant.
Had to figure out a lot of this stuff out on my own because nobody else has done it before.. the opCodes were not even in showEQ.
Anyway - someone else will have to do the database portion of this -- I also included some sample sql of how this can be done without having to modify the npc_types table.
Have to split code into seperate posts ;/
code for eq_opcodes.h
Code:
// Darvik: for shopkeepers
#define OP_ShopRequest 0x0b20 // right-click on merchant
#define OP_ShopItem 0x0c20
#define OP_ShopWelcome 0x1420
#define OP_ShopPlayerBuy 0x3520
#define OP_ShopGiveItem 0x3120
#define OP_ShopTakeMoney 0x3520
#define OP_ShopPlayerSell 0x2720
#define OP_ShopEnd 0x3720
#define OP_ShopEndConfirm 0x4521
code for client_process.cpp - I added this just above case OP_Jump:
Code:
case OP_ShopRequest:
{
Merchant_Click_Struct* mc=(Merchant_Click_Struct*)app->pBuffer;
if (app->size == sizeof(Merchant_Click_Struct))
{
cout << name << " is at merchant. ID:" << mc->merchantid << endl;
DumpPacketHex(app);
int32 mi = mc->merchantid;
// Send back opcode OP_ShopRequest - tells client to open merchant window.
APPLAYER* outapp = new APPLAYER;
outapp->opcode = OP_ShopRequest;
outapp->size = sizeof(Merchant_Click_Struct);
outapp->pBuffer = new uchar[sizeof(Merchant_Click_Struct)];
Merchant_Click_Struct* mco=(Merchant_Click_Struct*)outapp->pBuffer;
mco->mcs_unknown001 = mc->mcs_unknown001;
mco->merchantid = mc->merchantid;
mco->itemslot = 0x01; // unused here, but we set to a harmless value.
mco->mcs_unknown002[0] = mc->mcs_unknown002[0];
mco->mcs_unknown002[1] = mc->mcs_unknown002[0];
mco->mcs_unknown002[2] = mc->mcs_unknown002[0];
mco->quantity = 0x1b; // qty when used in purchase, unused here.
mco->mcs_unknown003[0] = 0x0d; // unknown data - has something to do with
mco->mcs_unknown003[1] = 0xa0; // buying and selling cost or markup.
mco->mcs_unknown003[2] = 0x3F; // <- changing this value even slightly severly screws up price.
cout << "sending back merchant_click_struct to client." << endl;
DumpPacketHex(outapp);
QueuePacket(outapp);
delete outapp;
// TODO: Lookup merchants wares..
// TODO: Start Loop through wares..
// Debug - hardcoded short beer .. trying to get stackable items to work.
uint16 item_nr = 16592;
Item_Struct* item = database.GetItem(item_nr);
cout << "merchant is selling: " << item->name << endl;
// Send this item to the client.
outapp = new APPLAYER;
outapp->opcode = OP_ShopItem;
outapp->size = sizeof(Item_Shop_Struct);
outapp->pBuffer = new uchar[outapp->size];
Item_Shop_Struct* iss = (Item_Shop_Struct*)outapp->pBuffer;
iss->merchantid = mi;
iss->itemtype = 0x00; // TODO: needs to be parsed from item.
item->equipSlot = 0x00; // this needs to be incremented in loop.
memcpy(&iss->item, item, sizeof(Item_Struct));
iss->iss_unknown001 = 0;
QueuePacket(outapp);
delete outapp;
// Debug - hardcoded cloth cap..
item_nr = 1001;
item = database.GetItem(item_nr);
cout << "merchant is selling: " << item->name << endl;
// Send this item to the client.
outapp = new APPLAYER;
outapp->opcode = OP_ShopItem;
outapp->size = sizeof(Item_Shop_Struct);
outapp->pBuffer = new uchar[outapp->size];
iss = (Item_Shop_Struct*)outapp->pBuffer;
iss->merchantid = mi;
iss->itemtype = 0x01; // TODO: needs to be parsed from item.
item->equipSlot = 0x01; // this needs to be incremented in loop.
item->common.number = 1; // not sure if this tells how many the merchant has.
memcpy(&iss->item, item, sizeof(Item_Struct));
iss->iss_unknown001 = 0;
QueuePacket(outapp);
delete outapp;
// TODO: End Loop through wares..
// say welcome to player - dont know c well enough to do this right.
// it's just a single null terminated string, heh.
outapp = new APPLAYER;
outapp->opcode = OP_ShopWelcome;
outapp->pBuffer = new uchar[12];
outapp->size = 12;
outapp->pBuffer[0] = 0x48;
outapp->pBuffer[1] = 0x65;
outapp->pBuffer[2] = 0x6c;
outapp->pBuffer[3] = 0x6c;
outapp->pBuffer[4] = 0x6f;
outapp->pBuffer[5] = 0x20;
outapp->pBuffer[6] = 0x74;
outapp->pBuffer[7] = 0x68;
outapp->pBuffer[8] = 0x65;
outapp->pBuffer[9] = 0x72;
outapp->pBuffer[10] = 0x65;
outapp->pBuffer[11] = 0x00;
QueuePacket(outapp);
delete outapp;
}
else
{
cout << "Wrong size" << app->size << ", should be " << sizeof(Merchant_Click_Struct) << endl;
}
break;
}
Will follow this post with the rest of the opCodes..