124 lines
3.9 KiB
C#
124 lines
3.9 KiB
C#
|
|
using System.Collections;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
namespace MedievalShopkeeper
|
||
|
|
{
|
||
|
|
public class NPCManager : MonoBehaviour
|
||
|
|
{
|
||
|
|
[Header("Prefabs")]
|
||
|
|
[Tooltip("List of visually different NPC prefabs to spawn.")]
|
||
|
|
public List<GameObject> npcPrefabs;
|
||
|
|
|
||
|
|
[Tooltip("Where the NPCs spawn when they arrive.")]
|
||
|
|
public Transform spawnPoint;
|
||
|
|
|
||
|
|
[Header("Spawning Settings")]
|
||
|
|
[Tooltip("Base minimum time between spawns when shop is open.")]
|
||
|
|
public float minSpawnDelay = 10f;
|
||
|
|
[Tooltip("Base maximum time between spawns when shop is open.")]
|
||
|
|
public float maxSpawnDelay = 25f;
|
||
|
|
|
||
|
|
[Header("Demand & Items")]
|
||
|
|
[Tooltip("List of all items currently available in the game that NPCs might want to buy.")]
|
||
|
|
public List<ItemData> allAvailableItems;
|
||
|
|
|
||
|
|
private float spawnTimer;
|
||
|
|
|
||
|
|
private void Start()
|
||
|
|
{
|
||
|
|
ResetSpawnTimer();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Update()
|
||
|
|
{
|
||
|
|
if (GameManager.Instance == null || !GameManager.Instance.IsShopOpen) return;
|
||
|
|
|
||
|
|
spawnTimer -= Time.deltaTime;
|
||
|
|
|
||
|
|
if (spawnTimer <= 0)
|
||
|
|
{
|
||
|
|
SpawnNPC();
|
||
|
|
ResetSpawnTimer();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void ResetSpawnTimer()
|
||
|
|
{
|
||
|
|
float delay = Random.Range(minSpawnDelay, maxSpawnDelay);
|
||
|
|
|
||
|
|
if (GameManager.Instance != null && GameManager.Instance.IsNightTime)
|
||
|
|
{
|
||
|
|
// Night time has fewer customers, so multiply the wait time
|
||
|
|
delay *= 2.5f;
|
||
|
|
}
|
||
|
|
|
||
|
|
spawnTimer = delay;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void SpawnNPC()
|
||
|
|
{
|
||
|
|
if (npcPrefabs == null || npcPrefabs.Count == 0)
|
||
|
|
{
|
||
|
|
Debug.LogWarning("[NPCManager] No NPC Prefabs assigned!");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
Vector3 spawnPos = spawnPoint != null ? spawnPoint.position : (ShopDoor.Instance != null ? ShopDoor.Instance.transform.position : Vector3.zero);
|
||
|
|
|
||
|
|
GameObject prefabToSpawn = npcPrefabs[Random.Range(0, npcPrefabs.Count)];
|
||
|
|
GameObject spawnedObj = Instantiate(prefabToSpawn, spawnPos, Quaternion.identity);
|
||
|
|
|
||
|
|
CustomerNPC npc = spawnedObj.GetComponent<CustomerNPC>();
|
||
|
|
if (npc != null)
|
||
|
|
{
|
||
|
|
NPCIntention intent = RollForIntention();
|
||
|
|
List<ItemData> shoppingList = GenerateShoppingList(intent);
|
||
|
|
|
||
|
|
npc.Initialize(intent, shoppingList);
|
||
|
|
Debug.Log($"[NPCManager] Spawned {npc.npcName} with intention: {intent}.");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private NPCIntention RollForIntention()
|
||
|
|
{
|
||
|
|
float shoplifterChance = 5f;
|
||
|
|
float raiderChance = 2f;
|
||
|
|
|
||
|
|
if (GameManager.Instance != null && GameManager.Instance.IsNightTime)
|
||
|
|
{
|
||
|
|
// Massive risk increase at night
|
||
|
|
shoplifterChance = 20f;
|
||
|
|
raiderChance = 10f;
|
||
|
|
}
|
||
|
|
|
||
|
|
float roll = Random.Range(0f, 100f);
|
||
|
|
|
||
|
|
if (roll < raiderChance) return NPCIntention.Raider;
|
||
|
|
if (roll < raiderChance + shoplifterChance) return NPCIntention.Shoplifter;
|
||
|
|
|
||
|
|
return NPCIntention.Shopper;
|
||
|
|
}
|
||
|
|
|
||
|
|
private List<ItemData> GenerateShoppingList(NPCIntention intent)
|
||
|
|
{
|
||
|
|
List<ItemData> list = new List<ItemData>();
|
||
|
|
|
||
|
|
// Raiders don't care about shopping lists
|
||
|
|
if (intent == NPCIntention.Raider) return list;
|
||
|
|
|
||
|
|
if (allAvailableItems == null || allAvailableItems.Count == 0) return list;
|
||
|
|
|
||
|
|
int itemsWanted = Random.Range(1, 4);
|
||
|
|
for (int i = 0; i < itemsWanted; i++)
|
||
|
|
{
|
||
|
|
ItemData randomItem = allAvailableItems[Random.Range(0, allAvailableItems.Count)];
|
||
|
|
list.Add(randomItem);
|
||
|
|
}
|
||
|
|
|
||
|
|
return list;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|