216 lines
7.0 KiB
C#
216 lines
7.0 KiB
C#
using Northbound.Data;
|
|
using System.Collections.Generic;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
namespace Northbound
|
|
{
|
|
public class CreepCamp : NetworkBehaviour
|
|
{
|
|
[Header("Camp Settings")]
|
|
[Tooltip("Creep prefabs available to spawn")]
|
|
[SerializeField] private List<GameObject> creepPrefabs = new List<GameObject>();
|
|
|
|
[Header("Spawning Settings")]
|
|
[Tooltip("Camp strength multiplier (higher = stronger creeps)")]
|
|
[SerializeField] private float campStrength = 1f;
|
|
|
|
[Tooltip("Cost budget for spawning creeps")]
|
|
[SerializeField] private float campCostBudget = 10f;
|
|
|
|
[Tooltip("Spawn radius around camp")]
|
|
[SerializeField] private float spawnRadius = 5f;
|
|
|
|
[Tooltip("Max creep spawn attempts")]
|
|
[SerializeField] private int maxSpawnAttempts = 50;
|
|
|
|
private float _zPosition;
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
if (IsServer)
|
|
{
|
|
SpawnCreeps();
|
|
}
|
|
}
|
|
|
|
public void InitializeCamp(float zPosition, float strengthMultiplier)
|
|
{
|
|
_zPosition = zPosition;
|
|
campStrength = strengthMultiplier;
|
|
}
|
|
|
|
public void SetCreepPrefabs(List<GameObject> prefabs)
|
|
{
|
|
creepPrefabs.Clear();
|
|
creepPrefabs.AddRange(prefabs);
|
|
Debug.Log($"[CreepCamp] SetCreepPrefabs called with {prefabs.Count} prefabs. Current count: {creepPrefabs.Count}");
|
|
}
|
|
|
|
private void SpawnCreeps()
|
|
{
|
|
Debug.Log($"[CreepCamp] Starting creep spawn at Z={_zPosition:F1}, strength={campStrength:F2}x, prefabs={creepPrefabs.Count}");
|
|
|
|
if (creepPrefabs.Count == 0)
|
|
{
|
|
Debug.LogWarning($"[CreepCamp] No creep prefabs assigned!");
|
|
return;
|
|
}
|
|
|
|
float remainingCost = campCostBudget * campStrength;
|
|
Debug.Log($"[CreepCamp] Cost budget: {campCostBudget} x {campStrength:F2} = {remainingCost:F2}");
|
|
|
|
int spawnedCount = 0;
|
|
|
|
for (int attempt = 0; attempt < maxSpawnAttempts && remainingCost > 0; attempt++)
|
|
{
|
|
GameObject selectedCreep = SelectCreepByCost(remainingCost);
|
|
if (selectedCreep == null)
|
|
{
|
|
Debug.LogWarning($"[CreepCamp] Could not select creep (attempt {attempt + 1}/{maxSpawnAttempts}), remaining cost: {remainingCost:F2}");
|
|
break;
|
|
}
|
|
|
|
CreepData creepData = GetCreepDataFromPrefab(selectedCreep);
|
|
if (creepData == null)
|
|
{
|
|
Debug.LogWarning($"[CreepCamp] Could not get creep data from {selectedCreep.name}");
|
|
continue;
|
|
}
|
|
|
|
if (creepData.cost > remainingCost)
|
|
{
|
|
if (!CanSpawnAnyCreep(remainingCost))
|
|
{
|
|
Debug.LogWarning($"[CreepCamp] No affordable creeps found. Remaining cost: {remainingCost:F2}");
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
Debug.Log($"[CreepCamp] Spawning {selectedCreep.name} (cost: {creepData.cost}, remaining: {remainingCost:F2})");
|
|
SpawnCreep(selectedCreep);
|
|
remainingCost -= creepData.cost;
|
|
spawnedCount++;
|
|
}
|
|
|
|
Debug.Log($"[CreepCamp] Spawned {spawnedCount} creeps at Z={_zPosition:F1} with strength {campStrength:F2}x");
|
|
}
|
|
|
|
private GameObject SelectCreepByCost(float remainingCost)
|
|
{
|
|
List<GameObject> affordableCreeps = new List<GameObject>();
|
|
|
|
foreach (var prefab in creepPrefabs)
|
|
{
|
|
CreepData creepData = GetCreepDataFromPrefab(prefab);
|
|
if (creepData != null && creepData.cost <= remainingCost)
|
|
{
|
|
affordableCreeps.Add(prefab);
|
|
}
|
|
}
|
|
|
|
if (affordableCreeps.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
float totalWeight = 0f;
|
|
foreach (var prefab in affordableCreeps)
|
|
{
|
|
CreepData creepData = GetCreepDataFromPrefab(prefab);
|
|
if (creepData != null)
|
|
{
|
|
totalWeight += creepData.weight;
|
|
}
|
|
}
|
|
|
|
if (totalWeight == 0f)
|
|
{
|
|
return affordableCreeps[Random.Range(0, affordableCreeps.Count)];
|
|
}
|
|
|
|
float randomValue = Random.Range(0f, totalWeight);
|
|
float cumulativeWeight = 0f;
|
|
|
|
foreach (var prefab in affordableCreeps)
|
|
{
|
|
CreepData creepData = GetCreepDataFromPrefab(prefab);
|
|
if (creepData != null)
|
|
{
|
|
cumulativeWeight += creepData.weight;
|
|
if (randomValue <= cumulativeWeight)
|
|
{
|
|
return prefab;
|
|
}
|
|
}
|
|
}
|
|
|
|
return affordableCreeps[Random.Range(0, affordableCreeps.Count)];
|
|
}
|
|
|
|
private bool CanSpawnAnyCreep(float remainingCost)
|
|
{
|
|
foreach (var prefab in creepPrefabs)
|
|
{
|
|
CreepData creepData = GetCreepDataFromPrefab(prefab);
|
|
if (creepData != null && creepData.cost <= remainingCost)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private CreepData GetCreepDataFromPrefab(GameObject prefab)
|
|
{
|
|
if (prefab == null) return null;
|
|
|
|
CreepDataComponent component = prefab.GetComponent<CreepDataComponent>();
|
|
if (component != null)
|
|
{
|
|
return component.creepData;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void SpawnCreep(GameObject prefab)
|
|
{
|
|
Vector3 spawnOffset = Random.insideUnitSphere * spawnRadius;
|
|
spawnOffset.y = 0;
|
|
|
|
GameObject creep = Instantiate(prefab, transform.position + spawnOffset, Quaternion.identity);
|
|
|
|
if (creep.GetComponent<FogOfWarVisibility>() == null)
|
|
{
|
|
var visibility = creep.AddComponent<FogOfWarVisibility>();
|
|
visibility.showInExploredAreas = false;
|
|
visibility.updateInterval = 0.2f;
|
|
}
|
|
|
|
NetworkObject networkObj = creep.GetComponent<NetworkObject>();
|
|
if (networkObj == null)
|
|
{
|
|
networkObj = creep.AddComponent<NetworkObject>();
|
|
}
|
|
|
|
networkObj.Spawn();
|
|
|
|
creep.transform.SetParent(transform);
|
|
}
|
|
|
|
private void OnDrawGizmos()
|
|
{
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawWireSphere(transform.position, spawnRadius);
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
Gizmos.color = new Color(1f, 0f, 0f, 0.3f);
|
|
Gizmos.DrawSphere(transform.position, spawnRadius);
|
|
}
|
|
}
|
|
}
|