using System; using UnityEngine; namespace GeometryTD.UI { public class CombatSelectFormUseCase : IUIUseCase { private const int BuildOptionCount = 4; private readonly Option[] _buildOptions = new Option[BuildOptionCount]; private readonly Option _upgradeOption = new Option(CombatSelectActionType.UpgradeTower, 0, true); private readonly Option _destroyOption = new Option(CombatSelectActionType.DestroyTower, 0, false); private Func _coinProvider; private bool _isVisible; private CombatSelectDisplayMode _displayMode = CombatSelectDisplayMode.Hidden; private Vector2 _contentPosition; public CombatSelectFormUseCase() { _coinProvider = DefaultCoinProvider; for (int i = 0; i < BuildOptionCount; i++) { _buildOptions[i] = new Option(CombatSelectActionType.BuildTower, i, true); } } public CombatSelectFormRawData CreateInitialModel() { return BuildModel(); } public CombatSelectFormRawData TryRefresh() { return BuildModel(); } public void SetCoinProvider(Func coinProvider) { _coinProvider = coinProvider ?? DefaultCoinProvider; } public void SetBuildAction(int buildIndex, Func buildAction, int cost, Sprite icon = null) { if (buildIndex < 0 || buildIndex >= _buildOptions.Length) { return; } Option option = _buildOptions[buildIndex]; option.Action = buildAction; option.Price = Mathf.Max(0, cost); option.Icon = icon; option.IsGain = false; option.IsVisible = true; } public void SetBuildAction(int buildIndex, Action buildAction, int cost, Sprite icon = null) { if (buildAction == null) { SetBuildAction(buildIndex, (Func)null, cost, icon); return; } SetBuildAction( buildIndex, () => { buildAction.Invoke(); return true; }, cost, icon); } public void SetUpgradeAction(Func upgradeAction, int cost, Sprite icon = null) { _upgradeOption.Action = upgradeAction; _upgradeOption.Price = Mathf.Max(0, cost); _upgradeOption.Icon = icon; _upgradeOption.IsGain = false; _upgradeOption.IsVisible = true; } public void SetUpgradeAction(Action upgradeAction, int cost, Sprite icon = null) { if (upgradeAction == null) { SetUpgradeAction((Func)null, cost, icon); return; } SetUpgradeAction( () => { upgradeAction.Invoke(); return true; }, cost, icon); } public void SetDestroyAction(Func destroyAction, int gain, Sprite icon = null) { _destroyOption.Action = destroyAction; _destroyOption.Price = Mathf.Max(0, gain); _destroyOption.Icon = icon; _destroyOption.IsGain = true; _destroyOption.IsVisible = true; } public void SetDestroyAction(Action destroyAction, int gain, Sprite icon = null) { if (destroyAction == null) { SetDestroyAction((Func)null, gain, icon); return; } SetDestroyAction( () => { destroyAction.Invoke(); return true; }, gain, icon); } public void SetUpgradePrice(int cost) { _upgradeOption.Price = Mathf.Max(0, cost); } public void SetUpgradeVisible(bool visible) { _upgradeOption.IsVisible = visible; } public void SetDestroyGain(int gain) { _destroyOption.Price = Mathf.Max(0, gain); _destroyOption.IsGain = true; } public void ShowForFoundation(Vector2 contentPosition) { _contentPosition = contentPosition; _displayMode = CombatSelectDisplayMode.Build; _isVisible = true; } public void ShowForTower(Vector2 contentPosition) { _contentPosition = contentPosition; _displayMode = CombatSelectDisplayMode.Func; _isVisible = true; } public void Hide() { _isVisible = false; _displayMode = CombatSelectDisplayMode.Hidden; } public bool TryExecuteAction(CombatSelectActionType actionType, int actionIndex) { if (!_isVisible) { return false; } Option option = GetOption(actionType, actionIndex); if (option == null || !option.IsVisible) { return false; } int currentCoin = Mathf.Max(0, _coinProvider != null ? _coinProvider.Invoke() : 0); if (!CanExecute(option, currentCoin)) { return false; } if (option.Action == null) { return false; } bool result = option.Action.Invoke(); if (result) { Hide(); } return result; } private CombatSelectFormRawData BuildModel() { int currentCoin = Mathf.Max(0, _coinProvider != null ? _coinProvider.Invoke() : 0); TowerSelectItemRawData[] buildItems = new TowerSelectItemRawData[_buildOptions.Length]; for (int i = 0; i < _buildOptions.Length; i++) { buildItems[i] = BuildOptionRawData(_buildOptions[i], currentCoin); } return new CombatSelectFormRawData { IsVisible = _isVisible, ContentPosition = _contentPosition, DisplayMode = _displayMode, BuildItems = buildItems, UpgradeItem = BuildOptionRawData(_upgradeOption, currentCoin), DestroyItem = BuildOptionRawData(_destroyOption, currentCoin) }; } private Option GetOption(CombatSelectActionType actionType, int actionIndex) { switch (actionType) { case CombatSelectActionType.BuildTower: if (actionIndex < 0 || actionIndex >= _buildOptions.Length) { return null; } return _buildOptions[actionIndex]; case CombatSelectActionType.UpgradeTower: return _upgradeOption; case CombatSelectActionType.DestroyTower: return _destroyOption; default: return null; } } private static int DefaultCoinProvider() { if (GameEntry.CombatNode == null) { return 0; } return Mathf.Max(0, GameEntry.CombatNode.CurrentCoin); } private static bool CanExecute(Option option, int currentCoin) { if (option == null) { return false; } if (option.RequiresAffordable && currentCoin < option.Price) { return false; } return true; } private static TowerSelectItemRawData BuildOptionRawData(Option option, int currentCoin) { if (option == null) { return null; } return new TowerSelectItemRawData { Icon = option.Icon, Price = option.Price, IsGain = option.IsGain, IsVisible = option.IsVisible, IsInteractable = option.Action != null && CanExecute(option, currentCoin), ActionType = option.ActionType, ActionIndex = option.ActionIndex }; } private sealed class Option { public readonly CombatSelectActionType ActionType; public readonly int ActionIndex; public readonly bool RequiresAffordable; public int Price; public bool IsGain; public bool IsVisible = true; public Sprite Icon; public Func Action; public Option(CombatSelectActionType actionType, int actionIndex, bool requiresAffordable) { ActionType = actionType; ActionIndex = actionIndex; RequiresAffordable = requiresAffordable; } } } }