using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using BITKit; using BITKit.Animations; using BITKit.StateMachine; using System.Linq; using BITFALL; using BITFALL.Entities.Equipment; using BITFALL.Player.Equip; using BITKit.Entities.Melee; using Cinemachine; using Cysharp.Threading.Tasks; namespace BITKit.Entities { public abstract class BITEquipBase : StateBasedMonoBehaviour, IEquipBase where T : IState { [Header(Constant.Header.Settings)] [SerializeField] protected AssetableEquip item; [Header(Constant.Header.Components)] public UnityAnimator animator; [SerializeField] private Renderer[] renderers; [Header(Constant.Header.Services)] [SerializeReference,SubclassSelector] protected IMeleeService meleeService; public Core.Entites.IEntity Entity { get; set; } public IBasicItem Item { get; set; } public readonly InputActionGroup inputActionGroup = new() { allowGlobalActivation = true }; protected readonly ValidHandle AllowRendering = new(); public virtual string AddressablePath => throw new System.NotImplementedException(); protected virtual Vector3 meleeForce => Transform.forward; public bool IsEntered { get; set; } public virtual void Entry() { AllowRendering.AddElement(this); inputActionGroup.allowInput.AddElement(this); } public virtual UniTask EntryAsync() { return UniTask.CompletedTask; } public virtual void Exit() { inputActionGroup.allowInput.AddElement(this); } public virtual UniTask ExitAsync() { AllowRendering.RemoveElement(this); return UniTask.CompletedTask; } public virtual void OnAwake() { AllowRendering.AddListener(x=>renderers.ForEach(y=>y.enabled = x)); AllowRendering.Invoke(); Initialize(); } public virtual void OnDestroy() { inputActionGroup.Dispose(); } public virtual void OnStart() { } public virtual void OnUpdate(float deltaTime) { } public virtual bool IsSupportItem(IBasicItem item) =>item is not null && item.AddressablePath == AddressablePath; public virtual void PlayAudio(string eventName) { } public virtual void EquipEvent(string eventName){} public virtual void AnimationEvent(string eventName) { if (IsEntered is false) return; switch (eventName) { case "Melee": case "Attack": meleeService.Melee(new MeleeCommand { PlayerId = Entity.Id, Position = Transform.position, Force = meleeForce * item.MeleeForce, Range = item.MeleeRange, Damage = item.MeleeDamage }); break; case "HeavyAttack": meleeService.Melee(new MeleeCommand { PlayerId = Entity.Id, Position = Transform.position, Force = meleeForce * item.HeavyMeleeForce, Range = item.HeavyMeleeRange, Damage = item.HeavyMeleeDamage, }); break; } } } [CustomType(typeof(IEquipService))] [CustomType(typeof(IEntityEquipment))] public class EntityEquipment : EntityComponent,IEquipService,IEntityEquipment { public EntryGroup equips = new(); public IOptional Zoom { get; } = new Optional(){Value = 1}; public float InitialFov; [SerializeField] private CinemachineVirtualCamera virtualCamera; public event Action OnEquip; public event Action OnDeEquip; protected IEquipBase entryComplete; private PlayerConfig playerConfig; private IBasicItem _currentItem; public override void OnStart() { base.OnStart(); equips.list = GetComponentsInChildren(true).ToList(); equips.OnEntry += OnEntry; equips.OnExit += OnExit; foreach (var x in equips.list) { x.Entity = entity; x.OnAwake(); } foreach (var x in equips.list) { x.OnStart(); } } private void OnExit(IEquipBase obj) { obj.Item = null; OnDeEquip?.Invoke(obj.Item); } private void OnEntry(IEquipBase obj) { obj.Item = _currentItem; OnEquip?.Invoke(obj.Item); } public override void OnUpdate(float deltaTime) { if (equips.TryGetEntried(out entryComplete)) { entryComplete.OnUpdate(deltaTime); } if (virtualCamera is not null) { var current = virtualCamera.m_Lens.FieldOfView; current= Mathf.Lerp(current,Zoom.Allow ? InitialFov / Zoom.Value : PlayerConfig.Singleton.Fov , deltaTime * 5); current = Mathf.Clamp(current, 10, PlayerConfig.Singleton.Fov); virtualCamera.m_Lens.FieldOfView = current; } } public bool IsSupportItem(IBasicItem item)=> equips.list.Any(x => x.IsSupportItem(item)); public void EntryEquip(int index)=> equips.Entry(index); public void EntryEquip(Func factory)=>equips.Entry(x=>factory.Invoke(x.AddressablePath)); public void EntryEquip(IBasicItem item) { _currentItem = item; equips.Entry(x=>x.IsSupportItem(item)); } } }