From e7cecb98f9f3b137f9549835078614e0cf15bec9 Mon Sep 17 00:00:00 2001
From: HungDK <>
Date: Wed, 27 May 2026 09:25:12 +0700
Subject: [PATCH] Deposit, withdraw account money handler
---
.../Scripts/Managers/EC_InventoryUI.cs | 10 +++
.../CSNetwork/C2SCommand/C2SCommandFactory.cs | 10 +++
.../Scripts/Network/UnityGameSession.cs | 5 ++
.../PerfectWorld/Scripts/UI/Dialogs/DlgNPC.cs | 3 +-
.../Scripts/UI/Dialogs/DlgQuantity.cs | 10 +++
Assets/Scripts/CECHostPlayer.Storage.cs | 66 ++++++++++++++++++-
Assets/Scripts/CECUIManager.cs | 52 +++++++++++++++
7 files changed, 152 insertions(+), 4 deletions(-)
diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs
index a014dc3809..4bd4a5aff2 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs
@@ -145,6 +145,11 @@ namespace BrewMonster.Scripts.Managers
CECHostPlayer.PopupStorageDialog(true);
return;
}
+ if (!value && GetHostPlayer() != null && GetHostPlayer().IsUsingAccountBox())
+ {
+ CECHostPlayer.PopupAccountBoxDialog(true);
+ return;
+ }
base.Show(value);
}
@@ -155,6 +160,11 @@ namespace BrewMonster.Scripts.Managers
CECHostPlayer.PopupStorageDialog(true);
return;
}
+ if (GetHostPlayer() != null && GetHostPlayer().IsUsingAccountBox())
+ {
+ CECHostPlayer.PopupAccountBoxDialog(true);
+ return;
+ }
base.CloseDialogue();
}
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs
index ae0e47c343..54eeed262e 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs
@@ -1268,6 +1268,16 @@ namespace CSNetwork.C2SCommand
return octets;
}
+ public static Octets CreateNPCSevOpenAccountBoxCmd()
+ {
+ var cmd = new cmd_sevnpc_serve
+ {
+ service_type = NPC_service_type.GP_NPCSEV_OPEN_ACCOUNT_BOX,
+ len = 0
+ };
+ return SerializeCommand(CommandID.SEVNPC_SERVE, cmd);
+ }
+
public static Octets CreateGetOtherEquipCmd(ushort _size, int[] _idlist)
{
var cmd = new cmd_get_other_equip
diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs
index 5a9b33cade..5bb555c408 100644
--- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs
+++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs
@@ -979,6 +979,11 @@ namespace BrewMonster.Network
Instance._gameSession.c2s_CmdNPCSevOpenTrash(password);
}
+ public static void c2s_CmdNPCSevOpenAccountBox()
+ {
+ Instance._gameSession.c2s_CmdNPCSevOpenAccountBox();
+ }
+
public static void c2s_CmdGetTrashBoxData(bool detail, bool accountBox = false)
{
Instance._gameSession.c2s_CmdGetTrashBoxData(detail, accountBox);
diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgNPC.cs b/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgNPC.cs
index a51b84a603..601c8f3da4 100644
--- a/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgNPC.cs
+++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgNPC.cs
@@ -3788,7 +3788,8 @@ namespace BrewMonster.UI
// GetGameUIMan().ShowErrorMsg(10130);
// GetGameUIMan().EndNPCService();
//}
- //else g_pGame.GetGameSession().c2s_CmdNPCSevOpenAccountBox();
+ UnityGameSession.c2s_CmdNPCSevOpenAccountBox();
+ GetGameUIMan().EndNPCService();
}
else if (idFunction == (int)SERVICE_TYPE.NPC_ENGRAVE)
{
diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgQuantity.cs b/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgQuantity.cs
index b8ba84cf51..86e3dd31c4 100644
--- a/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgQuantity.cs
+++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/DlgQuantity.cs
@@ -20,6 +20,10 @@ namespace BrewMonster.UI
StorageDepositMoney,
/// Rút tiền ra — C++ INPUTNO_STORAGE_TRASH_MONEY (Win_Storage choosemoney).
StorageWithdrawMoney,
+ /// Gửi tiền vào kho tài khoản — same C2S as storage, with is_accountbox=1.
+ AccountStorageDepositMoney,
+ /// Rút tiền ra từ kho tài khoản — same C2S as storage, with is_accountbox=1.
+ AccountStorageWithdrawMoney,
}
[Header("Amount")]
@@ -236,6 +240,12 @@ namespace BrewMonster.UI
// C++ INPUTNO_STORAGE_TRASH_MONEY: ExgTrashBoxMoney(iTrash=amount, iIvtr=0)
UnityGameSession.c2s_CmdExgTrashBoxMoney(0, amount);
break;
+ case QuantityMode.AccountStorageDepositMoney:
+ UnityGameSession.c2s_CmdExgTrashBoxMoney(amount, 0, true);
+ break;
+ case QuantityMode.AccountStorageWithdrawMoney:
+ UnityGameSession.c2s_CmdExgTrashBoxMoney(0, amount, true);
+ break;
}
}
diff --git a/Assets/Scripts/CECHostPlayer.Storage.cs b/Assets/Scripts/CECHostPlayer.Storage.cs
index 02c5d3e7aa..2b0bfb59eb 100644
--- a/Assets/Scripts/CECHostPlayer.Storage.cs
+++ b/Assets/Scripts/CECHostPlayer.Storage.cs
@@ -23,10 +23,15 @@ namespace BrewMonster
private bool m_bTrashPsw;
private bool m_bFirstTBOpen = true;
+ private bool m_bUsingAccountBox;
+ private bool m_bFirstAccountBoxOpen = true;
private int m_iTrashBoxMoneyCnt;
+ private int m_iAccountBoxMoneyCnt;
public bool TrashBoxHasPsw() => m_bTrashPsw;
public int GetTrashBoxMoneyCnt() => m_iTrashBoxMoneyCnt;
+ public bool IsUsingAccountBox() => m_bUsingAccountBox;
+ public int GetAccountBoxMoneyCnt() => m_iAccountBoxMoneyCnt;
public EC_Inventory GetTrashBox() => m_pTrashBoxPack;
public EC_Inventory GetTrashBox2() => m_pTrashBoxPack2;
public EC_Inventory GetTrashBox3() => m_pTrashBoxPack3;
@@ -54,9 +59,22 @@ namespace BrewMonster
{
var pCmd = GPDataTypeHelper.FromBytes(data);
if (pCmd.is_accountbox != 0)
- break; // PW_TODO: account box UI
+ {
+ m_bUsingAccountBox = true;
+ m_bUsingTrashBox = false;
+
+ if (m_bFirstAccountBoxOpen)
+ {
+ m_bFirstAccountBoxOpen = false;
+ UnityGameSession.c2s_CmdGetTrashBoxData(true, true);
+ }
+
+ PopupAccountBoxDialog();
+ break;
+ }
m_bUsingTrashBox = true;
+ m_bUsingAccountBox = false;
InitTrashBoxPacks();
if (m_bFirstTBOpen)
@@ -80,7 +98,11 @@ namespace BrewMonster
{
var pCmd = GPDataTypeHelper.FromBytes(data);
if (pCmd.is_accountbox != 0)
+ {
+ m_bUsingAccountBox = false;
+ PopupAccountBoxDialog(true);
break;
+ }
m_bUsingTrashBox = false;
PopupStorageDialog(true);
break;
@@ -89,19 +111,31 @@ namespace BrewMonster
{
var pCmd = GPDataTypeHelper.FromBytes(data);
if (pCmd.is_accountbox == 0)
+ {
m_iTrashBoxMoneyCnt = (int)pCmd.money;
- EC_StorageUI.RefreshMoneyStatic();
+ EC_StorageUI.RefreshMoneyStatic();
+ }
+ else
+ {
+ m_iAccountBoxMoneyCnt = (int)pCmd.money;
+ EC_AccountStorageUI.RefreshMoneyStatic();
+ }
break;
}
case CommandID.EXG_TRASH_MONEY:
{
var pCmd = GPDataTypeHelper.FromBytes(data);
+ AddMoneyAmount(pCmd.inv_delta);
if (pCmd.is_accountbox == 0)
{
- AddMoneyAmount(pCmd.inv_delta);
m_iTrashBoxMoneyCnt += pCmd.tra_delta;
}
+ else
+ {
+ m_iAccountBoxMoneyCnt += pCmd.tra_delta;
+ }
EC_StorageUI.RefreshMoneyStatic();
+ EC_AccountStorageUI.RefreshMoneyStatic();
var invUi = UnityEngine.Object.FindFirstObjectByType();
invUi?.RefreshAll();
break;
@@ -243,6 +277,32 @@ namespace BrewMonster
invDlg?.RefreshAll();
}
+ /// C++ CECGameUIMan::PopupAccountBoxDialog — money-only account warehouse.
+ public static void PopupAccountBoxDialog(bool close = false)
+ {
+ if (close)
+ {
+ var host = EC_Game.GetGameRun()?.GetHostPlayer();
+ if (host != null)
+ host.m_bUsingAccountBox = false;
+
+ EC_StorageUI.ClearSelectionStatic();
+ var invUi = UnityEngine.Object.FindFirstObjectByType(FindObjectsInactive.Include);
+ invUi?.DismissItemDetail();
+
+ CECUIManager.Instance?.HideAccountStorageDialogPair();
+ EC_Game.GetGameRun()?.GetUIManager()?.GetInGameUIMan()?.EndNPCService();
+ return;
+ }
+
+ CECUIManager.Instance?.ShowAccountStorageDialogPair();
+ var accountDlg = EC_Game.GetGameRun()?.GetUIManager()?.GetInGameUIMan()?.GetDialog("EC_AccountStorageUI") as EC_AccountStorageUI;
+ accountDlg?.RefreshAll();
+
+ var invDlg = UnityEngine.Object.FindFirstObjectByType(FindObjectsInactive.Include);
+ invDlg?.RefreshAll();
+ }
+
/// Transfer between main pack and trash box (C++ CDlgStorage::OnItemDragDrop).
public bool TransferPackAndTrash(byte trashWhere, int trashSlot, int invSlot, int amount = -1)
{
diff --git a/Assets/Scripts/CECUIManager.cs b/Assets/Scripts/CECUIManager.cs
index e90d5c7b8d..0399c9e2c4 100644
--- a/Assets/Scripts/CECUIManager.cs
+++ b/Assets/Scripts/CECUIManager.cs
@@ -361,6 +361,58 @@ public class CECUIManager : MonoSingleton
}
}
+ ///
+ /// Show money-only account warehouse + inventory together. This intentionally uses a
+ /// separate dialog from EC_StorageUI to avoid enabling warehouse item slots.
+ ///
+ public void ShowAccountStorageDialogPair()
+ {
+ if (canvasDlg == null)
+ return;
+
+ var gui = GetInGameUIMan();
+ if (gui == null)
+ return;
+
+ var accountDlg = gui.GetDialog("EC_AccountStorageUI");
+ var invDlg = gui.GetDialog("Win_Inventory");
+ if (accountDlg == null || invDlg == null)
+ return;
+
+ _uiStack.Remove("Win_Inventory");
+ _uiStack.Remove("EC_AccountStorageUI");
+
+ invDlg.Show(true);
+ accountDlg.Show(true);
+
+ _uiStack.Insert(0, "Win_Inventory");
+ _uiStack.Insert(0, "EC_AccountStorageUI");
+
+ invDlg.transform.SetAsLastSibling();
+ accountDlg.transform.SetAsLastSibling();
+ }
+
+ /// Hide account warehouse pair and restore previous stack top if any.
+ public void HideAccountStorageDialogPair()
+ {
+ _uiStack.Remove("EC_AccountStorageUI");
+ _uiStack.Remove("Win_Inventory");
+
+ var gui = GetInGameUIMan();
+ gui?.GetDialog("Win_Inventory")?.Show(false);
+ gui?.GetDialog("EC_AccountStorageUI")?.Show(false);
+
+ if (_uiStack.Count > 0)
+ {
+ var newTop = gui?.GetDialog(_uiStack[0]);
+ if (newTop != null)
+ {
+ newTop.Show(true);
+ newTop.transform.SetAsLastSibling();
+ }
+ }
+ }
+
///
/// Pop the top dialog off the stack: hide it and bring the new top (if any) to front. Returns true if something was popped.
///