BITFALL/Assets/Artists/Scripts/Entities/EquipSelector/PlayerEquipSelector.cs

481 lines
16 KiB
C#
Raw Normal View History

2023-09-01 14:33:54 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BITKit;
using BITKit.Entities;
using UnityEngine.InputSystem;
2023-10-20 19:31:12 +08:00
2023-09-01 14:33:54 +08:00
using System.Diagnostics;
using System.Linq;
2023-12-03 17:35:43 +08:00
using System.Threading;
2023-10-20 19:31:12 +08:00
using System.Threading.Tasks;
using BITFALL.Entities;
using BITFALL.Entities.Improvised;
2023-10-24 23:37:59 +08:00
using BITFALL.Entities.Inventory;
2023-11-15 23:54:54 +08:00
using BITFALL.Player.Equip;
2023-10-02 23:24:56 +08:00
using BITFALL.Player.Inventory;
2023-09-01 14:33:54 +08:00
using BITKit.Entities.Player;
2024-03-29 00:58:24 +08:00
using BITKit.UX;
2023-10-20 19:31:12 +08:00
using Cysharp.Threading.Tasks;
using JetBrains.Annotations;
using UnityEditor;
2023-11-30 00:23:23 +08:00
using UnityEngine.EventSystems;
2023-09-01 14:33:54 +08:00
using UnityEngine.InputSystem.Interactions;
using Debug = UnityEngine.Debug;
2023-10-20 19:31:12 +08:00
namespace BITFALL.Entities.Equipment
2023-09-01 14:33:54 +08:00
{
[CustomType(typeof(IPlayerEquipSelector))]
2023-10-30 01:25:53 +08:00
public class PlayerEquipSelector : EntityBehavior,IPlayerEquipSelector
2023-09-01 14:33:54 +08:00
{
[Header(Constant.Header.InternalVariables)]
private readonly Dictionary<int, IBasicItem> equips=new();
2023-11-30 00:23:23 +08:00
[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;
2024-03-22 20:16:32 +08:00
[SerializeField] private InputActionReference scrollAction;
2023-10-20 22:46:14 +08:00
2023-10-24 23:37:59 +08:00
public event Func<IBasicItem, bool> TryEquipFactory;
2023-09-01 14:33:54 +08:00
public event Action<IDictionary<int, IBasicItem>> OnUpdateEquip;
2023-10-20 19:31:12 +08:00
[Inject]
2023-10-24 23:37:59 +08:00
private IEntityInventory _inventory;
2023-10-20 19:31:12 +08:00
[Inject(true)]
private IKnockdown _knockdown;
[Inject]
private IHealth _health;
2023-09-01 14:33:54 +08:00
private IBasicItem currentEquip;
2023-10-20 19:31:12 +08:00
[Inject(true)]
private IEntityEquipment _equipment;
[Inject(true)]
private ImprovisedServiceInterface _improvisedService;
2023-10-24 23:37:59 +08:00
[Inject]
private IEntityEquipmentContainer _equipmentContainer;
2023-11-15 23:54:54 +08:00
[Inject]
private IEquipService _equipService;
2024-03-29 00:58:24 +08:00
[Inject(true)]
private InputActionGroup _inputActionGroup;
[Inject(true)]
private IUXPopup _uxPopup;
2023-10-20 19:31:12 +08:00
private readonly List<int> _blockList=new();
2023-11-30 00:23:23 +08:00
2024-03-29 00:58:24 +08:00
2023-11-30 00:23:23 +08:00
private readonly Optional<int> playerChoose = new ();
2023-09-01 14:33:54 +08:00
public override void OnAwake()
{
2023-10-20 19:31:12 +08:00
_health.OnSetAlive += OnSetAlive;
if (_knockdown is not null)
{
2023-11-30 00:23:23 +08:00
_knockdown.OnKnockdown += () =>
2023-10-20 19:31:12 +08:00
{
2023-11-30 00:23:23 +08:00
if (currentEquip is null) return;
if (currentEquip.GetAssetable().AllowUseWhileKnocked) return;
2023-10-20 19:31:12 +08:00
Equip(null);
2023-11-15 23:54:54 +08:00
};
_knockdown.OnRevive += () =>
{
2023-11-30 00:23:23 +08:00
if (playerChoose.Allow)
2023-11-15 23:54:54 +08:00
{
2023-11-30 00:23:23 +08:00
Equip(playerChoose.Value);
2023-11-15 23:54:54 +08:00
}
2023-10-20 19:31:12 +08:00
};
}
2023-11-30 00:23:23 +08:00
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);
2024-03-22 20:16:32 +08:00
if(scrollAction)
_inputActionGroup.RegisterCallback(scrollAction, OnScroll);
2023-11-30 00:23:23 +08:00
}
2023-10-20 19:31:12 +08:00
if (_improvisedService is not null)
{
_improvisedService.OnEquipImprovisedItem += OnEquipImprovisedItem;
_improvisedService.OnUnEquipImprovisedItem += OnUnEquipImprovisedItem;
_improvisedService.OnTryEquipImprovisedItem += OnTryEquipImprovisedItem;
_improvisedService.OnTryUnEquipImprovisedItem += OnTryUnEquipImprovisedItem;
}
2023-09-01 14:33:54 +08:00
}
2023-10-24 23:37:59 +08:00
2024-03-22 20:16:32 +08:00
private void OnScroll(InputAction.CallbackContext obj)
{
2024-03-29 00:58:24 +08:00
if (BITAppForUnity.AllowCursor) return;
if (obj.performed is false) return;
var value = obj.ReadValue<Vector2>().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);
}
2024-03-22 20:16:32 +08:00
}
2023-11-30 00:23:23 +08:00
2023-09-01 14:33:54 +08:00
public override void OnStart()
{
base.OnStart();
2023-10-24 23:37:59 +08:00
_inventory.TryUseItemFactory += TryEquip;
_inventory.OnUsedItem += OnEquip;
_inventory.OnAdd += OnAdd;
_inventory.OnRemove += OnRemove;
2023-10-20 19:31:12 +08:00
}
2023-09-01 14:33:54 +08:00
public override void OnUpdate(float deltaTime)
{
base.OnUpdate(deltaTime);
if (_knockdown is not null)
{
_equipService.AllowEquip.SetDisableElements(1868448, _knockdown.IsPressured);
}
}
2023-10-24 23:37:59 +08:00
2023-10-20 19:31:12 +08:00
private bool OnTryUnEquipImprovisedItem(IBasicItem arg)
{
return true;
}
private bool OnTryEquipImprovisedItem(IBasicItem arg)
{
return true;
2023-09-01 14:33:54 +08:00
}
2023-10-20 19:31:12 +08:00
private void OnUnEquipImprovisedItem(IBasicItem obj)
{
2023-12-03 17:35:43 +08:00
Cancel();
2023-10-20 19:31:12 +08:00
}
private void OnEquipImprovisedItem(IBasicItem obj)
{
Equip(obj);
}
2023-09-01 14:33:54 +08:00
public void OnPrimary(InputAction.CallbackContext context)
{
if (context is not {interaction:PressInteraction ,performed:true}) return;
2023-10-20 19:31:12 +08:00
Equip(1);
2023-11-30 00:23:23 +08:00
playerChoose.SetValueThenAllow(1);
2023-09-01 14:33:54 +08:00
}
public void OnSecondary(InputAction.CallbackContext context)
{
if (context is not {interaction:PressInteraction ,performed:true}) return;
Equip(2);
2023-11-30 00:23:23 +08:00
playerChoose.SetValueThenAllow(2);
2023-09-01 14:33:54 +08:00
}
public void OnTertiary(InputAction.CallbackContext context)
{
if (context is not {interaction:PressInteraction ,performed:true}) return;
if (Equip(3) is false)
{
Equip(-1);
2023-11-30 00:23:23 +08:00
playerChoose.Clear();
}
else
{
playerChoose.SetValueThenAllow(3);
2023-09-01 14:33:54 +08:00
}
}
public void OnQuaternary(InputAction.CallbackContext context)
{
if (context is not {interaction:PressInteraction ,performed:true}) return;
2023-10-24 23:37:59 +08:00
Equip<EquipmentAsArmorPlate>();
2023-09-01 14:33:54 +08:00
}
public void OnHolster(InputAction.CallbackContext context)
{
if (context is not {interaction:PressInteraction ,performed:true}) return;
Equip(-1);
}
private void OnSetAlive(bool alive)
{
2023-11-15 23:54:54 +08:00
_equipService.AllowEquip.SetDisableElements(this,!alive);
2023-11-30 00:23:23 +08:00
if (alive)
2023-09-01 14:33:54 +08:00
{
2023-11-30 00:23:23 +08:00
if (playerChoose.Allow)
{
Equip(playerChoose.Value);
}
}
else
{
Equip(-1);
if (Data.Get<bool>(BITConstant.Environment.sp_keepInventory)) return;
foreach (var x in equips.ToArray())
{
_inventory.Add(x.Value);
}
equips.Clear();
UpdateEquip();
2023-09-01 14:33:54 +08:00
}
}
2023-10-24 23:37:59 +08:00
private bool TryEquip(IBasicItem value)
2023-09-01 14:33:54 +08:00
{
2023-11-15 23:54:54 +08:00
if (_equipService.AllowEquip.Allow is false) return false;
2023-11-30 00:23:23 +08:00
switch (_knockdown)
{
case not null when _knockdown.IsKnockdown && value.GetAssetable().AllowUseWhileKnocked is false:
return false;
}
2023-09-01 14:33:54 +08:00
var asset = value.GetAssetable();
2023-10-20 19:31:12 +08:00
if (_equipment.IsSupportItem(value) is false) return false;
2023-09-01 14:33:54 +08:00
switch (asset)
{
case var _ when asset.TryGetProperty<EquipmentAsWeapon>(out _):
2023-11-30 00:23:23 +08:00
var index = 0;
if (equips.TryAdd(++index, value) || equips.TryAdd(++index,value))
2023-09-01 14:33:54 +08:00
{
2023-10-20 19:31:12 +08:00
_equipment.EntryEquip(value);
2023-09-01 14:33:54 +08:00
UpdateEquip();
2023-10-20 19:31:12 +08:00
_improvisedService?.TryUnEquipImprovised(out _);
currentEquip = value;
2023-10-24 23:37:59 +08:00
_inventory.UseItem(value);
2023-11-30 00:23:23 +08:00
playerChoose.SetValueThenAllow(index);
2023-09-01 14:33:54 +08:00
return true;
}
break;
2023-10-20 19:31:12 +08:00
case var _ when asset.TryGetProperty<EquipmentUseItem>(out _):
2024-04-10 18:12:40 +08:00
//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;
}
}
2023-10-24 23:37:59 +08:00
_equipment.EntryEquip(value);
_improvisedService?.TryUnEquipImprovised(out _);
currentEquip = value;
return true;
2023-11-30 00:23:23 +08:00
case var _ when asset.TryGetProperty<EquipmentAsSlot>(out var equipAsSlot):
break;
2023-10-20 19:31:12 +08:00
}
return false;
}
2023-12-03 17:35:43 +08:00
2023-10-20 19:31:12 +08:00
public async void OnAdd(IBasicItem item)
{
if (_blockList.Contains(item.Id)) return;
2023-12-03 17:35:43 +08:00
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))
2023-10-20 19:31:12 +08:00
{
2023-12-03 17:35:43 +08:00
equips.Remove(pair.Key);
UpdateEquip();
2023-10-20 19:31:12 +08:00
}
2023-12-03 17:35:43 +08:00
currentEquip = null;
_equipment.EntryEquip((IBasicItem)null);
}
else
{
try
2023-10-20 19:31:12 +08:00
{
2023-12-03 17:35:43 +08:00
for (var i = 0; i < 8; i++)
2023-10-20 19:31:12 +08:00
{
2023-12-03 17:35:43 +08:00
await UniTask.NextFrame();
}
if (_equipment.IsSupportItem(item) && item.GetAssetable().TryGetProperty<EquipmentAsWeapon>(out _))
{
_inventory.TryUseItem(item);
2023-10-20 19:31:12 +08:00
}
}
2023-12-03 17:35:43 +08:00
catch (OperationCanceledException)
{
}
}
2023-09-01 14:33:54 +08:00
}
2023-11-30 00:23:23 +08:00
private void OnTactics(InputAction.CallbackContext obj)
{
2024-03-29 00:58:24 +08:00
// switch(obj)
// {
// case {interaction:TapInteraction, performed: true}:
// Equip<EquipmentAsTactics>();
// break;
// }
2023-11-30 00:23:23 +08:00
}
2023-10-20 19:31:12 +08:00
public void Throw(InputAction.CallbackContext context)
{
2024-03-29 00:58:24 +08:00
//Debug.Log(context);
2023-10-24 23:37:59 +08:00
switch (context)
2023-10-20 19:31:12 +08:00
{
2024-03-29 00:58:24 +08:00
case {interaction:TapInteraction, started: true}:
2023-10-24 23:37:59 +08:00
Equip<EquipmentAsThrow>();
break;
2023-10-20 19:31:12 +08:00
}
2024-03-29 00:58:24 +08:00
// 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<EquipmentAsThrow>();
// break;
// }
2023-10-20 19:31:12 +08:00
}
2023-09-01 14:33:54 +08:00
public void OnRemove(IBasicItem item)
{
2023-12-03 17:35:43 +08:00
_blockList.Add(item.Id);
2023-10-20 19:31:12 +08:00
if (_equipment.IsSupportItem(item) is false)
2023-09-01 14:33:54 +08:00
{
UpdateEquip();
}
}
2023-10-24 23:37:59 +08:00
private void OnEquip(IBasicItem obj)
2023-09-01 14:33:54 +08:00
{
2023-11-30 00:23:23 +08:00
_blockList.Add(obj.Id);
2023-09-01 14:33:54 +08:00
}
private void UpdateEquip()
{
OnUpdateEquip?.Invoke(new Dictionary<int, IBasicItem>(equips));
}
2023-11-30 00:23:23 +08:00
public IDictionary<int, IBasicItem> Equipped => new Dictionary<int, IBasicItem>(equips);
2023-09-01 14:33:54 +08:00
public bool TryDeEquip(IBasicItem item)
{
if (item is null) return false;
if (equips.Any(x => x.Value.AddressablePath == item.AddressablePath) is false) return false;
2023-11-30 00:23:23 +08:00
var index = equips.First(x=>x.Value.AddressablePath==item.AddressablePath).Key;
2023-09-01 14:33:54 +08:00
if (equips.TryRemove(index) is false) return false;
2023-10-20 19:31:12 +08:00
if (!_inventory.Add(item)) return false;
2023-12-03 17:35:43 +08:00
if (currentEquip?.AddressablePath == item.AddressablePath)
{
Equip(null);
playerChoose.Clear();
}
2023-09-01 14:33:54 +08:00
UpdateEquip();
return true;
}
2023-11-30 00:23:23 +08:00
public async void Cancel()
2023-10-20 22:46:14 +08:00
{
2023-11-30 00:23:23 +08:00
await UniTask.NextFrame();
if (playerChoose.Allow)
2023-10-20 22:46:14 +08:00
{
2023-11-30 00:23:23 +08:00
if (Equip(playerChoose.Value))
{
return;
};
//playerChoose.Clear();
2023-10-20 22:46:14 +08:00
}
Equip(null);
2023-11-30 00:23:23 +08:00
return;
2023-10-20 22:46:14 +08:00
}
2023-09-01 14:33:54 +08:00
private void Equip(IBasicItem item)
{
2023-11-30 00:23:23 +08:00
if (item is not null && _equipService.AllowEquip.Allow is false) return;
2023-10-20 19:31:12 +08:00
_equipment.EntryEquip(item);
currentEquip = item;
2023-09-01 14:33:54 +08:00
}
private bool Equip(int index)
{
2023-11-30 00:23:23 +08:00
if (index is not -1)
{
if (_equipService.AllowEquip.Allow is false) return false;
}
2023-09-01 14:33:54 +08:00
if (!equips.TryGetValue(index, out var x) && index is not -1) return false;
2023-11-30 00:23:23 +08:00
if (index is not -1 && _knockdown is not null && _knockdown.IsKnockdown)
{
if (x.GetAssetable().AllowUseWhileKnocked is false) return false;
}
2023-10-20 19:31:12 +08:00
currentEquip = x;
_improvisedService?.TryUnEquipImprovised(out _);
_equipment.EntryEquip(x);
2023-09-01 14:33:54 +08:00
return true;
}
2023-10-24 23:37:59 +08:00
private bool Equip<T>() where T : IEquipmentSlot
{
if (!_equipmentContainer.Equipment.TryGetAny(x => x.Key is T, out var item)) return false;
2023-11-30 00:23:23 +08:00
if (_knockdown is not null)
{
if(_knockdown.IsKnockdown && item.Value.GetAssetable().AllowUseWhileKnocked is false) return false;
}
2024-03-29 00:58:24 +08:00
try
{
if (_inventory.AllowUseItem(item.Value) is false)
{
return false;
}
}
catch (InGameException e)
{
_uxPopup?.Popup(e.Message);
return false;
}
2023-10-29 15:27:13 +08:00
_improvisedService.TryUnEquipImprovised(out _);
2023-10-24 23:37:59 +08:00
Equip(item.Value);
return true;
}
2023-09-01 14:33:54 +08:00
}
}