Break the MASTERPLAN into 8 milestone documents (M1-M8) with a standard template. Each milestone includes prerequisites, current state assessment, numbered implementation tasks with file references, testing checkpoints, acceptance criteria, and risk analysis. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
23 KiB
M1: Foundation
The mod loads and plays cleanly on the vanilla map with zero errors, no vanilla bleed-through, and a working game rule toggle.
Prerequisites
- None. This is the first milestone.
- CK3 version 1.18.* installed and launchable.
- The
lords_of_ash/mod directory is loadable vialords-of-ash.mod.
Current State
The mod has a strong skeleton but several issues prevent a clean boot and
playthrough. All critical issues from the original review have been resolved
(trait name mismatches, missing event namespaces, @# comment syntax, missing
modifiers, province history, bookmark). However, warning-level issues remain
that must be fixed before M2 work can begin safely.
What exists and works:
common/modifiers/00_mistborn_modifiers.txt-- all 7 modifier definitions present (compounder, lord_ruler_attention tiers 1-3, ruin_influence, steel_inquisitor_power, great_house_status, atium_supply, ash_blight, koloss_rampage, opinion modifiers). Lines 1-154.history/provinces/00_mistborn_provinces.txt-- 105 provinces with culture, religion, and holding assignments. Lines 1-770.common/bookmarks/00_mistborn_bookmarks.txt-- "End of an Empire" bookmark.common/landed_titles/00_landed_titles.txt-- full title hierarchy mapping 105 baronies to vanilla Swiss/Swabian/Tyrolean/Burgundian/Lombard provinces. Lines 1-731.common/scripted_triggers/mistborn_triggers.txt-- 15 triggers. Lines 1-134.common/scripted_effects/mistborn_effects.txt-- 10 effects. Lines 1-190.common/culture/-- 3 cultures, 3 pillars, 4 traditions.common/religion/-- 4 religions with 4 faiths and 5 holy sites.history/characters/00_mistborn_characters.txt-- 30 characters.history/titles/00_mistborn_titles.txt-- title assignments for all 50+ titles.
What needs fixing (this milestone):
| Issue | File | Severity |
|---|---|---|
| Empty culture pillar blocks (WARNING-01) | common/culture/pillars/00_scadrial_pillars.txt |
Warning |
| Dual Lord Ruler attention systems (WARNING-05) | common/scripted_effects/, common/on_action/, events |
Warning |
is_feruchemist_trigger matches dormant potential (WARNING-06) |
common/scripted_triggers/mistborn_triggers.txt:71-76 |
Warning |
has_allomantic_potential_trigger is over-inclusive (WARNING-07) |
common/scripted_triggers/mistborn_triggers.txt:28-36 |
Warning |
| No vanilla decision suppression | common/decisions/ |
Missing |
| No game rule definitions | common/game_rules/ |
Missing |
| Province history uses sequential IDs 1-105 instead of vanilla IDs | history/provinces/00_mistborn_provinces.txt |
Critical |
trait_knows_hemalurgy referenced but was previously missing |
common/traits/05_hemalurgy_traits.txt:94-108 |
Resolved |
Critical discovery: The province history file uses sequential IDs 1-105,
but 00_landed_titles.txt maps baronies to vanilla province IDs (2046, 2047,
2048, etc.). Province history must use the actual vanilla province IDs from
the landed titles file, not sequential numbers. This mismatch means no province
currently has valid culture/religion/holding data at game start.
Implementation Tasks
1.1 -- Fix Province History to Use Vanilla Province IDs
Context: The province history file (history/provinces/00_mistborn_provinces.txt)
uses sequential IDs 1-105, but the landed titles file maps baronies to specific
vanilla province IDs (e.g., b_kredik_shaw -> province 2046, b_luthadel_city
-> province 2047). CK3 loads province history by matching numeric IDs to the
actual province definitions in map_data/. Since we use the vanilla map, our
province history must reference the vanilla province IDs from the landed titles
file. This is the single most critical fix -- without it, every province loads
with default (wrong) culture, religion, and holdings.
Steps:
- Extract all
province = XXXXvalues fromcommon/landed_titles/00_landed_titles.txt. There are 105 baronies with vanilla province IDs ranging from 2030 to 3107. - Rewrite
history/provinces/00_mistborn_provinces.txtto use these vanilla IDs instead of 1-105. Each province entry should keep the same culture, religion, and holding type, but the numeric key must match the vanilla province ID. - Group provinces by dominance (Central, Northern, Eastern, Western, Southern, Remote) with clear comments, matching the structure in the landed titles file.
- For each barony, determine the correct data from the existing file by matching
position -- e.g., province 1 in the old file corresponds to
b_kredik_shaw(province 2046), province 2 tob_luthadel_city(province 2047), etc. - Verify every vanilla province ID from the landed titles file has a corresponding entry in the province history file. Missing entries will cause errors.
Province ID mapping (first 21 as example -- Central Dominance):
| Old ID | Vanilla ID | Barony | Notes |
|---|---|---|---|
| 1 | 2046 | b_kredik_shaw | castle_holding, noble_scadrian |
| 2 | 2047 | b_luthadel_city | city_holding, noble_scadrian |
| 3 | 2048 | b_luthadel_slums | city_holding, skaa |
| 4 | 2049 | b_fellise | castle_holding, noble_scadrian |
| 5 | 2037 | b_fellise_estates | castle_holding, noble_scadrian |
| 6 | 2051 | b_holstep | castle_holding, noble_scadrian |
| 7 | 2461 | b_holstep_mines | city_holding, skaa |
| ... | ... | ... | ... |
The full mapping must be extracted from common/landed_titles/00_landed_titles.txt
lines 33-730 by reading each province = XXXX value in order.
Files:
history/provinces/00_mistborn_provinces.txt-- rewrite
References:
- Province ID source:
common/landed_titles/00_landed_titles.txt:33-730 - CK3 province history format:
{province_id} = { culture = X religion = Y holding = Z }
1.2 -- Fix Culture Pillar Definitions
Context: The culture pillars in common/culture/pillars/00_scadrial_pillars.txt
were originally empty {} blocks (WARNING-01). They have since been partially
filled but need validation against CK3 1.18 requirements. Pillars must have
type, is_shown, and typically audio_parameter (for heritage) or
ai_will_do (for language).
Steps:
- Validate
heritage_scadrial(lines 4-12): Confirm it hastype = heritage,is_shownblock, andaudio_parameter. Currently present -- verify theheritage_is_shown_triggeris a valid vanilla scripted trigger (it should reference the vanilla culture system). - Validate
language_scadrial(lines 14-28): Confirmtype = language,is_shown, andai_will_do. Currently present. - Validate
language_terris(lines 30-44): Same checks as above. - Add
martial_custom_male_onlyreference check -- this is used by all 3 cultures in00_scadrial_cultures.txt. Confirm it is a vanilla pillar that will be loaded (it is a standard CK3 martial custom, so this should work if vanilla pillars remain loaded). - If any pillar is missing a required field, add it following the vanilla
pattern in
common/culture/pillars/00_heritage.txtfrom the CK3 game files.
Files:
common/culture/pillars/00_scadrial_pillars.txt-- modify (validate/fix)
References:
- Current pillar code:
common/culture/pillars/00_scadrial_pillars.txt:1-44 - Cultures that reference these pillars:
common/culture/cultures/00_scadrial_cultures.txt:8,34,58
1.3 -- Fix Scripted Trigger Issues
Context: Two triggers have inclusiveness problems identified in WARNING-06 and WARNING-07 of the review. These will cause incorrect behavior in M2 when compounding checks and snapping logic rely on distinguishing active vs dormant Allomancers/Feruchemists.
Steps:
-
Rename
is_feruchemist_trigger(line 71) tohas_any_feruchemy_triggerto reflect that it matches both active and dormant. Create a newis_feruchemist_triggerthat only matchestrait_feruchemist(active). This preserves backward compatibility for any code already using the old name by making the old name now correctly mean "active Feruchemist."Actually, the cleaner fix:
is_feruchemist_triggercurrently matches bothtrait_feruchemistandtrait_feruchemy_potential. Change it to match onlytrait_feruchemist. Add a separatehas_feruchemy_potential_triggerthat matches onlytrait_feruchemy_potential. Addhas_any_feruchemy_triggerthat matches either.is_feruchemist_trigger = { has_trait = trait_feruchemist } has_feruchemy_potential_trigger = { has_trait = trait_feruchemy_potential } has_any_feruchemy_trigger = { OR = { has_trait = trait_feruchemist has_trait = trait_feruchemy_potential } } -
Fix
has_allomantic_potential_trigger(line 28). Currently matches active Allomancers viais_allomancer_triggerandis_mistborn_trigger. Rename tohas_any_allomantic_ability_trigger. Create a cleanhas_allomantic_potential_triggerthat only matches dormant potential:has_allomantic_potential_trigger = { OR = { has_trait = trait_allomantic_potential has_trait = trait_mistborn_potential } NOT = { is_allomancer_trigger = yes } }And add a broader trigger:
has_any_allomantic_ability_trigger = { OR = { has_trait = trait_allomantic_potential has_trait = trait_mistborn_potential is_allomancer_trigger = yes } } -
Verify
is_full_feruchemist_trigger(line 78) is correct -- it matches onlytrait_feruchemist, which is fine. -
Search all files that use
is_feruchemist_triggerorhas_allomantic_potential_triggerand update callsites to use the correct new trigger name. Key locations:common/on_action/mistborn_on_actions.txt(compounding check, line 69)events/mistborn_misc_events.txt(mist spirit encounter, line 381)- Any future M2 code
Files:
common/scripted_triggers/mistborn_triggers.txt-- modify
References:
- Current trigger code:
common/scripted_triggers/mistborn_triggers.txt:28-36,71-80 - Compounding check using triggers:
common/on_action/mistborn_on_actions.txt:66-91
1.4 -- Unify the Dual Lord Ruler Attention System
Context: WARNING-05 identifies two parallel Lord Ruler attention systems:
(1) a variable-based system (lord_ruler_attention variable 0-100) managed by
mistborn_effects.txt and mistborn_on_actions.txt, and (2) a modifier-based
system (lord_ruler_attention_modifier) applied by some events/decisions. The
variable system is more robust and already has threshold-based event firing in
on_actions. The modifier system is used in improve_skaa_conditions_decision
(line 524-527 of decisions) and the smuggle_atium_decision (line 370 check).
These should be unified on the variable system.
Steps:
-
Remove the generic
lord_ruler_attention_modifierfromcommon/modifiers/00_mistborn_modifiers.txt(lines 23-25). Keep the tiered modifiers (lord_ruler_attention_1/2/3) as they are applied by the attention threshold events. -
In
common/decisions/00_mistborn_decisions.txt:improve_skaa_conditions_decision(line 524): Replaceadd_character_modifier = { modifier = lord_ruler_attention_modifier ... }withincrease_lord_ruler_attention_effect = yes.smuggle_atium_decision(line 370): Replace the checkhas_character_modifier = lord_ruler_attention_modifierwithhas_variable = lord_ruler_attentionandvar:lord_ruler_attention >= 25(checking if already under scrutiny).
-
Update the on_action yearly pulse attention threshold checks (
common/on_action/mistborn_on_actions.txtlines 27-63) to apply the tiered modifiers automatically:- When attention >= 25: apply
lord_ruler_attention_1(remove 2 and 3) - When attention >= 60: apply
lord_ruler_attention_2(remove 1 and 3) - When attention >= 90: apply
lord_ruler_attention_3(remove 1 and 2) - When attention < 25: remove all three modifiers
This connects the variable thresholds to the modifier effects, giving players visible feedback.
- When attention >= 25: apply
-
Verify no other files reference
lord_ruler_attention_modifier. Search all.txtfiles in the mod for this string and update any remaining references.
Files:
common/modifiers/00_mistborn_modifiers.txt-- modify (remove generic modifier)common/decisions/00_mistborn_decisions.txt-- modifycommon/on_action/mistborn_on_actions.txt-- modify
References:
- Variable system:
common/scripted_effects/mistborn_effects.txt:44-99 - Threshold events:
common/on_action/mistborn_on_actions.txt:27-63 - Modifier definitions:
common/modifiers/00_mistborn_modifiers.txt:59-90
1.5 -- Suppress Vanilla Decisions
Context: As a total conversion mod, vanilla CK3 decisions (feasts, hunts,
pilgrimages, grand weddings, etc.) should not appear in the decision list.
CK3 mods suppress vanilla content by creating replacement files with the same
path that contain empty or no-op definitions. All files in common/decisions/
from the vanilla game that contain non-Mistborn decisions must be overridden.
Steps:
-
Identify the vanilla CK3 decision files. In version 1.18, the key vanilla decision files in
common/decisions/are:00_decisions.txt-- major decisions (found a kingdom, etc.)00_activity_decisions.txt-- feast, hunt, pilgrimage activities00_dlc_decisions.txt-- DLC-specific decisions00_major_decisions.txt-- form empire, etc.- Various numbered decision files
-
Create empty replacement files in
lords_of_ash/common/decisions/for each vanilla decision file that contains immersion-breaking content. The file must have the exact same filename as the vanilla file. The file content should be a comment explaining it is intentionally empty:# Vanilla decisions suppressed for Lords of Ash total conversion -
Key vanilla files to suppress (at minimum):
00_major_decisions.txt-- found kingdom, found holy order, etc.00_decisions.txt-- generic decisions- Activity decisions that reference feasts, hunts, pilgrimages
-
Do NOT suppress
00_coa_decisions.txtor decisions that are purely mechanical (succession, realm management) unless they reference anachronistic content. -
Test by loading the mod and checking the decision list -- only Mistborn decisions should appear.
Files:
common/decisions/00_major_decisions.txt-- create (empty suppression)common/decisions/00_decisions.txt-- create (empty suppression)common/decisions/00_activity_decisions.txt-- create (empty suppression)- Additional vanilla files as identified during testing
References:
- Existing mod decisions:
common/decisions/00_mistborn_decisions.txt:1-627 - Vanilla CK3 decision file names (check game installation directory)
1.6 -- Create Game Rule Infrastructure
Context: The MASTERPLAN specifies a Narrative Mode vs Sandbox Mode toggle that gates story events and certain decisions. M1 only needs the infrastructure -- the actual gating happens in M2 (Sandbox decision) and M5-M6 (narrative events). The game rule must appear on the game setup screen.
Steps:
- Create directory
lords_of_ash/common/game_rules/if it does not exist. - Create
lords_of_ash/common/game_rules/00_mistborn_game_rules.txtwith:mistborn_game_mode = { default = narrative_mode narrative_mode = { # Curated story arcs following the book's plot # Narrative events fire, some decisions restricted } sandbox_mode = { # Play any character, full freedom # "Discover Your Metallic Arts" decision available # Narrative events suppressed } } - Add localization keys to a new file
localization/english/mistborn_game_rules_l_english.yml:l_english: mistborn_game_mode:0 "Game Mode" mistborn_game_mode_desc:0 "Choose between a curated Mistborn story experience or an open sandbox." mistborn_game_mode_narrative_mode:0 "Narrative Mode" mistborn_game_mode_narrative_mode_desc:0 "Experience the story of Mistborn: The Final Empire. Curated events will fire based on story progression. Recommended for first playthrough." mistborn_game_mode_sandbox_mode:0 "Sandbox Mode" mistborn_game_mode_sandbox_mode_desc:0 "Play as any character with full freedom. The 'Discover Your Metallic Arts' decision is available. Narrative story events are suppressed." - Create a scripted trigger
is_narrative_mode_triggerincommon/scripted_triggers/mistborn_triggers.txtthat checks the game rule:is_narrative_mode_trigger = { has_game_rule = mistborn_game_mode_narrative_mode } is_sandbox_mode_trigger = { has_game_rule = mistborn_game_mode_sandbox_mode } - Verify the game rule appears on the setup screen when starting a new game.
Files:
common/game_rules/00_mistborn_game_rules.txt-- createlocalization/english/mistborn_game_rules_l_english.yml-- createcommon/scripted_triggers/mistborn_triggers.txt-- modify (add mode triggers)
References:
- CK3 game rule syntax:
game_rule_name = { default = X option_1 = { } option_2 = { } } - Localization pattern:
localization/english/mistborn_*_l_english.yml
1.7 -- Validate Localization Coverage for New Content
Context: Any new modifiers, game rules, triggers, or suppressed content
must have matching localization entries. Missing localization causes [KEY]
display errors in-game.
Steps:
- Verify all modifier names in
00_mistborn_modifiers.txthave localization keys inmistborn_modifiers_l_english.yml. Check for:lord_ruler_attention_1,lord_ruler_attention_2,lord_ruler_attention_3ruin_influence,steel_inquisitor_powergreat_house_status,atium_supplyash_blight,koloss_rampagecompounder_modifier,steel_ministry_favor,steel_ministry_displeasurebreeding_for_allomancy_modifier,disapproves_skaa_mercy
- If the removed
lord_ruler_attention_modifierhas a localization key, remove it to prevent orphaned entries. - Add any missing localization keys for new content created in this milestone (game rules, new triggers do not need localization, but game rule options do).
- Ensure all
.ymlfiles have UTF-8 BOM encoding (the first bytes must beEF BB BF).
Files:
localization/english/mistborn_modifiers_l_english.yml-- modifylocalization/english/mistborn_game_rules_l_english.yml-- validate (created in 1.6)
References:
- Existing localization:
localization/english/mistborn_modifiers_l_english.yml - Modifier definitions:
common/modifiers/00_mistborn_modifiers.txt
Testing Checkpoints
-
After 1.1 (Province History):
- Test: Launch the mod, start a new game at 1020.1.1, inspect any county.
- Expected: Province shows correct culture (e.g., Luthadel = noble_scadrian),
correct religion (steel_ministry), and correct holding type. No "missing
province history" errors in
error.log.
-
After 1.3 (Triggers):
- Test: Open console, check a character with
trait_feruchemy_potential. Verifyis_feruchemist_triggerreturns NO for that character (should only match activetrait_feruchemist). - Expected: Dormant potential characters are not flagged as active Feruchemists.
- Test: Open console, check a character with
-
After 1.4 (Unified Attention):
- Test: Use console to set
lord_ruler_attentionvariable to 30 on a character. Advance 1 year. Check iflord_ruler_attention_1modifier appears. - Expected: Tier 1 modifier is visible on the character. Variable and modifier are in sync.
- Test: Use console to set
-
After 1.5 (Vanilla Suppression):
- Test: Start a new game, open the decision menu.
- Expected: Only Mistborn-themed decisions appear. No "Host a Feast", "Go on a Pilgrimage", or "Found a Holy Order" options.
-
After 1.6 (Game Rules):
- Test: Start a new game from the main menu.
- Expected: "Game Mode" option appears on the game setup screen with "Narrative Mode" and "Sandbox Mode" choices.
-
After all tasks (Full Boot Test):
- Test: Load the mod, start as Devinshae Venture (900001), play 5 years at speed 5.
- Expected: No crashes.
error.logis clean (no errors, warnings acceptable only for missing vanilla content we intentionally suppressed). Lord Ruler attention events fire if attention rises. Snapping events fire for children with potential. Province data is correct on the map.
Acceptance Criteria
- The mod loads with no errors in
error.log(warnings for vanilla content suppression are acceptable). - All 105 provinces display correct culture, religion, and holding type at game start.
- Province history IDs match the vanilla province IDs referenced in
common/landed_titles/00_landed_titles.txt. - No vanilla decisions appear in the decision menu.
- The "Game Mode" game rule appears on the setup screen with Narrative and Sandbox options.
is_feruchemist_triggerreturns false for characters with onlytrait_feruchemy_potential.has_allomantic_potential_triggerreturns false for characters who have already snapped into active Allomancers.- Lord Ruler attention modifiers (tiers 1-3) are applied automatically based on the attention variable thresholds.
- No references to the old
lord_ruler_attention_modifierremain in any file. - Culture pillars load without errors.
- Playing as any landed character for 5 years produces no crashes.
- All localization keys for modifiers, game rules, and decisions resolve
correctly (no
[KEY]display).
Risks & Mitigations
-
Province ID mapping errors. If any vanilla province ID is wrong, the barony will have no culture/religion. Mitigation: Programmatically extract all province IDs from
00_landed_titles.txtand cross-reference. -
Vanilla decision suppression scope. We may miss vanilla decision files, causing some to leak through. Mitigation: Check the CK3 game directory for all files in
common/decisions/and create suppressions iteratively after testing. -
Game rule syntax changes. CK3 1.18 may have changed game rule syntax from earlier versions. Mitigation: Cross-reference with CK3 1.18 documentation or inspect vanilla game rule files.
-
Culture pillar validation. The vanilla
heritage_is_shown_triggerandlanguage_is_shown_triggermay not exist in CK3 1.18 or may have different names. Mitigation: Check vanilla culture pillar files for current syntax.
Open Questions
-
Should we suppress ALL vanilla decisions or only clearly anachronistic ones (feasts, hunts, pilgrimages)? Some mechanical decisions (e.g., disinherit heir) may still be useful. Decision needed on scope of suppression.
-
The province history currently assigns
culture = noble_scadrianto most provinces andculture = skaato some labor/slum provinces. Should Terris provinces (24-25, 27-29, 31, 33 in the old system, now d_tathingdwen/ d_urteau area) havereligion = terris_worldbringersinstead ofsteel_ministry? Lore says the Lord Ruler publicly suppressed Terris faith, sosteel_ministrymay be correct with characters secretly following Terris Worldbringers. -
Should we create a
common/on_action/file that runs a game-start initialization effect to set up variables, flags, and initial conditions beyond what currently exists inon_game_start? This would be useful for M2 and beyond.