Files
lords-of-ash/docs/milestones/M2-metallic-arts.md
T
jpmschweitzerandClaude Opus 4.6 84255ab819 docs(meta): add testing protocol and link from all milestones
Create docs/TESTING.md with debug game rule, debug decisions per
milestone, log analysis commands, pre-launch validation script,
post-run analysis script, and Claude Code testing capabilities.
Add cross-reference to TESTING.md in each milestone's Testing
Checkpoints section (M1-M8).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 17:34:33 +01:00

44 KiB

M2: The Metallic Arts

All metallic arts systems -- Allomancy, Feruchemy, Hemalurgy, and Compounding -- are complete, balanced, and tested.

Prerequisites

  • M1 (Foundation) complete: mod boots cleanly, province history correct, vanilla decisions suppressed, game rule toggle exists, triggers fixed.
  • All trigger fixes from M1 are in place (is_feruchemist_trigger matches only active, has_allomantic_potential_trigger matches only dormant, Lord Ruler attention system unified).

Current State

The metallic arts have a substantial foundation but need validation, polish, missing event content, new systems (training, savant consequences, Sandbox decision), and MaA balance.

Allomancy (mostly complete):

  • 12 Misting traits defined in common/traits/00_allomancy_traits.txt (lines 1-262): Coinshot, Lurcher, Thug, Tineye, Soother, Rioter, Smoker, Seeker, Augur, Oracle, Duralumin, Nicroburst. All genetic, grouped in allomancy_group, with trait indices 200-211.
  • Mistborn trait in common/traits/01_mistborn_trait.txt (index 220): genetic, same group, prowess 15 + martial 4 + intrigue 4 + diplomacy 2.
  • Allomantic potential traits in common/traits/03_allomantic_potential.txt (indices 240-241): trait_allomantic_potential (30% inherit, hidden) and trait_mistborn_potential (3% inherit, hidden). Separate allomantic_potential_group.
  • Strength tiers in common/traits/02_allomantic_strength.txt (indices 230-232): weak, strong, savant. Separate allomantic_strength_group with opposite blocks.
  • Snapping event chain in events/snapping_events.txt (4 events, ~470 lines): natural snapping on birthday (0001), forced snapping decision (0010), success (0020), failure (0030). Well-implemented with weighted random lists and parent trait modifiers.
  • activate_allomancy_effect in common/scripted_effects/mistborn_effects.txt (lines 6-40): weighted random list for Misting type, Mistborn requires parent trait.

Feruchemy (minimal):

  • 2 traits in common/traits/04_feruchemy_traits.txt (indices 250-251): trait_feruchemist (active, 15% inherit) and trait_feruchemy_potential (dormant, 25% inherit). Separate groups.
  • No Feruchemy activation event chain (no "Feruchemy snapping" equivalent).
  • No Keeper mechanics.
  • No Terris-only restriction enforced beyond initial character assignments.

Hemalurgy (functional stub):

  • 6 traits in common/traits/05_hemalurgy_traits.txt (indices 260-265): trait_hemalurgist, 4 spike types (steel, pewter, bronze, atium), trait_knows_hemalurgy.
  • 1 event in events/hemalurgy_events.txt (~148 lines): spike creation with victim selection, trait transfer based on victim's power, death of victim. Functional but only 1 event -- no follow-up consequences, no Inquisitor transformation event, no Ruin influence escalation.
  • create_steel_inquisitor_effect in mistborn_effects.txt (lines 146-157): adds all hemalurgic traits + disfigured. No associated event.
  • commission_hemalurgic_spike_decision in decisions file (lines 256-329): requires trait_knows_hemalurgy, targets courtier with Allomantic trait.

Compounding (functional):

  • Detection in common/on_action/mistborn_on_actions.txt (lines 65-91): yearly pulse checks for trait_feruchemist + any Allomantic trait.
  • Compounding discovery event mistborn_misc.0010 (lines 138-218): grants compounder_modifier with massive stat bonuses, or suppress knowledge.
  • compounder_modifier in modifiers file (lines 9-19): prowess 10, health 3, all skills +3-5.

Men-at-Arms (5 types, needs balance):

  • common/men_at_arms_types/00_mistborn_maa.txt (lines 1-166): Hazekillers, Koloss, Mistborn Agents, Skaa Levies, Noble Guard.
  • Mistborn Agents are extremely strong (100 damage, max 10) but have no recruitment restriction (any ruler can buy them -- should require Allomancer).
  • Koloss are very strong (80 damage, 40 toughness) and very cheap (50 gold) -- likely overpowered for cost.
  • No can_recruit blocks on any MaA type.

Events (mixed completeness):

  • events/ball_events.txt: 4 events, ~450 lines. Well-implemented chain with political, intrigue, and Allomantic display branches.
  • events/lord_ruler_events.txt: 5 events, ~587 lines. Full 3-tier escalation
    • decay + gain tracking. Well-implemented.
  • events/snapping_events.txt: 4 events, ~470 lines. Complete chain.
  • events/atium_events.txt: 2 events, ~160 lines. Success and failure branches for smuggling. Functional.
  • events/skaa_events.txt: 2 events, ~151 lines. Crackdown and improvement aftermath. Functional.
  • events/skaa_allomancer_events.txt: 2 events, ~204 lines. Recruitment and investigation. Functional but recruit always gets trait_misting_coinshot (hardcoded, should be random).
  • events/hemalurgy_events.txt: 1 event, ~148 lines. Spike creation only. Missing: Inquisitor creation event, Ruin influence consequences, multi-spike progression.
  • events/mistborn_misc_events.txt: 5 events, ~530 lines. Kandra hire, compounding discovery, skaa uprising, mist spirit, atium discovery.

