mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-18 19:54:21 +02:00
CLOSES #1418
This commit is contained in:
@@ -1968,6 +1968,7 @@ function Game2:applyOptions()
|
||||
})
|
||||
require("src.core.VideoMode").applyOptions(options)
|
||||
require("src.core.FrameCap").applyOptions(options)
|
||||
require("src.world.gen2.BorderFill").applyOptions(options)
|
||||
local GBCFX = require("src.render.GBCFX")
|
||||
if GBCFX.applyOptions(options) and self.save then
|
||||
-- applyOptions returns true when it had to clear an unsupported level.
|
||||
|
||||
@@ -274,6 +274,9 @@ Save.DEFAULT_OPTIONS = {
|
||||
color = "gbc",
|
||||
videoMode = "windowed",
|
||||
fpsCap = 60,
|
||||
-- VOID FILL: fade | water | trees | black. fade is each map header's own
|
||||
-- border block with the dissolve across a boundary (#1418).
|
||||
voidFill = "fade",
|
||||
musicVol = 7, -- 0-7, like the GB's NR50 master volume
|
||||
sfxVol = 7, -- 0-7
|
||||
musicFilter = 0, -- low-pass steps, 0 = off
|
||||
|
||||
@@ -529,9 +529,9 @@ end
|
||||
-- Gold reads NONE of the rows above. Its OPTION screen writes a different
|
||||
-- set of names, several of which collide with Gen 1's at a different TYPE
|
||||
-- (battleStyle "SHIFT" vs "shift", textSpeed a label vs a frame delay), and
|
||||
-- its renderer has no battle layout, no SGB palette packs and no void fill --
|
||||
-- so a gear opened on the Gold tab used to offer a dozen controls that did
|
||||
-- nothing and hide the seven that the cart itself has.
|
||||
-- its renderer has no battle layout and no SGB palette packs -- so a gear
|
||||
-- opened on the Gold tab used to offer a dozen controls that did nothing
|
||||
-- and hide the seven that the cart itself has.
|
||||
--
|
||||
-- The block lives in options.lua under `gold`, which is exactly where
|
||||
-- src/core/gen2/Save.lua loadOptions reads it, so an edit here is live on the
|
||||
@@ -617,6 +617,21 @@ local function gen2Rows(opts, hooks)
|
||||
end)
|
||||
end
|
||||
|
||||
local okFill, BorderFill = pcall(require, "src.world.gen2.BorderFill")
|
||||
if okFill and BorderFill.VOID_FILLS then
|
||||
add(Strings("VOID FILL"),
|
||||
function() return BorderFill.voidFillLabel(opts.voidFill) end,
|
||||
function(dir)
|
||||
local modes = BorderFill.VOID_FILLS
|
||||
local cur, idx = opts.voidFill or "fade", 1
|
||||
for i, m in ipairs(modes) do
|
||||
if m == cur then idx = i break end
|
||||
end
|
||||
opts.voidFill = modes[wrapIndex(idx - 1 + dir, #modes) + 1]
|
||||
return true
|
||||
end)
|
||||
end
|
||||
|
||||
-- Same #136 gate as the Gen 1 row and the in-game one.
|
||||
local okFx, GBCFX = pcall(require, "src.render.GBCFX")
|
||||
if okFx and GBCFX.isSupported() then
|
||||
|
||||
@@ -134,6 +134,19 @@ local ROWS = {
|
||||
text = function(options)
|
||||
return require("src.render.Zoom").offsetLabel(options.zoom or 0)
|
||||
end },
|
||||
-- VOID FILL: FADE is each map's own border block with the dissolve across
|
||||
-- a boundary; WATER / TREES force one outdoor block; BLACK is a flat void.
|
||||
-- #1418. Same key the Gen 1 OPTION screen uses, different ladder (FADE
|
||||
-- is Gold's default because that is already what the maps call for).
|
||||
{ label = "VOID FILL", key = "voidFill", port = true,
|
||||
cycle = function(options, delta)
|
||||
local BorderFill = require("src.world.gen2.BorderFill")
|
||||
BorderFill.setVoidFill(options.voidFill or "fade")
|
||||
options.voidFill = BorderFill.cycle(delta)
|
||||
end,
|
||||
text = function(options)
|
||||
return require("src.world.gen2.BorderFill").voidFillLabel(options.voidFill)
|
||||
end },
|
||||
{ label = "TILT", key = "tilt", port = true,
|
||||
cycle = function(options, delta)
|
||||
local Tilt = require("src.render.Tilt")
|
||||
|
||||
@@ -152,16 +152,95 @@ function BorderFill.bake(atlas, tileset, blockId, bgSet, waterFrame)
|
||||
return img
|
||||
end
|
||||
|
||||
-- VOID FILL (#1418): the beyond-edge scenery under survey zoom. FADE (the
|
||||
-- default) is each map header's own border block with the dissolve below;
|
||||
-- WATER / TREES force one block on outdoor tilesets that actually have that
|
||||
-- scenery; BLACK is a flat void. Indoor and cave tilesets have no tree wall
|
||||
-- or water metatile, so water/trees fall through to the map's own border
|
||||
-- rather than painting a random block.
|
||||
--
|
||||
-- Canonical ids are the wMapBorderBlock values already used as those fills
|
||||
-- in data/maps/attributes.asm: New Bark / Route 30 $05 trees, Cherrygrove
|
||||
-- $35 water, Pallet $0f trees, Cinnabar $43 water, Ilex Forest $05 trees.
|
||||
BorderFill.VOID_FILLS = { "fade", "water", "trees", "black" }
|
||||
BorderFill.voidFill = "fade"
|
||||
|
||||
local FILL_BLOCKS = {
|
||||
TILESET_JOHTO = { trees = 0x05, water = 0x35 },
|
||||
TILESET_JOHTO_MODERN = { trees = 0x05, water = 0x35 },
|
||||
TILESET_KANTO = { trees = 0x0f, water = 0x43 },
|
||||
TILESET_FOREST = { trees = 0x05 },
|
||||
}
|
||||
|
||||
function BorderFill.setVoidFill(mode)
|
||||
local ok = false
|
||||
for _, name in ipairs(BorderFill.VOID_FILLS) do
|
||||
if name == mode then ok = true; break end
|
||||
end
|
||||
BorderFill.voidFill = ok and mode or "fade"
|
||||
end
|
||||
|
||||
function BorderFill.cycle(delta)
|
||||
local cur = BorderFill.voidFill or "fade"
|
||||
local at = 1
|
||||
for i, name in ipairs(BorderFill.VOID_FILLS) do
|
||||
if name == cur then at = i; break end
|
||||
end
|
||||
local n = #BorderFill.VOID_FILLS
|
||||
at = (at - 1 + (delta or 1)) % n + 1
|
||||
BorderFill.setVoidFill(BorderFill.VOID_FILLS[at])
|
||||
return BorderFill.voidFill
|
||||
end
|
||||
|
||||
function BorderFill.applyOptions(opts)
|
||||
BorderFill.setVoidFill(opts and opts.voidFill or "fade")
|
||||
end
|
||||
|
||||
function BorderFill.voidFillLabel(mode)
|
||||
mode = mode or BorderFill.voidFill or "fade"
|
||||
if mode == "water" then return "WATER" end
|
||||
if mode == "trees" then return "TREES" end
|
||||
if mode == "black" then return "BLACK" end
|
||||
-- trailing space blanks the 5-char WATER/TREES/BLACK from the value column
|
||||
return "FADE "
|
||||
end
|
||||
|
||||
-- The metatile the void should bake, or false when BLACK skips tiling.
|
||||
function BorderFill.fillBlock(def)
|
||||
local mode = BorderFill.voidFill or "fade"
|
||||
if mode == "black" then return false end
|
||||
if (mode == "water" or mode == "trees") and def then
|
||||
local fills = FILL_BLOCKS[def.tileset]
|
||||
local block = fills and fills[mode]
|
||||
if block ~= nil then return block end
|
||||
end
|
||||
return def and def.borderBlock or 0
|
||||
end
|
||||
|
||||
-- Crossfade identity: FADE dissolves per map (Cherrygrove water -> Route 30
|
||||
-- trees). WATER/TREES dissolve only when the forced block itself changes
|
||||
-- (Johto water -> Kanto water), so walking two Johto routes does not fade
|
||||
-- identical water against itself. BLACK is one sheet everywhere.
|
||||
function BorderFill.fillKey(def)
|
||||
local mode = BorderFill.voidFill or "fade"
|
||||
if mode == "black" then return "black" end
|
||||
local block = BorderFill.fillBlock(def)
|
||||
if mode == "water" or mode == "trees" then
|
||||
return mode .. "|" .. tostring(def and def.tileset) .. "|" .. tostring(block)
|
||||
end
|
||||
return "fade|" .. tostring(def and def.id)
|
||||
end
|
||||
|
||||
-- Each map header carries its OWN border block, so crossing a boundary swaps
|
||||
-- the whole void from one block to another: Cherrygrove's water becomes Route
|
||||
-- 30's trees between one frame and the next. On a 20x18 viewport that is a few
|
||||
-- pixels at the screen edge and nobody sees it; under survey zoom the void is
|
||||
-- most of the window, and the swap reads as the background popping.
|
||||
--
|
||||
-- So the swap is dissolved rather than cut. `key` is the map the image belongs
|
||||
-- to, not the image itself: the same block gets re-baked by the daytime
|
||||
-- rollover, the COLOR option and the two-frame cave flicker, and a dissolve on
|
||||
-- any of those would smear the flicker into mush.
|
||||
-- So the swap is dissolved rather than cut. `key` is the fill identity
|
||||
-- (BorderFill.fillKey), not the image itself: the same block gets re-baked by
|
||||
-- the daytime rollover, the COLOR option and the two-frame cave flicker, and a
|
||||
-- dissolve on any of those would smear the flicker into mush.
|
||||
BorderFill.CROSSFADE_FRAMES = 20
|
||||
|
||||
-- The bookkeeping half, love-free so it can be checked without a canvas.
|
||||
|
||||
@@ -7900,8 +7900,10 @@ function World:borderWaterFrame(def, tileset)
|
||||
end
|
||||
end
|
||||
if not tile then return nil end
|
||||
local fill = BorderFill.fillBlock(def)
|
||||
if fill == false then return nil end
|
||||
local block = tileset.blocks
|
||||
and tileset.blocks[BorderFill.blockFor(0, def.borderBlock) + 1]
|
||||
and tileset.blocks[BorderFill.blockFor(0, fill) + 1]
|
||||
if not block then return nil end
|
||||
local found = false
|
||||
for i = 1, 16 do
|
||||
@@ -7933,11 +7935,19 @@ function World:borderImageFor(mapId)
|
||||
if not def then return nil end
|
||||
local tileset = self.tilesets and self.tilesets[def.tileset]
|
||||
if not tileset then return nil end
|
||||
-- VOID FILL black skips the tiled bake; drawGround paints a flat void.
|
||||
local fill = BorderFill.fillBlock(def)
|
||||
if fill == false then return nil end
|
||||
local blockId = BorderFill.blockFor(0, fill)
|
||||
-- A border block made of water animates with the rest of the map, so this
|
||||
-- frame's row joins the key: four bakes per map instead of one.
|
||||
-- frame's row joins the key: four bakes per map instead of one. The VOID
|
||||
-- FILL mode is in the key so switching FADE/WATER/TREES does not keep a
|
||||
-- stale bake (#1418).
|
||||
local waterFrame = self:borderWaterFrame(def, tileset)
|
||||
local cacheKey = BorderFill.cacheKey(mapId .. "|" .. tostring(daytime)
|
||||
.. "|" .. tostring(GbcPalette.mode) .. "|" .. tostring(flicker)
|
||||
.. "|" .. tostring(BorderFill.voidFill or "fade")
|
||||
.. "|" .. tostring(blockId)
|
||||
.. "|" .. tostring(waterFrame and waterFrame.row or 0))
|
||||
local cached = self.mapImages[cacheKey]
|
||||
if cached ~= nil then return cached or nil end
|
||||
@@ -7949,7 +7959,7 @@ function World:borderImageFor(mapId)
|
||||
bgSet = Palettes.withCaveFlicker(bgSet, flicker or 1)
|
||||
end
|
||||
local ok, img = pcall(BorderFill.bake, atlas, tileset,
|
||||
BorderFill.blockFor(0, def.borderBlock), bgSet, waterFrame)
|
||||
blockId, bgSet, waterFrame)
|
||||
-- `false` rather than nil: a bake that cannot be made (a headless run with
|
||||
-- no canvas support) must not be retried once per frame forever.
|
||||
self.mapImages[cacheKey] = (ok and img) or false
|
||||
@@ -9719,8 +9729,16 @@ function World:drawGround(s)
|
||||
else
|
||||
bw, bh = GameViewport.dimensions()
|
||||
end
|
||||
BorderFill.draw(self, self:borderImageFor(self.map.id),
|
||||
cam.x, cam.y, bw, bh, s, self.map.id)
|
||||
if BorderFill.fillBlock(self.map.def) == false then
|
||||
-- BLACK: World:draw clears to a brown letterbox, so the void itself
|
||||
-- has to be an actual black sheet or the map sits on that colour.
|
||||
G.setColor(0, 0, 0, 1)
|
||||
G.rectangle("fill", 0, 0, bw, bh)
|
||||
G.setColor(1, 1, 1, 1)
|
||||
else
|
||||
BorderFill.draw(self, self:borderImageFor(self.map.id),
|
||||
cam.x, cam.y, bw, bh, s, BorderFill.fillKey(self.map.def))
|
||||
end
|
||||
end
|
||||
for _, nb in ipairs(self.neighbors) do
|
||||
G.draw(nb.image,
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
-- Gold VOID FILL (#1418): FADE (each map's own border, dissolving across a
|
||||
-- boundary), WATER, TREES, or BLACK. Parks you on Cherrygrove zoomed out so
|
||||
-- the void is most of the window, cycles the four modes, then hands the pad
|
||||
-- over. Do not add POKEPORT_SPEED: the water anim and the dissolve both run
|
||||
-- on the real clock.
|
||||
--
|
||||
-- POKEPORT_IDENTITY=gold-dev POKEPORT_GAME=gold \
|
||||
-- POKEPORT_DRIVER=tests/drivers/gold_void_fill_bug1418_test.lua love .
|
||||
|
||||
local U = require("tests.drivers.util")
|
||||
|
||||
return function(game)
|
||||
local out = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/gold-void-fill"
|
||||
local BorderFill = require("src.world.gen2.BorderFill")
|
||||
local Tilt = require("src.render.Tilt")
|
||||
local Zoom = require("src.render.Zoom")
|
||||
local failures = 0
|
||||
|
||||
local function ok(label, condition, detail)
|
||||
if condition then
|
||||
print("[void] ok " .. label)
|
||||
else
|
||||
failures = failures + 1
|
||||
print("[void] FAIL " .. label .. " " .. tostring(detail))
|
||||
end
|
||||
end
|
||||
|
||||
U.wait(45)
|
||||
local world = game.world
|
||||
assert(world and world.map, "gold world did not boot")
|
||||
|
||||
-- Cherrygrove's header border is water ($35). FADE shows that water,
|
||||
-- TREES replaces it, BLACK drops the sheet. attributes.asm:123.
|
||||
world:setMap("CHERRYGROVE_CITY", 22, 16, "down")
|
||||
U.wait(10)
|
||||
|
||||
Zoom.offset = -3
|
||||
world:rebuildNeighbors()
|
||||
world:rebuildPeople({ seamless = true })
|
||||
Tilt.setLevel(3)
|
||||
for _ = 1, 40 do
|
||||
Tilt.update(1 / 60)
|
||||
U.wait(1)
|
||||
end
|
||||
|
||||
local function show(mode, file, label)
|
||||
BorderFill.setVoidFill(mode)
|
||||
if game.options then game.options.voidFill = mode end
|
||||
if game.save and game.save.options then
|
||||
game.save.options.voidFill = mode
|
||||
end
|
||||
U.wait(8)
|
||||
ok(label, BorderFill.voidFill == mode, BorderFill.voidFill)
|
||||
U.shot(game, out .. "/" .. file)
|
||||
end
|
||||
|
||||
show("fade", "01-fade.png", "FADE is the live fill")
|
||||
show("water", "02-water.png", "WATER forces the water block")
|
||||
show("trees", "03-trees.png", "TREES forces the tree wall")
|
||||
show("black", "04-black.png", "BLACK drops the tiled void")
|
||||
show("fade", "05-fade-again.png", "and FADE restores the map's own border")
|
||||
|
||||
Tilt.setLevel(0)
|
||||
Zoom.offset = 0
|
||||
world:rebuildNeighbors()
|
||||
world:rebuildPeople({ seamless = true })
|
||||
|
||||
if failures > 0 then
|
||||
print(("[driver] FAIL gold void fill: %d check(s)"):format(failures))
|
||||
return
|
||||
end
|
||||
print("[driver] PASS gold void fill in " .. out)
|
||||
U.log("cycled fade/water/trees/black on cherrygrove (#1418).")
|
||||
U.log("OPTION > VOID FILL, zoom out (-) to see the void.")
|
||||
|
||||
while true do
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
@@ -43,6 +43,15 @@ local gold = LauncherSettings.open(hooks, "gold")
|
||||
check(has(gold, "TOUCH PAD"), "Gold's gear offers TOUCH PAD")
|
||||
check(has(gold, "VIBRATION"), "and VIBRATION")
|
||||
check(has(gold, "TOUCH CONTROLS"), "and the layout editor")
|
||||
check(has(gold, "VOID FILL"), "and VOID FILL")
|
||||
|
||||
local voidFill = findRow(gold, "VOID FILL")
|
||||
eq(voidFill.value(), "FADE ", "VOID FILL defaults to FADE")
|
||||
voidFill.step(1)
|
||||
eq(gold.opts.gold.voidFill, "water", "right stores water in the gold block")
|
||||
eq(voidFill.value(), "WATER", "and the row reads WATER")
|
||||
voidFill.step(-1)
|
||||
eq(gold.opts.gold.voidFill, "fade", "left restores fade")
|
||||
|
||||
-- Every write has to land in the gold block: the flat keys beside it are
|
||||
-- Red's, and Gold's boot never reads them (src/core/gen2/Save.lua:299).
|
||||
|
||||
@@ -84,6 +84,63 @@ end
|
||||
local _, _, vw0, vh0 = BorderFill.viewport(0, 0, 160, 144, 0)
|
||||
check(vw0 > 0 and vh0 > 0, "scale 0 falls back to 1 rather than collapsing")
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- VOID FILL (#1418): FADE / WATER / TREES / BLACK
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
eq(BorderFill.voidFill, "fade", "the live fill defaults to FADE")
|
||||
eq(BorderFill.voidFillLabel(), "FADE ", "and prints with a trailing space")
|
||||
|
||||
local johto = { id = "CHERRYGROVE_CITY", tileset = "TILESET_JOHTO",
|
||||
borderBlock = 0x35 }
|
||||
local route = { id = "ROUTE_30", tileset = "TILESET_JOHTO", borderBlock = 0x05 }
|
||||
local kanto = { id = "PALLET_TOWN", tileset = "TILESET_KANTO",
|
||||
borderBlock = 0x0f }
|
||||
local cave = { id = "UNION_CAVE_1F", tileset = "TILESET_CAVE", borderBlock = 0x09 }
|
||||
local house = { id = "PLAYERS_HOUSE_1F", tileset = "TILESET_PLAYERS_HOUSE",
|
||||
borderBlock = 0x00 }
|
||||
|
||||
eq(BorderFill.fillBlock(johto), 0x35, "FADE keeps Cherrygrove's water")
|
||||
eq(BorderFill.fillBlock(route), 0x05, "and Route 30's trees")
|
||||
eq(BorderFill.fillKey(johto), "fade|CHERRYGROVE_CITY",
|
||||
"FADE dissolves per map")
|
||||
eq(BorderFill.fillKey(route) ~= BorderFill.fillKey(johto), true,
|
||||
"so the two maps are different fills")
|
||||
|
||||
BorderFill.setVoidFill("water")
|
||||
eq(BorderFill.fillBlock(johto), 0x35, "WATER uses Cherrygrove's water block")
|
||||
eq(BorderFill.fillBlock(route), 0x35, "on Route 30 too")
|
||||
eq(BorderFill.fillBlock(kanto), 0x43, "and Cinnabar's water on Kanto")
|
||||
eq(BorderFill.fillBlock(cave), 0x09, "but a cave keeps its own border")
|
||||
eq(BorderFill.fillBlock(house), 0x00, "and so does a house")
|
||||
eq(BorderFill.fillKey(johto), BorderFill.fillKey(route),
|
||||
"two Johto maps share one WATER fill")
|
||||
eq(BorderFill.fillKey(johto) ~= BorderFill.fillKey(kanto), true,
|
||||
"Kanto water is a different sheet")
|
||||
|
||||
BorderFill.setVoidFill("trees")
|
||||
eq(BorderFill.fillBlock(johto), 0x05, "TREES uses New Bark's tree wall")
|
||||
eq(BorderFill.fillBlock(kanto), 0x0f, "and Pallet's on Kanto")
|
||||
eq(BorderFill.fillBlock(cave), 0x09, "caves still keep their own")
|
||||
|
||||
BorderFill.setVoidFill("black")
|
||||
eq(BorderFill.fillBlock(johto), false, "BLACK skips the tiled bake")
|
||||
eq(BorderFill.fillBlock(house), false, "indoors too")
|
||||
eq(BorderFill.fillKey(johto), "black", "and is one sheet everywhere")
|
||||
|
||||
BorderFill.setVoidFill("nope")
|
||||
eq(BorderFill.voidFill, "fade", "an unknown mode falls back to FADE")
|
||||
BorderFill.setVoidFill("fade")
|
||||
eq(BorderFill.cycle(1), "water", "cycle steps FADE to WATER")
|
||||
eq(BorderFill.cycle(1), "trees", "then TREES")
|
||||
eq(BorderFill.cycle(1), "black", "then BLACK")
|
||||
eq(BorderFill.cycle(1), "fade", "and wraps to FADE")
|
||||
eq(BorderFill.cycle(-1), "black", "left wraps the other way")
|
||||
BorderFill.applyOptions({ voidFill = "trees" })
|
||||
eq(BorderFill.voidFill, "trees", "applyOptions pushes the saved mode")
|
||||
BorderFill.applyOptions({})
|
||||
eq(BorderFill.voidFill, "fade", "and a missing key restores FADE")
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- The real cache: the map the bug was reported on
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
@@ -213,6 +213,22 @@ previous, alpha = BorderFill.crossfade(owner, trees, "ROUTE_30")
|
||||
check("then it is over", previous, nil)
|
||||
check("and the new block owns the void", alpha, 1)
|
||||
|
||||
-- Forced WATER on two Johto maps shares a fill key, so the dissolve does
|
||||
-- not run identical water against itself.
|
||||
BorderFill.setVoidFill("water")
|
||||
local johtoWater = { id = "CHERRYGROVE_CITY", tileset = "TILESET_JOHTO",
|
||||
borderBlock = 0x35 }
|
||||
local routeTrees = { id = "ROUTE_30", tileset = "TILESET_JOHTO",
|
||||
borderBlock = 0x05 }
|
||||
check("WATER fill keys match across Johto",
|
||||
BorderFill.fillKey(johtoWater), BorderFill.fillKey(routeTrees))
|
||||
local forced = {}
|
||||
BorderFill.crossfade(forced, "water", BorderFill.fillKey(johtoWater))
|
||||
local fromForced = BorderFill.crossfade(forced, "water",
|
||||
BorderFill.fillKey(routeTrees))
|
||||
check("so walking Route 30 does not start a fade", fromForced, nil)
|
||||
BorderFill.setVoidFill("fade")
|
||||
|
||||
-- No key at all (an old caller) is the plain single draw.
|
||||
local bare = {}
|
||||
previous, alpha = BorderFill.crossfade(bare, trees, nil)
|
||||
|
||||
@@ -358,7 +358,7 @@ local options = OptionsMenu.new(optionsGame, {
|
||||
})
|
||||
-- The cart's seven rows, then the port's: CONTROLS, audio, speed, display,
|
||||
-- video mode, the mobile-gated touch three (buildRows), MAX FPS and CANCEL.
|
||||
check("twenty-two rows", #OptionsMenu.ROWS, 22)
|
||||
check("twenty-three rows", #OptionsMenu.ROWS, 23)
|
||||
check("the cart's rows come first", OptionsMenu.ROWS[7].key, "frame")
|
||||
check("then the rebind screen", OptionsMenu.ROWS[8].id, "controls")
|
||||
check("then the port's audio group", OptionsMenu.ROWS[9].key, "musicVol")
|
||||
@@ -861,10 +861,15 @@ check("GBC leaves a palette alone",
|
||||
1)[1], 1)
|
||||
check("and has no present pass", GbcPalette.presentColors(), nil)
|
||||
|
||||
local gbcfxIndex
|
||||
local zoomIndex, gbcfxIndex
|
||||
for i, row in ipairs(OptionsMenu.ROWS) do
|
||||
if row.label == "ZOOM" then zoomIndex = i end
|
||||
if row.label == "GBC FX" then gbcfxIndex = i end
|
||||
end
|
||||
check("VOID FILL follows ZOOM", OptionsMenu.ROWS[zoomIndex + 1].label,
|
||||
"VOID FILL")
|
||||
check("and TILT follows VOID FILL", OptionsMenu.ROWS[zoomIndex + 2].label,
|
||||
"TILT")
|
||||
check("VIDEO MODE follows GBC FX", OptionsMenu.ROWS[gbcfxIndex + 1].label,
|
||||
"VIDEO MODE")
|
||||
check("and TOUCH PAD follows it", OptionsMenu.ROWS[gbcfxIndex + 2].label,
|
||||
@@ -897,6 +902,28 @@ scrollOptions:cycle(videoRow, -1)
|
||||
check("left toggles back to windowed",
|
||||
scrollOptions.options.videoMode, "windowed")
|
||||
|
||||
local voidRow = select(2, rowNamed("VOID FILL"))
|
||||
check("VOID FILL is a row", voidRow ~= nil, true)
|
||||
check("and it defaults to FADE", Save.DEFAULT_OPTIONS.voidFill, "fade")
|
||||
scrollOptions.options.voidFill = "fade"
|
||||
local BorderFill = require("src.world.gen2.BorderFill")
|
||||
BorderFill.setVoidFill("fade")
|
||||
scrollOptions:cycle(voidRow, 1)
|
||||
check("right steps to WATER", scrollOptions.options.voidFill, "water")
|
||||
check("and the live fill tracks it", BorderFill.voidFill, "water")
|
||||
scrollOptions:cycle(voidRow, 1)
|
||||
check("then TREES", scrollOptions.options.voidFill, "trees")
|
||||
scrollOptions:cycle(voidRow, 1)
|
||||
check("then BLACK", scrollOptions.options.voidFill, "black")
|
||||
scrollOptions:cycle(voidRow, 1)
|
||||
check("and wraps back to FADE", scrollOptions.options.voidFill, "fade")
|
||||
check("FADE blanks the longer labels", voidRow.text(scrollOptions.options),
|
||||
"FADE ")
|
||||
scrollOptions.options.voidFill = "water"
|
||||
check("WATER fits the value column", voidRow.text(scrollOptions.options),
|
||||
"WATER")
|
||||
BorderFill.setVoidFill("fade")
|
||||
|
||||
check("text reads WINDOWED", videoRow.text(scrollOptions.options), "WINDOWED")
|
||||
scrollOptions.options.videoMode = "borderless"
|
||||
check("text reads FULL, not BORDERLESS", videoRow.text(scrollOptions.options),
|
||||
|
||||
Reference in New Issue
Block a user