using UnityEngine; using TD.Core; namespace TD.Towers { /// /// Data definition for a single tower type. One asset per tower type; shared across all /// instances of that tower in a match. Consumed by tower placement, construction, and /// (eventually) combat systems. /// /// /// TowerDefinitions are authored as ScriptableObject assets and referenced by /// (tower roster) and (which /// definition this placed tower corresponds to). Clients load the full asset locally /// from the project's ScriptableObject pool; only the asset reference (not the full data) /// is replicated over the network. /// /// Fields marked STUBBED are defined here to lock in the data shape but are not yet /// consumed by any runtime system. They will be wired in during the sessions noted. /// [CreateAssetMenu(fileName = "TowerDefinition", menuName = "TD/Tower Definition", order = 2)] public class TowerDefinition : ScriptableObject { // ------------------------------------------------------------------- // Identity // ------------------------------------------------------------------- [Header("Identity")] [Tooltip("Human-readable name shown in the HUD tower grid and context panel.")] public string DisplayName; [Tooltip("Short description shown in the HUD context panel when this tower is selected.")] [TextArea(2, 4)] public string Description; // ------------------------------------------------------------------- // Placement // ------------------------------------------------------------------- [Header("Placement")] [Tooltip("Footprint size in tiles. Default 2×2. The anchor tile is the south-west corner " + "of the footprint (minimum x, minimum y). Every tile in the footprint must be " + "Buildable and owned by the placing player for placement to succeed.")] public Vector2Int FootprintSize = new Vector2Int(2, 2); [Tooltip("Gold cost to place this tower. Deducted from the placing player's pool on " + "successful server-side placement validation.")] public int GoldCost; // ------------------------------------------------------------------- // Construction // ------------------------------------------------------------------- [Header("Construction")] [Tooltip("STUBBED — not consumed until Path D (Builder system). " + "Time in seconds from construction start to tower becoming active. " + "A Builder must be within build range for construction to proceed. " + "Set to 0 for instant construction (placeholder behaviour during Path B testing).")] public float BuildTime = 0f; // ------------------------------------------------------------------- // Visuals // ------------------------------------------------------------------- [Header("Visuals")] [Tooltip("Prefab instantiated in the world when this tower is placed. Must have a " + "TowerInstance component at its root. During Path B this is a colored cube; " + "replace with a real mesh when art is available.")] public GameObject TowerPrefab; // ------------------------------------------------------------------- // Combat // ------------------------------------------------------------------- [Header("Combat — Targeting")] [Tooltip("How the tower's damage is typed. Determines lingering effects and enemy " + "resistance/weakness interactions.")] public DamageType DamageType; [Tooltip("Which enemy in range the tower prioritizes.")] public TargetPriority TargetPriority; [Tooltip("How damage is distributed: Single (one enemy), Splash (primary + radius), " + "Chain (primary then N nearest neighbours).")] public TargetType TargetType; [Tooltip("When true, this tower can only target grounded enemies. " + "Default false = targets both grounded and flying units.")] public bool GroundedOnly; [Header("Combat — Attack")] [Tooltip("Damage dealt per hit to the primary target, before resistances.")] public float Damage; [Tooltip("Attack range in world units. Enemies within this radius are targetable. " + "Displayed as a translucent decal circle when the tower is selected.")] public float Range; [Tooltip("Attacks per second.")] public float FireRate; [Header("Combat — Area")] [Tooltip("Radius of splash damage around the primary impact point. " + "Only used when TargetType = Splash.")] public float SplashRadius; [Tooltip("Number of additional enemies damage chains to after the primary target. " + "Only used when TargetType = Chain.")] public int ChainCount; [Tooltip("Maximum world-unit distance each chain jump can travel. " + "Only used when TargetType = Chain.")] public float ChainRange; [Header("Combat — Effects")] [Tooltip("For Cold towers: fraction of movement speed retained on hit. " + "1.0 = no slow, 0.5 = half speed. Ignored for other damage types.")] [Range(0f, 1f)] public float SlowFactor = 1f; [Tooltip("For Fire / Poison towers: damage per second applied as a damage-over-time tick. " + "Ignored for other damage types.")] public float DotDamagePerSecond; [Tooltip("Duration in seconds that any lingering effect (slow, burn, poison) persists " + "after the hit. 0 = no lingering effect.")] public float EffectDuration; [Header("Combat — Projectile")] [Tooltip("Prefab fired at targets. Must have a Projectile component, NetworkObject, " + "and NetworkTransform at its root. Null = hitscan (instant hit, no travel).")] public GameObject ProjectilePrefab; [Tooltip("World-units per second the projectile travels. Ignored when ProjectilePrefab is null.")] public float ProjectileSpeed = 10f; // ------------------------------------------------------------------- // Upgrades // ------------------------------------------------------------------- [Header("Upgrades")] [Tooltip("Tower definitions this tower can upgrade into. Leave empty for no upgrades. " + "Multiple entries create branching paths — the player chooses one.")] public TowerDefinition[] UpgradePaths; } }