-- The Viridian City old-man catch tutorial, Yellow's way -- (pokeyellow scripts/ViridianCity.asm, scripts/ViridianCity_2.asm, -- scripts/OaksLab.asm). Registered on top of the shared tables by -- data/scripts/init.lua on a Yellow boot. -- -- Yellow has TWO gambler objects where Red/Blue have one: -- * VIRIDIANCITY_OLD_MAN at (17,5) -- a Red/Blue leftover; its -- toggle stays OFF forever in Yellow, no script ever shows it. -- * VIRIDIANCITY_OLD_MAN2 at (18,9) -- replaces the sleeper the -- moment the Pokédex is given (OaksLabOakGivesPokedexScript: -- HideObject TOGGLE_LYING_OLD_MAN / ShowObject TOGGLE_OLD_MAN_2). -- -- This is the tutorial old man. The Red/Blue "Are you in a hurry?" -- yes/no script must NOT run against him: Yellow's -- _ViridianCityOldManHadMyCoffeeNowText is the apology speech ("I've had -- my coffee now ... I'll show you how to catch POKéMON as my apology"), -- and the shared story.lua TEXT_VIRIDIANCITY_OLD_MAN rows hang an -- invented yes/no over it -- YES printed the TimeIsMoney alias -- (_ViridianCityOldManLosingMyTouchText) and NO ran the demo, every -- talk, forever (#617). -- -- The real flow (ViridianCityCheckWaitingOldMan + ViridianCityOldMan2Text -- + ViridianCityOldManInitialCatchTrainingScript + ...EndInitial... + -- ViridianCityPostInitialCatchTraining): stepping into (19,9) -- the gap -- east of the sleeper's cell -- faces the old man right and the player -- left, prints the apology, and without any choice runs the demo battle -- (BATTLE_TYPE_OLD_MAN, RATTATA lvl 5), which he FAILS -- the ball shakes -- three times and breaks open. After it, the same text pointer -- now prints _ViridianCityOldManLosingMyTouchText ("That didn't work! -- I must be losing my touch."), the old man walks off (down 6 with the -- player on (19,9), right 1 otherwise, Pikachu nudged out of the way -- first) and TOGGLE_OLD_MAN_2 hides. A direct talk does the same. local M = {} local OLD_MAN2 = "VIRIDIANCITY_OLD_MAN2" -- 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. -- story5's VIRIDIAN_CITY.onStep chains story.lua's sleeping-old-man -- gate and its own gym-lock step (same pattern as yellow_jessie_james). local baseViridianStep = require("data.scripts.story5").VIRIDIAN_CITY.onStep -- pokeyellow text/ViridianCity.asm, _ViridianCityOldManHadMyCoffeeNowText -- and _ViridianCityOldManLosingMyTouchText, spelled with the extractor's -- markers (line -> \n, cont -> \v, para -> \f) local function text(game) return { apology = game.data.text._ViridianCityOldManHadMyCoffeeNowText or "Ahh, I've had my\ncoffee now and I\vfeel great!\fSure, you can go\n" .. "through!\fI'm sorry I was\nso rude to you!\fI see you're using\n" .. "a POKéDEX.\fI'll show you how\nto catch POKéMON\vas my apology.", losingMyTouch = game.data.text._ViridianCityOldManLosingMyTouchText or "That didn't work!\nI must be losing\vmy touch.\fI've run out of\n" .. "POKé BALLs too.\fI have to get some\nat POKéMON MART.", } end -- The row list for the initial-tutorial branch, keyed by where the -- player stands when the battle ends (ViridianCityPostInitialCatchTraining -- reads wXCoord: (19,9) walks the old man down the corridor, anywhere -- else walks him right 1 after moving the follower Pikachu aside). local function oldMan2Rows(game, ow, npc) local rows = { { "show_text", "_ViridianCityOldManHadMyCoffeeNowText" }, -- ViridianCityOldManInitialCatchTrainingScript sets -- EVENT_INITIAL_CATCH_TRAINING before the battle runs, and -- ItemUseBall's .oldManBattle branch turns that event into anim data -- $63: three shakes, then the ball breaks open. The losing-my-touch -- line below only follows a throw that failed (#636). { "old_man_demo", "fail" }, { "set_flag", "EVENT_COMPLETED_CATCH_TRAINING" }, { "show_text", "_ViridianCityOldManLosingMyTouchText" }, } if ow.player and ow.player.cellX == 19 then rows[#rows + 1] = { "walk_npc", npc.def.index, { "down", "down", "down", "down", "down", "down" } } else -- ViridianCityMovePikachu (scripts/ViridianCity_2.asm): Pikachu -- steps out of the old man's way before he turns right local PikachuFollower = require("src.world.PikachuFollower") local pika = ow and PikachuFollower.current(ow) if pika then rows[#rows + 1] = { "walk_npc", pika.def.index, { "right" } } end rows[#rows + 1] = { "walk_npc", npc.def.index, { "right" } } end rows[#rows + 1] = { "hide_object", "VIRIDIAN_CITY", OLD_MAN2 } return rows end -- The shared talk handler: TEXT_VIRIDIANCITY_OLD_MAN2's text_asm branch -- (ViridianCityOldMan2Text) on EVENT_COMPLETED_CATCH_TRAINING. local function oldMan2Talk(game, ow, npc, done) if game.save.flags and game.save.flags.EVENT_COMPLETED_CATCH_TRAINING then local TextBox = require("src.render.TextBox") game.stack:push(TextBox.new(game, text(game).losingMyTouch, done)) return end ow.runner:run(oldMan2Rows(game, ow, npc), { npc = npc, onDone = done, checkpointOnDone = "release_npc" }) end M.VIRIDIAN_CITY = { talk = { TEXT_VIRIDIANCITY_OLD_MAN2 = oldMan2Talk, }, -- Re-apply the Pokédex swap for a save that already holds the flag but -- was never standing here when it fired (converted .sav imports, same -- shape as story.lua's VIRIDIAN_CITY.onEnter). Yellow shows OLD_MAN2, -- not the Red/Blue OLD_MAN at (17,5), and also puts away a stray -- OLD_MAN a save made by the pre-#617 build left standing. onEnter = function(game, ow) if not (game.save.flags and game.save.flags.EVENT_GOT_POKEDEX) then return end local Commands = require("src.script.Commands") local ctx = { save = game.save, game = game, overworld = ow } Commands.hide_object(ctx, "VIRIDIAN_CITY", "VIRIDIANCITY_OLD_MAN_SLEEPY") Commands.hide_object(ctx, "VIRIDIAN_CITY", "VIRIDIANCITY_OLD_MAN") Commands.show_object(ctx, "VIRIDIAN_CITY", OLD_MAN2) end, -- ViridianCityCheckWaitingOldMan: with the Pokédex held and the -- tutorial undone, (19,9) -- the gap east of the old man, the same -- cell the sleeper used to gate -- faces him right, turns the player -- left and starts the OLD_MAN2 flow with no choice. onStep = function(game, ow, x, y) if baseViridianStep and baseViridianStep(game, ow, x, y) then return true end local flags = game.save.flags if not flags.EVENT_GOT_POKEDEX then return false end if flags.EVENT_COMPLETED_CATCH_TRAINING then return false end if x ~= 19 or y ~= 9 then return false end local man for _, npc in ipairs(ow.npcs) do if npc.def and npc.def.name == OLD_MAN2 then man = npc break end end if not man then return false end man.facing = "right" ow.player.facing = "left" oldMan2Talk(game, ow, man, nil) return true end, } return M