CLOSES #806, CLOSES #809, CLOSES #853, CLOSES #854, CLOSES #860, CLOSES #862, CLOSES #865, CLOSES #866

This commit is contained in:
bryanthaboi
2026-08-05 14:38:10 -04:00
parent 104c95a942
commit 863f371e68
25 changed files with 1746 additions and 74 deletions
+6 -2
View File
@@ -16,9 +16,13 @@ local function push(game, s, done)
game.stack:push(TextBox.new(game, s, done))
end
-- PrintText on a text_end string returns with the box still drawn and
-- YesNoChoice then draws the menu above it (InitYesNoTextBoxParameters,
-- engine/menus/text_box.asm); no A press clears the question first. Ride
-- TextBox's opts.choice, the same as Commands.ask (#854).
local function ask(game, s, cb)
local ChoiceBox = require("src.ui.ChoiceBox")
push(game, s, function() game.stack:push(ChoiceBox.new(game, cb)) end)
local TextBox = require("src.render.TextBox")
game.stack:push(TextBox.new(game, s, nil, { choice = cb }))
end
M.PEWTER_CITY = {
+6 -2
View File
@@ -23,9 +23,13 @@ local function push(game, s, done)
game.stack:push(TextBox.new(game, s, done))
end
-- PrintText on a text_end string returns with the box still drawn and
-- YesNoChoice then draws the menu above it (InitYesNoTextBoxParameters,
-- engine/menus/text_box.asm); no A press clears the question first. Ride
-- TextBox's opts.choice, the same as Commands.ask (#854).
local function ask(game, s, cb)
local ChoiceBox = require("src.ui.ChoiceBox")
push(game, s, function() game.stack:push(ChoiceBox.new(game, cb)) end)
local TextBox = require("src.render.TextBox")
game.stack:push(TextBox.new(game, s, nil, { choice = cb }))
end
M.VIRIDIAN_CITY = {
+45 -12
View File
@@ -517,6 +517,14 @@ M.GAME_CORNER = {
done()
return
end
-- GameCornerRocketText hands the battle its own loss line through
-- SaveEndBattleTextPointers (.BattleEndText ->
-- _GameCornerRocketBattleEndText, "Dang!"), and PrintEndBattleText
-- prints it ON the battle screen between TrainerDefeatedText and
-- MoneyForWinningText (engine/battle/core.asm TrainerBattleVictory).
-- He is a text_asm trainer with no def_trainers header, so there is no
-- header.won for engageTrainer to find and the line has to be handed
-- over here or it never shows at all (#862).
ow:engageTrainer(npc, function()
if not ow:trainerDefeated(npc) then
done()
@@ -527,19 +535,44 @@ M.GAME_CORNER = {
game.data.text._GameCornerRocketAfterBattleText
or "Our hideout might\nbe discovered! I\nbetter tell BOSS!",
function()
-- #198: GameCornerRocketExitScript (scripts/GameCorner.asm)
-- ApplyMovementData walks the grunt one tile UP into the poster
-- (the hideout's secret entrance at 9,4) before HideObject, so
-- he leaves the floor rather than popping out of existence on
-- (9,5). scriptMove locks player input (#scriptMoves>0) and
-- ignores collision, so we despawn + unfreeze (done) only once
-- the step lands.
ow:scriptMove(npc, "up", 1, function()
hideRocket()
done()
end)
-- #198/#862: GameCornerRocketBattleScript (scripts/GameCorner.asm)
-- picks the exit walk from where the player is standing, because
-- the grunt on (9,5) has to get past him: wYCoord == 6 (talked to
-- from the south) or wXCoord == 8 (from the west) leaves the row
-- clear and takes GameCornerMovement_Rocket_WalkDirect, five steps
-- RIGHT; otherwise the player is east of him on (10,5) and
-- GameCornerMovement_Rocket_WalkAroundPlayer steps DOWN, right, UP
-- and right again to go AROUND him. pokeyellow's copy of the
-- around-path takes one extra RIGHT on the lower row before coming
-- back up (it also has to clear Pikachu); both versions end on
-- (15,5). He never steps UP: (9,4) is the poster wall, which is
-- where the old single UP step sent him.
local px = ow.player and ow.player.cellX
local py = ow.player and ow.player.cellY
local path
if py == 6 or px == 8 then
path = { { "right", 5 } }
elseif require("src.core.GameVersion").isYellow() then
path = { { "down", 1 }, { "right", 3 }, { "up", 1 }, { "right", 3 } }
else
path = { { "down", 1 }, { "right", 2 }, { "up", 1 }, { "right", 4 } }
end
-- GameCornerRocketExitScript only HideObjects him once
-- BIT_SCRIPTED_NPC_MOVEMENT clears, i.e. after the last step.
-- scriptMove locks player input (#scriptMoves>0) and ignores
-- collision, so the despawn + unfreeze (done) ride the final step.
local function step(i)
if i > #path then
hideRocket()
done()
return
end
ow:scriptMove(npc, path[i][1], path[i][2],
function() step(i + 1) end)
end
step(1)
end))
end)
end, game.data.text._GameCornerRocketBattleEndText or "Dang!")
end,
-- GameCornerClerk1Text (scripts/GameCorner.asm): the offer, a
-- YesNoChoice, then ¥1000 for 50 coins. Yellow drops the "1" from the
+40 -15
View File
@@ -13,9 +13,18 @@ local function push(game, s, done)
game.stack:push(TextBox.new(game, s, done))
end
-- The question stays on screen under the YES/NO menu. The dojo prize
-- balls are the clearest case: FightingDojoHitmonleePokeBallText
-- (scripts/FightingDojo.asm) is `call PrintText` on a text_end string --
-- no prompt, so no WaitForTextScrollButtonPress -- immediately followed
-- by `call YesNoChoice`, and InitYesNoTextBoxParameters
-- (engine/menus/text_box.asm) puts the menu above the dialogue box
-- rather than replacing it. Ride TextBox's opts.choice, the same as
-- Commands.ask, instead of popping the box with an A press and leaving a
-- bare ChoiceBox over the overworld (#854).
local function ask(game, s, cb)
local ChoiceBox = require("src.ui.ChoiceBox")
push(game, s, function() game.stack:push(ChoiceBox.new(game, cb)) end)
local TextBox = require("src.render.TextBox")
game.stack:push(TextBox.new(game, s, nil, { choice = cb }))
end
-- fill the extracted text placeholders ({NUM:...}, {RAM:...}, {PLAYER})
@@ -155,19 +164,35 @@ local function dojoBall(species, ownBall, otherBall, askKey)
push(game, "You'll have to\nbeat the master\nfirst!", done)
return
end
ask(game, t[askKey] or ("You want\n" .. species .. "?"), function(yes)
if not yes then done() return end
flags["EVENT_GOT_" .. species] = true
flags.EVENT_DEFEATED_FIGHTING_DOJO = true
local Commands = require("src.script.Commands")
local ctx = { save = game.save, game = game, overworld = ow }
Commands.give_pokemon(ctx, species, 30)
-- Hide ONLY the chosen ball; the other stays (FightingDojo.asm hides
-- just the picked object's index) and routes to the greedy line above
-- when talked to (#197).
Commands.hide_object(ctx, "FIGHTING_DOJO", ownBall)
push(game, ("%s got\n%s!"):format(game.save.player.name, species), done)
end)
local function offer()
ask(game, t[askKey] or ("You want\n" .. species .. "?"), function(yes)
if not yes then done() return end
flags["EVENT_GOT_" .. species] = true
flags.EVENT_DEFEATED_FIGHTING_DOJO = true
local Commands = require("src.script.Commands")
local ctx = { save = game.save, game = game, overworld = ow }
Commands.give_pokemon(ctx, species, 30)
-- Hide ONLY the chosen ball; the other stays (FightingDojo.asm hides
-- just the picked object's index) and routes to the greedy line above
-- when talked to (#197).
Commands.hide_object(ctx, "FIGHTING_DOJO", ownBall)
push(game, ("%s got\n%s!"):format(game.save.player.name, species), done)
end)
end
-- FightingDojoHitmonleePokeBallText / ...HitmonchanPokeBallText run
-- `ld a, HITMONLEE / call DisplayPokedex` BEFORE .Text and YesNoChoice,
-- so the ball opens the prize's dex page first and the offer follows
-- it. _DisplayPokedex (engine/events/display_pokedex.asm) sets only
-- the SEEN bit, so the page stays the name-and-sprite preview until
-- the mon is owned, the same shape as the Fuchsia exhibit signs in
-- data/scripts/flavor/fuchsia_city.lua (#853).
local dex = game.save.pokedex
if dex then
dex.seen = dex.seen or {}
dex.seen[species] = true
end
require("src.ui.Screens").push(game, "DexEntryMenu",
{ species = species, onClose = offer })
end
end
+6 -2
View File
@@ -12,9 +12,13 @@ local function push(game, s, done)
game.stack:push(TextBox.new(game, s, done))
end
-- PrintText on a text_end string returns with the box still drawn and
-- YesNoChoice then draws the menu above it (InitYesNoTextBoxParameters,
-- engine/menus/text_box.asm); no A press clears the question first. Ride
-- TextBox's opts.choice, the same as Commands.ask (#854).
local function ask(game, s, cb)
local ChoiceBox = require("src.ui.ChoiceBox")
push(game, s, function() game.stack:push(ChoiceBox.new(game, cb)) end)
local TextBox = require("src.render.TextBox")
game.stack:push(TextBox.new(game, s, nil, { choice = cb }))
end
-- -------------------------------------------------------------------
+45 -12
View File
@@ -62,10 +62,15 @@ M.MT_MOON_B2F = {
{ "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", "_MtMoonJessieJamesText3" },
{ "show_text", "_MtMoonJessieJamesText4" },
{ "stop_music" },
{ "play_music", "Music_MeetJessieJames" },
@@ -85,7 +90,8 @@ M.MT_MOON_B2F = {
-- 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 steps one. A loss
-- 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.
-- -------------------------------------------------------------------
@@ -106,7 +112,7 @@ M.ROCKET_HIDEOUT_B4F = {
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 1.
-- column-mate walks 3, the other 4.
local onLeft = (x == 25)
ow.runner:run({
{ "stop_music" },
@@ -116,16 +122,30 @@ M.ROCKET_HIDEOUT_B4F = {
{ "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
{ "walk_npc", 2, onLeft and { "down", "down", "down" } or { "down" } },
-- 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" } or { "down", "down", "down" } },
{ "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", "_RocketHideoutJessieJamesText3" },
{ "show_text", "_RocketHideoutJessieJamesText4" },
{ "stop_music" },
{ "play_music", "Music_MeetJessieJames" },
@@ -175,16 +195,27 @@ M.POKEMON_TOWER_7F = {
{ "show_text", "_PokemonTowerJessieJamesText1" },
{ "face_player_dir", "up" },
{ "emote", "player", "shock", 30 },
-- Jessie (object 1) then James (object 2), Script1..Script6 order
{ "walk_npc", 1, onLeft and { "down" } or { "down", "down", "down" } },
-- 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" } },
{ "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", "_PokemonTowerJessieJamesText3" },
{ "show_text", "_PokemonTowerJessieJamesText4" },
{ "stop_music" },
{ "play_music", "Music_MeetJessieJames" },
@@ -254,10 +285,12 @@ M.SILPH_CO_11F = {
{ "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", "_SilphCoJessieJamesText3" },
{ "show_text", "_SilphCoJessieJamesText4" },
{ "stop_music" },
{ "play_music", "Music_MeetJessieJames" },