diff --git a/docs/datafiles/ingame_trades.md b/docs/datafiles/ingame_trades.md new file mode 100644 index 0000000000..48115af940 --- /dev/null +++ b/docs/datafiles/ingame_trades.md @@ -0,0 +1,63 @@ +# In-Game Trade Data File Format + +This document describes the file format for in-game trade data consumed by the +`npctradeproc` build tool. Each NPC trade in the ROM is represented by a JSON +file `res/npc_trades/.json`, which contains metadata for the in-game trade +event and the received Pokémon. The fields from each of these files are mapped +onto the `NPCTradeMon` struct from `include/overlay006/npc_trade.h`. + +## Schema + +| Field | Type | Description | +| -------------------- | ------------------------- | --------------------------------------------------------------- | +| `name` | `string` | The Pokémon's nickname after the trade. | +| `otName` | `string` | The Original Trainer's name (max 7 characters). | +| `species` | `enum Species` | The species of the Pokémon being offered. | +| `hpIV` | `u8` (0–31) | HP Individual Value (stored in 5 bits). | +| `atkIV` | `u8` (0–31) | Attack Individual Value (stored in 5 bits). | +| `defIV` | `u8` (0–31) | Defense Individual Value (stored in 5 bits). | +| `speedIV` | `u8` (0–31) | Speed Individual Value (stored in 5 bits). | +| `spAtkIV` | `u8` (0–31) | Special Attack Individual Value (stored in 5 bits). | +| `spDefIV` | `u8` (0–31) | Special Defense Individual Value (stored in 5 bits). | +| `unused1` | `u32` | Unused field. Present in the retail ROM. | +| `otID` | `u32` | The Original Trainer's ID number. | +| `cool` | `u32` | Cool contest condition value. | +| `beauty` | `u32` | Beauty contest condition value. | +| `cute` | `u32` | Cute contest condition value. | +| `smart` | `u32` | Smart contest condition value. | +| `tough` | `u32` | Tough contest condition value. | +| `personality` | `u32` | Personality value, which determines gender, ability, and nature.| +| `heldItem` | `enum Item` | The item held by the Pokémon. | +| `otGender` | `enum Gender` | The gender of the Original Trainer. | +| `unused2` | `u32` | Unused field. Present in the retail ROM. | +| `language` | `enum Language` | The language of the Original Trainer. | +| `requestedSpecies` | `enum Species` | The species required in exchange for the trade. | + +## Example + +```json +{ + "name": "Kazza", + "otName": "Hilary", + "species": "SPECIES_ABRA", + "hpIV": 15, + "atkIV": 15, + "defIV": 15, + "speedIV": 20, + "spAtkIV": 25, + "spDefIV": 25, + "unused1": 28, + "otID": 25643, + "cool": 0, + "beauty": 0, + "cute": 0, + "smart": 0, + "tough": 0, + "personality": 142, + "heldItem": "ITEM_ORAN_BERRY", + "otGender": "GENDER_FEMALE", + "unused2": 0, + "language": "LANGUAGE_ENGLISH", + "requestedSpecies": "SPECIES_MACHOP" +} +``` diff --git a/docs/datafiles/items.md b/docs/datafiles/items.md new file mode 100644 index 0000000000..1c853ed0c6 --- /dev/null +++ b/docs/datafiles/items.md @@ -0,0 +1,166 @@ +# Item Data File Format + +This document describes the file format for item data consumed by the `itemproc` +build tool. Each item in the ROM is represented by a JSON file +`res/items/data/.json`. Fields from each of these files are mapped onto +the `ItemData` struct from `include/item.h` and the `BerryData` struct from +`include/berry_data.h`. + +Bogus items in the retail ROM—those with the `ITEM_UNUSED_` prefix—do not have +corresponding JSON files. They are assigned placeholder text in the output, but +they do not produce a data entry. + +## Schema + +| Field | Type | Description | +| -------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------- | +| `name` | `string` | The item's display name (singular). | +| `plural` | `string` | The item's display name (plural). | +| `article` | `string` | Indefinite article (e.g. "a", "an") for in-game text. | +| `description` | `string[]` | The item's description, as an array of lines. | +| `icon` | `object` | References to the item's icon graphics. See below. | +| `gbaID` | `string` | The corresponding Gen-III item identifier, or `GBA_ITEM_NONE` for Gen-IV items. | +| `price` | `u16` | Base price in Pokédollars paid when purchasing from a shop. `0` means the item cannot be sold. | +| `effectParam` | `u8` | Generic parameter; semantics vary by item type (e.g., heal amount). | +| `holdEffect` | `enum ItemHoldEffect` | Effect when held by a Pokémon. | +| `pluckEffect` | `define PLUCK_EFFECT` | Effect when consumed by Bug Bite / Pluck. | +| `flingEffect` | `define FLING_EFFECT` | Effect when used with Fling. | +| `flingPower` | `u8` | Base power of Fling when this item is flung. | +| `naturalGiftPower` | `u8` | Base power of Natural Gift when this item is held. 0 if not a berry. | +| `naturalGiftType` | `enum PokemonType` or `null` | Type of Natural Gift when this item is held. `null` if not a berry. | +| `preventToss` | `bool` | If `true`, then the item cannot be tossed or sold. | +| `canRegister` | `bool` | If `true`, then the item can be registered to the `Y` button. | +| `fieldPocket` | `define POCKET` | The Bag pocket the item belongs to (Items, Medicine, etc.). | +| `battlePocket` | `define BATTLE_POCKET_MASK` | The battle pocket mask for use during battle. | +| `fieldUseFunc` | `define ITEM_USE_FUNC` | The field-use function invoked from the overworld. | +| `battleUseFunc` | `u8` | The battle-use function invoked from the battle menu. | +| `itemUseParams` | `object` or `null` | Detailed usage parameters. See below. | +| `teachesMove` | `enum Move` | The move taught by this TM or HM (only for TMs/HMs). | +| `berryData` | `object` | Berry growth and flavor data (only for berries). See below. | + +### The `icon` Object + +| Field | Type | Description | +| --------- | -------- | ---------------------------------------------------- | +| `sprite` | `string` | Name of the NCGR sprite resource for the item icon. | +| `palette` | `string` | Name of the NCLR palette resource for the item icon. | + +These fields map to the in-game files produced from the inputs in +`res/items/icons`. + +### The `itemUseParams` Object + +This object defines the parameters for items that act on a Pokémon in the party +or in battle. All fields are optional and default to `0` or `false`. + +| Field | Type | Description | +| ------------------- | ------- | ---------------------------------------------------------------- | +| `healSleep` | `bool` | Cures sleep. | +| `healPoison` | `bool` | Cures poison. | +| `healBurn` | `bool` | Cures burn. | +| `healFreeze` | `bool` | Cures freeze. | +| `healParalysis` | `bool` | Cures paralysis. | +| `healConfusion` | `bool` | Cures confusion. | +| `healAttract` | `bool` | Cures infatuation. | +| `guardSpec` | `bool` | Temporarily protects from stat reduction. | +| `revive` | `bool` | Revives a fainted Pokémon. | +| `reviveAll` | `bool` | Revives all fainted Pokémon. | +| `levelUp` | `bool` | Increases the Pokémon's level by one. | +| `ppUp` | `bool` | Increases a move's PP. | +| `ppMax` | `bool` | Maximizes a move's PP. | +| `restorePPAllMoves` | `bool` | Restores PP to all moves. | +| `atkStages` | `u8` | Attack stage change (0–4). | +| `defStages` | `u8` | Defense stage change (0–4). | +| `spatkStages` | `u8` | Special Attack stage change (0–4). | +| `spdefStages` | `u8` | Special Defense stage change (0–4). | +| `speedStages` | `u8` | Speed stage change (0–4). | +| `accStages` | `u8` | Accuracy stage change (0–4). | +| `critStages` | `u8` | Critical-hit ratio stage change (0–2). | +| `hpRestored` | `s8` | HP restored. Use `-1` for 100%, `-2` for 50%, or `-3` for 25%. | +| `ppRestored` | `s8` | PP restored. Use `-1` for 100%. | +| `hpEVs` | `s8` | HP EVs gained. | +| `atkEVs` | `s8` | Attack EVs gained. | +| `defEVs` | `s8` | Defense EVs gained. | +| `speedEVs` | `s8` | Speed EVs gained. | +| `spatkEVs` | `s8` | Special Attack EVs gained. | +| `spdefEVs` | `s8` | Special Defense EVs gained. | +| `friendshipLow` | `s8` | Friendship change when friendship < 100. | +| `friendshipMed` | `s8` | Friendship change when 100 ≤ friendship < 200. | +| `friendshipHigh` | `s8` | Friendship change when friendship ≥ 200. | + +When `fieldUseFunc` is set to `ITEM_USE_FUNC_BERRY`, `ITEM_USE_FUNC_EVO_STONE`, +`ITEM_USE_FUNC_HEALING`, or any other use function that acts on a party Pokémon, +this object is optional but will be used if present. + +### The `berryData` Object + +| Field | Type | Description | +| ------------------- | ---------------------- | ------------------------------------------------------ | +| `size` | `u16` | Size of the berry in millimeters. | +| `firmness` | `define FIRMNESS` | Firmness category (Very Soft through Super Hard). | +| `baseYield` | `u8` | Base yield per plant. | +| `stageDuration` | `u8` | Number of stages to grow. | +| `moistureDrainRate` | `u8` | How quickly moisture drains. | +| `spiciness` | `u8` | Spicy flavor value. | +| `dryness` | `u8` | Dry flavor value. | +| `sweetness` | `u8` | Sweet flavor value. | +| `bitterness` | `u8` | Bitter flavor value. | +| `sourness` | `u8` | Sour flavor value. | +| `smoothness` | `u8` | Smoothness for Poffin cooking. | + +This field is only recognized when `fieldUseFunc` is `ITEM_USE_FUNC_BERRY`. + +## Outputs + +The tool produces the following outputs: + +| Output | Description | +| ------------------------------- | -------------------------------------------------------------------- | +| `pl_item_data.narc` | `ItemData` entries for every item, packed by index ID. | +| `item_id_map.h` | Maps item IDs to data index, icon resource, palette, and Gen-III ID. | +| `item_tm_move_map.h` | Maps TM indices to the move they teach. | +| `item_berry_list.h` | Lists all berry items by their berry index. | +| `item_mail_list.h` | Lists all mail items by their mail type index. | +| `item_names.json` | Text bank for singular item names. | +| `item_names_plural.json` | Text bank for plural item names. | +| `item_names_with_articles.json` | Text bank for item names with their indefinite article. | +| `item_descriptions.json` | Text bank for item descriptions. | +| `hidden_item_scripts.h` | Generated header mapping hidden item script IDs to script entries. | +| `nuts_data.narc` | `BerryData` entries for each in-game berry. | + +## Example + +```json +{ + "name": "Potion", + "plural": "Potions", + "article": "a", + "description": [ + "A spray-type medicine for wounds.\n", + "It restores the HP of one Pokémon by\n", + "just 20 points." + ], + "icon": { + "sprite": "potion_NCGR", + "palette": "potion_NCLR" + }, + "gbaID": "GBA_ITEM_POTION", + "price": 300, + "effectParam": 20, + "holdEffect": "HOLD_EFFECT_NONE", + "pluckEffect": "PLUCK_EFFECT_NONE", + "flingEffect": "FLING_EFFECT_NONE", + "flingPower": 30, + "naturalGiftPower": 0, + "naturalGiftType": null, + "preventToss": false, + "canRegister": false, + "fieldPocket": "POCKET_MEDICINE", + "battlePocket": "BATTLE_POCKET_MASK_RECOVER_HP", + "fieldUseFunc": "ITEM_USE_FUNC_HEALING", + "battleUseFunc": 2, + "itemUseParams": { + "hpRestored": 20 + } +} +``` diff --git a/docs/datafiles/pokemon.md b/docs/datafiles/pokemon.md new file mode 100644 index 0000000000..d81a941276 --- /dev/null +++ b/docs/datafiles/pokemon.md @@ -0,0 +1,361 @@ +# Pokémon Data File Format + +This document describes the file format for Pokémon species data consumed by the +`speciesproc` build tool. Each species in the ROM is represented by a directory +`res/pokemon/` which must contain the following files: + +| File | Purpose | +| ------------------ | -------------------------------------------------------------- | +| `data.json` | Internal metadata (stats, types, learnsets, evolutions, etc.) | +| `sprite_data.json` | Sprite offset, shadow, and animation data (National Dex only) | + +Some alternate forms have their own input data due to differing base stats, +types, or abilities. In the retail ROM, this includes forms for: + +1. Deoxys +2. Wormadam +3. Shaymin +4. Giratina +5. Rotom + +Each such form has a corresponding subdirectory under their species parent, e.g. +`giratina/forms/origin`. These forms have a similar `data.json` file, but they +do not have a `sprite_data.json` file. + +## `data.json` — Internal Metadata + +The JSON fields from this file map onto the `SpeciesData`, `SpeciesEvolution`, +`SpeciesLearnset`, and `SpeciesPalPark` structs from +`include/struct_defs/species.h`. + +### Schema + +| Field | Type | Description | +| ------------------- | -------------------- | ----------------------------------------------------------------------------------------------- | +| `base_stats` | `object` | Base stat values (HP, Attack, Defense, Speed, Sp. Atk, Sp. Def). | +| `types` | `enum PokemonType[]` | The species' primary and secondary types (2 elements). | +| `catch_rate` | `u8` | Catch rate (0–255). | +| `base_exp_reward` | `u8` | Base experience yield on defeat. | +| `ev_yields` | `object` | EV yield values (2-bit each) for each stat. | +| `held_items.common` | `enum Item` | The common wild held item (20%). | +| `held_items.rare` | `enum Item` | The rare wild held item (5%). | +| `gender_ratio` | `enum GenderRatio` | Gender ratio of the species. | +| `hatch_cycles` | `u8` | Number of hatch cycles (255 x cycle length). | +| `base_friendship` | `u8` | Base friendship level. | +| `exp_rate` | `enum ExpRate` | Level-up experience curve. | +| `egg_groups` | `enum EggGroup[]` | Egg groups for breeding (2 elements). | +| `abilities` | `enum Ability[]` | Slot 1 and slot 2 abilities (2 elements). | +| `safari_flee_rate` | `u8` | Safari Zone flee rate. | +| `body_color` | `enum PokemonColor` | Pokédex body color. | +| `flip_sprite` | `bool` | Whether the in-battle sprite should be flipped horizontally in menus (like the summary screen). | +| `icon_palette` | `u8` or `array` | Icon palette index; array of `[form_name, index]` tuples for species with per-form palettes. | +| `learnset` | `object` | Learnset data (level-up, TM/HM, tutor, egg moves). See below. | +| `evolutions` | `array` | Evolution methods and targets. | +| `offspring` | `enum Species` | The species produced when breeding (usually self). | +| `footprint` | `object` | Footprint data for the Pokédex. | +| `pokedex_data` | `object` | Pokédex entry text, height, weight, body shape, and sprite scales/positions. | +| `catching_show` | `object` | Pal Park encounter data. | + +#### The `learnset` Object + +| Field | Type | Description | +| ---------- | ------------- | ------------------------------------------------------------------------- | +| `by_level` | `array` | Level-up learnset: array of `[level, move]` tuples. | +| `by_tm` | `string[]` | TM/HM compatibility: array of TM or HM markers (e.g. `"TM01"`, `"HM04"`). | +| `by_tutor` | `enum Move[]` | Moves teachable by move tutors. | +| `egg_moves`| `enum Move[]` | Moves available as egg moves (optional). | + +If a move listed in the `by_tutor` array is not teachable by any move tutor in +the game, then a warning will be emitted, and that move will be skipped. + +No validation is performed against `egg_moves` due to the potential cost of +analyzing every other member of each egg group. + +#### The `evolutions` Array + +Each element is a tuple describing one evolution path: + +| Index | Type | Description | +| ----- | ---------------------- | ---------------------------------------------------------------------- | +| 0 | `enum EvolutionMethod` | The evolution method (level, trade, item, etc.) | +| 1 | varies | The parameter for the method (level, item, move, species, or nothing). | +| 2 | `enum Species` | The target species to evolve into. | + +The parameter type depends on the method: + +- For `EVO_LEVEL`, `EVO_LEVEL_ATK_GT_DEF`, etc., it is the level at which the + evolution should trigger. +- For `EVO_USE_ITEM`, `EVO_TRADE_WITH_HELD_ITEM`, etc., it is the `enum Item` + required to be held or used to trigger the evolution. +- For `EVO_LEVEL_KNOW_MOVE`, it is an `enum Move` which must be known for the + next level-up to trigger the evolution. +- For `EVO_LEVEL_SPECIES_IN_PARTY`, it is an `enum Species` which must be + present in the party for the next level-up to trigger the evolution. +- For `EVO_NONE`, `EVO_LEVEL_HAPPINESS`, `EVO_TRADE`, there is no listed + parameter, and the evolution only has two elements: `[method, species]`. + +#### The `footprint` Object + +| Field | Type | Description | +| ------ | ----------------------- | --------------------------------------------------- | +| `has` | `bool` | Whether the species has a footprint in the Pokédex. | +| `size` | `enum FootprintSize` | The relative size of the footprint. | +| `type` | `define FOOTPRINT_TYPE` | The footprint type (e.g. Cute, Scary, etc.). | + +#### The `pokedex_data` Object + +Height and weight may be specified in either metric or imperial units, but not +both. + +| Field | Type | Description | +| ------------------ | ----------------------- | -------------------------------------------------------- | +| `height_meters` | `float` | Height in meters (alternative to `height_inches`). | +| `height_inches` | `u32` | Height in inches (alternative to `height_meters`). | +| `weight_kilograms` | `float` | Weight in kilograms (alternative to `weight_pounds`). | +| `weight_pounds` | `float` | Weight in pounds (alternative to `weight_kilograms`). | +| `body_shape` | `enum PokemonBodyShape` | Pokédex body shape category. | +| `trainer_scale_f` | `u16` | Trainer back-sprite scale (female). | +| `pokemon_scale_f` | `u16` | Pokémon front-sprite scale (female). | +| `trainer_scale_m` | `u16` | Trainer back-sprite scale (male). | +| `pokemon_scale_m` | `u16` | Pokémon front-sprite scale (male). | +| `trainer_pos_f` | `u16` | Trainer back-sprite Y-position offset (female). | +| `pokemon_pos_f` | `u16` | Pokémon front-sprite Y-position offset (female). | +| `trainer_pos_m` | `u16` | Trainer back-sprite Y-position offset (male). | +| `pokemon_pos_m` | `u16` | Pokémon front-sprite Y-position offset (male). | +| `origin_forme` | `object` | Alternate-forme Pokédex data (Giratina only). See below. | +| `en`, `fr`, `etc.` | `object` | Localized Pokédex data. See below. | + +The `origin_forme` sub-object uses the same schema as the top-level +`pokedex_data` (height, weight, body shape, scales, and positions) and is only +present for Giratina to support its Origin Forme. + +Each language sub-object has the following fields: + +| Field | Type | Description | +| ------------ | ---------- | --------------------------------------------- | +| `name` | `string` | The species name in that language. | +| `category` | `string` | The species category (e.g. "Lizard Pokémon"). | +| `entry_text` | `string[]` | The Pokédex entry text, as an array of lines. | + +#### The `catching_show` Object + +| Field | Type | Description | +| --------------------- | ----------------------- | ---------------------------------------- | +| `pal_park_land_area` | `enum PalParkLandArea` | Pal Park land area assignment. | +| `pal_park_water_area` | `enum PalParkWaterArea` | Pal Park water area assignment. | +| `catching_points` | `u8` | Catching show points awarded. | +| `rarity` | `u8` | Rarity score for the catching show. | +| `unused` | `u16` | Unused field. Present in the retail ROM. | + +## `sprite_data.json` — Sprite Offsets and Animation Data + +This file is only processed for species present in the National Pokédex (that +is, those with an ID less than `SPECIES_EGG`) and defines the battle sprite +layout and some animation parameters. + +| Field | Type | Description | +| -------- | -------- | ---------------------------------------------- | +| `front` | `object` | Front-face sprite animation and Y-offset data. | +| `back` | `object` | Back-face sprite animation and Y-offset data. | +| `shadow` | `object` | Shadow sprite position and size. | + +### The `front` and `back` Objects + +| Field | Type | Description | +| --------------- | ---------- | -------------------------------------------------------- | +| `y_offset` | `object` | Per-gender Y-offsets for the sprite (`male` / `female`). | +| `addl_y_offset` | `s8` | Additional Y-offset (front only). | +| `animation` | `u8` | Pre-programmed animation sequence ID. | +| `cry_delay` | `u8` | Frames to wait before playing the cry. | +| `start_delay` | `u8` | Frames to wait before starting the animation. | +| `frames` | `object[]` | Array of animation frame definitions (up to 10 frames). | + +#### The `frame` Objects + +| Field | Type | Description | +| -------------- | ---- | ------------------------------------- | +| `sprite_frame` | `s8` | Sprite frame index (`-1` = no frame). | +| `frame_delay` | `u8` | Duration of this frame in ticks. | +| `x_shift` | `s8` | Horizontal shift for this frame. | +| `y_shift` | `s8` | Vertical shift for this frame. | + +### The `shadow` Object + +| Field | Type | Description | +| ---------- | ----------------- | --------------------------------------- | +| `x_offset` | `s8` | Horizontal offset of the shadow sprite. | +| `size` | `enum ShadowSize` | Size category of the shadow sprite. | + +### Outputs + +The tool produces the following outputs: + +| Output | Description | +| ---------------------------------------- | ----------------------------------------------------------------- | +| `pl_personal.narc` | `SpeciesData` entries for every species and alternate form. | +| `evo.narc` | `SpeciesEvolution` entries. | +| `wotbl.narc` | Level-up learnset entries for every species. | +| `height.narc` | Per-gender sprite Y-offsets (4 files per National Dex species). | +| `pl_poke_data.narc` | `SpeciesSpriteData` for all National Dex species. | +| `ppark.narc` | `SpeciesPalPark` data for all National Dex species. | +| `pms.narc` | Offspring species map (breeding species resolution). | +| `zukan_data(_gira).narc` | Data for the sorted Pokédex indices (by height, by weight, etc.). | +| `tutorable_moves.h` | Move tutor definitions and costs. | +| `species_learnsets_by_tutor.h` | Bitmask of tutorable moves per species. | +| `species_egg_moves.h` | Egg move lists per species. | +| `species_footprint_sizes.h` | Footprint size per species. | +| `species_footprint_types.h` | Footprint type per species. | +| `species_icon_palettes.h` | Icon palette index per species. | +| `species_name.json` | Text bank for species names. | +| `species_name_with_articles.json` | Text bank for species names with indefinite articles. | +| `species_pokedex_entry_*.json` | Text banks for Pokédex entries in 6 languages. | +| `species_name_with_natdex_number_*.json` | Text banks for species names with National Dex numbers. | +| `species_category*.json` | Text banks for species categories. | +| `species_weight*.json` | Text banks for Pokédex weight display. | +| `species_height*.json` | Text banks for Pokédex height display. | + +### Example + +```json +{ + "base_stats": { + "hp": 39, + "attack": 52, + "defense": 43, + "speed": 65, + "special_attack": 60, + "special_defense": 50 + }, + "types": [ "TYPE_FIRE", "TYPE_FIRE" ], + "catch_rate": 45, + "base_exp_reward": 65, + "ev_yields": { + "hp": 0, + "attack": 0, + "defense": 0, + "speed": 1, + "special_attack": 0, + "special_defense": 0 + }, + "held_items": { + "common": "ITEM_NONE", + "rare": "ITEM_NONE" + }, + "gender_ratio": "GENDER_RATIO_FEMALE_12_5", + "hatch_cycles": 20, + "base_friendship": 70, + "exp_rate": "EXP_RATE_MEDIUM_SLOW", + "egg_groups": [ "EGG_GROUP_MONSTER", "EGG_GROUP_DRAGON" ], + "abilities": [ "ABILITY_BLAZE", "ABILITY_NONE" ], + "safari_flee_rate": 0, + "body_color": "MON_COLOR_RED", + "flip_sprite": false, + "icon_palette": 0, + "learnset": { + "by_level": [ + [ 1, "MOVE_SCRATCH" ], + [ 1, "MOVE_GROWL" ], + [ 7, "MOVE_EMBER" ], + [ 10, "MOVE_SMOKE_SCREEN" ], + [ 16, "MOVE_DRAGON_RAGE" ] + ], + "by_tm": [ + "TM01", "TM02", "TM06", "TM10", + "HM01", "HM04", "HM06" + ], + "by_tutor": [ + "MOVE_MUD_SLAP", + "MOVE_FIRE_PUNCH", + "MOVE_SNORE" + ], + "egg_moves": [ + "MOVE_BELLY_DRUM", + "MOVE_OUTRAGE", + "MOVE_DRAGON_DANCE" + ] + }, + "evolutions": [ + [ "EVO_LEVEL", 16, "SPECIES_CHARMELEON" ] + ], + "offspring": "SPECIES_CHARMANDER", + "footprint": { + "has": true, + "size": "FOOTPRINT_MEDIUM", + "type": "FOOTPRINT_TYPE_CUTE" + }, + "pokedex_data": { + "height_inches": 24, + "weight_pounds": 18.7, + "body_shape": "SHAPE_BIPEDAL_TAILED", + "trainer_scale_f": 272, + "pokemon_scale_f": 384, + "trainer_scale_m": 256, + "pokemon_scale_m": 384, + "trainer_pos_f": 8, + "pokemon_pos_f": 23, + "trainer_pos_m": 9, + "pokemon_pos_m": 23, + "en": { + "name": "CHARMANDER", + "category": "Lizard Pokémon", + "entry_text": [ + "The fire on the tip of its tail is a\n", + "measure of its life. If healthy,\n", + "its tail burns intensely." + ] + }, + "fr": { + "name": "SALAMECHE", + "category": "Pokémon Lézard", + "entry_text": [ + "La flamme de sa queue symbolise sa\n", + "vitalité. Elle est intense quand il\n", + "est en bonne santé." + ] + }, + "de": { + "name": "GLUMANDA", + "category": "Echse", + "entry_text": [ + "Lodert die Flamme auf seiner\n", + "Schweifspitze hell, ist GLUMANDA\n", + "gesund." + ] + }, + "it": { + "name": "CHARMANDER", + "category": "Pokémon Lucertola", + "entry_text": [ + "La fiamma sulla punta della coda\n", + "indica la sua vitalità. Se sta bene,\n", + "la fiamma è più ardente." + ] + }, + "es": { + "name": "CHARMANDER", + "category": "Pokémon Lagartija", + "entry_text": [ + "La llama de la punta de su cola\n", + "indica su salud. Si CHARMANDER\n", + "está sano, arderá con más fuerza." + ] + }, + "jp": { + "name": "ヒトカゲ", + "category": "とかげポケモン", + "entry_text": [ + "ヒトカゲの しっぽの ほのおは\n", + "いのちの ともしび。げんきな ときは\n", + "ほのおも ちからづよく もえあがる。" + ] + } + }, + "catching_show": { + "pal_park_land_area": "PAL_PARK_AREA_LAND_SOUTH_WEST", + "pal_park_water_area": "PAL_PARK_AREA_WATER_NONE", + "catching_points": 50, + "rarity": 30, + "unused": 514 + } +} +``` diff --git a/docs/datafiles/trainers.md b/docs/datafiles/trainers.md new file mode 100644 index 0000000000..2957d9212a --- /dev/null +++ b/docs/datafiles/trainers.md @@ -0,0 +1,231 @@ +# Trainer Data File Format + +This document describes the file format for trainer data consumed by the +`trainerproc` build tool. Each trainer in the ROM is represented by a JSON file +`res/trainers/data/.json`, which contains metadata for the trainer and +their party. The fields from each of these files are mapped onto the structs +defined in `include/struct_defs/trainer_data.h`. + +## Top-Level Schema + +| Field | Type | Description | +| --------------- | ----------------------------- | ---------------------------------------------------------------- | +| `name` | `string` | The trainer's display name. | +| `class` | `enum TrainerClass` | The trainer class, e.g. Youngster, Ace Trainer, Gym Leader. | +| `items` | `enum Item[]` | Items usable by the trainer in battle (up to 4). May be empty. | +| `ai_flags` | `enum AIFlag[]` | AI behavior flags for battle scripts. May be empty. | +| `double_battle` | `bool` | Whether this is a double battle. | +| `party` | `object[]` | The trainer's party of Pokémon. See below for the member schema. | +| `messages` | `object[]` | Dialogue messages. See the Messages section below. | + +## Party Member Schema + +Each element of the `party` array represents a Pokémon owned by the trainer. + +| Field | Type | Description | +| ------------ | ----------------------- | ----------------------------------------------------------------- | +| `species` | `enum Species` | The species of the Pokémon. | +| `form` | `u8` | Form index, packed into the high bits of the species field. | +| `level` | `u16` | The level of the Pokémon. | +| `item` | `enum Item` or `null` | The held item, or `null` for none. | +| `moves` | `enum Move[]` or `null` | Known moves (up to 4), or `null` for default level-up moves. | +| `iv_scale` | `u16` | IV scaling factor (0–255). | +| `ball_seal` | `u16` | Ball seal / capsule decoration index. | + +The presence of the `item` and `moves` fields determines the exact structure of +the output data, which affects the trainer's party in-game. If any Pokémon in +the party specifies that it can have a held item or a custom move-set, then all +other Pokémon in the party must *also* specify as much. + +To illustrate, this party is valid: + +```json +{ + "party": [ + { + "species": "SPECIES_STARLY", + "form": 0, + "level": 7, + "item": null, + "moves": [ + "MOVE_QUICK_ATTACK", + "MOVE_GROWL" + ], + "iv_scale": 30, + "ball_seal": 0 + }, + { + "species": "SPECIES_CHIMCHAR", + "form": 0, + "level": 9, + "item": null, + "moves": [ + "MOVE_SCRATCH", + "MOVE_LEER" + ], + "iv_scale": 30, + "ball_seal": 0 + } + ] +} +``` + +However, this party is *not* valid, as Chimchar specifies that it has data for +its held-item, while Starly does not: + +```json +{ + "party": [ + { + "species": "SPECIES_STARLY", + "form": 0, + "level": 7, + "item": null, + "moves": [ + "MOVE_QUICK_ATTACK", + "MOVE_GROWL" + ], + "iv_scale": 30, + "ball_seal": 0 + }, + { + "species": "SPECIES_CHIMCHAR", + "form": 0, + "level": 9, + "item": "ITEM_ORAN_BERRY", + "moves": [ + "MOVE_SCRATCH", + "MOVE_LEER" + ], + "iv_scale": 30, + "ball_seal": 0 + } + ], +} +``` + +Similarly, this party would also be invalid, as Starly declares that it should +derive its move-set from the moves that it learns by level-up, while Chimchar +declares that it has a custom move-set: + +```json +{ + "party": [ + { + "species": "SPECIES_STARLY", + "form": 0, + "level": 7, + "item": null, + "moves": null, + "iv_scale": 30, + "ball_seal": 0 + }, + { + "species": "SPECIES_CHIMCHAR", + "form": 0, + "level": 9, + "item": null, + "moves": [ + "MOVE_SCRATCH", + "MOVE_LEER" + ], + "iv_scale": 30, + "ball_seal": 0 + } + ], +} +``` + +## Messages + +The `messages` array defines dialogue that the trainer may speak at various +points during a battle. Each entry has a `type` field drawn from +`enum TrainerMessageType` (e.g. `TRMSG_PRE_BATTLE`, `TRMSG_DEFEAT`, +`TRMSG_POST_BATTLE`, `TRMSG_REMATCH`) and an `en_US` field containing the +message text. As with the text-files stored in `res/text`, the content may be +a single string or an array of strings as a convenience for multi-line messages. +Entries with the `garbage` key in place of `en_US` represent padding present in +the retail ROM. + +## Outputs + +The tool produces the following outputs: + +| Output | Description | +| --------------------------- | -------------------------------------------------------------- | +| `trdata.narc` | `TrainerHeader` entries for every trainer, packed by index ID. | +| `trpoke.narc` | Party data for every trainer, packed by index ID. | +| `trainer_scripts.h` | Generated header mapping trainer IDs to `ScriptEntry` macros. | +| `npc_trainer_names.json` | Text bank for trainer display names. | +| `npc_trainer_messages.json` | Text bank for in-battle trainer dialogue. | +| `trtbl.narc` | Message lookup table mapping `(trainerID, messageType)` pairs. | +| `trtblofs.narc` | Offset table into `trtbl.narc` for each trainer index. | + +## Example + +```json +{ + "name": "Catherine", + "class": "TRAINER_CLASS_ACE_TRAINER_FEMALE", + "items": [], + "ai_flags": [ + "AI_FLAG_BASIC", + "AI_FLAG_EVAL_ATTACK", + "AI_FLAG_EXPERT" + ], + "double_battle": false, + "party": [ + { + "species": "SPECIES_HAUNTER", + "form": 0, + "level": 23, + "item": null, + "moves": [ + "MOVE_NIGHT_SHADE", + "MOVE_CONFUSE_RAY", + "MOVE_SUCKER_PUNCH", + "MOVE_CURSE" + ], + "iv_scale": 60, + "ball_seal": 0 + }, + { + "species": "SPECIES_MISDREAVUS", + "form": 0, + "level": 24, + "item": null, + "moves": [ + "MOVE_PSYBEAM", + "MOVE_PAIN_SPLIT", + "MOVE_CONFUSE_RAY", + "MOVE_SPITE" + ], + "iv_scale": 60, + "ball_seal": 0 + } + ], + "messages": [ + { + "type": "TRMSG_PRE_BATTLE", + "en_US": [ + "What does it feel like, taking one step\n", + "after another into darkness?\r" + ] + }, + { + "type": "TRMSG_DEFEAT", + "en_US": [ + "You’re the kind of person who can keep\n", + "going forward even into the unknown.\n" + ] + }, + { + "type": "TRMSG_POST_BATTLE", + "en_US": [ + "I think, sometimes, one has to make\n", + "mistakes to learn what is right.\n" + ] + } + ] +} +``` diff --git a/docs/index.md b/docs/index.md index ee19a82350..a325c44905 100644 --- a/docs/index.md +++ b/docs/index.md @@ -15,6 +15,10 @@ For more detailed information about the project as a whole, please refer to its ## Working with Files for Various Data Types - [Overview of the Processing Tools](datafiles/overview.md) +- [Pokémon Species](datafiles/pokemon.md) +- [In-Game Trainers](datafiles/trainers.md) +- [In-Game Trades](datafiles/trainers.md) +- [Items](datafiles/items.md) - [Moves](datafiles/moves.md) ## Subsystems