using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using BITKit; using BITKit.Animations; using BITKit.StateMachine; using System.Linq; using System.Security.Permissions; using BITFALL; using BITFALL.Entities.Equipment; using BITFALL.Player.Equip; using BITKit.Entities.Melee; using BITKit.Entities.VFX; using Cinemachine; using Cysharp.Threading.Tasks; namespace BITKit.Entities { public abstract class BITEquipBase : StateBasedMonoBehaviour, IEquipBase where T : IState { [Header(Constant.Header.Settings)] [SerializeField] protected AssetableItem item; [Header(Constant.Header.Components)] [SerializeField] public UnityAnimator animator; [SerializeField] protected EntityVFXPlayer vfxPlayer; [SerializeField] protected EntityAnimator entityAnimator; [SerializeField] private Renderer[] renderers; [SerializeField] protected Transform cameraTransform; [Header(Constant.Header.Services)] [SerializeReference,SubclassSelector] protected IMeleeService meleeService; public Core.Entites.IEntity Entity { get; set; } public Entity UnityEntity=>Entity as Entity; public IBasicItem Item { get; set; } public readonly InputActionGroup inputActionGroup = new() { allowGlobalActivation = true }; protected readonly ValidHandle AllowRendering = new(); public virtual string AddressablePath => item.AddressablePath; protected virtual Vector3 meleeForce => Transform.forward; public bool IsEntered { get; set; } private Quaternion _initialCameraRotation; public virtual void Entry() { AllowRendering.AddElement(this); inputActionGroup.allowInput.AddElement(this); if (entityAnimator) entityAnimator.enabled = true; if (vfxPlayer) vfxPlayer.enabled = true; var animName = animator.animator.GetCurrentAnimatorStateInfo(0).shortNameHash; animator.animator.Play(animName, -1, 0); } public virtual UniTask EntryAsync() { return UniTask.CompletedTask; } public virtual void Exit() { if (entityAnimator) entityAnimator.enabled = false; if (vfxPlayer) vfxPlayer.enabled = false; inputActionGroup.allowInput.RemoveElement(this); } public virtual UniTask ExitAsync() { AllowRendering.RemoveElement(this); if (cameraTransform is not null) { cameraTransform.localPosition = default; cameraTransform.localRotation = _initialCameraRotation; } return UniTask.CompletedTask; } public virtual void OnAwake() { AllowRendering.AddListener(x => renderers.ForEach(y => { y.enabled = x; animator.enabled = x; })); AllowRendering.Invoke(); if (cameraTransform is not null) _initialCameraRotation = cameraTransform.localRotation; Initialize(); inputActionGroup.allowInput.Invoke(); } 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; if (item is not AssetableEquip equip) return; switch (eventName) { case "Melee": case "Attack": meleeService.Melee(new MeleeCommand { PlayerId = Entity.Id, Position = Transform.position, Force = meleeForce * equip.MeleeForce, Range = equip.MeleeRange, Damage = equip.MeleeDamage }); break; case "HeavyAttack": meleeService.Melee(new MeleeCommand { PlayerId = Entity.Id, Position = Transform.position, Force = meleeForce * equip.HeavyMeleeForce, Range = equip.HeavyMeleeRange, Damage = equip.HeavyMeleeDamage, }); break; } } } [CustomType(typeof(IEquipService))] [CustomType(typeof(IEntityEquipment))] public class EntityEquipment : EntityComponent,IEquipService,IEntityEquipment { public IOptional Zoom { get; } = new Optional(){Value = 1}; public float InitialFov; [SerializeField] private CinemachineVirtualCamera virtualCamera; [SerializeField] private Optional overrideIndex; public event Action OnEquip; public event Action OnUnEquip; public event Action OnEquipAddressable; public event Action OnUnEquipAddressable; private readonly EntryGroup equips = new(); protected IEquipBase entryComplete; private PlayerConfig playerConfig; private IBasicItem _currentItem; [Inject(true)] private IHealth _health; public override void OnAwake() { base.OnAwake(); equips.list = GetComponentsInChildren(true).ToList(); equips.OnEntry += OnEntry; equips.OnExit += OnExit; if (_health is not null) { _health.OnSetAlive += x => { if (x is false) EntryEquip(-1); }; } foreach (var x in equips.list) { x.Entity = entity; x.OnAwake(); } } public override void OnStart() { base.OnStart(); foreach (var x in equips.list) { x.OnStart(); } } private void OnExit(IEquipBase obj) { OnUnEquipAddressable?.Invoke(obj.AddressablePath); OnUnEquip?.Invoke(obj.Item); //Debug.Log($"已退出:{obj.Item.Name}"); obj.Item = null; } private void OnEntry(IEquipBase obj) { OnEquipAddressable?.Invoke(obj.AddressablePath); obj.Item = _currentItem; OnEquip?.Invoke(obj.Item); //Debug.Log($"已进入:{obj.Item.Name}"); } 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; } if (overrideIndex.Allow && (_health?.IsAlive ?? true)) { EntryEquip(overrideIndex.Value); } } 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)); } } }