using BehaviorDesigner.Runtime; using BlueWater.Audios; using BlueWater.Enemies; using BlueWater.Interfaces; using BlueWater.Players; using BlueWater.Uis; using Pathfinding; using PixelCrushers.DialogueSystem; using Sirenix.OdinInspector; using UnityEngine; namespace BlueWater.Npcs.Crews { public static class CrewSpineAnimation { public const string Idle = "Idle"; public const string Walk = "Run"; public const string ServingIdle = "ServingIdle"; public const string Serving = "Serving"; public const string CleaningFloor = "CleaningFloor"; public const string CleaningTable = "CleaningTable"; public const string MakingCocktail = "BeerMaker"; } public abstract class Crew : MonoBehaviour { // Variables #region Variables // Components [field: SerializeField] public Transform CenterTransform { get; private set; } [field: SerializeField] public Rigidbody Rigidbody { get; private set; } [field: SerializeField] public CapsuleCollider CharacterCollider { get; private set; } [field: SerializeField] public BehaviorTree BehaviorTree { get; private set; } [field: SerializeField] public Transform VisualLook { get; private set; } [field: SerializeField] public MeshRenderer MeshRenderer { get; private set; } [field: SerializeField] public BarkTrigger BarkTrigger { get; private set; } [field: SerializeField] public InteractionCanvas InteractionCanvas { get; private set; } [field: SerializeField] public BalloonUi BalloonUi { get; private set; } // Classes [field: SerializeField, Required] public SpineController SpineController { get; private set; } [field: SerializeField, Required] public AiMovement AIMovement { get; private set; } [Title("사운드")] [SerializeField] private string _createCrewSfxName = "CreateCrew"; public bool IsMoving { get; protected set; } private Vector3 _currentDirection = Vector3.right; public Vector3 CurrentDirection { get => _currentDirection; set { if (value == Vector3.zero) return; _currentDirection = value; } } public ICrewInteraction CrewInteraction { get; protected set; } public bool IsOnMission { get; protected set; } private IAstarAI _astarAi; private Transform _spawnTransform; #endregion // Unity events #region Unity events private void Awake() { InitializeComponents(); } protected virtual void Update() { HandleMovement(); FlipVisualLook(); } #endregion // Initialize methods #region Initialize methods [Button("컴포넌트 초기화")] protected virtual void InitializeComponents() { CenterTransform = transform; Rigidbody = GetComponent(); CharacterCollider = GetComponent(); BehaviorTree = GetComponent(); VisualLook = transform.Find("VisualLook"); MeshRenderer = VisualLook.GetComponent(); BarkTrigger = transform.Find("DialogueSystem").GetComponent(); InteractionCanvas = transform.GetComponentInChildren(); BalloonUi = InteractionCanvas.transform.GetComponentInChildren(); SpineController = GetComponent(); AIMovement = GetComponent(); _astarAi = GetComponent(); } public virtual void Initialize() { AudioManager.Instance.PlaySfx(_createCrewSfxName); BehaviorTree.EnableBehavior(); } #endregion // Methods #region Methods private void HandleMovement() { if (!_astarAi.canMove || _astarAi.isStopped) { IsMoving = false; return; } CurrentDirection = _astarAi.velocity.normalized; IsMoving = _astarAi.velocity != Vector3.zero || _astarAi.velocity != Vector3.positiveInfinity; } private void FlipVisualLook() { var localScale = VisualLook.localScale; localScale.x = CurrentDirection.x switch { > 0.01f => -Mathf.Abs(localScale.x), < -0.01f => Mathf.Abs(localScale.x), _ => localScale.x }; VisualLook.localScale = localScale; } public void Bark(string conversation, BarkOrder barkOrder = BarkOrder.Random) { if (string.IsNullOrEmpty(conversation)) return; BarkTrigger.barkOrder = barkOrder; BarkTrigger.conversation = conversation; BarkTrigger.OnUse(); } public virtual void OnMission(ICrewInteraction crewInteraction) { CrewInteraction = crewInteraction; CrewInteraction.OnInteractionCompleted += ResetMission; IsOnMission = true; } public abstract void ResetMission(); public abstract bool IsCompletedMission(); public virtual bool CanInteractionPosition() { if (CrewInteraction == null || CrewInteraction.CenterTransform == null) return false; return AIMovement.HasReachedDestination() || Vector3.Distance(CrewInteraction.CenterTransform.position, transform.position) <= CrewInteraction.InteractionRadius; } #endregion } }