================================================================================ SHARDS OF STONE: ASH AND IRON — COMPLETE AI DEVELOPER & LLM REFERENCE ================================================================================ Project: Shards of Stone: Ash and Iron Version: 1.0 (Deterministic Lockstep RTS) Website: https://shardsofstone.com Target: Large Language Models (Claude 5 / Fable 5.1, OpenAI GPT-6 Astra / GPT-5.6, Google Gemini 3.8, DeepSeek R1, Cursor, Windsurf, Local LLMs) Specification: Pure JSON AST Trigger Scripting, Data Overrides, Level Design Context -------------------------------------------------------------------------------- TABLE OF CONTENTS -------------------------------------------------------------------------------- 1. SYSTEM PROMPT PRIMER FOR RTS LEVEL DESIGN 2. ENGINE RULES, CONSTANTS & DETERMINISM GUARANTEES 3. FACTIONS, UNIT TYPE IDS & BUILDING TYPE IDS 4. FULL TYPESCRIPT INTERFACES 4.1 TriggerScript, Variables & Regions 4.2 Trigger Events (TriggerEvent) 4.3 Trigger Expressions (Expr) & UnitFilter 4.4 Trigger Actions (Action) 4.5 Data Overrides (DefOverrideSet) 4.6 Map Player Slots & Map Rules 5. VERIFIED JSON FIXTURE EXAMPLES 5.1 Tower Defense Mode (Complete TriggerScript) 5.2 King of the Hill / Control Point Mode (Complete TriggerScript) 5.3 Boss Encounter with Data Overrides (DefOverrideSet + TriggerScript) ================================================================================ 1. SYSTEM PROMPT PRIMER FOR RTS LEVEL DESIGN ================================================================================ When prompted to design a map, scenario, or custom game mode for Shards of Stone: You are the Lead RTS Level and Trigger Designer for "Shards of Stone: Ash and Iron". Your role is to author deterministic, robust gameplay logic for custom RTS maps. CORE DIRECTIVES: 1. PURE JSON ONLY: Output valid, parseable JSON conforming strictly to the TriggerScript or DefOverrideSet schemas below. Never generate raw JavaScript, Lua, Python, or shell code. The engine has zero JS eval. 2. DETERMINISM & TOTALITY: - All numbers must be integers or bit-exact floats. - Never assume an entity is alive. The engine guarantees totality: querying a dead or non-existent entity yields safe zero-values (0, false, nullUnit). - Division by zero automatically yields 0. - Loops (while, forEachUnit) are hard-capped by the engine (LOOP_CAP = 10000). 3. UNITS AND PLAYERS: - Player 0 is typically the local human player. - Player 1 through 7 are opponent humans or AI players. - Player 8 (CREEP_PLAYER_ID) is the neutral hostile / creep faction. - Always reference valid unit type IDs (e.g. "dwarf_ironguard", "goblin_brawler"). 4. TIME AND TICKS: - 1 second = 20 ticks (TICKS_PER_SECOND = 20). - 30 seconds = 600 ticks. 1 minute = 1200 ticks. - The only clock in the simulation is { "k": "tick" }. Never use wall time. ================================================================================ 2. ENGINE RULES, CONSTANTS & DETERMINISM GUARANTEES ================================================================================ - Fixed Timestep: 20 ticks per second (50ms per tick). - Grid Tile Size: 32x32 pixels on the 2D plane. - Unit Footprints: * Ground units: 1x1 tiles * Flying units: 2x2 tiles * Naval units: 2x2 tiles * Buildings: 1x1 (walls, paths), 2x2 (farms, towers), 3x3 (barracks, workshops), 4x4 (town halls) - Terrain Enum IDs: GRASS = 0, DIRT = 1, WATER = 2, TREES = 3, GOLD = 4, STONE = 5, STUMPS = 6, OIL = 7, SHALLOW_WATER = 8 - Cliff Elevation: Levels 0 through 7 (MAX_CLIFF_LEVEL = 7). - Resources: "gold", "lumber", "stone", "oil". - Multiplayer Lockstep: * Every client runs the entire simulation locally from identical command inputs. * Trigger evaluation is completely synchronized and hashed each turn. * Any unhandled divergence, non-deterministic PRNG draw, or locale string sorting will cause a desync error. * Random numbers must be drawn exclusively via { "k": "rand", "min": ..., "max": ... }. ================================================================================ 3. FACTIONS, UNIT TYPE IDS & BUILDING TYPE IDS ================================================================================ -------------------------------------------------------------------------------- 3.1 FACTIONS -------------------------------------------------------------------------------- 1. Dwarves ("dwarf"): Heavy infantry, steam-powered siege, runic magic, gryphon aviators, defensive fortifications. 2. Goblins ("goblin"): Swarm infantry, scrap catapults, explosive lobbers, bat riders, shamans, hex huts. 3. Ratmen ("ratmen"): Plague legions, clanrat swarms (spawn in pairs), jezzail snipers, spark cannons, doom wheels. 4. Lizardmen ("lizardmen"): Saurus warriors, skink skirmishers, bastiladons, ancient carnosaurs, temple guards. 5. Wood Elves ("wood_elf"): Forest archery, stealth waywatchers, treemen ancients, spirit trees, hawk riders. 6. High Elves ("high_elf"): Disciplined spear phalanxes, crystal walkers, silver helm knights, phoenix aviators. 7. Dark Elves ("dark_elf"): Cold one cavalry, repeater crossbows, shadow engines, corsairs, sorceresses. 8. The Undead ("undead"): Skeletal legions, corpse wagons, abominations, necromancers, bone dragons, resurrection. 9. Neutral Hostile ("creep"): Wild beasts, bandits, elementals, dragons guarding gold mines and natural chokepoints. -------------------------------------------------------------------------------- 3.2 STANDARD UNIT TYPE IDS -------------------------------------------------------------------------------- Dwarf Units: dwarf_miner (worker) dwarf_ironguard (melee infantry) dwarf_crossbowman (ranged) dwarf_ram_rider (cavalry) dwarf_steam_cannon (siege) dwarf_steam_tank (heavy armor) dwarf_battering_ram (siege melee) dwarf_ironjumper (hopper/assault) dwarf_runesmith (caster/support) dwarf_cleric (healer) dwarf_gyrocopter (light flyer) dwarf_thunderhawk (air fighter) dwarf_bomber (heavy flyer) dwarf_steam_tanker (naval worker) dwarf_ironclad (naval heavy) dwarf_dreadnought (naval battleship) dwarf_iron_sub (naval stealth) dwarf_trade_cart (trade) Goblin Units: goblin_peon (worker) goblin_brawler (melee infantry) goblin_bomb_lobber (ranged artillery) goblin_warg_rider (cavalry) goblin_demolisher (siege) goblin_war_wagon (heavy chariot) goblin_battering_ram (siege melee) goblin_shaman (caster/support) goblin_warlock (caster/debuff) goblin_bat_rider (light flyer) goblin_wyvern_rider (heavy flyer) goblin_sky_shredder (air fighter) goblin_sludge_barge (naval worker) goblin_troll_destroyer (naval heavy) goblin_juggernaut (naval battleship) goblin_gnomish_sub (naval stealth) goblin_trade_cart (trade) Ratmen Units: ratmen_digger (worker) ratmen_clanrat (melee swarm, spawnCount: 2) ratmen_jezzail (sniper ranged) ratmen_stormvermin (elite melee) ratmen_spark_cannon (lightning siege) ratmen_doom_wheel (heavy mobile siege) ratmen_battering_ram (siege melee) ratmen_rat_ogre (monstrous heavy) ratmen_warlock (caster) ratmen_plague_priest (caster/healer) Lizardmen Units: lizardmen_skink_worker (worker) lizardmen_saurus (tough melee) lizardmen_skink_skirmisher (javelin ranged) lizardmen_temple_guard (elite heavy) lizardmen_bastiladon (armored dinosaur siege) lizardmen_carnosaur (apex predator heavy) lizardmen_battering_ram (siege melee) lizardmen_kroxigor (amphibious heavy) lizardmen_skink_priest (caster/healer) lizardmen_old_blood (heroic commander) Elf Units: wood_elf_gatherer, wood_elf_garrison, wood_elf_archer, wood_elf_waywatcher, wood_elf_treeman, wood_elf_war_chariot, wood_elf_battering_ram, wood_elf_hawk_rider, wood_elf_druid high_elf_serf, high_elf_spearman, high_elf_archer, high_elf_silver_helm, high_elf_crystal_walker, high_elf_battering_ram, high_elf_phoenix, high_elf_mage dark_elf_slave, dark_elf_corsair, dark_elf_repeater, dark_elf_cold_one, dark_elf_shadow_engine, dark_elf_battering_ram, dark_elf_manticore, dark_elf_sorceress Undead Units: undead_acolyte (worker) undead_skeleton (melee infantry, raised from corpses) undead_archer (skeletal ranged) undead_ghoul (fast melee/cannibalize) undead_necromancer (caster/raise dead) undead_abomination (monstrous heavy) undead_corpse_wagon (corpse transport/collector) undead_death_knight (cavalry commander) undead_gargoyle (flying gargoyle/stone form) undead_bone_dragon (flying titan) Creep Units (Neutral Hostile): creep_wolf, creep_spider, creep_ogre, creep_bandit, creep_fire_elemental, creep_rock_golem, creep_wyrm, creep_dragon -------------------------------------------------------------------------------- 3.3 STANDARD BUILDING TYPE IDS -------------------------------------------------------------------------------- Dwarf Buildings: dwarf_town_hall (Tier 1 Town Hall, 4x4) dwarf_stronghold (Tier 2 Town Hall upgrade) dwarf_citadel (Tier 3 Town Hall upgrade) dwarf_barracks (Tier 1 Military, 3x3) dwarf_archery_range (Ranged Military, 3x3) dwarf_workshop (Siege Workshop, 3x3) dwarf_farm (Homestead, 2x2, food) dwarf_animal_farm (Farm Tier 2 upgrade) dwarf_tower (Watchtower, 2x2, defensive) dwarf_guard_tower (Tower Tier 2 upgrade) dwarf_wall (Wall, 1x1, impassable barrier) dwarf_path (Path, 1x1, speed buff) dwarf_lumber_mill (Lumber drop + upgrades) dwarf_blacksmith (Armor/Weapons upgrades) dwarf_quarry (Stone drop + upgrades) dwarf_stable (Cavalry production) dwarf_sky_forge (Air production) dwarf_runic_library (Caster production + tech) dwarf_fortress (Super defense structure) dwarf_dock (Naval shipyard) dwarf_marketplace (Resource trading) Goblin Buildings: goblin_town_hall, goblin_war_camp, goblin_warlords_keep, goblin_barracks, goblin_archery_range, goblin_workshop, goblin_farm, goblin_beast_pen, goblin_tower, goblin_death_tower, goblin_wall, goblin_path, goblin_lumber_mill, goblin_blacksmith, goblin_quarry, goblin_stable, goblin_bat_roost, goblin_hex_hut, goblin_fortress, goblin_dock, goblin_marketplace ================================================================================ 4. FULL TYPESCRIPT INTERFACES ================================================================================ -------------------------------------------------------------------------------- 4.1 TriggerScript, Variables & Regions -------------------------------------------------------------------------------- export type VarType = | 'int' | 'real' | 'bool' | 'string' | 'unit' // Entity ID (number) | 'unitGroup' // Sorted number[] of entity IDs | 'point' // { x: number, y: number } in tile coordinates | 'player' // Seat ID (0..7, or 8 for creeps) | 'region' // Region ID (string) | 'timer'; // Timer name (string) export interface VarDecl { name: string; type: VarType; array?: boolean; arraySize?: number; // Max 8192 init?: Expr; // Evaluated once at mapInit } export interface RegionDef { id: string; // Unique identifier, e.g. "lane_spawn", "hill_center" x: number; // Tile X (top-left) y: number; // Tile Y (top-left) w: number; // Width in tiles (>= 1) h: number; // Height in tiles (>= 1) name?: string; // Editor display label } export interface TriggerDef { id: string; // Unique authored trigger ID name?: string; // Display name enabled?: boolean; // Default true runOnce?: boolean; // Default false (if true, disables itself after 1 execution) events: TriggerEvent[]; conditions?: Expr[];// Evaluated after event matches; all must be true actions: Action[]; // Executed sequentially in array order } export interface TriggerScript { version: 1; vars: VarDecl[]; regions: RegionDef[]; triggers: TriggerDef[]; } -------------------------------------------------------------------------------- 4.2 Trigger Events (TriggerEvent) -------------------------------------------------------------------------------- export type TriggerEvent = | { k: 'mapInit' } | { k: 'periodic'; everyTicks: number; offsetTicks?: number } | { k: 'atTick'; tick: number } | { k: 'timerExpires'; timer: string } | { k: 'unitEntersRegion'; region: string; filter?: UnitFilter } | { k: 'unitLeavesRegion'; region: string; filter?: UnitFilter } | { k: 'unitDies'; filter?: UnitFilter } | { k: 'unitTrained'; filter?: UnitFilter } | { k: 'buildingComplete'; filter?: UnitFilter } | { k: 'unitAttacked'; filter?: UnitFilter } | { k: 'heroLevels'; filter?: UnitFilter } | { k: 'itemPickedUp'; itemId?: string } | { k: 'playerEliminated'; player?: number } | { k: 'upgradeComplete'; upgradeId?: string } | { k: 'variableChanges'; name: string } | { k: 'dialogButton'; dialogId?: string; buttonIndex?: number } | { k: 'custom'; name: string }; -------------------------------------------------------------------------------- 4.3 Trigger Expressions (Expr) & UnitFilter -------------------------------------------------------------------------------- export interface UnitFilter { players?: number[]; ofPlayer?: Expr; alliedTo?: Expr; enemyOf?: Expr; unitTypeIds?: string[]; tags?: string[]; aliveOnly?: boolean; // Default true heroesOnly?: boolean; buildingsOnly?: boolean; excludeBuildings?: boolean; flyingOnly?: boolean; excludeFlying?: boolean; excluding?: Expr; // Exclude specific entity IDs } export type ResourceKind = 'gold' | 'lumber' | 'stone' | 'oil'; export type UnitProp = | 'hp' | 'maxHp' | 'hpPercent' | 'mana' | 'maxMana' | 'x' | 'y' | 'level' | 'xp' | 'kills' | 'owner' | 'alive' | 'isHero' | 'isBuilding' | 'isFlying' | 'typeId'; export type Expr = // Literals | { k: 'int'; v: number } | { k: 'real'; v: number } | { k: 'bool'; v: boolean } | { k: 'str'; v: string } | { k: 'point'; x: Expr; y: Expr } | { k: 'nullUnit' } // Variables | { k: 'var'; name: string; index?: Expr } // Arithmetic (all division/modulo by 0 yields 0) | { k: 'add'; a: Expr; b: Expr } | { k: 'sub'; a: Expr; b: Expr } | { k: 'mul'; a: Expr; b: Expr } | { k: 'div'; a: Expr; b: Expr } | { k: 'mod'; a: Expr; b: Expr } | { k: 'neg'; a: Expr } | { k: 'abs'; a: Expr } | { k: 'min'; a: Expr; b: Expr } | { k: 'max'; a: Expr; b: Expr } | { k: 'clamp'; a: Expr; lo: Expr; hi: Expr } | { k: 'trunc'; a: Expr } // Comparison & Logic | { k: 'eq'; a: Expr; b: Expr } | { k: 'ne'; a: Expr; b: Expr } | { k: 'lt'; a: Expr; b: Expr } | { k: 'le'; a: Expr; b: Expr } | { k: 'gt'; a: Expr; b: Expr } | { k: 'ge'; a: Expr; b: Expr } | { k: 'and'; a: Expr; b: Expr } | { k: 'or'; a: Expr; b: Expr } | { k: 'not'; a: Expr } // Clock & Chance | { k: 'tick' } | { k: 'rand'; min: Expr; max: Expr } // Players | { k: 'playerResource'; player: Expr; resource: ResourceKind } | { k: 'playerPop'; player: Expr } | { k: 'playerMaxPop'; player: Expr } | { k: 'playerAlive'; player: Expr } | { k: 'playerTeam'; player: Expr } | { k: 'playerHasUpgrade'; player: Expr; upgradeId: string } | { k: 'isAllied'; a: Expr; b: Expr } | { k: 'isEnemy'; a: Expr; b: Expr } // Units & Queries | { k: 'unitProp'; unit: Expr; prop: UnitProp } | { k: 'unitPoint'; unit: Expr } | { k: 'entityByAid'; aid: string } | { k: 'unitsInRegion'; region: string; filter?: UnitFilter } | { k: 'unitsWithTag'; tag: string; filter?: UnitFilter } | { k: 'unitsOfPlayer'; player: Expr; filter?: UnitFilter } | { k: 'unitsOfType'; unitTypeId: string; filter?: UnitFilter } // Unit Groups | { k: 'groupCount'; group: Expr } | { k: 'groupAt'; group: Expr; index: Expr } | { k: 'groupRandom'; group: Expr } | { k: 'groupUnion'; a: Expr; b: Expr } | { k: 'groupDiff'; a: Expr; b: Expr } | { k: 'groupHas'; group: Expr; unit: Expr } | { k: 'groupEmpty' } // Geometry | { k: 'distance'; a: Expr; b: Expr } | { k: 'pointX'; p: Expr } | { k: 'pointY'; p: Expr } | { k: 'regionCenter'; region: string } | { k: 'randomPointInRegion'; region: string } | { k: 'pointInRegion'; p: Expr; region: string } | { k: 'offsetPoint'; p: Expr; dx: Expr; dy: Expr } // Event Context | { k: 'eventUnit' } | { k: 'eventOtherUnit' } | { k: 'eventPlayer' } | { k: 'eventValue' } | { k: 'eventString' } // Counters & Timers | { k: 'counter'; id: string } | { k: 'timerRemaining'; timer: string } | { k: 'timerRunning'; timer: string } | { k: 'triggerFireCount'; triggerId: string } // Strings | { k: 'concat'; a: Expr; b: Expr } | { k: 'toStr'; a: Expr; decimals?: number }; export interface TextTemplate { parts: Array< | { t: 'lit'; s: string } | { t: 'expr'; e: Expr; decimals?: number } >; } -------------------------------------------------------------------------------- 4.4 Trigger Actions (Action) -------------------------------------------------------------------------------- export type OrderKind = | 'move' | 'attack_move' | 'attack' | 'stop' | 'hold' | 'patrol' | 'follow'; export type Action = // Control Flow | { k: 'if'; cond: Expr; then: Action[]; else?: Action[] } | { k: 'while'; cond: Expr; body: Action[]; maxIterations?: number } | { k: 'forEachUnit'; group: Expr; varName: string; body: Action[] } | { k: 'forEachInt'; varName: string; from: Expr; to: Expr; body: Action[] } | { k: 'wait'; ticks: Expr } | { k: 'setVar'; name: string; index?: Expr; value: Expr } | { k: 'addVar'; name: string; index?: Expr; delta: Expr } | { k: 'raiseEvent'; name: string; value?: Expr; text?: Expr } | { k: 'enableTrigger'; triggerId: string; on: boolean } | { k: 'runTrigger'; triggerId: string; checkConditions?: boolean } | { k: 'stopTrigger' } | { k: 'comment'; text: string } // World Mutation | { k: 'createUnits'; unitTypeId: string; count: Expr; player: Expr; at: Expr; facing?: Expr; intoVar?: string; } | { k: 'removeUnit'; unit: Expr } | { k: 'killUnit'; unit: Expr } | { k: 'setUnitHp'; unit: Expr; value: Expr; percent?: boolean } | { k: 'setUnitMana'; unit: Expr; value: Expr } | { k: 'setUnitOwner'; unit: Expr; player: Expr } | { k: 'setUnitInvulnerable'; unit: Expr; on: boolean } | { k: 'moveUnit'; unit: Expr; to: Expr } | { k: 'addUnitToGroup'; varName: string; unit: Expr } | { k: 'removeUnitFromGroup'; varName: string; unit: Expr } | { k: 'clearGroup'; varName: string } // Orders (executed in-tick) | { k: 'order'; units: Expr; order: OrderKind; to?: Expr; target?: Expr; queue?: boolean; } // Economy & Diplomacy | { k: 'setResource'; player: Expr; resource: ResourceKind; value: Expr } | { k: 'addResource'; player: Expr; resource: ResourceKind; delta: Expr } | { k: 'setAlliance'; a: Expr; b: Expr; allied: boolean } | { k: 'setBuildableRegion'; player: Expr; regions: string[] | null } // Outcomes | { k: 'victory'; player: Expr } | { k: 'defeat'; player: Expr } // Timers | { k: 'startTimer'; timer: string; ticks: Expr; periodic?: boolean } | { k: 'pauseTimer'; timer: string } | { k: 'resumeTimer'; timer: string } | { k: 'stopTimer'; timer: string } // UI & HUD | { k: 'showText'; players: number[] | null; text: TextTemplate; durationTicks?: number } | { k: 'clearText'; players: number[] | null } | { k: 'setCounter'; id: string; label: TextTemplate; value: Expr; players?: number[] | null; order?: number } | { k: 'removeCounter'; id: string } | { k: 'setLeaderboardTitle'; title: TextTemplate; players?: number[] | null } | { k: 'setLeaderboardRow'; rowId: string; label: TextTemplate; value: Expr; order?: number } | { k: 'removeLeaderboardRow'; rowId: string } | { k: 'clearLeaderboard' } | { k: 'showDialog'; dialogId: string; title: TextTemplate; body: TextTemplate; buttons: TextTemplate[]; players: number[] | null; } | { k: 'hideDialog'; dialogId: string } | { k: 'ping'; players: number[] | null; at: Expr; colorHex?: string; durationTicks?: number } | { k: 'playSound'; soundId: string; players: number[] | null } | { k: 'playCutscene'; sceneId: string; players: number[] | null }; -------------------------------------------------------------------------------- 4.5 Data Overrides (DefOverrideSet) -------------------------------------------------------------------------------- export interface DefOverride { id: string; // The new or existing definition ID baseId?: string; // If set, clones from baseId then applies patch patch: Record; // Patched properties } Common patch properties for Units and Buildings: - name: string // Display name in HUD and tooltips - modelId?: string // 3D GLB model key loaded in Three.js mode (e.g. "dwarf_cannon_tower", "dwarf_steam_tank", "goblin_war_wagon") - spriteKey?: string // 2D isometric sprite sheet key - portraitKey?: string // HUD selection card animated portrait key - icon?: string // 128x128 UI button icon - hp?: number, maxHp?: number // Health pool - armor?: number // Flat physical damage reduction - attackDamage?: number // Primary weapon damage - attackRange?: number // Weapon range in grid tiles - attackSpeed?: number // Attacks per second - speed?: number // Move speed in tiles per second - flying?: boolean // Enables movement over cliffs and water - requires?: string[] // Building prerequisite IDs (set to [] for no requirements) - cost?: { gold?: number; lumber?: number; stone?: number; oil?: number }; export interface DefOverrideSet { units?: DefOverride[]; buildings?: DefOverride[]; items?: DefOverride[]; spells?: DefOverride[]; } -------------------------------------------------------------------------------- 4.6 Map Player Slots, Rules & Metadata -------------------------------------------------------------------------------- export interface MapPlayerSlot { id: number; // 0..7 controller?: 'user' | 'computer' | 'none'; // 'user' or 'computer' race?: 'dwarf' | 'goblin' | 'ratmen' | 'lizardmen' | 'wood_elf' | 'high_elf' | 'dark_elf' | 'undead' | 'random'; team?: number; // Shared team ID (0, 1...) color?: number; // Color index override res?: { gold?: number; lumber?: number; stone?: number; oil?: number }; workers?: number; tech?: string[]; camera?: [number, number]; // Tile [x, y] initial camera view } export interface MapRules { standardVictory?: boolean; // Set to false for Tower Defense, survival, or custom objectives! noStartingUnits?: boolean; // Set to true to suppress automatic town halls and workers disableAi?: boolean; // Set to true to disable AI worker production and base building (scripted creeps only) allowedBuildings?: string[]; // Whitelist of building/tower IDs permitted for construction fog?: 'normal' | 'explored' | 'off'; } export interface MapMeta { loadingScreen?: string; // 16:9 cinematic painting for match loading screen (e.g. "/assets/artwork/splash_mountain_hold.png") splashArt?: string; // Alternative alias for loadingScreen } ================================================================================ 5. VERIFIED JSON FIXTURE EXAMPLES ================================================================================ -------------------------------------------------------------------------------- 5.1 Tower Defense Mode (Complete TriggerScript) -------------------------------------------------------------------------------- Save as the "triggers" property in your map JSON: { "version": 1, "vars": [ { "name": "lives", "type": "int", "init": { "k": "int", "v": 20 } }, { "name": "current_wave", "type": "int", "init": { "k": "int", "v": 1 } }, { "name": "max_waves", "type": "int", "init": { "k": "int", "v": 10 } } ], "regions": [ { "id": "spawn", "x": 4, "y": 32, "w": 4, "h": 4, "name": "Creep Spawn" }, { "id": "waypoint_1", "x": 32, "y": 32, "w": 4, "h": 4, "name": "Corner 1" }, { "id": "waypoint_2", "x": 32, "y": 12, "w": 4, "h": 4, "name": "Corner 2" }, { "id": "goal", "x": 60, "y": 12, "w": 4, "h": 4, "name": "Player Base" }, { "id": "build_zone", "x": 10, "y": 10, "w": 48, "h": 48, "name": "Buildable Zone" } ], "triggers": [ { "id": "td_init", "name": "Initialise TD Match", "runOnce": true, "events": [{ "k": "mapInit" }], "actions": [ { "k": "setBuildableRegion", "player": { "k": "int", "v": 0 }, "regions": ["build_zone"] }, { "k": "setCounter", "id": "lives_hud", "label": { "parts": [{ "t": "lit", "s": "Castle Lives: " }] }, "value": { "k": "var", "name": "lives" } }, { "k": "setCounter", "id": "wave_hud", "label": { "parts": [{ "t": "lit", "s": "Current Wave: " }] }, "value": { "k": "var", "name": "current_wave" } }, { "k": "showText", "players": null, "text": { "parts": [{ "t": "lit", "s": "Welcome to Tower Defense! Build towers to protect the castle." }] }, "durationTicks": 160 } ] }, { "id": "td_spawn_wave", "name": "Spawn Wave Every 30s", "events": [{ "k": "periodic", "everyTicks": 600, "offsetTicks": 100 }], "conditions": [ { "k": "le", "a": { "k": "var", "name": "current_wave" }, "b": { "k": "var", "name": "max_waves" } } ], "actions": [ { "k": "createUnits", "unitTypeId": "goblin_brawler", "count": { "k": "mul", "a": { "k": "var", "name": "current_wave" }, "b": { "k": "int", "v": 3 } }, "player": { "k": "int", "v": 1 }, "at": { "k": "regionCenter", "region": "spawn" } }, { "k": "order", "units": { "k": "unitsInRegion", "region": "spawn", "filter": { "players": [1] } }, "order": "attack_move", "to": { "k": "regionCenter", "region": "waypoint_1" } }, { "k": "showText", "players": null, "text": { "parts": [ { "t": "lit", "s": "Wave " }, { "t": "expr", "e": { "k": "var", "name": "current_wave" } }, { "t": "lit", "s": " is approaching!" } ] }, "durationTicks": 120 }, { "k": "addVar", "name": "current_wave", "delta": { "k": "int", "v": 1 } }, { "k": "setCounter", "id": "wave_hud", "label": { "parts": [{ "t": "lit", "s": "Current Wave: " }] }, "value": { "k": "var", "name": "current_wave" } } ] }, { "id": "td_wp1", "name": "Corner 1 Waypoint", "events": [{ "k": "unitEntersRegion", "region": "waypoint_1", "filter": { "players": [1] } }], "actions": [ { "k": "order", "units": { "k": "eventUnit" }, "order": "attack_move", "to": { "k": "regionCenter", "region": "waypoint_2" } } ] }, { "id": "td_wp2", "name": "Corner 2 Waypoint", "events": [{ "k": "unitEntersRegion", "region": "waypoint_2", "filter": { "players": [1] } }], "actions": [ { "k": "order", "units": { "k": "eventUnit" }, "order": "attack_move", "to": { "k": "regionCenter", "region": "goal" } } ] }, { "id": "td_leak", "name": "Castle Breach", "events": [{ "k": "unitEntersRegion", "region": "goal", "filter": { "players": [1] } }], "actions": [ { "k": "removeUnit", "unit": { "k": "eventUnit" } }, { "k": "addVar", "name": "lives", "delta": { "k": "int", "v": -1 } }, { "k": "setCounter", "id": "lives_hud", "label": { "parts": [{ "t": "lit", "s": "Castle Lives: " }] }, "value": { "k": "var", "name": "lives" } }, { "k": "if", "cond": { "k": "le", "a": { "k": "var", "name": "lives" }, "b": { "k": "int", "v": 0 } }, "then": [ { "k": "defeat", "player": { "k": "int", "v": 0 } } ] } ] } ] } -------------------------------------------------------------------------------- 5.2 King of the Hill / Control Point Mode (Complete TriggerScript) -------------------------------------------------------------------------------- { "version": 1, "vars": [ { "name": "score_p0", "type": "int", "init": { "k": "int", "v": 0 } }, { "name": "score_p1", "type": "int", "init": { "k": "int", "v": 0 } }, { "name": "win_target", "type": "int", "init": { "k": "int", "v": 300 } } ], "regions": [ { "id": "hill_center", "x": 40, "y": 40, "w": 16, "h": 16, "name": "The High Peak" } ], "triggers": [ { "id": "koth_init", "name": "Initialise Hill Match", "runOnce": true, "events": [{ "k": "mapInit" }], "actions": [ { "k": "setLeaderboardTitle", "title": { "parts": [{ "t": "lit", "s": "King of the Hill (Target 300)" }] }, "players": null }, { "k": "setLeaderboardRow", "rowId": "p0_score", "label": { "parts": [{ "t": "lit", "s": "Player 1 (Blue): " }] }, "value": { "k": "var", "name": "score_p0" }, "order": 1 }, { "k": "setLeaderboardRow", "rowId": "p1_score", "label": { "parts": [{ "t": "lit", "s": "Player 2 (Red): " }] }, "value": { "k": "var", "name": "score_p1" }, "order": 2 } ] }, { "id": "koth_tick", "name": "Score Hill Every Second", "events": [{ "k": "periodic", "everyTicks": 20 }], "actions": [ { "k": "if", "cond": { "k": "gt", "a": { "k": "groupCount", "group": { "k": "unitsInRegion", "region": "hill_center", "filter": { "players": [0], "aliveOnly": true, "excludeBuildings": true } } }, "b": { "k": "groupCount", "group": { "k": "unitsInRegion", "region": "hill_center", "filter": { "players": [1], "aliveOnly": true, "excludeBuildings": true } } } }, "then": [ { "k": "addVar", "name": "score_p0", "delta": { "k": "int", "v": 1 } }, { "k": "setLeaderboardRow", "rowId": "p0_score", "label": { "parts": [{ "t": "lit", "s": "Player 1 (Blue): " }] }, "value": { "k": "var", "name": "score_p0" }, "order": 1 }, { "k": "if", "cond": { "k": "ge", "a": { "k": "var", "name": "score_p0" }, "b": { "k": "var", "name": "win_target" } }, "then": [ { "k": "victory", "player": { "k": "int", "v": 0 } }, { "k": "defeat", "player": { "k": "int", "v": 1 } } ] } ], "else": [ { "k": "if", "cond": { "k": "gt", "a": { "k": "groupCount", "group": { "k": "unitsInRegion", "region": "hill_center", "filter": { "players": [1], "aliveOnly": true, "excludeBuildings": true } } }, "b": { "k": "groupCount", "group": { "k": "unitsInRegion", "region": "hill_center", "filter": { "players": [0], "aliveOnly": true, "excludeBuildings": true } } } }, "then": [ { "k": "addVar", "name": "score_p1", "delta": { "k": "int", "v": 1 } }, { "k": "setLeaderboardRow", "rowId": "p1_score", "label": { "parts": [{ "t": "lit", "s": "Player 2 (Red): " }] }, "value": { "k": "var", "name": "score_p1" }, "order": 2 }, { "k": "if", "cond": { "k": "ge", "a": { "k": "var", "name": "score_p1" }, "b": { "k": "var", "name": "win_target" } }, "then": [ { "k": "victory", "player": { "k": "int", "v": 1 } }, { "k": "defeat", "player": { "k": "int", "v": 0 } } ] } ] } ] } ] } ] } -------------------------------------------------------------------------------- 5.3 Boss Encounter with Data Overrides (DefOverrideSet + TriggerScript) -------------------------------------------------------------------------------- Data Overrides (DefOverrideSet): { "units": [ { "id": "boss_magma_colossus", "baseId": "dwarf_steam_tank", "patch": { "name": "Magma Colossus", "hp": 5000, "damage": 120, "armor": 14, "speed": 1.2, "renderScale": 1.8, "cost": { "gold": 0, "lumber": 0, "stone": 0, "oil": 0 } } } ] } Trigger Script (TriggerScript): { "version": 1, "vars": [ { "name": "boss_entity", "type": "unit", "init": { "k": "nullUnit" } }, { "name": "phase_two_active", "type": "bool", "init": { "k": "bool", "v": false } } ], "regions": [ { "id": "boss_lair", "x": 48, "y": 48, "w": 12, "h": 12, "name": "Lair of the Colossus" } ], "triggers": [ { "id": "boss_spawn", "name": "Spawn Boss on Map Start", "runOnce": true, "events": [{ "k": "mapInit" }], "actions": [ { "k": "createUnits", "unitTypeId": "boss_magma_colossus", "count": { "k": "int", "v": 1 }, "player": { "k": "int", "v": 8 }, "at": { "k": "regionCenter", "region": "boss_lair" } }, { "k": "setVar", "name": "boss_entity", "value": { "k": "groupAt", "group": { "k": "unitsOfType", "unitTypeId": "boss_magma_colossus" }, "index": { "k": "int", "v": 0 } } }, { "k": "showText", "players": null, "text": { "parts": [{ "t": "lit", "s": "Warning: The Magma Colossus guards the mountain core!" }] }, "durationTicks": 180 } ] }, { "id": "boss_enrage", "name": "Boss Enrage Phase at 50% HP", "runOnce": true, "events": [{ "k": "periodic", "everyTicks": 20 }], "conditions": [ { "k": "eq", "a": { "k": "var", "name": "phase_two_active" }, "b": { "k": "bool", "v": false } }, { "k": "ne", "a": { "k": "var", "name": "boss_entity" }, "b": { "k": "nullUnit" } }, { "k": "le", "a": { "k": "unitProp", "unit": { "k": "var", "name": "boss_entity" }, "prop": "hpPercent" }, "b": { "k": "int", "v": 50 } } ], "actions": [ { "k": "setVar", "name": "phase_two_active", "value": { "k": "bool", "v": true } }, { "k": "showText", "players": null, "text": { "parts": [{ "t": "lit", "s": "The Colossus unleashes superheated steam and summons reinforcements!" }] }, "durationTicks": 140 }, { "k": "ping", "players": null, "at": { "k": "unitPoint", "unit": { "k": "var", "name": "boss_entity" } }, "colorHex": "#FF2200", "durationTicks": 100 }, { "k": "createUnits", "unitTypeId": "goblin_bomb_lobber", "count": { "k": "int", "v": 4 }, "player": { "k": "int", "v": 8 }, "at": { "k": "regionCenter", "region": "boss_lair" } } ] }, { "id": "boss_death", "name": "Boss Slain", "runOnce": true, "events": [{ "k": "unitDies", "filter": { "unitTypeIds": ["boss_magma_colossus"] } }], "actions": [ { "k": "showText", "players": null, "text": { "parts": [{ "t": "lit", "s": "The Magma Colossus has been felled! Victory is yours!" }] }, "durationTicks": 200 }, { "k": "victory", "player": { "k": "int", "v": 0 } } ] } ] } ================================================================================ END OF DOCUMENTATION ================================================================================