Implementation Tasks

2.1 -- Validate and Polish Allomancy Traits

Context: The 12 Misting traits and Mistborn trait are well-defined but need validation of inheritance mechanics, group exclusivity, and balance. All traits in allomancy_group are mutually exclusive (a character can only be one Misting type OR Mistborn). The potential traits are in a separate group and should be removed upon snapping.

Steps:

  1. Verify all traits in 00_allomancy_traits.txt and 01_mistborn_trait.txt share group = "allomancy_group". Confirm CK3 enforces mutual exclusivity within a group -- a character cannot have two traits from the same group.
  2. Verify birth = 0 on all allomancy traits -- these should not appear at birth (only potential traits should).
  3. Review trait stat balance across the 12 Mistings:
    • Physical metals (Coinshot, Lurcher, Thug, Tineye): prowess/martial focus
    • Mental metals (Soother, Rioter, Smoker, Seeker): diplomacy/intrigue focus
    • Higher metals (Augur, Oracle, Duralumin, Nicroburst): learning or niche
    • Oracle is very powerful (prowess 8, intrigue 4) -- appropriate given extreme rarity (1% inherit). Acceptable.
    • Duralumin (learning 2) and Nicroburst (diplomacy 2) are weak -- intentional per lore (their Allomantic abilities are about enhancing others, not direct power). Acceptable.
  4. Ensure all trait icon paths reference unique .dds files. Currently all use gfx/interface/icons/traits/trait_misting_*.dds. These files do not exist yet but will be created in M8. For now, add a fallback comment and accept missing icon warnings.
  5. Validate trait_mistborn has genetic = yes and reasonable inheritance (2% base, 5% both parents). This is intentionally very rare.
  6. Verify ruler_designer_cost values are balanced -- Mistborn (200) should be the most expensive, Oracle (150) next, Thug (75), others 40-60. Current values are reasonable.

Files:

  • common/traits/00_allomancy_traits.txt -- validate (modify if needed)
  • common/traits/01_mistborn_trait.txt -- validate (modify if needed)
  • common/traits/02_allomantic_strength.txt -- validate (modify if needed)
  • common/traits/03_allomantic_potential.txt -- validate (modify if needed)

References:

  • Trait definitions: common/traits/00_allomancy_traits.txt:1-262
  • Lore reference for metal abilities: docs/lore/mistborn-universe.md:47-86

2.2 -- Complete the Snapping Event Chain

Context: The snapping system is well-built but needs edge case handling and a few additional events. Currently, the activate_allomancy_effect (in mistborn_effects.txt lines 6-40) and the snapping success event (mistborn_snapping.0020) both contain independent random lists for determining Misting type. The effect's list is simpler; the event's list includes parent trait modifiers. Only the event's list should be used -- the effect is called by trigger_snapping_effect but the event handles activation directly in its immediate block.

Steps:

  1. Fix the dual-activation path. Currently trigger_snapping_effect (line 103 of mistborn_effects.txt) calls activate_allomancy_effect which assigns a random Misting type, AND the snapping success event 0020 also assigns a type in its immediate block. If both run, the character could get two traits. Verify the flow:

    • Decision triggers mistborn_snapping.0010 -> options trigger mistborn_snapping.0020 on the snapping_target -> event 0020's immediate block does the activation.
    • trigger_snapping_effect should NOT be called by the decision path.
    • trigger_snapping_effect is used by the natural snapping path (birthday event 0001 option fires 0020 on root). This is correct -- 0020 handles activation.
    • Conclusion: trigger_snapping_effect is actually NOT called by any existing code path. It exists as a utility. Verify this and either remove it or update it to simply call 0020 via trigger_event.
  2. Add a mistborn_snapping.0040 event -- "Late Snapping" for characters age 17-30 who still have dormant potential. Lower success chance (15%), fires from rare traumatic life events (combat, imprisonment, near-death). Add this to on_action hooks:

    on_imprison = {
        events = { mistborn_snapping.0040 }
    }
    
  3. Add proper mistborn_potential handling to mistborn_snapping.0020. The event already handles this (lines 276-282) -- trait_mistborn_potential is removed and trait_mistborn is added. Verify this path works correctly and the Mistborn discovery option (option A) fires with appropriate rewards.

  4. Ensure the snapping failure event (0030) adds appropriate opinion modifiers -- currently the father gets disappointed_opinion (-15). Add a check: if the character is now wounded from the snapping attempt, the father should also get a guilt_opinion modifier.

  5. Add localization for any new events in localization/english/mistborn_events_l_english.yml.

Files:

  • events/snapping_events.txt -- modify (add late snapping event, fix flow)
  • common/scripted_effects/mistborn_effects.txt -- modify (clean up unused effect or redirect)
  • common/on_action/mistborn_on_actions.txt -- modify (add late snapping hooks)
  • localization/english/mistborn_events_l_english.yml -- modify

