EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Server Code Submissions (https://www.eqemulator.org/forums/forumdisplay.php?f=669)
-   -   Fix for Corpse Slot Population and Power Source Auto-Inventory (https://www.eqemulator.org/forums/showthread.php?t=36054)

Uleat 11-28-2012 11:13 PM

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 11-29-2012 11:51 AM

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*/


lerxst2112 11-29-2012 07:16 PM

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.

Uleat 11-29-2012 07:49 PM

kk, thanks for the info!

I'll save the rework for the next overhaul.

Uleat 11-30-2012 11:22 PM

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.

lerxst2112 12-01-2012 01:42 AM

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

Uleat 12-01-2012 02:43 AM

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 12-02-2012 10:00 PM

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 12-12-2012 09:21 PM

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 12-14-2012 08:48 PM

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.


All times are GMT -4. The time now is 01:11 PM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.