(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.
This commit is contained in:
Trevius 2015-01-02 01:42:52 -06:00
parent f0d2fb796f
commit 3c6c5b9732
9 changed files with 42 additions and 32 deletions

View File

@ -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.

View File

@ -1509,7 +1509,8 @@ enum ItemPacketType
ItemPacketTributeItem = 0x6C,
ItemPacketMerchant = 0x64,
ItemPacketWorldContainer = 0x6B,
ItemPacketCharmUpdate = 0x6E
ItemPacketCharmUpdate = 0x6E,
ItemPacketInvalid = 0xFF
};
struct ItemPacket_Struct
{

View File

@ -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);
}
}

View File

@ -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

View File

@ -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*/
};

View File

@ -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));

View File

@ -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);
}

View File

@ -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++;
}
}

View File

@ -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... <watch>
for (int16 i = EmuConstants::EQUIPMENT_BEGIN; i < MainPowerSource; i++) // originally (i < 22)