This commit is contained in:
2026-08-10 19:23:04 +02:00
commit 404d15a56c
134 changed files with 5374 additions and 0 deletions
@@ -0,0 +1,85 @@
using AfterHours.Core;
using AfterHours.Data;
using AfterHours.Shop;
using Unity.Netcode;
using UnityEngine;
namespace AfterHours.Customers
{
/// <summary>
/// Erzeugt Kunden abhängig von Uhrzeit und Ruf. Läuft nur auf dem Server.
/// </summary>
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<NetworkObject>();
netObject.Spawn();
var categories = (ProductCategory[])System.Enum.GetValues(typeof(ProductCategory));
var agent = instance.GetComponent<CustomerAgent>();
agent.Initialize(
tolerance: Random.Range(0.15f, 0.95f),
wantedItems: Random.Range(1, 4),
wantedCategory: categories[Random.Range(0, categories.Length)],
register: _register);
_alive++;
}
/// <summary>Wird von CustomerAgent kurz vor dem Despawn aufgerufen.</summary>
public void NotifyCustomerGone()
{
if (!IsServer) return;
_alive = Mathf.Max(0, _alive - 1);
}
}
}