// Assets/_Project/Scripts/Gameplay/Draft/DraftOption.cs using UnityEngine; namespace TD.Gameplay.Draft { /// /// Base class for one authored draft choice. The draft system offers a player a /// weighted-random selection of these between waves; the player picks one and the /// server applies its effect. /// /// /// One asset per choice. Concrete subclasses (e.g. /// ) carry the payload and implement /// . New choice types (systemic upgrade, builder ability, /// relic quest, enemy debuff) are added as new subclasses — the draft spine /// (, , HUD) is type-agnostic. /// /// Identity. Options live in and are referenced /// over the network by their pool index (DraftOptionId) — the same /// stable-within-a-match index pattern used by the tower catalog. /// /// Server-only logic. and /// run on the server and operate on the target player's /// per-player components (deck, gold, etc.). The ScriptableObject holds no per-player /// state, so a single asset is shared across all players and matches. /// public abstract class DraftOption : ScriptableObject { [Header("Presentation")] [Tooltip("Name shown on the draft card.")] public string DisplayName; [Tooltip("Short description shown on the draft card.")] [TextArea(2, 4)] public string Description; [Tooltip("OPTIONAL override for the draft card icon. Leave empty to inherit the icon of " + "the item this option grants (its tower / spell); assign one only when you want " + "to override that inherited icon.")] public Sprite Icon; /// /// The icon actually shown on the draft card. Returns the explicit /// override when one is assigned; otherwise subclasses fall back to the icon of the item /// they grant (tower, spell). The base class has no referenced item, so it just returns /// (which may be null). /// public virtual Sprite ResolveIcon() => Icon; [Header("Generation")] [Tooltip("Relative draw weight. Higher = offered more often. Rarer rewards use " + "lower weights. Must be > 0.")] [Min(0.0001f)] public float Weight = 1f; /// /// Server-only: can this option validly be OFFERED to the given player right now? /// Lets the generator skip options that would be a no-op (e.g. a tower the player /// already owns). Default true; override when an option has prerequisites. /// public virtual bool IsValidFor(ulong clientId) => true; /// /// Server-only: apply this option's effect to the given player. Returns false if /// it could not be applied (caller treats as a no-op and logs). /// public abstract bool ServerApply(ulong clientId); } }