using UnityEngine; [CreateAssetMenu( fileName = "MapEnemyBalance", menuName = "Map Radar/Enemy Balance Config")] public sealed class MapEnemyBalanceConfig : ScriptableObject { [Header("Wave")] [SerializeField, Min(0)] private int targetsPerWave = 5; [SerializeField, Min(0.02f)] private float simulationStep = 0.1f; [Header("Spawn")] [SerializeField, Range(0f, MapCoordinateSystem.CoordinateMaximum)] private float minimumSpawnDistanceFromBase = 5f; [SerializeField, Range(1, 128)] private int spawnPositionAttempts = 32; [Header("Global Balance Multipliers")] [SerializeField, Min(0f)] private float movementSpeedMultiplier = 0.5f; [SerializeField, Min(0f)] private float attackDelayMultiplier = 1.5f; [SerializeField, Min(0.01f)] private float healthMultiplier = 1f; [SerializeField, Min(0f)] private float baseDamageMultiplier = 1f; public int TargetsPerWave => Mathf.Max(0, targetsPerWave); public float SimulationStep => Mathf.Max(0.02f, simulationStep); public float MinimumSpawnDistanceFromBase => Mathf.Clamp( minimumSpawnDistanceFromBase, 0f, MapCoordinateSystem.CoordinateMaximum); public int SpawnPositionAttempts => Mathf.Clamp(spawnPositionAttempts, 1, 128); public float MovementSpeedMultiplier => Mathf.Max(0f, movementSpeedMultiplier); public float AttackDelayMultiplier => Mathf.Max(0f, attackDelayMultiplier); public float HealthMultiplier => Mathf.Max(0.01f, healthMultiplier); public float BaseDamageMultiplier => Mathf.Max(0f, baseDamageMultiplier); public float GetMovementSpeed(TargetConfig target) => target != null ? target.MovementSpeed * MovementSpeedMultiplier : 0f; public float GetAttackDelay(TargetConfig target) => target != null ? target.TimeBeforeAttack * AttackDelayMultiplier : 0f; public int GetHealth(TargetConfig target) => target != null ? Mathf.Max(1, Mathf.RoundToInt(target.Health * HealthMultiplier)) : 1; public int GetBaseDamage(TargetConfig target) => target != null ? Mathf.Max(0, Mathf.RoundToInt(target.BaseDamage * BaseDamageMultiplier)) : 1; private void OnValidate() { targetsPerWave = Mathf.Max(0, targetsPerWave); simulationStep = Mathf.Max(0.02f, simulationStep); minimumSpawnDistanceFromBase = Mathf.Clamp( minimumSpawnDistanceFromBase, 0f, MapCoordinateSystem.CoordinateMaximum); spawnPositionAttempts = Mathf.Clamp(spawnPositionAttempts, 1, 128); movementSpeedMultiplier = Mathf.Max(0f, movementSpeedMultiplier); attackDelayMultiplier = Mathf.Max(0f, attackDelayMultiplier); healthMultiplier = Mathf.Max(0.01f, healthMultiplier); baseDamageMultiplier = Mathf.Max(0f, baseDamageMultiplier); } }