mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-15 07:41:21 +02:00
fix: battle screens keep their composition when they open a menu or prompt
BATTLE SIZE "fixed" draws the battle as a discrete letterbox rather than
filling the window, and BATTLE BG "world" composes it over the live map.
Everything the battle then opens broke out of that composition, because
each piece of the frame's geometry was read off a fact about THIS FRAME
instead of about the battle:
* Renderer:uiScale follows the survey zoom only while a world is behind
the UI, gated on worldActive -- this frame's world pass. PartyMenu and
ListMenu are opaque, so pushing one makes StateStack:visibleBase skip
the map, no world pass runs, and the menu loses the step-down and blits
a whole integer scale larger than the battle it just covered. Held
with uiWorldHold, the same whole-stack rule uiFill and the battle dim
already use. ("fill" hid this: it overrides the scale outright.)
* Game:draw started the frame at visibleBase, so that same opaque menu
cut the overworld -- and the world pass with it -- out of the frame
entirely, collapsing a "world" backdrop to endFrame's flat black clear.
A world-bg battle now keeps the frame starting from underneath itself
(drawBaseInStack). Only the START of the draw moves; the clear stays
keyed to the real visibleBase, so the menu still gets its opaque canvas
and draws exactly as before.
* worldZones was keyed to that same clear base, so it came out nil for a
frame whose world pass HAD run -- dropping endFrame's world blit onto
the UI zone list instead, smearing the party menu's own HP-bar palettes
across a world-canvas-sized image. Keyed to whether the map drew.
* endFrame's letterbox clear read letterboxWhite off visibleBase alone,
so an opaque menu over a BG "white" battle flipped its surround to
black the same way. Same whole-stack hold.
* ChoiceBox bottom-anchored unconditionally, docking it to the WINDOW
edge. That is only right when it rides the dialogue box beneath it,
which is anchored there too; TextBox now passes the anchor and nothing
else does, so the battle's switch offer and the shop/PC confirms stay
over the screen that pushed them.
* TextBox anchors likewise: a battle is a self-contained SCREEN, not the
window, and pokered prints its text box in the same 160x144 tilemap as
the HUD. The caught-mon nickname prompt was landing a whole letterbox
below the blanked battle field it is printed on. BattleState.holdsUI-
Anchors holds setUIAnchor off while a battle is in the stack; the
overworld's own dialogue box still docks to the screen edge.
This commit is contained in:
+33
-7
@@ -142,13 +142,22 @@ end
|
||||
function Renderer:uiScale()
|
||||
local S = self:fitScale()
|
||||
local off = Zoom.offset or 0
|
||||
-- Only follow the zoom when a world is actually on screen. Survey zoom is
|
||||
-- an OVERWORLD control; the title screen, the intro and the credits show no
|
||||
-- world at all, and shrinking them to match a zoom level the player set for
|
||||
-- the map is meaningless. worldActive is this frame's answer -- beginFrame
|
||||
-- clears it and beginWorldPass sets it -- so a state that draws no world
|
||||
-- keeps the full fit scale.
|
||||
if not self.worldActive then return S end
|
||||
-- Only follow the zoom when a world is actually behind the UI. Survey zoom
|
||||
-- is an OVERWORLD control; the title screen, the intro and the credits show
|
||||
-- no world at all, and shrinking them to match a zoom level the player set
|
||||
-- for the map is meaningless. worldActive is this frame's answer --
|
||||
-- beginFrame clears it and beginWorldPass sets it -- so a state that draws
|
||||
-- no world keeps the full fit scale.
|
||||
--
|
||||
-- uiWorldHold (Game:draw) is the case worldActive cannot answer: a BATTLE
|
||||
-- BG "world" battle stays the scene's backdrop while an OPAQUE state -- the
|
||||
-- party menu, the bag -- covers it, whether or not a world pass ran under
|
||||
-- that state. Reading worldActive alone drops the step-down there and
|
||||
-- blits those menus a whole scale larger than the battle they cover.
|
||||
-- Game.drawBaseInStack keeps the map drawing in the common case, so the two
|
||||
-- normally agree; this holds the scale even when it cannot (a battle with
|
||||
-- something other than the overworld beneath it).
|
||||
if not (self.worldActive or self.uiWorldHold) then return S end
|
||||
if off >= 0 then return S end
|
||||
local floorS = math.ceil(S / 2) -- at most a 50% reduction
|
||||
local s = S + off -- one integer step per zoom-out step
|
||||
@@ -621,6 +630,10 @@ end
|
||||
-- pixels, and consumed by endFrame this frame only.
|
||||
-- anchor: "bottom" | "topright" | "topleft" | "bottomright"
|
||||
function Renderer:setUIAnchor(x, y, w, h, anchor)
|
||||
-- uiAnchorHold (Game:draw): a state that composes its own screen -- a
|
||||
-- battle -- keeps every element inside it, so the box blits where it was
|
||||
-- drawn in the canvas instead of being pulled to the window edge.
|
||||
if self.uiAnchorHold then return end
|
||||
self.uiAnchors = self.uiAnchors or {}
|
||||
self.uiAnchors[#self.uiAnchors + 1] =
|
||||
{ x = x, y = y, w = w, h = h, anchor = anchor }
|
||||
@@ -740,6 +753,19 @@ function Renderer:endFrame(zones, worldZones)
|
||||
local stack = ok and Game and Game.stack
|
||||
local base = stack and stack.visibleBase and stack:visibleBase()
|
||||
local state = base and stack.states and stack.states[base]
|
||||
-- A battle owns the surround it established until it leaves the stack.
|
||||
-- Reading it off visibleBase alone loses that the moment the battle opens
|
||||
-- an OPAQUE state -- the party menu, the bag -- because that state becomes
|
||||
-- the base and answers no to letterboxWhite, flipping a white battle
|
||||
-- surround to flat black for as long as the menu is up. Same whole-stack
|
||||
-- hold as uiFill and the dim.
|
||||
for i = #(stack and stack.states or {}), 1, -1 do
|
||||
local s = stack.states[i]
|
||||
if s and s.letterboxWhite then
|
||||
state = s
|
||||
break
|
||||
end
|
||||
end
|
||||
-- BATTLE BG "black" keeps the default black clear; "white" (and any
|
||||
-- non-battle state that opts in) uses the paper shade. "world" never
|
||||
-- reaches here -- it makes the battle non-opaque, so the world pass is
|
||||
|
||||
Reference in New Issue
Block a user