using AfterHours.Core; using AfterHours.Data; using AfterHours.Shop; using Unity.Netcode; using UnityEngine; namespace AfterHours.Customers { /// /// Erzeugt Kunden abhängig von Uhrzeit und Ruf. Läuft nur auf dem Server. /// public sealed class CustomerSpawner : NetworkBehaviour { public static CustomerSpawner Instance { get; private set; } [SerializeField] private GameObject _customerPrefab; [SerializeField] private Transform _entryPoint; [SerializeField] private Transform _exitPoint; [SerializeField] private CashRegister _register; [Header("Andrang")] [SerializeField] private int _maxConcurrent = 20; [SerializeField] private float _baseSecondsBetweenSpawns = 8f; [Tooltip("Multiplikator über den Tag: x-Achse 0..24 Uhr, y = Andrang.")] [SerializeField] private AnimationCurve _rushCurve = AnimationCurve.Linear(0f, 1f, 24f, 1f); public Transform ExitPoint => _exitPoint; private float _cooldown; private int _alive; private void Awake() => Instance = this; public override void OnNetworkDespawn() { if (Instance == this) Instance = null; } private void Update() { if (!IsServer) return; if (GameClock.Instance == null || !GameClock.Instance.IsOpen) return; if (_alive >= _maxConcurrent) return; _cooldown -= Time.deltaTime; if (_cooldown > 0f) return; Spawn(); _cooldown = NextInterval(); } private float NextInterval() { float rush = Mathf.Max(0.1f, _rushCurve.Evaluate(GameClock.Instance.HourOfDay)); float reputation = Mathf.Lerp(1.6f, 0.6f, ShopEconomy.Instance.Reputation); return _baseSecondsBetweenSpawns / rush * reputation * Random.Range(0.7f, 1.3f); } private void Spawn() { var instance = Instantiate(_customerPrefab, _entryPoint.position, _entryPoint.rotation); var netObject = instance.GetComponent(); netObject.Spawn(); var categories = (ProductCategory[])System.Enum.GetValues(typeof(ProductCategory)); var agent = instance.GetComponent(); agent.Initialize( tolerance: Random.Range(0.15f, 0.95f), wantedItems: Random.Range(1, 4), wantedCategory: categories[Random.Range(0, categories.Length)], register: _register); _alive++; } /// Wird von CustomerAgent kurz vor dem Despawn aufgerufen. public void NotifyCustomerGone() { if (!IsServer) return; _alive = Mathf.Max(0, _alive - 1); } } }