CapersProject/Assets/02.Scripts/BlueWater/Tycoon/CustomerController.cs

175 lines
5.9 KiB
C#
Raw Normal View History

2025-01-02 09:33:05 +00:00
using System;
using System.Collections;
using System.Collections.Generic;
2024-10-29 12:17:00 +00:00
using System.Linq;
2025-02-10 02:13:46 +00:00
using DDD.Audios;
using DDD.Interfaces;
using DDD.Npcs.Customers;
using DDD.Utility;
using Sirenix.OdinInspector;
using UnityEngine;
2025-01-02 09:33:05 +00:00
using Random = UnityEngine.Random;
2025-02-10 02:13:46 +00:00
namespace DDD.Tycoons
{
2025-01-02 09:33:05 +00:00
[Serializable]
public class RoundSkinData
{
[field: SerializeField]
public int MinRound { get; private set; }
[field: SerializeField]
public List<string> Skins { get; private set; } = new();
}
2024-10-15 18:01:16 +00:00
public class CustomerController : MonoBehaviour
{
[Title("손님 데이터")]
[SerializeField, Required]
private Customer _customerPrefab;
[SerializeField, Required]
private Transform _customerSpawnTransform;
2024-11-17 15:36:08 +00:00
[SerializeField]
private string _createCustomerSfxName = "CreateCustomer";
2025-01-02 09:33:05 +00:00
[Title("라운드별 스킨 데이터")]
[SerializeField]
private List<RoundSkinData> _roundSkinData = new();
[Title("대기중인 손님 정보")]
[SerializeField]
private float _checkEmptySeatInterval = 0.5f;
[field: SerializeField]
public List<Customer> InstanceCustomers { get; private set; } = new();
[ShowInInspector]
private Queue<int> _waitingCustomers = new();
private CustomerTableController _customerTableController;
private Coroutine _findEmptySeatCoroutineInstance;
2024-10-22 12:41:31 +00:00
private int _instanceCount;
private void Start()
{
_customerTableController = TycoonManager.Instance.CustomerTableController;
EventManager.OnCreateCustomer += TryFindEmptySeat;
2024-10-15 18:01:16 +00:00
EventManager.OnDestroyCustomer += UnregisterCustomer;
}
private void OnDestroy()
{
EventManager.OnCreateCustomer -= TryFindEmptySeat;
2024-10-15 18:01:16 +00:00
EventManager.OnDestroyCustomer -= UnregisterCustomer;
}
public Customer CreateCustomer()
{
var currentLevelData = TycoonManager.Instance.GetCurrentLevelData();
2025-01-02 09:33:05 +00:00
List<string> randomSkins = GetSkins();
var newCustomer = Instantiate(_customerPrefab, _customerSpawnTransform.position, Quaternion.identity);
2025-01-02 09:33:05 +00:00
newCustomer.Initialize(currentLevelData, _customerSpawnTransform, randomSkins);
2024-10-22 12:41:31 +00:00
newCustomer.gameObject.name = $"Customer (Clone) {_instanceCount}";
_instanceCount++;
RegisterCustomer(newCustomer);
2024-11-17 15:36:08 +00:00
AudioManager.Instance.PlaySfx(_createCustomerSfxName);
return newCustomer;
}
public void TryFindEmptySeat()
{
// 1. 빈 자리를 체크한다. (빈 자리가 있다면 생성)
// 2. 빈 자리가 없는 경우, Queue에 대기 손님을 넣고 빈 자리가 생길 때 생성
// 3. 생성하는 순간에 레벨 data 참조
// 이미 대기열에 사람들이 있는 경우, 새로운 손님도 바로 대기열에 넣는다.
if (_waitingCustomers.Count > 0)
{
_waitingCustomers.Enqueue(1);
return;
}
// 대기열에는 아무도 없는 경우
var emptySeat = _customerTableController.FindEmptySeat();
if (emptySeat == null)
{
// 내가 첫 대기열 손님이 된다.
_waitingCustomers.Enqueue(1);
Utils.StartUniqueCoroutine(this, ref _findEmptySeatCoroutineInstance, CheckEmptySeatCoroutine());
return;
}
var newCustomer = CreateCustomer();
newCustomer.SetTableSeat(emptySeat);
emptySeat.ReserveSeat();
newCustomer.AIMovement.Move(emptySeat.SeatTransform.position);
}
private IEnumerator CheckEmptySeatCoroutine()
{
var checkEmptySeatInterval = new WaitForSeconds(_checkEmptySeatInterval);
while (_waitingCustomers.Count > 0)
{
var emptySeat = _customerTableController.FindEmptySeat();
if (emptySeat != null)
{
_waitingCustomers.Dequeue();
var customer = CreateCustomer();
customer.SetTableSeat(emptySeat);
emptySeat.ReserveSeat();
customer.AIMovement.Move(emptySeat.SeatTransform.position);
continue;
}
yield return checkEmptySeatInterval;
}
_findEmptySeatCoroutineInstance = null;
}
public void RegisterCustomer(Customer customer)
{
Utils.RegisterList(InstanceCustomers, customer);
}
public void UnregisterCustomer(Customer customer)
{
Utils.UnregisterList(InstanceCustomers, customer);
}
2024-10-20 17:21:39 +00:00
public Customer FindCustomerMatchingItem(IPickup servingTableItem)
{
2024-10-15 18:01:16 +00:00
foreach (var element in InstanceCustomers)
{
2024-10-22 12:41:31 +00:00
if (!element || element.IsReceivedItem || element.IsMatchedServer) continue;
2024-10-15 18:01:16 +00:00
2024-10-22 12:41:31 +00:00
if (servingTableItem.Idx != element.OrderedCocktailData.Idx) continue;
2024-10-20 17:21:39 +00:00
return element;
}
2024-10-20 17:21:39 +00:00
return null;
}
2024-10-29 12:17:00 +00:00
public int OrderedCocktailCount(string cocktailDataIdx)
{
return InstanceCustomers.Count(element => element.IsOrderedCocktail() && element.OrderedCocktailData.Idx == cocktailDataIdx);
}
2025-01-02 09:33:05 +00:00
public List<string> GetSkins()
{
int currentRound = int.Parse(TycoonManager.Instance.GetCurrentLevelData().Idx);
foreach (var data in _roundSkinData.Where(data => currentRound >= data.MinRound))
{
return data.Skins;
}
return new List<string> { "default" };
}
}
}