References:

  • Snapping events: events/snapping_events.txt:1-470
  • Activation effect: common/scripted_effects/mistborn_effects.txt:6-40
  • Trigger snapping effect: common/scripted_effects/mistborn_effects.txt:103-132

2.3 -- Add Allomantic Training Event Chain

Context: The MASTERPLAN specifies an Allomantic Training system -- an education-style event chain where a mentor teaches a pupil, with choices that influence specialization. Completion grants trait_allomantic_strong. This is entirely new content.

Steps:

  1. Create a new event namespace mistborn_training in a new file events/training_events.txt.

  2. Create a decision train_allomancer_decision in common/decisions/00_mistborn_decisions.txt:

    train_allomancer_decision = {
        is_shown = {
            is_ruler = yes
            OR = {
                is_allomancer_trigger = yes
                any_courtier = { is_allomancer_trigger = yes }
            }
            any_close_or_extended_family_member = {
                is_allomancer_trigger = yes
                NOT = { has_trait = trait_allomantic_strong }
                NOT = { has_trait = trait_allomantic_savant }
                NOT = { has_character_flag = undergoing_allomantic_training }
            }
        }
        is_valid = {
            gold >= 100
            # Must have a mentor (self or courtier who is an Allomancer)
            OR = {
                is_allomancer_trigger = yes
                any_courtier = { is_allomancer_trigger = yes }
            }
        }
        cost = { gold = 100 }
        cooldown = { years = 3 }
        effect = {
            # Select trainee and mentor
            random_close_or_extended_family_member = {
                limit = {
                    is_allomancer_trigger = yes
                    NOT = { has_trait = trait_allomantic_strong }
                    NOT = { has_trait = trait_allomantic_savant }
                    NOT = { has_character_flag = undergoing_allomantic_training }
                }
                save_scope_as = training_pupil
                add_character_flag = {
                    flag = undergoing_allomantic_training
                    years = 5
                }
            }
            trigger_event = mistborn_training.0001
        }
    }
    
  3. Create 4-5 training events:

    • mistborn_training.0001 -- Training begins: choose training focus (combat, subtlety, endurance). Mentor assigned.
    • mistborn_training.0010 -- Mid-training: a challenge arises (opponent duel, discovery risk, physical limit). Player chooses response.
    • mistborn_training.0020 -- Training complete: grant trait_allomantic_strong on success, or trait_allomantic_weak on failure. Success chance based on mentor quality and choices.
    • mistborn_training.0030 -- Training interrupted: Lord Ruler attention, injury, or other disruption. Training fails, flag removed.
  4. Wire training to on_yearly_pulse or use delayed events (2-3 year chain using trigger_event with days = { 365 730 }).

  5. Add all localization keys for the new events and decision.

Files:

  • events/training_events.txt -- create
  • common/decisions/00_mistborn_decisions.txt -- modify (add decision)
  • common/on_action/mistborn_on_actions.txt -- modify (if using on_action hooks)
  • localization/english/mistborn_events_l_english.yml -- modify
  • localization/english/mistborn_decisions_l_english.yml -- modify

References:

  • Existing decision patterns: common/decisions/00_mistborn_decisions.txt:56-130
  • Strength traits: common/traits/02_allomantic_strength.txt:1-85

2.4 -- Validate and Complete Feruchemy System

Context: Feruchemy currently has only 2 traits and no activation events. Per lore, Feruchemy is native to the Terris people and all Terris have the genetic potential. Unlike Allomancy, Feruchemy does not require "snapping" -- it manifests naturally through practice. The Lord Ruler's breeding program suppresses Feruchemy, so it should be rare even among Terris.

Steps:

  1. Add a Feruchemy activation event chain in a new event namespace mistborn_feruchemy in events/feruchemy_events.txt:

    • mistborn_feruchemy.0001 -- "Discovering the Art": fires on yearly pulse for Terris characters aged 14+ with trait_feruchemy_potential. Low chance (10% per year), increased if character has high learning or is in a court with another Feruchemist.
    • mistborn_feruchemy.0010 -- "The First Metalmind": character creates their first metalmind. Remove trait_feruchemy_potential, add trait_feruchemist. Options for what attribute to store first (affects a small temporary modifier).
  2. Add Terris-only inheritance enforcement. Currently trait_feruchemy_potential has 25% inherit chance with no culture restriction. CK3's genetic trait system does not natively restrict by culture, so inheritance is handled automatically. However, add a scripted effect check_feruchemy_bloodline_effect that runs on birth (via on_birth in on_actions) to remove trait_feruchemy_potential from non-Terris children (lore: Feruchemy is genetically tied to Terris blood, though cross-breeding can carry it). Decision: keep the trait on mixed-heritage children but at reduced chance. Actually, the simpler approach is to leave inheritance as-is (genetic system handles it) and accept that noble-Terris crossbreeding can produce Feruchemists -- this is lore-accurate (it is how the Lord Ruler's breeding program works, and how Compounders are eventually created).

  3. Add a Keeper mechanic: characters with trait_feruchemist and culture = terris who follow terris_worldbringers faith gain a "Keeper of Terris" modifier via an event. This modifier grants learning +2, monthly piety +0.5. Define the modifier in 00_mistborn_modifiers.txt.

  4. Wire mistborn_feruchemy.0001 to on_yearly_pulse in on_actions.

  5. Add localization for all new events and modifiers.

