Show the Pokédex entry for the Fighting Dojo prize balls

This commit is contained in:
johnjohto
2026-08-05 10:18:47 -04:00
parent f0ed2efe07
commit 1f878c3098
4 changed files with 124 additions and 19 deletions
+20 -13
View File
@@ -155,19 +155,26 @@ 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)
-- Examining a ball shows that species' POKéDEX entry first
-- (DisplayPokedex in FightingDojo.asm, which also marks it seen),
-- then the yes/no take-it prompt (#853).
local Commands = require("src.script.Commands")
local ctx = { save = game.save, game = game, overworld = ow }
Commands.mark_seen(ctx, species)
local DexEntryMenu = require("src.ui.DexEntryMenu")
game.stack:push(DexEntryMenu.new(game, species, function()
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
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))
end
end
+9 -2
View File
@@ -6,6 +6,11 @@
-- StarterDex (engine/events/starter_dex.asm), which temporarily sets the
-- owned bit so Oak's lab ball previews show height/weight/description
-- without permanently marking the mon owned.
--
-- `onDone` (optional) runs right after the page pops itself, the way a
-- TextBox onDone does; map scripts use it to continue once the player
-- closes the entry (the Fighting Dojo prize balls chain their take-it
-- prompt off it).
local Font = require("src.render.Font")
local Strings = require("src.core.Strings")
@@ -31,9 +36,10 @@ local function resolveArgs(speciesOrOpts)
return speciesOrOpts, false
end
function DexEntryMenu.new(game, speciesOrOpts)
function DexEntryMenu.new(game, speciesOrOpts, onDone)
local species, forceOwned = resolveArgs(speciesOrOpts)
local self = setmetatable({ game = game, forceOwned = forceOwned }, DexEntryMenu)
local self = setmetatable({ game = game, forceOwned = forceOwned,
onDone = onDone }, DexEntryMenu)
self.def = game.data.pokemon[species]
local path, trueColor = require("src.pokemon.Sprites").path(
game.data, species, "front", { kind = "dex" })
@@ -52,6 +58,7 @@ function DexEntryMenu:update(dt)
local input = self.game.input
if input:wasPressed("a") or input:wasPressed("b") then
self.game.stack:pop()
if self.onDone then self.onDone() end
end
end
+6 -4
View File
@@ -3,7 +3,8 @@
-- BUG1 gate -- the master stops the player on the tile to his left
-- BUG2 no speech -- no won text + no prize dialogue after the win
-- BUG3 wrong re-talk -- shows the pre-battle challenge, not the after line
-- BUG4 (verify) -- the ball ask() is the Gen1 descriptor, not a dex entry
-- BUG4 (verify) -- the ball ask() is the Gen1 descriptor, shown after
-- the species' dex entry (DisplayPokedex)
-- BUG5 both balls -- the chosen ball AND the other one both vanish; the
-- other should stay and give the "greedy" refusal
-- BUG6 poster -- the north-wall posters ("Enemies on every side!") are
@@ -163,8 +164,9 @@ return function(game)
mashUntil(function() return game.stack:top() == ow end)
------------------------------------------------------------------
-- BUG4 (verify-only): the Hitmonlee ball prompt is the Gen1 descriptor
-- ("You want the hard kicking HITMONLEE?"), not a Pokedex entry screen.
-- BUG4 (verify-only): the Hitmonlee ball shows the species' Pokedex
-- entry first (DisplayPokedex, #853), then the Gen1 descriptor prompt
-- ("You want the hard kicking HITMONLEE?").
------------------------------------------------------------------
ow = resetDojo(4, 2, "up", { EVENT_BEAT_KARATE_MASTER = true })
local leeBall = npcByName(ow, "FIGHTINGDOJO_HITMONLEE_POKE_BALL")
@@ -173,7 +175,7 @@ return function(game)
if leeBall then
ow:talkTo(leeBall)
check(sawText("hard kicking") or sawText("HITMONLEE"),
"BUG4: ball asks the Gen1 descriptor prompt (no dex entry)")
"BUG4: ball asks the Gen1 descriptor prompt after the dex entry")
U.shot(game, DIR .. "/dojo_4_prompt.png")
------------------------------------------------------------------
-- BUG5: choose YES -> only the chosen ball vanishes; the other stays
+89
View File
@@ -0,0 +1,89 @@
-- Parity: the Fighting Dojo prize balls open the Pokédex entry before the
-- take-it prompt (#853). FightingDojo.asm runs DisplayPokedex on the
-- ball's species (marking it seen) and only then prints the yes/no ask.
package.path = "./?.lua;./?/init.lua;" .. package.path
if not _G.love then _G.love = require("tests.love_stub") end
local Data = require("src.core.Data")
if not Data.maps then Data:load() end
local S = require("tests.harness").suite("parity Fighting Dojo dex entry")
local check, eq = S.check, S.eq
local Font = require("src.render.Font")
Font.load(Data)
local TextBox = require("src.render.TextBox")
local DexEntryMenu = require("src.ui.DexEntryMenu")
local SaveData = require("src.core.SaveData")
local dojo = require("data.scripts.story4").FIGHTING_DOJO
local function fakeGame()
local states = {}
local save = SaveData.newGame()
save.pokedex = { seen = {}, owned = {} }
save.flags = { EVENT_BEAT_KARATE_MASTER = true }
local game = {
data = Data,
save = save,
pressed = false,
stack = {
states = states,
push = function(_, s) states[#states + 1] = s end,
pop = function(_) states[#states] = nil end,
top = function(_) return states[#states] end,
},
}
game.input = { wasPressed = function(_, btn)
local p = game.pressed
game.pressed = false
return p and btn == "a"
end }
return game
end
local function pageText(box)
local out = {}
for _, page in ipairs(box.pages or {}) do
out[#out + 1] = table.concat(page, "\n")
end
return table.concat(out, "\n")
end
-- each ball: dex entry first (seen, not owned), then the ask prompt
for _, c in ipairs({
{ textId = "TEXT_FIGHTINGDOJO_HITMONLEE_POKE_BALL", species = "HITMONLEE" },
{ textId = "TEXT_FIGHTINGDOJO_HITMONCHAN_POKE_BALL", species = "HITMONCHAN" },
}) do
local game = fakeGame()
dojo.talk[c.textId](game, {}, nil, function() end)
local top = game.stack:top()
check(getmetatable(top) == DexEntryMenu,
c.textId .. " opens the Pokédex entry first")
eq(top and top.def and top.def.id, c.species,
"the entry shows " .. c.species)
check(game.save.pokedex.seen[c.species] == true,
"the preview marks " .. c.species .. " seen")
check(not game.save.pokedex.owned[c.species],
"the preview does not mark " .. c.species .. " owned")
game.pressed = true
top:update(0)
local ask = game.stack:top()
check(getmetatable(ask) == TextBox,
"closing the entry shows the take-it prompt")
check(ask and pageText(ask):find(c.species, 1, true) ~= nil,
"the prompt names " .. c.species)
end
-- before the Karate Master is beaten the ball still refuses, no dex entry
do
local game = fakeGame()
game.save.flags.EVENT_BEAT_KARATE_MASTER = nil
dojo.talk.TEXT_FIGHTINGDOJO_HITMONLEE_POKE_BALL(game, {}, nil,
function() end)
check(getmetatable(game.stack:top()) == TextBox,
"an unbeaten master keeps the refusal text, not the dex entry")
check(not game.save.pokedex.seen.HITMONLEE,
"the refusal does not mark Hitmonlee seen")
end
S.finish()