UnityTowerDefense/Assets/_Project/Scripts/Gameplay/GoldConfig.cs

112 lines
5.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Assets/_Project/Scripts/Gameplay/GoldConfig.cs
using System;
using UnityEngine;
namespace TD.Gameplay
{
/// <summary>
/// Per-wave gold rules nested under <see cref="GoldConfig"/>. Each entry maps to one
/// wave by array index in <see cref="GoldConfig.Waves"/>.
/// </summary>
/// <remarks>
/// <b>Pairing with WaveDefinition.</b> The runtime pairing of gold entry to wave is by
/// array index — entry 0 applies to wave 1, etc. The <see cref="Wave"/> reference here
/// is OPTIONAL and exists purely so the inspector can compute and display the
/// <see cref="PreviewTotalGold"/> read-only value (which needs to know the wave's
/// total enemy count to multiply against <see cref="GoldPerEnemy"/>). Leaving it
/// unset just hides the kill-reward portion of the preview; runtime is unaffected.
/// </remarks>
[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;
/// <summary>
/// Read-only preview of the maximum gold a single player could earn in this wave:
/// <c>GoldPerEnemy × totalEnemyCount + CompletionBonus + NoLeaksBonus</c>.
/// </summary>
/// <remarks>
/// Returns just <c>CompletionBonus + NoLeaksBonus</c> if <see cref="Wave"/> is null
/// (no enemy count to multiply against). Pure computation — safe at edit time and
/// at runtime. The custom inspector under <see cref="GoldConfig"/> renders this as
/// a non-editable label under the entry's fields.
/// </remarks>
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;
}
}
}
/// <summary>
/// Single source of truth for every gold-related tunable in the game.
/// </summary>
/// <remarks>
/// <b>Inspector layout.</b> 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.
///
/// <b>Wiring.</b> Assign one GoldConfig asset to <c>WaveManager.goldConfig</c> in
/// the Match scene. WaveManager initializes per-player starting gold from
/// <see cref="StartingGold"/> at match start, uses <see cref="WaveGoldEntry.GoldPerEnemy"/>
/// to compute kill rewards, and awards <see cref="WaveGoldEntry.CompletionBonus"/> /
/// <see cref="WaveGoldEntry.NoLeaksBonus"/> when each wave clears.
///
/// <b>No per-enemy-type bounties.</b> Every enemy killed in wave N grants the same
/// <see cref="WaveGoldEntry.GoldPerEnemy"/> regardless of <see cref="EnemyDefinition"/>.
/// If per-type variation becomes a design need, extend WaveGoldEntry with a per-type
/// table; the current model intentionally favors simplicity.
/// </remarks>
[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;
/// <summary>
/// Returns the gold entry for the given 1-based wave number, or null if out of range.
/// </summary>
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];
}
}
}