using System; using System.Collections.Generic; using JetBrains.Annotations; using UnityEngine; using static CustomerController; using Random = UnityEngine.Random; public class CustomerManager : MonoBehaviour { public static CustomerManager Instance { get; private set; } [SerializeField] private GameObject _customerPrefab; [SerializeField] private Transform _customerSpawnPoint; [SerializeField] private float _timeToNextCustomerMin = 5; [SerializeField] private float _timeToNextCustomerMax = 10; private List _sellCounters = new List(); private List AvailableCounters { get; } = new List(); private readonly List _customers = new List(); private int _newCustomerNeeded; // 0 = no new ones needed, > 0 = new one needed private float _timeToNextCustomer; //Args for the event public class OnCustomerLeftArgs : EventArgs { public bool Angry; } public event EventHandler OnCustomerLeft; // Start is called before the first frame update private void Start() { // Find all sellingCounters in the scene if (Instance != null) { Debug.LogError("What? 2 CustomerManagers crazy!!!"); } Instance = this; var sellCounters = FindObjectsOfType(); foreach (var sellCounter in sellCounters) { sellCounter.OnCounterStartSelling += CounterStartedSelling; _sellCounters?.Add(sellCounter); } } private void CounterStartedSelling(object sender, [NotNull] SellCounter.OnCounterStartSellingArgs e) { if (e == null) throw new ArgumentNullException(nameof(e)); // Spawn a customer at the spawn point _newCustomerNeeded += 1; AvailableCounters.Add(e.SellCounter); } private void SpawnCustomer(SellCounter target) { var customer = Instantiate(_customerPrefab, _customerSpawnPoint.position, Quaternion.identity); var customerController = customer.GetComponent(); customerController.SetTargetCounter(target); customerController.SetExitPosition(_customerSpawnPoint.position); customerController.OnCustomerLeft += CustomerLeft; _customers.Add(customerController); } private void CustomerLeft(SellCounter sellCounter, CustomerController customerController) { if (customerController.State == Customer.MoodState.Angry) { //Customer left angry, should dispach a new customer to the counter _newCustomerNeeded += 1; if (!AvailableCounters.Contains(sellCounter)) { AvailableCounters.Add(sellCounter); } else { Debug.LogError("This should not happen, the counter is already in the available list"); } } OnCustomerLeft?.Invoke(this, new OnCustomerLeftArgs { Angry = customerController.State == Customer.MoodState.Angry }); } // Update is called once per frame private void Update() { if(AvailableCounters.Count == 0) return; if (_newCustomerNeeded > 0) { _timeToNextCustomer -= Time.deltaTime; if (_timeToNextCustomer <= 0) { _newCustomerNeeded--; _timeToNextCustomer = Random.Range(_timeToNextCustomerMin, _timeToNextCustomerMax); SellCounter target = AvailableCounters[Random.Range(0, AvailableCounters.Count)]; SpawnCustomer(target); AvailableCounters.Remove(target); } } } public void StoppedSelling(SellCounter sellCounter) { if (AvailableCounters.Contains(sellCounter)) { AvailableCounters.Remove(sellCounter); } //Check if any customer has this counter as an target foreach (var customerController in _customers) { if (customerController.TargetCounter != sellCounter) continue; customerController.SetDestination(_customerSpawnPoint.position); customerController.SetState(CustomerState.WalkingToExit); } } public void CustomerDies([NotNull] CustomerController customerController) { if (customerController == null) return; if (_customers.Contains(customerController)) { _customers.Remove(customerController); } } }