From 1dae9622e199bbe8af8cef9f695d10df4415bd82 Mon Sep 17 00:00:00 2001 From: Shane McGovern Date: Sun, 2 Aug 2026 16:14:25 +0100 Subject: [PATCH] Play the jingle when Oak hands over the starter (#668) The starter balls' scripts showed the received-mon text but never played the sound_get_key_item fanfare that the text carries in the original (scripts/OaksLab.asm OaksLabReceivedMonText / OaksLabRivalReceivedMonText). Add play_sound Get_Key_Item before each received text, mirroring the Yellow starter port. --- data/scripts/oaks_lab.lua | 41 ++++++++++++---------- tests/engine/oaks_lab_last_ball_bug601.lua | 33 ++++++++++++----- tests/parity_F.lua | 20 +++++++++++ 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/data/scripts/oaks_lab.lua b/data/scripts/oaks_lab.lua index 7a1bed16..fe2602ff 100644 --- a/data/scripts/oaks_lab.lua +++ b/data/scripts/oaks_lab.lua @@ -22,10 +22,10 @@ local function starterBall(askText, species, choseFlag, ownBall, rivalBallX, rivalBall) return { { "check_flag", "EVENT_GOT_STARTER" }, -- 1 - { "jump_if_true", 20 }, -- 2 + { "jump_if_true", 22 }, -- 2 -- no picking until Oak has walked you in (OaksLabScript gating) { "check_flag", "EVENT_FOLLOWED_OAK_INTO_LAB" }, -- 3 - { "jump_if_false", 23 }, -- 4 + { "jump_if_false", 25 }, -- 4 -- the Pokédex "new species" entry shows before the ask (predef -- StarterDex ahead of OaksLabYouWant...Text). StarterDex temporarily -- sets the owned bits so ShowPokedexData prints height/weight/text; @@ -37,36 +37,41 @@ local function starterBall(askText, species, choseFlag, ownBall, -- OaksLab.asm prints ReceivedMon then AddPartyMon (AskName lives -- inside give_pokemon). Show the received text first so the -- nickname prompt follows "you got X", matching Gen1. - { "show_text", "_OaksLabReceivedMonText", { RAM = species } }, -- 8 - { "give_pokemon", species, 5 }, -- 9 - { "set_flag", "EVENT_GOT_STARTER" }, -- 10 - { "set_flag", choseFlag }, -- 11 + -- The received text carries sound_get_key_item (OaksLab.asm + -- OaksLabReceivedMonText); the jingle plays as the box opens + -- (same beat as the Yellow port's starter, #668). + { "play_sound", "Get_Key_Item" }, -- 8 + { "show_text", "_OaksLabReceivedMonText", { RAM = species } }, -- 9 + { "give_pokemon", species, 5 }, -- 10 + { "set_flag", "EVENT_GOT_STARTER" }, -- 11 + { "set_flag", choseFlag }, -- 12 -- POKé BALLs are not handed out here in the original -- Oak gives -- them later, at OaksLabOak1Text's .give_poke_balls beat once the -- player has beaten the Route 22 rival (see TEXT_OAKSLAB_OAK1 below) - { "hide_object", "OAKS_LAB", ownBall }, -- 12 + { "hide_object", "OAKS_LAB", ownBall }, -- 13 -- the rival walks to the countering ball (around the furniture) - { "move_npc_to", 1, rivalBallX, 4 }, -- 13 - { "face_object", 1, "up" }, -- 14 - { "show_text", "_OaksLabRivalIllTakeThisOneText" }, -- 15 - { "hide_object", "OAKS_LAB", rivalBall }, -- 16 + { "move_npc_to", 1, rivalBallX, 4 }, -- 14 + { "face_object", 1, "up" }, -- 15 + { "show_text", "_OaksLabRivalIllTakeThisOneText" }, -- 16 + { "hide_object", "OAKS_LAB", rivalBall }, -- 17 + { "play_sound", "Get_Key_Item" }, -- 18 (sound_get_key_item) { "show_text", "_OaksLabRivalReceivedMonText", { RAM = rivalBall == "OAKSLAB_CHARMANDER_POKE_BALL" and "CHARMANDER" or rivalBall == "OAKSLAB_SQUIRTLE_POKE_BALL" and "SQUIRTLE" - or "BULBASAUR" } }, -- 17 - { "jump", "end" }, -- 18 - { "jump", "end" }, -- 19 (spacer) + or "BULBASAUR" } }, -- 19 + { "jump", "end" }, -- 20 + { "jump", "end" }, -- 21 (spacer) -- a leftover ball after the player's pick: Oak turns to face the -- player and reads the last-mon line instead of re-offering the -- starter (scripts/OaksLab.asm OaksLabSelectedPokeBallScript -> -- OaksLabLastMonScript; #601). The ROM's "#MON" ligature is spelled -- out as Pokémon here. - { "face_object", 5, "down" }, -- 20 - { "show_text", "That's PROF.OAK's\nlast Pokémon!" }, -- 21 + { "face_object", 5, "down" }, -- 22 + { "show_text", "That's PROF.OAK's\nlast Pokémon!" }, -- 23 -- OaksLabLastMonScript ends at TextScriptEnd; the port used to fall -- through into the pre-pick line below (#601 remnant, reported on #600) - { "jump", "end" }, -- 22 - { "show_text", "_OaksLabThoseArePokeBallsText" }, -- 23 + { "jump", "end" }, -- 24 + { "show_text", "_OaksLabThoseArePokeBallsText" }, -- 25 } end diff --git a/tests/engine/oaks_lab_last_ball_bug601.lua b/tests/engine/oaks_lab_last_ball_bug601.lua index 9320da0b..cd7aff42 100644 --- a/tests/engine/oaks_lab_last_ball_bug601.lua +++ b/tests/engine/oaks_lab_last_ball_bug601.lua @@ -94,11 +94,18 @@ T.check(box:find("Those are", 1, true) == nil, T.check(box:find("#MON", 1, true) == nil, "the ROM #MON ligature is spelled out as Pokémon") --- the pokered beat also turns Oak to face the player -T.check(contribution.talk[BALL][20][1] == "face_object" - and contribution.talk[BALL][20][2] == 5 - and contribution.talk[BALL][20][3] == "down", - "row 20 faces Oak down before the line (OaksLabLastMonScript)") +-- the pokered beat also turns Oak to face the player: find the +-- face_object row in the leftover-ball path (content-based, so a jingle +-- row added for #668 doesn't shift the hard-coded index) +local oakFaceRow +for i, row in ipairs(contribution.talk[BALL]) do + if row[1] == "face_object" and row[2] == 5 and row[3] == "down" then + oakFaceRow = i + break + end +end +T.check(oakFaceRow ~= nil, + "a face_object row turns Oak down before the line (OaksLabLastMonScript)") -- ---- pre-escort: still the vanilla "Those are POKé BALLs" line local pre = { EVENT_GOT_STARTER = false, EVENT_FOLLOWED_OAK_INTO_LAB = false } @@ -115,15 +122,25 @@ T.check(concat(t3):find("last Pokémon!", 1, true) == nil, "no last-mon line before the pick") -- ---- all three balls share the same table shape (last-mon beat present) +-- content-based again: locate the leftover-ball "Pokémon" line wherever +-- it sits, instead of pinning a row number (#668 added two jingle rows) for _, key in ipairs({ "TEXT_OAKSLAB_CHARMANDER_POKE_BALL", "TEXT_OAKSLAB_SQUIRTLE_POKE_BALL", "TEXT_OAKSLAB_BULBASAUR_POKE_BALL", }) do local script = contribution.talk[key] - T.check(script and script[21] and script[21][2] and - script[21][2]:find("Pokémon", 1, true) ~= nil, - key .. " carries the last-mon line") + local lastMon + if script then + for _, row in ipairs(script) do + if row[1] == "show_text" and type(row[2]) == "string" + and row[2]:find("Pokémon", 1, true) then + lastMon = row[2] + break + end + end + end + T.check(lastMon ~= nil, key .. " carries the last-mon line") end T.finish("oaks_lab_last_ball_bug601") diff --git a/tests/parity_F.lua b/tests/parity_F.lua index e90d1084..d514ebf6 100644 --- a/tests/parity_F.lua +++ b/tests/parity_F.lua @@ -34,6 +34,16 @@ Game.stack = StateStack; StateStack:init() Game.save = SaveData.newGame() require("src.render.Font").load(Data) +-- spy on Sound.play so the starter-received jingle beat is observable +-- without real audio (parity_C does the same for its arrival SFX) +local Sound = require("src.core.Sound") +local realSoundPlay = Sound.play +local played = {} +Sound.play = function(data, name) + played[#played + 1] = name + return realSoundPlay(data, name) +end + -- pumps a script coroutine to completion; pressFn returns the Input.pressed -- table for this frame (default: mash A through text/ask/naming) local function runScript(script, pressFn) @@ -64,6 +74,14 @@ check(Flags.get(Game.save, "EVENT_GOT_STARTER"), "starter flag set") eq(Game.save.inventory.POKE_BALL, nil, "no POKe BALLs yet right after picking a starter") check(Game.save.party[1] and Game.save.party[1].species == "BULBASAUR", "starter joined the party") +-- #668: OaksLabReceivedMonText carries sound_get_key_item; the jingle +-- must fire as the starter is handed over (once for the player's mon, +-- once for the rival's counter-pick) +local jingles = 0 +for _, name in ipairs(played) do + if name == "Get_Key_Item" then jingles = jingles + 1 end +end +eq(jingles, 2, "starter + rival counter-pick both play the Get_Key_Item jingle (#668)") -- A-mash accepts the nickname prompt and fills NamingScreen with A's check(Game.save.party[1].nickname == "AAAAAAAAAA", "starter nickname prompt accepted (AskName / #137)") @@ -182,4 +200,6 @@ do Game.save = realSave end +Sound.play = realSoundPlay + S.finish()