using System; using System.Collections.Generic; using UnityEngine; using WarGame.Data; namespace WarGame.Units { [System.Serializable] public class UnitProgression { [SerializeField] private UnitDataSO unitData; [SerializeField] private int currentLevel = 1; [SerializeField] private int currentExp = 0; [SerializeField] private int totalKills = 0; [SerializeField] private int battlesSurvived = 0; public UnitDataSO UnitData => unitData; public int CurrentLevel => currentLevel; public int CurrentExp => currentExp; public int TotalKills => totalKills; public int BattlesSurvived => battlesSurvived; public event Action OnExpGained; // gainedAmount, currentTotal public event Action OnLevelUp; // newLevel public event Action OnTacticUnlocked; public UnitProgression(UnitDataSO data, int startingLevel = 1) { unitData = data; currentLevel = Mathf.Clamp(startingLevel, 1, data != null ? data.maxLevel : 10); currentExp = 0; } public int ExpNeededForNextLevel => unitData != null ? unitData.GetExpRequiredForLevel(currentLevel) : 100; public float ExpPercent => unitData != null ? (float)currentExp / ExpNeededForNextLevel : 0f; /// /// Adds experience to this unit, handling level-ups and tactic unlocks. /// public void AddExperience(int amount) { if (unitData == null || currentLevel >= unitData.maxLevel || amount <= 0) return; currentExp += amount; OnExpGained?.Invoke(amount, currentExp); while (currentLevel < unitData.maxLevel && currentExp >= ExpNeededForNextLevel) { currentExp -= ExpNeededForNextLevel; currentLevel++; OnLevelUp?.Invoke(currentLevel); // Notify of any new tactics unlocked at this level List tactics = unitData.unlockedTactics; for (int i = 0; i < tactics.Count; i++) { if (tactics[i].requiredLevel == currentLevel) { OnTacticUnlocked?.Invoke(tactics[i]); } } } } public void RecordKill() { totalKills++; } public void RecordBattleSurvived() { battlesSurvived++; } // Calculated runtime stats public float GetMaxHealth() { if (unitData == null) return 100f; return unitData.maxHealth + (currentLevel - 1) * unitData.healthGrowth; } public float GetAttackDamage() { if (unitData == null) return 10f; return unitData.attackDamage + (currentLevel - 1) * unitData.damageGrowth; } public float GetDefenseArmor() { if (unitData == null) return 0f; return unitData.defenseArmor + (currentLevel - 1) * unitData.defenseGrowth; } public float GetMoveSpeed() { if (unitData == null) return 3.5f; return unitData.moveSpeed + (currentLevel - 1) * unitData.speedGrowth; } public float GetAttackRange() => unitData != null ? unitData.attackRange : 1.5f; public float GetAttackInterval() => unitData != null ? unitData.attackInterval : 1.2f; public float GetCriticalChance() => unitData != null ? unitData.criticalChance : 0.05f; public bool HasTactic(UnitTacticType tactic, out UnlockedTactic config) { if (unitData == null) { config = null; return false; } return unitData.HasTacticUnlocked(tactic, currentLevel, out config); } } }