Files:

  • events/feruchemy_events.txt -- create
  • common/on_action/mistborn_on_actions.txt -- modify (add feruchemy hooks)
  • common/modifiers/00_mistborn_modifiers.txt -- modify (add keeper modifier)
  • localization/english/mistborn_events_l_english.yml -- modify
  • localization/english/mistborn_modifiers_l_english.yml -- modify

References:

  • Feruchemy traits: common/traits/04_feruchemy_traits.txt:1-48
  • Terris culture: common/culture/cultures/00_scadrial_cultures.txt:53-75
  • Lore: docs/lore/mistborn-universe.md:88-115

2.5 -- Complete Hemalurgy Event Chain

Context: Hemalurgy has 1 event (spike creation). The MASTERPLAN requires Inquisitor creation events, Ruin influence consequences, and more depth. The create_steel_inquisitor_effect exists in mistborn_effects.txt but is never called by any event.

Steps:

  1. Add mistborn_hemalurgy.0010 -- "The Inquisitor Rises": an event that fires after a character has accumulated 3+ hemalurgic spike traits. Offers the option to undergo full Inquisitor transformation (calls create_steel_inquisitor_effect, applies steel_inquisitor_power modifier, massive dread and opinion penalties). This event should fire from on_yearly_pulse with a trigger checking spike count.

  2. Add mistborn_hemalurgy.0020 -- "Ruin's Whispers": fires periodically for characters with trait_hemalurgist. Each spike increases Ruin's influence. Options:

    • Resist the whispers (stress gain, learning XP)
    • Listen to Ruin (gain intrigue bonus, apply ruin_influence modifier, lose some diplomacy)
    • Give in completely (convert to cult_of_ruin faith, gain trait_knows_hemalurgy if not already held)
  3. Add mistborn_hemalurgy.0030 -- "Discovery": if a character with trait_hemalurgist is discovered by the Steel Ministry (random chance on yearly pulse, higher chance with more spikes), triggers Lord Ruler attention spike and potential execution.

  4. Wire the Inquisitor check and Ruin's Whispers to on_yearly_pulse in on_actions:

    on_yearly_pulse = {
        events = {
            mistborn_hemalurgy.0010  # Inquisitor transformation check
            mistborn_hemalurgy.0020  # Ruin's whispers
            mistborn_hemalurgy.0030  # Discovery risk
        }
    }
    
  5. Create a scripted trigger has_multiple_spikes_trigger:

    has_multiple_spikes_trigger = {
        calc_true_if = {
            amount >= 3
            has_trait = trait_hemalurgic_steel
            has_trait = trait_hemalurgic_pewter
            has_trait = trait_hemalurgic_bronze
            has_trait = trait_hemalurgic_atium
        }
    }
    
  6. Add all localization keys.

Files:

  • events/hemalurgy_events.txt -- modify (add 3 new events)
  • common/on_action/mistborn_on_actions.txt -- modify
  • common/scripted_triggers/mistborn_triggers.txt -- modify (add spike trigger)
  • localization/english/mistborn_events_l_english.yml -- modify

References:

  • Existing hemalurgy event: events/hemalurgy_events.txt:1-148
  • Inquisitor effect: common/scripted_effects/mistborn_effects.txt:146-157
  • Hemalurgy traits: common/traits/05_hemalurgy_traits.txt:1-108
  • Ruin influence modifier: common/modifiers/00_mistborn_modifiers.txt:95-102

2.6 -- Validate Compounding and Add Savant Consequences

Context: Compounding detection works but needs validation that it correctly matches trait pairs. The savant system exists as a trait (trait_allomantic_savant with health -1, stress_gain_mult 0.3) but has no acquisition mechanism or consequence events.

Steps:

  1. Validate the compounding check in on_yearly_pulse (lines 65-91 of on_actions). Currently checks trait_feruchemist + any Misting/Mistborn trait. This is correct per lore -- a full Feruchemist who is also any kind of Allomancer can Compound. Verify the check excludes characters who already have compounder_modifier.

  2. Verify the compounding event (mistborn_misc.0010) correctly identifies the metal overlap. Currently it does not specify which metal is being compounded -- it just grants the generic compounder_modifier. This is acceptable for now (a full Feruchemist + any Allomantic metal = compounding). Per lore, the Lord Ruler compounded ALL metals because he was both Mistborn and full Feruchemist.

  3. Add savant acquisition mechanics. Savantism comes from years of constant metal-burning. Add a hidden event mistborn_misc.0050 that fires on yearly pulse for characters who:

    • Have any active Allomantic trait (Misting or Mistborn)
    • Have trait_allomantic_strong
    • Have been an Allomancer for 10+ years (check via years_of_reign proxy or use a character flag allomancer_years_active incremented yearly)
    • Do NOT already have trait_allomantic_savant

    The event should have a low chance (5% per year after conditions met) and present the player with the choice to embrace or resist savantism.

  4. Add savant consequence events mistborn_misc.0060:

    • Fires yearly for characters with trait_allomantic_savant
    • Random outcomes: heightened senses cause paranoia (stress), burning metal involuntarily in sleep (health risk), enhanced power moment (temporary prowess boost), dependency withdrawal (if the character runs out of metal metaphorically -- stress spike)
    • 3-4 options with different risk/reward tradeoffs
  5. Add localization for new events.

