mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
174 lines
6.1 KiB
Lua
174 lines
6.1 KiB
Lua
-- The wall radios: `special MapRadio` -> src/ui/gen2/MapRadio.lua, a port of
|
|
-- engine/pokegear/pokegear.asm PlayRadio.
|
|
--
|
|
-- luajit tests/gen2_map_radio_test.lua
|
|
--
|
|
-- PlayRadio's contract, row by row: resolve the MAPRADIO_* index through
|
|
-- PlayRadioStationPointers (index 0, the Pokemon Channel, resolves by region
|
|
-- and time of day), wait 100 frames with only the station name up, then run
|
|
-- one show frame per loop until A or B, and leave the channel song playing as
|
|
-- the map music on the way out (ExitPokegearRadio_HandleMusic /
|
|
-- RadioMusicRestartDE). Every interaction builds a fresh machine, which is
|
|
-- what makes the radio replayable: back out, talk again, it plays again.
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local S = require("tests.harness").suite("gen2 map radio")
|
|
local check, eq = S.check, S.eq
|
|
|
|
love = require("tests.love_stub")
|
|
|
|
require("src.core.Logger").warn = function() end
|
|
|
|
local MapRadio = require("src.ui.gen2.MapRadio")
|
|
local Music = require("src.core.Music")
|
|
local Save = require("src.core.gen2.Save")
|
|
|
|
-- `call Random`, scripted: hand back the listed bytes in order, cycling.
|
|
local function rolls(...)
|
|
local list = { ... }
|
|
local index = 0
|
|
return function()
|
|
index = index % #list + 1
|
|
return list[index]
|
|
end
|
|
end
|
|
|
|
local function newInput()
|
|
local input = { pressed = {} }
|
|
function input:press(...)
|
|
for _, b in ipairs({ ... }) do self.pressed[b] = true end
|
|
end
|
|
function input:wasPressed(b)
|
|
if self.pressed[b] then self.pressed[b] = nil return true end
|
|
return false
|
|
end
|
|
function input:isDown() return false end
|
|
return input
|
|
end
|
|
|
|
local LANDMARKS = { landmarks = {
|
|
LANDMARK_NEW_BARK_TOWN = { index = 2 },
|
|
LANDMARK_VERMILION_CITY = { index = 50 },
|
|
} }
|
|
|
|
local function newGame(save)
|
|
return {
|
|
input = newInput(),
|
|
save = save,
|
|
options = Save.defaultOptions(),
|
|
data = { audio = {}, pokemon = {}, items = {},
|
|
gen2Landmarks = LANDMARKS },
|
|
stack = { _items = {},
|
|
push = function(self, s) self._items[#self._items + 1] = s end,
|
|
pop = function(self) return table.remove(self._items) end,
|
|
top = function(self) return self._items[#self._items] end,
|
|
},
|
|
}
|
|
end
|
|
|
|
-- Enough of the show tables for LETS_ALL_SING (the Ben/Fern chatter needs
|
|
-- only a weekday) -- the full fixtures live in gen2_menus_test.lua, which
|
|
-- owns the line-by-line show assertions.
|
|
local RADIO_DATA = {
|
|
landmarks = {}, mapLandmark = {}, grass = {}, species = {},
|
|
caught = function() return false end,
|
|
dex = {}, classes = {}, hidden = {},
|
|
weekday = 2, luckyNumber = 42, inJohto = true,
|
|
}
|
|
|
|
-- ---- the blocking loop -----------------------------------------------------
|
|
|
|
do
|
|
local save = Save.newGame()
|
|
local game = newGame(save)
|
|
game.world = { map = { def = { music = "Music_NewBarkTown" } } }
|
|
local done = false
|
|
local mr = MapRadio.new(game, {
|
|
channel = 7, radioData = RADIO_DATA, radioRng = rolls(0),
|
|
save = save, onDone = function() done = true end,
|
|
})
|
|
game.stack:push(mr)
|
|
eq(mr.station, "LETS_ALL_SING", "MAPRADIO index 7 is Let's All Sing")
|
|
eq(mr.radioMusicPlaying, "enterMap",
|
|
".PlayStation parks ENTER_MAP_MUSIC before the show starts")
|
|
|
|
-- `ld c, 100 / call DelayFrames`: no lines and no buttons for 100 frames.
|
|
game.input:press("a")
|
|
for _ = 1, 100 do mr:update(0) end
|
|
eq(#mr.radio.log, 0, "nothing prints during the delay")
|
|
eq(game.stack:top(), mr, "and A during the delay does not close it")
|
|
game.input.pressed = {}
|
|
|
|
-- The loop's first frame: StartPokemonMusicChannel reads the weekday's low
|
|
-- bit and RadioMusicRestartDE lands the song (an even weekday marches).
|
|
mr:update(0)
|
|
eq(mr.radio.music, "Music_PokemonMarch",
|
|
"the sing show starts the weekday's song")
|
|
eq(mr.radioMusicPlaying, "Music_PokemonMarch",
|
|
"and RadioMusicRestartDE parks it for the exit handler")
|
|
|
|
-- Left running, the DJ chatter scrolls through the box.
|
|
for _ = 1, 700 do mr:update(0) end
|
|
check(#mr.radio.log >= 1, "the show prints once the delay is spent")
|
|
|
|
-- A stops the loop: pop, resume, and the song stays as the map music.
|
|
Music.setMapSong("Music_NewBarkTown")
|
|
game.input:press("a")
|
|
mr:update(0)
|
|
eq(game.stack:top(), nil, "A closes the radio")
|
|
eq(done, true, "and resumes the parked script")
|
|
eq(Music.mapSong(), "Music_PokemonMarch",
|
|
"with the playing song left as the map music (wMapMusic)")
|
|
|
|
-- Replay: the next interaction builds a fresh machine and plays again.
|
|
local again = MapRadio.new(game, {
|
|
channel = 7, radioData = RADIO_DATA, radioRng = rolls(0), save = save,
|
|
})
|
|
game.stack:push(again)
|
|
for _ = 1, 101 do again:update(0) end
|
|
eq(again.radio.music, "Music_PokemonMarch", "a second listen plays again")
|
|
for _ = 1, 400 do again:update(0) end
|
|
check(#again.radio.log >= 1, "and prints again")
|
|
game.input:press("b")
|
|
again:update(0)
|
|
eq(game.stack:top(), nil, "B closes it too")
|
|
end
|
|
|
|
-- ---- LoadStation_PokemonChannel --------------------------------------------
|
|
|
|
-- Index 0 is not a station: it resolves by region, and in Johto by time of
|
|
-- day -- the morning airs the Pokedex Show, the rest of the day Oak.
|
|
do
|
|
local save = Save.newGame()
|
|
local function stationFor(landmark, daytime)
|
|
local game = newGame(save)
|
|
game.world = { daytime = daytime,
|
|
map = { def = { music = "Music_NewBarkTown" } } }
|
|
local mr = MapRadio.new(game, {
|
|
channel = 0, radioData = RADIO_DATA, radioRng = rolls(0),
|
|
save = save, currentLandmark = landmark,
|
|
})
|
|
return mr.station
|
|
end
|
|
eq(stationFor("LANDMARK_NEW_BARK_TOWN", "MORN"), "POKEDEX_SHOW",
|
|
"Johto mornings air the Pokedex Show")
|
|
eq(stationFor("LANDMARK_NEW_BARK_TOWN", "DAY"), "OAKS_POKEMON_TALK",
|
|
"and the day belongs to Oak")
|
|
eq(stationFor("LANDMARK_VERMILION_CITY", "DAY"), "PLACES_AND_PEOPLE",
|
|
"from Kanto the same dial carries Places & People")
|
|
end
|
|
|
|
-- ---- the fixed stations ----------------------------------------------------
|
|
|
|
do
|
|
local save = Save.newGame()
|
|
local game = newGame(save)
|
|
local mr = MapRadio.new(game, {
|
|
channel = 4, radioData = RADIO_DATA, radioRng = rolls(0), save = save,
|
|
})
|
|
eq(mr.station, "LUCKY_CHANNEL",
|
|
"Radio2Script's MAPRADIO_LUCKY_CHANNEL is index 4")
|
|
end
|
|
|
|
S.finish()
|