using Northbound; using System.Collections.Generic; using Unity.Netcode; using UnityEngine; public class EnemyPortal : MonoBehaviour { [System.Serializable] public class MonsterEntry { public Northbound.Data.MonsterData monsterData; public GameObject prefab; } [Header("Spawn Settings")] [Tooltip("몬스터 데이터 목록 (Editor에서 자동 로드 가능)")] [SerializeField] private List 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(); if (selectedEntry.monsterData.cost > remainingCost) { if (!CanSpawnAnyMonster(remainingCost)) { break; } continue; } SpawnEnemy(selectedEntry.prefab); remainingCost -= selectedEntry.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) { if (entry.monsterData.cost <= remainingCost) { return true; } } return false; } private MonsterEntry SelectMonsterByWeight() { float totalWeight = 0f; foreach (var entry in monsterEntries) { totalWeight += entry.monsterData.weight; } float randomValue = Random.Range(0f, totalWeight); float cumulativeWeight = 0f; foreach (var entry in monsterEntries) { cumulativeWeight += entry.monsterData.weight; if (randomValue <= cumulativeWeight) { return entry; } } return monsterEntries[0]; } private void SpawnEnemy(GameObject prefab) { GameObject enemy = Instantiate(prefab, transform); if (enemy.GetComponent() == null) { var visibility = enemy.AddComponent(); visibility.showInExploredAreas = false; visibility.updateInterval = 0.2f; } enemy.GetComponent().Spawn(); } private void IncreaseCost() { currentCost *= (1f + costIncreaseRate / 100f); } }