first pass at enemy upgrades

This commit is contained in:
Ian Woods 2026-07-28 20:59:43 -07:00
parent a26d0acbfb
commit 8714885efa
13 changed files with 351 additions and 0 deletions

View file

@ -0,0 +1,55 @@
// Assets/_Project/Scripts/Gameplay/EnemyAbilities/EnemyAbilityDefinition.cs
using UnityEngine;
using TD.Core;
namespace TD.Gameplay.EnemyAbilities
{
/// <summary>
/// Base class for one enemy ability (e.g. "split into smaller enemies on death"). Rolled
/// at random for each spawned enemy by <see cref="EnemyAbilityPool.RollRandom"/> and applied
/// via <see cref="EnemyAbility.InitializeServer"/>.
/// </summary>
/// <remarks>
/// <para><b>One asset per kind.</b> <see cref="Kind"/> is fixed per subclass, same as
/// <see cref="BuilderSpells.BuilderSpellDefinition"/>. <see cref="EnemyAbilityPool"/> uses
/// it to build a fixed-size, enum-indexed lookup table.</para>
///
/// <para><b>Server-only hooks.</b> All three hooks below only ever run on the server —
/// <see cref="EnemyAbility"/> only calls them when <c>IsServer</c> is true. <see
/// cref="ServerOnSpawn"/> and <see cref="ServerTick"/> 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.</para>
/// </remarks>
public abstract class EnemyAbilityDefinition : ScriptableObject
{
/// <summary>Which enemy ability this asset's data belongs to.</summary>
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;
/// <summary>Server-only: called once, right after this ability is assigned (before the
/// enemy's NetworkObject is spawned to clients). Default no-op.</summary>
public virtual void ServerOnSpawn(EnemyAbility instance) { }
/// <summary>Server-only: called every frame this ability is active on a live enemy.
/// Default no-op.</summary>
public virtual void ServerTick(EnemyAbility instance, float dt) { }
/// <summary>Server-only: called the instant the enemy's HP reaches zero, before the
/// death animation/despawn sequence plays. Default no-op.</summary>
public virtual void ServerOnDeath(EnemyAbility instance, EnemyHealth health) { }
}
}