Merge pull request #328 from johnjohto/fix-fieldmove-whiteflash

Run the field-move white blink under its text, not after (#320)
This commit is contained in:
bryanthaboi
2026-07-28 05:10:06 -04:00
committed by GitHub
5 changed files with 75 additions and 17 deletions
+5 -3
View File
@@ -304,10 +304,12 @@ function PartyMenu:update(dt)
or Strings("{RAM:wNameBuffer} used\nSTRENGTH.")):gsub("{RAM:wNameBuffer}", name) or Strings("{RAM:wNameBuffer} used\nSTRENGTH.")):gsub("{RAM:wNameBuffer}", name)
local t2 = (self.game.data.text._CanMoveBouldersText local t2 = (self.game.data.text._CanMoveBouldersText
or Strings("{RAM:wNameBuffer} can\nmove boulders.")):gsub("{RAM:wNameBuffer}", name) or Strings("{RAM:wNameBuffer} can\nmove boulders.")):gsub("{RAM:wNameBuffer}", name)
-- like surf (#320): the blink belongs UNDER the texts, not as a
-- flashbang on the empty map after them; the stack only updates
-- the top state, so the flash holds until the texts close
self.game.stack:push(Transition.whiteFlash(self.game))
self.game.stack:push(TextBox.new(self.game, t1, function() self.game.stack:push(TextBox.new(self.game, t1, function()
self.game.stack:push(TextBox.new(self.game, t2, function() self.game.stack:push(TextBox.new(self.game, t2))
self.game.stack:push(Transition.whiteFlash(self.game))
end))
end, { auto = { sound = function() end, { auto = { sound = function()
return require("src.core.Sound").playCry(self.game.data, mon.species) return require("src.core.Sound").playCry(self.game.data, mon.species)
end } })) end } }))
+10 -14
View File
@@ -2004,23 +2004,19 @@ function OverworldState:trySurf(fx, fy)
if not mon then return end if not mon then return end
local name = mon.nickname or Game.data.pokemon[mon.species].name local name = mon.nickname or Game.data.pokemon[mon.species].name
local p = self.player local p = self.player
p.surfing = true
require("src.core.Music").setSurfing(Game.data, true)
local text = (Game.data.text._SurfingGotOnText or Strings("{PLAYER} got on\n{RAM:wNameBuffer}!")) local text = (Game.data.text._SurfingGotOnText or Strings("{PLAYER} got on\n{RAM:wNameBuffer}!"))
:gsub("{RAM:wNameBuffer}", name) :gsub("{RAM:wNameBuffer}", name)
-- GBPalWhiteOutWithDelay3 runs while the got-on text is still up
-- (start_sub_menus.asm .surf), so the blink reads as a text flash
-- instead of a flashbang on the empty map (#320). The flash sits
-- under the textbox on the stack: only the top state updates, so it
-- holds its frames until the text closes. surfing (and the sprite
-- swap) only applies when the step happens -- no paddling on land.
Game.stack:push(require("src.render.Transition").whiteFlash(Game))
Game.stack:push(TextBox.new(Game, text, function() Game.stack:push(TextBox.new(Game, text, function()
-- start_sub_menus.asm .surf: UseItem returns (mount + text done), p.surfing = true
-- then GBPalWhiteOutWithDelay3 blinks before the simulated forward require("src.core.Music").setSurfing(Game.data, true)
-- press steps onto the water (or across a connection strip, like self:stepForwardOrCrossEdge(p.facing)
-- Cinnabar's east coast onto Route 20)
local Transition = require("src.render.Transition")
if Transition.whiteFlash then
Game.stack:push(Transition.whiteFlash(Game, nil, function()
self:stepForwardOrCrossEdge(p.facing)
end))
else
self:stepForwardOrCrossEdge(p.facing)
end
end)) end))
end end
+24
View File
@@ -532,6 +532,30 @@ press(fpm, "a")
check(not fpm.submenu and forced == fgame.save.party[1], check(not fpm.submenu and forced == fgame.save.party[1],
"forceSwitch still picks immediately (ChooseNextMon / SHIFT)") "forceSwitch still picks immediately (ChooseNextMon / SHIFT)")
-- ------- issue #320: the STRENGTH blink sits under its texts
do
local owStub = { strengthActive = false,
map = { def = { tileset = "OVERWORLD" } }, dark = false }
local sgame = partyGame()
sgame.overworld = owStub
sgame.data.text = {} -- the strength texts fall back to Strings sources
sgame.save.inventory.RAINBOWBADGE = 1
sgame.save.party[1].moves = { { id = "STRENGTH" } }
local pm = PartyMenu.new(sgame)
pm.game = sgame
sgame.stack:push(pm)
press(pm, "a") -- open the submenu
check(pm.subItems[#pm.subItems].action == "strength",
"the strength row is listed with badge + move")
pm.subIndex = #pm.subItems
press(pm, "a") -- run STRENGTH
local states = sgame.stack.states
check(#states == 2 and states[1].frames ~= nil
and states[2].pages ~= nil,
"the blink sits under the strength texts")
check(owStub.strengthActive == true, "strength still activates")
end
-- ------- mod.ui helpers and theme defaults -- ------- mod.ui helpers and theme defaults
local items = { { label = "A" }, { label = "B" } } local items = { { label = "A" }, { label = "B" } }
ModUI.insertAfter(items, "A", { label = "X" }) ModUI.insertAfter(items, "A", { label = "X" })
+32
View File
@@ -607,6 +607,38 @@ do
end) end)
end end
do
-- issue #320: the surf blink sits UNDER the "got on" text (pokered's
-- GBPalWhiteOutWithDelay3 runs while the text is up), and the surfing
-- sprite swap waits for the actual step onto the water
require("src.render.Font").load(Data)
local save = {
flags = {},
inventory = { SOULBADGE = 1 },
party = { { species = "SQUIRTLE", moves = { { id = "SURF" } } } },
player = { name = "RED" },
}
local stack = { states = {} }
function stack:push(s) self.states[#self.states + 1] = s end
function stack:pop() return table.remove(self.states) end
function stack:top() return self.states[#self.states] end
local game = { data = Data, save = save, stack = stack }
check(bindGame(OW.trySurf, game), "trySurf binds a test Game")
check(bindGame(OW.partyKnows, game), "partyKnows binds the same Game")
local ow = setmetatable({ player = { facing = "down" } }, { __index = OW })
ow.stepForwardOrCrossEdge = function(_, dir) ow.stepped = dir end
ow:trySurf(10, 10)
local bottom, top = stack.states[1], stack.states[2]
check(bottom and bottom.frames ~= nil and top and top.pages ~= nil,
"the blink sits under the surf text on the stack")
check(not ow.player.surfing, "no surfing sprite while the text is up")
top.onDone()
check(ow.player.surfing == true, "surfing applies with the step")
check(ow.stepped == "down", "the step onto the water fires")
end
do do
-- warp.destination reroutes one door without owning the warp table -- warp.destination reroutes one door without owning the warp table
local warpDef = Data.maps.PALLET_TOWN.warps[1] local warpDef = Data.maps.PALLET_TOWN.warps[1]
+4
View File
@@ -166,6 +166,9 @@ ow.player.facing = "down"; ow.player.surfing = false
clearCaptured() clearCaptured()
local pmSurf = PartyMenu.new(Game) local pmSurf = PartyMenu.new(Game)
selectSubItem(pmSurf, 3) selectSubItem(pmSurf, 3)
-- the blink sits under the got-on text (#320); dismissing the text is
-- what mounts and steps
Game.stack:top().onDone()
eq(ow.player.surfing, true, "SURF from the party menu sets player.surfing") eq(ow.player.surfing, true, "SURF from the party menu sets player.surfing")
check(not onStack(pmSurf), "party menu closes after a successful SURF") check(not onStack(pmSurf), "party menu closes after a successful SURF")
check(sawText("got on"), "_SurfingGotOnText shown on a successful SURF") check(sawText("got on"), "_SurfingGotOnText shown on a successful SURF")
@@ -498,6 +501,7 @@ clearCaptured()
-- submenu order: STATS, SWITCH, FLY, CUT, STRENGTH, SURF (move order on mon) -- submenu order: STATS, SWITCH, FLY, CUT, STRENGTH, SURF (move order on mon)
local pmFaintSurf = PartyMenu.new(Game) local pmFaintSurf = PartyMenu.new(Game)
selectSubItem(pmFaintSurf, 6) selectSubItem(pmFaintSurf, 6)
Game.stack:top().onDone() -- dismiss the text: mount + step (#320)
eq(ow.player.surfing, true, "fainted mon can SURF from the party menu") eq(ow.player.surfing, true, "fainted mon can SURF from the party menu")
check(not onStack(pmFaintSurf), "party menu closes after fainted SURF") check(not onStack(pmFaintSurf), "party menu closes after fainted SURF")