And here are some roughed in packet handling for mercs for client_packet.cpp. These are mostly just hard set with the basic packet responses so they can be corrected later with actual functions supporting them.
Code:
ConnectedOpcodes[OP_MercenaryCommand] = &Client::Handle_OP_MercenaryCommand;
ConnectedOpcodes[OP_MercenaryDataUpdateRequest] = &Client::Handle_OP_MercenaryDataUpdateRequest;
ConnectedOpcodes[OP_MercenarySuspendRequest] = &Client::Handle_OP_MercenarySuspendRequest;
Code:
void Client::Handle_OP_MercenarySuspendRequest(const EQApplicationPacket *app)
{
if(app->size != sizeof(SuspendMercenary_Struct))
{
LogFile->write(EQEMuLog::Debug, "Size mismatch in OP_MercenarySuspendRequest expected %i got %i", sizeof(SuspendMercenary_Struct), app->size);
DumpPacket(app);
return;
}
SuspendMercenary_Struct* sm = (SuspendMercenary_Struct*) app->pBuffer;
uint32 merc_suspend = sm->SuspendMerc; // Seen 30 for suspending or unsuspending
DumpPacket(app);
// Handle the Command here...
// Check if the merc is suspended and if so, unsuspend, otherwise suspend it
// This response packet includes the timestamp of the suspend request
EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenarySuspendResponse, sizeof(SuspendMercenaryResponse_Struct));
SuspendMercenaryResponse_Struct* smr = (SuspendMercenaryResponse_Struct*)outapp->pBuffer;
smr->SuspendTime = time(); // Unix Timestamp
DumpPacket(outapp);
FastQueuePacket(&outapp);
}
void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app)
{
if(app->size != sizeof(MercenaryCommand_Struct))
{
LogFile->write(EQEMuLog::Debug, "Size mismatch in OP_MercenaryCommand expected %i got %i", sizeof(MercenaryCommand_Struct), app->size);
DumpPacket(app);
return;
}
MercenaryCommand_Struct* mc = (MercenaryCommand_Struct*) app->pBuffer;
uint32 merc_command = mc->MercCommand; // Seen 0 (zone in with no merc or suspended), 1 (dismiss merc), 5 (normal state), 36 (zone in with merc)
sint32 option = mc->Option; // Seen -1 (zone in with no merc), 0 (setting to passive stance), 1 (normal or setting to balanced stance)
DumpPacket(app);
// Handle the Command here...
// Will need a list of what every type of command is supposed to do
// Unsure if there is a server response to this packet
}
void Client::Handle_OP_MercenaryDataUpdateRequest(const EQApplicationPacket *app)
{
// The payload is 0 bytes.
if(app->size != 0)
{
LogFile->write(EQEMuLog::Debug, "Size mismatch in OP_MercenaryDataUpdateRequest expected 0 got %i", app->size);
DumpPacket(app);
return;
}
DumpPacket(app);
// Hard setting some stuff until it can be coded to load properly from the DB
int mercCount = 1;
int stanceCount = 2;
char mercName[32]; // This actually needs to be null terminated
strcpy(mercName, GetRandPetName());
uint32 packetSize = sizeof(MercenaryDataUpdate_Struct) + ( sizeof(MercenaryData_Struct) - 8 + sizeof(MercenaryStance_Struct) * stanceCount ) * mercCount + strlen(mercName);
// This response packet seems to be sent on zoning or camping by client request
// It is populated with owned merc data only
EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, packetSize);
MercenaryDataUpdate_Struct* mdu = (MercenaryDataUpdate_Struct*)outapp->pBuffer;
mdu->MercStatus = 0;
mdu->MercCount = mercCount;
for(int i = 0; i < mercCount; i++)
{
mdu->Mercs[i].MercID = 400;
mdu->Mercs[i].MercType = 330000100;
mdu->Mercs[i].MercSubType = 330020105;
mdu->Mercs[i].PurchaseCost = 4910;
mdu->Mercs[i].UpkeepCost = 123;
mdu->Mercs[i].Status = 0;
mdu->Mercs[i].AltCurrencyCost = 0;
mdu->Mercs[i].AltCurrencyUpkeep = 1;
mdu->Mercs[i].AltCurrencyType = 19;
mdu->Mercs[i].MercUnk01 = 0;
mdu->Mercs[i].TimeLeft = 900000;
mdu->Mercs[i].MerchantSlot = 1;
mdu->Mercs[i].MercUnk02 = 1;
mdu->Mercs[i].StanceCount = stanceCount;
mdu->Mercs[i].MercUnk03 = 519044964;
mdu->Mercs[i].MercUnk04 = 1;
strcpy(mml->Mercs[i].MercName, mercName);
for (int stanceindex = 0; stanceindex < stanceCount; stanceindex++)
{
mdu->Mercs[i].Stances[stanceindex].StanceIndex = stanceindex;
mdu->Mercs[i].Stances[stanceindex].Stance = stanceindex + 1;
}
mdu->Mercs[i].MercUnk05 = 1;
i++;
}
DumpPacket(outapp);
FastQueuePacket(&outapp);
}
I haven't tested these yet, but the basics should be there and easy to get working. I think this is the last of the handling needed for packets coming from the client. There is still plenty to do to get this stuff actually working as intended though.