mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-15 07:41:21 +02:00
G2 support
This commit is contained in:
@@ -0,0 +1,907 @@
|
||||
# Section 04 - Slowpoke Well & Azalea Town Gym
|
||||
|
||||
Source: `../section-04-slowpoke-well-azalea-town-gym.txt`
|
||||
Maps covered: `MAP_AZALEA_TOWN`, `MAP_KURTS_HOUSE`, `MAP_AZALEA_POKECENTER_1F`,
|
||||
`MAP_SLOWPOKE_WELL_B1F`, `MAP_SLOWPOKE_WELL_B2F` (off-route, Surf-only),
|
||||
`MAP_AZALEA_GYM`. `MAP_AZALEA_MART` is referenced for its stock only
|
||||
(`data/items/marts.asm` `MartAzalea`); its map file was not transcribed.
|
||||
Badges / key milestones in this section: **HIVEBADGE** (`ENGINE_HIVEBADGE`),
|
||||
`EVENT_CLEARED_SLOWPOKE_WELL`, `EVENT_BEAT_BUGSY`, `TM_FURY_CUTTER` (TM49),
|
||||
`LURE_BALL`, `SUPER_POTION`, `WHT_APRICORN`, hidden `FULL_HEAL`. Clearing the
|
||||
well is what unlocks the Gym door and arms the Azalea rival battle for the next
|
||||
section.
|
||||
|
||||
Coordinate convention throughout: the raw asm x/y from
|
||||
`warp_event` / `coord_event` / `bg_event` / `object_event`, i.e. walk cells
|
||||
(two 8x8 tiles per side, two cells per map block). `macros/scripts/maps.asm`
|
||||
adds the +4 border internally; the numbers below are the pre-border values as
|
||||
written in the map file.
|
||||
|
||||
---
|
||||
|
||||
## 1. Route order
|
||||
|
||||
| # | Map constant | asm file | Enter via | Leaves via | Why (walkthrough beat) |
|
||||
|---|---|---|---|---|---|
|
||||
| 1 | `MAP_AZALEA_TOWN` | `maps/AzaleaTown.asm` | west edge of Route 33 (`connection east, Route33, ROUTE_33, 0` in `data/maps/attributes.asm`) | warp 4, `warp_event 9, 5, KURTS_HOUSE, 1` | Rocket guard is standing on the well; head west then north to Kurt's house |
|
||||
| 2 | `MAP_KURTS_HOUSE` | `maps/KurtsHouse.asm` | warp 1 (`3, 7`) | warps 1/2 (`3, 7` / `4, 7`) back to `AZALEA_TOWN` warp 4 | `Kurt1` first-visit arm: Kurt storms off to the well and sets `EVENT_AZALEA_TOWN_SLOWPOKETAIL_ROCKET`, which hides the guard |
|
||||
| 3 | `MAP_AZALEA_POKECENTER_1F` | `maps/AzaleaPokecenter1F.asm` | `AZALEA_TOWN` warp 1 (`15, 9`) | warps 1/2 (`3, 7` / `4, 7`) | "heal at the Pokemon Center" |
|
||||
| 4 | `MAP_AZALEA_TOWN` | `maps/AzaleaTown.asm` | Pokecenter warp | warp 6, `warp_event 31, 7, SLOWPOKE_WELL_B1F, 1` | walk east to the now-unguarded well |
|
||||
| 5 | `MAP_SLOWPOKE_WELL_B1F` | `maps/SlowpokeWellB1F.asm` | warp 1 (`17, 15`) | **scripted** `warp KURTS_HOUSE, 3, 3` at the end of `TrainerGruntM1.Script` | four Rocket grunts, Super Potion, tailless Slowpoke |
|
||||
| 6 | `MAP_KURTS_HOUSE` | `maps/KurtsHouse.asm` | script warp to `3, 3` | warps 1/2 | `Kurt1.ClearedSlowpokeWell` -> free `LURE_BALL` |
|
||||
| 7 | `MAP_AZALEA_TOWN` | `maps/AzaleaTown.asm` | Kurt's House warp | fruit tree object at `8, 2`, then warp 1 (Pokecenter) | `WHT_APRICORN` from `WhiteApricornTree` / `FRUITTREE_AZALEA_TOWN`, then heal |
|
||||
| 8 | `MAP_AZALEA_GYM` | `maps/AzaleaGym.asm` | `AZALEA_TOWN` warp 5, `warp_event 10, 15, AZALEA_GYM, 1` | warps 1/2 (`4, 15` / `5, 15`) | five gym trainers + Bugsy -> HIVEBADGE + TM49 |
|
||||
|
||||
Off-route in this section: `MAP_SLOWPOKE_WELL_B2F` (`maps/SlowpokeWellB2F.asm`)
|
||||
hangs off `SLOWPOKE_WELL_B1F` warp 2 at `7, 11`, but the only land approach to
|
||||
that ladder is across water (see the derived grid under B1F) - it is a Surf
|
||||
return trip, not part of this visit, and holds the King's Rock and TM Rain Dance.
|
||||
|
||||
Spills into the next section: `AzaleaTown_MapEvents` has
|
||||
`coord_event 5, 10` / `coord_event 5, 11` for `SCENE_AZALEATOWN_RIVAL_BATTLE`.
|
||||
`TrainerGruntM1.Script` arms that scene with
|
||||
`setmapscene AZALEA_TOWN, SCENE_AZALEATOWN_RIVAL_BATTLE`, so the rival ambush
|
||||
fires the first time you walk west toward the Ilex Forest gate. That battle and
|
||||
Ilex Forest belong to section 05.
|
||||
|
||||
## 2. Maps
|
||||
|
||||
### MAP_AZALEA_TOWN
|
||||
|
||||
- Script: `maps/AzaleaTown.asm`
|
||||
- Blocks: `maps/AzaleaTown.blk`
|
||||
- Header: `data/maps/maps.asm:232` -> `TILESET_JOHTO_MODERN`, `TOWN`,
|
||||
`LANDMARK_AZALEA_TOWN`, `MUSIC_AZALEA_TOWN`, phone `FALSE`, `PALETTE_AUTO`,
|
||||
`FISHGROUP_SHORE`
|
||||
- Dimensions: `constants/map_constants.asm:213` -> `map_const AZALEA_TOWN, 20, 9`
|
||||
(20x9 blocks = 40x18 walk cells)
|
||||
- Connections (`data/maps/attributes.asm:132`): `map_attributes AzaleaTown, AZALEA_TOWN, $05`,
|
||||
`connection west, Route34, ROUTE_34, -18`, `connection east, Route33, ROUTE_33, 0`
|
||||
- Scene var: `data/maps/scenes.asm:37` -> `scene_var AZALEA_TOWN, wAzaleaTownSceneID`
|
||||
- Spawn / fly landing: `data/maps/spawn_points.asm:31` -> `spawn AZALEA_TOWN, 15, 10`;
|
||||
flypoint row `data/maps/flypoints.asm:8` -> `db LANDMARK_AZALEA_TOWN, SPAWN_AZALEA`
|
||||
- Map scripts: `def_scene_scripts` = `AzaleaTownNoop1Scene` (`SCENE_AZALEATOWN_NOOP` = 0),
|
||||
`AzaleaTownNoop2Scene` (`SCENE_AZALEATOWN_RIVAL_BATTLE` = 1);
|
||||
`def_callbacks` = `callback MAPCALLBACK_NEWMAP, AzaleaTownFlypointCallback`
|
||||
|
||||
**Warps** (`def_warp_events`)
|
||||
|
||||
| idx | x | y | destination map | dest warp |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 15 | 9 | `AZALEA_POKECENTER_1F` | 1 |
|
||||
| 2 | 21 | 13 | `CHARCOAL_KILN` | 1 |
|
||||
| 3 | 21 | 5 | `AZALEA_MART` | 2 |
|
||||
| 4 | 9 | 5 | `KURTS_HOUSE` | 1 |
|
||||
| 5 | 10 | 15 | `AZALEA_GYM` | 1 |
|
||||
| 6 | 31 | 7 | `SLOWPOKE_WELL_B1F` | 1 |
|
||||
| 7 | 2 | 10 | `ILEX_FOREST_AZALEA_GATE` | 3 |
|
||||
| 8 | 2 | 11 | `ILEX_FOREST_AZALEA_GATE` | 4 |
|
||||
|
||||
**Coord events** (`def_coord_events`)
|
||||
|
||||
| scene | x | y | script label | effect |
|
||||
|---|---|---|---|---|
|
||||
| `SCENE_AZALEATOWN_RIVAL_BATTLE` | 5 | 10 | `AzaleaTownRivalBattleScene1` | rival ambush, approach from the east; next section |
|
||||
| `SCENE_AZALEATOWN_RIVAL_BATTLE` | 5 | 11 | `AzaleaTownRivalBattleScene2` | same battle, second entry row; next section |
|
||||
|
||||
**BG events** (`def_bg_events`)
|
||||
|
||||
| x | y | type | script/item |
|
||||
|---|---|---|---|
|
||||
| 19 | 9 | `BGEVENT_READ` | `AzaleaTownSign` |
|
||||
| 10 | 9 | `BGEVENT_READ` | `KurtsHouseSign` |
|
||||
| 14 | 15 | `BGEVENT_READ` | `AzaleaGymSign` |
|
||||
| 29 | 7 | `BGEVENT_READ` | `SlowpokeWellSign` |
|
||||
| 19 | 13 | `BGEVENT_READ` | `CharcoalKilnSign` |
|
||||
| 16 | 9 | `BGEVENT_READ` | `AzaleaTownPokecenterSign` (`jumpstd PokecenterSignScript`) |
|
||||
| 22 | 5 | `BGEVENT_READ` | `AzaleaTownMartSign` (`jumpstd MartSignScript`) |
|
||||
| 3 | 9 | `BGEVENT_READ` | `AzaleaTownIlextForestSign` |
|
||||
| 31 | 6 | `BGEVENT_ITEM` | `AzaleaTownHiddenFullHeal` -> `hiddenitem FULL_HEAL, EVENT_AZALEA_TOWN_HIDDEN_FULL_HEAL` |
|
||||
|
||||
**Object events** (`def_object_events`) - `object_const_def` is `const_def 2`, so
|
||||
the first const is 2 and row N carries const N+1.
|
||||
|
||||
| const | sprite | x | y | movement (radius x,y / hours / pal) | type | script label | event flag |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 2 `AZALEATOWN_AZALEA_ROCKET1` | `SPRITE_AZALEA_ROCKET` | 31 | 9 | `STANDING_DOWN` 0,0 / -1,-1 / 0 | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaTownRocket1Script` | `EVENT_AZALEA_TOWN_SLOWPOKETAIL_ROCKET` |
|
||||
| 3 `AZALEATOWN_GRAMPS` | `SPRITE_GRAMPS` | 21 | 9 | `WANDER` 1,2 / -1,-1 / 0 | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaTownGrampsScript` | -1 |
|
||||
| 4 `AZALEATOWN_TEACHER` | `SPRITE_TEACHER` | 15 | 13 | `WALK_UP_DOWN` 0,2 / -1,-1 / `PAL_NPC_BLUE` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaTownTeacherScript` | -1 |
|
||||
| 5 `AZALEATOWN_YOUNGSTER` | `SPRITE_YOUNGSTER` | 7 | 9 | `WALK_LEFT_RIGHT` 1,0 / -1,-1 / `PAL_NPC_GREEN` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaTownYoungsterScript` | -1 |
|
||||
| 6 `AZALEATOWN_SLOWPOKE1` | `SPRITE_SLOWPOKE` | 8 | 17 | `STILL` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaTownSlowpokeScript` | `EVENT_AZALEA_TOWN_SLOWPOKES` |
|
||||
| 7 `AZALEATOWN_SLOWPOKE2` | `SPRITE_SLOWPOKE` | 18 | 9 | `STILL` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaTownSlowpokeScript` | `EVENT_AZALEA_TOWN_SLOWPOKES` |
|
||||
| 8 `AZALEATOWN_SLOWPOKE3` | `SPRITE_SLOWPOKE` | 29 | 9 | `STILL` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaTownSlowpokeScript` | `EVENT_AZALEA_TOWN_SLOWPOKES` |
|
||||
| 9 `AZALEATOWN_SLOWPOKE4` | `SPRITE_SLOWPOKE` | 15 | 15 | `STILL` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaTownSlowpokeScript` | `EVENT_AZALEA_TOWN_SLOWPOKES` |
|
||||
| 10 `AZALEATOWN_FRUIT_TREE` | `SPRITE_FRUIT_TREE` | 8 | 2 | `STILL` | `OBJECTTYPE_SCRIPT`, 0 | `WhiteApricornTree` | -1 |
|
||||
| 11 `AZALEATOWN_RIVAL` | `SPRITE_AZALEA_ROCKET` | 11 | 10 | `STANDING_LEFT` | `OBJECTTYPE_SCRIPT`, 0 | `ObjectEvent` | `EVENT_RIVAL_AZALEA_TOWN` |
|
||||
| 12 `AZALEATOWN_AZALEA_ROCKET3` | `SPRITE_AZALEA_ROCKET` | 10 | 16 | `STANDING_DOWN` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaTownRocket2Script` | `EVENT_SLOWPOKE_WELL_ROCKETS` |
|
||||
|
||||
`SPRITE_AZALEA_ROCKET` (`constants/sprite_constants.asm:156`, id `$f6`) is a
|
||||
variable sprite. `engine/events/std_scripts.asm:539` seeds it as
|
||||
`variablesprite SPRITE_AZALEA_ROCKET, SPRITE_ROCKET`; `TrainerGruntM1.Script`
|
||||
in `maps/SlowpokeWellB1F.asm` re-points it with
|
||||
`variablesprite SPRITE_AZALEA_ROCKET, SPRITE_RIVAL`, which is why const 11 draws
|
||||
as the rival even though the row names the Rocket slot.
|
||||
|
||||
**Derived walkability** (from `maps/AzaleaTown.blk` + `data/tilesets/johto_modern_collision.asm`
|
||||
+ `data/collision/collision_permissions.asm`; `.` land, `#` wall, `h` ledge hop,
|
||||
`W` warp tile, columns are x, rows are y)
|
||||
|
||||
```
|
||||
0123456789012345678901234567890123456789
|
||||
0 ###############################.........
|
||||
1 ######....#####################.........
|
||||
2 ######....#####################.........
|
||||
3 ######....##############################
|
||||
4 ######..################################
|
||||
5 ######..#W###########W######......######
|
||||
6 ######hhh.hh########....####..###.######
|
||||
7 #########.##########....####.##W#.######
|
||||
8 ##...#......######............#.#.######
|
||||
9 ######....#.###W##.#..............######
|
||||
10 ##W.........................hhh.hh######
|
||||
11 ##W.....................#######.########
|
||||
12 ######..######......########......######
|
||||
13 ######..######.....##W######............
|
||||
14 ######..######..........####............
|
||||
15 ######..##W####.........####............
|
||||
16 ######..............####################
|
||||
17 ######..............####################
|
||||
```
|
||||
|
||||
Two chokepoints matter: `31, 9` is the only walkable cell that reaches `31, 8`
|
||||
and then the well ladder at `31, 7`, and `10, 16` is the only walkable cell
|
||||
adjacent to the Gym door at `10, 15` (`9, 15`, `11, 15` and `10, 14` are all
|
||||
wall). The two Rocket objects sit exactly on those cells.
|
||||
|
||||
**Scripts of interest**
|
||||
|
||||
- `AzaleaTownFlypointCallback` - `MAPCALLBACK_NEWMAP`; `setflag ENGINE_FLYPOINT_AZALEA`,
|
||||
`endcallback`. Entering the map once is enough to register the fly point.
|
||||
- `AzaleaTownRocket1Script` / `AzaleaTownRocket2Script` -
|
||||
`jumptextfaceplayer AzaleaTownRocket1Text` / `...Rocket2Text`. Pure flavour;
|
||||
neither one gates anything by script. They block by standing on tiles.
|
||||
- `AzaleaTownGrampsScript` - `checkevent EVENT_CLEARED_SLOWPOKE_WELL` /
|
||||
`iftrue .ClearedWell`, then one of `AzaleaTownGrampsTextBefore` /
|
||||
`AzaleaTownGrampsTextAfter`. Cheap read-only probe of well state.
|
||||
- `WhiteApricornTree` - `fruittree FRUITTREE_AZALEA_TOWN`.
|
||||
`constants/script_constants.asm:226` gives `FRUITTREE_AZALEA_TOWN ; 14` (hex),
|
||||
and `data/items/fruit_trees.asm:23` is `db WHT_APRICORN ; AZALEA_TOWN`.
|
||||
Once-per-day, tracked by the fruit-tree daily bit, not by an `EVENT_*`.
|
||||
- `AzaleaTownHiddenFullHeal` - `hiddenitem FULL_HEAL, EVENT_AZALEA_TOWN_HIDDEN_FULL_HEAL`;
|
||||
reached by facing the wall cell `31, 6` from `31, 7`/`31, 5` neighbours.
|
||||
- `AzaleaTownRivalBattleScene1` / `...Scene2` / `AzaleaTownRivalBattleScript` -
|
||||
next section. For completeness they `setevent EVENT_RIVAL_AZALEA_TOWN`,
|
||||
branch on `EVENT_GOT_TOTODILE_FROM_ELM` / `EVENT_GOT_CHIKORITA_FROM_ELM`,
|
||||
`loadtrainer RIVAL1, RIVAL1_2_TOTODILE|RIVAL1_2_CHIKORITA|RIVAL1_2_CYNDAQUIL`,
|
||||
and end with `setscene SCENE_AZALEATOWN_NOOP`.
|
||||
|
||||
**Flags and events**
|
||||
|
||||
| constant | defined in | read/written by | meaning for a bot |
|
||||
|---|---|---|---|
|
||||
| `ENGINE_FLYPOINT_AZALEA` | `constants/engine_flags.asm:82` | set by `AzaleaTownFlypointCallback` | Fly destination unlocked on first entry |
|
||||
| `EVENT_AZALEA_TOWN_SLOWPOKETAIL_ROCKET` | `constants/event_flags.asm:1180` | set by `Kurt1` (first-visit arm) and read by `KurtsGranddaughter.Lonely` | **set = the well guard at `31, 9` is hidden**; this is the well gate |
|
||||
| `EVENT_SLOWPOKE_WELL_ROCKETS` | `constants/event_flags.asm:1182` | set by the `disappear` calls in `TrainerGruntM1.Script` | **set = the Rocket at `10, 16` is hidden**; this is the Gym gate |
|
||||
| `EVENT_AZALEA_TOWN_SLOWPOKES` | `constants/event_flags.asm:1179` | `clearevent` in `TrainerGruntM1.Script` | cleared = the four town Slowpoke appear |
|
||||
| `EVENT_CLEARED_SLOWPOKE_WELL` | `constants/event_flags.asm:52` | set in `TrainerGruntM1.Script`; read by `AzaleaTownGrampsScript`, `Kurt1`, `KurtsGranddaughter`, `KurtsHouseKurtCallback` | the section-4 milestone flag |
|
||||
| `EVENT_RIVAL_AZALEA_TOWN` | `constants/event_flags.asm:1121` | set by `AzaleaTownRivalBattleScript` | next section |
|
||||
| `EVENT_AZALEA_TOWN_HIDDEN_FULL_HEAL` | `constants/event_flags.asm:187` | `hiddenitem` | one-shot hidden item |
|
||||
| `SCENE_AZALEATOWN_NOOP` = 0, `SCENE_AZALEATOWN_RIVAL_BATTLE` = 1 | generated by `scene_script` in `macros/scripts/maps.asm:25` (`scene_const` + `EXPORT`) | `setscene` / `setmapscene` | scene id in `wAzaleaTownSceneID` |
|
||||
|
||||
Object visibility semantics, since everything above depends on it:
|
||||
`engine/overworld/scripting.asm:879` `Script_appear` calls
|
||||
`ApplyEventActionAppearDisappear` with `b = 0 ; clear`, and `:887`
|
||||
`Script_disappear` with `b = 1 ; set`. **An object's `EVENT_*` flag SET means the
|
||||
object is hidden.**
|
||||
|
||||
**Items**
|
||||
|
||||
| item | how obtained | source (label / bg_event / hidden) | one-time flag |
|
||||
|---|---|---|---|
|
||||
| `WHT_APRICORN` | talk to the tree object at `8, 2` | `WhiteApricornTree` -> `fruittree FRUITTREE_AZALEA_TOWN`, `data/items/fruit_trees.asm:23` | none (daily respawn) |
|
||||
| `FULL_HEAL` | hidden, face `31, 6` | `AzaleaTownHiddenFullHeal` bg_event | `EVENT_AZALEA_TOWN_HIDDEN_FULL_HEAL` |
|
||||
|
||||
Azalea Mart stock (`data/items/marts.asm:71`, `MartAzalea`, 9 items):
|
||||
`CHARCOAL`, `POKE_BALL`, `POTION`, `SUPER_POTION`, `ESCAPE_ROPE`, `REPEL`,
|
||||
`ANTIDOTE`, `PARLYZ_HEAL`, `FLOWER_MAIL`.
|
||||
|
||||
**Trainers**
|
||||
|
||||
None on this map in this section (the rival at const 11 is section 05).
|
||||
|
||||
**Wild encounters**
|
||||
|
||||
`AZALEA_TOWN` has no entry in `data/wild/johto_grass.asm` or
|
||||
`data/wild/johto_water.asm`. Fishing group is `FISHGROUP_SHORE`
|
||||
(`data/maps/maps.asm:232`); headbutt set is
|
||||
`data/wild/treemon_maps.asm:31` -> `treemon_map AZALEA_TOWN, TREEMON_SET_FOREST`.
|
||||
|
||||
---
|
||||
|
||||
### MAP_KURTS_HOUSE
|
||||
|
||||
- Script: `maps/KurtsHouse.asm`
|
||||
- Blocks: `maps/KurtsHouse.blk`
|
||||
- Header: `data/maps/maps.asm:229` -> `TILESET_TRADITIONAL_HOUSE`, `INDOOR`,
|
||||
`LANDMARK_AZALEA_TOWN`, `MUSIC_AZALEA_TOWN`, phone `FALSE`, `PALETTE_DAY`,
|
||||
`FISHGROUP_SHORE`
|
||||
- Dimensions: `constants/map_constants.asm:210` -> `map_const KURTS_HOUSE, 8, 4`
|
||||
- Connections: none (indoor)
|
||||
- Map scripts: no scene scripts; `callback MAPCALLBACK_OBJECTS, KurtsHouseKurtCallback`
|
||||
|
||||
**Warps** (`def_warp_events`)
|
||||
|
||||
| idx | x | y | destination map | dest warp |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 3 | 7 | `AZALEA_TOWN` | 4 |
|
||||
| 2 | 4 | 7 | `AZALEA_TOWN` | 4 |
|
||||
|
||||
**Coord events** (`def_coord_events`) - none.
|
||||
|
||||
**BG events** (`def_bg_events`)
|
||||
|
||||
| x | y | type | script/item |
|
||||
|---|---|---|---|
|
||||
| 6 | 1 | `BGEVENT_READ` | `KurtsHouseRadio` (`jumpstd Radio2Script`) |
|
||||
| 8 | 0 | `BGEVENT_READ` | `KurtsHouseOakPhoto` |
|
||||
| 9 | 0 | `BGEVENT_READ` | `KurtsHouseOakPhoto` |
|
||||
| 5 | 1 | `BGEVENT_READ` | `KurtsHouseBookshelf` (`jumpstd DifficultBookshelfScript`) |
|
||||
| 2 | 1 | `BGEVENT_READ` | `KurtsHouseBookshelf` |
|
||||
| 3 | 1 | `BGEVENT_READ` | `KurtsHouseBookshelf` |
|
||||
| 4 | 1 | `BGEVENT_READ` | `KurtsHouseCelebiStatue` |
|
||||
|
||||
**Object events** (`def_object_events`)
|
||||
|
||||
| const | sprite | x | y | movement | type | script label | event flag |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 2 `KURTSHOUSE_KURT1` | `SPRITE_KURT` | 3 | 2 | `STANDING_DOWN` | `OBJECTTYPE_SCRIPT`, 0 | `Kurt1` | `EVENT_KURTS_HOUSE_KURT_1` |
|
||||
| 3 `KURTSHOUSE_TWIN` | `SPRITE_TWIN` | 5 | 3 | `SPINRANDOM_SLOW` | `OBJECTTYPE_SCRIPT`, 0 | `KurtsGranddaughter` | -1 |
|
||||
| 4 `KURTSHOUSE_SLOWPOKE` | `SPRITE_SLOWPOKE` | 6 | 3 | `STILL` | `OBJECTTYPE_SCRIPT`, 0 | `KurtsHouseSlowpoke` | `EVENT_KURTS_HOUSE_SLOWPOKE` |
|
||||
| 5 `KURTSHOUSE_KURT2` | `SPRITE_KURT` | 14 | 3 | `STANDING_UP` | `OBJECTTYPE_SCRIPT`, 0 | `Kurt1` | `EVENT_KURTS_HOUSE_KURT_2` |
|
||||
|
||||
Both Kurt objects run the same `Kurt1` script; the callback picks which one is
|
||||
visible.
|
||||
|
||||
**Derived walkability** (`maps/KurtsHouse.blk` + `data/tilesets/traditional_house_collision.asm`)
|
||||
|
||||
```
|
||||
0123456789012345
|
||||
0 ################
|
||||
1 #######...######
|
||||
2 #...........####
|
||||
3 .......##...#...
|
||||
4 .......##...#...
|
||||
5 ................
|
||||
6 ................
|
||||
7 ...WW...........
|
||||
```
|
||||
|
||||
The post-well script warp lands you on `3, 3`, one cell south of `KURTSHOUSE_KURT1`
|
||||
at `3, 2`, who faces down. Talk immediately, no walking required.
|
||||
|
||||
**Scripts of interest**
|
||||
|
||||
- `KurtsHouseKurtCallback` (`MAPCALLBACK_OBJECTS`) -
|
||||
`checkevent EVENT_CLEARED_SLOWPOKE_WELL` / `iffalse .Done`;
|
||||
then `checkflag ENGINE_KURT_MAKING_BALLS` / `iftrue .MakingBalls`.
|
||||
Not making balls: `disappear KURTSHOUSE_KURT2`, `appear KURTSHOUSE_KURT1`.
|
||||
Making balls: `disappear KURTSHOUSE_KURT1`, `appear KURTSHOUSE_KURT2`
|
||||
(he moves to the workshop at `14, 3`).
|
||||
- `Kurt1` - three arms, tested in this order:
|
||||
1. `checkevent EVENT_KURT_GAVE_YOU_LURE_BALL` / `iftrue .GotLureBall`
|
||||
2. `checkevent EVENT_CLEARED_SLOWPOKE_WELL` / `iftrue .ClearedSlowpokeWell`
|
||||
3. fallthrough = **first visit**: `writetext KurtsHouseKurtMakingBallsMustWaitText`,
|
||||
`special FadeOutMusic`, `setevent EVENT_AZALEA_TOWN_SLOWPOKETAIL_ROCKET`,
|
||||
`readvar VAR_FACING` / `ifequal UP, .RunAround`, `turnobject PLAYER, DOWN`,
|
||||
`playsound SFX_FLY`,
|
||||
`applymovement KURTSHOUSE_KURT1, KurtsHouseKurtExitHouseMovement`
|
||||
(5x `big_step DOWN`; the `.RunAround` variant is
|
||||
`KurtsHouseKurtGoAroundPlayerThenExitHouseMovement`, `big_step RIGHT` then
|
||||
5x `big_step DOWN`), `disappear KURTSHOUSE_KURT1`, `special RestartMapMusic`.
|
||||
**This single `setevent` is what removes the well guard.**
|
||||
- `.ClearedSlowpokeWell`: `writetext KurtsHouseKurtHonoredToMakeBallsText`,
|
||||
`promptbutton`, `verbosegiveitem LURE_BALL`, `iffalse .NoRoomForBall`,
|
||||
`setevent EVENT_KURT_GAVE_YOU_LURE_BALL`, then falls into `.GotLureBall`.
|
||||
- `.GotLureBall`: the apricorn loop. Checks `EVENT_TEMPORARY_UNTIL_MAP_RELOAD_2`,
|
||||
`EVENT_TEMPORARY_UNTIL_MAP_RELOAD_1`, then the seven
|
||||
`EVENT_GAVE_KURT_<colour>_APRICORN` in order RED, BLU, YLW, GRN, WHT, BLK, PNK;
|
||||
if none, `checkitem` the seven apricorns, `special SelectApricornForKurt`,
|
||||
set the matching event, `setevent EVENT_TEMPORARY_UNTIL_MAP_RELOAD_1`,
|
||||
`setflag ENGINE_KURT_MAKING_BALLS`. WHT -> `verbosegiveitem FAST_BALL`
|
||||
(`.GiveFastBall`) the next day. Only one apricorn is held at a time, which
|
||||
is exactly the reader comment quoted in the walkthrough.
|
||||
- `KurtsGranddaughter` - branch order `EVENT_FAST_SHIP_FIRST_TIME`,
|
||||
`EVENT_CLEARED_SLOWPOKE_WELL`, `EVENT_AZALEA_TOWN_SLOWPOKETAIL_ROCKET`. Read-only.
|
||||
|
||||
**Flags and events**
|
||||
|
||||
| constant | defined in | read/written by | meaning for a bot |
|
||||
|---|---|---|---|
|
||||
| `EVENT_KURTS_HOUSE_KURT_1` | `constants/event_flags.asm:1248` | `disappear`/`appear` in `Kurt1` + callback | set = house Kurt hidden (he is at the well) |
|
||||
| `EVENT_KURTS_HOUSE_KURT_2` | `constants/event_flags.asm:1249` | callback; also `setevent` in `engine/events/std_scripts.asm:531` | set = workshop Kurt hidden |
|
||||
| `EVENT_KURTS_HOUSE_SLOWPOKE` | `constants/event_flags.asm:1183` | `clearevent` in `TrainerGruntM1.Script` | cleared = the family Slowpoke is back |
|
||||
| `EVENT_KURT_GAVE_YOU_LURE_BALL` | `constants/event_flags.asm:62` | set in `Kurt1.ClearedSlowpokeWell` | free ball already taken |
|
||||
| `EVENT_GAVE_KURT_WHT_APRICORN` | `constants/event_flags.asm:263` | `Kurt1.Wht` / cleared in `.GiveFastBall` | apricorn currently in Kurt's hands |
|
||||
| `ENGINE_KURT_MAKING_BALLS` | `constants/engine_flags.asm:97` (`wDailyFlags1`) | `setflag` in `.GaveKurtApricorns`, read by the callback and every `.Give*Ball` arm | the day-long wait; cleared by the daily reset, not by a script |
|
||||
| `EVENT_TEMPORARY_UNTIL_MAP_RELOAD_1` / `_2` | `constants/event_flags.asm:5` / `:6` | `Kurt1` | per-visit conversation state, wiped on map reload |
|
||||
|
||||
**Items**
|
||||
|
||||
| item | how obtained | source (label / bg_event / hidden) | one-time flag |
|
||||
|---|---|---|---|
|
||||
| `LURE_BALL` | talk to Kurt after clearing the well | `Kurt1.ClearedSlowpokeWell` -> `verbosegiveitem LURE_BALL` | `EVENT_KURT_GAVE_YOU_LURE_BALL` |
|
||||
| `FAST_BALL` | give Kurt the `WHT_APRICORN`, return a day later | `Kurt1.GiveFastBall` -> `verbosegiveitem FAST_BALL` | clears `EVENT_GAVE_KURT_WHT_APRICORN` |
|
||||
|
||||
**Trainers** - none. **Wild encounters** - none (indoor).
|
||||
|
||||
---
|
||||
|
||||
### MAP_AZALEA_POKECENTER_1F
|
||||
|
||||
- Script: `maps/AzaleaPokecenter1F.asm`
|
||||
- Blocks: not present in `maps/` (shared Pokecenter layout)
|
||||
- Header: `data/maps/maps.asm:226` -> `TILESET_POKECENTER`, `INDOOR`,
|
||||
`LANDMARK_AZALEA_TOWN`, `MUSIC_POKEMON_CENTER`, phone `FALSE`, `PALETTE_DAY`,
|
||||
`FISHGROUP_SHORE`
|
||||
- Dimensions: `constants/map_constants.asm:207` -> `map_const AZALEA_POKECENTER_1F, 5, 4`
|
||||
- Map scripts: `def_scene_scripts` = `AzaleaPokecenter1FNoopScene` (marked `; unusable`)
|
||||
|
||||
**Warps** (`def_warp_events`)
|
||||
|
||||
| idx | x | y | destination map | dest warp |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 3 | 7 | `AZALEA_TOWN` | 1 |
|
||||
| 2 | 4 | 7 | `AZALEA_TOWN` | 1 |
|
||||
| 3 | 0 | 7 | `POKECENTER_2F` | 1 |
|
||||
|
||||
**Coord events** / **BG events** - none.
|
||||
|
||||
**Object events** (`def_object_events`)
|
||||
|
||||
| const | sprite | x | y | movement | type | script label | event flag |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 2 `AZALEAPOKECENTER1F_NURSE` | `SPRITE_NURSE` | 3 | 1 | `STANDING_DOWN` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaPokecenter1FNurseScript` (`jumpstd PokecenterNurseScript`) | -1 |
|
||||
| 3 `AZALEAPOKECENTER1F_GENTLEMAN` | `SPRITE_GENTLEMAN` | 9 | 6 | `WALK_UP_DOWN` 0,1 | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaPokecenter1FGentlemanScript` | -1 |
|
||||
| 4 `AZALEAPOKECENTER1F_FISHING_GURU` | `SPRITE_FISHING_GURU` | 6 | 1 | `STANDING_DOWN` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaPokecenter1FFishingGuruScript` | -1 |
|
||||
| 5 `AZALEAPOKECENTER1F_POKEFAN_F` | `SPRITE_POKEFAN_F` | 1 | 4 | `WANDER` 1,2 | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaPokecenter1FPokefanFScript` | -1 |
|
||||
|
||||
Healing is `jumpstd PokecenterNurseScript`; no flags are touched.
|
||||
|
||||
---
|
||||
|
||||
### MAP_SLOWPOKE_WELL_B1F
|
||||
|
||||
- Script: `maps/SlowpokeWellB1F.asm`
|
||||
- Blocks: `maps/SlowpokeWellB1F.blk`
|
||||
- Header: `data/maps/maps.asm:110` -> `TILESET_CAVE`, `CAVE`,
|
||||
`LANDMARK_SLOWPOKE_WELL`, `MUSIC_DARK_CAVE`, phone `TRUE`, `PALETTE_NITE`,
|
||||
`FISHGROUP_LAKE`
|
||||
- Dimensions: `constants/map_constants.asm:97` -> `map_const SLOWPOKE_WELL_B1F, 10, 9`
|
||||
(20x18 walk cells)
|
||||
- Connections: none
|
||||
- Map scripts: `def_scene_scripts` and `def_callbacks` are both empty
|
||||
|
||||
**Warps** (`def_warp_events`)
|
||||
|
||||
| idx | x | y | destination map | dest warp |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 17 | 15 | `AZALEA_TOWN` | 6 |
|
||||
| 2 | 7 | 11 | `SLOWPOKE_WELL_B2F` | 1 |
|
||||
|
||||
**Coord events** / **BG events** - none. Nothing trips automatically on this map;
|
||||
every beat is a trainer sight-line or an A press.
|
||||
|
||||
**Object events** (`def_object_events`)
|
||||
|
||||
| const | sprite | x | y | movement / pal | type, sight | script label | event flag |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 2 `SLOWPOKEWELLB1F_ROCKET1` | `SPRITE_ROCKET` | 14 | 8 | `STANDING_RIGHT` | `OBJECTTYPE_TRAINER`, 1 | `TrainerGruntM29` | `EVENT_SLOWPOKE_WELL_ROCKETS` |
|
||||
| 3 `SLOWPOKEWELLB1F_ROCKET2` | `SPRITE_ROCKET` | 5 | 2 | `STANDING_DOWN` | `OBJECTTYPE_TRAINER`, 1 | `TrainerGruntM1` | `EVENT_SLOWPOKE_WELL_ROCKETS` |
|
||||
| 4 `SLOWPOKEWELLB1F_ROCKET3` | `SPRITE_ROCKET` | 5 | 6 | `STANDING_RIGHT` | `OBJECTTYPE_TRAINER`, 2 | `TrainerGruntM2` | `EVENT_SLOWPOKE_WELL_ROCKETS` |
|
||||
| 5 `SLOWPOKEWELLB1F_ROCKET_GIRL` | `SPRITE_ROCKET_GIRL` | 13 | 2 | `STANDING_DOWN` / `PAL_NPC_RED` | `OBJECTTYPE_TRAINER`, 2 | `TrainerGruntF1` | `EVENT_SLOWPOKE_WELL_ROCKETS` |
|
||||
| 6 `SLOWPOKEWELLB1F_SLOWPOKE1` | `SPRITE_SLOWPOKE` | 7 | 4 | `STILL` / `PAL_NPC_RED` | `OBJECTTYPE_SCRIPT`, 0 | `SlowpokeWellB1FSlowpokeWithMailScript` | `EVENT_SLOWPOKE_WELL_SLOWPOKES` |
|
||||
| 7 `SLOWPOKEWELLB1F_SLOWPOKE2` | `SPRITE_SLOWPOKE` | 6 | 2 | `STILL` / `PAL_NPC_RED` | `OBJECTTYPE_SCRIPT`, 0 | `SlowpokeWellB1FTaillessSlowpokeScript` | `EVENT_SLOWPOKE_WELL_SLOWPOKES` |
|
||||
| 8 `SLOWPOKEWELLB1F_KURT` | `SPRITE_KURT` | 16 | 14 | `STANDING_UP` | `OBJECTTYPE_SCRIPT`, 0 | `SlowpokeWellB1FKurtScript` | `EVENT_SLOWPOKE_WELL_KURT` |
|
||||
| 9 `SLOWPOKEWELLB1F_BOULDER` | `SPRITE_BOULDER` | 3 | 2 | `STRENGTH_BOULDER` | `OBJECTTYPE_SCRIPT`, 0 | `SlowpokeWellB1FBoulder` (`jumpstd StrengthBoulderScript`) | -1 |
|
||||
| 10 `SLOWPOKEWELLB1F_POKE_BALL` | `SPRITE_POKE_BALL` | 10 | 3 | `STILL` | `OBJECTTYPE_ITEMBALL`, 0 | `SlowpokeWellB1FSuperPotion` (`itemball SUPER_POTION`) | `EVENT_SLOWPOKE_WELL_B1F_SUPER_POTION` |
|
||||
|
||||
**Derived walkability** (`maps/SlowpokeWellB1F.blk` + `data/tilesets/cave_collision.asm`
|
||||
+ `data/collision/collision_permissions.asm`; `~` = water, `L` = ladder/warp)
|
||||
|
||||
```
|
||||
01234567890123456789
|
||||
1 .################...
|
||||
2 .#......#......##...
|
||||
3 .#..#...#......##...
|
||||
4 .#.#....#......##...
|
||||
5 .#.#....###.##.##...
|
||||
6 .#..#.......#...#...
|
||||
7 .##.##########..#...
|
||||
8 .#..#####....#..#...
|
||||
9 .#.######....#..#...
|
||||
10 .#.##........#..#...
|
||||
11 .#.##..L.#####..###.
|
||||
12 .#~~#....#~~~~....#.
|
||||
13 .#~~###.##~~~~....#.
|
||||
14 .#~~~~~~##~~~~....#.
|
||||
15 .#~~~~~~##~~~~...L#.
|
||||
```
|
||||
|
||||
Route through the well, matching the walkthrough beat for beat:
|
||||
`17, 15` (entry ladder) -> Kurt at `16, 14` -> north up the `14-15` column to
|
||||
`14, 8`/`15, 8` where `TrainerGruntM29` sees you -> continue north to the top
|
||||
room `9..14, 2..4`, where `TrainerGruntF1` at `13, 2` faces down with sight 2 ->
|
||||
Super Potion ball at `10, 3` -> back east/down through the gap at `11, 5` into
|
||||
the long row-6 corridor -> west to `TrainerGruntM2` at `5, 6` (faces right,
|
||||
sight 2) -> Slowpoke with mail at `7, 4`, tailless Slowpoke at `6, 2` ->
|
||||
`TrainerGruntM1` at `5, 2` (faces down, sight 1).
|
||||
|
||||
The B2F ladder at `7, 11` sits in a chamber walled off along row 7 and reachable
|
||||
only from `7, 13`, whose only non-wall neighbour outside the chamber is the water
|
||||
at `7, 14`. **B2F is Surf-only**; the water is also the only route down from the
|
||||
land at `2, 11`.
|
||||
|
||||
**Scripts of interest**
|
||||
|
||||
- `SlowpokeWellB1FKurtScript` - `jumptextfaceplayer SlowpokeWellB1FKurtText`.
|
||||
Flavour only; Kurt does not gate anything here.
|
||||
- `TrainerGruntM29` - `trainer GRUNTM, GRUNTM_29, EVENT_BEAT_ROCKET_GRUNTM_29, GruntM29SeenText, GruntM29BeatenText, 0, .Script`;
|
||||
`.Script` is `endifjustbattled` + `GruntM29AfterBattleText`. Talking again is
|
||||
the "they're chopping off Slowpoke tails" line the walkthrough mentions.
|
||||
- `TrainerGruntF1` - `trainer GRUNTF, GRUNTF_1, EVENT_BEAT_ROCKET_GRUNTF_1, ...`,
|
||||
same `endifjustbattled` shape.
|
||||
- `TrainerGruntM2` - `trainer GRUNTM, GRUNTM_2, EVENT_BEAT_ROCKET_GRUNTM_2, ...`,
|
||||
same shape.
|
||||
- `TrainerGruntM1` - **the section's payload.**
|
||||
`trainer GRUNTM, GRUNTM_1, EVENT_BEAT_ROCKET_GRUNTM_1, GruntM1SeenText, GruntM1BeatenText, 0, .Script`.
|
||||
`.Script` has no `endifjustbattled`, so it runs immediately after the win:
|
||||
`writetext TrainerGruntM1WhenTalkText`, `special FadeOutToBlack`,
|
||||
`special ReloadSpritesNoPalettes`,
|
||||
`disappear` on consts 2/3/4/5 (all four share `EVENT_SLOWPOKE_WELL_ROCKETS`,
|
||||
so this is the flag that clears the Gym door in town), `pause 15`,
|
||||
`special FadeInFromBlack`, `disappear SLOWPOKEWELLB1F_KURT`,
|
||||
`moveobject SLOWPOKEWELLB1F_KURT, 11, 6`, `appear SLOWPOKEWELLB1F_KURT`,
|
||||
`applymovement SLOWPOKEWELLB1F_KURT, KurtSlowpokeWellVictoryMovementData`
|
||||
(4x `step LEFT`, `step UP`, 3x `step_sleep 8`, `step LEFT`, 2x `step UP`,
|
||||
3x `step_sleep 8`, `turn_head LEFT`), `turnobject PLAYER, RIGHT`,
|
||||
`writetext KurtLeaveSlowpokeWellText`, then the flag block:
|
||||
```
|
||||
setevent EVENT_CLEARED_SLOWPOKE_WELL
|
||||
variablesprite SPRITE_AZALEA_ROCKET, SPRITE_RIVAL
|
||||
setmapscene AZALEA_TOWN, SCENE_AZALEATOWN_RIVAL_BATTLE
|
||||
clearevent EVENT_ILEX_FOREST_APPRENTICE
|
||||
clearevent EVENT_ILEX_FOREST_FARFETCHD_1
|
||||
setevent EVENT_CHARCOAL_KILN_FARFETCH_D
|
||||
setevent EVENT_CHARCOAL_KILN_APPRENTICE
|
||||
setevent EVENT_SLOWPOKE_WELL_SLOWPOKES
|
||||
setevent EVENT_SLOWPOKE_WELL_KURT
|
||||
clearevent EVENT_AZALEA_TOWN_SLOWPOKES
|
||||
clearevent EVENT_KURTS_HOUSE_SLOWPOKE
|
||||
clearevent EVENT_KURTS_HOUSE_KURT_1
|
||||
```
|
||||
then `special FadeOutToWhite`, `special HealParty`, `pause 15`,
|
||||
`warp KURTS_HOUSE, 3, 3`, `end`. Note the free party heal, and note that the
|
||||
Ilex Forest Farfetch'd quest is armed here, not in Ilex Forest.
|
||||
- `SlowpokeWellB1FSlowpokeWithMailScript` - `faceplayer`, `cry SLOWPOKE`,
|
||||
`SlowpokeWellB1FSlowpokeWithMailText`, `yesorno` / `iftrue .ReadMail` ->
|
||||
`SlowpokeWellB1FSlowpokeMailText`. No flag, no item, purely optional.
|
||||
- `SlowpokeWellB1FSuperPotion` - `itemball SUPER_POTION`, guarded by
|
||||
`EVENT_SLOWPOKE_WELL_B1F_SUPER_POTION`.
|
||||
- `SlowpokeWellB1FBoulder` - `jumpstd StrengthBoulderScript`; needs Strength,
|
||||
which is not obtainable in this section.
|
||||
|
||||
**Flags and events**
|
||||
|
||||
| constant | defined in | read/written by | meaning for a bot |
|
||||
|---|---|---|---|
|
||||
| `EVENT_BEAT_ROCKET_GRUNTM_29` | `constants/event_flags.asm:792` | `TrainerGruntM29` | grunt 1 beaten |
|
||||
| `EVENT_BEAT_ROCKET_GRUNTF_1` | `constants/event_flags.asm:796` | `TrainerGruntF1` | grunt 2 beaten |
|
||||
| `EVENT_BEAT_ROCKET_GRUNTM_2` | `constants/event_flags.asm:765` | `TrainerGruntM2` | grunt 3 beaten |
|
||||
| `EVENT_BEAT_ROCKET_GRUNTM_1` | `constants/event_flags.asm:764` | `TrainerGruntM1` | grunt 4 (leader) beaten |
|
||||
| `EVENT_SLOWPOKE_WELL_ROCKETS` | `constants/event_flags.asm:1182` | set via the four `disappear` calls | hides the well grunts **and** the Azalea Gym blocker |
|
||||
| `EVENT_SLOWPOKE_WELL_SLOWPOKES` | `constants/event_flags.asm:1181` | `setevent` in `TrainerGruntM1.Script` | hides the two well Slowpoke |
|
||||
| `EVENT_SLOWPOKE_WELL_KURT` | `constants/event_flags.asm:1250` | `setevent` in `TrainerGruntM1.Script` | hides well Kurt |
|
||||
| `EVENT_CLEARED_SLOWPOKE_WELL` | `constants/event_flags.asm:52` | set here | section milestone |
|
||||
| `EVENT_SLOWPOKE_WELL_B1F_SUPER_POTION` | `constants/event_flags.asm:1027` | itemball | Super Potion taken |
|
||||
| `EVENT_ILEX_FOREST_APPRENTICE` / `EVENT_ILEX_FOREST_FARFETCHD_1` | `constants/event_flags.asm:1173` / `:1163` | `clearevent` here | Farfetch'd quest NPCs become visible in Ilex Forest (section 05) |
|
||||
| `EVENT_CHARCOAL_KILN_FARFETCH_D` / `EVENT_CHARCOAL_KILN_APPRENTICE` | `constants/event_flags.asm:1175` / `:1176` | `setevent` here | they leave the Charcoal Kiln |
|
||||
|
||||
**Items**
|
||||
|
||||
| item | how obtained | source (label / bg_event / hidden) | one-time flag |
|
||||
|---|---|---|---|
|
||||
| `SUPER_POTION` | ball at `10, 3` | `SlowpokeWellB1FSuperPotion` | `EVENT_SLOWPOKE_WELL_B1F_SUPER_POTION` |
|
||||
|
||||
**Trainers**
|
||||
|
||||
Money = `base reward` x level of the last enemy mon x 4. The x4 is
|
||||
`engine/battle/read_trainer_party.asm:300` `ComputeTrainerReward`
|
||||
(`base * wCurPartyLevel`) followed by the `ld c, 4` add loop and two
|
||||
unconditional `call .DoubleReward` at `engine/battle/core.asm:2340-2361`.
|
||||
`GRUNTM` / `GRUNTF` base reward is 10 (`data/trainers/attributes.asm:185`, `:395`).
|
||||
|
||||
| const | class | id | party (`data/trainers/parties.asm` label) | script label | rematch/phone |
|
||||
|---|---|---|---|---|---|
|
||||
| `GRUNTM_29` | `GRUNTM` | `constants/trainer_constants.asm:289` | `GruntMGroup` "GRUNT@", `TRAINERTYPE_NORMAL`: L9 `RATTATA`, L9 `RATTATA` | `TrainerGruntM29` | no (360 = 10x9x4) |
|
||||
| `GRUNTF_1` | `GRUNTF` | `constants/trainer_constants.asm:648` | `GruntFGroup` "GRUNT@", `TRAINERTYPE_NORMAL`: L9 `ZUBAT`, L11 `EKANS` | `TrainerGruntF1` | no (440 = 10x11x4) |
|
||||
| `GRUNTM_2` | `GRUNTM` | `constants/trainer_constants.asm:262` | `GruntMGroup` "GRUNT@", `TRAINERTYPE_NORMAL`: L7 `RATTATA`, L9 `ZUBAT`, L9 `ZUBAT` | `TrainerGruntM2` | no (360 = 10x9x4) |
|
||||
| `GRUNTM_1` | `GRUNTM` | `constants/trainer_constants.asm:261` | `GruntMGroup` "GRUNT@", `TRAINERTYPE_NORMAL`: L14 `KOFFING` | `TrainerGruntM1` | no (560 = 10x14x4) |
|
||||
|
||||
**Wild encounters**
|
||||
|
||||
- Grass/cave, `data/wild/johto_grass.asm:582` `def_grass_wildmons SLOWPOKE_WELL_B1F`,
|
||||
`db 2 percent, 2 percent, 2 percent` - **identical morn/day/nite lists**:
|
||||
L5 `ZUBAT`, L6 `ZUBAT`, L7 `ZUBAT`, L6 `SLOWPOKE`, L8 `ZUBAT`, L8 `SLOWPOKE`,
|
||||
L8 `SLOWPOKE`.
|
||||
- Water, `data/wild/johto_water.asm:33` `def_water_wildmons SLOWPOKE_WELL_B1F`,
|
||||
`db 2 percent`: L15 `SLOWPOKE`, L20 `SLOWPOKE`, L10 `SLOWPOKE`.
|
||||
- Fishing: `FISHGROUP_LAKE` (`data/wild/fish.asm:14`) ->
|
||||
`.Lake_Old` L10 `MAGIKARP`/`MAGIKARP`/`GOLDEEN`, `.Lake_Good` L20
|
||||
`MAGIKARP`/`GOLDEEN`/`GOLDEEN` + `time_group 4`, `.Lake_Super` L40
|
||||
`GOLDEEN`/`time_group 5`/`MAGIKARP`/`SEAKING`.
|
||||
- Headbutt: `data/wild/treemon_maps.asm:47` -> `treemon_map SLOWPOKE_WELL_B1F, TREEMON_SET_ROCK`
|
||||
(rock smash set; no headbutt trees underground).
|
||||
|
||||
---
|
||||
|
||||
### MAP_SLOWPOKE_WELL_B2F (off-route, Surf-gated)
|
||||
|
||||
- Script: `maps/SlowpokeWellB2F.asm`
|
||||
- Blocks: `maps/SlowpokeWellB2F.blk`
|
||||
- Header: `data/maps/maps.asm:111` -> `TILESET_CAVE`, `CAVE`,
|
||||
`LANDMARK_SLOWPOKE_WELL`, `MUSIC_DARK_CAVE`, phone `TRUE`, `PALETTE_NITE`,
|
||||
`FISHGROUP_LAKE`
|
||||
- Dimensions: `constants/map_constants.asm:98` -> `map_const SLOWPOKE_WELL_B2F, 10, 9`
|
||||
|
||||
**Warps**
|
||||
|
||||
| idx | x | y | destination map | dest warp |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 9 | 11 | `SLOWPOKE_WELL_B1F` | 2 |
|
||||
|
||||
**Coord events** / **BG events** - none.
|
||||
|
||||
**Object events**
|
||||
|
||||
| const | sprite | x | y | movement | type | script label | event flag |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 2 `SLOWPOKEWELLB2F_GYM_GUIDE` | `SPRITE_GYM_GUIDE` | 5 | 4 | `WANDER` 1,2 | `OBJECTTYPE_SCRIPT`, 1 | `SlowpokeWellB2FGymGuideScript` | -1 |
|
||||
| 3 `SLOWPOKEWELLB2F_POKE_BALL` | `SPRITE_POKE_BALL` | 15 | 5 | `STILL` | `OBJECTTYPE_ITEMBALL`, 0 | `SlowpokeWellB2FTMRainDance` (`itemball TM_RAIN_DANCE`) | `EVENT_SLOWPOKE_WELL_B2F_TM_RAIN_DANCE` |
|
||||
|
||||
`SlowpokeWellB2FGymGuideScript`: `checkevent EVENT_GOT_KINGS_ROCK_IN_SLOWPOKE_WELL`
|
||||
/ `iftrue .GotKingsRock`, else `verbosegiveitem KINGS_ROCK`, `iffalse .NoRoom`,
|
||||
`setevent EVENT_GOT_KINGS_ROCK_IN_SLOWPOKE_WELL`
|
||||
(`constants/event_flags.asm:124`).
|
||||
|
||||
Wild: `data/wild/johto_grass.asm:610` L19-23 `ZUBAT`/`SLOWPOKE`/`GOLBAT`
|
||||
(same three time slots); `data/wild/johto_water.asm:40` is `4 percent` in Gold
|
||||
(`IF DEF(_GOLD)`) / `2 percent` in Silver, L15 `SLOWPOKE`, L20 `SLOWPOKE`,
|
||||
L20 `SLOWBRO`.
|
||||
|
||||
---
|
||||
|
||||
### MAP_AZALEA_GYM
|
||||
|
||||
- Script: `maps/AzaleaGym.asm`
|
||||
- Blocks: `maps/AzaleaGym.blk`
|
||||
- Header: `data/maps/maps.asm:230` -> `TILESET_ELITE_FOUR_ROOM`, `INDOOR`,
|
||||
`LANDMARK_AZALEA_TOWN`, `MUSIC_GYM`, phone `TRUE`, `PALETTE_DAY`,
|
||||
`FISHGROUP_SHORE`
|
||||
- Dimensions: `constants/map_constants.asm:211` -> `map_const AZALEA_GYM, 5, 8`
|
||||
(10x16 walk cells)
|
||||
- Map scripts: `def_scene_scripts` and `def_callbacks` are both empty
|
||||
|
||||
**Warps** (`def_warp_events`)
|
||||
|
||||
| idx | x | y | destination map | dest warp |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 4 | 15 | `AZALEA_TOWN` | 5 |
|
||||
| 2 | 5 | 15 | `AZALEA_TOWN` | 5 |
|
||||
|
||||
**Coord events** - none.
|
||||
|
||||
**BG events** (`def_bg_events`)
|
||||
|
||||
| x | y | type | script/item |
|
||||
|---|---|---|---|
|
||||
| 3 | 13 | `BGEVENT_READ` | `AzaleaGymStatue` |
|
||||
| 6 | 13 | `BGEVENT_READ` | `AzaleaGymStatue` |
|
||||
|
||||
`AzaleaGymStatue`: `checkflag ENGINE_HIVEBADGE` / `iftrue .Beaten`;
|
||||
unbeaten -> `jumpstd GymStatue1Script`, beaten ->
|
||||
`gettrainername STRING_BUFFER_4, BUGSY, BUGSY1` + `jumpstd GymStatue2Script`.
|
||||
|
||||
**Object events** (`def_object_events`)
|
||||
|
||||
| const | sprite | x | y | movement / pal | type, sight | script label | event flag |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 2 `AZALEAGYM_BUGSY` | `SPRITE_BUGSY` | 5 | 7 | `SPINRANDOM_SLOW` / `PAL_NPC_GREEN` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaGymBugsyScript` | -1 |
|
||||
| 3 `AZALEAGYM_BUG_CATCHER1` | `SPRITE_BUG_CATCHER` | 5 | 3 | `SPINRANDOM_FAST` / `PAL_NPC_BROWN` | `OBJECTTYPE_TRAINER`, 2 | `TrainerBugCatcherBenny` | -1 |
|
||||
| 4 `AZALEAGYM_BUG_CATCHER2` | `SPRITE_BUG_CATCHER` | 8 | 8 | `STANDING_DOWN` / `PAL_NPC_BROWN` | `OBJECTTYPE_TRAINER`, 3 | `TrainerBugCatcherAl` | -1 |
|
||||
| 5 `AZALEAGYM_BUG_CATCHER3` | `SPRITE_BUG_CATCHER` | 0 | 2 | `STANDING_DOWN` / `PAL_NPC_BROWN` | `OBJECTTYPE_TRAINER`, 3 | `TrainerBugCatcherJosh` | -1 |
|
||||
| 6 `AZALEAGYM_TWIN1` | `SPRITE_TWIN` | 4 | 10 | `STANDING_DOWN` / `PAL_NPC_RED` | `OBJECTTYPE_TRAINER`, 1 | `TrainerTwinsAmyandmay1` | -1 |
|
||||
| 7 `AZALEAGYM_TWIN2` | `SPRITE_TWIN` | 5 | 10 | `STANDING_DOWN` / `PAL_NPC_RED` | `OBJECTTYPE_TRAINER`, 1 | `TrainerTwinsAmyandmay2` | -1 |
|
||||
| 8 `AZALEAGYM_GYM_GUIDE` | `SPRITE_GYM_GUIDE` | 7 | 13 | `STANDING_DOWN` / `PAL_NPC_RED` | `OBJECTTYPE_SCRIPT`, 0 | `AzaleaGymGuideScript` | -1 |
|
||||
|
||||
None of the gym objects carry an event flag, so they are always drawn; being
|
||||
"beaten" is entirely the `trainer` macro's own `EVENT_BEAT_*` check.
|
||||
|
||||
**Derived walkability** (`maps/AzaleaGym.blk` + `data/tilesets/elite_four_room_collision.asm`)
|
||||
|
||||
```
|
||||
0123456789
|
||||
0 ##########
|
||||
1 ##########
|
||||
2 ..........
|
||||
3 ..........
|
||||
4 ..##..##..
|
||||
5 ..#....#..
|
||||
6 .#..##..#.
|
||||
7 .#......#.
|
||||
8 ..#....#..
|
||||
9 ..##..##..
|
||||
10 ..........
|
||||
11 ..........
|
||||
12 ##.#..#.##
|
||||
13 ##.#..#.##
|
||||
14 ###.....##
|
||||
15 ###.WW..##
|
||||
```
|
||||
|
||||
It is a spiral. Entry `4, 15` / `5, 15` -> `4, 14`..`7, 14` -> the two
|
||||
entry stalks at columns 4-5 and 7 -> the row 10/11 ring -> up either side
|
||||
column (0-1 or 8-9) -> row 2/3 -> in at `4, 4` / `5, 4` -> `4, 5`..`6, 5` ->
|
||||
`3, 6` -> `3, 7` -> Bugsy at `5, 7`.
|
||||
|
||||
Derived from the grid plus the sight fields: only the **twins** sit on the
|
||||
straight-line path (`4, 11` and `5, 11` are their sight cells), and even they
|
||||
are dodgeable by taking the column-7 stalk from `7, 14` up to `7, 11`. Josh's
|
||||
sight covers `0, 3`-`0, 5` so the left column is his; Al's covers `8, 9`-`8, 11`
|
||||
so the column-8 approach is his; column 9 is clear all the way from row 11 to
|
||||
row 3. Benny spins (`SPINRANDOM_FAST`, sight 2) at `5, 3`, so crossing row 2/3
|
||||
near column 5 is a coin flip rather than a guarantee.
|
||||
|
||||
**Scripts of interest**
|
||||
|
||||
- `AzaleaGymBugsyScript` -
|
||||
`faceplayer`, `opentext`, `checkevent EVENT_BEAT_BUGSY` / `iftrue .FightDone`;
|
||||
otherwise `BugsyText_INeverLose`,
|
||||
`winlosstext BugsyText_ResearchIncomplete, 0` (no loss text - losing is a
|
||||
whiteout), `loadtrainer BUGSY, BUGSY1`, `startbattle`, `reloadmapafterbattle`,
|
||||
`setevent EVENT_BEAT_BUGSY`, `Text_ReceivedHiveBadge`,
|
||||
`playsound SFX_GET_BADGE`, `waitsfx`, **`setflag ENGINE_HIVEBADGE`**,
|
||||
`readvar VAR_BADGES`, `scall AzaleaGymActivateRockets`.
|
||||
`.FightDone`: `checkevent EVENT_GOT_TM49_FURY_CUTTER` / `iftrue .GotFuryCutter`,
|
||||
then - and this is the bot-relevant part -
|
||||
```
|
||||
setevent EVENT_BEAT_TWINS_AMY_AND_MAY
|
||||
setevent EVENT_BEAT_BUG_CATCHER_BENNY
|
||||
setevent EVENT_BEAT_BUG_CATCHER_AL
|
||||
setevent EVENT_BEAT_BUG_CATCHER_JOSH
|
||||
```
|
||||
so beating Bugsy retroactively marks the five gym trainers beaten. Then
|
||||
`BugsyText_HiveBadgeSpeech`, `promptbutton`,
|
||||
`verbosegiveitem TM_FURY_CUTTER`, `iffalse .NoRoomForFuryCutter`,
|
||||
`setevent EVENT_GOT_TM49_FURY_CUTTER`, `BugsyText_FuryCutterSpeech`.
|
||||
- `AzaleaGymActivateRockets` - `ifequal 7, .RadioTowerRockets`,
|
||||
`ifequal 6, .GoldenrodRockets`, `end`. `VAR_BADGES`
|
||||
(`constants/script_constants.asm:55`, id 7) is the badge count, which is 2
|
||||
right after HIVEBADGE, so **this scall is a no-op at Bugsy**; it is the shared
|
||||
gym-clear hook that only fires at the 6th and 7th badge.
|
||||
- `TrainerTwinsAmyandmay1` / `TrainerTwinsAmyandmay2` - both use
|
||||
`EVENT_BEAT_TWINS_AMY_AND_MAY`, so you fight **one** twin, whichever spots you
|
||||
first, and the other drops to her after-battle line.
|
||||
- `TrainerBugCatcherBenny` / `...Al` / `...Josh` - plain
|
||||
`trainer BUG_CATCHER, <id>, EVENT_BEAT_BUG_CATCHER_<id>, ...` with
|
||||
`endifjustbattled` after-scripts.
|
||||
- `AzaleaGymGuideScript` - `checkevent EVENT_BEAT_BUGSY`; the pre-battle text is
|
||||
the "bug Pokemon don't like fire, flying-type moves are super-effective" hint.
|
||||
|
||||
**Flags and events**
|
||||
|
||||
| constant | defined in | read/written by | meaning for a bot |
|
||||
|---|---|---|---|
|
||||
| `EVENT_BEAT_BUGSY` | `constants/event_flags.asm:707` | `AzaleaGymBugsyScript` | leader beaten |
|
||||
| `ENGINE_HIVEBADGE` | `constants/engine_flags.asm:39` (`wJohtoBadges`, `data/events/engine_flags.asm:47`) | `setflag` here; read by `CutFunction.CheckAble`, `TryCutOW`, `AzaleaGymStatue`, `engine/battle/core.asm:6566` (obedience) | **the badge that enables field Cut and L30 obedience** |
|
||||
| `EVENT_GOT_TM49_FURY_CUTTER` | `constants/event_flags.asm:15` | `AzaleaGymBugsyScript` | TM49 already handed over |
|
||||
| `EVENT_BEAT_TWINS_AMY_AND_MAY` | `constants/event_flags.asm:608` | both twin objects; force-set by `.FightDone` | one flag, two objects |
|
||||
| `EVENT_BEAT_BUG_CATCHER_BENNY` | `constants/event_flags.asm:843` | `TrainerBugCatcherBenny`; force-set by `.FightDone` | |
|
||||
| `EVENT_BEAT_BUG_CATCHER_AL` | `constants/event_flags.asm:844` | `TrainerBugCatcherAl`; force-set by `.FightDone` | |
|
||||
| `EVENT_BEAT_BUG_CATCHER_JOSH` | `constants/event_flags.asm:845` | `TrainerBugCatcherJosh`; force-set by `.FightDone` | |
|
||||
|
||||
**Items**
|
||||
|
||||
| item | how obtained | source (label / bg_event / hidden) | one-time flag |
|
||||
|---|---|---|---|
|
||||
| `TM_FURY_CUTTER` (TM49) | Bugsy hands it over after the badge speech | `AzaleaGymBugsyScript.FightDone` -> `verbosegiveitem TM_FURY_CUTTER` | `EVENT_GOT_TM49_FURY_CUTTER` |
|
||||
|
||||
**Trainers**
|
||||
|
||||
Base rewards: `BUG_CATCHER` 4 (`data/trainers/attributes.asm:215`),
|
||||
`TWINS` 5 (`:365`), `BUGSY` 25 (`:17`). Money = base x last-mon level x 4.
|
||||
|
||||
| const | class | id | party (`data/trainers/parties.asm` label) | script label | rematch/phone |
|
||||
|---|---|---|---|---|---|
|
||||
| `AMYANDMAY1` | `TWINS` | `constants/trainer_constants.asm:621` | `TwinsGroup` TWINS(1) "AMY & MAY@", `TRAINERTYPE_NORMAL`: L10 `SPINARAK`, L10 `LEDYBA` | `TrainerTwinsAmyandmay1` | no (200 = 5x10x4) |
|
||||
| `AMYANDMAY2` | `TWINS` | `constants/trainer_constants.asm:624` | `TwinsGroup` TWINS(4) "AMY & MAY@", `TRAINERTYPE_NORMAL`: L10 `LEDYBA`, L10 `SPINARAK` | `TrainerTwinsAmyandmay2` | no (200) |
|
||||
| `JOSH` | `BUG_CATCHER` | `constants/trainer_constants.asm:319` | `BugCatcherGroup` BUG_CATCHER(7) "JOSH@", `TRAINERTYPE_NORMAL`: L13 `PARAS` | `TrainerBugCatcherJosh` | no (208 = 4x13x4) |
|
||||
| `BENNY` | `BUG_CATCHER` | `constants/trainer_constants.asm:317` | `BugCatcherGroup` BUG_CATCHER(5) "BENNY@", `TRAINERTYPE_NORMAL`: L7 `WEEDLE`, L9 `KAKUNA`, L12 `BEEDRILL` | `TrainerBugCatcherBenny` | no (192 = 4x12x4) |
|
||||
| `AL` | `BUG_CATCHER` | `constants/trainer_constants.asm:318` | `BugCatcherGroup` BUG_CATCHER(6) "AL@", `TRAINERTYPE_NORMAL`: L12 `CATERPIE`, L12 `WEEDLE` | `TrainerBugCatcherAl` | no (192 = 4x12x4) |
|
||||
| `BUGSY1` | `BUGSY` (class 3, `constants/trainer_constants.asm:33`) | `:34` | `BugsyGroup` "BUGSY@", **`TRAINERTYPE_MOVES`**: L14 `METAPOD` (`TACKLE`, `STRING_SHOT`, `HARDEN`), L14 `KAKUNA` (`POISON_STING`, `STRING_SHOT`, `HARDEN`), L16 `SCYTHER` (`QUICK_ATTACK`, `LEER`, `FURY_CUTTER`) | `AzaleaGymBugsyScript` | no (1600 = 25x16x4) |
|
||||
|
||||
Bugsy's AI/items row (`data/trainers/attributes.asm:17`): `NO_ITEM, NO_ITEM`,
|
||||
`AI_BASIC | AI_SETUP | AI_SMART | AI_AGGRESSIVE | AI_CAUTIOUS | AI_STATUS | AI_RISKY`,
|
||||
`CONTEXT_USE | SWITCH_SOMETIMES`. Bug Catchers are `AI_BASIC | AI_SETUP | AI_STATUS`;
|
||||
Twins are `NO_AI` with `SWITCH_OFTEN`.
|
||||
|
||||
**Wild encounters** - none (indoor).
|
||||
|
||||
## 3. Blockers and gates
|
||||
|
||||
| Gate | Enforced by (file:label) | Requirement | Unlock condition |
|
||||
|---|---|---|---|
|
||||
| Rocket standing on the Slowpoke Well approach | `maps/AzaleaTown.asm` object const 2 at `31, 9`, flag `EVENT_AZALEA_TOWN_SLOWPOKETAIL_ROCKET`. `31, 9` is the only walkable neighbour of `31, 8`, which is the only walkable neighbour of the ladder at `31, 7` (derived from `maps/AzaleaTown.blk` + `data/tilesets/johto_modern_collision.asm`) | talk to Kurt once | `Kurt1` first-visit arm runs `setevent EVENT_AZALEA_TOWN_SLOWPOKETAIL_ROCKET`, which hides him (`Script_disappear` semantics, `engine/overworld/scripting.asm:887`) |
|
||||
| Rocket standing on the Azalea Gym door | `maps/AzaleaTown.asm` object const 12 at `10, 16`, flag `EVENT_SLOWPOKE_WELL_ROCKETS`. `10, 16` is the only walkable neighbour of the gym warp at `10, 15` | clear Slowpoke Well | the four `disappear SLOWPOKEWELLB1F_ROCKET*` calls in `maps/SlowpokeWellB1F.asm` `TrainerGruntM1.Script` set that shared flag |
|
||||
| Slowpoke Well B2F (King's Rock, TM Rain Dance) | `maps/SlowpokeWellB1F.asm` warp 2 at `7, 11`; the chamber's only outside neighbour is water at `7, 14` (derived from `maps/SlowpokeWellB1F.blk` + `data/tilesets/cave_collision.asm` + `data/collision/collision_permissions.asm`) | Surf (`ENGINE_FOGBADGE` + HM03) | out of section - Fog Badge is Morty |
|
||||
| Boulder at Slowpoke Well `3, 2` | `SlowpokeWellB1FBoulder` -> `jumpstd StrengthBoulderScript` | Strength | out of section; nothing behind it is required |
|
||||
| Field Cut (leaving Azalea west for Ilex Forest) | `engine/events/overworld.asm` `CutFunction.CheckAble` (`ld de, ENGINE_HIVEBADGE` / `call CheckBadge` / `jr c, .nohivebadge`, sym `03:47e1`) and `TryCutOW` (`CheckPartyMove` with `CUT`, then `ld de, ENGINE_HIVEBADGE` / `CheckEngineFlag`, sym `03:5193`) | HIVEBADGE **and** a party member that knows CUT | HIVEBADGE from `AzaleaGymBugsyScript`; HM01 itself comes from the Charcoal Kiln / Ilex Forest chain in section 05 |
|
||||
| Pokemon obedience above L30 | `engine/battle/core.asm:6566` masks `(1 << ZEPHYRBADGE) | (1 << HIVEBADGE) | ...` | HIVEBADGE | same |
|
||||
| Bugsy himself | `AzaleaGymBugsyScript` has no `checkevent` guard before the battle | nothing - the five gym trainers are optional | `.FightDone` force-sets all four of their beat events afterwards |
|
||||
|
||||
## 4. Bot checklist
|
||||
|
||||
Coordinates are `x, y` as written in the asm. "warp N" means the Nth
|
||||
`warp_event` row of the source map.
|
||||
|
||||
1. `MAP_AZALEA_TOWN`, walk in from the Route 33 east connection. Post: engine
|
||||
flag `ENGINE_FLYPOINT_AZALEA` set by `AzaleaTownFlypointCallback`
|
||||
(`MAPCALLBACK_NEWMAP`). No input needed.
|
||||
2. `MAP_AZALEA_TOWN`, walk to `9, 5` and step on it -> warp 4 ->
|
||||
`MAP_KURTS_HOUSE` `3, 7`. Pre: none.
|
||||
3. `MAP_KURTS_HOUSE`, walk to `3, 3`, face UP, press A on object const 2
|
||||
(`KURTSHOUSE_KURT1`, `3, 2`). Pre: `EVENT_CLEARED_SLOWPOKE_WELL` clear and
|
||||
`EVENT_KURT_GAVE_YOU_LURE_BALL` clear. Post:
|
||||
`EVENT_AZALEA_TOWN_SLOWPOKETAIL_ROCKET` set, `EVENT_KURTS_HOUSE_KURT_1` set
|
||||
(Kurt walks out). If the player is facing UP when the script starts, Kurt
|
||||
takes the `.RunAround` movement instead - same result, one extra step.
|
||||
4. `MAP_KURTS_HOUSE`, step on `3, 7` or `4, 7` -> `MAP_AZALEA_TOWN` warp 4 (`9, 5`).
|
||||
5. Optional heal: `MAP_AZALEA_TOWN` `15, 9` -> `MAP_AZALEA_POKECENTER_1F`;
|
||||
talk to object const 2 at `3, 1` (`jumpstd PokecenterNurseScript`); leave via
|
||||
`3, 7`.
|
||||
6. `MAP_AZALEA_TOWN`, walk east along row 10 to `31, 10`, north to `31, 9`
|
||||
(now empty), `31, 8`, then step on `31, 7` -> warp 6 -> `MAP_SLOWPOKE_WELL_B1F`
|
||||
`17, 15`. Optional: from `31, 7` face UP and press A for the hidden
|
||||
`FULL_HEAL` at `31, 6` (post: `EVENT_AZALEA_TOWN_HIDDEN_FULL_HEAL`).
|
||||
7. `MAP_SLOWPOKE_WELL_B1F`, optional A on const 8 (`16, 14`, Kurt).
|
||||
8. Walk north along column 15 to `15, 8`. Trigger: const 2 `TrainerGruntM29`
|
||||
(sight 1, faces right). Battle `GRUNTM` / `GRUNTM_29` (L9 Rattata x2).
|
||||
Post: `EVENT_BEAT_ROCKET_GRUNTM_29`. Optional A again for the after-battle text.
|
||||
9. Continue north column 14 to `14, 4`, then west into the top room. Trigger:
|
||||
const 5 `TrainerGruntF1` at `13, 2` (sight 2, faces down) from `13, 3` or
|
||||
`13, 4`. Battle `GRUNTF` / `GRUNTF_1` (L9 Zubat, L11 Ekans). Post:
|
||||
`EVENT_BEAT_ROCKET_GRUNTF_1`.
|
||||
10. Walk to `11, 3` -> `10, 3`, press A on const 10 -> `SUPER_POTION`. Post:
|
||||
`EVENT_SLOWPOKE_WELL_B1F_SUPER_POTION`.
|
||||
11. Go to `11, 4` -> `11, 5` -> `11, 6`, then west along row 6. Trigger: const 4
|
||||
`TrainerGruntM2` at `5, 6` (sight 2, faces right) from `7, 6` or `6, 6`.
|
||||
Battle `GRUNTM` / `GRUNTM_2` (L7 Rattata, L9 Zubat, L9 Zubat). Post:
|
||||
`EVENT_BEAT_ROCKET_GRUNTM_2`.
|
||||
12. Optional: `7, 5` face UP, A on const 6 at `7, 4` (Slowpoke with mail,
|
||||
`yesorno` -> read). No flag.
|
||||
13. Walk to `5, 3`. Trigger: const 3 `TrainerGruntM1` at `5, 2` (sight 1, faces
|
||||
down). Battle `GRUNTM` / `GRUNTM_1` (L14 Koffing). Post:
|
||||
`EVENT_BEAT_ROCKET_GRUNTM_1`, then `.Script` runs with no `endifjustbattled`,
|
||||
so the whole cutscene plays automatically and ends with
|
||||
`special HealParty` + `warp KURTS_HOUSE, 3, 3`. Post-flags to assert:
|
||||
`EVENT_CLEARED_SLOWPOKE_WELL`, `EVENT_SLOWPOKE_WELL_ROCKETS`,
|
||||
`EVENT_SLOWPOKE_WELL_SLOWPOKES`, `EVENT_SLOWPOKE_WELL_KURT`,
|
||||
`EVENT_CHARCOAL_KILN_FARFETCH_D`, `EVENT_CHARCOAL_KILN_APPRENTICE`;
|
||||
cleared: `EVENT_AZALEA_TOWN_SLOWPOKES`, `EVENT_KURTS_HOUSE_SLOWPOKE`,
|
||||
`EVENT_KURTS_HOUSE_KURT_1`, `EVENT_ILEX_FOREST_APPRENTICE`,
|
||||
`EVENT_ILEX_FOREST_FARFETCHD_1`; scene: `AZALEA_TOWN` -> `SCENE_AZALEATOWN_RIVAL_BATTLE`.
|
||||
14. `MAP_KURTS_HOUSE` at `3, 3`, face UP, A on const 2. Pre:
|
||||
`EVENT_CLEARED_SLOWPOKE_WELL` set, `EVENT_KURT_GAVE_YOU_LURE_BALL` clear.
|
||||
Post: `LURE_BALL` in bag, `EVENT_KURT_GAVE_YOU_LURE_BALL` set. The script
|
||||
then falls straight into the apricorn prompt - answer no unless you want to
|
||||
hand over the White Apricorn you have not picked yet.
|
||||
15. Leave via `3, 7`; in `MAP_AZALEA_TOWN` walk to `8, 3`, face UP, A on const 10
|
||||
at `8, 2` -> `WHT_APRICORN` (daily). Optional: return to Kurt and give it
|
||||
(`special SelectApricornForKurt`, post: `EVENT_GAVE_KURT_WHT_APRICORN` +
|
||||
`ENGINE_KURT_MAKING_BALLS`), then come back a real in-game day later for
|
||||
`FAST_BALL`.
|
||||
16. Optional heal at the Pokecenter (`15, 9`).
|
||||
17. `MAP_AZALEA_TOWN`, walk to `10, 17` -> `10, 16` (now empty) -> step on
|
||||
`10, 15` -> warp 5 -> `MAP_AZALEA_GYM` `4, 15`.
|
||||
18. `MAP_AZALEA_GYM`: optional A on const 8 at `7, 13` for the type hint.
|
||||
Walk `4, 14` -> `4, 13` -> `4, 12` -> `4, 11`. Trigger: const 6
|
||||
`TrainerTwinsAmyandmay1` at `4, 10` (sight 1). Battle `TWINS` / `AMYANDMAY1`
|
||||
(L10 Spinarak, L10 Ledyba). Post: `EVENT_BEAT_TWINS_AMY_AND_MAY`, which also
|
||||
retires const 7.
|
||||
19. West along row 11 to `0, 11`, north up column 0 to `0, 5`. Trigger: const 5
|
||||
`TrainerBugCatcherJosh` at `0, 2` (sight 3, faces down). Battle
|
||||
`BUG_CATCHER` / `JOSH` (L13 Paras). Post: `EVENT_BEAT_BUG_CATCHER_JOSH`.
|
||||
20. North to `0, 3`, east along row 3 toward `4, 3`. Trigger: const 3
|
||||
`TrainerBugCatcherBenny` at `5, 3` (sight 2, spins). Battle
|
||||
`BUG_CATCHER` / `BENNY` (L7 Weedle, L9 Kakuna, L12 Beedrill). Post:
|
||||
`EVENT_BEAT_BUG_CATCHER_BENNY`.
|
||||
21. East along row 2/3 to column 8-9, south to `8, 11`. Trigger: const 4
|
||||
`TrainerBugCatcherAl` at `8, 8` (sight 3, faces down). Battle
|
||||
`BUG_CATCHER` / `AL` (L12 Caterpie, L12 Weedle). Post:
|
||||
`EVENT_BEAT_BUG_CATCHER_AL`.
|
||||
22. Route into the middle: `4, 3` or `5, 3` row -> `4, 4` -> `4, 5` -> `3, 5` ->
|
||||
`3, 6` -> `3, 7` -> `4, 7`, face RIGHT, A on const 2 at `5, 7`. Pre:
|
||||
`EVENT_BEAT_BUGSY` clear. Battle `BUGSY` / `BUGSY1` (L14 Metapod, L14 Kakuna,
|
||||
L16 Scyther). Post: `EVENT_BEAT_BUGSY`, `ENGINE_HIVEBADGE`, then the same
|
||||
conversation continues and yields `TM_FURY_CUTTER` +
|
||||
`EVENT_GOT_TM49_FURY_CUTTER` and force-sets the four gym-trainer events.
|
||||
A bot that wants the badge fast can skip steps 19-21 entirely.
|
||||
23. Leave via `4, 15` / `5, 15`. Next section starts when you walk west and hit
|
||||
`coord_event 5, 10` / `5, 11`.
|
||||
|
||||
## 5. Port coverage
|
||||
|
||||
| Beat | Port file | Status |
|
||||
|---|---|---|
|
||||
| Map data for all six maps (blocks, connections, warps, coord/bg/object events, `scriptKey`) | `src/import/RomExtractorGen2.lua` (`self:write("maps", out)`, line 987), consumed by `src/world/gen2/Map.lua` | implemented - `docs/gold-phase1.md` states all 368 maps extract |
|
||||
| Collision / walkability (`COLL_*` quads, block -> cell) | `src/world/gen2/Map.lua` `Map:cellCollision`, `src/world/gen2/Permissions.lua` | implemented (quad order `ly*2 + lx` matches `gfx/tilesets.asm` `tilecoll`) |
|
||||
| Warps between these maps | `src/world/gen2/World.lua` + `Map:warpAt`; driver `tests/drivers/gold_warp_scene.lua` | implemented |
|
||||
| Map callbacks (`MAPCALLBACK_NEWMAP` flypoint, `MAPCALLBACK_OBJECTS` Kurt swap) | `src/world/gen2/World.lua`, driver `tests/drivers/gold_map_callbacks.lua` | implemented |
|
||||
| Script VM opcodes used here (`checkevent`/`setevent`/`clearevent`, `checkflag`/`setflag`, `readvar`, `scall`, `jumpstd`, `special`, `warp`, `setscene`/`setmapscene`, `loadtrainer`/`startbattle`/`winlosstext`/`endifjustbattled`, `applymovement`, `moveobject`, `showemote`, `variablesprite`, `verbosegiveitem`, `yesorno`, `checkitem`, `promptbutton`, `fruittree`) | `src/script/gen2/Opcodes.lua`, `src/script/gen2/Vm.lua` | implemented - every opcode in this section's scripts has a row and a VM arm |
|
||||
| Specials used here (`FadeOutToBlack`, `FadeInFromBlack`, `FadeOutToWhite`, `ReloadSpritesNoPalettes`, `HealParty`, `SelectApricornForKurt`, `FadeOutMusic`/`RestartMapMusic`) | `src/script/gen2/Specials.lua` | implemented (spot-checked `FadeOutToBlack`, `ReloadSpritesNoPalettes`, `HealParty`, `SelectApricornForKurt`) |
|
||||
| Trainer sight lines / approach walk (the four grunts, the five gym trainers) | `src/world/gen2/Trainers.lua` (`Trainers.sees`, `Trainers.approach`), wired at `src/world/gen2/World.lua:5212-5264`; driver `tests/drivers/gold_trainer_smoke.lua` | implemented |
|
||||
| Trainer parties + class attributes | `src/import/RomExtractorGen2.lua` (trainers), `src/world/gen2/Trainers.lua`, `src/battle/gen2/Battle.lua` (`BUGSY` in the gym-leader set, line 85) | implemented |
|
||||
| Prize money (base x level x 4, Mom's split) | `src/battle/gen2/Prize.lua` | implemented, and it ports the `ld c, 4` loop and `.DoubleReward` faithfully |
|
||||
| Badge storage + `VAR_BADGES` count | `src/core/gen2/Save.lua` (`player.badges`, `player.kantoBadges`), `src/world/gen2/World.lua:1241-1244`, `World:engineFlags` (`:1304`) | implemented |
|
||||
| Cut gate on `ENGINE_HIVEBADGE` | `src/world/gen2/FieldMoves.lua` (`FieldMoves.BADGE.CUT = "HIVE"`, `cutFromMenu`, the overworld ask path) | implemented |
|
||||
| Fly point `ENGINE_FLYPOINT_AZALEA` | `src/world/gen2/FieldMoves.lua:347` (`LANDMARK_AZALEA_TOWN` / `SPAWN_AZALEA` / flag 67) | implemented |
|
||||
| Hidden item at `31, 6` (`BGEVENT_ITEM`) | `src/world/gen2/HiddenItems.lua` | implemented (module exists and the extractor carries `hiddenItem = { item, event }`); not exercised by any Azalea driver |
|
||||
| Kurt / apricorn conversation, `ENGINE_KURT_MAKING_BALLS` day wait, Lure Ball, Fast Ball | `src/core/gen2/Apricorns.lua` | implemented at the model level; the file is written against `maps/KurtsHouse.asm` directly and lists `FRUITTREE_AZALEA_TOWN` -> `WHT_APRICORN` at index `0x14` |
|
||||
| Item balls (`OBJECTTYPE_ITEMBALL`: Super Potion at B1F `10, 3`, TM Rain Dance at B2F `15, 5`) | extracted by `src/import/RomExtractorGen2.lua:2968`; **no runtime handler found in `src/world/gen2/World.lua`** | **missing** - the object data is there, nothing picks it up |
|
||||
| `fruittree` at runtime (White Apricorn tree object) | opcode row exists (`src/script/gen2/Opcodes.lua`, `[0x9a]`) and `Vm.lua` references it; the daily-tree store is described in `src/core/gen2/Apricorns.lua` (`save.fruitTrees`) | partial - modelled, not verified end to end in a driver |
|
||||
| Wild encounters for Slowpoke Well (grass 3-slot time split, water, fishing) | `src/import/RomExtractorGen2.lua` (Encounters), `src/battle/gen2/Encounter.lua` | implemented per `docs/gold-phase1.md`; not verified for this map specifically |
|
||||
| A driver that walks any part of this section | none - `tests/drivers/gold_*.lua` has nothing matching azalea / slowpoke / kurt / bugsy | **missing** |
|
||||
|
||||
## 6. Unresolved / verify by hand
|
||||
|
||||
- **Bug Catcher Al's prize.** The walkthrough says 200G. The asm gives
|
||||
4 (`data/trainers/attributes.asm:215`) x 12 (last mon, L12 Weedle) x 4 = **192G**.
|
||||
Every other figure in the section matches the formula exactly
|
||||
(360 / 440 / 360 / 560 / 200 / 208 / 192 / 1600), so this looks like a
|
||||
walkthrough typo, not a special case.
|
||||
- **Bugsy's gender.** The walkthrough says "Bugsy and her apprentices" and
|
||||
"she may have the Bug Pokemon". `AzaleaGymGuideText` in `maps/AzaleaGym.asm`
|
||||
says "BUGSY's young, but **his** knowledge of bug #MON is for real". The asm
|
||||
wins.
|
||||
- **"Liz the Picnicker calls about Moo Moo Milk."** `LizPhoneCallerScript`
|
||||
(`engine/phone/scripts/trainers.asm:234-254`) only does
|
||||
`PhoneScript_GreetPhone_Female`, a `checkflag ENGINE_FLYPOINT_GOLDENROD`
|
||||
rematch gate, `PhoneScript_Random2` and `Phone_GenericCall_Female` /
|
||||
`Phone_CheckIfUnseenRare_Female`. There is no Moo Moo Milk text in her script,
|
||||
and no `MOOMOO` string turned up anywhere under `engine/phone/`. The generic
|
||||
call pool may contain such a line, but it is not attributable to Liz from the
|
||||
map/phone scripts - unresolved.
|
||||
- **"TM49" listed under *Items found in Azalea Town*.** TM49 is
|
||||
`verbosegiveitem TM_FURY_CUTTER` inside `AzaleaGymBugsyScript`, i.e. found in
|
||||
`MAP_AZALEA_GYM`, not on the town map. Cosmetic, but a bot indexing by map
|
||||
should not look for it outdoors.
|
||||
- **Battle order inside Slowpoke Well.** The walkthrough's "move on up the
|
||||
stairs", "head down the stairs" prose does not correspond to any `LADDER` or
|
||||
`STAIRCASE` collision inside B1F - the only two ladder cells are the two warps
|
||||
(`17, 15` and `7, 11`). The trainer order it describes (M29 -> F1 -> M2 -> M1)
|
||||
does match the geometry, so the "stairs" are just prose for the corridors.
|
||||
- **`SLOWPOKE_WELL_B2F` reachability.** I derived "Surf only" from
|
||||
`maps/SlowpokeWellB1F.blk` decoded against `data/tilesets/cave_collision.asm`
|
||||
and `data/collision/collision_permissions.asm`; no script or engine check
|
||||
states it. If a future reader wants a stronger citation, it would have to come
|
||||
from the block data, not from an `EVENT_*`.
|
||||
- **Gym-trainer skippability.** The claim that Josh, Al and (via the column-7
|
||||
stalk) the twins can be walked past is derived from `maps/AzaleaGym.blk` plus
|
||||
each object's sight field, not asserted anywhere in the asm. The retroactive
|
||||
`setevent` block in `AzaleaGymBugsyScript.FightDone` is direct asm evidence
|
||||
that skipping them is an anticipated state, but the exact dodge path should be
|
||||
confirmed in-game before a driver depends on it.
|
||||
- **`variablesprite SPRITE_AZALEA_ROCKET, SPRITE_RIVAL`.** This is why
|
||||
`AZALEATOWN_RIVAL` is declared with `SPRITE_AZALEA_ROCKET` in
|
||||
`maps/AzaleaTown.asm`. It also means consts 2 and 12 on that map would draw as
|
||||
the rival if they were still visible after the well is cleared - they are not,
|
||||
because both are hidden by then. Worth a look if a port ever renders them.
|
||||
Reference in New Issue
Block a user