From 3c6c5b9732ccb0913c7f1b24491b01d03aab5da7 Mon Sep 17 00:00:00 2001 From: Trevius Date: Fri, 2 Jan 2015 01:42:52 -0600 Subject: [PATCH] (RoF2) *Hopefully* Fixed looting incorrect items from NPCs. Please report any issues! (RoF2) Now able to loot items past the 10th slot on NPC corpses. Attuned Items can now be auto-looted and will equip properly. Mercenaries and Bots will no longer take a share from /split or /autosplit. --- changelog.txt | 6 +++++ common/eq_packet_structs.h | 3 ++- common/patches/rof.cpp | 2 -- common/patches/rof2.cpp | 46 +++++++++++++++++++++-------------- common/patches/rof2_structs.h | 4 +-- zone/client_packet.cpp | 6 ----- zone/corpse.cpp | 2 +- zone/groups.cpp | 3 ++- zone/inventory.cpp | 2 +- 9 files changed, 42 insertions(+), 32 deletions(-) diff --git a/changelog.txt b/changelog.txt index 26bf9c85c..3840c43a4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/02/2015 == +Trevius: (RoF2) *Hopefully* Fixed looting incorrect items from NPCs. Please report any issues! +Trevius: (RoF2) Now able to loot items past the 10th slot on NPC corpses. +Trevius: Attuned Items can now be auto-looted and will equip properly. +Trevius: Mercenaries and Bots will no longer take a share from /split or /autosplit. + == 12/30/2014 == Trevius: (RoF2) Aug Type 21 no longer shows the "Buy Now" button in the aug slot of items. Trevius: (RoF2) Identified the "Copied" item flag with the help of Uleat. diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index a0d9eb59a..07daa97fd 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1509,7 +1509,8 @@ enum ItemPacketType ItemPacketTributeItem = 0x6C, ItemPacketMerchant = 0x64, ItemPacketWorldContainer = 0x6B, - ItemPacketCharmUpdate = 0x6E + ItemPacketCharmUpdate = 0x6E, + ItemPacketInvalid = 0xFF }; struct ItemPacket_Struct { diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index eace95089..699b4e75a 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5485,7 +5485,6 @@ namespace RoF static inline uint32 ServerToRoFCorpseSlot(uint32 ServerCorpse) { - //uint32 RoFCorpse; return (ServerCorpse + 1); } @@ -5626,7 +5625,6 @@ namespace RoF static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse) { - //uint32 ServerCorpse; return (RoFCorpse - 1); } } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 054a2073c..00a468534 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -21,15 +21,15 @@ namespace RoF2 static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth, ItemPacketType packet_type); // server to client inventory location converters - static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot); + static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot, ItemPacketType PacketType = ItemPacketInvalid); static inline structs::MainInvItemSlotStruct ServerToRoF2MainInvSlot(uint32 ServerSlot); static inline uint32 ServerToRoF2CorpseSlot(uint32 ServerCorpse); // client to server inventory location converters - static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot); + static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot, ItemPacketType PacketType = ItemPacketInvalid); static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot); static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse); @@ -622,7 +622,7 @@ namespace RoF2 uint32 Length = 0; - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); + char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0, ItemPacketCharInventory); if (Serialized) { @@ -1436,7 +1436,7 @@ namespace RoF2 InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); uint32 length; - char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); + char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0, old_item_pkt->PacketType); if (!serialized) { _log(NET__STRUCTS, "Serialization failed on item slot %d.", int_struct->slot_id); @@ -4867,7 +4867,7 @@ namespace RoF2 return NextItemInstSerialNumber; } - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) + char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth, ItemPacketType packet_type) { int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint8 null_term = 0; @@ -4891,7 +4891,7 @@ namespace RoF2 hdr.stacksize = stackable ? charges : 1; hdr.unknown004 = 0; - structs::ItemSlotStruct slot_id = ServerToRoF2Slot(slot_id_in); + structs::ItemSlotStruct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); hdr.slot_type = (merchant_slot == 0) ? slot_id.SlotType : 9; // 9 is merchant 20 is reclaim items? hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; @@ -5396,7 +5396,7 @@ namespace RoF2 SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); */ - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); + SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1, packet_type); } } @@ -5422,7 +5422,7 @@ namespace RoF2 return item_serial; } - static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot) + static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot, ItemPacketType PacketType) { structs::ItemSlotStruct RoF2Slot; RoF2Slot.SlotType = INVALID_INDEX; @@ -5435,13 +5435,21 @@ namespace RoF2 uint32 TempSlot = 0; if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // Main Inventory and Cursor - RoF2Slot.SlotType = maps::MapPossessions; - RoF2Slot.MainSlot = ServerSlot; - + if (PacketType == ItemPacketLoot) + { + RoF2Slot.SlotType = maps::MapCorpse; + RoF2Slot.MainSlot = ServerSlot - EmuConstants::CORPSE_BEGIN; + } + else + { + RoF2Slot.SlotType = maps::MapPossessions; + RoF2Slot.MainSlot = ServerSlot; + } + if (ServerSlot == MainPowerSource) RoF2Slot.MainSlot = slots::MainPowerSource; - else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory + else if (ServerSlot >= MainCursor && PacketType != ItemPacketLoot) // Cursor and Extended Corpse Inventory RoF2Slot.MainSlot += 3; else if (ServerSlot >= MainAmmo) // (> 20) @@ -5568,11 +5576,10 @@ namespace RoF2 static inline uint32 ServerToRoF2CorpseSlot(uint32 ServerCorpse) { - //uint32 RoF2Corpse; - return (ServerCorpse + 1); + return (ServerCorpse - EmuConstants::CORPSE_BEGIN + 1); } - static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot) + static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot, ItemPacketType PacketType) { uint32 ServerSlot = INVALID_INDEX; uint32 TempSlot = 0; @@ -5667,6 +5674,10 @@ namespace RoF2 ServerSlot = INVALID_INDEX; } + else if (RoF2Slot.SlotType == maps::MapCorpse) { + ServerSlot = RoF2Slot.MainSlot + EmuConstants::CORPSE_BEGIN; + } + _log(NET__ERROR, "Convert RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", RoF2Slot.SlotType, RoF2Slot.Unknown02, RoF2Slot.MainSlot, RoF2Slot.SubSlot, RoF2Slot.AugSlot, RoF2Slot.Unknown01, ServerSlot); return ServerSlot; @@ -5709,8 +5720,7 @@ namespace RoF2 static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse) { - //uint32 ServerCorpse; - return (RoF2Corpse - 1); + return (RoF2Corpse + EmuConstants::CORPSE_BEGIN - 1); } } // end namespace RoF2 diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index f80bd17b2..9ba71574c 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1843,8 +1843,8 @@ struct LootingItem_Struct { /*000*/ uint32 lootee; /*004*/ uint32 looter; /*008*/ uint16 slot_id; -/*010*/ uint16 unknown10; -/*012*/ uint32 auto_loot; +/*010*/ uint16 unknown10; // slot_id is probably uint32 +/*012*/ int32 auto_loot; /*016*/ uint32 unknown16; /*020*/ }; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f809fb3c8..7534deff7 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9170,12 +9170,6 @@ void Client::Handle_OP_LootItem(const EQApplicationPacket *app) LogFile->write(EQEMuLog::Error, "Wrong size: OP_LootItem, size=%i, expected %i", app->size, sizeof(LootingItem_Struct)); return; } - /* - ** fixed the looting code so that it sends the correct opcodes - ** and now correctly removes the looted item the player selected - ** as well as gives the player the proper item. - ** Also fixed a few UI lock ups that would occur. - */ EQApplicationPacket* outapp = 0; Entity* entity = entity_list.GetID(*((uint16*)app->pBuffer)); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index a99b8b500..380697eac 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1207,7 +1207,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args); parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0); - if ((RuleB(Character, EnableDiscoveredItems))) { + if (!IsPlayerCorpse() && RuleB(Character, EnableDiscoveredItems)) { if (client && !client->GetGM() && !client->IsDiscovered(inst->GetItem()->ID)) client->DiscoverItem(inst->GetItem()->ID); } diff --git a/zone/groups.cpp b/zone/groups.cpp index 3395833bf..a6d8be42b 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -122,7 +122,8 @@ void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinu uint32 i; uint8 membercount = 0; for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr) { + // Don't split with Mercs or Bots + if (members[i] != nullptr && members[i]->IsClient()) { membercount++; } } diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 19520a177..fed4dde3b 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -926,7 +926,7 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_cursor, ServerLootItem_Struct** bag_item_data) { // #1: Try to auto equip - if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && !inst.GetItem()->Attuneable && inst.GetItem()->ItemType != ItemTypeAugmentation) + if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != ItemTypeAugmentation) { // too messy as-is... for (int16 i = EmuConstants::EQUIPMENT_BEGIN; i < MainPowerSource; i++) // originally (i < 22)