151 lines
4.0 KiB
C#
151 lines
4.0 KiB
C#
using Northbound;
|
|
using Northbound.Data;
|
|
using System.Collections.Generic;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
public class EnemyPortal : MonoBehaviour
|
|
{
|
|
[System.Serializable]
|
|
public class MonsterEntry
|
|
{
|
|
public GameObject prefab;
|
|
}
|
|
|
|
[Header("Spawn Settings")]
|
|
[Tooltip("몬스터 프리팹 목록 (Editor에서 자동 로드 가능)")]
|
|
[SerializeField] private List<MonsterEntry> monsterEntries = new();
|
|
|
|
[Header("Cost Settings")]
|
|
[Tooltip("시간당 코스트 시작 값")]
|
|
[SerializeField] private float initialCost = 4f;
|
|
[Tooltip("사이클마다 코스트 증가율 (%)")]
|
|
[SerializeField] private float costIncreaseRate = 10f;
|
|
|
|
private float currentCost;
|
|
|
|
void Start()
|
|
{
|
|
currentCost = initialCost;
|
|
GlobalTimer.Instance.OnCycleStart += OnCycleStart;
|
|
}
|
|
|
|
private void OnCycleStart(int cycleNumber)
|
|
{
|
|
SpawnMonsters();
|
|
IncreaseCost();
|
|
}
|
|
|
|
private void SpawnMonsters()
|
|
{
|
|
float remainingCost = currentCost;
|
|
int spawnedCount = 0;
|
|
|
|
while (remainingCost > 0 && monsterEntries.Count > 0)
|
|
{
|
|
MonsterEntry selectedEntry = SelectMonsterByWeight();
|
|
MonsterData monsterData = GetMonsterDataFromPrefab(selectedEntry.prefab);
|
|
|
|
if (monsterData == null)
|
|
{
|
|
Debug.LogWarning($"[EnemyPortal] Could not find MonsterData on {selectedEntry.prefab.name}");
|
|
continue;
|
|
}
|
|
|
|
if (monsterData.cost > remainingCost)
|
|
{
|
|
if (!CanSpawnAnyMonster(remainingCost))
|
|
{
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
SpawnEnemy(selectedEntry.prefab);
|
|
remainingCost -= monsterData.cost;
|
|
spawnedCount++;
|
|
}
|
|
|
|
if (spawnedCount > 0)
|
|
{
|
|
Debug.Log($"[EnemyPortal] Spawned {spawnedCount} monsters (Cost used: {currentCost - remainingCost:F2})");
|
|
}
|
|
}
|
|
|
|
private bool CanSpawnAnyMonster(float remainingCost)
|
|
{
|
|
foreach (var entry in monsterEntries)
|
|
{
|
|
MonsterData monsterData = GetMonsterDataFromPrefab(entry.prefab);
|
|
if (monsterData != null && monsterData.cost <= remainingCost)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private MonsterEntry SelectMonsterByWeight()
|
|
{
|
|
float totalWeight = 0f;
|
|
foreach (var entry in monsterEntries)
|
|
{
|
|
MonsterData monsterData = GetMonsterDataFromPrefab(entry.prefab);
|
|
if (monsterData != null)
|
|
{
|
|
totalWeight += monsterData.weight;
|
|
}
|
|
}
|
|
|
|
float randomValue = Random.Range(0f, totalWeight);
|
|
float cumulativeWeight = 0f;
|
|
|
|
foreach (var entry in monsterEntries)
|
|
{
|
|
MonsterData monsterData = GetMonsterDataFromPrefab(entry.prefab);
|
|
if (monsterData != null)
|
|
{
|
|
cumulativeWeight += monsterData.weight;
|
|
if (randomValue <= cumulativeWeight)
|
|
{
|
|
return entry;
|
|
}
|
|
}
|
|
}
|
|
|
|
return monsterEntries[0];
|
|
}
|
|
|
|
private MonsterData GetMonsterDataFromPrefab(GameObject prefab)
|
|
{
|
|
if (prefab == null) return null;
|
|
|
|
MonsterDataComponent component = prefab.GetComponent<MonsterDataComponent>();
|
|
if (component != null)
|
|
{
|
|
return component.monsterData;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void SpawnEnemy(GameObject prefab)
|
|
{
|
|
GameObject enemy = Instantiate(prefab, transform);
|
|
|
|
if (enemy.GetComponent<FogOfWarVisibility>() == null)
|
|
{
|
|
var visibility = enemy.AddComponent<FogOfWarVisibility>();
|
|
visibility.showInExploredAreas = false;
|
|
visibility.updateInterval = 0.2f;
|
|
}
|
|
|
|
enemy.GetComponent<NetworkObject>().Spawn();
|
|
}
|
|
|
|
private void IncreaseCost()
|
|
{
|
|
currentCost *= (1f + costIncreaseRate / 100f);
|
|
}
|
|
}
|