Tiny Moddable Feature
This chapter eases you into implementing a tiny moddable feature. The first goal is not to write clever Rust. The first goal is to learn the path a small idea takes through EchoWarrior.
We start with the safest possible feature: a new level-up card that uses existing data fields and existing commands.
The Tiny Feature Shape
Section titled “The Tiny Feature Shape”flowchart LR idea[Idea] data[Assets/Data entry] existing[Existing loader and command] validate[mod_check] pack[asset_pack list] run[cargo run smoke test]
idea --> data --> existing --> validate --> pack --> runThis is the best first contribution shape because it teaches the architecture without changing the architecture.
The Question To Ask First
Section titled “The Question To Ask First”Can the feature be expressed with existing data?
flowchart TD feature[Feature idea] existing{Existing schema or command supports it?} dataonly[Data-only contribution] rust[Small Rust-backed contribution] docs[Document the surface]
feature --> existing existing -- yes --> dataonly --> docs existing -- no --> rust --> docsFor a first feature, prefer “yes”.
Good First Tiny Features
Section titled “Good First Tiny Features”| Feature idea | Likely path |
|---|---|
| new level-up card using existing stats | Assets/Data/upgrades.toml |
| new item using existing stat effects | Assets/Data/items.toml |
| new companion banter line | Assets/Data/companions.toml |
| small spawn tweak | Assets/Scripts/spawn.d/*.lua |
| new scene beat using existing choreography verbs | Assets/Data/scenes/*.toml |
| clearer mod_check error wording | src/bin/mod_check.rs |
When Rust Becomes Necessary
Section titled “When Rust Becomes Necessary”Rust is needed when the idea asks for a new rule, not just new content.
flowchart TD idea[New idea] newstat{New stat/effect key?} newcommand{New command verb?} newbeat{New choreography beat?} data[Data-only] rust[Rust model + apply layer + validation]
idea --> newstat newstat -- yes --> rust newstat -- no --> newcommand newcommand -- yes --> rust newcommand -- no --> newbeat newbeat -- yes --> rust newbeat -- no --> dataIf Rust is needed, the slice grows:
- add or update the data model
- load with defaults
- apply in pure code or runtime
- validate with
mod_check - document in
Docs/MODDING.md - verify asset-pack discovery if assets changed
First Exercise
Section titled “First Exercise”Read these in order:
- Example: Upgrade Card for a data-only level-up card.
- Example: Item Equipment for a persistent gear entry.
- Example: Spawn Layer for a tiny additive Lua layer.
- Example: Mini Dialogue for a lightweight narrative cue.
- Example: Scene Beat for a manual choreography scene.
- Example: Mod Check Diagnostic for improving contributor tooling.
- Tiny Rust-Backed Stat for the first moment when existing data is not enough.
Keep the first attempt tiny. A small clean slice teaches more than a large half-finished one.