// Assets/_Project/Scripts/Gameplay/EnemyAbilities/EnemyAbilityDefinition.cs using UnityEngine; using TD.Core; namespace TD.Gameplay.EnemyAbilities { /// /// Base class for one enemy ability (e.g. "split into smaller enemies on death"). Rolled /// at random for each spawned enemy by and applied /// via . /// /// /// One asset per kind. is fixed per subclass, same as /// . uses /// it to build a fixed-size, enum-indexed lookup table. /// /// Server-only hooks. All three hooks below only ever run on the server — /// only calls them when IsServer is true. and are no-ops for abilities that don't /// need spawn-time setup or a per-frame timer (e.g. Split on Death uses neither); they exist /// so a future cooldown-driven ability (disable towers, teleport) doesn't need a base-class /// change. /// public abstract class EnemyAbilityDefinition : ScriptableObject { /// Which enemy ability this asset's data belongs to. public abstract EnemyAbilityKind Kind { get; } [Header("Presentation")] [Tooltip("Name shown in debug logs and future enemy-info UI.")] public string DisplayName; [Tooltip("Short description shown in future enemy-info UI.")] [TextArea(2, 4)] public string Description; [Header("Selection")] [Tooltip("Relative weight of this ability being rolled, vs. the pool's other abilities " + "and its no-ability chance. Same semantics as DraftOption.Weight.")] [Min(0f)] public float Weight = 1f; /// Server-only: called once, right after this ability is assigned (before the /// enemy's NetworkObject is spawned to clients). Default no-op. public virtual void ServerOnSpawn(EnemyAbility instance) { } /// Server-only: called every frame this ability is active on a live enemy. /// Default no-op. public virtual void ServerTick(EnemyAbility instance, float dt) { } /// Server-only: called the instant the enemy's HP reaches zero, before the /// death animation/despawn sequence plays. Default no-op. public virtual void ServerOnDeath(EnemyAbility instance, EnemyHealth health) { } } }