// Assets/_Project/Scripts/Gameplay/Waves/WaveGroup.cs
using System;
using UnityEngine;
using TD.Core;
namespace TD.Gameplay.Waves
{
///
/// One weighted candidate inside a : a wave that may be drawn,
/// and how likely it is to be drawn relative to the group's other entries.
///
///
/// Weight is RELATIVE, not an absolute probability. The draw normalizes every
/// candidate's weight against the summed weight of the whole candidate set, so three
/// entries at 1.0 each are equally likely (33% apiece) and an entry at 0.5 is half as
/// likely to be drawn as one at 1.0. This is what makes the default sane: new entries
/// start at 1.0, so adding a wave to a group never silently re-weights the others.
///
/// A class rather than a struct specifically so can carry a
/// field initializer — Unity runs it when the inspector creates a fresh array element,
/// which is what gives new entries their equal-by-default weighting. Mirrors
/// .
///
[Serializable]
public class WavePoolEntry
{
[Tooltip("The wave that may be drawn from this group.")]
public WaveDefinition Wave;
[Tooltip("Relative draw weight within this group's pool. Entries at equal weight are " +
"equally likely; an entry at 0.5 is half as likely as one at 1.0. NOT an " +
"absolute percentage.")]
[PoolWeight("wave")]
public float Weight = 1f;
}
///
/// A named, reusable bag of candidate waves. Groups are the unit designers move between
/// phases: dragging a group asset from Phase 1's pool to Phase 2's moves every wave in it
/// (and their weights) in one action.
///
///
/// Why weights live on the entry, not on . Weight is a
/// property of "how common is this wave in this pool", not of the wave itself. Keeping
/// it here means the same asset can be a staple of one group and
/// a rarity in another, and a group carries its tuning with it when moved between phases.
///
/// Boss groups use the same type. A boss wave is just a
/// whose entries spawn a single powerful enemy, so boss pools
/// are ordinary s referenced from
/// .
///
[CreateAssetMenu(fileName = "WaveGroup", menuName = "TD/Run/Wave Group", order = 10)]
public class WaveGroup : ScriptableObject
{
[Tooltip("Designer-facing name for this group, shown in run-structure validation " +
"messages. Falls back to the asset name when empty.")]
public string DisplayName;
[Tooltip("Candidate waves in this group, each with a relative draw weight.")]
public WavePoolEntry[] Waves;
/// Name used in validation and log messages. Falls back to the asset name.
public string Label => string.IsNullOrWhiteSpace(DisplayName) ? name : DisplayName;
/// Number of entries, including any that are null or zero-weight.
public int Count => Waves?.Length ?? 0;
}
}