diff --git a/EOLib/Domain/Interact/Bank/BankActions.cs b/EOLib/Domain/Interact/Bank/BankActions.cs new file mode 100644 index 000000000..fb3a6ea2f --- /dev/null +++ b/EOLib/Domain/Interact/Bank/BankActions.cs @@ -0,0 +1,52 @@ +using AutomaticTypeMapper; +using EOLib.Net; +using EOLib.Net.Communication; + +namespace EOLib.Domain.Interact.Bank +{ + [AutoMappedType] + public class BankActions : IBankActions + { + private readonly IPacketSendService _packetSendService; + + public BankActions(IPacketSendService packetSendService) + { + _packetSendService = packetSendService; + } + + public void Deposit(int amount) + { + var packet = new PacketBuilder(PacketFamily.Bank, PacketAction.Add) + .AddInt(amount) + .Build(); + + _packetSendService.SendPacket(packet); + } + + public void Withdraw(int amount) + { + var packet = new PacketBuilder(PacketFamily.Bank, PacketAction.Take) + .AddInt(amount) + .Build(); + + _packetSendService.SendPacket(packet); + } + + public void BuyStorageUpgrade() + { + var packet = new PacketBuilder(PacketFamily.Locker, PacketAction.Buy) + .Build(); + + _packetSendService.SendPacket(packet); + } + } + + public interface IBankActions + { + void Deposit(int amount); + + void Withdraw(int amount); + + void BuyStorageUpgrade(); + } +} diff --git a/EOLib/Domain/Interact/Bank/BankDataRepository.cs b/EOLib/Domain/Interact/Bank/BankDataRepository.cs new file mode 100644 index 000000000..2a6bd49c4 --- /dev/null +++ b/EOLib/Domain/Interact/Bank/BankDataRepository.cs @@ -0,0 +1,45 @@ +using AutomaticTypeMapper; +using Optional; + +namespace EOLib.Domain.Interact.Bank +{ + public interface IBankDataRepository : IResettable + { + int AccountValue { get; set; } + + int SessionID { get; set; } + + Option LockerUpgrades { get; set; } + } + + public interface IBankDataProvider : IResettable + { + int AccountValue { get; } + + int SessionID { get; } + + Option LockerUpgrades { get; } + } + + [AutoMappedType(IsSingleton = true)] + public class BankDataRepository : IBankDataRepository, IBankDataProvider + { + public int AccountValue { get; set; } + + public int SessionID { get; set; } + + public Option LockerUpgrades { get; set; } + + public BankDataRepository() + { + ResetState(); + } + + public void ResetState() + { + AccountValue = 0; + SessionID = 0; + LockerUpgrades = Option.None(); + } + } +} diff --git a/EOLib/Domain/Interact/MapNPCActions.cs b/EOLib/Domain/Interact/MapNPCActions.cs index ad7f3a441..c56efe22c 100644 --- a/EOLib/Domain/Interact/MapNPCActions.cs +++ b/EOLib/Domain/Interact/MapNPCActions.cs @@ -45,6 +45,15 @@ public void RequestQuest(INPC npc) _packetSendService.SendPacket(packet); } + + public void RequestBank(INPC npc) + { + var packet = new PacketBuilder(PacketFamily.Bank, PacketAction.Open) + .AddShort(npc.Index) + .Build(); + + _packetSendService.SendPacket(packet); + } } public interface IMapNPCActions @@ -52,5 +61,7 @@ public interface IMapNPCActions void RequestShop(INPC npc); void RequestQuest(INPC npc); + + void RequestBank(INPC npc); } } diff --git a/EOLib/Net/API/Bank.cs b/EOLib/Net/API/Bank.cs deleted file mode 100644 index a5dd6128c..000000000 --- a/EOLib/Net/API/Bank.cs +++ /dev/null @@ -1,71 +0,0 @@ -using EOLib.Net.Handlers; - -namespace EOLib.Net.API -{ - partial class PacketAPI - { - public delegate void BankOpenEvent(int bankGold, int lockerUpgrades); - public delegate void BankChangeEvent(int characterGold, int bankGold); - - public event BankOpenEvent OnBankOpen; - public event BankChangeEvent OnBankChange; - - private void _createBankMembers() - { - m_client.AddPacketHandler(new FamilyActionPair(PacketFamily.Bank, PacketAction.Open), _handleBankOpen, true); - m_client.AddPacketHandler(new FamilyActionPair(PacketFamily.Bank, PacketAction.Reply), _handleBankReply, true); - } - - public bool BankOpen(short npcIndex) - { - if (!m_client.ConnectedAndInitialized || !Initialized || npcIndex < 0) - return false; - - OldPacket pkt = new OldPacket(PacketFamily.Bank, PacketAction.Open); - pkt.AddShort(npcIndex); - - return m_client.SendPacket(pkt); - } - - private void _handleBankOpen(OldPacket pkt) - { - int bankGold = pkt.GetInt(); - pkt.Skip(3); /*Session token - eoserv always sets 0*/ - int lockerUpgrades = pkt.GetChar(); //number of locker upgrades that have been done - - if (OnBankOpen != null) - OnBankOpen(bankGold, lockerUpgrades); - } - - public bool BankDeposit(int amount) - { - if (!m_client.ConnectedAndInitialized || !Initialized || amount < 0) - return false; - - OldPacket pkt = new OldPacket(PacketFamily.Bank, PacketAction.Add); - pkt.AddInt(amount); - - return m_client.SendPacket(pkt); - } - - public bool BankWithdraw(int amount) - { - if (!m_client.ConnectedAndInitialized || !Initialized || amount < 0) - return false; - - OldPacket pkt = new OldPacket(PacketFamily.Bank, PacketAction.Take); - pkt.AddInt(amount); - - return m_client.SendPacket(pkt); - } - - private void _handleBankReply(OldPacket pkt) - { - int characterGold = pkt.GetInt(); - int bankAmount = pkt.GetInt(); - - if(OnBankChange != null) - OnBankChange(characterGold, bankAmount); - } - } -} diff --git a/EOLib/Net/API/Locker.cs b/EOLib/Net/API/Locker.cs deleted file mode 100644 index e992f55af..000000000 --- a/EOLib/Net/API/Locker.cs +++ /dev/null @@ -1,26 +0,0 @@ -using EOLib.Net.Handlers; - -namespace EOLib.Net.API -{ - partial class PacketAPI - { - public delegate void LockerUpgradeEvent(int goldRemaining, byte lockerUpgrades); - - public event LockerUpgradeEvent OnLockerUpgrade; - - private void _createLockerMembers() - { - m_client.AddPacketHandler(new FamilyActionPair(PacketFamily.Locker, PacketAction.Buy), _handleLockerBuy, true); - } - - /// - /// Handles LOCKER_BUY from server when buying a locker unit upgrade - /// - /// - private void _handleLockerBuy(OldPacket pkt) - { - if (OnLockerUpgrade != null) - OnLockerUpgrade(pkt.GetInt(), pkt.GetChar()); //gold remaining, num upgrades - } - } -} diff --git a/EOLib/Net/API/PacketAPI.cs b/EOLib/Net/API/PacketAPI.cs index 19ef11d21..d87fdad80 100644 --- a/EOLib/Net/API/PacketAPI.cs +++ b/EOLib/Net/API/PacketAPI.cs @@ -20,9 +20,7 @@ public PacketAPI(EOClient client) m_client = client; //each of these sets up members of the partial PacketAPI class relevant to a particular packet family - _createBankMembers(); _createInitMembers(); - _createLockerMembers(); _createMusicMembers(); _createPartyMembers(); _createNPCMembers(); diff --git a/EOLib/PacketHandlers/Bank/BankOpenHandler.cs b/EOLib/PacketHandlers/Bank/BankOpenHandler.cs new file mode 100644 index 000000000..012f08065 --- /dev/null +++ b/EOLib/PacketHandlers/Bank/BankOpenHandler.cs @@ -0,0 +1,35 @@ +using AutomaticTypeMapper; +using EOLib.Domain.Interact.Bank; +using EOLib.Domain.Login; +using EOLib.Net; +using EOLib.Net.Handlers; +using Optional; + +namespace EOLib.PacketHandlers.Bank +{ + [AutoMappedType] + public class BankOpenHandler : InGameOnlyPacketHandler + { + private readonly IBankDataRepository _bankDataRepository; + + public override PacketFamily Family => PacketFamily.Bank; + + public override PacketAction Action => PacketAction.Open; + + public BankOpenHandler(IPlayerInfoProvider playerInfoProvider, + IBankDataRepository bankDataRepository) + : base(playerInfoProvider) + { + _bankDataRepository = bankDataRepository; + } + + public override bool HandlePacket(IPacket packet) + { + _bankDataRepository.AccountValue = packet.ReadInt(); + _bankDataRepository.SessionID = packet.ReadThree(); + _bankDataRepository.LockerUpgrades = Option.Some(packet.ReadChar()); + + return true; + } + } +} diff --git a/EOLib/PacketHandlers/Bank/BankReplyHandler.cs b/EOLib/PacketHandlers/Bank/BankReplyHandler.cs new file mode 100644 index 000000000..22abb821c --- /dev/null +++ b/EOLib/PacketHandlers/Bank/BankReplyHandler.cs @@ -0,0 +1,40 @@ +using AutomaticTypeMapper; +using EOLib.Domain.Character; +using EOLib.Domain.Interact.Bank; +using EOLib.Domain.Login; +using EOLib.Net; +using EOLib.Net.Handlers; + +namespace EOLib.PacketHandlers.Bank +{ + [AutoMappedType] + public class BankReplyHandler : InGameOnlyPacketHandler + { + private readonly IBankDataRepository _bankDataRepository; + private readonly ICharacterInventoryRepository _characterInventoryRepository; + + public override PacketFamily Family => PacketFamily.Bank; + + public override PacketAction Action => PacketAction.Reply; + + public BankReplyHandler(IPlayerInfoProvider playerInfoProvider, + IBankDataRepository bankDataRepository, + ICharacterInventoryRepository characterInventoryRepository) + : base(playerInfoProvider) + { + _bankDataRepository = bankDataRepository; + _characterInventoryRepository = characterInventoryRepository; + } + + public override bool HandlePacket(IPacket packet) + { + var characterGold = packet.ReadInt(); + _characterInventoryRepository.ItemInventory.RemoveWhere(x => x.ItemID == 1); + _characterInventoryRepository.ItemInventory.Add(new InventoryItem(1, characterGold)); + + _bankDataRepository.AccountValue = packet.ReadInt(); + + return true; + } + } +} diff --git a/EOLib/PacketHandlers/Locker/LockerBuyHandler.cs b/EOLib/PacketHandlers/Locker/LockerBuyHandler.cs new file mode 100644 index 000000000..45502e1a1 --- /dev/null +++ b/EOLib/PacketHandlers/Locker/LockerBuyHandler.cs @@ -0,0 +1,41 @@ +using AutomaticTypeMapper; +using EOLib.Domain.Character; +using EOLib.Domain.Interact.Bank; +using EOLib.Domain.Login; +using EOLib.Net; +using EOLib.Net.Handlers; +using Optional; + +namespace EOLib.PacketHandlers.Locker +{ + [AutoMappedType] + public class LockerBuyHandler : InGameOnlyPacketHandler + { + private readonly IBankDataRepository _bankDataRepository; + private readonly ICharacterInventoryRepository _characterInventoryRepository; + + public override PacketFamily Family => PacketFamily.Locker; + + public override PacketAction Action => PacketAction.Buy; + + public LockerBuyHandler(IPlayerInfoProvider playerInfoProvider, + IBankDataRepository bankDataRepository, + ICharacterInventoryRepository characterInventoryRepository) + : base(playerInfoProvider) + { + _bankDataRepository = bankDataRepository; + _characterInventoryRepository = characterInventoryRepository; + } + + public override bool HandlePacket(IPacket packet) + { + var inventoryGold = packet.ReadInt(); + _characterInventoryRepository.ItemInventory.RemoveWhere(x => x.ItemID == 1); + _characterInventoryRepository.ItemInventory.Add(new InventoryItem(1, inventoryGold)); + + _bankDataRepository.LockerUpgrades = Option.Some(packet.ReadChar()); + + return true; + } + } +} diff --git a/EOLib/misc.cs b/EOLib/misc.cs index df3b4ed1b..aec71ad1f 100644 --- a/EOLib/misc.cs +++ b/EOLib/misc.cs @@ -35,6 +35,7 @@ public static class Constants public const byte ViewLength = 16; public const int LockerMaxSingleItemAmount = 200; + public const int MaxLockerUpgrades = 7; public const int PartyRequestTimeoutSeconds = 15; public const int TradeRequestTimeoutSeconds = 15; public const int MuteDefaultTimeMinutes = 5; diff --git a/EndlessClient/Controllers/NPCInteractionController.cs b/EndlessClient/Controllers/NPCInteractionController.cs index 88b030251..b4f0e5914 100644 --- a/EndlessClient/Controllers/NPCInteractionController.cs +++ b/EndlessClient/Controllers/NPCInteractionController.cs @@ -1,5 +1,6 @@ using AutomaticTypeMapper; using EndlessClient.Dialogs; +using EndlessClient.Dialogs.Actions; using EOLib.Domain.Interact; using EOLib.Domain.NPC; using EOLib.IO.Repositories; @@ -11,14 +12,17 @@ namespace EndlessClient.Controllers public class NPCInteractionController : INPCInteractionController { private readonly IMapNPCActions _mapNpcActions; + private readonly IInGameDialogActions _inGameDialogActions; private readonly IENFFileProvider _enfFileProvider; private readonly IActiveDialogProvider _activeDialogProvider; public NPCInteractionController(IMapNPCActions mapNpcActions, + IInGameDialogActions inGameDialogActions, IENFFileProvider enfFileProvider, IActiveDialogProvider activeDialogProvider) { _mapNpcActions = mapNpcActions; + _inGameDialogActions = inGameDialogActions; _enfFileProvider = enfFileProvider; _activeDialogProvider = activeDialogProvider; } @@ -38,6 +42,13 @@ public void ShowNPCDialog(INPC npc) case EOLib.IO.NPCType.Quest: _mapNpcActions.RequestQuest(npc); break; + case EOLib.IO.NPCType.Bank: + _mapNpcActions.RequestBank(npc); + // note: the npc action types rely on a server response to show the dialog because they are driven + // by config data on the server. Bank account dialog does not have this restriction; + // interaction with the NPC should *always* show the dialog + _inGameDialogActions.ShowBankAccountDialog(); + break; } } } diff --git a/EndlessClient/Dialogs/Actions/InGameDialogActions.cs b/EndlessClient/Dialogs/Actions/InGameDialogActions.cs index 8ee4eba01..63d1e33f4 100644 --- a/EndlessClient/Dialogs/Actions/InGameDialogActions.cs +++ b/EndlessClient/Dialogs/Actions/InGameDialogActions.cs @@ -4,7 +4,6 @@ using EOLib.Domain.Interact; using EOLib.Domain.Interact.Quest; using EOLib.Domain.Interact.Shop; -using EOLib.Domain.NPC; using EOLib.IO; using Optional; @@ -22,6 +21,7 @@ public class InGameDialogActions : IInGameDialogActions, INPCInteractionNotifier private readonly IQuestDataRepository _questDataRepository; private readonly IChestDialogFactory _chestDialogFactory; private readonly ILockerDialogFactory _lockerDialogFactory; + private readonly IBankAccountDialogFactory _bankAccountDialogFactory; private readonly IShopDialogFactory _shopDialogFactory; private readonly IQuestDialogFactory _questDialogFactory; @@ -35,7 +35,8 @@ public InGameDialogActions(IFriendIgnoreListDialogFactory friendIgnoreListDialog IShopDataRepository shopDataRepository, IQuestDataRepository questDataRepository, IChestDialogFactory chestDialogFactory, - ILockerDialogFactory lockerDialogFactory) + ILockerDialogFactory lockerDialogFactory, + IBankAccountDialogFactory bankAccountDialogFactory) { _friendIgnoreListDialogFactory = friendIgnoreListDialogFactory; _paperdollDialogFactory = paperdollDialogFactory; @@ -46,6 +47,7 @@ public InGameDialogActions(IFriendIgnoreListDialogFactory friendIgnoreListDialog _questDataRepository = questDataRepository; _chestDialogFactory = chestDialogFactory; _lockerDialogFactory = lockerDialogFactory; + _bankAccountDialogFactory = bankAccountDialogFactory; _shopDialogFactory = shopDialogFactory; _questDialogFactory = questDialogFactory; } @@ -178,6 +180,18 @@ public void ShowLockerDialog() dlg.Show(); }); } + + public void ShowBankAccountDialog() + { + _activeDialogRepository.BankAccountDialog.MatchNone(() => + { + var dlg = _bankAccountDialogFactory.Create(); + dlg.DialogClosed += (_, _) => _activeDialogRepository.BankAccountDialog = Option.None(); + _activeDialogRepository.BankAccountDialog = Option.Some(dlg); + + dlg.Show(); + }); + } } public interface IInGameDialogActions @@ -199,5 +213,7 @@ public interface IInGameDialogActions void ShowChestDialog(); void ShowLockerDialog(); + + void ShowBankAccountDialog(); } } diff --git a/EndlessClient/Dialogs/ActiveDialogRepository.cs b/EndlessClient/Dialogs/ActiveDialogRepository.cs index 78923528e..11a7e7436 100644 --- a/EndlessClient/Dialogs/ActiveDialogRepository.cs +++ b/EndlessClient/Dialogs/ActiveDialogRepository.cs @@ -25,6 +25,8 @@ public interface IActiveDialogProvider : IDisposable Option LockerDialog { get; } + Option BankAccountDialog { get; } + IReadOnlyList> ActiveDialogs { get; } } @@ -46,6 +48,8 @@ public interface IActiveDialogRepository : IDisposable Option LockerDialog { get; set; } + Option BankAccountDialog { get; set; } + IReadOnlyList> ActiveDialogs { get; } } @@ -68,6 +72,8 @@ public class ActiveDialogRepository : IActiveDialogRepository, IActiveDialogProv public Option LockerDialog { get; set; } + public Option BankAccountDialog { get; set; } + IReadOnlyList> ActiveDialogs { get @@ -82,6 +88,7 @@ IReadOnlyList> ActiveDialogs QuestDialog.Map(d => (IXNADialog)d), ChestDialog.Map(d => (IXNADialog)d), LockerDialog.Map(d => (IXNADialog)d), + BankAccountDialog.Map(d => (IXNADialog)d), }.ToList(); } } @@ -103,6 +110,7 @@ public void Dispose() QuestDialog = Option.None(); ChestDialog = Option.None(); LockerDialog = Option.None(); + BankAccountDialog = Option.None(); } } } diff --git a/EndlessClient/Dialogs/BankAccountDialog.cs b/EndlessClient/Dialogs/BankAccountDialog.cs new file mode 100644 index 000000000..09cd38234 --- /dev/null +++ b/EndlessClient/Dialogs/BankAccountDialog.cs @@ -0,0 +1,243 @@ +using EndlessClient.ControlSets; +using EndlessClient.Dialogs.Factories; +using EndlessClient.Dialogs.Services; +using EndlessClient.HUD; +using EndlessClient.HUD.Controls; +using EndlessClient.HUD.Panels; +using EOLib; +using EOLib.Domain.Character; +using EOLib.Domain.Interact.Bank; +using EOLib.Graphics; +using EOLib.IO.Repositories; +using EOLib.Localization; +using Microsoft.Xna.Framework; +using Optional; +using Optional.Collections; +using System; +using XNAControls; + +namespace EndlessClient.Dialogs +{ + public class BankAccountDialog : ScrollingListDialog + { + private readonly IBankActions _bankActions; + private readonly ILocalizedStringFinder _localizedStringFinder; + private readonly IStatusLabelSetter _statusLabelSetter; + private readonly IEOMessageBoxFactory _messageBoxFactory; + private readonly IItemTransferDialogFactory _itemTransferDialogFactory; + private readonly IBankDataProvider _bankDataProvider; + private readonly ICharacterInventoryProvider _characterInventoryProvider; + private readonly IEIFFileProvider _eifFileProvider; + private readonly InventoryPanel _inventoryPanel; + + private int _cachedValue; + private Option _cachedUpgrades; + + public BankAccountDialog(INativeGraphicsManager nativeGraphicsManager, + IBankActions bankActions, + IEODialogButtonService dialogButtonService, + IEODialogIconService dialogIconService, + ILocalizedStringFinder localizedStringFinder, + IStatusLabelSetter statusLabelSetter, + IEOMessageBoxFactory messageBoxFactory, + IItemTransferDialogFactory itemTransferDialogFactory, + IHudControlProvider hudControlProvider, + IBankDataProvider bankDataProvider, + ICharacterInventoryProvider characterInventoryProvider, + IEIFFileProvider eifFileProvider) + : base(nativeGraphicsManager, dialogButtonService, dialogSize: ScrollingListDialogSize.SmallNoScroll) + { + _bankActions = bankActions; + _localizedStringFinder = localizedStringFinder; + _statusLabelSetter = statusLabelSetter; + _messageBoxFactory = messageBoxFactory; + _itemTransferDialogFactory = itemTransferDialogFactory; + _bankDataProvider = bankDataProvider; + _characterInventoryProvider = characterInventoryProvider; + _eifFileProvider = eifFileProvider; + _inventoryPanel = hudControlProvider.GetComponent(HudControlIdentifier.InventoryPanel); + + ListItemType = ListDialogItem.ListItemStyle.Large; + Buttons = ScrollingListDialogButtons.Cancel; + + _titleText.Text = "0"; + _titleText.TextAlign = LabelAlignment.MiddleRight; + _titleText.AutoSize = false; + + var currencyName = _eifFileProvider.EIFFile[1].Name; + + var depositItem = new ListDialogItem(this, ListDialogItem.ListItemStyle.Large, 0) + { + PrimaryText = _localizedStringFinder.GetString(EOResourceID.DIALOG_BANK_DEPOSIT), + SubText = $"{_localizedStringFinder.GetString(EOResourceID.DIALOG_BANK_TRANSFER)} {currencyName} {_localizedStringFinder.GetString(EOResourceID.DIALOG_BANK_TO_ACCOUNT)}", + IconGraphic = dialogIconService.IconSheet, + IconGraphicSource = dialogIconService.GetDialogIconSource(DialogIcon.BankDeposit), + OffsetY = 55, + ShowIconBackGround = false, + }; + depositItem.LeftClick += Deposit; + depositItem.RightClick += Deposit; + + var withdrawItem = new ListDialogItem(this, ListDialogItem.ListItemStyle.Large, 1) + { + PrimaryText = _localizedStringFinder.GetString(EOResourceID.DIALOG_BANK_WITHDRAW), + SubText = $"{_localizedStringFinder.GetString(EOResourceID.DIALOG_BANK_TRANSFER)} {currencyName} {_localizedStringFinder.GetString(EOResourceID.DIALOG_BANK_FROM_ACCOUNT)}", + IconGraphic = dialogIconService.IconSheet, + IconGraphicSource = dialogIconService.GetDialogIconSource(DialogIcon.BankWithdraw), + OffsetY = 55, + ShowIconBackGround = false, + }; + withdrawItem.LeftClick += Withdraw; + withdrawItem.RightClick += Withdraw; + + var upgradeItem = new ListDialogItem(this, ListDialogItem.ListItemStyle.Large, 2) + { + PrimaryText = _localizedStringFinder.GetString(EOResourceID.DIALOG_BANK_LOCKER_UPGRADE), + SubText = _localizedStringFinder.GetString(EOResourceID.DIALOG_BANK_MORE_SPACE), + IconGraphic = dialogIconService.IconSheet, + IconGraphicSource = dialogIconService.GetDialogIconSource(DialogIcon.BankLockerUpgrade), + OffsetY = 55, + ShowIconBackGround = false, + }; + upgradeItem.LeftClick += Upgrade; + upgradeItem.RightClick += Upgrade; + + AddItemToList(depositItem, sortList: false); + AddItemToList(withdrawItem, sortList: false); + AddItemToList(upgradeItem, sortList: false); + + DrawPosition += new Vector2(0, 50); + } + + protected override void OnUpdateControl(GameTime gameTime) + { + if (_bankDataProvider.AccountValue != _cachedValue) + { + _cachedValue = _bankDataProvider.AccountValue; + Title = $"{_bankDataProvider.AccountValue}"; + } + + _cachedUpgrades.Match( + some: c => + { + _bankDataProvider.LockerUpgrades.MatchSome( + upgrades => + { + if (upgrades != c) + { + _cachedUpgrades = _bankDataProvider.LockerUpgrades; + _statusLabelSetter.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_INFORMATION, EOResourceID.STATUS_LABEL_LOCKER_SPACE_INCREASED); + } + }); + }, + none: () => _cachedUpgrades = _bankDataProvider.LockerUpgrades); + + SuppressClickDragEvent(!_inventoryPanel.NoItemsDragging()); + + base.OnUpdateControl(gameTime); + } + + private void Deposit(object sender, EventArgs e) + { + _characterInventoryProvider.ItemInventory.SingleOrNone(x => x.ItemID == 1) + .Match( + some: characterGold => + { + if (characterGold.Amount == 0) + { + var dlg = _messageBoxFactory.CreateMessageBox(DialogResourceID.BANK_ACCOUNT_UNABLE_TO_DEPOSIT); + dlg.ShowDialog(); + + // todo: show the dialog message as a warning in the status label + } + else if (characterGold.Amount == 1) + { + _bankActions.Deposit(1); + } + else if (characterGold.Amount > 1) + { + var dlg = _itemTransferDialogFactory.CreateItemTransferDialog(_eifFileProvider.EIFFile[1].Name, ItemTransferDialog.TransferType.BankTransfer, characterGold.Amount, EOResourceID.DIALOG_TRANSFER_DEPOSIT); + dlg.DialogClosing += (_, e) => + { + if (e.Result == XNADialogResult.OK) + _bankActions.Deposit(dlg.SelectedAmount); + }; + dlg.ShowDialog(); + } + }, + none: () => + { + var dlg = _messageBoxFactory.CreateMessageBox(DialogResourceID.BANK_ACCOUNT_UNABLE_TO_DEPOSIT); + dlg.ShowDialog(); + + // todo: show the dialog message as a warning in the status label + }); + } + + private void Withdraw(object sender, EventArgs e) + { + if (_bankDataProvider.AccountValue == 0) + { + var dlg = _messageBoxFactory.CreateMessageBox(DialogResourceID.BANK_ACCOUNT_UNABLE_TO_WITHDRAW); + dlg.ShowDialog(); + + // todo: show the dialog message as a warning in the status label + } + else if (_bankDataProvider.AccountValue == 1) + { + _bankActions.Withdraw(1); + } + else if (_bankDataProvider.AccountValue > 1) + { + var dlg = _itemTransferDialogFactory.CreateItemTransferDialog(_eifFileProvider.EIFFile[1].Name, ItemTransferDialog.TransferType.BankTransfer, _bankDataProvider.AccountValue, EOResourceID.DIALOG_TRANSFER_WITHDRAW); + dlg.DialogClosing += (_, e) => + { + if (e.Result == XNADialogResult.OK) + _bankActions.Withdraw(dlg.SelectedAmount); + }; + dlg.ShowDialog(); + } + } + + private void Upgrade(object sender, EventArgs e) + { + _bankDataProvider.LockerUpgrades.MatchSome(lockerUpgrades => + { + if (lockerUpgrades == Constants.MaxLockerUpgrades) + { + var dlg = _messageBoxFactory.CreateMessageBox(DialogResourceID.LOCKER_UPGRADE_IMPOSSIBLE); + dlg.ShowDialog(); + return; + } + + int requiredGold = (lockerUpgrades + 1) * 1000; + + _characterInventoryProvider.ItemInventory.SingleOrNone(x => x.ItemID == 1) + .Match( + some: charaterGold => + { + if (charaterGold.Amount < requiredGold) + { + var dlg = _messageBoxFactory.CreateMessageBox(DialogResourceID.WARNING_YOU_HAVE_NOT_ENOUGH, $" {_eifFileProvider.EIFFile[1].Name}"); + dlg.ShowDialog(); + } + else + { + var dlg = _messageBoxFactory.CreateMessageBox(DialogResourceID.LOCKER_UPGRADE_UNIT, $"{requiredGold} {_eifFileProvider.EIFFile[1].Name}?", EODialogButtons.OkCancel); + dlg.DialogClosing += (_, e) => + { + if (e.Result == XNADialogResult.OK) + _bankActions.BuyStorageUpgrade(); + }; + dlg.ShowDialog(); + } + }, + () => + { + var dlg = _messageBoxFactory.CreateMessageBox(DialogResourceID.WARNING_YOU_HAVE_NOT_ENOUGH, $" {_eifFileProvider.EIFFile[1].Name}"); + dlg.ShowDialog(); + }); + }); + } + } +} diff --git a/EndlessClient/Dialogs/Factories/BankAccountDialogFactory.cs b/EndlessClient/Dialogs/Factories/BankAccountDialogFactory.cs new file mode 100644 index 000000000..908bbc221 --- /dev/null +++ b/EndlessClient/Dialogs/Factories/BankAccountDialogFactory.cs @@ -0,0 +1,77 @@ +using AutomaticTypeMapper; +using EndlessClient.ControlSets; +using EndlessClient.Dialogs.Services; +using EndlessClient.HUD; +using EOLib.Domain.Character; +using EOLib.Domain.Interact.Bank; +using EOLib.Graphics; +using EOLib.IO.Repositories; +using EOLib.Localization; + +namespace EndlessClient.Dialogs.Factories +{ + [AutoMappedType] + public class BankAccountDialogFactory : IBankAccountDialogFactory + { + private readonly INativeGraphicsManager _nativeGraphicsManager; + private readonly IBankActions _bankActions; + private readonly IEODialogButtonService _dialogButtonService; + private readonly IEODialogIconService _dialogIconService; + private readonly ILocalizedStringFinder _localizedStringFinder; + private readonly IStatusLabelSetter _statusLabelSetter; + private readonly IEOMessageBoxFactory _messageBoxFactory; + private readonly IItemTransferDialogFactory _itemTransferDialogFactory; + private readonly IHudControlProvider _hudControlProvider; + private readonly IBankDataProvider _bankDataProvider; + private readonly ICharacterInventoryProvider _characterInventoryProvider; + private readonly IEIFFileProvider _eifFileProvider; + + public BankAccountDialogFactory(INativeGraphicsManager nativeGraphicsManager, + IBankActions bankActions, + IEODialogButtonService dialogButtonService, + IEODialogIconService dialogIconService, + ILocalizedStringFinder localizedStringFinder, + IStatusLabelSetter statusLabelSetter, + IEOMessageBoxFactory messageBoxFactory, + IItemTransferDialogFactory itemTransferDialogFactory, + IHudControlProvider hudControlProvider, + IBankDataProvider bankDataProvider, + ICharacterInventoryProvider characterInventoryProvider, + IEIFFileProvider eifFileProvider) + { + _nativeGraphicsManager = nativeGraphicsManager; + _bankActions = bankActions; + _dialogButtonService = dialogButtonService; + _dialogIconService = dialogIconService; + _localizedStringFinder = localizedStringFinder; + _statusLabelSetter = statusLabelSetter; + _messageBoxFactory = messageBoxFactory; + _itemTransferDialogFactory = itemTransferDialogFactory; + _hudControlProvider = hudControlProvider; + _bankDataProvider = bankDataProvider; + _characterInventoryProvider = characterInventoryProvider; + _eifFileProvider = eifFileProvider; + } + + public BankAccountDialog Create() + { + return new BankAccountDialog(_nativeGraphicsManager, + _bankActions, + _dialogButtonService, + _dialogIconService, + _localizedStringFinder, + _statusLabelSetter, + _messageBoxFactory, + _itemTransferDialogFactory, + _hudControlProvider, + _bankDataProvider, + _characterInventoryProvider, + _eifFileProvider); + } + } + + public interface IBankAccountDialogFactory + { + BankAccountDialog Create(); + } +} diff --git a/EndlessClient/Dialogs/Old/BankAccountDialog.cs b/EndlessClient/Dialogs/Old/BankAccountDialog.cs deleted file mode 100644 index 52af6d17d..000000000 --- a/EndlessClient/Dialogs/Old/BankAccountDialog.cs +++ /dev/null @@ -1,216 +0,0 @@ -using EndlessClient.Dialogs.Services; -using EndlessClient.Old; -using EOLib; -using EOLib.Domain.Character; -using EOLib.Graphics; -using EOLib.Localization; -using EOLib.Net; -using EOLib.Net.API; -using Microsoft.Xna.Framework; -using XNAControls.Old; - -namespace EndlessClient.Dialogs.Old -{ - public class BankAccountDialog : EODialogBase - { - public static BankAccountDialog Instance { get; private set; } - - public static void Show(PacketAPI api, short npcID) - { - if (Instance != null) - return; - - Instance = new BankAccountDialog(api); - - if (!api.BankOpen(npcID)) - { - Instance.Close(); - Instance = null; - EOGame.Instance.DoShowLostConnectionDialogAndReturnToMainMenu(); - } - } - - private readonly XNALabel m_accountBalance; - - public string AccountBalance - { - get { return m_accountBalance.Text; } - set { m_accountBalance.Text = value; } - } - - public int LockerUpgrades { get; set; } - - private BankAccountDialog(PacketAPI api) - : base(api) - { - //this uses EODialogListItems but does not inherit from ListDialog since it is a different size - //offsety 50 - bgTexture = ((EOGame)Game).GFXManager.TextureFromResource(GFXTypes.PostLoginUI, 53); - _setSize(bgTexture.Width, bgTexture.Height); - - m_accountBalance = new XNALabel(new Rectangle(129, 20, 121, 16), Constants.FontSize08pt5) - { - ForeColor = ColorConstants.LightGrayText, - Text = "", - TextAlign = LabelAlignment.MiddleRight, - AutoSize = false - }; - m_accountBalance.SetParent(this); - - XNAButton cancel = new XNAButton(smallButtonSheet, new Vector2(92, 191), _getSmallButtonOut(SmallButton.Cancel), _getSmallButtonOver(SmallButton.Cancel)); - cancel.SetParent(this); - cancel.OnClick += (o, e) => Close(cancel, XNADialogResult.Cancel); - - OldListDialogItem deposit = new OldListDialogItem(this, OldListDialogItem.ListItemStyle.Large, 0) - { - Text = OldWorld.GetString(EOResourceID.DIALOG_BANK_DEPOSIT), - SubText = - $"{OldWorld.GetString(EOResourceID.DIALOG_BANK_TRANSFER)} gold {OldWorld.GetString(EOResourceID.DIALOG_BANK_TO_ACCOUNT)}", - IconGraphic = _getDlgIcon(ListIcon.BankDeposit), - OffsetY = 55, - ShowItemBackGround = false - }; - deposit.OnLeftClick += (o, e) => _deposit(); - deposit.OnRightClick += (o, e) => _deposit(); - OldListDialogItem withdraw = new OldListDialogItem(this, OldListDialogItem.ListItemStyle.Large, 1) - { - Text = OldWorld.GetString(EOResourceID.DIALOG_BANK_WITHDRAW), - SubText = - $"{OldWorld.GetString(EOResourceID.DIALOG_BANK_TAKE)} gold {OldWorld.GetString(EOResourceID.DIALOG_BANK_FROM_ACCOUNT)}", - IconGraphic = _getDlgIcon(ListIcon.BankWithdraw), - OffsetY = 55, - ShowItemBackGround = false - }; - withdraw.OnLeftClick += (o, e) => _withdraw(); - withdraw.OnRightClick += (o, e) => _withdraw(); - OldListDialogItem upgrade = new OldListDialogItem(this, OldListDialogItem.ListItemStyle.Large, 2) - { - Text = OldWorld.GetString(EOResourceID.DIALOG_BANK_LOCKER_UPGRADE), - SubText = OldWorld.GetString(EOResourceID.DIALOG_BANK_MORE_SPACE), - IconGraphic = _getDlgIcon(ListIcon.BankLockerUpgrade), - OffsetY = 55, - ShowItemBackGround = false - }; - upgrade.OnLeftClick += (o, e) => _upgrade(); - upgrade.OnRightClick += (o, e) => _upgrade(); - - DialogClosing += (o, e) => { Instance = null; }; - - Center(Game.GraphicsDevice); - DrawLocation = new Vector2(DrawLocation.X, 50); - endConstructor(false); - } - - private void _deposit() - { - InventoryItem item = OldWorld.Instance.MainPlayer.ActiveCharacter.Inventory.Find(i => i.ItemID == 1); - if (item.Amount == 0) - { - EOMessageBox.Show(DialogResourceID.BANK_ACCOUNT_UNABLE_TO_DEPOSIT, EODialogButtons.Ok, EOMessageBoxStyle.SmallDialogSmallHeader); - return; - } - if (item.Amount == 1) - { - if (!m_api.BankDeposit(1)) - { - Close(null, XNADialogResult.NO_BUTTON_PRESSED); - EOGame.Instance.DoShowLostConnectionDialogAndReturnToMainMenu(); - } - return; - } - - ItemTransferDialog dlg = new ItemTransferDialog(OldWorld.Instance.EIF[1].Name, - ItemTransferDialog.TransferType.BankTransfer, item.Amount, EOResourceID.DIALOG_TRANSFER_DEPOSIT); - dlg.DialogClosing += (o, e) => - { - if (e.Result == XNADialogResult.Cancel) - return; - - if (!m_api.BankDeposit(dlg.SelectedAmount)) - { - Close(null, XNADialogResult.NO_BUTTON_PRESSED); - EOGame.Instance.DoShowLostConnectionDialogAndReturnToMainMenu(); - } - }; - } - - private void _withdraw() - { - int balance = int.Parse(AccountBalance); - if (balance == 0) - { - EOMessageBox.Show(DialogResourceID.BANK_ACCOUNT_UNABLE_TO_WITHDRAW, EODialogButtons.Ok, EOMessageBoxStyle.SmallDialogSmallHeader); - return; - } - if (balance == 1) - { - if (!m_api.BankWithdraw(1)) - { - Close(null, XNADialogResult.NO_BUTTON_PRESSED); - EOGame.Instance.DoShowLostConnectionDialogAndReturnToMainMenu(); - } - return; - } - - ItemTransferDialog dlg = new ItemTransferDialog(OldWorld.Instance.EIF[1].Name, - ItemTransferDialog.TransferType.BankTransfer, balance, EOResourceID.DIALOG_TRANSFER_WITHDRAW); - dlg.DialogClosing += (o, e) => - { - if (e.Result == XNADialogResult.Cancel) - return; - - if (!m_api.BankWithdraw(dlg.SelectedAmount)) - { - Close(null, XNADialogResult.NO_BUTTON_PRESSED); - EOGame.Instance.DoShowLostConnectionDialogAndReturnToMainMenu(); - } - }; - } - - private void _upgrade() - { - if (LockerUpgrades == 7) - { - EOMessageBox.Show(DialogResourceID.LOCKER_UPGRADE_IMPOSSIBLE, EODialogButtons.Ok, EOMessageBoxStyle.SmallDialogSmallHeader); - return; - } - - int requiredGold = (LockerUpgrades + 1) * 1000; - InventoryItem item = OldWorld.Instance.MainPlayer.ActiveCharacter.Inventory.Find(i => i.ItemID == 1); - if (item.Amount < requiredGold) - { - EOMessageBox.Show(DialogResourceID.WARNING_YOU_HAVE_NOT_ENOUGH, "gold", EODialogButtons.Ok, EOMessageBoxStyle.SmallDialogSmallHeader); - return; - } - - EOMessageBox.Show(DialogResourceID.LOCKER_UPGRADE_UNIT, $"{requiredGold} gold?", EODialogButtons.OkCancel, - EOMessageBoxStyle.SmallDialogSmallHeader, - (o, e) => - { - if (e.Result == XNADialogResult.Cancel) - return; - - OldPacket pkt = new OldPacket(PacketFamily.Locker, PacketAction.Buy); - OldWorld.Instance.Client.SendPacket(pkt); - }); - } - - public override void Update(GameTime gt) - { - if (!Game.IsActive) return; - - //if (EOGame.Instance.Hud.IsInventoryDragging()) - //{ - // shouldClickDrag = false; - // SuppressParentClickDrag(true); - //} - //else - //{ - // shouldClickDrag = true; - // SuppressParentClickDrag(false); - //} - - base.Update(gt); - } - } -} diff --git a/EndlessClient/Dialogs/ScrollingListDialog.cs b/EndlessClient/Dialogs/ScrollingListDialog.cs index 23989eb4c..c4901c2cf 100644 --- a/EndlessClient/Dialogs/ScrollingListDialog.cs +++ b/EndlessClient/Dialogs/ScrollingListDialog.cs @@ -41,6 +41,7 @@ public enum ScrollingListDialogSize Medium, // quest progress/history dialog MediumWithHeader, // todo: implement boards Small, // npc quest dialog + SmallNoScroll, // bank account dialog } public class ScrollingListDialog : BaseEODialog @@ -187,7 +188,7 @@ public ScrollingListDialog(INativeGraphicsManager nativeGraphicsManager, _scrollBar = new ScrollBar(new Vector2(DialogSize == ScrollingListDialogSize.Medium ? 449 : 252, 44), new Vector2(16, GetScrollBarHeight(DialogSize)), ScrollBarColors.LightOnMed, GraphicsManager) { - Visible = DialogSize != ScrollingListDialogSize.LargeNoScroll, + Visible = DialogSize != ScrollingListDialogSize.LargeNoScroll && DialogSize != ScrollingListDialogSize.SmallNoScroll, }; _scrollBar.SetParentControl(this); @@ -404,6 +405,7 @@ private static Rectangle GetTitleDrawArea(ScrollingListDialogSize size) case ScrollingListDialogSize.LargeNoScroll: return new Rectangle(16, 13, 253, 19); case ScrollingListDialogSize.Medium: return new Rectangle(18, 14, 452, 19); case ScrollingListDialogSize.Small: return new Rectangle(16, 16, 255, 18); + case ScrollingListDialogSize.SmallNoScroll: return new Rectangle(129, 20, 121, 16); default: throw new NotImplementedException(); } } @@ -415,7 +417,8 @@ private static int GetScrollBarHeight(ScrollingListDialogSize size) case ScrollingListDialogSize.Large: case ScrollingListDialogSize.LargeNoScroll: case ScrollingListDialogSize.Medium: return 199; - case ScrollingListDialogSize.Small: return 99; + case ScrollingListDialogSize.Small: + case ScrollingListDialogSize.SmallNoScroll: return 99; default: throw new NotImplementedException(); } } @@ -428,6 +431,7 @@ private static int GetBackgroundTexture(ScrollingListDialogSize size) case ScrollingListDialogSize.LargeNoScroll: return 51; case ScrollingListDialogSize.Medium: return 59; case ScrollingListDialogSize.Small: return 67; + case ScrollingListDialogSize.SmallNoScroll: return 53; default: throw new NotImplementedException(); } } @@ -439,7 +443,8 @@ private static int GetBackgroundTexture(ScrollingListDialogSize size) case ScrollingListDialogSize.Large: case ScrollingListDialogSize.LargeNoScroll: return null; case ScrollingListDialogSize.Medium: return new Rectangle(0, 0, backgroundTexture.Width, backgroundTexture.Height / 2); - case ScrollingListDialogSize.Small: return null; + case ScrollingListDialogSize.Small: + case ScrollingListDialogSize.SmallNoScroll: return null; default: throw new NotImplementedException(); } } @@ -451,7 +456,8 @@ private static Vector2 GetButton1Position(Rectangle dialogArea, Rectangle button { // buttons are centered on these dialogs case ScrollingListDialogSize.Large: - case ScrollingListDialogSize.LargeNoScroll: return new Vector2((int)Math.Floor((dialogArea.Width - buttonArea.Width) / 2.0) - 48, yCoord); + case ScrollingListDialogSize.LargeNoScroll: + case ScrollingListDialogSize.SmallNoScroll: return new Vector2((int)Math.Floor((dialogArea.Width - buttonArea.Width) / 2.0) - 48, yCoord); // buttons are offset from center on these dialogs case ScrollingListDialogSize.Medium: return new Vector2(288, yCoord); case ScrollingListDialogSize.Small: return new Vector2(89, yCoord); @@ -466,7 +472,8 @@ private static Vector2 GetButton2Position(Rectangle dialogArea, Rectangle button { // buttons are centered on these dialogs case ScrollingListDialogSize.Large: - case ScrollingListDialogSize.LargeNoScroll: return new Vector2((int)Math.Floor((dialogArea.Width - buttonArea.Width) / 2.0) + 48, yCoord); + case ScrollingListDialogSize.LargeNoScroll: + case ScrollingListDialogSize.SmallNoScroll: return new Vector2((int)Math.Floor((dialogArea.Width - buttonArea.Width) / 2.0) + 48, yCoord); // buttons are offset from center on these dialogs case ScrollingListDialogSize.Medium: return new Vector2(380, yCoord); case ScrollingListDialogSize.Small: return new Vector2(183, yCoord); @@ -480,6 +487,10 @@ private static Vector2 GetButtonCenterPosition(Rectangle dialogArea, Rectangle b if (dialogSize == ScrollingListDialogSize.LargeNoScroll) return new Vector2(92, 227); + // bank dialog has a button built in to the graphic that needs to be covered up... + if (dialogSize == ScrollingListDialogSize.SmallNoScroll) + return new Vector2(92, 191); + var yCoord = GetButtonYCoordinate(dialogArea); return new Vector2((dialogArea.Width - buttonArea.Width) / 2, yCoord); } diff --git a/EndlessClient/Old/PacketAPICallbackManager.cs b/EndlessClient/Old/PacketAPICallbackManager.cs index 8f6dab2a7..fbfc0cc73 100644 --- a/EndlessClient/Old/PacketAPICallbackManager.cs +++ b/EndlessClient/Old/PacketAPICallbackManager.cs @@ -29,13 +29,6 @@ public void AssignCallbacks() //npc related m_packetAPI.OnRemoveChildNPCs += _removeChildNPCs; - //bank related - m_packetAPI.OnBankOpen += _bankOpen; - m_packetAPI.OnBankChange += _bankChange; - - //locker - m_packetAPI.OnLockerUpgrade += _lockerUpgrade; - //party m_packetAPI.OnPartyClose += _partyClose; m_packetAPI.OnPartyDataRefresh += _partyDataRefresh; @@ -85,29 +78,6 @@ private void _removeChildNPCs(short childNPCID) OldWorld.Instance.ActiveMapRenderer.RemoveNPCsWhere(x => x.NPC.Data.ID == childNPCID); } - private void _bankOpen(int gold, int upgrades) - { - if (BankAccountDialog.Instance == null) return; - BankAccountDialog.Instance.AccountBalance = $"{gold}"; - BankAccountDialog.Instance.LockerUpgrades = upgrades; - } - - private void _bankChange(int gold, int bankGold) - { - if (BankAccountDialog.Instance == null) return; - - //OldWorld.Instance.MainPlayer.ActiveCharacter.UpdateInventoryItem(1, gold); - BankAccountDialog.Instance.AccountBalance = $"{bankGold}"; - } - - private void _lockerUpgrade(int remaining, byte upgrades) - { - if (BankAccountDialog.Instance == null) return; - //OldWorld.Instance.MainPlayer.ActiveCharacter.UpdateInventoryItem(1, remaining); - BankAccountDialog.Instance.LockerUpgrades = upgrades; - m_game.Hud.SetStatusLabel(EOResourceID.STATUS_LABEL_TYPE_INFORMATION, EOResourceID.STATUS_LABEL_LOCKER_SPACE_INCREASED); - } - private void _partyClose() { m_game.Hud.CloseParty(); diff --git a/EndlessClient/Rendering/OldNPCRenderer.cs b/EndlessClient/Rendering/OldNPCRenderer.cs index 48d7c4edc..bcda918ae 100644 --- a/EndlessClient/Rendering/OldNPCRenderer.cs +++ b/EndlessClient/Rendering/OldNPCRenderer.cs @@ -333,7 +333,6 @@ private void HandleLeftClick() switch (NPC.Data.Type) { case NPCType.Inn: break; - case NPCType.Bank: BankAccountDialog.Show(api, NPC.Index); break; case NPCType.Barber: break; case NPCType.Guild: break; case NPCType.Priest: break;