using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using BITKit; using BITKit.Entities; using UnityEngine.InputSystem; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using BITFALL.Entities; using BITFALL.Entities.Improvised; using BITFALL.Entities.Inventory; using BITFALL.Player.Equip; using BITFALL.Player.Inventory; using BITKit.Entities.Player; using BITKit.UX; using Cysharp.Threading.Tasks; using JetBrains.Annotations; using UnityEditor; using UnityEngine.EventSystems; using UnityEngine.InputSystem.Interactions; using Debug = UnityEngine.Debug; namespace BITFALL.Entities.Equipment { [CustomType(typeof(IPlayerEquipSelector))] public class PlayerEquipSelector : EntityBehavior,IPlayerEquipSelector { [Header(Constant.Header.InternalVariables)] private readonly Dictionary equips=new(); [Header(Constant.Header.Input)] [SerializeField] private InputActionReference primaryAction; [SerializeField] private InputActionReference secondaryAction; [SerializeField] private InputActionReference tertiaryAction; [SerializeField] private InputActionReference quaternaryAction; [SerializeField] private InputActionReference holsterAction; [SerializeField] private InputActionReference throwAction; [SerializeField] private InputActionReference tacticsAction; [SerializeField] private InputActionReference scrollAction; public event Func TryEquipFactory; public event Action> OnUpdateEquip; [Inject] private IEntityInventory _inventory; [Inject(true)] private IKnockdown _knockdown; [Inject] private IHealth _health; private IBasicItem currentEquip; [Inject(true)] private IEntityEquipment _equipment; [Inject(true)] private ImprovisedServiceInterface _improvisedService; [Inject] private IEntityEquipmentContainer _equipmentContainer; [Inject] private IEquipService _equipService; [Inject(true)] private InputActionGroup _inputActionGroup; [Inject(true)] private IUXPopup _uxPopup; private readonly List _blockList=new(); private readonly Optional playerChoose = new (); public override void OnAwake() { _health.OnSetAlive += OnSetAlive; if (_knockdown is not null) { _knockdown.OnKnockdown += () => { if (currentEquip is null) return; if (currentEquip.GetAssetable().AllowUseWhileKnocked) return; Equip(null); }; _knockdown.OnRevive += () => { if (playerChoose.Allow) { Equip(playerChoose.Value); } }; } if (_inputActionGroup is not null) { if (primaryAction) _inputActionGroup.RegisterCallback(primaryAction, OnPrimary); if (secondaryAction) _inputActionGroup.RegisterCallback(secondaryAction, OnSecondary); if (tertiaryAction) _inputActionGroup.RegisterCallback(tertiaryAction, OnTertiary); if (quaternaryAction) _inputActionGroup.RegisterCallback(quaternaryAction, OnQuaternary); if (holsterAction) _inputActionGroup.RegisterCallback(holsterAction, OnHolster); if (throwAction) _inputActionGroup.RegisterCallback(throwAction, Throw); if (tacticsAction) _inputActionGroup.RegisterCallback(tacticsAction, OnTactics); if(scrollAction) _inputActionGroup.RegisterCallback(scrollAction, OnScroll); } if (_improvisedService is not null) { _improvisedService.OnEquipImprovisedItem += OnEquipImprovisedItem; _improvisedService.OnUnEquipImprovisedItem += OnUnEquipImprovisedItem; _improvisedService.OnTryEquipImprovisedItem += OnTryEquipImprovisedItem; _improvisedService.OnTryUnEquipImprovisedItem += OnTryUnEquipImprovisedItem; } } private void OnScroll(InputAction.CallbackContext obj) { if (BITAppForUnity.AllowCursor) return; if (obj.performed is false) return; var value = obj.ReadValue().y; if (playerChoose.Allow is false) { if (equips.ContainsKey(1)) { playerChoose.SetValueThenAllow(1); Equip(1); }else if (equips.ContainsKey(2)) { playerChoose.SetValueThenAllow(2); Equip(2); } } //Debug.Log(playerChoose.Value); var nextChoose = playerChoose.Value is 1 ? 2 : 1; if (equips.ContainsKey(nextChoose)) { playerChoose.SetValueThenAllow(nextChoose); Equip(nextChoose); } } public override void OnStart() { base.OnStart(); _inventory.TryUseItemFactory += TryEquip; _inventory.OnUsedItem += OnEquip; _inventory.OnAdd += OnAdd; _inventory.OnRemove += OnRemove; } public override void OnUpdate(float deltaTime) { base.OnUpdate(deltaTime); if (_knockdown is not null) { _equipService.AllowEquip.SetDisableElements(1868448, _knockdown.IsPressured); } } private bool OnTryUnEquipImprovisedItem(IBasicItem arg) { return true; } private bool OnTryEquipImprovisedItem(IBasicItem arg) { return true; } private void OnUnEquipImprovisedItem(IBasicItem obj) { Cancel(); } private void OnEquipImprovisedItem(IBasicItem obj) { Equip(obj); } public void OnPrimary(InputAction.CallbackContext context) { if (context is not {interaction:PressInteraction ,performed:true}) return; Equip(1); playerChoose.SetValueThenAllow(1); } public void OnSecondary(InputAction.CallbackContext context) { if (context is not {interaction:PressInteraction ,performed:true}) return; Equip(2); playerChoose.SetValueThenAllow(2); } public void OnTertiary(InputAction.CallbackContext context) { if (context is not {interaction:PressInteraction ,performed:true}) return; if (Equip(3) is false) { Equip(-1); playerChoose.Clear(); } else { playerChoose.SetValueThenAllow(3); } } public void OnQuaternary(InputAction.CallbackContext context) { if (context is not {interaction:PressInteraction ,performed:true}) return; Equip(); } public void OnHolster(InputAction.CallbackContext context) { if (context is not {interaction:PressInteraction ,performed:true}) return; Equip(-1); } private void OnSetAlive(bool alive) { _equipService.AllowEquip.SetDisableElements(this,!alive); if (alive) { if (playerChoose.Allow) { Equip(playerChoose.Value); } } else { Equip(-1); if (Data.Get(BITConstant.Environment.sp_keepInventory)) return; foreach (var x in equips.ToArray()) { _inventory.Add(x.Value); } equips.Clear(); UpdateEquip(); } } private bool TryEquip(IBasicItem value) { if (_equipService.AllowEquip.Allow is false) return false; switch (_knockdown) { case not null when _knockdown.IsKnockdown && value.GetAssetable().AllowUseWhileKnocked is false: return false; } var asset = value.GetAssetable(); if (_equipment.IsSupportItem(value) is false) return false; switch (asset) { case var _ when asset.TryGetProperty(out _): var index = 0; if (equips.TryAdd(++index, value) || equips.TryAdd(++index,value)) { _equipment.EntryEquip(value); UpdateEquip(); _improvisedService?.TryUnEquipImprovised(out _); currentEquip = value; _inventory.UseItem(value); playerChoose.SetValueThenAllow(index); return true; } break; case var _ when asset.TryGetProperty(out _): //if (TryEquipFactory?.CastAsFunc().Any(x => x.Invoke(value)) is false) return false; foreach (var func in TryEquipFactory.CastAsFunc()) { try { func.Invoke(value); } catch (InGameException e) { _uxPopup.Popup(e.Message); return false; } } _equipment.EntryEquip(value); _improvisedService?.TryUnEquipImprovised(out _); currentEquip = value; return true; case var _ when asset.TryGetProperty(out var equipAsSlot): break; } return false; } public async void OnAdd(IBasicItem item) { if (_blockList.Contains(item.Id)) return; if (_equipment.IsSupportItem(item) is false) { UpdateEquip(); } if (currentEquip is not null && currentEquip.AddressablePath == item.AddressablePath) { if (equips.TryGetAny(x => x.Value.AddressablePath == item.AddressablePath, out var pair)) { equips.Remove(pair.Key); UpdateEquip(); } currentEquip = null; _equipment.EntryEquip((IBasicItem)null); } else { try { for (var i = 0; i < 8; i++) { await UniTask.NextFrame(); } if (_equipment.IsSupportItem(item) && item.GetAssetable().TryGetProperty(out _)) { _inventory.TryUseItem(item); } } catch (OperationCanceledException) { } } } private void OnTactics(InputAction.CallbackContext obj) { // switch(obj) // { // case {interaction:TapInteraction, performed: true}: // Equip(); // break; // } } public void Throw(InputAction.CallbackContext context) { //Debug.Log(context); switch (context) { case {interaction:TapInteraction, started: true}: Equip(); break; } // switch (context) // { // case { interaction: HoldInteraction, performed: true }: // if (currentEquip is null) return; // if (equips.TryGetAny(x => x.Value.AddressablePath == currentEquip.AddressablePath, out var pair)) // { // if (_inventory.DropOrSpawn(currentEquip)) // { // equips.Remove(pair.Key); // _equipment.EntryEquip((IBasicItem)null); // currentEquip = null; // UpdateEquip(); // } // } // // break; // case { interaction: TapInteraction, performed: true }: // Equip(); // break; // } } public void OnRemove(IBasicItem item) { _blockList.Add(item.Id); if (_equipment.IsSupportItem(item) is false) { UpdateEquip(); } } private void OnEquip(IBasicItem obj) { _blockList.Add(obj.Id); } private void UpdateEquip() { OnUpdateEquip?.Invoke(new Dictionary(equips)); } public IDictionary Equipped => new Dictionary(equips); public bool TryDeEquip(IBasicItem item) { if (item is null) return false; if (equips.Any(x => x.Value.AddressablePath == item.AddressablePath) is false) return false; var index = equips.First(x=>x.Value.AddressablePath==item.AddressablePath).Key; if (equips.TryRemove(index) is false) return false; if (!_inventory.Add(item)) return false; if (currentEquip?.AddressablePath == item.AddressablePath) { Equip(null); playerChoose.Clear(); } UpdateEquip(); return true; } public async void Cancel() { await UniTask.NextFrame(); if (playerChoose.Allow) { if (Equip(playerChoose.Value)) { return; }; //playerChoose.Clear(); } Equip(null); return; } private void Equip(IBasicItem item) { if (item is not null && _equipService.AllowEquip.Allow is false) return; _equipment.EntryEquip(item); currentEquip = item; } private bool Equip(int index) { if (index is not -1) { if (_equipService.AllowEquip.Allow is false) return false; } if (!equips.TryGetValue(index, out var x) && index is not -1) return false; if (index is not -1 && _knockdown is not null && _knockdown.IsKnockdown) { if (x.GetAssetable().AllowUseWhileKnocked is false) return false; } currentEquip = x; _improvisedService?.TryUnEquipImprovised(out _); _equipment.EntryEquip(x); return true; } private bool Equip() where T : IEquipmentSlot { if (!_equipmentContainer.Equipment.TryGetAny(x => x.Key is T, out var item)) return false; if (_knockdown is not null) { if(_knockdown.IsKnockdown && item.Value.GetAssetable().AllowUseWhileKnocked is false) return false; } try { if (_inventory.AllowUseItem(item.Value) is false) { return false; } } catch (InGameException e) { _uxPopup?.Popup(e.Message); return false; } _improvisedService.TryUnEquipImprovised(out _); Equip(item.Value); return true; } } }