using BehaviorDesigner.Runtime; 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 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; } 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; set; } public bool IsOnMission { get; set; } public bool IsCleaningFloor { get; set; } public bool IsCleaningTable { get; set; } public bool IsServing { get; set; } public bool IsMakingCocktail { get; set; } private IAstarAI _astarAi; private Transform _spawnTransform; // State public IState CurrentState { get; private set; } public IState IdleState { get; private set; } public IState WalkingState { get; private set; } public IState ServingIdleState { get; private set; } public IState ServingState { get; private set; } public IState CleaningFloorState { get; private set; } public IState CleaningTableState { get; private set; } public IState MakingCocktailState { get; private set; } #endregion // Unity events #region Unity events private void Awake() { InitializeComponents(); } protected virtual void Update() { CurrentState.UpdateState(this); 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() { IdleState = new IdleState(); WalkingState = new WalkingState(); ServingIdleState = new ServingIdleState(); ServingState = new ServingState(); CleaningFloorState = new CleaningFloorState(); CleaningTableState = new CleaningTableState(); MakingCocktailState = new MakingCocktailState(); CurrentState = IdleState; CurrentState.EnterState(this); 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 void TransitionToState(IState newState) { CurrentState.ExitState(this); CurrentState = newState; CurrentState.EnterState(this); } public virtual void OnMission(ICrewInteraction crewInteraction) { CrewInteraction = crewInteraction; CrewInteraction.OnInteractionCompleted += InteractionCompleted; IsOnMission = true; } public virtual void ResetMission() { CrewInteraction = null; IsOnMission = false; IsCleaningFloor = false; IsCleaningTable = false; IsServing = false; IsMakingCocktail = false; } public virtual bool CanInteractionPosition() { if (CrewInteraction.CenterTransform == null) return false; return AIMovement.HasReachedDestination() || Vector3.Distance(CrewInteraction.CenterTransform.position, transform.position) <= CrewInteraction.InteractionRadius; } protected virtual void InteractionCompleted() { CrewInteraction.OnInteractionCompleted -= InteractionCompleted; ResetMission(); } #endregion } }