refactor(data): rebalance card stats and update starter deck composition

- Significantly increase HP values across all Imperial and Raider cards to extend combat duration and emphasize defense mechanics.
- Adjust armor values on select units (e.g., Raider Berserker, Marauder) to better match their roles.
- Reformat `cards.json` skills into expanded multi-line objects for improved readability and maintainability.
- Update the default starter deck in `DeckManager` to a more focused composition: 4x Trooper, 3x Gunner, 3x Guardian.
- Reduce starting gold in `SaveManager` from 1500 to 400 to better align with the new economic balance.
This commit is contained in:
Brian Fertig 2026-03-12 20:49:15 -06:00
parent 5e0d17b2c4
commit d865634a2f
3 changed files with 157 additions and 60 deletions

View File

@ -6,11 +6,15 @@
"type": "commander", "type": "commander",
"rarity": "legendary", "rarity": "legendary",
"attack": 5, "attack": 5,
"health": 30, "health": 60,
"armor": 2, "armor": 2,
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ "name": "rally", "value": 2, "trigger": "on_turn_start" } {
"name": "rally",
"value": 2,
"trigger": "on_turn_start"
}
], ],
"flavorText": "Iron discipline forged an empire from ash.", "flavorText": "Iron discipline forged an empire from ash.",
"artKey": "imp_cmd_1" "artKey": "imp_cmd_1"
@ -22,11 +26,15 @@
"type": "assault", "type": "assault",
"rarity": "common", "rarity": "common",
"attack": 3, "attack": 3,
"health": 5, "health": 13,
"armor": 0, "armor": 0,
"delay": 1, "delay": 1,
"skills": [ "skills": [
{ "name": "strike", "value": 1, "trigger": "on_attack" } {
"name": "strike",
"value": 1,
"trigger": "on_attack"
}
], ],
"flavorText": "The backbone of the Imperial war machine.", "flavorText": "The backbone of the Imperial war machine.",
"artKey": "imp_trooper_1" "artKey": "imp_trooper_1"
@ -38,11 +46,15 @@
"type": "assault", "type": "assault",
"rarity": "common", "rarity": "common",
"attack": 4, "attack": 4,
"health": 4, "health": 10,
"armor": 0, "armor": 0,
"delay": 1, "delay": 1,
"skills": [ "skills": [
{ "name": "pierce", "value": 1, "trigger": "on_attack" } {
"name": "pierce",
"value": 1,
"trigger": "on_attack"
}
], ],
"flavorText": "Precision fire, no mercy.", "flavorText": "Precision fire, no mercy.",
"artKey": "imp_gunner_1" "artKey": "imp_gunner_1"
@ -54,11 +66,15 @@
"type": "assault", "type": "assault",
"rarity": "rare", "rarity": "rare",
"attack": 2, "attack": 2,
"health": 8, "health": 20,
"armor": 3, "armor": 3,
"delay": 1, "delay": 1,
"skills": [ "skills": [
{ "name": "protect", "value": 2, "trigger": "on_attack" } {
"name": "protect",
"value": 2,
"trigger": "on_attack"
}
], ],
"flavorText": "Their shields have never broken. Never.", "flavorText": "Their shields have never broken. Never.",
"artKey": "imp_shieldwall_1" "artKey": "imp_shieldwall_1"
@ -70,11 +86,15 @@
"type": "assault", "type": "assault",
"rarity": "rare", "rarity": "rare",
"attack": 5, "attack": 5,
"health": 3, "health": 8,
"armor": 0, "armor": 0,
"delay": 2, "delay": 2,
"skills": [ "skills": [
{ "name": "strike", "value": 3, "trigger": "on_attack" } {
"name": "strike",
"value": 3,
"trigger": "on_attack"
}
], ],
"flavorText": "One shot. One less problem.", "flavorText": "One shot. One less problem.",
"artKey": "imp_sniper_1" "artKey": "imp_sniper_1"
@ -86,12 +106,20 @@
"type": "assault", "type": "assault",
"rarity": "epic", "rarity": "epic",
"attack": 6, "attack": 6,
"health": 7, "health": 16,
"armor": 2, "armor": 2,
"delay": 2, "delay": 2,
"skills": [ "skills": [
{ "name": "berserk", "value": 1, "trigger": "on_kill" }, {
{ "name": "strike", "value": 2, "trigger": "on_attack" } "name": "berserk",
"value": 1,
"trigger": "on_kill"
},
{
"name": "strike",
"value": 2,
"trigger": "on_attack"
}
], ],
"flavorText": "Built for war. Perfected through slaughter.", "flavorText": "Built for war. Perfected through slaughter.",
"artKey": "imp_mech_1" "artKey": "imp_mech_1"
@ -103,11 +131,15 @@
"type": "assault", "type": "assault",
"rarity": "rare", "rarity": "rare",
"attack": 2, "attack": 2,
"health": 6, "health": 14,
"armor": 1, "armor": 1,
"delay": 2, "delay": 2,
"skills": [ "skills": [
{ "name": "mortar", "value": 3, "trigger": "on_attack" } {
"name": "mortar",
"value": 3,
"trigger": "on_attack"
}
], ],
"flavorText": "Indirect fire is still very much on fire.", "flavorText": "Indirect fire is still very much on fire.",
"artKey": "imp_mortar_1" "artKey": "imp_mortar_1"
@ -119,11 +151,15 @@
"type": "assault", "type": "assault",
"rarity": "common", "rarity": "common",
"attack": 3, "attack": 3,
"health": 6, "health": 15,
"armor": 1, "armor": 1,
"delay": 1, "delay": 1,
"skills": [ "skills": [
{ "name": "counter", "value": 2, "trigger": "on_defend" } {
"name": "counter",
"value": 2,
"trigger": "on_defend"
}
], ],
"flavorText": "They who stand firm turn every blade aside.", "flavorText": "They who stand firm turn every blade aside.",
"artKey": "imp_guardian_1" "artKey": "imp_guardian_1"
@ -135,11 +171,15 @@
"type": "assault", "type": "assault",
"rarity": "epic", "rarity": "epic",
"attack": 7, "attack": 7,
"health": 9, "health": 20,
"armor": 3, "armor": 3,
"delay": 3, "delay": 3,
"skills": [ "skills": [
{ "name": "swipe", "value": 2, "trigger": "on_attack" } {
"name": "swipe",
"value": 2,
"trigger": "on_attack"
}
], ],
"flavorText": "Nothing stops it. Nothing.", "flavorText": "Nothing stops it. Nothing.",
"artKey": "imp_juggernaut_1" "artKey": "imp_juggernaut_1"
@ -151,12 +191,20 @@
"type": "assault", "type": "assault",
"rarity": "legendary", "rarity": "legendary",
"attack": 8, "attack": 8,
"health": 10, "health": 22,
"armor": 4, "armor": 4,
"delay": 3, "delay": 3,
"skills": [ "skills": [
{ "name": "strike", "value": 4, "trigger": "on_attack" }, {
{ "name": "armored", "value": 2, "trigger": "passive" } "name": "strike",
"value": 4,
"trigger": "on_attack"
},
{
"name": "armored",
"value": 2,
"trigger": "passive"
}
], ],
"flavorText": "The last line of defense. And they have never fallen.", "flavorText": "The last line of defense. And they have never fallen.",
"artKey": "imp_sentinel_1" "artKey": "imp_sentinel_1"
@ -168,11 +216,15 @@
"type": "commander", "type": "commander",
"rarity": "legendary", "rarity": "legendary",
"attack": 6, "attack": 6,
"health": 25, "health": 50,
"armor": 1, "armor": 1,
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ "name": "siege", "value": 3, "trigger": "on_turn_start" } {
"name": "siege",
"value": 3,
"trigger": "on_turn_start"
}
], ],
"flavorText": "The Khan takes what he wants. Everything else burns.", "flavorText": "The Khan takes what he wants. Everything else burns.",
"artKey": "raider_cmd_1" "artKey": "raider_cmd_1"
@ -184,11 +236,15 @@
"type": "assault", "type": "assault",
"rarity": "common", "rarity": "common",
"attack": 4, "attack": 4,
"health": 4, "health": 12,
"armor": 0, "armor": 0,
"delay": 1, "delay": 1,
"skills": [ "skills": [
{ "name": "berserk", "value": 1, "trigger": "on_kill" } {
"name": "berserk",
"value": 1,
"trigger": "on_kill"
}
], ],
"flavorText": "Cheap to field. Costly to face.", "flavorText": "Cheap to field. Costly to face.",
"artKey": "raider_grunt_1" "artKey": "raider_grunt_1"
@ -200,11 +256,15 @@
"type": "assault", "type": "assault",
"rarity": "common", "rarity": "common",
"attack": 3, "attack": 3,
"health": 3, "health": 11,
"armor": 0, "armor": 0,
"delay": 0, "delay": 0,
"skills": [ "skills": [
{ "name": "jam", "value": 1, "trigger": "on_attack" } {
"name": "jam",
"value": 1,
"trigger": "on_attack"
}
], ],
"flavorText": "Fast, quiet, deadly. Usually in that order.", "flavorText": "Fast, quiet, deadly. Usually in that order.",
"artKey": "raider_scout_1" "artKey": "raider_scout_1"
@ -216,12 +276,20 @@
"type": "assault", "type": "assault",
"rarity": "rare", "rarity": "rare",
"attack": 6, "attack": 6,
"health": 5, "health": 14,
"armor": 0, "armor": 1,
"delay": 1, "delay": 1,
"skills": [ "skills": [
{ "name": "berserk", "value": 2, "trigger": "on_kill" }, {
{ "name": "strike", "value": 2, "trigger": "on_attack" } "name": "berserk",
"value": 2,
"trigger": "on_kill"
},
{
"name": "strike",
"value": 2,
"trigger": "on_attack"
}
], ],
"flavorText": "Pain is just another fuel source.", "flavorText": "Pain is just another fuel source.",
"artKey": "raider_berserker_1" "artKey": "raider_berserker_1"
@ -233,11 +301,15 @@
"type": "assault", "type": "assault",
"rarity": "rare", "rarity": "rare",
"attack": 4, "attack": 4,
"health": 4, "health": 10,
"armor": 0, "armor": 2,
"delay": 1, "delay": 1,
"skills": [ "skills": [
{ "name": "enfeeble", "value": 2, "trigger": "on_attack" } {
"name": "enfeeble",
"value": 2,
"trigger": "on_attack"
}
], ],
"flavorText": "They don't kill you. They just make sure you can't fight back.", "flavorText": "They don't kill you. They just make sure you can't fight back.",
"artKey": "raider_cutthroat_1" "artKey": "raider_cutthroat_1"
@ -248,12 +320,16 @@
"faction": "raider", "faction": "raider",
"type": "assault", "type": "assault",
"rarity": "epic", "rarity": "epic",
"attack": 5, "attack": 6,
"health": 6, "health": 16,
"armor": 1, "armor": 3,
"delay": 2, "delay": 2,
"skills": [ "skills": [
{ "name": "rally", "value": 3, "trigger": "on_attack" } {
"name": "rally",
"value": 3,
"trigger": "on_attack"
}
], ],
"flavorText": "Where he goes, the pack follows.", "flavorText": "Where he goes, the pack follows.",
"artKey": "raider_warlord_1" "artKey": "raider_warlord_1"
@ -265,11 +341,15 @@
"type": "assault", "type": "assault",
"rarity": "common", "rarity": "common",
"attack": 3, "attack": 3,
"health": 5, "health": 13,
"armor": 0, "armor": 0,
"delay": 1, "delay": 1,
"skills": [ "skills": [
{ "name": "siege", "value": 2, "trigger": "on_attack" } {
"name": "siege",
"value": 2,
"trigger": "on_attack"
}
], ],
"flavorText": "Leave nothing standing. Take everything else.", "flavorText": "Leave nothing standing. Take everything else.",
"artKey": "raider_pillager_1" "artKey": "raider_pillager_1"
@ -281,11 +361,15 @@
"type": "assault", "type": "assault",
"rarity": "rare", "rarity": "rare",
"attack": 5, "attack": 5,
"health": 5, "health": 12,
"armor": 1, "armor": 2,
"delay": 2, "delay": 2,
"skills": [ "skills": [
{ "name": "swipe", "value": 1, "trigger": "on_attack" } {
"name": "swipe",
"value": 1,
"trigger": "on_attack"
}
], ],
"flavorText": "Swift violence is an art form.", "flavorText": "Swift violence is an art form.",
"artKey": "raider_marauder_1" "artKey": "raider_marauder_1"
@ -297,12 +381,20 @@
"type": "assault", "type": "assault",
"rarity": "epic", "rarity": "epic",
"attack": 7, "attack": 7,
"health": 7, "health": 16,
"armor": 0, "armor": 2,
"delay": 2, "delay": 2,
"skills": [ "skills": [
{ "name": "flurry", "value": 1, "trigger": "passive" }, {
{ "name": "berserk", "value": 2, "trigger": "on_kill" } "name": "flurry",
"value": 1,
"trigger": "passive"
},
{
"name": "berserk",
"value": 2,
"trigger": "on_kill"
}
], ],
"flavorText": "Every kill feeds the frenzy.", "flavorText": "Every kill feeds the frenzy.",
"artKey": "raider_reaver_1" "artKey": "raider_reaver_1"
@ -314,14 +406,22 @@
"type": "assault", "type": "assault",
"rarity": "legendary", "rarity": "legendary",
"attack": 8, "attack": 8,
"health": 8, "health": 18,
"armor": 2, "armor": 3,
"delay": 3, "delay": 3,
"skills": [ "skills": [
{ "name": "siege", "value": 5, "trigger": "on_attack" }, {
{ "name": "strike", "value": 3, "trigger": "on_attack" } "name": "siege",
"value": 5,
"trigger": "on_attack"
},
{
"name": "strike",
"value": 3,
"trigger": "on_attack"
}
], ],
"flavorText": "The Overlord doesn't negotiate. He dictates terms from the rubble.", "flavorText": "The Overlord doesn't negotiate. He dictates terms from the rubble.",
"artKey": "raider_overlord_1" "artKey": "raider_overlord_1"
} }
] ]

View File

@ -27,12 +27,9 @@ export class DeckManager {
name: 'Starter Deck', name: 'Starter Deck',
commander: 'imp_cmd_1', commander: 'imp_cmd_1',
cards: [ cards: [
'imp_trooper_1', 'imp_trooper_1', 'imp_trooper_1', 'imp_trooper_1', 'imp_trooper_1', 'imp_trooper_1', 'imp_trooper_1',
'imp_gunner_1', 'imp_gunner_1', 'imp_gunner_1', 'imp_gunner_1', 'imp_gunner_1',
'imp_guardian_1', 'imp_guardian_1', 'imp_guardian_1', 'imp_guardian_1', 'imp_guardian_1',
'imp_shieldwall_1',
'imp_mortar_1',
'imp_sniper_1'
] ]
}; };
} }

View File

@ -5,7 +5,7 @@ export class SaveManager {
static defaultSave() { static defaultSave() {
return { return {
version: CURRENT_VERSION, version: CURRENT_VERSION,
gold: 1500, gold: 400,
collection: {}, collection: {},
decks: [], decks: [],
campaignProgress: { completedMissions: [], currentChapter: 1 }, campaignProgress: { completedMissions: [], currentChapter: 1 },