From 15db68d7efad35efd9c9fc894bcee200129d226a Mon Sep 17 00:00:00 2001 From: sruon Date: Fri, 15 May 2026 09:22:24 -0600 Subject: [PATCH 1/3] Allow ammo to be consumed while equipped --- scripts/tests/systems/items/equip.lua | 11 +++++++++++ src/map/utils/charutils.cpp | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/scripts/tests/systems/items/equip.lua b/scripts/tests/systems/items/equip.lua index 91f81a0fd66..b2484300f7e 100644 --- a/scripts/tests/systems/items/equip.lua +++ b/scripts/tests/systems/items/equip.lua @@ -87,6 +87,17 @@ describe('Equipment', function() assert(player:getEquippedItem(xi.slot.MAIN) == nil) end) + it('equipped ammo stack decrements on use', function() + player:addItem(xi.item.FIRE_ARROW, 50) + player:equipItem(xi.item.FIRE_ARROW, nil, xi.slot.AMMO) + + player:delItem(xi.item.FIRE_ARROW, 1) + + local ammo = player:getEquippedItem(xi.slot.AMMO) + assert(ammo) + assert(ammo:getQuantity() == 49) + end) + it('all visible armor slots accept their piece', function() local pieces = { diff --git a/src/map/utils/charutils.cpp b/src/map/utils/charutils.cpp index 9791b06c601..0c5899f903a 100644 --- a/src/map/utils/charutils.cpp +++ b/src/map/utils/charutils.cpp @@ -1933,7 +1933,10 @@ uint32 UpdateItem(CCharEntity* PChar, uint8 LocationID, uint8 slotID, int32 quan } } - if (PItem->isBusy() && !force) + // Equipped ammo decrements its stack on consumption without leaving the slot. + const bool isEquippedAmmo = PItem->state() == ItemState::Equipped && + PChar->getEquip(SLOT_AMMO) == PItem; + if (PItem->isBusy() && !isEquippedAmmo && !force) { ShowWarningFmt("UpdateItem: refusing to mutate busy item {} in state {} (loc={}, slot={}, char={})", ItemID, From 38b4e16eb99e7ce01ded010c4d69a711ae2817fc Mon Sep 17 00:00:00 2001 From: sruon Date: Fri, 15 May 2026 09:22:50 -0600 Subject: [PATCH 2/3] Carry ItemUse transaction on PChar for dtor order --- src/map/ai/states/item_state.cpp | 10 +++------- src/map/ai/states/item_state.h | 22 ++++++++++------------ 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/map/ai/states/item_state.cpp b/src/map/ai/states/item_state.cpp index 2aff99f3e4d..e17a9276fd9 100644 --- a/src/map/ai/states/item_state.cpp +++ b/src/map/ai/states/item_state.cpp @@ -119,7 +119,7 @@ CItemState::CItemState(CCharEntity* PEntity, const uint16 targid, const uint8 lo m_PEntity->UContainer->SetType(UCONTAINER_USEITEM); m_PEntity->UContainer->SetItem(0, m_PItem); - tx_ = ItemUseTransaction::start(m_PEntity, m_PItem); + tx_ = m_PEntity->addTransaction(ItemUseTransaction::start(m_PEntity, m_PItem)); m_startPos = m_PEntity->loc.p; m_castTime = m_PItem->getActivationTime(); m_animationTime = m_PItem->getAnimationTime(); @@ -241,13 +241,9 @@ void CItemState::Cleanup(timer::time_point tick) { m_PEntity->UContainer->Clean(); - // Clear InTransaction before the ITEM_LIST packet below. - if (m_interrupted || !IsCompleted()) + if (tx_ && tx_->isOpen()) { - if (tx_) - { - tx_->rollback(); - } + tx_->rollback(); } if (m_PItem && (m_interrupted || !IsCompleted()) && !m_PItem->isType(ITEM_EQUIPMENT)) diff --git a/src/map/ai/states/item_state.h b/src/map/ai/states/item_state.h index fdc7c687249..0aec8107cdc 100644 --- a/src/map/ai/states/item_state.h +++ b/src/map/ai/states/item_state.h @@ -23,8 +23,6 @@ #include "state.h" -#include - class CBattleEntity; class CCharEntity; class CItemUsable; @@ -62,14 +60,14 @@ class CItemState : public CState protected: bool HasMoved() const; - CCharEntity* m_PEntity; - CItemUsable* m_PItem; - uint8 m_location; - uint8 m_slot; - timer::duration m_castTime{}; - timer::duration m_animationTime{}; - position_t m_startPos; - bool m_interrupted{ false }; - bool m_interruptable{ true }; - std::unique_ptr tx_; + CCharEntity* m_PEntity; + CItemUsable* m_PItem; + uint8 m_location; + uint8 m_slot; + timer::duration m_castTime{}; + timer::duration m_animationTime{}; + position_t m_startPos; + bool m_interrupted{ false }; + bool m_interruptable{ true }; + ItemUseTransaction* tx_{ nullptr }; }; From 3eb7de22a9bd63b89c3b5a4659a394caf24405a5 Mon Sep 17 00:00:00 2001 From: sruon Date: Fri, 15 May 2026 09:23:12 -0600 Subject: [PATCH 3/3] Send item unlock packet on craft material saved --- src/map/items/transactions/synth.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/map/items/transactions/synth.cpp b/src/map/items/transactions/synth.cpp index f16d8ead727..bb2ff177516 100644 --- a/src/map/items/transactions/synth.cpp +++ b/src/map/items/transactions/synth.cpp @@ -251,6 +251,7 @@ void SynthTransaction::releaseAllClaims() { exitTx(item); item->setSubType(ITEM_UNLOCKED); + this->player_->pushPacket(item, ItemLockFlg::Normal); } this->slots_[i].item = nullptr;