feat: introduce dedicated armor classes for air and fortifications

Add `air` and `fortification` armor classes to enable more nuanced
balance. Aircraft now use `air` class instead of light/medium, and
defensive turrets use `fortification` instead of `structure`, allowing
weapons to specialize against planes and defenses without affecting
other targets.

- Add armor classes to all 12 weapons with appropriate multipliers
- Adjust weapon stats (sniperrifle, rocketpod, shoulderrocket)
- Reduce HP on several combat units for balance
- Reclassify aircraft and defensive turrets to new armor classes
This commit is contained in:
Brian Fertig 2026-08-01 14:02:22 -06:00
parent ac063d34a6
commit 71e455650b
1 changed files with 76 additions and 42 deletions

View File

@ -20,7 +20,15 @@
"aircraft is an ordinary ground target that anything can shoot, and it cannot fire back.",
"`domain` and the unit's `moveClass` have to agree: an air unit takes a move class flagged",
"`\"air\": true`. Terrain passability comes from the move class COST TABLE, not from the terrain's",
"own `blocksMove` \u2014 that is how `hover` crosses water without a per-terrain exception."
"own `blocksMove` \u2014 that is how `hover` crosses water without a per-terrain exception.",
"",
"Armor classes are the whole balance surface: every weapon lists a multiplier for EVERY class,",
"so a roster change is a table edit rather than a code change. Two of them exist purely so a",
"counter can be expressed at all \u2014 `air` (aircraft, separate from light/medium so a weapon can",
"be lethal to planes without also being lethal to jeeps and tanks) and `fortification` (Laser",
"Tower and Missile Launcher, separate from `structure` so a weapon can specialise in cracking",
"defences without flattening generators). Adding a class means adding a key to all 12 weapons;",
"compileRules refuses to start if one is missing, which is the point."
],
"version": 1,
"constants": {
@ -80,7 +88,9 @@
"light",
"medium",
"heavy",
"structure"
"structure",
"fortification",
"air"
],
"moveClasses": {
"foot": {
@ -264,11 +274,13 @@
"ground"
],
"armorMul": {
"infantry": 1.3,
"light": 0.85,
"medium": 0.3,
"heavy": 0.12,
"structure": 0.2
"infantry": 1.0,
"light": 0.5,
"medium": 0.25,
"heavy": 0.15,
"structure": 0.7,
"fortification": 0.55,
"air": 0.3
},
"fx": {
"style": "tracer",
@ -292,11 +304,13 @@
"ground"
],
"armorMul": {
"infantry": 1.3,
"light": 0.85,
"infantry": 2.2,
"light": 0.7,
"medium": 0.3,
"heavy": 0.12,
"structure": 0.2
"heavy": 0.15,
"structure": 0.5,
"fortification": 0.4,
"air": 0.35
},
"fx": {
"style": "tracer",
@ -310,20 +324,22 @@
"id": "sniperrifle",
"name": "Marksman Rifle",
"kind": "hitscan",
"damage": 55,
"reload": 2.0,
"damage": 70,
"reload": 2.2,
"burst": 1,
"range": 460,
"range": 580,
"spread": 0.0,
"targets": [
"ground"
],
"armorMul": {
"infantry": 2.2,
"light": 0.9,
"medium": 0.3,
"heavy": 0.1,
"structure": 0.1
"infantry": 3.2,
"light": 0.35,
"medium": 0.12,
"heavy": 0.08,
"structure": 0.08,
"fortification": 0.08,
"air": 0.15
},
"fx": {
"style": "beam",
@ -354,7 +370,9 @@
"light": 1.15,
"medium": 1.0,
"heavy": 0.8,
"structure": 1.2
"structure": 1.2,
"fortification": 1.1,
"air": 1.0
},
"fx": {
"style": "shell",
@ -368,7 +386,7 @@
"id": "rocketpod",
"name": "Rocket Pod",
"kind": "guided",
"damage": 40,
"damage": 48,
"reload": 4.0,
"burst": 2,
"burstDelay": 0.25,
@ -387,7 +405,9 @@
"light": 0.6,
"medium": 1.0,
"heavy": 1.4,
"structure": 1.5
"structure": 1.5,
"fortification": 1.6,
"air": 2.6
},
"fx": {
"style": "rocket",
@ -402,10 +422,10 @@
"id": "shoulderrocket",
"name": "Shoulder Rocket",
"kind": "guided",
"damage": 32,
"damage": 40,
"reload": 2.2,
"burst": 1,
"range": 320,
"range": 380,
"minRange": 60,
"speed": 260,
"turnRate": 2.0,
@ -416,11 +436,13 @@
"air"
],
"armorMul": {
"infantry": 0.35,
"light": 0.8,
"medium": 1.1,
"heavy": 1.3,
"structure": 1.0
"infantry": 0.3,
"light": 0.9,
"medium": 1.3,
"heavy": 1.2,
"structure": 1.2,
"fortification": 1.9,
"air": 2.8
},
"fx": {
"style": "rocket",
@ -448,7 +470,9 @@
"light": 1.0,
"medium": 0.8,
"heavy": 0.6,
"structure": 0.5
"structure": 0.5,
"fortification": 0.45,
"air": 0.8
},
"fx": {
"style": "beam",
@ -476,7 +500,9 @@
"light": 1,
"medium": 1,
"heavy": 1,
"structure": 1
"structure": 1,
"fortification": 1,
"air": 1
},
"fx": {
"style": "dgun",
@ -503,7 +529,9 @@
"light": 1.2,
"medium": 0.9,
"heavy": 0.55,
"structure": 0.4
"structure": 0.4,
"fortification": 0.35,
"air": 1.0
},
"fx": {
"style": "beam",
@ -535,7 +563,9 @@
"light": 0.7,
"medium": 1.1,
"heavy": 1.5,
"structure": 1.3
"structure": 1.3,
"fortification": 1.2,
"air": 2.8
},
"fx": {
"style": "rocket",
@ -561,7 +591,9 @@
"light": 1.0,
"medium": 0.85,
"heavy": 0.6,
"structure": 0.2
"structure": 0.2,
"fortification": 0.2,
"air": 1.0
},
"fx": {
"style": "tracer",
@ -591,7 +623,9 @@
"light": 1.0,
"medium": 1.0,
"heavy": 0.85,
"structure": 1.6
"structure": 1.6,
"fortification": 1.5,
"air": 1.0
},
"fx": {
"style": "shell",
@ -696,7 +730,7 @@
"role": "combat",
"size": "small",
"radius": 16,
"hp": 200,
"hp": 130,
"speed": 46,
"turnRate": 5.0,
"moveClass": "foot",
@ -726,7 +760,7 @@
"role": "combat",
"size": "small",
"radius": 16,
"hp": 240,
"hp": 150,
"speed": 50,
"turnRate": 5.5,
"moveClass": "foot",
@ -818,7 +852,7 @@
"role": "artillery",
"size": "medium",
"radius": 28,
"hp": 1250,
"hp": 1050,
"speed": 75,
"turnRate": 1.8,
"moveClass": "tread",
@ -893,7 +927,7 @@
"speed": 290,
"turnRate": 3.0,
"moveClass": "air",
"armorClass": "light",
"armorClass": "air",
"sight": 620,
"cost": {
"energy": 900,
@ -932,7 +966,7 @@
"speed": 215,
"turnRate": 1.7,
"moveClass": "air",
"armorClass": "medium",
"armorClass": "air",
"sight": 560,
"cost": {
"energy": 1700,
@ -1140,7 +1174,7 @@
"h": 1
},
"hp": 1700,
"armorClass": "structure",
"armorClass": "fortification",
"sight": 300,
"cost": {
"energy": 420,
@ -1171,7 +1205,7 @@
"h": 2
},
"hp": 3100,
"armorClass": "structure",
"armorClass": "fortification",
"sight": 420,
"cost": {
"energy": 1100,