// Assets/_Project/Scripts/Gameplay/EnemyDefinition.cs using UnityEngine; namespace TD.Gameplay { /// /// Data definition for a single enemy type. One asset per type; shared across all /// instances spawned in a match. Consumed by at spawn time. /// /// /// Follows the same ScriptableObject pattern as TowerDefinition: data lives /// in project assets, only the asset reference (or its fields) crosses runtime code. /// Replace with a real mesh/animator when art is ready — /// no code changes required. /// /// An enemy type is flavour, not a difficulty tier. There is deliberately no /// absolute health field: health comes from based on how far /// into the run the encounter sits, and this asset only says how the type deviates from that /// (). Because waves are drawn at random from a phase pool, any /// difficulty baked into the roster would be difficulty handed out by the luck of the draw. /// Every type should be a viable occupant of any slot. /// [CreateAssetMenu(fileName = "EnemyDefinition", menuName = "TD/Enemy Definition", order = 3)] public class EnemyDefinition : ScriptableObject { [Header("Identity")] [Tooltip("Human-readable name shown in debug logs and future enemy-info UI.")] public string DisplayName; [Header("Stats")] [Tooltip("How tough this enemy is RELATIVE to its encounter's budget — not an absolute " + "hit-point value. 1.0 = exactly its share of the budget; 1.25 = a quarter " + "tougher than the slot calls for. Keep it near 1.0 and let the wave's enemy " + "count express tankiness (fewer enemies each get a bigger share).")] [Min(0.01f)] public float HpMultiplier = 1f; [Tooltip("Movement speed in world units per second along the A* path. ABSOLUTE and " + "unscaled — speed is a fixed character trait, not a progression axis. See " + "EnemyScalingConfig for why.")] public float MoveSpeed = 3f; [Tooltip("When true this enemy flies: it paths on the baked terrain grid, ignoring " + "towers, so it soars directly over the maze instead of following it. " + "Towers with GroundedOnly=true will not target it.")] public bool IsFlying; [Tooltip("Height (world units) above the ground a flying enemy hovers, so it " + "visually clears towers. Only used when IsFlying is true. Keep modest — " + "tower targeting uses 3D range, so large values eat into effective range.")] public float FlightHeight = 3f; [Header("Costs")] [Tooltip("Number of lives deducted from the shared pool when this enemy " + "reaches the Goal. Boss enemies might cost 2 or more lives.")] public int LivesCost = 1; // GoldReward removed in favor of per-wave GoldPerEnemy in GoldConfig — every // enemy in a given wave grants the same kill reward regardless of type. If // per-type variation is needed later, add an optional override here. [Header("Visuals")] [Tooltip("Prefab spawned in the world for this enemy. Must have NetworkObject, " + "NetworkTransform, EnemyHealth, EnemyStatus, and EnemyMovement at its root. " + "Place it on the Enemy physics layer.")] public GameObject EnemyPrefab; } }