From 2060f92f2c6e6b2daadfe5c4112870f0d0af8274 Mon Sep 17 00:00:00 2001
From: HungDK <>
Date: Mon, 6 Apr 2026 10:12:21 +0700
Subject: [PATCH] Fixing buying progress and result in inventory
---
.../Scripts/Managers/EC_Inventory.cs | 13 +--
.../Scripts/Managers/EC_InventoryUI.cs | 26 ++++--
.../Managers/EC_IvtrItem/EC_IvtrItem.cs | 6 +-
Assets/Scripts/CECHostPlayer.ConfigData.cs | 41 ++++++++++
Assets/Scripts/CECHostPlayer.Inventory.cs | 82 ++++++++++++++-----
5 files changed, 126 insertions(+), 42 deletions(-)
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs
index 7d113a8309..cb5a5fde1c 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs
@@ -159,6 +159,7 @@ namespace BrewMonster.Scripts.Managers
return true;
}
+ /// C++ CECInventory::MergeItem: walk slots, call CECIvtrItem::MergeItem, then new slot if needed.
public bool MergeItem(int tid, int iExpireDate, int iAmount, out int piLastSlot, out int piLastAmount)
{
piLastSlot = -1;
@@ -171,16 +172,8 @@ namespace BrewMonster.Scripts.Managers
var slotItem = m_aItems[i];
if (slotItem != null)
{
- if (slotItem.GetTemplateID() != tid)
- continue;
-
- int pileLimit = Math.Max(1, EC_IvtrItem.GetPileLimit(tid));
- int canAdd = Math.Max(0, pileLimit - Math.Max(0, slotItem.GetCount()));
- if (canAdd <= 0) continue;
-
- int add = Math.Min(canAdd, iAmount);
- slotItem.AddAmount(add);
- iAmount -= add;
+ int iNumMerge = slotItem.MergeItem(tid, iAmount);
+ iAmount -= iNumMerge;
if (iAmount == 0)
{
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs
index 8a3e9d53e7..cba791e16e 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs
@@ -873,6 +873,23 @@ namespace BrewMonster.Scripts.Managers
}
}
+ ///
+ /// Stack count label under slot buttons: prefabs use text_quatity (typo) or text_quantity; legacy code used text_quality.
+ /// Only checks immediate children (Unity ); deeper layouts fall back to below.
+ ///
+ private static Transform FindStackCountTextTransform(Transform root)
+ {
+ if (root == null) return null;
+ string[] names = { "text_quality", "text_quatity", "text_quantity" };
+ for (int n = 0; n < names.Length; n++)
+ {
+ var t = root.Find(names[n]);
+ if (t != null) return t;
+ }
+
+ return null;
+ }
+
///
/// Update or create text component to show item count on the button
///
@@ -885,22 +902,19 @@ namespace BrewMonster.Scripts.Managers
TMPro.TextMeshProUGUI tmpText = null;
Text legacyText = null;
- // Find text component
- var textTransform = button.transform.Find("text_quality");
+ var textTransform = FindStackCountTextTransform(button.transform);
if (textTransform != null)
{
tmpText = textTransform.GetComponent();
legacyText = textTransform.GetComponent();
}
- else
+
+ if (tmpText == null && legacyText == null)
{
- // Fallback: find any text in children
tmpText = button.GetComponentInChildren();
if (tmpText == null)
- {
legacyText = button.GetComponentInChildren();
- }
}
// Update text
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs
index 8498617bb8..2314b84926 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem/EC_IvtrItem.cs
@@ -1211,14 +1211,12 @@ namespace BrewMonster.Scripts.Managers
return iNumAdd;
}
- /// Add item amount. Returns new amount of item.
+ /// Add item amount. Returns new count (C++ a_Clamp to m_iPileLimit).
public int AddAmount(int iAmount)
{
- Debug.Log($"[EC_IvtrItem] Old Amount: {m_iCount}");
m_iCount += iAmount;
if (m_iCount < 0) m_iCount = 0;
- //if (m_iCount > m_iPileLimit) m_iCount = m_iPileLimit;
- Debug.Log($"[EC_IvtrItem] New Amount: {m_iCount}");
+ if (m_iCount > m_iPileLimit) m_iCount = m_iPileLimit;
return m_iCount;
}
diff --git a/Assets/Scripts/CECHostPlayer.ConfigData.cs b/Assets/Scripts/CECHostPlayer.ConfigData.cs
index bd840e76df..27c715023d 100644
--- a/Assets/Scripts/CECHostPlayer.ConfigData.cs
+++ b/Assets/Scripts/CECHostPlayer.ConfigData.cs
@@ -482,6 +482,47 @@ namespace BrewMonster
}
}
}
+
+ /// C++ CECDealInventory::GetItemIndexByFlag
+ public int GetItemIndexByFlag(int iFlag)
+ {
+ int n = GetSize();
+ for (int i = 0; i < n; i++)
+ {
+ if (GetItem(i, false) != null && m_aItemInfo[i].iFlag == iFlag)
+ return i;
+ }
+ return -1;
+ }
+
+ /// C++ CECDealInventory::RemoveItemByFlag
+ public void RemoveItemByFlag(int iFlag, int iAmount)
+ {
+ int n = GetSize();
+ for (int i = 0; i < n; i++)
+ {
+ var slotItem = GetItem(i, false);
+ if (slotItem == null)
+ continue;
+
+ var info = m_aItemInfo[i];
+ if (info.iFlag != iFlag)
+ continue;
+
+ if (iAmount < 0 || iAmount >= info.iAmount)
+ {
+ SetItem(i, null);
+ }
+ else
+ {
+ info.iAmount -= iAmount;
+ m_aItemInfo[i] = info;
+ if (info.bDelete)
+ slotItem.AddAmount(-iAmount);
+ }
+ return;
+ }
+ }
}
// ��̯��Ʊ�Զ�ת��
diff --git a/Assets/Scripts/CECHostPlayer.Inventory.cs b/Assets/Scripts/CECHostPlayer.Inventory.cs
index 2d383f5e3b..83c2c72450 100644
--- a/Assets/Scripts/CECHostPlayer.Inventory.cs
+++ b/Assets/Scripts/CECHostPlayer.Inventory.cs
@@ -594,7 +594,13 @@ namespace BrewMonster
UpdateEquipSkins();
}
- /// Buy from NPC/booth: server sends PURCHASE_ITEM (cmd_purchase_item). C++ OnMsgHstPurchaseItems.
+ ///
+ /// Buy from NPC/booth: S2C PURCHASE_ITEM (cmd_purchase_item).
+ /// Port of CECHostPlayer::OnMsgHstPurchaseItems (EC_HostMsg.cpp): prefer MergeItem like the C++ client.
+ /// If merge lands on a different slot than inv_index (common when stacking into an earlier pile), we still accept
+ /// the merged slot—the strict C++ iLastSlot == inv_index check would skip updates and break buy/stack UI here.
+ /// Fallback: PutItemInSlot(inv_index) then MergeItem when merge alone fails.
+ ///
public void OnMsgHstPurchaseItems(ECMSG Msg)
{
var data = Msg.dwParam1 as byte[];
@@ -609,6 +615,7 @@ namespace BrewMonster
return;
var slotsNeedingDetail = new System.Collections.Generic.List();
+ bool purchaseSlotMismatch = false;
for (int i = 0; i < header.item_count && index + itemSize <= data.Length; i++)
{
@@ -616,37 +623,58 @@ namespace BrewMonster
int expire_date = BitConverter.ToInt32(data, index); index += 4;
int count = (int)BitConverter.ToUInt32(data, index); index += 4;
ushort inv_index = BitConverter.ToUInt16(data, index); index += 2;
- index += 1; // booth_slot
+ byte booth_slot = data[index];
+ index += 1;
if (inv_index >= pPack.GetSize())
pPack.Resize(inv_index + 1);
- bool placed = pPack.PutItemInSlot(inv_index, item_id, expire_date, count, out int lastSlot, out int slotNum);
+ int iLastSlot = 0;
+ int iSlotNum = 0;
+ bool placed = pPack.MergeItem(item_id, expire_date, count, out iLastSlot, out iSlotNum);
+ if (!placed)
+ placed = pPack.PutItemInSlot(inv_index, item_id, expire_date, count, out iLastSlot, out iSlotNum);
+ if (!placed)
+ placed = pPack.MergeItem(item_id, expire_date, count, out iLastSlot, out iSlotNum);
if (!placed)
{
- placed = pPack.MergeItem(item_id, expire_date, count, out lastSlot, out slotNum);
- if (!placed || lastSlot != inv_index)
- continue;
+#if UNITY_EDITOR
+ UnityEngine.Debug.LogWarning(
+ $"[OnMsgHstPurchaseItems] Could not place purchase tid={item_id} count={count} inv_index={inv_index}");
+#endif
+ continue;
}
- var pItem = pPack.GetItem(inv_index, false);
+ if (iLastSlot != inv_index)
+ purchaseSlotMismatch = true;
+
+#if UNITY_EDITOR
+ if (iLastSlot != inv_index)
+ {
+ UnityEngine.Debug.Log(
+ $"[OnMsgHstPurchaseItems] Using merge slot {iLastSlot} (packet inv_index={inv_index}) tid={item_id}");
+ }
+#endif
+
+ var pItem = pPack.GetItem(iLastSlot, false);
if (pItem != null)
{
pItem.Package = (byte)Inventory_type.IVTRTYPE_PACK;
- pItem.Slot = inv_index;
- int cid = pItem.GetClassID();
- if (pItem.IsEquipment() ||
- cid == (int)EC_IvtrItem.InventoryClassId.ICID_TASKNMMATTER ||
- cid == (int)EC_IvtrItem.InventoryClassId.ICID_TASKDICE ||
- cid == (int)EC_IvtrItem.InventoryClassId.ICID_TASKITEM ||
- cid == (int)EC_IvtrItem.InventoryClassId.ICID_GOBLIN_EXPPILL ||
- cid == (int)EC_IvtrItem.InventoryClassId.ICID_WEDDINGBOOKCARD ||
- cid == (int)EC_IvtrItem.InventoryClassId.ICID_WEDDINGINVITECARD ||
- cid == (int)EC_IvtrItem.InventoryClassId.ICID_SKILLTOME ||
- cid == (int)EC_IvtrItem.InventoryClassId.ICID_GOBLIN ||
- cid == (int)EC_IvtrItem.InventoryClassId.ICID_PETEGG)
+ pItem.Slot = iLastSlot;
+ // Keep stack size in sync with MergeItem/PutItemInSlot totals (authoritative for this slot).
+ if (iSlotNum > 0)
+ pItem.SetCount(iSlotNum);
+ if (pItem.IsEquipment())
+ slotsNeedingDetail.Add((byte)iLastSlot);
+ }
+
+ if (header.flag != 0 && GetBoothState() == 2)
+ {
+ var boothBPack = GetBoothBuyPack();
+ if (boothBPack != null)
{
- slotsNeedingDetail.Add((byte)inv_index);
+ // C++: CDlgInfo FIXMSG_BOOTHBUY — no matching in-game UI hook here; update booth pack only.
+ boothBPack.RemoveItemByFlag(booth_slot, count);
}
}
}
@@ -656,8 +684,18 @@ namespace BrewMonster
foreach (byte slot in slotsNeedingDetail)
UnityGameSession.c2s_CmdGetItemInfo((byte)Inventory_type.IVTRTYPE_PACK, slot);
- var ui = GameObject.FindFirstObjectByType();
- ui?.RefreshAll();
+ {
+ var ui = GameObject.FindFirstObjectByType();
+ ui?.RefreshAll();
+ if (purchaseSlotMismatch)
+ {
+ UnityGameSession.RequestInventoryAsync(0, () =>
+ {
+ var ui2 = GameObject.FindFirstObjectByType();
+ ui2?.RefreshAll();
+ });
+ }
+ }
UpdateEquipSkins();
}