Files
WarGame/Assets/Scripts/Units/UnitProgression.cs

115 lines
3.9 KiB
C#
Raw Permalink Normal View History

2026-09-30 23:45:58 +01:00
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<int, int> OnExpGained; // gainedAmount, currentTotal
public event Action<int> OnLevelUp; // newLevel
public event Action<UnlockedTactic> 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;
/// <summary>
/// Adds experience to this unit, handling level-ups and tactic unlocks.
/// </summary>
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<UnlockedTactic> 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);
}
}
}