I went through and refined, corrected, and added to the previous list of Mercenary related packet structures that I had posted. Each includes the opcode used on Live as well as the opcode name used on EQEmu currently where I could find them. I added notes for each struct to explain the packet a bit.
This should compile find on windows now, and should work for the initial changes to get mercs to be purchaseable and spawning at least. These structs are the ones used on Live as of April 12 2012, so these would go in eq_packet_structs.h. I will go through the SoD and UF clients and add the structs for those patch files as well in the next post.
Right now, there are still a couple of struct issues remaining due to how the variable sized packets for the Mercenary Data has variable sized arrays within it. To prevent it from breaking anything, I just hard set the variable sized structs that are inside the already variable sized structs. This only effects a few fields, but it is something that will need to be corrected to make these packets work exactly like they do on Live. For example, the MercName, MercTypes,and Stances fields are all hard set to values that should make them functional enough for now, but ideally those should all be able to vary in size. I am not really sure of the best way to do this and still allow the data to be sent to patch .cpp files so they can be encoded accordingly for each client.
Code:
// Used by MercenaryListEntry_Struct
struct MercenaryStance_Struct {
/*0000*/ int32 StanceIndex; // Index of this stance (sometimes reverse reverse order - 3, 2, 1, 0 for 4 stances etc)
/*0004*/ int32 Stance; // From dbstr_us.txt - 1^24^Passive^0, 2^24^Balanced^0, etc (1 to 9 as of April 2012)
};
// Used by MercenaryMerchantList_Struct
struct MercenaryListEntry_Struct {
/*0000*/ int32 MercID; // ID unique to each type of mercenary (probably a DB id)
/*0004*/ int32 MercType; // From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300)
/*0008*/ int32 MercSubType; // From dbstr_us.txt - 330020105^23^Race: Guktan<br>Type: Healer<br>Confidence: High<br>Proficiency: Apprentice, Tier V...
/*0012*/ int32 PurchaseCost; // Purchase Cost (in gold)
/*0016*/ int32 UpkeepCost; // Upkeep Cost (in gold)
/*0020*/ int32 Status; // Required Account Status (Free = 0, Silver = 1, Gold = 2) at merchants - Seen 0 (suspended) or 1 (unsuspended) on hired mercs ?
/*0024*/ int32 AltCurrencyCost; // Alternate Currency Purchase Cost? (all seen costs show N/A Bayle Mark) - Seen 0
/*0028*/ int32 AltCurrencyUpkeep; // Alternate Currency Upkeep Cost? (all seen costs show 1 Bayle Mark) - Seen 1
/*0032*/ int32 AltCurrencyType; // Alternate Currency Type? - 19^17^Bayle Mark^0 - Seen 19
/*0036*/ int8 MercUnk01; // Unknown (always see 0)
/*0037*/ sint32 TimeLeft; // Unknown (always see -1 at merchant) - Seen 900000 (15 minutes in ms for newly hired merc)
/*0041*/ int32 MerchantSlot; // Merchant Slot? Increments, but not always by 1 - May be for Merc Window Options (Seen 5, 36, 1 for active mercs)?
/*0045*/ int32 MercUnk02; // Unknown (normally see 1, but sometimes 2 or 0)
/*0049*/ int32 StanceCount; // Iterations of MercenaryStance_Struct - Normally 2 to 4 seen
/*0053*/ int32 MercUnk03; // Unknown (always 0 at merchant) - Seen on active merc: 93 a4 03 77, b8 ed 2f 26, 88 d5 8b c3, and 93 a4 ad 77
/*0057*/ int8 MercUnk04; // Seen 1
/*0058*/ char MercName[1]; // Null Terminated Mercenary Name (00 at merchants)
/*0000*/ MercenaryStance_Struct Stances[2]; // Count Varies, but hard set to 2 for now - From dbstr_us.txt - 1^24^Passive^0, 2^24^Balanced^0, etc (1 to 9 as of April 2012)
};
// [OPCode: 0x27ac OP_MercenaryDataResponse] On Live as of April 2 2012 [Server->Client]
// Opcode should be renamed to something like OP_MercenaryMerchantShopResponse since the Data Response packet is different
// Sent by the server when browsing the Mercenary Merchant
struct MercenaryMerchantList_Struct {
/*0000*/ int32 MercTypeCount; // Number of Merc Types to follow
/*0004*/ int32 MercTypes[3]; // Count varies, but hard set to 3 for now - From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300)
/*0016*/ int32 MercCount; // Number of MercenaryInfo_Struct to follow
/*0020*/ MercenaryListEntry_Struct Mercs[0]; // Data for individual mercenaries in the Merchant List
};
// [OPCode: 0x4dd9 OP_MercenaryDataRequest] On Live as of April 2 2012 [Client->Server]
// Opcode should be renamed to something like OP_MercenaryMerchantShopRequest since the Data Request packet is different
// Right clicking merchant - shop request
struct MercenaryMerchantShopRequest_Struct {
/*0000*/ int32 MercMerchantID; // Entity ID of the Mercenary Merchant
/*0004*/
};
// Used by MercenaryDataUpdate_Struct
struct MercenaryData_Struct {
/*0000*/ int32 MercID; // ID unique to each type of mercenary (probably a DB id) - (if 1, do not send MercenaryData_Struct - No merc hired)
/*0004*/ int32 MercType; // From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300)
/*0008*/ int32 MercSubType; // From dbstr_us.txt - 330020105^23^Race: Guktan<br>Type: Healer<br>Confidence: High<br>Proficiency: Apprentice, Tier V...
/*0012*/ int32 PurchaseCost; // Purchase Cost (in gold)
/*0016*/ int32 UpkeepCost; // Upkeep Cost (in gold)
/*0020*/ int32 Status; // Required Account Status (Free = 0, Silver = 1, Gold = 2) at merchants - Seen 0 (suspended) or 1 (unsuspended) on hired mercs ?
/*0024*/ int32 AltCurrencyCost; // Alternate Currency Purchase Cost? (all seen costs show N/A Bayle Mark) - Seen 0
/*0028*/ int32 AltCurrencyUpkeep; // Alternate Currency Upkeep Cost? (all seen costs show 1 Bayle Mark) - Seen 1
/*0032*/ int32 AltCurrencyType; // Alternate Currency Type? - 19^17^Bayle Mark^0 - Seen 19
/*0036*/ int8 MercUnk01; // Unknown (always see 0)
/*0037*/ sint32 TimeLeft; // Unknown (always see -1 at merchant) - Seen 900000 (15 minutes in ms for newly hired merc)
/*0041*/ int32 MerchantSlot; // Merchant Slot? Increments, but not always by 1 - May be for Merc Window Options (Seen 5, 36, 1 for active mercs)?
/*0045*/ int32 MercUnk02; // Unknown (normally see 1, but sometimes 2 or 0)
/*0049*/ int32 StanceCount; // Iterations of MercenaryStance_Struct - Normally 2 to 4 seen
/*0053*/ int32 MercUnk03; // Unknown (always 0 at merchant) - Seen on active merc: 93 a4 03 77, b8 ed 2f 26, 88 d5 8b c3, and 93 a4 ad 77
/*0057*/ int8 MercUnk04; // Seen 1
/*0058*/ char MercName[1]; // Null Terminated Mercenary Name (00 at merchants)
/*0000*/ MercenaryStance_Struct Stances[2]; // Count Varies, but hard set to 2 for now - From dbstr_us.txt - 1^24^Passive^0, 2^24^Balanced^0, etc (1 to 9 as of April 2012)
/*0000*/ int32 MercUnk05; // Seen 1 - Extra Merc Data field that differs from MercenaryListEntry_Struct
// MercUnk05 may be a field that is at the end of the packet only, even if multiple mercs are listed (haven't seen examples of multiple mercs owned at once)
};
// [OPCode: 0x6537] On Live as of April 2 2012 [Server->Client]
// Should be named OP_MercenaryDataResponse, but the current opcode using that name should be renamed first
// Size varies if mercenary is hired or if browsing Mercenary Merchant
// This may also be the response for Client->Server 0x0327 (size 0) packet On Live as of April 2 2012
struct MercenaryDataUpdate_Struct {
/*0000*/ sint32 MercStatus; // Seen 0 with merc and -1 with no merc hired
/*0004*/ int32 MercCount; // Seen 1 with 1 merc hired and 0 with no merc hired
/*0008*/ MercenaryData_Struct MercData[0]; // Data for individual mercenaries in the Merchant List
};
// [OPCode: 0x6537] On Live as of April 2 2012 [Server->Client]
// Size 12 and sent on Zone-In if no mercenary is currently hired and when merc is dismissed
// (Same packet as MercAssign_Struct?)
struct NoMercenaryHired_Struct {
/*0000*/ sint32 MercStatus; // Seen -1 with no merc hired
/*0004*/ int32 MercCount; // Seen 0 with no merc hired
/*0008*/ int32 MercID; // Seen 1 when no merc is hired - ID unique to each type of mercenary
/*0012*/
};
// OP_MercenaryAssign (Same packet as NoMercenaryHired_Struct?)
struct MercenaryAssign_Struct {
/*0000*/ int32 MercEntityID; // Seen 0 (no merc spawned) or 615843841 and 22779137
/*0004*/ int32 MercUnk01; //
/*0008*/ int32 MercUnk02; //
/*0012*/
};
// [OPCode: 0x495d OP_MercenaryTimer] On Live as of April 2 2012 [Server->Client] [Size: 20]
// Sent on Zone-In, or after Dismissing, Suspending, or Unsuspending Mercs
struct MercenaryStatus_Struct {
/*0000*/ int32 MercEntityID; // Seen 0 (no merc spawned) or 615843841 and 22779137
/*0004*/ int32 UpdateInterval; // Seen 900000 - Matches from 0x6537 packet (15 minutes in ms?)
/*0008*/ int32 MercUnk01; // Seen 180000 - 3 minutes in milleseconds? Maybe next update interval?
/*0012*/ int32 MercState; // Seen 5 (normal) or 1 (suspended)
/*0016*/ int32 SuspendedTime; // Seen 0 (not suspended) or c9 c2 64 4f (suspended on Sat Mar 17 11:58:49 2012) - Unix Timestamp
/*0020*/
};
// [OPCode: 0x4c6c] On Live as of April 2 2012 [Client->Server] [Size: 8]
// Sent from the client when using the Mercenary Window
struct MercenaryCommand_Struct {
/*0000*/ int32 MercCommand; // Seen 0 (zone in with no merc or suspended), 1 (dismiss merc), 5 (normal state), 36 (zone in with merc)
/*0004*/ sint32 Option; // Seen -1 (zone in with no merc), 0 (setting to passive stance), 1 (normal or setting to balanced stance)
/*0008*/
};
// [OPCode: 0x1a79] On Live as of April 2 2012 [Client->Server] [Size: 1]
// Requesting to suspend or unsuspend merc
struct SuspendMercenary_Struct {
/*0000*/ int8 SuspendMerc; // Seen 30 (48) for suspending or unsuspending
/*0001*/
};
// [OPCode: 0x2528] On Live as of April 2 2012 [Server->Client] [Size: 4]
// Response to suspend merc with timestamp
struct SuspendMercenaryResponse_Struct {
/*0000*/ int32 SuspendTime; // Unix Timestamp - Seen a9 11 78 4f
/*0004*/
};
// [OPCode: 0x5e78 (OP_MercenaryHire?)] On Live as of April 2 2012
// Sent by client when requesting to view Mercenary info or Hire a Mercenary
struct MercenaryMerchantRequest_Struct {
/*0000*/ int32 MercID; // Seen 399 and 400 for merc ID
/*0004*/ int32 MercUnk01; // Seen 1
/*0008*/ int32 MercMerchantID; // Entity ID for Mercenary Merchant
/*0012*/ int32 MercUnk02; // Seen 65302016 (00 6e e4 03) - (probably actually individual int8 fields)
/*0016*/
};
// [OPCode: 0x5e78 (OP_MercenaryHire?)] On Live as of April 2 2012
// Sent by Server in response to requesting to view Mercenary info or Hire a Mercenary
struct MercenaryMerchantResponse_Struct {
/*0000*/ int32 ResponseType; // Seen 0 for hire response, 6 for info response, and 9 for denied hire request
/*0004*/
};