-
Notifications
You must be signed in to change notification settings - Fork 1
Tutorial Per Individual Fields
Give each individual monster its own extra state -- a grade, a variant type, a tint, a mark -- beyond what its species defines. You declare the fields once; the engine validates every producer against your declaration, carries the values through saves, trades, and link battles, and feeds them to your stat and palette hooks.
1. Declare the fields in data/ruleset.json:
{"mon_fields": {
"grade": {"type": "integer", "minimum": 0, "maximum": 5},
"delta_type": {"type": "string"},
"shiny_mark": {"type": "boolean"}
}}Each field is a schema fragment. Everything below is checked against it -- a typo'd field name or an out-of-range value refuses at --validate, again at load, and the engine never half-applies.
2. Author it on content. Any surface that produces an individual takes an ext block:
{"cmd": "give_mon", "species": "species:cindercub", "level": 5,
"ext": {"grade": 3}}The same block works on wild_battle commands, on encounter-group entries (every wild rolled from that entry carries it -- grass rolls and visible overworld spawns alike), and on trainer party members, which also accept pinned dvs and sexp bags (and ivs/evs/nature if your project declares mon_wire: 2):
{"species": "species:galewisp", "level": 18,
"dvs": {"atk": 15, "spd": 15}, "ext": {"grade": 4}}3. Write it from a story. The set_mon_ext command (or the same call inside a HatchScript event) changes a party member's field -- the appraisal booth, the fusion altar, the grading ceremony:
let g = get_mon_ext(0, "grade")
if g < 5 { set_mon_ext(0, "grade", g + 1) }
Reads answer the field's type default (0/false/"") until something writes it. Writes queue with the event's other commands, so a failing script never half-writes, and stats recompute immediately -- a graded mon grows the moment the ceremony ends.
4. Roll it at birth. Bind the on_mon_created formula kernel and every new individual -- wild, gift, trainer's, starter, traded-in -- rolls your fields when it's created:
{"formula_scripts": {"on_mon_created": "script:birth_roll"}}# script:birth_roll — a rare mark, a graded wild
if rand_int(64) == 0 { out("shiny_mark", true) }
if provenance == "wild" { out("grade", rand_int(3)) }
The script sees species, level, provenance, and the rolled dv_* values; rand_int(n) draws from a dedicated stream seeded off the run seed -- the same run rolls the same individuals, and your rolls never disturb battles, spawns, or anything else. An authored ext block on the same surface beats the roll.
5. Consume it. stat_base_scale reads every declared field as ext_<name> (Modern Individuals shows verifying it with --statread), the sprite-variant ladder reads ext.palette (Sprite Variants), and an effective_types kernel can rewrite an individual's typing from its ext -- resolved once into the types field that damage, STAB, immunities, the AI, and Transform all read, so a "Delta" variant type-shifts everywhere at once:
# script:delta_typing — replace the primary, keep the secondary
if ext_delta_type != "" { out("type1", ext_delta_type) }
out("type2", type2)
All of it rides the mon record through saves, trades, and link play -- both peers always compute the same stats and the same typing from the same individual.
Monworks: MIT code · CC0 samples · everything pictured is original content. The faithful Pokémon Red build derives from your own local pokered clone and is never distributed. Pokémon is © Nintendo/Creatures/GAME FREAK; this is an unaffiliated fan engineering project.
Play
Create
Tutorials
- Writing Text
- Battle Backdrops
- Colors and Palettes
- Display Filters and Shaders
- Widescreen and Scaling
- Quality-of-Life Knobs
- Overlays (Recipes)
- Abilities & Battle Hooks
- Modern Individuals
- Per-Individual Fields
- Item Field Scripts
- Field Effects
- The Modern Ruleset
- Per-Save Rulesets
- Six Stats
- The Clock
- Conditioned Bindings
- Day and Night
- Sprite Variants
- Overworld Spawns
- Language Packs
- Set-Piece Battles & Narration
- Run a Server
- Join a Server
Elsewhere