Files:

  • events/mistborn_misc_events.txt -- modify (add savant events)
  • common/on_action/mistborn_on_actions.txt -- modify (add savant hooks)
  • localization/english/mistborn_events_l_english.yml -- modify

References:

  • Compounding check: common/on_action/mistborn_on_actions.txt:65-91
  • Compounding event: events/mistborn_misc_events.txt:138-218
  • Savant trait: common/traits/02_allomantic_strength.txt:60-85

2.7 -- Metal Supply and Scarcity System

Context: In the books, Allomancers burn metals to fuel their powers — they carry vials of metal flakes dissolved in alcohol and can run out mid-fight. Noble houses maintain metal reserves for their Allomancers. Skaa Allomancers struggle to acquire metals at all. Atium is astronomically rare and controlled by the Lord Ruler. Currently the mod treats Allomancy as always-on via traits with zero resource cost, which removes a core tension from the source material.

This task group introduces a metal supply system that makes Allomantic power dependent on access to metals, creating gameplay tension around procurement, wealth, and logistics.

Steps:

  1. Define metal supply modifiers in common/modifiers/00_mistborn_modifiers.txt:

    • metal_reserves_abundant — character has a well-stocked metal supply. Bonuses: prowess +3, martial +1, intrigue +1 (Allomantic powers at full strength). Granted to noble houses with gold > 300.
    • metal_reserves_low — supplies running thin. Penalties: prowess -2, martial -1, stress +0.5/month (anxiety about running out). Triggers events to acquire more.
    • metal_reserves_depleted — out of metals entirely. Penalties: prowess -5, martial -3, intrigue -2 (Allomantic abilities effectively offline). Removes after metals acquired.
    • atium_reserve — character holds atium (refactor existing has_atium_reserve flag into a proper modifier). Bonuses: prowess +5, monthly_prestige +0.3. Duration: 3 years (atium is consumed). These modifiers should only apply to characters who pass is_allomancer_trigger — non-Allomancers don't burn metals.
  2. Create a decision acquire_metal_supply_decision in common/decisions/00_mistborn_decisions.txt:

    • is_shown: character passes is_allomancer_trigger = yes
    • is_valid: does NOT have metal_reserves_abundant modifier, gold >= 50
    • Cost: 50-150 gold (scaled by Allomantic strength — Mistborn burn more, savants burn much more)
    • Effect: remove metal_reserves_low and metal_reserves_depleted if present, add metal_reserves_abundant for 2 years
    • Cooldown: 1 year
    • AI: base 80 (AI Allomancers should maintain supplies)
  3. Create a decision acquire_metals_black_market_decision for skaa Allomancers and characters without easy access:

    • is_shown: is_allomancer_trigger = yes AND (culture is skaa OR gold < 50)
    • Cost: 20 gold + intrigue skill check
    • Effect: on success, add metal_reserves_abundant for 1 year (shorter — black market supply is unreliable). On failure, Lord Ruler attention +5 and metal_reserves_low.
    • This creates the lore-accurate dynamic where skaa Allomancers face real risk just acquiring metals.
  4. Add metal depletion events to events/mistborn_misc_events.txt or a new events/metal_supply_events.txt:

    • mistborn_metal.0001 — Metal reserves running low. Fires on yearly pulse for Allomancers who have had metal_reserves_abundant for 2+ years (duration expired) and haven't re-acquired. Grants metal_reserves_low. Options: buy more (gold cost), seek black market, ration (keep low, extend duration).
    • mistborn_metal.0010 — Depleted. Fires 1 year after metal_reserves_low if not resupplied. Grants metal_reserves_depleted. Urgent tone — "your vials are empty."
    • mistborn_metal.0020 — Windfall. Rare event (~0.1 weight) for characters with metal_reserves_low or depleted. A metal merchant arrives, a cache is discovered, or a benefactor provides supply. Free resupply with minor narrative flavor.
    • mistborn_metal.0030 — Wartime scarcity. Fires during wars for Allomancer characters. Metal supply consumed faster in combat. If at war and metal_reserves_abundant, 30% chance per year of dropping to metal_reserves_low.
  5. Add on_action hooks in common/on_action/mistborn_on_actions.txt:

    • On yearly pulse: check Allomancer characters for metal supply expiry
    • On game start: grant metal_reserves_abundant to all starting noble Allomancers (they begin well-supplied). Skaa Allomancers start with metal_reserves_low.
    • On war declaration: trigger wartime scarcity check for Allomancer rulers
  6. Add localization for all modifiers, decisions, and events in localization/english/mistborn_modifiers_l_english.yml, localization/english/mistborn_decisions_l_english.yml, and localization/english/mistborn_events_l_english.yml.

Files:

  • common/modifiers/00_mistborn_modifiers.txt -- modify
  • common/decisions/00_mistborn_decisions.txt -- modify
  • events/metal_supply_events.txt -- create (or extend mistborn_misc_events.txt)
  • common/on_action/mistborn_on_actions.txt -- modify
  • localization/english/mistborn_modifiers_l_english.yml -- modify
  • localization/english/mistborn_decisions_l_english.yml -- modify
  • localization/english/mistborn_events_l_english.yml -- modify

