CapersProject/Assets/02.Scripts/Character/Npc/Customer.cs
2024-10-08 22:44:20 +09:00

426 lines
13 KiB
C#

using System;
using BehaviorDesigner.Runtime;
using BlueWater.Enemies;
using BlueWater.Interfaces;
using BlueWater.Items;
using BlueWater.Players;
using BlueWater.Tycoons;
using BlueWater.Uis;
using Pathfinding;
using PixelCrushers.DialogueSystem;
using Sirenix.OdinInspector;
using UnityEngine;
using Random = UnityEngine.Random;
namespace BlueWater.Npcs.Customers
{
public static class CustomerSpineAnimation
{
public const string Idle = "Idle";
public const string Walk = "Run";
}
public enum CustomerInteractionType
{
None = 0,
OrderCocktail
}
public class Customer : MonoBehaviour, IPlayerInteraction
{
// 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 ParticleSystem PayMoneyParticle { get; private set; }
[field: SerializeField]
public BalloonUi BalloonUi { get; private set; }
[field: SerializeField]
public PayMoneyUi PayMoneyUi { get; private set; }
// Classes
[field: SerializeField, Required]
public SpineController SpineController { get; private set; }
[field: SerializeField, Required]
public AiMovement AIMovement { get; private set; }
[field: SerializeField]
public bool EnableInteraction { get; private set; } = true;
[field: SerializeField]
public float InteractionRadius { get; private set; } = 2f;
[field: SerializeField]
public string InteractionMessage { get; set; }
[SerializeField]
private Vomiting _vomiting;
[field: Title("실시간 데이터")]
[field: SerializeField]
public LevelData CurrentLevelData { get; private set; }
[field: SerializeField]
public TableSeat CurrentTableSeat { get; private set; }
[field: SerializeField]
public CocktailData OrderedCocktailData { get; private set; }
[field: SerializeField]
public bool IsReceivedItem { get; set; }
[field: SerializeField]
public bool IsOrderedSucceed { get; set; }
[SerializeField]
private CustomerInteractionType _customerInteractionType;
// private int _happyPoint;
// public int HappyPoint
// {
// get => _happyPoint;
// private set
// {
// var newHappyPoint = Mathf.Max(0, value);
// _happyPoint = newHappyPoint;
// }
// }
private bool _isMoving;
public bool IsMoving
{
get => _isMoving;
set
{
if (_isMoving == value) return;
_isMoving = value;
SpineController.PlayAnimation(_isMoving
? CustomerSpineAnimation.Walk
: CustomerSpineAnimation.Idle, true);
}
}
private Vector3 _currentDirection = Vector3.right;
public Vector3 CurrentDirection
{
get => _currentDirection;
set
{
if (value == Vector3.zero) return;
_currentDirection = value;
}
}
private IAstarAI _astarAi;
private Transform _spawnTransform;
private int _paidAmount;
private int _foodPrice;
private int _tipAmount;
private bool _isQuitting;
#endregion
// Unity events
#region Unity events
private void Awake()
{
InitializeComponents();
}
private void OnApplicationQuit()
{
_isQuitting = true;
}
private void Update()
{
HandleMovement();
FlipVisualLook();
}
private void OnDestroy()
{
if (_isQuitting) return;
CustomerManager.Instance.UnregisterCustomer(this);
}
#endregion
// Initialize methods
#region Initialize methods
[Button("컴포넌트 초기화")]
protected virtual void InitializeComponents()
{
CenterTransform = transform;
Rigidbody = GetComponent<Rigidbody>();
CharacterCollider = GetComponent<CapsuleCollider>();
BehaviorTree = GetComponent<BehaviorTree>();
VisualLook = transform.Find("VisualLook");
MeshRenderer = VisualLook.GetComponent<MeshRenderer>();
BarkTrigger = transform.Find("DialogueSystem").GetComponent<BarkTrigger>();
PayMoneyParticle = transform.Find("PayMoneyParticle").GetComponent<ParticleSystem>();
InteractionCanvas = transform.GetComponentInChildren<InteractionCanvas>();
BalloonUi = InteractionCanvas.transform.GetComponentInChildren<BalloonUi>();
PayMoneyUi = InteractionCanvas.transform.GetComponentInChildren<PayMoneyUi>();
SpineController = GetComponent<SpineController>();
AIMovement = GetComponent<AiMovement>();
_astarAi = GetComponent<IAstarAI>();
}
public void Initialize(LevelData levelData, Transform spawnTransform)
{
CurrentLevelData = levelData;
_spawnTransform = spawnTransform;
//CustomerData = CustomerManager.Instance.GetRandomCustomerData();
//AIMovement.SetMoveSpeed(CustomerData.MoveSpeed);
//HappyPoint = CustomerData.BaseHappyPoint;
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 SetTableSeat(TableSeat tableSeat)
{
CurrentTableSeat = tableSeat;
BalloonUi.Initialize(CurrentTableSeat);
}
public void SetCurrentDirection(Vector3 normalDirection) => CurrentDirection = normalDirection;
public void SetTableSeatPositionAndDirection()
{
transform.position = CurrentTableSeat.SeatTransform.position;
SetCurrentDirection(CurrentTableSeat.TableDirection);
}
public void ServedItem(CocktailData cocktailData)
{
OrderedCocktailData = cocktailData;
CurrentTableSeat.SetFood(OrderedCocktailData.Sprite);
}
public void Interaction()
{
switch (_customerInteractionType)
{
case CustomerInteractionType.None:
break;
case CustomerInteractionType.OrderCocktail:
var currentPickupItem = GameManager.Instance.CurrentTycoonPlayer.TycoonPickupHandler.GetCurrentPickupItem();
var servedCocktailData = ItemManager.Instance.CocktailDataSo.GetDataByIdx(currentPickupItem.Idx);
ServedItem(servedCocktailData);
BalloonUi.ReceiveItem(servedCocktailData);
EventManager.OnCocktailServedToCustomer?.Invoke(servedCocktailData);
IsOrderedSucceed = currentPickupItem.Idx == OrderedCocktailData.Idx;
IsReceivedItem = true;
EventManager.OnOrderResult?.Invoke(this, IsOrderedSucceed);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public virtual void CancelInteraction() { }
public bool CanInteraction()
{
switch (_customerInteractionType)
{
case CustomerInteractionType.None:
return false;
case CustomerInteractionType.OrderCocktail:
var currentPickupItem = GameManager.Instance.CurrentTycoonPlayer.TycoonPickupHandler.GetCurrentPickupItem();
return currentPickupItem != null;
default:
throw new ArgumentOutOfRangeException();
}
}
public virtual void ShowInteractionUi()
{
SpineController.EnableCustomMaterial();
EventManager.OnShowInteractionUi?.Invoke(InteractionMessage);
}
public virtual void HideInteractionUi()
{
SpineController.DisableCustomMaterial();
EventManager.OnHideInteractionUi?.Invoke();
}
public void RegisterPlayerInteraction()
{
if (EnableInteraction)
{
GameManager.Instance.CurrentTycoonPlayer.TycoonInput.RegisterPlayerInteraction(this);
}
}
public void UnregisterPlayerInteraction()
{
if (EnableInteraction)
{
GameManager.Instance.CurrentTycoonPlayer.TycoonInput.UnregisterPlayerInteraction(this);
}
_customerInteractionType = CustomerInteractionType.None;
}
//public void AddHappyPoint(int value) => HappyPoint += value;
public void Bark(string conversation, BarkOrder barkOrder = BarkOrder.Random)
{
if (string.IsNullOrEmpty(conversation)) return;
BarkTrigger.barkOrder = barkOrder;
BarkTrigger.conversation = conversation;
BarkTrigger.OnUse();
}
public bool IsWaitTimeOver()
{
var isWaitTimeOver = BalloonUi.IsWaitTimeOver();
if (isWaitTimeOver)
{
EventManager.OnOrderResult?.Invoke(this, false);
}
return isWaitTimeOver;
}
public void PayMoney()
{
var random = Random.Range(0f, 100f);
if (random <= TycoonManager.Instance.TycoonStageController.StageDataSo.DirtyTablePercent)
{
CurrentTableSeat.DirtyTable();
}
else
{
CurrentTableSeat.CleanTable();
}
PayMoneyParticle.Play();
PayMoneyUi.PayMoney(CurrentLevelData.Gold);
TycoonManager.Instance.TycoonStatus.CurrentExp += CurrentLevelData.Exp;
TycoonManager.Instance.TycoonStatus.CurrentGold += CurrentLevelData.Gold;
}
// public void PayMoney(int foodPrice, int tipAmount)
// {
// _foodPrice = foodPrice;
// _tipAmount = tipAmount;
// _paidAmount = _foodPrice + _tipAmount;
//
// PayMoneyParticle.gameObject.SetActive(true);
// PayMoneyParticle.Play();
// PayMoneyUi.PayMoney(_paidAmount);
// }
public void Vomit()
{
AIMovement.StopMove();
var spawnPosition = transform.position + new Vector3(0f, 0f, 0.1f);
Instantiate(_vomiting, spawnPosition, _vomiting.transform.rotation);
}
public void CheckOut()
{
//var customerVisitInfo = new CustomerVisitInfo(HappyPoint, _foodPrice, _tipAmount, _paidAmount);
//TycoonManager.Instance.TycoonStageController.RegisterCustomerVisitInfo(customerVisitInfo);
AIMovement.StopMove();
Destroy(gameObject);
}
// 상호작용 메서드
public void OrderCocktail()
{
IsReceivedItem = false;
IsOrderedSucceed = false;
InteractionMessage = "칵테일 전달";
OrderedCocktailData = TycoonManager.Instance.TycoonIngredientController.GetRandomCocktailData();
BalloonUi.OrderItem(OrderedCocktailData.Idx, CurrentLevelData.WaitTime, CurrentLevelData.HurryTime);
_customerInteractionType = CustomerInteractionType.OrderCocktail;
RegisterPlayerInteraction();
EventManager.OnOrderedCocktail?.Invoke(this);
}
public void MoveSpawnPosition()
{
CurrentTableSeat.VacateSeat();
AIMovement.Move(_spawnTransform.position);
}
#endregion
}
}