-- Jessie & James, Yellow's Team Rocket duo, at all four ambush sites: -- Mt Moon B2F (scripts/MtMoonB2F.asm), Rocket Hideout B4F -- (scripts/RocketHideoutB4F.asm), Pokemon Tower 7F -- (scripts/PokemonTower7F.asm) and Silph Co 11F (scripts/SilphCo11F.asm). -- Every site shares one shape: a coordinate trigger swaps the map theme -- for Music_MeetJessieJames, the motto plays, the duo closes in, one -- battle against the shared OPP_ROCKET party fights them both, and after -- their parting lines they vanish together under a second sting of the -- theme before the map theme resumes (PlayDefaultMusic -> -- play_default_music). -- -- Registered on top of the shared tables by data/scripts/init.lua on a -- Yellow boot; MT_MOON_B2F's onStep chains story2's Super Nerd / fossil -- trigger and SILPH_CO_11F's chains story's Giovanni trigger, since -- non-talk hooks replace rather than merge. local M = {} -- Capture the FUNCTION, not the table: attachBase stores the module -- table itself, so once this file's onStep is attached the table's slot -- points back here -- delegating through the table would self-recurse. local baseMtMoonStep = require("data.scripts.story2").MT_MOON_B2F.onStep local baseSilph11Step = require("data.scripts.story").SILPH_CO_11F.onStep M.MT_MOON_B2F = { talk = { TEXT_MTMOONB2F_JESSIE = { { "face_player" }, { "show_text", "_MtMoonJessieJamesText1" }, }, TEXT_MTMOONB2F_JAMES = { { "face_player" }, { "show_text", "_MtMoonJessieJamesText1" }, }, }, onStep = function(game, ow, x, y) if baseMtMoonStep and baseMtMoonStep(game, ow, x, y) then return true end local f = game.save.flags if x ~= 3 or y ~= 5 then return false end if f.EVENT_BEAT_MT_MOON_3_JESSIE_JAMES then return false end if not (f.EVENT_GOT_DOME_FOSSIL or f.EVENT_GOT_HELIX_FOSSIL) then return false end ow.runner:run({ { "stop_music" }, { "play_music", "Music_MeetJessieJames" }, { "show_object", "MT_MOON_B2F", "MTMOONB2F_JESSIE" }, { "show_object", "MT_MOON_B2F", "MTMOONB2F_JAMES" }, { "show_text", "_MtMoonJessieJamesText1" }, { "face_player_dir", "up" }, { "emote", "player", "shock", 30 }, -- MtMoonB2FScript_49e15 simulates PAD_UP for one player step, then -- Script6/Script9 walk Jessie (object 2, MovementData_f9e65: six -- $06) and James (object 6, f9e66: five $06); both objects' movement -- byte 2 is LEFT, so .determineDirection makes those LEFT steps -- -- Jessie (9,3)->(3,3) above the player at (3,4), James (9,4)->(4,4) -- beside him. #423 { "walk_npc", "player", { "up" } }, { "walk_npc", 2, { "left", "left", "left", "left", "left", "left" } }, { "face_object", 2, "down" }, { "walk_npc", 6, { "left", "left", "left", "left", "left" } }, { "face_object", 6, "left" }, { "show_text", "_MtMoonJessieJamesText2" }, -- MtMoonB2FScript12 arms _MtMoonJessieJamesText3 with -- SaveEndBattleTextPointers before it sets wCurOpponent, so -- TrainerBattleVictory prints it on the battle screen as "ROCKET: A -- brat beat us?" between TrainerDefeatedText and MoneyForWinningText. -- Its one-word first line only reads right behind that tag (#866). { "save_end_battle_text", "_MtMoonJessieJamesText3" }, { "start_battle", "trainer", "OPP_ROCKET", 42 }, { "check_battle_result", "win" }, { "jump_if_false", "end" }, { "show_text", "_MtMoonJessieJamesText4" }, { "stop_music" }, { "play_music", "Music_MeetJessieJames" }, { "fade", "out" }, { "hide_object", "MT_MOON_B2F", "MTMOONB2F_JESSIE" }, { "hide_object", "MT_MOON_B2F", "MTMOONB2F_JAMES" }, { "fade", "in" }, { "play_default_music" }, { "set_flag", "EVENT_BEAT_MT_MOON_3_JESSIE_JAMES" }, }, {}) return true end, } -- ------------------------------------------------------------------- -- Rocket Hideout B4F (RocketHideoutB4FScript_455a5..Script13): the -- motto plays from off-screen FIRST, then the duo pops in at (25,10) / -- (24,10) and whichever of them shares the player's column ($18=24 or -- $19=25, EVENT_ROCKET_HIDEOUT_4_JESSIE_JAMES_ON_LEFT) walks the three -- tiles down to loom over the player while the other walks four and ends -- up beside him. A loss -- re-hides them (RocketHideoutB4FResetScripts via EVENT_6A0), so the -- trigger re-arms clean. -- ------------------------------------------------------------------- M.ROCKET_HIDEOUT_B4F = { talk = { TEXT_ROCKETHIDEOUTB4F_JESSIE = { { "face_player" }, { "show_text", "_RocketHideoutJessieJamesText1" }, }, TEXT_ROCKETHIDEOUTB4F_JAMES = { { "face_player" }, { "show_text", "_RocketHideoutJessieJamesText1" }, }, }, onStep = function(game, ow, x, y) local f = game.save.flags if y ~= 14 or (x ~= 24 and x ~= 25) then return false end if f.EVENT_BEAT_ROCKET_HIDEOUT_4_JESSIE_JAMES then return false end -- ON_LEFT: player under James's column (25); movement data pairs -- RocketHideoutB4FJessieJamesMovementData_45605/45606 swap so the -- column-mate walks 3, the other 4. local onLeft = (x == 25) ow.runner:run({ { "stop_music" }, { "play_music", "Music_MeetJessieJames" }, { "show_text", "_RocketHideoutJessieJamesText1" }, { "face_player_dir", "up" }, { "emote", "player", "shock", 30 }, { "show_object", "ROCKET_HIDEOUT_B4F", "ROCKETHIDEOUTB4F_JAMES" }, { "show_object", "ROCKET_HIDEOUT_B4F", "ROCKETHIDEOUTB4F_JESSIE" }, -- James (object 2) then Jessie (object 3), Script4..Script9 order. -- RocketHideoutB4FJessieJamesMovementData_45605 is a lone $4 that FALLS -- THROUGH into _45606 ($4 $4 $4 $ff), so MoveSprite_ (home/pathfinding.asm) -- reads _45605 as FOUR steps and _45606 as three; $4 is DOWN in Yellow's -- Func_5288 lookup (engine/overworld/movement.asm), which walks with no -- collision test. From (25,10)/(24,10) against a player on y=14 the -- column-mate stops three down, right above him, and the other walks the -- full four to stand alongside -- which is what the facings below assume. -- Reading _45605 as a single step stranded whoever was off-column three -- tiles away, so James never reached the player (#865). { "walk_npc", 2, onLeft and { "down", "down", "down" } or { "down", "down", "down", "down" } }, { "face_object", 2, onLeft and "down" or "left" }, { "walk_npc", 3, onLeft and { "down", "down", "down", "down" } or { "down", "down", "down" } }, { "face_object", 3, onLeft and "right" or "down" }, { "show_text", "_RocketHideoutJessieJamesText2" }, -- RocketHideoutB4FScript10 saves _RocketHideoutJessieJamesText3 as the -- end-battle text, so it prints as "ROCKET: Such a dreadful twerp!" on -- the battle screen ahead of MoneyForWinningText (#866). { "save_end_battle_text", "_RocketHideoutJessieJamesText3" }, { "start_battle", "trainer", "OPP_ROCKET", 43 }, { "check_battle_result", "win" }, { "jump_if_false", "lost" }, { "show_text", "_RocketHideoutJessieJamesText4" }, { "stop_music" }, { "play_music", "Music_MeetJessieJames" }, { "fade", "out" }, { "hide_object", "ROCKET_HIDEOUT_B4F", "ROCKETHIDEOUTB4F_JAMES" }, { "hide_object", "ROCKET_HIDEOUT_B4F", "ROCKETHIDEOUTB4F_JESSIE" }, { "fade", "in" }, { "play_default_music" }, { "set_flag", "EVENT_BEAT_ROCKET_HIDEOUT_4_JESSIE_JAMES" }, { "jump", "end" }, { "label", "lost" }, { "hide_object", "ROCKET_HIDEOUT_B4F", "ROCKETHIDEOUTB4F_JAMES" }, { "hide_object", "ROCKET_HIDEOUT_B4F", "ROCKETHIDEOUTB4F_JESSIE" }, }, {}) return true end, } -- ------------------------------------------------------------------- -- Pokemon Tower 7F (PokemonTower7FScript_60d2a..Script10): same beat -- one floor below Fuji, except the duo pops in BEFORE the motto and -- Jessie ($a=10 column) leads the walk-down; ON_LEFT ($b=11) hands the -- three-tile walk to James instead. On a loss vanilla only resets the -- script counter (the blackout warp reloads the map anyway). -- ------------------------------------------------------------------- M.POKEMON_TOWER_7F = { talk = { TEXT_POKEMONTOWER7F_JESSIE = { { "face_player" }, { "show_text", "_PokemonTowerJessieJamesText1" }, }, TEXT_POKEMONTOWER7F_JAMES = { { "face_player" }, { "show_text", "_PokemonTowerJessieJamesText1" }, }, }, onStep = function(game, ow, x, y) local f = game.save.flags if y ~= 12 or (x ~= 10 and x ~= 11) then return false end if f.EVENT_BEAT_POKEMONTOWER_7_JESSIE_JAMES then return false end local onLeft = (x == 11) -- EVENT_POKEMONTOWER_7_JESSIE_JAMES_ON_LEFT ow.runner:run({ { "stop_music" }, { "play_music", "Music_MeetJessieJames" }, { "show_object", "POKEMON_TOWER_7F", "POKEMONTOWER7F_JESSIE" }, { "show_object", "POKEMON_TOWER_7F", "POKEMONTOWER7F_JAMES" }, { "show_text", "_PokemonTowerJessieJamesText1" }, { "face_player_dir", "up" }, { "emote", "player", "shock", 30 }, -- Jessie (object 1) then James (object 2), Script1..Script6 order. -- Same fall-through blob as the hideout: PokemonTower7FMovementData_60d7a -- is a lone $4 running into _60d7b ($4 $4 $4 $FF), so _60d7a is FOUR -- steps and _60d7b is three. From (10,8)/(11,8) against a player on -- y=12 the column-mate halts one tile above him and the other closes the -- full four to his side; the single-step reading is why James only -- "moved a bit" here (#865). { "walk_npc", 1, onLeft and { "down", "down", "down", "down" } or { "down", "down", "down" } }, { "face_object", 1, onLeft and "right" or "down" }, { "walk_npc", 2, onLeft and { "down", "down", "down" } or { "down", "down", "down", "down" } }, { "face_object", 2, onLeft and "down" or "left" }, { "show_text", "_PokemonTowerJessieJamesText2" }, -- PokemonTower7FScript7 saves _PokemonTowerJessieJamesText3 as the -- end-battle text: "ROCKET: You will regret this!" on the battle screen, -- before the prize money (#866). { "save_end_battle_text", "_PokemonTowerJessieJamesText3" }, { "start_battle", "trainer", "OPP_ROCKET", 44 }, { "check_battle_result", "win" }, { "jump_if_false", "end" }, { "show_text", "_PokemonTowerJessieJamesText4" }, { "stop_music" }, { "play_music", "Music_MeetJessieJames" }, { "fade", "out" }, { "hide_object", "POKEMON_TOWER_7F", "POKEMONTOWER7F_JESSIE" }, { "hide_object", "POKEMON_TOWER_7F", "POKEMONTOWER7F_JAMES" }, { "fade", "in" }, { "play_default_music" }, { "set_flag", "EVENT_BEAT_POKEMONTOWER_7_JESSIE_JAMES" }, }, {}) return true end, } -- ------------------------------------------------------------------- -- Silph Co 11F (SilphCo11FScript_6229c..Script14): the only site where -- the duo starts VISIBLE (toggleable_objects.asm keeps SILPHCO11F_JAMES -- / _JESSIE ON), flanking Giovanni at (2,8)/(3,8), so they are talkable -- before the ambush (SilphCo11FJessieJamesText = the full motto). The -- trigger is the top row (y=3, x<4); EVENT_780/EVENT_781 pick one of -- three approach paths (SilphCo11FMovementData_622f5..62311, $5=up -- $6=left) that route James then Jessie up to the player without ever -- crossing the player's tile. Their duo text lives in -- text/SilphCo10F.asm (_SilphCoJessieJamesText*). -- ------------------------------------------------------------------- M.SILPH_CO_11F = { talk = { TEXT_SILPHCO11F_JESSIE = { { "face_player" }, { "show_text", "_SilphCoJessieJamesText1" }, }, TEXT_SILPHCO11F_JAMES = { { "face_player" }, { "show_text", "_SilphCoJessieJamesText1" }, }, }, onStep = function(game, ow, x, y) if baseSilph11Step and baseSilph11Step(game, ow, x, y) then return true end local f = game.save.flags if y ~= 3 or x > 3 then return false end if f.EVENT_BEAT_SILPH_CO_11F_JESSIE_JAMES then return false end -- x==3 -> base path, x==2 -> EVENT_780 variant, x<=1 -> EVENT_781 local jamesDirs, jamesFace, jessieDirs, jessieFace if x == 3 then jamesDirs, jamesFace = { "up", "up", "up", "up", "up" }, "right" jessieDirs, jessieFace = { "up", "up", "up", "up" }, "up" elseif x == 2 then jamesDirs, jamesFace = { "up", "up", "up", "up" }, "up" jessieDirs, jessieFace = { "up", "up", "up", "up", "up" }, "left" else jamesDirs = { "up", "up", "left", "up", "up" } jamesFace = "up" jessieDirs = { "up", "up", "up", "left", "up", "up" } jessieFace = "left" end ow.runner:run({ { "stop_music" }, { "play_music", "Music_MeetJessieJames" }, { "show_text", "_SilphCoJessieJamesText1" }, { "face_player_dir", "down" }, { "emote", "player", "shock", 30 }, -- James (object 4) then Jessie (object 6), Script5..Script10 order { "walk_npc", 4, jamesDirs }, { "face_object", 4, jamesFace }, { "walk_npc", 6, jessieDirs }, { "face_object", 6, jessieFace }, { "show_text", "_SilphCoJessieJamesText2" }, -- SilphCo11FScript11 saves _SilphCoJessieJamesText3 (SilphCo11FText_624c2) -- as the end-battle text: "ROCKET: Like always..." before the money (#866). { "save_end_battle_text", "_SilphCoJessieJamesText3" }, { "start_battle", "trainer", "OPP_ROCKET", 45 }, { "check_battle_result", "win" }, { "jump_if_false", "end" }, { "show_text", "_SilphCoJessieJamesText4" }, { "stop_music" }, { "play_music", "Music_MeetJessieJames" }, { "fade", "out" }, { "hide_object", "SILPH_CO_11F", "SILPHCO11F_JAMES" }, { "hide_object", "SILPH_CO_11F", "SILPHCO11F_JESSIE" }, { "fade", "in" }, { "play_default_music" }, { "set_flag", "EVENT_BEAT_SILPH_CO_11F_JESSIE_JAMES" }, }, {}) return true end, } return M