mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-28 18:06:09 +02:00
@@ -2753,7 +2753,8 @@ function RomExtractorGen2:extractAudio(maps)
|
||||
local speciesOrder = self.manifest.constants.speciesOrder or {}
|
||||
local cries = {}
|
||||
for index, species in ipairs(speciesOrder) do
|
||||
if species ~= "UNOWN" and not tostring(species):match("^UNUSED") then
|
||||
-- data/pokemon/cries.asm:209 gives UNOWN a real cry row
|
||||
if not tostring(species):match("^UNUSED") then
|
||||
local row = self.rom:bytes(
|
||||
pokeCryPtr.bank, pokeCryPtr.address + (index - 1) * 6, 6)
|
||||
local cryIndex = row[1] + row[2] * 256
|
||||
|
||||
@@ -112,6 +112,8 @@ function TextBox.new(game, text, onDone, opts)
|
||||
self.stay = opts and opts.stay
|
||||
-- engine/events/hidden_events/cinnabar_gym_quiz.asm:119
|
||||
self.preSound = opts and opts.preSound
|
||||
-- pokegold engine/overworld/scripting.asm:485 WaitSFX
|
||||
self.sfxWait = opts and opts.sfxWait
|
||||
-- opts.instant: put the LAST page up already typed, with no typewriter and
|
||||
-- no page waits. A `yesorno` follows a `writetext` that has already been
|
||||
-- read, so re-typing the line under the YES/NO box would be wrong -- the
|
||||
@@ -328,6 +330,14 @@ function TextBox:visibleText()
|
||||
return #out > 0 and out or nil
|
||||
end
|
||||
|
||||
-- pokegold engine/overworld/scripting.asm:484-485 PlaySFX / WaitSFX
|
||||
function TextBox:sfxHeld()
|
||||
if not self.sfxWait then return false end
|
||||
if require("src.core.Sound").sfxBusy() then return true end
|
||||
self.sfxWait = nil
|
||||
return false
|
||||
end
|
||||
|
||||
function TextBox:update(dt)
|
||||
local input = self.game.input
|
||||
self.blink = (self.blink + 1) % 60
|
||||
@@ -444,6 +454,7 @@ function TextBox:update(dt)
|
||||
end
|
||||
return
|
||||
end
|
||||
if self:sfxHeld() then return end
|
||||
if input:wasPressed("a") or input:wasPressed("b") then
|
||||
require("src.core.Sound").play(self.game.data, "Press_AB")
|
||||
self.game.stack:pop()
|
||||
@@ -459,6 +470,7 @@ function TextBox:update(dt)
|
||||
self.preWait = self.preWait - 1
|
||||
return
|
||||
end
|
||||
if self:sfxHeld() then return end
|
||||
if input:wasPressed("a") or input:wasPressed("b") then
|
||||
require("src.core.Sound").play(self.game.data, "Press_AB")
|
||||
self.waiting = false
|
||||
|
||||
@@ -150,13 +150,10 @@ end
|
||||
|
||||
-- true while the spinner arrow tiles should show the 'blur' graphic; false
|
||||
-- means draw nothing extra (the static window tile shows through,
|
||||
-- matching the asm's restore-to-original behavior). The 8-tick
|
||||
-- half-period approximates one GB movement step (2px/frame); this is a
|
||||
-- deliberate approximation of wSimulatedJoypadStatesIndex bit-0 parity, not
|
||||
-- a cycle-accurate replication -- the port's tweened scriptMove has no
|
||||
-- direct equivalent discrete step counter.
|
||||
-- matching the asm's restore-to-original behavior).
|
||||
-- spinners.asm:17-22, home/overworld.asm:1844-1846, :49-52
|
||||
function TileRenderer.spinBlurActive()
|
||||
return spinning and (math.floor(animFrame / 8) % 2 == 0)
|
||||
return spinning and (math.floor(animFrame / 16) % 2 == 0)
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------
|
||||
|
||||
@@ -152,6 +152,12 @@ local function answer(vm, value)
|
||||
vm.scriptVar = value or 0
|
||||
end
|
||||
|
||||
-- WaitSFX (pokegold home/audio.asm); a test stub that calls a handler off
|
||||
-- the coroutine has no sfx to drain.
|
||||
local function drainSfx()
|
||||
if coroutine.running() then coroutine.yield({ kind = "waitsfx" }) end
|
||||
end
|
||||
|
||||
-- Every routine that ends `call GetPokemonName / jp
|
||||
-- CopyPokemonName_Buffer1_Buffer3` puts a name where the next writetext's
|
||||
-- {STRBUF} will find it.
|
||||
@@ -452,8 +458,10 @@ H.BugContestJudging = function(vm)
|
||||
local what = (h.monName and h.monName(entry.species)) or entry.species
|
||||
or ""
|
||||
vm:showRaw(Strings(row.page, who, what))
|
||||
-- pokegold engine/events/bug_contest/judging.asm:29-32
|
||||
drainSfx()
|
||||
if h.playSfxNamed then h.playSfxNamed(row.sfx) end
|
||||
vm:showRaw(Strings(row.score, entry.score or 0))
|
||||
vm:showRaw(Strings(row.score, entry.score or 0), nil, nil, true)
|
||||
end
|
||||
end
|
||||
answer(vm, place)
|
||||
@@ -2033,12 +2041,10 @@ H.ProfOaksPCBoot = function(vm)
|
||||
vm:showRaw(Strings(OAK_PC_TEXT.counts, seen, caught))
|
||||
local rating = findOakRating(caught)
|
||||
local h = hooks(vm)
|
||||
-- pokegold engine/events/prof_oaks_pc.asm:18-20 PlaySFX / JoyWaitAorB / WaitSFX
|
||||
drainSfx()
|
||||
if h.playSfxNamed then h.playSfxNamed(rating.sfx) end
|
||||
vm:showRaw(Strings(rating.text))
|
||||
-- `call PlaySFX / call JoyWaitAorB / call WaitSFX`: the fanfare is left
|
||||
-- playing under the rating text, and the caller (OaksLab's own script)
|
||||
-- waits it out before closing the box.
|
||||
coroutine.yield({ kind = "waitsfx" })
|
||||
vm:showRaw(Strings(rating.text), nil, nil, true)
|
||||
end
|
||||
|
||||
-- The whose-PC menu's PROF.OAK's PC row (src/ui/gen2/CenterPcMenu.lua) runs
|
||||
|
||||
+10
-6
@@ -700,8 +700,10 @@ local function runCmd(self, cmd, op)
|
||||
-- GetPocketName fills from ItemPocketNames: KEY ITEMs, BALLs and TMs
|
||||
-- name their own pocket, not the ITEM one (data/text/common_2.asm
|
||||
-- :1351, data/items/pocket_names.asm:10-13).
|
||||
-- Script_specialsound's WaitSFX (scripting.asm:485): the box holds
|
||||
-- its press until the jingle ends.
|
||||
self:showRaw(Strings("{PLAYER} put the\n%s in\nthe %s.",
|
||||
name, self:pocketName(item)))
|
||||
name, self:pocketName(item)), nil, nil, true)
|
||||
else
|
||||
self:showRaw(Strings("The %s\nis full…", self:pocketName(item)))
|
||||
end
|
||||
@@ -1510,8 +1512,8 @@ local function runCmd(self, cmd, op)
|
||||
self.playSoundFn(SFX_ITEM)
|
||||
end
|
||||
-- FruitTreeScript's tail is `specialsound / itemnotify` with NOTHING
|
||||
-- between them (engine/events/fruit_trees.asm:23-24), and Script_specialsound
|
||||
-- is a bare PlaySFX -- it does not wait either (scripting.asm:476-483).
|
||||
-- between them (engine/events/fruit_trees.asm:23-24);
|
||||
-- Script_specialsound ends PlaySFX / WaitSFX (scripting.asm:484-485)
|
||||
-- The port used to park here on a `waitsfx`, which is the same seam
|
||||
-- GiveItemScript's did: this port's box takes its own button and pops on
|
||||
-- it, so the park ran with an EMPTY state stack and the bare overworld
|
||||
@@ -1523,7 +1525,7 @@ local function runCmd(self, cmd, op)
|
||||
-- noun still comes from ItemPocketNames rather than from a third copy of
|
||||
-- the literal (data/items/pocket_names.asm:10-13).
|
||||
self:showRaw(Strings("{PLAYER} put the\n%s in\nthe %s.",
|
||||
name, self:pocketName(item)))
|
||||
name, self:pocketName(item)), nil, nil, true)
|
||||
return "end"
|
||||
elseif op == "describedecoration" then
|
||||
-- `describedecoration byte` picks one of five DECODESC_* arms
|
||||
@@ -2427,7 +2429,7 @@ end
|
||||
-- the port's world does not tick while a box is on the stack (Game2:update
|
||||
-- stops at the top state), so the only clock that can count it is the box's;
|
||||
-- World:showText is where it lands.
|
||||
function Vm:showRaw(body, stay, hold)
|
||||
function Vm:showRaw(body, stay, hold, sfxWait)
|
||||
if not body or body == "" then body = "..." end
|
||||
if self.stringBuffer and self.stringBuffer ~= "" then
|
||||
body = body:gsub("{STRBUF}", self.stringBuffer)
|
||||
@@ -2438,6 +2440,8 @@ function Vm:showRaw(body, stay, hold)
|
||||
text = body,
|
||||
stay = (stay or self:textStays()) and true or false,
|
||||
hold = hold,
|
||||
-- pokegold engine/overworld/scripting.asm:485 WaitSFX
|
||||
sfxWait = sfxWait and true or nil,
|
||||
})
|
||||
end
|
||||
end
|
||||
@@ -2646,7 +2650,7 @@ function Vm:resume(resumeValue)
|
||||
if req and req.kind == "text" and self.showTextFn then
|
||||
self.showTextFn(req.text, function()
|
||||
self:resume()
|
||||
end, req.stay, req.hold)
|
||||
end, req.stay, req.hold, req.sfxWait)
|
||||
elseif req and req.kind == "wait" then
|
||||
self.waitLeft = req.frames or 0
|
||||
elseif req and req.kind == "waitbutton" then
|
||||
|
||||
@@ -605,7 +605,7 @@ function BattleState:animData(mon)
|
||||
local def = self.pokemon and mon and self.pokemon[mon.species]
|
||||
if not def then return nil end
|
||||
if mon.species == Unown.SPECIES and def.letters then
|
||||
local entry = def.letters[Unown.monLetter(mon)]
|
||||
local entry = def.letters[Unown.name(Unown.monLetter(mon))]
|
||||
if entry and entry.anim then return entry.anim end
|
||||
end
|
||||
return def.anim
|
||||
|
||||
@@ -336,7 +336,7 @@ function SummaryMenu:startPicAnim()
|
||||
if not def then return end
|
||||
local data = def.anim
|
||||
if mon.species == Unown.SPECIES and def.letters then
|
||||
local entry = def.letters[Unown.monLetter(mon)]
|
||||
local entry = def.letters[Unown.name(Unown.monLetter(mon))]
|
||||
if entry and entry.anim then data = entry.anim end
|
||||
end
|
||||
if not data then return end
|
||||
|
||||
@@ -182,6 +182,9 @@ function Player:update()
|
||||
if self.turnTimer > 0 then
|
||||
self.turnTimer = self.turnTimer - 1
|
||||
end
|
||||
if self.spinning then
|
||||
self.spinTimer = (self.spinTimer or 0) + 1
|
||||
end
|
||||
if self.spinFrames then
|
||||
self.spinFrames = self.spinFrames - 1
|
||||
if self.spinFrames <= 0 then
|
||||
@@ -261,11 +264,6 @@ local SPIN_ORDER = { "down", "left", "up", "right" }
|
||||
--
|
||||
-- The last return says the player is mid-ledge-hop, which is what the 2D
|
||||
-- path draws the ground shadow from and a 3D path turns into vertical lift.
|
||||
--
|
||||
-- This ADVANCES the surf-bob and spinner timers, so exactly one of pose()
|
||||
-- and draw() may run per frame -- and draw() is written in terms of pose()
|
||||
-- to keep that true by construction. (hopFrames counts down in
|
||||
-- Player:update, on the fixed step, so it is safe to read here.)
|
||||
function Player:pose()
|
||||
local py = self.py
|
||||
local hopping = false
|
||||
@@ -288,10 +286,8 @@ function Player:pose()
|
||||
-- the leg cadence
|
||||
local flip = math.floor((self.animClock or 0) / 16) % 2 == 1
|
||||
if self.spinning then
|
||||
-- spinner tiles whirl the sprite on its standing pose, one facing
|
||||
-- per frame (LoadSpinnerArrowTiles runs every OverworldLoop frame)
|
||||
self.spinTimer = (self.spinTimer or 0) + 1
|
||||
facing = SPIN_ORDER[self.spinTimer % 4 + 1]
|
||||
-- spinners.asm:1-11, home/overworld.asm:41-44, :268-272
|
||||
facing = SPIN_ORDER[math.floor((self.spinTimer or 0) / 2) % 4 + 1]
|
||||
phase, flip = 0, false
|
||||
-- teleport arrivals spin the sprite down into place
|
||||
-- (EnterMapAnim PlayerSpinWhileMovingDown)
|
||||
|
||||
@@ -187,6 +187,11 @@ function FieldMoves.bindEngineFlags(order)
|
||||
-- row, so every id from BUG_CONTEST_TIMER up shifts one.
|
||||
FieldMoves.BUG_CONTEST_FLAG = byName["ENGINE_BUG_CONTEST_TIMER"] or 16
|
||||
FieldMoves.BIKE_SHOP_CALL_FLAG = byName["ENGINE_BIKE_SHOP_CALL_ENABLED"] or 19
|
||||
-- pokecrystal constants/engine_flags.asm:66-92 vs pokegold :65-91
|
||||
for _, row in ipairs(FieldMoves.FLYPOINTS or {}) do
|
||||
row.goldFlag = row.goldFlag or row.flag
|
||||
row.flag = byName[row.name] or row.goldFlag
|
||||
end
|
||||
return flags
|
||||
end
|
||||
|
||||
@@ -475,33 +480,35 @@ end
|
||||
-- const_def count (0-based, ENGINE_RADIO_CARD is 0): the byte a town's own
|
||||
-- MAPCALLBACK_NEWMAP callback sets with `setflag` the first time you walk in,
|
||||
-- and what FieldMoves.hasVisitedSpawn below actually reads.
|
||||
-- Ids are pokegold's; bindEngineFlags rebinds by name (pokecrystal
|
||||
-- constants/engine_flags.asm:25 ENGINE_MOBILE_SYSTEM shifts them +1).
|
||||
FieldMoves.FLYPOINTS = {
|
||||
-- Johto
|
||||
{ landmark = "LANDMARK_NEW_BARK_TOWN", spawn = "SPAWN_NEW_BARK", flag = 64 },
|
||||
{ landmark = "LANDMARK_CHERRYGROVE_CITY", spawn = "SPAWN_CHERRYGROVE", flag = 65 },
|
||||
{ landmark = "LANDMARK_VIOLET_CITY", spawn = "SPAWN_VIOLET", flag = 66 },
|
||||
{ landmark = "LANDMARK_AZALEA_TOWN", spawn = "SPAWN_AZALEA", flag = 67 },
|
||||
{ landmark = "LANDMARK_GOLDENROD_CITY", spawn = "SPAWN_GOLDENROD", flag = 69 },
|
||||
{ landmark = "LANDMARK_ECRUTEAK_CITY", spawn = "SPAWN_ECRUTEAK", flag = 71 },
|
||||
{ landmark = "LANDMARK_OLIVINE_CITY", spawn = "SPAWN_OLIVINE", flag = 70 },
|
||||
{ landmark = "LANDMARK_CIANWOOD_CITY", spawn = "SPAWN_CIANWOOD", flag = 68 },
|
||||
{ landmark = "LANDMARK_MAHOGANY_TOWN", spawn = "SPAWN_MAHOGANY", flag = 72 },
|
||||
{ landmark = "LANDMARK_LAKE_OF_RAGE", spawn = "SPAWN_LAKE_OF_RAGE", flag = 73 },
|
||||
{ landmark = "LANDMARK_BLACKTHORN_CITY", spawn = "SPAWN_BLACKTHORN", flag = 74 },
|
||||
{ landmark = "LANDMARK_SILVER_CAVE", spawn = "SPAWN_MT_SILVER", flag = 75 },
|
||||
{ landmark = "LANDMARK_NEW_BARK_TOWN", spawn = "SPAWN_NEW_BARK", flag = 64, name = "ENGINE_FLYPOINT_NEW_BARK" },
|
||||
{ landmark = "LANDMARK_CHERRYGROVE_CITY", spawn = "SPAWN_CHERRYGROVE", flag = 65, name = "ENGINE_FLYPOINT_CHERRYGROVE" },
|
||||
{ landmark = "LANDMARK_VIOLET_CITY", spawn = "SPAWN_VIOLET", flag = 66, name = "ENGINE_FLYPOINT_VIOLET" },
|
||||
{ landmark = "LANDMARK_AZALEA_TOWN", spawn = "SPAWN_AZALEA", flag = 67, name = "ENGINE_FLYPOINT_AZALEA" },
|
||||
{ landmark = "LANDMARK_GOLDENROD_CITY", spawn = "SPAWN_GOLDENROD", flag = 69, name = "ENGINE_FLYPOINT_GOLDENROD" },
|
||||
{ landmark = "LANDMARK_ECRUTEAK_CITY", spawn = "SPAWN_ECRUTEAK", flag = 71, name = "ENGINE_FLYPOINT_ECRUTEAK" },
|
||||
{ landmark = "LANDMARK_OLIVINE_CITY", spawn = "SPAWN_OLIVINE", flag = 70, name = "ENGINE_FLYPOINT_OLIVINE" },
|
||||
{ landmark = "LANDMARK_CIANWOOD_CITY", spawn = "SPAWN_CIANWOOD", flag = 68, name = "ENGINE_FLYPOINT_CIANWOOD" },
|
||||
{ landmark = "LANDMARK_MAHOGANY_TOWN", spawn = "SPAWN_MAHOGANY", flag = 72, name = "ENGINE_FLYPOINT_MAHOGANY" },
|
||||
{ landmark = "LANDMARK_LAKE_OF_RAGE", spawn = "SPAWN_LAKE_OF_RAGE", flag = 73, name = "ENGINE_FLYPOINT_LAKE_OF_RAGE" },
|
||||
{ landmark = "LANDMARK_BLACKTHORN_CITY", spawn = "SPAWN_BLACKTHORN", flag = 74, name = "ENGINE_FLYPOINT_BLACKTHORN" },
|
||||
{ landmark = "LANDMARK_SILVER_CAVE", spawn = "SPAWN_MT_SILVER", flag = 75, name = "ENGINE_FLYPOINT_SILVER_CAVE" },
|
||||
-- Kanto
|
||||
{ landmark = "LANDMARK_PALLET_TOWN", spawn = "SPAWN_PALLET", flag = 52 },
|
||||
{ landmark = "LANDMARK_VIRIDIAN_CITY", spawn = "SPAWN_VIRIDIAN", flag = 53 },
|
||||
{ landmark = "LANDMARK_PEWTER_CITY", spawn = "SPAWN_PEWTER", flag = 54 },
|
||||
{ landmark = "LANDMARK_CERULEAN_CITY", spawn = "SPAWN_CERULEAN", flag = 55 },
|
||||
{ landmark = "LANDMARK_VERMILION_CITY", spawn = "SPAWN_VERMILION", flag = 57 },
|
||||
{ landmark = "LANDMARK_ROCK_TUNNEL", spawn = "SPAWN_ROCK_TUNNEL", flag = 56 },
|
||||
{ landmark = "LANDMARK_LAVENDER_TOWN", spawn = "SPAWN_LAVENDER", flag = 58 },
|
||||
{ landmark = "LANDMARK_CELADON_CITY", spawn = "SPAWN_CELADON", flag = 60 },
|
||||
{ landmark = "LANDMARK_SAFFRON_CITY", spawn = "SPAWN_SAFFRON", flag = 59 },
|
||||
{ landmark = "LANDMARK_FUCHSIA_CITY", spawn = "SPAWN_FUCHSIA", flag = 61 },
|
||||
{ landmark = "LANDMARK_CINNABAR_ISLAND", spawn = "SPAWN_CINNABAR", flag = 62 },
|
||||
{ landmark = "LANDMARK_INDIGO_PLATEAU", spawn = "SPAWN_INDIGO", flag = 63 },
|
||||
{ landmark = "LANDMARK_PALLET_TOWN", spawn = "SPAWN_PALLET", flag = 52, name = "ENGINE_FLYPOINT_PALLET" },
|
||||
{ landmark = "LANDMARK_VIRIDIAN_CITY", spawn = "SPAWN_VIRIDIAN", flag = 53, name = "ENGINE_FLYPOINT_VIRIDIAN" },
|
||||
{ landmark = "LANDMARK_PEWTER_CITY", spawn = "SPAWN_PEWTER", flag = 54, name = "ENGINE_FLYPOINT_PEWTER" },
|
||||
{ landmark = "LANDMARK_CERULEAN_CITY", spawn = "SPAWN_CERULEAN", flag = 55, name = "ENGINE_FLYPOINT_CERULEAN" },
|
||||
{ landmark = "LANDMARK_VERMILION_CITY", spawn = "SPAWN_VERMILION", flag = 57, name = "ENGINE_FLYPOINT_VERMILION" },
|
||||
{ landmark = "LANDMARK_ROCK_TUNNEL", spawn = "SPAWN_ROCK_TUNNEL", flag = 56, name = "ENGINE_FLYPOINT_ROCK_TUNNEL" },
|
||||
{ landmark = "LANDMARK_LAVENDER_TOWN", spawn = "SPAWN_LAVENDER", flag = 58, name = "ENGINE_FLYPOINT_LAVENDER" },
|
||||
{ landmark = "LANDMARK_CELADON_CITY", spawn = "SPAWN_CELADON", flag = 60, name = "ENGINE_FLYPOINT_CELADON" },
|
||||
{ landmark = "LANDMARK_SAFFRON_CITY", spawn = "SPAWN_SAFFRON", flag = 59, name = "ENGINE_FLYPOINT_SAFFRON" },
|
||||
{ landmark = "LANDMARK_FUCHSIA_CITY", spawn = "SPAWN_FUCHSIA", flag = 61, name = "ENGINE_FLYPOINT_FUCHSIA" },
|
||||
{ landmark = "LANDMARK_CINNABAR_ISLAND", spawn = "SPAWN_CINNABAR", flag = 62, name = "ENGINE_FLYPOINT_CINNABAR" },
|
||||
{ landmark = "LANDMARK_INDIGO_PLATEAU", spawn = "SPAWN_INDIGO", flag = 63, name = "ENGINE_FLYPOINT_INDIGO_PLATEAU" },
|
||||
}
|
||||
|
||||
-- spawn -> row, built once, so hasVisitedSpawn below does not walk the whole
|
||||
|
||||
@@ -929,8 +929,8 @@ function World:load()
|
||||
-- `hold` is the same story one argument along: the cart `pause` a held box
|
||||
-- stands through (FindItemInBallScript's `pause 60`). Dropping it made the
|
||||
-- box hand back the instant it finished typing.
|
||||
showText = function(body, onDone, stay, hold)
|
||||
self:showText(body, onDone, stay, hold)
|
||||
showText = function(body, onDone, stay, hold, sfxWait)
|
||||
self:showText(body, onDone, stay, hold, sfxWait)
|
||||
end,
|
||||
facePlayer = function()
|
||||
if self.talkNpc and self.player then
|
||||
@@ -4224,7 +4224,7 @@ function World:tryWildEncounter()
|
||||
-- That is what keeps the Ruins chambers empty until a wall has been solved.
|
||||
local monOpts = nil
|
||||
if roll.species == Unown.SPECIES then
|
||||
local flags = self:engineFlags()
|
||||
local flags = self:unownUnlockFlags()
|
||||
if not Unown.anyUnlocked(flags) then return false end
|
||||
-- LoadEnemyMon's .GenerateDVs loop rerolls until CheckUnownLetter clears
|
||||
-- the form, so a chamber only ever produces letters its own puzzle
|
||||
@@ -4846,6 +4846,19 @@ function World:engineFlagId(name, goldId)
|
||||
return ids[name] or goldId
|
||||
end
|
||||
|
||||
-- Unown.UNLOCK_SETS keys the flags by pokegold's ids; Crystal's are one
|
||||
-- higher (../pokecrystal/constants/engine_flags.asm:57-60 vs ../pokegold:56-59).
|
||||
function World:unownUnlockFlags()
|
||||
local engine = self:engineFlags()
|
||||
local out = {}
|
||||
for _, set in ipairs(Unown.UNLOCK_SETS) do
|
||||
if engine[self:engineFlagId(set.name, set.flag)] then
|
||||
out[set.flag] = true
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- wBikeFlags' three bits are ENGINE_* ids like any other flag, so the map
|
||||
-- callbacks that set them (Route16AlwaysOnBikeCallback,
|
||||
-- Route17AlwaysOnBikeCallback) already land on save.engineFlags.
|
||||
@@ -5338,7 +5351,7 @@ function World:sweetScentEncounter()
|
||||
-- stays empty for SWEET SCENT too.
|
||||
local monOpts = nil
|
||||
if roll.species == Unown.SPECIES then
|
||||
local flags = self:engineFlags()
|
||||
local flags = self:unownUnlockFlags()
|
||||
if not Unown.anyUnlocked(flags) then return false end
|
||||
monOpts = { dvs = Unown.wildDVs(flags, Mon.randomDVs) }
|
||||
end
|
||||
@@ -7280,7 +7293,7 @@ end
|
||||
-- stack the overworld and the VM under it do not tick at all -- so the wait has
|
||||
-- to be counted by the box itself. Frames, already doubled by Vm:pauseFrames
|
||||
-- the way Script_pause's `ld c, 2 / call DelayFrames` doubles the operand.
|
||||
function World:showText(body, onDone, stay, hold)
|
||||
function World:showText(body, onDone, stay, hold, sfxWait)
|
||||
local game = self.game
|
||||
-- The box a PREVIOUS `stay` left standing (TextBox's contract is "whoever
|
||||
-- pushed it owns the pop", src/render/TextBox.lua:40). `yesorno` consumes it
|
||||
@@ -7330,7 +7343,7 @@ function World:showText(body, onDone, stay, hold)
|
||||
game.stack:push(TextBox.new(game, body, function()
|
||||
self.textbox = nil
|
||||
if onDone then onDone() end
|
||||
end))
|
||||
end, sfxWait and { sfxWait = true } or nil))
|
||||
end
|
||||
|
||||
function World:pooledNpc(mapId, obj)
|
||||
|
||||
Reference in New Issue
Block a user