fertig-classic-games/data/totalannihilation-rules.json

277 lines
12 KiB
JSON

{
"_readme": [
"Engine data for Total Annihilation. Everything the simulation knows lives here — adding a unit,",
"building, weapon, terrain type, army or map theme is a JSON-only change.",
"After editing, run `node tools/verifyTotalAnnihilation.js` — it cross-checks every id reference,",
"frame index and closed key set in this file and will tell you exactly what broke.",
"",
"Sheet resolution: a unit/building's `sheetSlot` names a field on its ARMY (unitSheet or",
"structureSheet), so one unit definition renders correctly for every army. That is what makes a",
"third army a two-line change: add an `armies` entry pointing at two new sheets in",
"data/totalannihilation-artwork.json.",
"",
"Units are drawn once and ROTATED at runtime — there are no per-facing frames. `turretFrame` is",
"an optional second sprite that aims independently of the hull."
],
"version": 1,
"constants": {
"tickHz": 20,
"tileSize": 64,
"unitCapPerArmy": 100,
"projectileCap": 400,
"startEnergy": 1000,
"startMass": 1000,
"baseEnergyCap": 500,
"baseMassCap": 500,
"pathBudgetPerTick": 8,
"retargetPeriodTicks": 10,
"separationStiffness": 0.55,
"shoveAfterSec": 0.6,
"stuckGiveUpSec": 3.0,
"arriveSlackPx": 12,
"friendlyFire": false,
"buildPowerNominal": 100,
"eliminateWhenUnrecoverable": true
},
"sizeClasses": {
"small": { "radius": 16, "footprint": 1, "mass": 1 },
"medium": { "radius": 26, "footprint": 1, "mass": 4 },
"large": { "radius": 44, "footprint": 2, "mass": 16 }
},
"armorClasses": ["infantry", "light", "medium", "heavy", "structure"],
"moveClasses": {
"foot": {
"cost": { "ground": 1.0, "rough": 1.3, "road": 0.85, "metal": 1.0, "cliff": null, "water": null }
},
"tread": {
"cost": { "ground": 1.0, "rough": 1.8, "road": 0.7, "metal": 1.0, "cliff": null, "water": null }
},
"wheel": {
"cost": { "ground": 1.0, "rough": 2.4, "road": 0.6, "metal": 1.0, "cliff": null, "water": null }
}
},
"armies": [
{ "id": "arm", "name": "ARM", "color": "#4a90e2",
"unitSheet": "arm-units", "structureSheet": "arm-structures" },
{ "id": "core", "name": "CORE", "color": "#e05a2f",
"unitSheet": "core-units", "structureSheet": "core-structures" }
],
"commanders": [
{ "id": "vance", "armyId": "arm", "opponentId": "ethel", "name": "Commander Ethel",
"tagline": "Holds the line, and makes you pay for every metre of it.",
"aiProfile": { "aggression": 0.45, "expansion": 0.65 } },
{ "id": "klaxon", "armyId": "core", "opponentId": "klaxon", "name": "Unit KLAXON",
"tagline": "Efficiency is a weapon. You are an inefficiency.",
"aiProfile": { "aggression": 0.7, "expansion": 0.45 } },
{ "id": "cybro", "armyId": "core", "opponentId": "cybro", "name": "Cy-Bro",
"tagline": "Builds faster than you can knock it down.",
"aiProfile": { "aggression": 0.35, "expansion": 0.85 } },
{ "id": "nadia", "armyId": "arm", "opponentId": "nadia", "name": "Commander Nadia",
"tagline": "Hits the flank while you watch the front.",
"aiProfile": { "aggression": 0.8, "expansion": 0.4 } }
],
"terrain": [
{ "id": "ground", "ch": ".", "frame": 0, "buildable": true, "blocksMove": false, "elevation": 0 },
{ "id": "rough", "ch": "r", "frame": 3, "buildable": true, "blocksMove": false, "elevation": 0 },
{ "id": "road", "ch": "=", "frame": 8, "buildable": true, "blocksMove": false, "elevation": 0 },
{ "id": "metal", "ch": "M", "frame": 7, "buildable": true, "blocksMove": false, "elevation": 0,
"massMultiplier": 2.0 },
{ "id": "cliff", "ch": "^", "frame": 4, "buildable": false, "blocksMove": true, "blocksFire": true, "elevation": 1 },
{ "id": "water", "ch": "~", "frame": 5, "buildable": false, "blocksMove": true, "elevation": -1 }
],
"weapons": [
{ "id": "rifle", "name": "Assault Rifle", "kind": "hitscan",
"damage": 6, "reload": 0.5, "burst": 3, "burstDelay": 0.06,
"range": 200, "spread": 0.05, "targets": ["ground"],
"armorMul": { "infantry": 1.4, "light": 0.8, "medium": 0.35, "heavy": 0.15, "structure": 0.2 },
"fx": { "style": "tracer", "color": "#ffe6a0", "width": 1.5, "lifeMs": 70 },
"sound": "sfx-battle-gunfire-modern" },
{ "id": "sniperrifle", "name": "Marksman Rifle", "kind": "hitscan",
"damage": 55, "reload": 3.0, "burst": 1,
"range": 460, "spread": 0.0, "targets": ["ground"],
"armorMul": { "infantry": 2.2, "light": 0.9, "medium": 0.3, "heavy": 0.1, "structure": 0.1 },
"fx": { "style": "beam", "color": "#d8f0ff", "width": 2, "lifeMs": 160 },
"sound": "sfx-laser-zap" },
{ "id": "tankgun", "name": "120mm Cannon", "kind": "ballistic",
"damage": 90, "reload": 2.4, "burst": 1,
"range": 340, "speed": 700, "spread": 0.015, "leadTarget": true,
"aoe": 48, "aoeFalloff": 0.4, "targets": ["ground"],
"armorMul": { "infantry": 0.5, "light": 1.0, "medium": 1.0, "heavy": 0.8, "structure": 1.2 },
"fx": { "style": "shell", "color": "#ffd27a", "width": 3, "muzzle": 18 },
"sound": "sfx-battle-tank" },
{ "id": "rocketpod", "name": "Rocket Pod", "kind": "guided",
"damage": 130, "reload": 4.0, "burst": 2, "burstDelay": 0.25,
"range": 480, "minRange": 140, "speed": 340, "turnRate": 2.2,
"aoe": 80, "aoeFalloff": 0.35, "targets": ["ground"],
"armorMul": { "infantry": 0.6, "light": 1.1, "medium": 1.2, "heavy": 1.3, "structure": 1.4 },
"fx": { "style": "rocket", "color": "#ff8844", "width": 2, "trail": true },
"sound": "sfx-battle-missle" },
{ "id": "dgun", "name": "D-Gun", "kind": "beam",
"damage": 2000, "reload": 1.5, "burst": 1,
"range": 220, "energyPerShot": 500, "targets": ["ground"],
"armorMul": { "infantry": 1, "light": 1, "medium": 1, "heavy": 1, "structure": 1 },
"fx": { "style": "dgun", "color": "#8ad4ff", "width": 9, "lifeMs": 260 },
"sound": "sfx-scifi-launch" }
],
"units": [
{ "id": "commander", "name": "Commander", "role": "builder",
"size": "medium", "radius": 20,
"hp": 3000, "speed": 62, "turnRate": 3.5, "moveClass": "foot",
"armorClass": "heavy", "sight": 420,
"cost": { "energy": 0, "mass": 0 }, "buildTime": 0,
"buildPower": 100, "buildRange": 200,
"builds": ["energygen", "massgen", "barracks", "vehicleplant"],
"produce": { "energy": 25, "mass": 3.0 },
"storage": { "energy": 1000, "mass": 1000 },
"weapons": ["dgun"],
"deathExplosion": { "radius": 280, "damage": 1200 },
"sheetSlot": "unitSheet", "frame": 0, "turretFrame": 1,
"procShape": "commander", "icon": 0, "spritePx": 56 },
{ "id": "infantry", "name": "Infantry", "role": "combat",
"size": "small", "radius": 16,
"hp": 90, "speed": 55, "turnRate": 6.0, "moveClass": "foot",
"armorClass": "infantry", "sight": 260,
"cost": { "energy": 120, "mass": 24 }, "buildTime": 6,
"builtBy": ["barracks"],
"weapons": ["rifle"],
"sheetSlot": "unitSheet", "frame": 2,
"procShape": "infantry", "icon": 1, "spritePx": 30,
"moveSound": "sfx-march" },
{ "id": "sniper", "name": "Sniper", "role": "combat",
"size": "small", "radius": 16,
"hp": 70, "speed": 46, "turnRate": 5.0, "moveClass": "foot",
"armorClass": "infantry", "sight": 500,
"cost": { "energy": 260, "mass": 55 }, "buildTime": 12,
"builtBy": ["barracks"],
"weapons": ["sniperrifle"],
"sheetSlot": "unitSheet", "frame": 3,
"procShape": "sniper", "icon": 2, "spritePx": 30,
"moveSound": "sfx-march" },
{ "id": "jeep", "name": "Jeep", "role": "scout",
"size": "small", "radius": 20,
"hp": 180, "speed": 175, "turnRate": 3.4, "moveClass": "wheel",
"armorClass": "light", "sight": 520,
"cost": { "energy": 320, "mass": 70 }, "buildTime": 8,
"builtBy": ["vehicleplant"],
"weapons": ["rifle"],
"sheetSlot": "unitSheet", "frame": 4, "turretFrame": 5,
"procShape": "jeep", "icon": 3, "spritePx": 40,
"moveSound": "sfx-engine-medium" },
{ "id": "tank", "name": "Tank", "role": "combat",
"size": "medium", "radius": 26,
"hp": 520, "speed": 90, "turnRate": 2.2, "moveClass": "tread",
"armorClass": "medium", "sight": 300,
"cost": { "energy": 700, "mass": 180 }, "buildTime": 20,
"builtBy": ["vehicleplant"],
"weapons": ["tankgun"],
"sheetSlot": "unitSheet", "frame": 6, "turretFrame": 7,
"procShape": "tank", "icon": 4, "spritePx": 54,
"moveSound": "sfx-engine-heavy" },
{ "id": "rockettank", "name": "Rocket Tank", "role": "artillery",
"size": "medium", "radius": 28,
"hp": 400, "speed": 75, "turnRate": 1.8, "moveClass": "tread",
"armorClass": "medium", "sight": 320,
"cost": { "energy": 1100, "mass": 300 }, "buildTime": 28,
"builtBy": ["vehicleplant"],
"weapons": ["rocketpod"],
"sheetSlot": "unitSheet", "frame": 8, "turretFrame": 9,
"procShape": "rockettank", "icon": 5, "spritePx": 56,
"moveSound": "sfx-engine-heavy" }
],
"buildings": [
{ "id": "energygen", "name": "Energy Generator",
"footprint": { "w": 2, "h": 2 },
"hp": 800, "armorClass": "structure", "sight": 160,
"cost": { "energy": 200, "mass": 60 }, "buildTime": 12,
"produce": { "energy": 20 },
"storage": { "energy": 500 },
"deathExplosion": { "radius": 110, "damage": 160 },
"sheetSlot": "structureSheet", "frame": 0, "buildFrame": 1,
"procShape": "energyGen", "icon": 10 },
{ "id": "massgen", "name": "Mass Generator",
"footprint": { "w": 2, "h": 2 },
"hp": 700, "armorClass": "structure", "sight": 160,
"cost": { "energy": 600, "mass": 50 }, "buildTime": 16,
"produce": { "mass": 2.0 },
"upkeep": { "energy": 15 },
"storage": { "mass": 250 },
"terrainMultiplier": "massMultiplier",
"sheetSlot": "structureSheet", "frame": 2, "buildFrame": 3,
"procShape": "massGen", "icon": 11 },
{ "id": "barracks", "name": "Barracks",
"footprint": { "w": 3, "h": 3 },
"hp": 1400, "armorClass": "structure", "sight": 220,
"cost": { "energy": 600, "mass": 180 }, "buildTime": 26,
"buildPower": 100, "builds": ["infantry", "sniper"],
"spawnOffset": { "x": 0, "y": 2.2 },
"sheetSlot": "structureSheet", "frame": 4, "buildFrame": 5,
"procShape": "barracks", "icon": 12 },
{ "id": "vehicleplant", "name": "Vehicle Plant",
"footprint": { "w": 3, "h": 3 },
"hp": 2200, "armorClass": "structure", "sight": 220,
"cost": { "energy": 1400, "mass": 520 }, "buildTime": 40,
"buildPower": 100, "builds": ["jeep", "tank", "rockettank"],
"spawnOffset": { "x": 0, "y": 2.2 },
"sheetSlot": "structureSheet", "frame": 6, "buildFrame": 7,
"procShape": "vehiclePlant", "icon": 13 }
],
"commandIcons": {
"move": 20, "attack": 21, "attackMove": 22, "stop": 23,
"hold": 24, "patrol": 25, "guard": 26, "assist": 27
},
"aiSkills": [
{ "skill": 1, "decisionPeriodMs": 1500, "apmCap": 1, "squadSize": 3, "expansion": 0.6, "microLevel": 0, "reactionMs": 4000 },
{ "skill": 2, "decisionPeriodMs": 1100, "apmCap": 2, "squadSize": 4, "expansion": 1.0, "microLevel": 1, "reactionMs": 3000 },
{ "skill": 3, "decisionPeriodMs": 800, "apmCap": 4, "squadSize": 6, "expansion": 1.6, "microLevel": 2, "reactionMs": 2000 },
{ "skill": 4, "decisionPeriodMs": 500, "apmCap": 8, "squadSize": 8, "expansion": 2.2, "microLevel": 3, "reactionMs": 1000 },
{ "skill": 5, "decisionPeriodMs": 300, "apmCap": 15, "squadSize": 10, "expansion": 3.0, "microLevel": 4, "reactionMs": 300 }
],
"skirmish": {
"sizes": { "small": 64, "medium": 96, "large": 128 },
"symmetries": ["mirror-x", "mirror-y", "rotational"],
"themes": ["grasslands", "snowfields", "tropics"],
"defaults": {
"size": "medium", "symmetry": "mirror-x", "theme": "grasslands",
"aiSkill": 3, "playerArmy": "arm"
},
"startUnits": ["commander"],
"gen": {
"waterFraction": 0.10,
"roughFraction": 0.18,
"cliffFraction": 0.10,
"metalSpotsPerStart": 4,
"metalSpotRadiusTiles": 14,
"minStartSeparationTiles": 40,
"smoothPasses": 3,
"startClearRadiusTiles": 8,
"noiseScale": 0.09
}
}
}