References:

  • Existing modifier pattern: common/modifiers/00_mistborn_modifiers.txt:128-136 (atium_supply modifier)
  • Existing decision pattern: common/decisions/00_mistborn_decisions.txt:331-389 (smuggle_atium_decision)
  • Allomancer trigger: common/scripted_triggers/mistborn_triggers.txt (is_allomancer_trigger)
  • Lore: docs/lore/mistborn-universe.md — Allomancers consume metals, nobles maintain vial supplies, skaa acquire metals through underground networks

2.8 -- Balance Men-at-Arms Types

Context: 5 MaA types exist but have no recruitment restrictions, and some stat values are unbalanced. Hazekillers should counter Allomancer-heavy armies, Koloss should be powerful but have drawbacks, Mistborn Agents should require Allomancers in court, and Skaa Levies should be limited by culture/situation.

Steps:

  1. Add can_recruit triggers to MaA types in 00_mistborn_maa.txt:

    • Mistborn Agents: require ruler or courtier to have is_allomancer_trigger
      can_recruit = {
          OR = {
              is_allomancer_trigger = yes
              any_courtier = { is_allomancer_trigger = yes }
          }
      }
      
    • Koloss: require special condition -- culture is noble_scadrian AND either holds c_koloss_range or has Lord Ruler attention < 50 (Koloss are controlled by the empire, not freely available)
      can_recruit = {
          culture = culture:noble_scadrian
          OR = {
              any_held_county = { this = title:c_koloss_range }
              highest_held_title_tier >= tier_kingdom
          }
      }
      
    • Hazekillers: require culture = culture:noble_scadrian (these are trained noble house soldiers)
    • Noble Guard: require culture = culture:noble_scadrian
    • Skaa Levies: no restriction (any ruler can conscript skaa)
  2. Balance stat adjustments:

    • Koloss: increase buy_cost from 50 to 120 (they are expensive to maintain/control, not cheap). Reduce max from 300 to 150 (they are rare). Add siege_value = 0.1 (good at breaking walls).
    • Mistborn Agents: reduce damage from 100 to 80 (still elite). Add counters = { heavy_infantry = 1 } only (remove skirmishers = 1 -- Mistborn don't counter their own type).
    • Hazekillers: add counters = { skirmishers = 2 } (specifically anti-Allomancer, and Mistborn Agents are skirmishers). This creates the Hazekillers-counter-Mistborn dynamic from the books.
    • Skaa Levies: reduce max from 1000 to 500 (still plentiful but not unlimited).
  3. Add localization for any new can_recruit tooltip strings if CK3 requires them.

Files:

  • common/men_at_arms_types/00_mistborn_maa.txt -- modify
  • localization/english/mistborn_maa_l_english.yml -- modify (if needed)

References:

  • Current MaA: common/men_at_arms_types/00_mistborn_maa.txt:1-166
  • Lore on Hazekillers: docs/lore/mistborn-universe.md (anti-Allomancer soldiers)

2.9 -- Polish Existing Event Files

Context: Several event files have issues that need fixing: hardcoded trait assignment, missing edge cases, and incomplete follow-up events.

Steps:

  1. Fix skaa_allomancer_events.txt: mistborn_skaa_allomancer.0001 (line 32) hardcodes trait = trait_misting_coinshot on the created character. Replace with a post-creation random trait assignment:

    create_character = {
        location = root.capital_province
        template = pool_repopulate_prowess
        culture = culture:skaa
        faith = root.faith
        gender_female_chance = 50
        dynasty = none
        save_scope_as = skaa_recruit
    }
    # After creation, assign random Allomantic trait
    scope:skaa_recruit = {
        activate_allomancy_effect = yes
    }
    

    Actually, activate_allomancy_effect requires trait_allomantic_potential first. Instead, add the potential then activate:

    scope:skaa_recruit = {
        add_trait = trait_allomantic_potential
        activate_allomancy_effect = yes
    }
    
  2. Fix atium_events.txt: mistborn_atium.0002 (atium failure) directly modifies lord_ruler_attention variable in the immediate block AND in option effects. Ensure the variable is properly initialized before modification (add an if check like in other events, or use the scripted effect increase_lord_ruler_attention_effect).

  3. Fix ball_events.txt: mistborn_ball.0010 political maneuvering (line 131) uses random_neighboring_top_liege_realm_owner which may fail if the player IS the top liege. Add a fallback to random_vassal (already partially handled on lines 141-151, verify it works).

  4. Fix mistborn_misc_events.txt: mistborn_misc.0020 skaa uprising (line 277) applies ash_blight county modifier as punishment for crushing a rebellion -- this is thematically wrong (ash blight is a natural phenomenon). Replace with a new modifier skaa_devastation or brutal_repression:

    brutal_repression = {
        county_opinion = -20
        development_growth_factor = -0.3
    }
    

    Add this modifier to 00_mistborn_modifiers.txt and add localization.

  5. Add all localization for new/changed content.

Files:

  • events/skaa_allomancer_events.txt -- modify
  • events/atium_events.txt -- modify
  • events/ball_events.txt -- modify (validate)
  • events/mistborn_misc_events.txt -- modify
  • common/modifiers/00_mistborn_modifiers.txt -- modify (add new modifier)
  • localization/english/mistborn_events_l_english.yml -- modify
  • localization/english/mistborn_modifiers_l_english.yml -- modify

References:

  • Skaa allomancer recruit: events/skaa_allomancer_events.txt:23-34
  • Atium failure variable handling: events/atium_events.txt:86-100
  • Skaa uprising ash_blight misuse: events/mistborn_misc_events.txt:274-278

2.10 -- Add Sandbox Mode Decision

Context: The MASTERPLAN specifies a "Discover Your Metallic Arts" decision available only in Sandbox Mode. This lets any character test for Allomantic/Feruchemical potential and trigger a snapping/activation event.

Steps:

  1. Add discover_metallic_arts_decision to common/decisions/00_mistborn_decisions.txt:

    discover_metallic_arts_decision = {
        picture = "gfx/interface/illustrations/decisions/decision_personal_religious.dds"
        desc = discover_metallic_arts_decision_desc
        selection_tooltip = discover_metallic_arts_decision_tooltip
    
        ai_check_interval = 0  # AI should not use this
    
        is_shown = {
            is_sandbox_mode_trigger = yes
            NOT = { is_allomancer_trigger = yes }
            NOT = { is_feruchemist_trigger = yes }
            NOT = { has_character_flag = tried_metallic_arts_discovery }
        }
    
        is_valid = {
            is_sandbox_mode_trigger = yes
            age >= 16
            NOT = { has_character_flag = tried_metallic_arts_discovery }
        }
    
        cost = {
            gold = 200
            prestige = 100
        }
    
        cooldown = { years = 5 }
    
        effect = {
            add_character_flag = {
                flag = tried_metallic_arts_discovery
                years = 5
            }
            trigger_event = mistborn_sandbox.0001
        }
    }
    
  2. Create events/sandbox_events.txt with namespace mistborn_sandbox:

    • mistborn_sandbox.0001 -- "Testing Your Blood": character undergoes voluntary trauma to test for potential. Based on culture:
      • Noble Scadrian: 40% chance Allomantic potential found, then snap
      • Skaa: 20% chance (diluted bloodlines)
      • Terris: 40% chance Feruchemical potential found, 15% Allomantic
      • If potential found, immediately snap (Allomancy) or activate (Feruchemy)
      • If no potential: "Your blood carries no metallic legacy" -- refund partial gold, gain stress
  3. Add localization for the decision and events.

  4. Gate the decision visibility on the is_sandbox_mode_trigger from M1.

Files:

  • common/decisions/00_mistborn_decisions.txt -- modify (add decision)
  • events/sandbox_events.txt -- create
  • localization/english/mistborn_decisions_l_english.yml -- modify
  • localization/english/mistborn_events_l_english.yml -- modify

References:

  • Game rule trigger: common/scripted_triggers/mistborn_triggers.txt (from M1)
  • Existing decision patterns: common/decisions/00_mistborn_decisions.txt
  • Snapping flow: events/snapping_events.txt:256-427

2.11 -- Localization Pass for All New Content

Context: Every trait, event, decision, modifier, and tooltip added in M2 needs localization entries. This task collects all missing keys.

Steps:

  1. Audit all new events created in M2 tasks (training, feruchemy, hemalurgy extensions, savant, sandbox). For each event, ensure these keys exist:

    • {event_id}.t -- title
    • {event_id}.desc -- description
    • {event_id}.{option_letter} -- option text for each option
    • Any custom_tooltip keys referenced
  2. Audit all new decisions. Each needs:

    • {decision_id} -- name
    • {decision_id}_desc -- description
    • {decision_id}_tooltip -- selection tooltip
    • Any custom_tooltip keys
  3. Audit all new modifiers. Each needs:

    • {modifier_name} -- display name
    • {modifier_name}_desc -- description (optional but recommended)
  4. Verify BOM encoding on all .yml files. The first 3 bytes must be EF BB BF (UTF-8 BOM). CK3 will silently fail to load localization without BOM.

  5. Verify no duplicate keys across localization files -- each key must appear in exactly one file.

Files:

  • localization/english/mistborn_events_l_english.yml -- modify
  • localization/english/mistborn_decisions_l_english.yml -- modify
  • localization/english/mistborn_modifiers_l_english.yml -- modify
  • localization/english/mistborn_traits_l_english.yml -- validate

References:

  • Key format: <namespace>_<identifier>:<digit> "Display text"
  • Existing localization: all files in localization/english/

Testing Checkpoints

See docs/TESTING.md for the full testing protocol, debug decisions, log analysis commands, and helper scripts.

  • After 2.1 (Trait Validation):

    • Test: Open ruler designer, check all Allomantic traits appear with correct costs and stat bonuses.
    • Expected: 12 Misting types + Mistborn + 3 strength tiers all visible. Mutually exclusive within their group.
  • After 2.2 (Snapping Polish):

    • Test: Start as a character with a child who has trait_allomantic_potential. Use the "Subject Heir to Snapping" decision.
    • Expected: Child snaps into a specific Misting type (weighted by parent). Success/failure/injury/death outcomes all possible. No duplicate trait assignment.
  • After 2.3 (Training):

    • Test: Use the "Train Allomancer" decision on a family member who is a Misting.
    • Expected: Training event chain fires over 2-3 years. On completion, character gains trait_allomantic_strong or fails.
  • After 2.4 (Feruchemy):

    • Test: Play as or near a Terris character with trait_feruchemy_potential. Wait several years.
    • Expected: Feruchemy activation event fires. Character gains trait_feruchemist. Keeper modifier applied if Terris Worldbringer.
  • After 2.5 (Hemalurgy):

    • Test: Give a character trait_knows_hemalurgy via console. Use the "Commission a Hemalurgic Spike" decision 3+ times.
    • Expected: After 3 spikes, Inquisitor transformation event fires. Ruin's Whispers events fire periodically. Discovery risk events fire.
  • After 2.6 (Compounding + Savant):

    • Test: Give a character both trait_feruchemist and trait_misting_thug via console. Wait for yearly pulse.
    • Expected: Compounding discovery event fires. Character can gain compounder_modifier. Savant events fire for long-term strong Allomancers.
  • After 2.7 (Metal Supply):

    • Test: Play as a noble Allomancer for 3 years without using the acquire metals decision after the initial supply expires.
    • Expected: metal_reserves_abundant expires after 2 years. Low-supply event fires. If ignored another year, depleted event fires with stat penalties. Using the acquire decision restores abundant status. Skaa Allomancers start with metal_reserves_low and must use black market.
  • After 2.8 (MaA Balance):

    • Test: As a ruler without any Allomancers, check if Mistborn Agents appear in the MaA recruitment list.
    • Expected: Mistborn Agents do NOT appear (blocked by can_recruit). Hazekillers and Noble Guard appear for noble Scadrian rulers.
  • After 2.10 (Sandbox Decision):

    • Test: Start a new game in Sandbox Mode. Select a character without Allomantic traits.
    • Expected: "Discover Your Metallic Arts" decision appears in the decision menu. Using it triggers the testing event with culture-appropriate odds.
  • After all tasks (Full Integration Test):

    • Test: Play 20 years as any Great House lord. Monitor for:
      • Natural snapping events for children
      • Lord Ruler attention rising from actions
      • Compounding check on characters with both arts
      • Hemalurgy events if trait_knows_hemalurgy granted
      • MaA recruitment restrictions working
    • Expected: All metallic arts systems interact correctly. No errors in error.log. Events fire at reasonable frequencies. Balance feels right.

Acceptance Criteria

  • All 12 Misting traits + Mistborn are validated with correct groups, stats, inheritance, and mutual exclusivity.
  • Snapping event chain handles all edge cases: natural (birthday), forced (decision), late (trauma), with proper Misting type weighting.
  • Allomantic Training decision and event chain exist and can grant trait_allomantic_strong.
  • Feruchemy activation events fire for Terris characters with potential. Keeper modifier applied to qualifying Feruchemists.
  • Hemalurgy has 4+ events: spike creation, Inquisitor transformation, Ruin's Whispers, discovery risk.
  • Compounding correctly detects Allomancy + Feruchemy overlap and fires the discovery event.
  • Savant acquisition and consequence events exist for long-term Allomancers.
  • Metal supply system creates meaningful resource tension for Allomancers: abundant/low/depleted modifiers exist, acquire decisions work for nobles and skaa, depletion events fire on schedule, wartime scarcity functions.
  • Men-at-Arms types have can_recruit restrictions and balanced stats.
  • Skaa Allomancer recruitment creates characters with random Misting types (not hardcoded Coinshot).
  • "Discover Your Metallic Arts" Sandbox-only decision exists and functions.
  • All new content has complete localization with BOM-encoded .yml files.
  • Playing as any character for 20 years produces no errors related to metallic arts systems.
  • The Lord Ruler attention system does not reference the old lord_ruler_attention_modifier.

Risks & Mitigations

  1. Trait group conflicts. If CK3 does not properly enforce mutual exclusivity within trait groups, a character could end up with multiple Misting types. Mitigation: Add explicit NOT = { is_allomancer_trigger } checks before adding Misting traits in all activation effects.

  2. Event frequency tuning. Savant events, Ruin's Whispers, and Feruchemy activation may fire too often or too rarely. Mitigation: Use conservative weight_multiplier values initially and tune after playtesting.

  3. MaA balance. New can_recruit restrictions may make some MaA types inaccessible to AI rulers who should have them. Mitigation: Verify AI house heads in history have appropriate traits to recruit their faction's MaA.

  4. create_character template. The pool_repopulate_prowess template used in skaa allomancer recruitment may not exist in CK3 1.18. Mitigation: Check vanilla template names and use an appropriate one, or define a custom template.

  5. Compounding detection edge cases. If a character gains Feruchemy AFTER already having an Allomantic trait, the yearly pulse will catch it. But if both are gained in the same event chain, the flag check (compounding_check_done) may prevent detection. Mitigation: Add compounding check to Feruchemy activation events directly.

Open Questions

  1. Should Feruchemy use a "snapping" mechanic like Allomancy, or should it activate naturally through practice as per lore? Current design follows lore (natural activation through study/practice, no trauma required).

  2. Should savant consequences be purely negative (health loss, stress, paranoia) or mixed (some power benefits alongside penalties)? Per lore, savants gain enhanced abilities but lose control -- the trait already has +prowess/-health.

  3. The activate_allomancy_effect exists in both the scripted effects file and duplicated logic exists in mistborn_snapping.0020's immediate block. Should we consolidate to a single source of truth? Recommendation: make 0020 call the scripted effect and remove the duplicate logic from the event.

  4. Era 2 metals (chromium, aluminum, cadmium, bendalloy) are listed in the lore doc but are not known in the Final Empire era. The MASTERPLAN suggests omitting them. Confirm this decision: no Era 2 metal traits in this mod.