Merge pull request #1240 from AverageConsumer/codex/gen2-battle-ui-visibility

This commit is contained in:
bryanthaboi
2026-08-14 05:54:22 -04:00
committed by GitHub
5 changed files with 57 additions and 4 deletions
+3 -2
View File
@@ -533,8 +533,9 @@ gains a field instead of the name gaining a prefix.
`pokemon.level_up`, `pokemon.move_learned`; hooks `battle.damage`, `pokemon.level_up`, `pokemon.move_learned`; hooks `battle.damage`,
`battle.crit`, `battle.accuracy`, `battle.turn_order`, `battle.crit`, `battle.accuracy`, `battle.turn_order`,
`battle.enemy_action`, `battle.run`, `battle.exp_award`, `exp.gain`, `battle.enemy_action`, `battle.run`, `battle.exp_award`, `exp.gain`,
`catch.rate`, `trainer.party`, `battle.overlay`, `battle.low_health_alarm` `catch.rate`, `trainer.party`, `battle.overlay`, `battle.low_health_alarm`,
and `battle.catch_exp`. One payload difference: Gen 1's vanilla `battle.catch_exp`, `battle.bottom_ui_visible` and
`battle.status_hud_visible`. One payload difference: Gen 1's vanilla
`battle.low_health_alarm` link reads `ctx.battle.data`, and Gold's battle `battle.low_health_alarm` link reads `ctx.battle.data`, and Gold's battle
screen has no `.data` field, so the Gen 2 site **adds** `ctx.data` beside the screen has no `.data` field, so the Gen 2 site **adds** `ctx.data` beside the
Gen 1 keys. A mod that calls `nextFn` is unaffected; one that reaches through Gen 1 keys. A mod that calls `nextFn` is unaffected; one that reaches through
+1
View File
@@ -455,6 +455,7 @@ identifiers: `pc_box_withdraw`, `pc_box_deposit`, `pc_box_release`,
`battle.bottom_ui_visible` and `battle.status_hud_visible` independently `battle.bottom_ui_visible` and `battle.status_hud_visible` independently
control the battle text/menu layer and the HP/status panels. Both receive control the battle text/menu layer and the HP/status panels. Both receive
`(next, state)` and default to `true`, so vanilla rendering is unchanged. `(next, state)` and default to `true`, so vanilla rendering is unchanged.
Both hooks apply to Gen 1 and Gen 2 battles.
Text boxes and YES/NO prompts pushed above a battle inherit a `false` result Text boxes and YES/NO prompts pushed above a battle inherit a `false` result
for that battle, so hiding the bottom layer cannot leave their white backing for that battle, so hiding the bottom layer cannot leave their white backing
behind under another overlay. Text boxes also pass through the hook as their behind under another overlay. Text boxes also pass through the hook as their
+21 -2
View File
@@ -173,6 +173,18 @@ end
function BattleState:wantsFillScale() return true end function BattleState:wantsFillScale() return true end
function BattleState:drawsWidescreen() return true end function BattleState:drawsWidescreen() return true end
function BattleState:bottomUIVisible()
if not Runtime.wantsHook("battle.bottom_ui_visible") then return true end
return Runtime.call("battle.bottom_ui_visible", function() return true end,
self) ~= false
end
function BattleState:statusHUDVisible()
if not Runtime.wantsHook("battle.status_hud_visible") then return true end
return Runtime.call("battle.status_hud_visible", function() return true end,
self) ~= false
end
-- opts: battle (a Battle), onDone(outcome), save -- opts: battle (a Battle), onDone(outcome), save
function BattleState.new(game, opts) function BattleState.new(game, opts)
opts = opts or {} opts = opts or {}
@@ -3079,6 +3091,7 @@ end
function BattleState:drawHud() function BattleState:drawHud()
local wasBattle = Font.useBattleExtra(true) local wasBattle = Font.useBattleExtra(true)
local enemy, player = self:activeMon("enemy"), self:activeMon("player") local enemy, player = self:activeMon("enemy"), self:activeMon("player")
local showStatus = self:statusHUDVisible()
-- Enemy HUD (DrawEnemyHUD clears (1,0) 4 rows x 11 cols): -- Enemy HUD (DrawEnemyHUD clears (1,0) 4 rows x 11 cols):
-- name at (1,0); PrintLevel at (6,1) with the gender symbol at (9,1); -- name at (1,0); PrintLevel at (6,1) with the gender symbol at (9,1);
@@ -3087,7 +3100,7 @@ function BattleState:drawHud()
-- runs, so a shake or a slide does not drag the HP bar with it. -- runs, so a shake or a slide does not drag the HP bar with it.
-- And nothing at all before UpdateEnemyHUD has ever run: the intro bands -- And nothing at all before UpdateEnemyHUD has ever run: the intro bands
-- slide in over a blanked tilemap (core.asm:8554/8564). -- slide in over a blanked tilemap (core.asm:8554/8564).
if self.showEnemyHud and not self:hudCleared("enemy") then if showStatus and self.showEnemyHud and not self:hudCleared("enemy") then
Chrome.print(self:name(enemy), 1, 0) Chrome.print(self:name(enemy), 1, 0)
-- PrintLevel writes <LV> at the coordinate it is given and then LEFT-aligns -- PrintLevel writes <LV> at the coordinate it is given and then LEFT-aligns
-- the digits after it, so the glyph is pinned to column 6 whether the level -- the digits after it, so the glyph is pinned to column 6 whether the level
@@ -3127,7 +3140,8 @@ function BattleState:drawHud()
-- BattleMenu's own tutorial arm skips UpdateBattleHuds as well. The DUDE's -- BattleMenu's own tutorial arm skips UpdateBattleHuds as well. The DUDE's
-- half of the screen is his back-pic and nothing more. -- half of the screen is his back-pic and nothing more.
-- Nor before SendOutPlayerMon's own UpdatePlayerHUD (core.asm:3838). -- Nor before SendOutPlayerMon's own UpdatePlayerHUD (core.asm:3838).
if not player or not self.showPlayerHud or self:hudCleared("player") then if not showStatus or not player or not self.showPlayerHud
or self:hudCleared("player") then
Font.useBattleExtra(wasBattle) Font.useBattleExtra(wasBattle)
return return
end end
@@ -3226,6 +3240,11 @@ function BattleState:drawPanel()
end end
self:drawHud() self:drawHud()
if not self:bottomUIVisible() then
love.graphics.setColor(1, 1, 1, 1)
return
end
-- Message box across the bottom, with the menu window over its right half -- -- Message box across the bottom, with the menu window over its right half --
-- the cart draws the prompt into the full-width box and then opens the menu -- the cart draws the prompt into the full-width box and then opens the menu
-- on top, so the tail of a long name is simply covered. -- on top, so the tail of a long name is simply covered.
+1
View File
@@ -420,6 +420,7 @@ local GEN2_HOOKS = {
-- that a Gen 1 mod reaching through ctx.battle.data instead of calling -- that a Gen 1 mod reaching through ctx.battle.data instead of calling
-- nextFn gets nil there). -- nextFn gets nil there).
"battle.catch_exp", "battle.low_health_alarm", "battle.overlay", "battle.catch_exp", "battle.low_health_alarm", "battle.overlay",
"battle.bottom_ui_visible", "battle.status_hud_visible",
-- One pic path resolver for both games: the Gen 1 site is the SHARED -- One pic path resolver for both games: the Gen 1 site is the SHARED
-- src/pokemon/Sprites.lua and Gold's own battle screen calls the same hook -- src/pokemon/Sprites.lua and Gold's own battle screen calls the same hook
-- with the Gen 1 ctx keys plus `letter` and `shiny`, which Red has no -- with the Gen 1 ctx keys plus `letter` and `shiny`, which Red has no
+31
View File
@@ -168,8 +168,11 @@ end
do do
local BattleState = require("src.battle.BattleState") local BattleState = require("src.battle.BattleState")
local Gen2BattleState = require("src.ui.gen2.BattleState")
check(BattleState.bottomUIVisible({ phase = "menu" }), check(BattleState.bottomUIVisible({ phase = "menu" }),
"battle bottom UI is visible without a mod") "battle bottom UI is visible without a mod")
check(Gen2BattleState.bottomUIVisible({ phase = "menu" }),
"Gold battle bottom UI is visible without a mod")
local seen local seen
local unsub = wrap("battle.bottom_ui_visible", function(_, state) local unsub = wrap("battle.bottom_ui_visible", function(_, state)
seen = state seen = state
@@ -177,6 +180,8 @@ do
end) end)
check(not BattleState.bottomUIVisible({ phase = "messages" }), check(not BattleState.bottomUIVisible({ phase = "messages" }),
"a mod can hide the battle text and menu layer") "a mod can hide the battle text and menu layer")
check(not Gen2BattleState.bottomUIVisible({ phase = "menu" }),
"the same hook hides Gold's battle text and menu layer")
local text = setmetatable({}, TextBox) local text = setmetatable({}, TextBox)
text:draw() text:draw()
check(seen == text, "pushed text boxes use the same visibility hook") check(seen == text, "pushed text boxes use the same visibility hook")
@@ -200,15 +205,41 @@ do
check(BattleState.bottomUIVisible({ phase = "moveSelect" }), check(BattleState.bottomUIVisible({ phase = "moveSelect" }),
"battle bottom UI returns when the hook is removed") "battle bottom UI returns when the hook is removed")
check(Gen2BattleState.bottomUIVisible({ phase = "moves" }),
"Gold battle bottom UI returns when the hook is removed")
local Chrome = require("src.ui.gen2.Chrome")
local clear, box, print = Chrome.clear, Chrome.box, Chrome.print
local boxes = 0
Chrome.clear = function() end
Chrome.box = function() boxes = boxes + 1 end
Chrome.print = function() end
local panel = setmetatable({
battle = { player = {}, enemy = {} }, phase = "resolving",
drawHud = function() end,
}, { __index = Gen2BattleState })
unsub = wrap("battle.bottom_ui_visible", function() return false end)
panel:drawPanel()
check(boxes == 0, "Gold skips its in-state battle box when a mod owns it")
unsub()
panel:drawPanel()
check(boxes == 1, "Gold draws its battle box again without the hook")
Chrome.clear, Chrome.box, Chrome.print = clear, box, print
check(BattleState.statusHUDVisible({}), check(BattleState.statusHUDVisible({}),
"battle status HUD is visible without a mod") "battle status HUD is visible without a mod")
check(Gen2BattleState.statusHUDVisible({}),
"Gold battle status HUD is visible without a mod")
unsub = wrap("battle.status_hud_visible", function() return false end) unsub = wrap("battle.status_hud_visible", function() return false end)
check(not BattleState.statusHUDVisible({}), check(not BattleState.statusHUDVisible({}),
"a mod can hide the battle status HUD") "a mod can hide the battle status HUD")
check(not Gen2BattleState.statusHUDVisible({}),
"the same hook hides Gold's battle status HUD")
unsub() unsub()
check(BattleState.statusHUDVisible({}), check(BattleState.statusHUDVisible({}),
"battle status HUD returns when the hook is removed") "battle status HUD returns when the hook is removed")
check(Gen2BattleState.statusHUDVisible({}),
"Gold battle status HUD returns when the hook is removed")
end end
-- ------- battle.caught_marker_visible (caught wild marker) -- ------- battle.caught_marker_visible (caught wild marker)