From 5946af88a60b0571f7bf1b6b3d8a010c45d03b16 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 20 Aug 2014 18:30:19 -0400 Subject: [PATCH] Reworked Trade::AddEntity() to allow client-directed movement of stacked items (as close to 'stacking' as I can get it - see changelog.txt) --- changelog.txt | 9 ++++-- zone/common.h | 2 +- zone/inventory.cpp | 2 +- zone/trading.cpp | 68 +++++++++++++++++++++++++++------------------- 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/changelog.txt b/changelog.txt index 26fb72c5a..bf2ea97f0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,13 +1,18 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/20/2014 == +Uleat: Rework of Trade::AddEntity() - function used to move items into the trade window. Now accepts argument for 'stack_size' and updates client properly. +Note: I tested trade with Titanium:{SoF,SoD,UF,RoF} in both directions and no client generated an OP_MoveItem event for attempting to place a stackable +onto a partial stack already in the trade window. The only way to achieve stacking is to click on the receiving client. If there is a partial stack remaining +on the cursor after the OP_MoveItem event, and there is room available, the client will generate subsequent events to move the remaining count. + == 08/19/2014 == Akkadius: Implemented a Stop_Return feature (Accidental item handin prevention) that will be symmetrically used with plugin::return_items that I am currently running live testing on EZ before releasing to EQEmu. This does not hurt to have this in the source. Akkadius: Fixed crash where 'attacker' validation is not being checked Akkadius: Removed petition console spam that does not follow traditional logging and is useless -Akkadius: Made fix with SympatheticProcChances where it was checking for TempItem->Focus.Effect instead of TempItemAug->Focus.Effect== 08/18/2014 == +Akkadius: Made fix with SympatheticProcChances where it was checking for TempItem->Focus.Effect instead of TempItemAug->Focus.Effect == 08/18/2014 == - Uleat: Fix for https://github.com/EQEmu/Server/issues/127 -- also activated a remarked action in doors.cpp to eliminate a memory leak. == 08/16/2014 == diff --git a/zone/common.h b/zone/common.h index 19cd51ce1..10ce05420 100644 --- a/zone/common.h +++ b/zone/common.h @@ -526,7 +526,7 @@ public: Mob* With(); // Add item from cursor slot to trade bucket (automatically does bag data too) - void AddEntity(uint16 from_slot_id, uint16 trade_slot_id); + void AddEntity(uint16 from_slot_id, uint16 trade_slot_id, uint32 stack_size); // Audit trade void LogTrade(); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 76f0d9f87..7a36aa5e9 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1540,7 +1540,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Also sends trade information to other client of trade session if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - trade->AddEntity(src_slot_id, dst_slot_id); + trade->AddEntity(src_slot_id, dst_slot_id, move_in->number_in_stack); return true; } else { diff --git a/zone/trading.cpp b/zone/trading.cpp index 1ace776a7..7dbc93bad 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -71,8 +71,9 @@ void Trade::Start(uint32 mob_id, bool initiate_with) } // Add item from a given slot to trade bucket (automatically does bag data too) -void Trade::AddEntity(uint16 from_slot_id, uint16 trade_slot_id) -{ +void Trade::AddEntity(uint16 from_slot_id, uint16 trade_slot_id, uint32 stack_size) { + // TODO: review for inventory saves + if (!owner || !owner->IsClient()) { // This should never happen LogFile->write(EQEMuLog::Debug, "Programming error: NPC's should not call Trade::AddEntity()"); @@ -87,45 +88,56 @@ void Trade::AddEntity(uint16 from_slot_id, uint16 trade_slot_id) // Item always goes into trade bucket from cursor Client* client = owner->CastToClient(); - const ItemInst* inst = client->GetInv().GetItem(MainCursor); + ItemInst* inst = client->GetInv().GetItem(MainCursor); + if (!inst) { client->Message(13, "Error: Could not find item on your cursor!"); return; } - _log(TRADING__HOLDER, "%s added item '%s' to trade slot %i", owner->GetName(), inst->GetItem()->Name, trade_slot_id); - ItemInst* inst2 = client->GetInv().GetItem(trade_slot_id); - int new_charges = 0; - if (!inst2 || !inst2->GetItem()) { - // Send all item data to other client - SendItemData(inst, trade_slot_id); - // Move item on cursor to the trade slots - client->PutItemInInventory(trade_slot_id, *inst); - } - else - { - if (client->GetInv().GetItem(MainCursor)->GetID() != client->GetInv().GetItem(trade_slot_id)->GetID()) { + + // it looks like the original code attempted to allow stacking... + // (it just didn't handle partial stack move actions -U) + if (stack_size > 0) { + if (!inst->IsStackable() || !inst2 || !inst2->GetItem() || (inst->GetID() != inst2->GetID()) || (stack_size > inst->GetCharges())) { client->Kick(); return; } - new_charges = (inst2->GetCharges()+inst->GetCharges()); - if (new_charges < inst2->GetItem()->StackSize) - { - inst2->SetCharges(new_charges); - new_charges = 0; - } - else - { - new_charges = inst->GetCharges()-(inst2->GetItem()->StackSize-inst2->GetCharges()); //Leftover charges = charges - difference + + uint32 _stack_size = 0; + + if ((stack_size + inst2->GetCharges()) > inst2->GetItem()->StackSize) { + _stack_size = (stack_size + inst2->GetCharges()) - inst->GetItem()->StackSize; inst2->SetCharges(inst2->GetItem()->StackSize); } + else { + _stack_size = inst->GetCharges() - stack_size; + inst2->SetCharges(stack_size + inst2->GetCharges()); + } + + _log(TRADING__HOLDER, "%s added partial item '%s' stack (qty: %i) to trade slot %i", owner->GetName(), inst->GetItem()->Name, stack_size, trade_slot_id); + + if (_stack_size > 0) + inst->SetCharges(_stack_size); + else + client->DeleteItemInInventory(from_slot_id); + SendItemData(inst2, trade_slot_id); } - if (new_charges > 0) - client->GetInv().GetItem(from_slot_id)->SetCharges(new_charges); - else - client->DeleteItemInInventory(from_slot_id);//, (ItemInst&)trade_inst); + else { + if (inst2 && inst2->GetID()) { + client->Kick(); + return; + } + + SendItemData(inst, trade_slot_id); + + _log(TRADING__HOLDER, "%s added item '%s' to trade slot %i", owner->GetName(), inst->GetItem()->Name, trade_slot_id); + + client->PutItemInInventory(trade_slot_id, *inst); + client->DeleteItemInInventory(from_slot_id); + } } // Retrieve mob the owner is trading with