Changed the return type of Corpse::MoveItemToCorpse() to void and added a 'by address' parameter to replace it -- Fixed a bug that would 'unattune' soulbound items inside of bags

This commit is contained in:
Uleat 2015-01-26 19:44:33 -05:00
parent 58b5f6b88f
commit 89f8006f11
3 changed files with 58 additions and 69 deletions

View File

@ -1,5 +1,8 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 01/26/2015 ==
Uleat: Changed Corpse::MoveItemToCorpse() to allow 'by address' passing of removed item slot list. Fixed a bug that would 'unattune' soulbound items inside of binds
== 01/25/2015 == == 01/25/2015 ==
Trevius: Fixed an issue where Mercenaries were causing several DB queries per second while suspended. Trevius: Fixed an issue where Mercenaries were causing several DB queries per second while suspended.
Trevius: Added Logs::Mercenaries to the new Logging System. Logging of Mercenary information is off by default with the required SQL. Trevius: Added Logs::Mercenaries to the new Logging System. Logging of Mercenary information is off by default with the required SQL.

View File

@ -320,52 +320,28 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
// solar: TODO soulbound items need not be added to corpse, but they need // solar: TODO soulbound items need not be added to corpse, but they need
// to go into the regular slots on the player, out of bags // to go into the regular slots on the player, out of bags
// possessions
// TODO: accomodate soul-bound items
std::list<uint32> removed_list; std::list<uint32> removed_list;
//bool cursor = false;
for(i = MAIN_BEGIN; i < EmuConstants::MAP_POSSESSIONS_SIZE; i++) { for(i = MAIN_BEGIN; i < EmuConstants::MAP_POSSESSIONS_SIZE; ++i) {
if(i == MainAmmo && client->GetClientVersion() >= ClientVersion::SoF) { if(i == MainAmmo && client->GetClientVersion() >= ClientVersion::SoF) {
item = client->GetInv().GetItem(MainPowerSource); item = client->GetInv().GetItem(MainPowerSource);
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) { if (item != nullptr) {
std::list<uint32> slot_list = MoveItemToCorpse(client, item, MainPowerSource); if (!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent))
removed_list.merge(slot_list); MoveItemToCorpse(client, item, MainPowerSource, removed_list);
} }
} }
item = client->GetInv().GetItem(i); item = client->GetInv().GetItem(i);
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) { if (item == nullptr) { continue; }
std::list<uint32> slot_list = MoveItemToCorpse(client, item, i);
removed_list.merge(slot_list);
}
}
#if 0 if(!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent))
// This will either be re-enabled or deleted at some point. The client doesn't appear MoveItemToCorpse(client, item, i, removed_list);
// to like to have items deleted from it's buffer..or, I just haven't figure out how -U
// (Besides, the 'corpse' slots equal the size of MapPossessions..not MapPossessions + MapCorpse)
// cursor queue // (change to first client that supports 'death hover' mode, if not SoF.)
if (!RuleB(Character, RespawnFromHover) || client->GetClientVersion() < EQClientSoF) {
// bumped starting assignment to 8001 because any in-memory 'slot 8000' item was moved above as 'slot 30'
// this was mainly for client profile state reflection..should match db player inventory entries now.
i = 8001;
for (auto it = client->GetInv().cursor_begin(); it != client->GetInv().cursor_end(); ++it, i++) {
item = *it;
if ((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
std::list<uint32> slot_list = MoveItemToCorpse(client, item, i);
removed_list.merge(slot_list);
cursor = true;
} }
}
}
#endif
database.TransactionBegin(); database.TransactionBegin();
if (removed_list.size() != 0) {
// I have an untested process that avoids this snarl up when all possessions inventory is removed..but this isn't broke -U
if (!removed_list.empty()) {
std::stringstream ss(""); std::stringstream ss("");
ss << "DELETE FROM inventory WHERE charid=" << client->CharacterID(); ss << "DELETE FROM inventory WHERE charid=" << client->CharacterID();
ss << " AND ("; ss << " AND (";
@ -385,18 +361,6 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
database.QueryDatabase(ss.str().c_str()); database.QueryDatabase(ss.str().c_str());
} }
#if 0
if (cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
while (!client->GetInv().CursorEmpty())
client->DeleteItemInInventory(MainCursor, 0, false, false);
}
else { // only visible cursor made it to corpse (client >= Sof and RespawnFromHover = true)
std::list<ItemInst*>::const_iterator start = client->GetInv().cursor_begin();
std::list<ItemInst*>::const_iterator finish = client->GetInv().cursor_end();
database.SaveCursor(client->CharacterID(), start, finish);
}
#endif
auto start = client->GetInv().cursor_begin(); auto start = client->GetInv().cursor_begin();
auto finish = client->GetInv().cursor_end(); auto finish = client->GetInv().cursor_end();
database.SaveCursor(client->CharacterID(), start, finish); database.SaveCursor(client->CharacterID(), start, finish);
@ -406,8 +370,13 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
IsRezzed(false); IsRezzed(false);
Save(); Save();
database.TransactionCommit(); database.TransactionCommit();
UpdateEquipLightValue();
spell_light = NOT_USED;
UpdateActiveLightValue();
return; return;
} //end "not leaving naked corpses" } //end "not leaving naked corpses"
@ -419,32 +388,49 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
Save(); Save();
} }
std::list<uint32> Corpse::MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot) void Corpse::MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list<uint32> &removedList)
{ {
int bagindex; AddItem(
int16 interior_slot; inst->GetItem()->ID,
ItemInst *interior_item; inst->GetCharges(),
std::list<uint32> returnlist; equipSlot,
inst->GetAugmentItemID(0),
inst->GetAugmentItemID(1),
inst->GetAugmentItemID(2),
inst->GetAugmentItemID(3),
inst->GetAugmentItemID(4),
inst->GetAugmentItemID(5),
inst->IsAttuned()
);
removedList.push_back(equipSlot);
AddItem(item->GetItem()->ID, item->GetCharges(), equipslot, item->GetAugmentItemID(0), item->GetAugmentItemID(1), item->GetAugmentItemID(2), item->GetAugmentItemID(3), item->GetAugmentItemID(4), item->GetAugmentItemID(5), item->IsAttuned()); while (true) {
returnlist.push_back(equipslot); if (!inst->IsType(ItemClassContainer)) { break; }
if (equipSlot < EmuConstants::GENERAL_BEGIN || equipSlot > MainCursor) { break; }
// Qualified bag slot iterations. processing bag slots that don't exist is probably not a good idea. for (auto sub_index = SUB_BEGIN; sub_index < EmuConstants::ITEM_CONTAINER_SIZE; ++sub_index) {
if (item->IsType(ItemClassContainer) && ((equipslot >= EmuConstants::GENERAL_BEGIN && equipslot <= MainCursor))) { int16 real_bag_slot = Inventory::CalcSlotId(equipSlot, sub_index);
for (bagindex = SUB_BEGIN; bagindex <= EmuConstants::ITEM_CONTAINER_SIZE; bagindex++) { auto bag_inst = client->GetInv().GetItem(real_bag_slot);
// For empty bags in cursor queue, slot was previously being resolved as SLOT_INVALID (-1) if (bag_inst == nullptr) { continue; }
interior_slot = Inventory::CalcSlotId(equipslot, bagindex);
interior_item = client->GetInv().GetItem(interior_slot);
if (interior_item) { AddItem(
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), interior_item->GetAugmentItemID(5), item->IsAttuned()); bag_inst->GetItem()->ID,
returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex)); bag_inst->GetCharges(),
client->DeleteItemInInventory(interior_slot, 0, true, false); real_bag_slot,
bag_inst->GetAugmentItemID(0),
bag_inst->GetAugmentItemID(1),
bag_inst->GetAugmentItemID(2),
bag_inst->GetAugmentItemID(3),
bag_inst->GetAugmentItemID(4),
bag_inst->GetAugmentItemID(5),
bag_inst->IsAttuned()
);
removedList.push_back(real_bag_slot);
client->DeleteItemInInventory(real_bag_slot, 0, true, false);
} }
break;
} }
} client->DeleteItemInInventory(equipSlot, 0, true, false);
client->DeleteItemInInventory(equipslot, 0, true, false);
return returnlist;
} }
// To be called from LoadFromDBData // To be called from LoadFromDBData

View File

@ -128,7 +128,7 @@ class Corpse : public Mob {
virtual void UpdateEquipLightValue(); virtual void UpdateEquipLightValue();
protected: protected:
std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot); void MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list<uint32> &removedList);
private: private:
bool is_player_corpse; /* Determines if Player Corpse or not */ bool is_player_corpse; /* Determines if Player Corpse or not */