// Assets/_Project/Scripts/Gameplay/GoldConfig.cs using System; using UnityEngine; namespace TD.Gameplay { /// /// Per-wave gold rules nested under . Each entry maps to one /// wave by array index in . /// /// /// Pairing with WaveDefinition. The runtime pairing of gold entry to wave is by /// array index — entry 0 applies to wave 1, etc. The reference here /// is OPTIONAL and exists purely so the inspector can compute and display the /// read-only value (which needs to know the wave's /// total enemy count to multiply against ). Leaving it /// unset just hides the kill-reward portion of the preview; runtime is unaffected. /// [Serializable] public class WaveGoldEntry { [Tooltip("Optional reference to the WaveDefinition this entry pairs with. " + "Used ONLY for the inspector preview total — runtime pairing is by " + "array index in GoldConfig.Waves. Drag the matching WaveDefinition " + "here to see the live total computed under this entry.")] public WaveDefinition Wave; [Tooltip("Gold awarded to the killing player per enemy slain during this wave. " + "Applies uniformly to every enemy type in the wave.")] public int GoldPerEnemy = 10; [Tooltip("Flat bonus gold awarded to every active player when this wave is fully " + "cleared (all enemies dead or reached the goal).")] public int CompletionBonus = 50; [Tooltip("Extra bonus gold awarded to a player who cleared this wave without any " + "enemy from their own zone escaping their leak volume. Stacks on top of " + "CompletionBonus for the no-leak achievement.")] public int NoLeaksBonus = 50; /// /// Read-only preview of the maximum gold a single player could earn in this wave: /// GoldPerEnemy × totalEnemyCount + CompletionBonus + NoLeaksBonus. /// /// /// Returns just CompletionBonus + NoLeaksBonus if is null /// (no enemy count to multiply against). Pure computation — safe at edit time and /// at runtime. The custom inspector under renders this as /// a non-editable label under the entry's fields. /// public int PreviewTotalGold { get { int total = CompletionBonus + NoLeaksBonus; if (Wave != null && Wave.Entries != null) { int enemies = 0; foreach (var e in Wave.Entries) { if (e.EnemyType != null && e.Count > 0) enemies += e.Count; } total += GoldPerEnemy * enemies; } return total; } } } /// /// Single source of truth for every gold-related tunable in the game. /// /// /// Inspector layout. StartingGold is at the top and applies to every player. /// The Waves array follows, each element collapsible in the inspector with the /// per-wave rules and a read-only preview total computed from the entry's data. /// /// Wiring. Assign one GoldConfig asset to WaveManager.goldConfig in /// the Match scene. WaveManager initializes per-player starting gold from /// at match start, uses /// to compute kill rewards, and awards / /// when each wave clears. /// /// No per-enemy-type bounties. Every enemy killed in wave N grants the same /// regardless of . /// If per-type variation becomes a design need, extend WaveGoldEntry with a per-type /// table; the current model intentionally favors simplicity. /// [CreateAssetMenu(fileName = "GoldConfig", menuName = "TD/Gold Config", order = 2)] public class GoldConfig : ScriptableObject { [Tooltip("Gold each player starts the match with. Same for every player.")] public int StartingGold = 100; [Tooltip("Per-wave gold rules. Element 0 = Wave 1. Match the order and length of " + "WaveManager.waveDefinitions; extra entries are ignored, missing entries " + "fall back to zero gold for that wave.")] public WaveGoldEntry[] Waves; /// /// Returns the gold entry for the given 1-based wave number, or null if out of range. /// public WaveGoldEntry GetWaveEntry(int waveNumber) { if (Waves == null) return null; int index = waveNumber - 1; if (index < 0 || index >= Waves.Length) return null; return Waves[index]; } } }