Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Server Code Submissions

Reply
 
Thread Tools Display Modes
  #1  
Old 11-28-2012, 11:13 PM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default Fix for Corpse Slot Population and Power Source Auto-Inventory

This patch addresses the issue of corpse window slots not being fully populated and power source items not being auto-inventoried.


In the corpse slots, I adjusted the translators to allow relevent enumerated client slots to be accessed. The SoF translator was off by one already and that's
where that weird clicking issue I was having came from. I also tweaked Corpse::QueryLoot, accessed through '#corpse inspectloot,' to display accordingly
as well.

The other issue was with auto-looting a power source item. It never went into the power source slot. The looting procedure didn't include this slot and I added
it to the check with a client verifier to avoid possible titanium crashes.


These should work with at least SoD and UF clients since they use the same slot assignments. It tested ok with SoF, but really should be tested with the other
three clients as well.


[CorpseLoot-PowerSource.patch]
Code:
Index: common/patches/SoD.cpp
===================================================================
--- common/patches/SoD.cpp	(revision 2267)
+++ common/patches/SoD.cpp	(working copy)
@@ -108,7 +108,7 @@
 static inline int32 TitaniumToSoDSlot(int32 TitaniumSlot) {
 	int32 SoDSlot = 0;
 
-	if(TitaniumSlot >= 21 && TitaniumSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(TitaniumSlot >= 21 && TitaniumSlot <= 53)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		SoDSlot = TitaniumSlot + 1;
 	}
@@ -140,7 +140,7 @@
 static inline int32 SoDToTitaniumSlot(int32 SoDSlot) {
 	int32 TitaniumSlot = 0;
 	
-	if(SoDSlot >= 22 && SoDSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(SoDSlot >= 22 && SoDSlot <= 54)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		TitaniumSlot = SoDSlot - 1;
 	}
Index: common/patches/SoF.cpp
===================================================================
--- common/patches/SoF.cpp	(revision 2267)
+++ common/patches/SoF.cpp	(working copy)
@@ -108,7 +108,7 @@
 static inline int32 TitaniumToSoFSlot(int32 TitaniumSlot) {
 	int32 SoFSlot = 0;
 
-	if(TitaniumSlot >= 21 && TitaniumSlot <= 50)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(TitaniumSlot >= 21 && TitaniumSlot <= 53)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		SoFSlot = TitaniumSlot + 1;
 	}
@@ -140,7 +140,7 @@
 static inline int32 SoFToTitaniumSlot(int32 SoFSlot) {
 	int32 TitaniumSlot = 0;
 	
-	if(SoFSlot >= 22 && SoFSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(SoFSlot >= 22 && SoFSlot <= 54)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		TitaniumSlot = SoFSlot - 1;
 	}
Index: common/patches/Underfoot.cpp
===================================================================
--- common/patches/Underfoot.cpp	(revision 2267)
+++ common/patches/Underfoot.cpp	(working copy)
@@ -109,7 +109,7 @@
 static inline int32 TitaniumToUnderfootSlot(int32 TitaniumSlot) {
 	int32 UnderfootSlot = 0;
 
-	if(TitaniumSlot >= 21 && TitaniumSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(TitaniumSlot >= 21 && TitaniumSlot <= 53)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		UnderfootSlot = TitaniumSlot + 1;
 	}
@@ -141,7 +141,7 @@
 static inline int32 UnderfootToTitaniumSlot(int32 UnderfootSlot) {
 	int32 TitaniumSlot = 0;
 	
-	if(UnderfootSlot >= 22 && UnderfootSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(UnderfootSlot >= 22 && UnderfootSlot <= 54)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		TitaniumSlot = UnderfootSlot - 1;
 	}
Index: zone/inventory.cpp
===================================================================
--- zone/inventory.cpp	(revision 2267)
+++ zone/inventory.cpp	(working copy)
@@ -580,8 +580,13 @@
 	// #1: Try to auto equip
 	if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && !inst.GetItem()->Attuneable && inst.GetItem()->ItemType != ItemTypeAugment)
 	{
-		for (sint16 i = 0; i < 22; i++)
+		for (sint16 i = 0; i < 9999; i++) // originally (i < 22)
 		{
+			if (i == 22) {
+				if(this->GetClientVersion() >= EQClientSoF) { i = 9999; } // added power source check for SoF+ clients
+				else { break; }
+			}
+
 			if (!m_inv[i])
 			{
 				if( i == SLOT_PRIMARY && inst.IsWeapon() ) // If item is primary slot weapon
Index: zone/PlayerCorpse.cpp
===================================================================
--- zone/PlayerCorpse.cpp	(revision 2267)
+++ zone/PlayerCorpse.cpp	(working copy)
@@ -366,8 +366,12 @@
 		// worn + inventory + cursor
         std::list<uint32> removed_list;
         bool cursor = false;
-		for(i = 0; i <= 30; i++)
+		for(i = 0; i <= 31; i++)
 		{
+			if(i == 31) {
+				if(client->GetClientVersion() >= EQClientSoF) { i = 9999; }
+				else { break; }
+			}
 			item = client->GetInv().GetItem(i);
 			if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent))
 			{
@@ -445,7 +449,7 @@
    // Qualified bag slot iterations. processing bag slots that don't exist is probably not a good idea.
    if(item->IsType(ItemClassContainer) && ((equipslot >= 22 && equipslot <=30))) // Limit the bag check to inventory and cursor slots.
 	{
-		for(bagindex = 0; bagindex <= 10; bagindex++)
+		for(bagindex = 0; bagindex <= 9; bagindex++)
 		{
          // For empty bags in cursor queue, slot was previously being resolved as SLOT_INVALID (-1)
 			interior_slot = Inventory::CalcSlotId(equipslot, bagindex);
@@ -454,7 +458,7 @@
 			if(interior_item)
 			{
 				AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4));
-            returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex));
+				returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex));
 				client->DeleteItemInInventory(interior_slot, 0, true, false);
 			}
 		}
@@ -1004,27 +1008,11 @@
 		cur = itemlist.begin();
 		end = itemlist.end();
 
-      int corpselootlimit = 30; // 30 is the original value // con check value in QueryLoot needs to reflect this value
+		int corpselootlimit;
       
-      /* need actual corpse limit values per client (or client range)..if always 30, then these con checks are unneeded
-      // enumeration shouldn't be needed unless someone finds a use for this info elsewhere
-      
-      if (client->GetClientVersion()>=EQClientVoA)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientHoT)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientUnderfoot)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientSoD)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientSoF) // SoF has 32 visible slots..change untested
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientTitanium)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClient62)
-         corpselootlimit=30;
-      else
-         corpselootlimit=30; // */
+		if (client->GetClientVersion() >= EQClientSoF) { corpselootlimit = 32; }
+		else if (client->GetClientVersion() == EQClientTitanium) { corpselootlimit = 31; }
+		else { corpselootlimit = 30; }
 
 		for(; cur != end; cur++) {
 			ServerLootItem_Struct* item_data = *cur;
@@ -1033,10 +1021,11 @@
          // Dont display the item if it's in a bag
 
          // Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse.
-         if(!IsPlayerCorpse() || item_data->equipSlot <= 30 || tCanLoot>=3 ||
+		 // A Power Source item viewed on a corpse by a Titanium client hopefully won't crash it.
+         if(!IsPlayerCorpse() || item_data->equipSlot <= 30 || item_data->equipSlot == 9999 || tCanLoot>=3 || 
             (item_data->equipSlot >= 8000 && item_data->equipSlot <= 8999))
 			{
-            if (i < corpselootlimit) // < 30 (0 - 29)
+            if (i < corpselootlimit)
 				{
 					item = database.GetItem(item_data->item_id);
 					if (client && item)
@@ -1050,15 +1039,15 @@
 						item_data->lootslot = i;
 					}
 				}
-            else if (i == corpselootlimit) // = 30
+            else if (i == corpselootlimit)
             {
-               client->Message(13, "*** This corpse contains more items than can be displayed! ***");
+               client->Message(15, "*** This corpse contains more items than can be displayed! ***");
                client->Message(0, "Remove items and re-loot corpse to access remaining inventory.");
             }
 				i++;
 			}
 		}
-      if (i > corpselootlimit) // > 30 (remember 'i' is increased again after the last iteration, so no '=')
+      if (i > corpselootlimit) // (remember 'i' is increased again after the last iteration, so no '=')
          client->Message(0, "(%s contains %i additional %s.)", GetName(), (i-corpselootlimit), (i-corpselootlimit)==1?"item":"items");
 
       if (IsPlayerCorpse() && i == 0 && itemlist.size() > 0) { // somehow, corpse contains items, but client doesn't see them...
@@ -1355,12 +1344,20 @@
 }
 
 void Corpse::QueryLoot(Client* to) {
-   int x = 0, y = 0; // x = visible items, y = total items
-	to->Message(0, "Coin: %ip %ig %is %ic", platinum, gold, silver, copper);
 
+	int x = 0, y = 0; // x = visible items, y = total items
+	to->Message(0, "Coin: %ip, %ig, %is, %ic", platinum, gold, silver, copper);
+
 	ItemList::iterator cur,end;
 	cur = itemlist.begin();
 	end = itemlist.end();
+
+	int corpselootlimit;
+      
+	if (to->GetClientVersion() >= EQClientSoF) { corpselootlimit = 32; }
+	else if (to->GetClientVersion() == EQClientTitanium) { corpselootlimit = 31; }
+	else { corpselootlimit = 30; }
+
 	for(; cur != end; cur++) {
 		ServerLootItem_Struct* sitem = *cur;
 
@@ -1368,14 +1365,14 @@
          if (sitem->equipSlot >= 251 && sitem->equipSlot <= 340)
             sitem->lootslot = 0xFFFF;
          else
-            x < 30 ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; // this con value needs to reflect corpselootlimit in MakeLootRequestPackets
+            x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF;
          
          const Item_Struct* item = database.GetItem(sitem->item_id);
 
          if (item)
-            to->Message((sitem->lootslot == 0xFFFF), "  LootSlot: %i (EquipSlot: %i) Item: %s (%d) with %i %s", sitem->lootslot, sitem->equipSlot, item->Name, item->ID, sitem->charges, sitem->charges==1?"charge":"charges");
+            to->Message((sitem->lootslot == 0xFFFF), "LootSlot: %i (EquipSlot: %i) Item: %s (%d), Count: %i", static_cast<sint16>(sitem->lootslot), sitem->equipSlot, item->Name, item->ID, sitem->charges);
          else
-            to->Message((sitem->lootslot == 0xFFFF), "  Error: 0x%04x", sitem->item_id);
+            to->Message((sitem->lootslot == 0xFFFF), "Error: 0x%04x", sitem->item_id);
          
          if (sitem->lootslot != 0xFFFF)
             x++;
@@ -1387,9 +1384,9 @@
          const Item_Struct* item = database.GetItem(sitem->item_id);
          
          if (item)
-            to->Message(0, "  LootSlot: %i Item: %s (%d) with %i %s", sitem->lootslot, item->Name, item->ID, sitem->charges, sitem->charges==1?"charge":"charges");
+            to->Message(0, "LootSlot: %i Item: %s (%d), Count: %i", sitem->lootslot, item->Name, item->ID, sitem->charges);
          else
-            to->Message(0, "  Error: 0x%04x", sitem->item_id);
+            to->Message(0, "Error: 0x%04x", sitem->item_id);
 
          y++;
       }
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #2  
Old 11-29-2012, 11:51 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

Ok, I THINK that I've got a working patch for the character inspect issue as well. (This issue is what led me to this patch line.) It does work for SoF, which means
the SoD and Underfoot changes should work as well. I've attempted to add ENCODE and DECODE functions to the Titanium module, but was not able to test
it for proper operation. (TRANSLATION: The Titanium client needs to be tested for proper operation with this patch.)


In short, I changed the server struct to use the SoF+ model and enabled the Power Source code in Client::ProcessInspectRequest(), with proper changes.

I also revamped the ENCODE/DECODE functions in the SoF+ modules to properly swap the correct slot numbers. (It was kinda messy before.)

In the Titanium module, I did a direct copy for the appropriate slots for the ENCODE and inserted nullchar and -1 (as C::PIR() does) into the DECODE
procedure. (It shouldn't need the OP_InspectRequest code since it wasn't needed before.)


NOTE: Since the HoT and VoA translators are not active at this time, I have not modifed any code in these modules. This will need to be addressed once those
clients become active.


[Cumulative Corpse-Power.patch]
Code:
Index: common/eq_packet_structs.h
===================================================================
--- common/eq_packet_structs.h	(revision 2271)
+++ common/eq_packet_structs.h	(working copy)
@@ -2283,15 +2283,16 @@
 	int16 TargetID;
 	int16 PlayerID;
 };
-//OP_InspectAnswer
-struct InspectResponse_Struct{//Cofruben:need to send two of this for the inspect response.
+//OP_InspectAnswer - Size: 1860
+struct InspectResponse_Struct{
 /*000*/	int32 TargetID;
 /*004*/	int32 playerid;
-/*008*/	char itemnames[21][64];
-/*1352*/char unknown_zero[64];//fill with zero's.
-/*1416*/int32 itemicons[21];
-/*1500*/int32 unknown_zero2;
-/*1504*/char text[288];
+/*008*/	char itemnames[22][64];
+/*1416*/char unknown_zero[64];
+/*1480*/int32 itemicons[22];
+/*1568*/int32 unknown_zero2;
+/*1572*/char text[288];	// Max number of chars in Inspect Window appears to be 254
+/*1860*/
 };
 
 //OP_SetDataRate
Index: common/patches/SoD.cpp
===================================================================
--- common/patches/SoD.cpp	(revision 2271)
+++ common/patches/SoD.cpp	(working copy)
@@ -108,7 +108,7 @@
 static inline int32 TitaniumToSoDSlot(int32 TitaniumSlot) {
 	int32 SoDSlot = 0;
 
-	if(TitaniumSlot >= 21 && TitaniumSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(TitaniumSlot >= 21 && TitaniumSlot <= 53)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		SoDSlot = TitaniumSlot + 1;
 	}
@@ -140,7 +140,7 @@
 static inline int32 SoDToTitaniumSlot(int32 SoDSlot) {
 	int32 TitaniumSlot = 0;
 	
-	if(SoDSlot >= 22 && SoDSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(SoDSlot >= 22 && SoDSlot <= 54)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		TitaniumSlot = SoDSlot - 1;
 	}
@@ -2056,7 +2056,7 @@
 		strn0cpy(eq->itemnames[r], emu->itemnames[r], sizeof(eq->itemnames[r]));
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	strn0cpy(eq->itemnames[21], emu->itemnames[22], sizeof(eq->itemnames[21]));
+	strn0cpy(eq->itemnames[21], emu->unknown_zero, sizeof(eq->itemnames[21]));
 	strn0cpy(eq->unknown_zero, emu->itemnames[21], sizeof(eq->unknown_zero));
 
 	int k;
@@ -2064,7 +2064,7 @@
 		OUT(itemicons[k]);
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	eq->itemicons[21] = emu->itemicons[22];
+	eq->itemicons[21] = emu->unknown_zero2;
 	eq->unknown_zero2 = emu->itemicons[21];
 	strn0cpy(eq->text, emu->text, sizeof(eq->text));
 
@@ -2473,20 +2473,17 @@
 		strn0cpy(emu->itemnames[r], eq->itemnames[r], sizeof(emu->itemnames[r]));
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	strn0cpy(emu->itemnames[22], eq->itemnames[21], sizeof(emu->itemnames[22]));
+	strn0cpy(emu->unknown_zero, eq->itemnames[21], sizeof(emu->unknown_zero));
 	strn0cpy(emu->itemnames[21], eq->unknown_zero, sizeof(emu->itemnames[21]));
-	strn0cpy(emu->unknown_zero, eq->unknown_zero, sizeof(emu->unknown_zero));
 
 	int k;
 	for (k = 0; k < 21; k++) {
 		IN(itemicons[k]);
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	emu->itemicons[22] = eq->itemicons[21];
+	emu->unknown_zero2 = eq->itemicons[21];
 	emu->itemicons[21] = eq->unknown_zero2;
-	emu->unknown_zero2 = eq->unknown_zero2;
 	strn0cpy(emu->text, eq->text, sizeof(emu->text));
-	//emu->unknown1772 = 0;
 
 	FINISH_DIRECT_DECODE();
 }
Index: common/patches/SoF.cpp
===================================================================
--- common/patches/SoF.cpp	(revision 2271)
+++ common/patches/SoF.cpp	(working copy)
@@ -108,7 +108,7 @@
 static inline int32 TitaniumToSoFSlot(int32 TitaniumSlot) {
 	int32 SoFSlot = 0;
 
-	if(TitaniumSlot >= 21 && TitaniumSlot <= 50)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(TitaniumSlot >= 21 && TitaniumSlot <= 53)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		SoFSlot = TitaniumSlot + 1;
 	}
@@ -140,7 +140,7 @@
 static inline int32 SoFToTitaniumSlot(int32 SoFSlot) {
 	int32 TitaniumSlot = 0;
 	
-	if(SoFSlot >= 22 && SoFSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(SoFSlot >= 22 && SoFSlot <= 54)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		TitaniumSlot = SoFSlot - 1;
 	}
@@ -1771,7 +1771,7 @@
 		strn0cpy(eq->itemnames[r], emu->itemnames[r], sizeof(eq->itemnames[r]));
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	strn0cpy(eq->itemnames[21], emu->itemnames[22], sizeof(eq->itemnames[21]));
+	strn0cpy(eq->itemnames[21], emu->unknown_zero, sizeof(eq->itemnames[21]));
 	strn0cpy(eq->unknown_zero, emu->itemnames[21], sizeof(eq->unknown_zero));
 
 	int k;
@@ -1779,7 +1779,7 @@
 		OUT(itemicons[k]);
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	eq->itemicons[21] = emu->itemicons[22];
+	eq->itemicons[21] = emu->unknown_zero2;
 	eq->unknown_zero2 = emu->itemicons[21];
 	strn0cpy(eq->text, emu->text, sizeof(eq->text));
 
@@ -2003,20 +2003,17 @@
 		strn0cpy(emu->itemnames[r], eq->itemnames[r], sizeof(emu->itemnames[r]));
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	strn0cpy(emu->itemnames[22], eq->itemnames[21], sizeof(emu->itemnames[22]));
+	strn0cpy(emu->unknown_zero, eq->itemnames[21], sizeof(emu->unknown_zero));
 	strn0cpy(emu->itemnames[21], eq->unknown_zero, sizeof(emu->itemnames[21]));
-	strn0cpy(emu->unknown_zero, eq->unknown_zero, sizeof(emu->unknown_zero));
 
 	int k;
 	for (k = 0; k < 21; k++) {
 		IN(itemicons[k]);
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	emu->itemicons[22] = eq->itemicons[21];
+	emu->unknown_zero2 = eq->itemicons[21];
 	emu->itemicons[21] = eq->unknown_zero2;
-	emu->unknown_zero2 = eq->unknown_zero2;
 	strn0cpy(emu->text, eq->text, sizeof(emu->text));
-	//emu->unknown1772 = 0;
 
 	FINISH_DIRECT_DECODE();
 }
Index: common/patches/Titanium.cpp
===================================================================
--- common/patches/Titanium.cpp	(revision 2271)
+++ common/patches/Titanium.cpp	(working copy)
@@ -916,6 +916,31 @@
 	delete[] __emu_buffer;
 }
 
+ENCODE(OP_InspectAnswer) {
+	ENCODE_LENGTH_EXACT(InspectResponse_Struct);
+	SETUP_DIRECT_ENCODE(InspectResponse_Struct, structs::InspectResponse_Struct);
+
+	OUT(TargetID);
+	OUT(playerid);
+
+	int r;
+	for (r = 0; r < 20; r++) {
+		strn0cpy(eq->itemnames[r], emu->itemnames[r], sizeof(eq->itemnames[r]));
+	}
+
+	strn0cpy(eq->unknown_zero, emu->itemnames[20], sizeof(eq->unknown_zero));
+
+	int k;
+	for (k = 0; k < 20; k++) {
+		OUT(itemicons[k]);
+	}
+
+	eq->unknown_zero2 = emu->itemicons[20];
+	strn0cpy(eq->text, emu->text, sizeof(eq->text));
+
+	FINISH_ENCODE();
+}
+
 ENCODE(OP_RespondAA) {
 	ENCODE_LENGTH_EXACT(AATable_Struct);
 	SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct);
@@ -1131,6 +1156,33 @@
 	FINISH_ENCODE();
 }
 
+DECODE(OP_InspectAnswer) {
+	DECODE_LENGTH_EXACT(structs::InspectResponse_Struct);
+	SETUP_DIRECT_DECODE(InspectResponse_Struct, structs::InspectResponse_Struct);
+	
+	IN(TargetID);
+	IN(playerid);
+
+	int r;
+	for (r = 0; r < 21; r++) {
+		strn0cpy(emu->itemnames[r], eq->itemnames[r], sizeof(emu->itemnames[r]));
+	}
+
+	strn0cpy(emu->itemnames[21], eq->unknown_zero, sizeof(emu->itemnames[21]));
+	strn0cpy(emu->unknown_zero, "", sizeof(emu->unknown_zero));
+	
+	int k;
+	for (k = 0; k < 21; k++) {
+		IN(itemicons[k]);
+	}
+
+	emu->itemicons[21] = eq->unknown_zero2;
+	emu->unknown_zero2 = 0xFFFFFFFF;
+	strn0cpy(emu->text, eq->text, sizeof(emu->text));
+
+	FINISH_DIRECT_DECODE();
+}
+
 ENCODE(OP_LFGuild)
 {
 	EQApplicationPacket *in = *p;
Index: common/patches/Titanium_ops.h
===================================================================
--- common/patches/Titanium_ops.h	(revision 2271)
+++ common/patches/Titanium_ops.h	(working copy)
@@ -19,6 +19,7 @@
 E(OP_ReadBook)
 E(OP_Illusion)
 E(OP_VetRewardsAvaliable)
+E(OP_InspectAnswer)
 E(OP_Track)
 E(OP_RespondAA)
 E(OP_DeleteSpawn)
@@ -43,6 +44,7 @@
 D(OP_WhoAllRequest)
 D(OP_ReadBook)
 D(OP_FaceChange)
+D(OP_InspectAnswer)
 D(OP_WearChange)
 D(OP_LFGuild)
 #undef E
Index: common/patches/Underfoot.cpp
===================================================================
--- common/patches/Underfoot.cpp	(revision 2271)
+++ common/patches/Underfoot.cpp	(working copy)
@@ -109,7 +109,7 @@
 static inline int32 TitaniumToUnderfootSlot(int32 TitaniumSlot) {
 	int32 UnderfootSlot = 0;
 
-	if(TitaniumSlot >= 21 && TitaniumSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(TitaniumSlot >= 21 && TitaniumSlot <= 53)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		UnderfootSlot = TitaniumSlot + 1;
 	}
@@ -141,7 +141,7 @@
 static inline int32 UnderfootToTitaniumSlot(int32 UnderfootSlot) {
 	int32 TitaniumSlot = 0;
 	
-	if(UnderfootSlot >= 22 && UnderfootSlot <= 51)	// Cursor/Ammo/Power Source and Normal Inventory Slots
+	if(UnderfootSlot >= 22 && UnderfootSlot <= 54)	// Cursor/Ammo/Power Source and Normal Inventory Slots
 	{
 		TitaniumSlot = UnderfootSlot - 1;
 	}
@@ -2116,7 +2116,7 @@
 		strn0cpy(eq->itemnames[r], emu->itemnames[r], sizeof(eq->itemnames[r]));
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	strn0cpy(eq->itemnames[21], emu->itemnames[22], sizeof(eq->itemnames[21]));
+	strn0cpy(eq->itemnames[21], emu->unknown_zero, sizeof(eq->itemnames[21]));
 	strn0cpy(eq->unknown_zero, emu->itemnames[21], sizeof(eq->unknown_zero));
 
 	int k;
@@ -2124,7 +2124,7 @@
 		OUT(itemicons[k]);
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	eq->itemicons[21] = emu->itemicons[22];
+	eq->itemicons[21] = emu->unknown_zero2;
 	eq->unknown_zero2 = emu->itemicons[21];
 	strn0cpy(eq->text, emu->text, sizeof(eq->text));
 
@@ -2743,20 +2743,17 @@
 		strn0cpy(emu->itemnames[r], eq->itemnames[r], sizeof(emu->itemnames[r]));
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	strn0cpy(emu->itemnames[22], eq->itemnames[21], sizeof(emu->itemnames[22]));
+	strn0cpy(emu->unknown_zero, eq->itemnames[21], sizeof(emu->unknown_zero));
 	strn0cpy(emu->itemnames[21], eq->unknown_zero, sizeof(emu->itemnames[21]));
-	strn0cpy(emu->unknown_zero, eq->unknown_zero, sizeof(emu->unknown_zero));
 
 	int k;
 	for (k = 0; k < 21; k++) {
 		IN(itemicons[k]);
 	}
 	// Swap last 2 slots for Arrow and Power Source
-	emu->itemicons[22] = eq->itemicons[21];
+	emu->unknown_zero2 = eq->itemicons[21];
 	emu->itemicons[21] = eq->unknown_zero2;
-	emu->unknown_zero2 = eq->unknown_zero2;
 	strn0cpy(emu->text, eq->text, sizeof(emu->text));
-	//emu->unknown1772 = 0;
 
 	FINISH_DIRECT_DECODE();
 }
Index: zone/client.cpp
===================================================================
--- zone/client.cpp	(revision 2271)
+++ zone/client.cpp	(working copy)
@@ -5524,21 +5524,22 @@
 					insr->itemicons[L] = 0xFFFFFFFF;
 			}
 		}
-		/*
+		
 		// Special handling for Power Source slot on SoF clients
+		// The ENCODE/DECODE functions in \Patches\Titanium.cpp will probably allow us to drop the client check here -U
 		if(requestee->GetClientVersion() >= EQClientSoF && requester->GetClientVersion() >= EQClientSoF) {
 			const ItemInst* inst = requestee->GetInv().GetItem(9999);
 			if(inst) {
 				item = inst->GetItem();
 				if(item) {
-					strcpy(insr->itemnames[22], item->Name);
-					insr->itemicons[22] = item->Icon;
+					strcpy(insr->unknown_zero, item->Name);
+					insr->unknown_zero2 = item->Icon;
 				}
 				else
-					insr->itemicons[22] = 0xFFFFFFFF;
+					insr->unknown_zero2 = 0xFFFFFFFF;
 			}
 		}
-		*/
+		
 
 		//Need to add the player inspect notes code here at some point...
 
Index: zone/inventory.cpp
===================================================================
--- zone/inventory.cpp	(revision 2271)
+++ zone/inventory.cpp	(working copy)
@@ -580,8 +580,13 @@
 	// #1: Try to auto equip
 	if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && !inst.GetItem()->Attuneable && inst.GetItem()->ItemType != ItemTypeAugment)
 	{
-		for (sint16 i = 0; i < 22; i++)
+		for (sint16 i = 0; i < 9999; i++) // originally (i < 22)
 		{
+			if (i == 22) {
+				if(this->GetClientVersion() >= EQClientSoF) { i = 9999; } // added power source check for SoF+ clients
+				else { break; }
+			}
+
 			if (!m_inv[i])
 			{
 				if( i == SLOT_PRIMARY && inst.IsWeapon() ) // If item is primary slot weapon
Index: zone/PlayerCorpse.cpp
===================================================================
--- zone/PlayerCorpse.cpp	(revision 2271)
+++ zone/PlayerCorpse.cpp	(working copy)
@@ -366,8 +366,12 @@
 		// worn + inventory + cursor
         std::list<uint32> removed_list;
         bool cursor = false;
-		for(i = 0; i <= 30; i++)
+		for(i = 0; i <= 31; i++)
 		{
+			if(i == 31) {
+				if(client->GetClientVersion() >= EQClientSoF) { i = 9999; }
+				else { break; }
+			}
 			item = client->GetInv().GetItem(i);
 			if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent))
 			{
@@ -445,7 +449,7 @@
    // Qualified bag slot iterations. processing bag slots that don't exist is probably not a good idea.
    if(item->IsType(ItemClassContainer) && ((equipslot >= 22 && equipslot <=30))) // Limit the bag check to inventory and cursor slots.
 	{
-		for(bagindex = 0; bagindex <= 10; bagindex++)
+		for(bagindex = 0; bagindex <= 9; bagindex++)
 		{
          // For empty bags in cursor queue, slot was previously being resolved as SLOT_INVALID (-1)
 			interior_slot = Inventory::CalcSlotId(equipslot, bagindex);
@@ -454,7 +458,7 @@
 			if(interior_item)
 			{
 				AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4));
-            returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex));
+				returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex));
 				client->DeleteItemInInventory(interior_slot, 0, true, false);
 			}
 		}
@@ -1004,27 +1008,11 @@
 		cur = itemlist.begin();
 		end = itemlist.end();
 
-      int corpselootlimit = 30; // 30 is the original value // con check value in QueryLoot needs to reflect this value
+		int corpselootlimit;
       
-      /* need actual corpse limit values per client (or client range)..if always 30, then these con checks are unneeded
-      // enumeration shouldn't be needed unless someone finds a use for this info elsewhere
-      
-      if (client->GetClientVersion()>=EQClientVoA)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientHoT)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientUnderfoot)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientSoD)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientSoF) // SoF has 32 visible slots..change untested
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClientTitanium)
-         corpselootlimit=30;
-      else if (client->GetClientVersion()>=EQClient62)
-         corpselootlimit=30;
-      else
-         corpselootlimit=30; // */
+		if (client->GetClientVersion() >= EQClientSoF) { corpselootlimit = 32; }
+		else if (client->GetClientVersion() == EQClientTitanium) { corpselootlimit = 31; }
+		else { corpselootlimit = 30; }
 
 		for(; cur != end; cur++) {
 			ServerLootItem_Struct* item_data = *cur;
@@ -1033,10 +1021,11 @@
          // Dont display the item if it's in a bag
 
          // Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse.
-         if(!IsPlayerCorpse() || item_data->equipSlot <= 30 || tCanLoot>=3 ||
+		 // A Power Source item viewed on a corpse by a Titanium client hopefully won't crash it.
+         if(!IsPlayerCorpse() || item_data->equipSlot <= 30 || item_data->equipSlot == 9999 || tCanLoot>=3 || 
             (item_data->equipSlot >= 8000 && item_data->equipSlot <= 8999))
 			{
-            if (i < corpselootlimit) // < 30 (0 - 29)
+            if (i < corpselootlimit)
 				{
 					item = database.GetItem(item_data->item_id);
 					if (client && item)
@@ -1050,15 +1039,15 @@
 						item_data->lootslot = i;
 					}
 				}
-            else if (i == corpselootlimit) // = 30
+            else if (i == corpselootlimit)
             {
-               client->Message(13, "*** This corpse contains more items than can be displayed! ***");
+               client->Message(15, "*** This corpse contains more items than can be displayed! ***");
                client->Message(0, "Remove items and re-loot corpse to access remaining inventory.");
             }
 				i++;
 			}
 		}
-      if (i > corpselootlimit) // > 30 (remember 'i' is increased again after the last iteration, so no '=')
+      if (i > corpselootlimit) // (remember 'i' is increased again after the last iteration, so no '=')
          client->Message(0, "(%s contains %i additional %s.)", GetName(), (i-corpselootlimit), (i-corpselootlimit)==1?"item":"items");
 
       if (IsPlayerCorpse() && i == 0 && itemlist.size() > 0) { // somehow, corpse contains items, but client doesn't see them...
@@ -1355,12 +1344,20 @@
 }
 
 void Corpse::QueryLoot(Client* to) {
-   int x = 0, y = 0; // x = visible items, y = total items
-	to->Message(0, "Coin: %ip %ig %is %ic", platinum, gold, silver, copper);
 
+	int x = 0, y = 0; // x = visible items, y = total items
+	to->Message(0, "Coin: %ip, %ig, %is, %ic", platinum, gold, silver, copper);
+
 	ItemList::iterator cur,end;
 	cur = itemlist.begin();
 	end = itemlist.end();
+
+	int corpselootlimit;
+      
+	if (to->GetClientVersion() >= EQClientSoF) { corpselootlimit = 32; }
+	else if (to->GetClientVersion() == EQClientTitanium) { corpselootlimit = 31; }
+	else { corpselootlimit = 30; }
+
 	for(; cur != end; cur++) {
 		ServerLootItem_Struct* sitem = *cur;
 
@@ -1368,14 +1365,14 @@
          if (sitem->equipSlot >= 251 && sitem->equipSlot <= 340)
             sitem->lootslot = 0xFFFF;
          else
-            x < 30 ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; // this con value needs to reflect corpselootlimit in MakeLootRequestPackets
+            x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF;
          
          const Item_Struct* item = database.GetItem(sitem->item_id);
 
          if (item)
-            to->Message((sitem->lootslot == 0xFFFF), "  LootSlot: %i (EquipSlot: %i) Item: %s (%d) with %i %s", sitem->lootslot, sitem->equipSlot, item->Name, item->ID, sitem->charges, sitem->charges==1?"charge":"charges");
+            to->Message((sitem->lootslot == 0xFFFF), "LootSlot: %i (EquipSlot: %i) Item: %s (%d), Count: %i", static_cast<sint16>(sitem->lootslot), sitem->equipSlot, item->Name, item->ID, sitem->charges);
          else
-            to->Message((sitem->lootslot == 0xFFFF), "  Error: 0x%04x", sitem->item_id);
+            to->Message((sitem->lootslot == 0xFFFF), "Error: 0x%04x", sitem->item_id);
          
          if (sitem->lootslot != 0xFFFF)
             x++;
@@ -1387,9 +1384,9 @@
          const Item_Struct* item = database.GetItem(sitem->item_id);
          
          if (item)
-            to->Message(0, "  LootSlot: %i Item: %s (%d) with %i %s", sitem->lootslot, item->Name, item->ID, sitem->charges, sitem->charges==1?"charge":"charges");
+            to->Message(0, "LootSlot: %i Item: %s (%d), Count: %i", sitem->lootslot, item->Name, item->ID, sitem->charges);
          else
-            to->Message(0, "  Error: 0x%04x", sitem->item_id);
+            to->Message(0, "Error: 0x%04x", sitem->item_id);
 
          y++;
       }

SIDENOTE: Is possible to change the structs as indicated below? Or does the client explicitly look for the assigned properties? (I can't see any difference
based on offsets...)

Change from this:
Code:
//OP_InspectAnswer - Size: 1860
struct InspectResponse_Struct{
/*000*/	int32 TargetID;
/*004*/	int32 playerid;
/*008*/	char itemnames[22][64];
/*1416*/char unknown_zero[64];
/*1480*/int32 itemicons[22];
/*1568*/int32 unknown_zero2;
/*1572*/char text[288];	// Max number of chars in Inspect Window appears to be 254
/*1860*/
 };
To this:
Code:
//OP_InspectAnswer - Size: 1860
struct InspectResponse_Struct{
/*000*/	int32 TargetID;
/*004*/	int32 playerid;
/*008*/	char itemnames[23][64];
/*1480*/int32 itemicons[23];
/*1572*/char text[288];	// Max number of chars in Inspect Window appears to be 254
/*1860*/
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #3  
Old 11-29-2012, 07:16 PM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,743
Default

Yes, if those unknown members actually are known and used then they should be part of the arrays like your second example. My guess would be that whoever set it up initially never saw any data in those, kept them separate, and set them to zero as the packet captures indicated.
Reply With Quote
  #4  
Old 11-29-2012, 07:49 PM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

kk, thanks for the info!

I'll save the rework for the next overhaul.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #5  
Old 11-30-2012, 11:22 PM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

Anyone testing this patch with a Titanium client will no doubt know that I broke inspect character.

I'll repost the patch once I get it working.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #6  
Old 12-01-2012, 01:42 AM
lerxst2112
Demi-God
 
Join Date: Aug 2010
Posts: 1,743
Default

As far as I know, inspect has been broken on Titanium for a while. There's no encode/decode for it and the struct is the wrong size because of it.

http://www.eqemulator.org/forums/showthread.php?t=35469
Reply With Quote
  #7  
Old 12-01-2012, 02:43 AM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

That was a long time ago..for me anyways... Thanks for bringing this up!

I'll work the logic out tonight and see what happens. If Ti is handled differently than SoF+ clients in regards to where the information comes from, then we may
need two sets of handlers.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #8  
Old 12-02-2012, 10:00 PM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

quick update..

We have been able to get the power source slot to show up on SoF+ clients.

We have also been able to get SoF+ clients to properly inspect Ti clients... Unfortunately, the reverse still doesn't work properly.


The power source update will likely be committed soon, but the cross-client update will not until both sides work correctly.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #9  
Old 12-12-2012, 09:21 PM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

Ok, we're getting close to finishing this..sans any issues that may arise.

Cross-client inspects are working properly, to include Ti inspecting bots.

I have also discovered how to fix 'inspect messages' for SoF+ clients. I need to gather a few opcodes and finish the database r/w procedures
before this will be committable.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
  #10  
Old 12-14-2012, 08:48 PM
Uleat's Avatar
Uleat
Developer
 
Join Date: Apr 2012
Location: North Carolina
Posts: 2,815
Default

Inspect messages should now be processed and saved correctly.

When using a Titanium client, these messages are stored on the local computer. No server database entries are made.

For SoF+ clients, inspect messages are saved in the new data field 'inspectmessage' in the 'character_' table.

(If you're message doesn't appear to be updating, try editing your word usage.)


In finishing this line, bots currently do not process power source items, nor do they generate inspect message text. They may be added at a
later date, but they are low priority. Editing commands fall into this category as well.
__________________
Uleat of Bertoxxulous

Compilin' Dirty
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 06:50 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3