mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-28 18:06:09 +02:00
fix(yellow): address version:yellow issues and title pupil bake
Seed Mt Moon Super Nerd dialogue (#1743), play item-use heal jingles (#1635), use white fades for fly/teleport warps (#1644), add a Yellow-only Advanced palette overlay (#1639), parse Yellow Super Rod data including Safari Dragonair (#1074), and apply title rOBP0 when baking Pikachu eye OAM so pupils stay black with white glints.
This commit is contained in:
@@ -170,6 +170,10 @@ function Data:seedDefaults(version)
|
||||
-- writes no header for him -- seed one so he engages on sight and has
|
||||
-- his defeat / re-talk lines (same idea as the Cinnabar seed above).
|
||||
Data.seedFightingDojoKarateMaster(self)
|
||||
-- #1743: Mt. Moon B2F Super Nerd is text_asm (no def_trainers), so Yellow's
|
||||
-- extractor never writes his header -- seed one so engageTrainer finds
|
||||
-- battle/won/after text instead of the "I like shorts!" fallback.
|
||||
Data.seedMtMoonB2FSuperNerd(self)
|
||||
-- #189: 1F cabin door order vs rooms map (survey zoom)
|
||||
require("src.world.SsAnneLayout").apply(self.maps)
|
||||
end
|
||||
@@ -201,6 +205,25 @@ function Data:seedFightingDojoKarateMaster()
|
||||
}
|
||||
end
|
||||
|
||||
-- Mt. Moon B2F Super Nerd (object index 1) is text_asm with no def_trainers
|
||||
-- row, so Yellow never gets a trainerHeaders.MtMoonB2F[1] entry (Red/Blue
|
||||
-- pin one in make_rom_manifest.py). Without it, engageTrainer falls through
|
||||
-- to the hard-coded "I like shorts!" fallback (#1743). trainerDefeated still
|
||||
-- tracks him via defeatedTrainers[npc.id]; the fabricated event name matches
|
||||
-- the shipped Red/Blue manifest pin for consistency with fossil drivers.
|
||||
function Data:seedMtMoonB2FSuperNerd()
|
||||
local headers = self.trainer_headers
|
||||
if not headers then return end
|
||||
headers.MtMoonB2F = headers.MtMoonB2F or {}
|
||||
if headers.MtMoonB2F[1] then return end
|
||||
headers.MtMoonB2F[1] = {
|
||||
battle = "_MtMoonB2FSuperNerdTheyreBothMineText",
|
||||
won = "_MtMoonB2FSuperNerdOkIllShareText",
|
||||
after = "_MtMoonB2FSuperNerdTheresAPokemonLabText",
|
||||
event = "EVENT_BEAT_MT_MOON_3_SUPER_NERD",
|
||||
}
|
||||
end
|
||||
|
||||
function Data:seedCinnabarGymTrainerHeaders()
|
||||
local headers = self.trainer_headers
|
||||
if not headers or headers.CinnabarGym then return end
|
||||
|
||||
@@ -7,6 +7,28 @@ local SHADES = {
|
||||
{ 0, 0, 0, 1 },
|
||||
}
|
||||
|
||||
ImageWriter.SHADES = SHADES
|
||||
|
||||
-- Title screen rOBP0 = %11100000 ($E0): OBJ shades 1 and 2 draw as white,
|
||||
-- shade 3 as black (pokeyellow engine/movie/title.asm after PlacePikachu).
|
||||
-- Eye OAM is baked into the MEWMON-colored BG PNG; without this remap the
|
||||
-- shade-1 glints become body yellow under the title palette.
|
||||
function ImageWriter.applyTitleObp0(image)
|
||||
local mid, dark = SHADES[2][1], SHADES[3][1]
|
||||
local w, h = image:getWidth(), image:getHeight()
|
||||
for y = 0, h - 1 do
|
||||
for x = 0, w - 1 do
|
||||
local r, g, b, a = image:getPixel(x, y)
|
||||
if a ~= 0 then
|
||||
if math.abs(r - mid) < 0.02 or math.abs(r - dark) < 0.02 then
|
||||
image:setPixel(x, y, 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return image
|
||||
end
|
||||
|
||||
local function assertDimensions(raw, width, height, bits)
|
||||
assert(width % 8 == 0 and height % 8 == 0,
|
||||
("%dbpp dimensions must be tile-aligned: %dx%d")
|
||||
|
||||
@@ -1535,6 +1535,14 @@ function RomExtractor:extractYellowTitleArt()
|
||||
local bg = sheetTiles("TitlePikachuBGGraphics", 64)
|
||||
local ob = sheetTiles("TitlePikachuOBGraphics", 12)
|
||||
local obClear = sheetTiles("TitlePikachuOBGraphics", 12, true)
|
||||
-- Title rOBP0=$E0: remap eye OAM shades 1/2 → white before baking into the
|
||||
-- MEWMON BG composition (otherwise glints read as body yellow).
|
||||
local eyeOb = {}
|
||||
for i, tile in ipairs(obClear) do
|
||||
local copy = ImageWriter.blank(8, 8, 0, 0, 0, 0)
|
||||
ImageWriter.blit(copy, tile, 0, 0)
|
||||
eyeOb[i] = ImageWriter.applyTitleObp0(copy)
|
||||
end
|
||||
local function tileFor(id)
|
||||
if id < 0x80 then return logo[id + 1] end
|
||||
if id < 0xF0 then return bg[id - 0x80 + 1] end
|
||||
@@ -1623,13 +1631,13 @@ function RomExtractor:extractYellowTitleArt()
|
||||
local overlay = ImageWriter.blank(48, 16, 1, 1, 1, 0)
|
||||
ImageWriter.blit(overlay, pikachu, 0, 0, 24, 16, 48, 16)
|
||||
for _, e in ipairs(EYE_LAYOUT) do
|
||||
blitSprite(overlay, obClear[base + e[1]], e[2] - 24, e[3] - 16, e[4])
|
||||
blitSprite(overlay, eyeOb[base + e[1]], e[2] - 24, e[3] - 16, e[4])
|
||||
end
|
||||
overlays[suffix] = overlay
|
||||
end
|
||||
-- open eyes bake into pikachu.png AFTER the blank-face crops
|
||||
for _, e in ipairs(EYE_LAYOUT) do
|
||||
blitSprite(pikachu, obClear[e[1]], e[2], e[3], e[4])
|
||||
blitSprite(pikachu, eyeOb[e[1]], e[2], e[3], e[4])
|
||||
end
|
||||
self:save(pikachu, "title/pikachu.png")
|
||||
for suffix, overlay in pairs(overlays) do
|
||||
|
||||
@@ -184,6 +184,14 @@ local function adjacentSleepingSnorlax(save, ow)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function itemUseLine(data, save, name)
|
||||
return romText(data, "_ItemUseText001", "%s used\n%s!", save.player.name, name)
|
||||
end
|
||||
|
||||
-- PrintItemUseTextAndRemoveItem (item_effects.asm): used-line + SFX_HEAL_AILMENT.
|
||||
-- BagMenu plays Heal_Ailment via TextBox.soundOpts when extra.useJingle is set.
|
||||
local USE_JINGLE = { useJingle = true }
|
||||
|
||||
-- Use an item on a target party mon (target may be nil for targetless
|
||||
-- items). data = generated data tables; battle = BattleState when used
|
||||
-- mid-battle; ow = the overworld (OverworldState), needed only to check
|
||||
@@ -280,7 +288,7 @@ function ItemEffects.use(data, save, itemId, target, battle, moveIndex, ow)
|
||||
"All sleeping\nPOKéMON woke up!") }
|
||||
end
|
||||
|
||||
-- battle-only items
|
||||
-- battle-only items (PrintItemUseTextAndRemoveItem + Heal_Ailment, #1635)
|
||||
if X_ITEMS[itemId] or itemId == "DIRE_HIT" or itemId == "GUARD_SPEC"
|
||||
or itemId == "POKE_DOLL" then
|
||||
if not battle then
|
||||
@@ -293,21 +301,23 @@ function ItemEffects.use(data, save, itemId, target, battle, moveIndex, ow)
|
||||
require("src.world.PikachuFollower")
|
||||
.modifyHappiness(save, "USEDXITEM", b and b.mon)
|
||||
end
|
||||
local used = itemUseLine(data, save, name)
|
||||
if itemId == "X_ACCURACY" then
|
||||
-- ItemUseXAccuracy sets USING_X_ACCURACY: moves never miss
|
||||
-- (not an accuracy stage)
|
||||
-- (not an accuracy stage); vanilla prints only the used line
|
||||
b.xAccuracy = true
|
||||
return "consumed", { Strings("%s's\nhits will never\nmiss!", b.name) }
|
||||
return "consumed", { used }, USE_JINGLE
|
||||
end
|
||||
if X_ITEMS[itemId] then
|
||||
local stat = X_ITEMS[itemId]
|
||||
local cur = b.stages[stat] or 0
|
||||
-- ItemUseXStat removes the item BEFORE running the stat-up
|
||||
-- effect, so at +6 it is still consumed and StatModifierUpEffect
|
||||
-- just prints "Nothing happened!"
|
||||
-- ItemUseXStat: PrintItemUseTextAndRemoveItem, then StatModifierUpEffect
|
||||
if cur >= 6 then
|
||||
return "consumed", { romText(data, "_NothingHappenedText",
|
||||
"Nothing happened!") }
|
||||
return "consumed", { used }, {
|
||||
useJingle = true,
|
||||
afterMessages = { romText(data, "_NothingHappenedText",
|
||||
"Nothing happened!") },
|
||||
}
|
||||
end
|
||||
b.stages[stat] = cur + 1
|
||||
b.hazeStatReset = nil
|
||||
@@ -315,26 +325,29 @@ function ItemEffects.use(data, save, itemId, target, battle, moveIndex, ow)
|
||||
and battle.kind ~= "link" then
|
||||
require("src.battle.Damage").reapplyBadgeBoosts(b, stat)
|
||||
end
|
||||
return "consumed", { Strings("%s's\n%s rose!", b.name, Strings(STAT_LABEL[stat])) }
|
||||
return "consumed", { used }, {
|
||||
useJingle = true,
|
||||
afterMessages = { Strings("%s's\n%s rose!", b.name,
|
||||
Strings(STAT_LABEL[stat])) },
|
||||
}
|
||||
end
|
||||
-- ItemUseDireHit/ItemUseGuardSpec always set the bit and consume
|
||||
-- the item, even when it is already active
|
||||
-- the item, even when it is already active; vanilla prints only used
|
||||
if itemId == "DIRE_HIT" then
|
||||
b.focusEnergy = true
|
||||
return "consumed", { romText(data, "_GettingPumpedText",
|
||||
"%s's\ngetting pumped!", b.name) }
|
||||
return "consumed", { used }, USE_JINGLE
|
||||
end
|
||||
if itemId == "GUARD_SPEC" then
|
||||
b.mist = true
|
||||
return "consumed", { Strings("%s's\nprotected against\nstat changes!", b.name) }
|
||||
return "consumed", { used }, USE_JINGLE
|
||||
end
|
||||
if itemId == "POKE_DOLL" then
|
||||
if battle.kind ~= "wild" then
|
||||
-- ItemUsePokeDoll jumps to ItemUseNotTime in trainer battles
|
||||
return "failed", { notTime(data, save) }
|
||||
end
|
||||
return "consumed_escape", { romText(data, "_WildRanText",
|
||||
"The wild POKéMON\nran away!", battle.enemy and battle.enemy.name) }
|
||||
-- PrintItemUseTextAndRemoveItem then escape
|
||||
return "consumed_escape", { used }, USE_JINGLE
|
||||
end
|
||||
end
|
||||
|
||||
@@ -613,7 +626,7 @@ function ItemEffects.use(data, save, itemId, target, battle, moveIndex, ow)
|
||||
if REPELS[itemId] then
|
||||
local steps = itemId == "REPEL" and 100 or itemId == "SUPER_REPEL" and 200 or 250
|
||||
save.repelSteps = steps
|
||||
return "consumed", { Strings("%s used\n%s!", save.player.name, name) }
|
||||
return "consumed", { itemUseLine(data, save, name) }, USE_JINGLE
|
||||
end
|
||||
|
||||
return "failed", { notTime(data, save) }
|
||||
|
||||
+49
-13
@@ -20,6 +20,8 @@ local PaletteFX = {}
|
||||
local shader -- false = unavailable (headless / no shader support)
|
||||
local gbcPack -- false = missing; nil = not loaded yet
|
||||
local yellowPack -- false = missing; nil = not loaded yet
|
||||
local gbcYellowPack -- Yellow Advanced deltas; false = missing; nil = not loaded yet
|
||||
|
||||
|
||||
-- Cycle order matches OptionsMenu / hotkey 2. The three real colorizations
|
||||
-- come first (OG RED/BLUE/YELLOW = GBC hardware, SGB = per-map Super Game Boy,
|
||||
@@ -300,6 +302,38 @@ function PaletteFX.yellowPack()
|
||||
return yellowPack or nil
|
||||
end
|
||||
|
||||
-- Yellow-only Advanced deltas (BEACH_HOUSE, sprite remap, YELLOWMON). Never
|
||||
-- consulted on Red/Blue (#1639).
|
||||
function PaletteFX.gbcYellowPack()
|
||||
if gbcYellowPack == nil then
|
||||
local ok, pack = pcall(require, "data.palettes_gbc_yellow")
|
||||
gbcYellowPack = ok and pack or false
|
||||
end
|
||||
return gbcYellowPack or nil
|
||||
end
|
||||
|
||||
-- Active world bake tables for Advanced. Yellow merges gbc_yellow deltas
|
||||
-- via __index so shared Red tilesets stay identical byte-for-byte.
|
||||
function PaletteFX.worldPack()
|
||||
local pack = PaletteFX.gbcPack()
|
||||
local w = pack and pack.world
|
||||
if not w then return nil end
|
||||
if not GameVersion.isYellow() then return w end
|
||||
local y = PaletteFX.gbcYellowPack()
|
||||
local yw = y and y.world
|
||||
if not yw then return w end
|
||||
return {
|
||||
tileGroups = setmetatable(yw.tileGroups or {}, { __index = w.tileGroups }),
|
||||
groupColors = setmetatable(yw.groupColors or {}, { __index = w.groupColors }),
|
||||
roofGroup = w.roofGroup,
|
||||
roofByMapIndex = w.roofByMapIndex,
|
||||
spriteAssignment = yw.spriteAssignment or w.spriteAssignment,
|
||||
spritePalettes = yw.spritePalettes
|
||||
and setmetatable(yw.spritePalettes, { __index = w.spritePalettes })
|
||||
or w.spritePalettes,
|
||||
}
|
||||
end
|
||||
|
||||
function PaletteFX.usesGbcPack(mode)
|
||||
mode = mode or PaletteFX.mode
|
||||
return mode == "redpp"
|
||||
@@ -453,7 +487,10 @@ function PaletteFX.pal(data, name)
|
||||
if fromRom then return fromRom end
|
||||
end
|
||||
if GameVersion.isYellow() then
|
||||
if PaletteFX.usesYellowCgb() then
|
||||
-- OG YELLOW and Advanced both use CGBBase for named pals: SuperPalettes
|
||||
-- wash out yellows (title MEWMON/LOGO, YELLOWMON) to pale cream. World
|
||||
-- tile bake still comes from the Advanced GBC pack via worldPack (#1639).
|
||||
if PaletteFX.usesYellowCgb() or PaletteFX.usesGbcPack() then
|
||||
local fromCgb = yellowCgbNamedPal(data, name)
|
||||
if fromCgb then return fromCgb end
|
||||
end
|
||||
@@ -511,7 +548,8 @@ function PaletteFX.monPal(data, species, transformed)
|
||||
if pal then return pal end
|
||||
end
|
||||
local name = p.pokemon[species] or "MEWMON"
|
||||
if PaletteFX.usesYellowCgb() then
|
||||
if PaletteFX.usesYellowCgb()
|
||||
or (GameVersion.isYellow() and PaletteFX.usesGbcPack()) then
|
||||
local yc = PaletteFX.pal(data, name)
|
||||
if yc then return yc end
|
||||
end
|
||||
@@ -618,16 +656,14 @@ local ROUTE_6_SAFFRON = { mapId = "ROUTE_6", useMapId = "SAFFRON_CITY", cellYBel
|
||||
-- (false for a mod tileset with no pokered-gbc counterpart, or when the
|
||||
-- pack failed to load at all)
|
||||
function PaletteFX.hasWorldTileset(tileset)
|
||||
local pack = PaletteFX.gbcPack()
|
||||
local w = pack and pack.world
|
||||
local w = PaletteFX.worldPack()
|
||||
return (w and w.tileGroups[tileset]) ~= nil
|
||||
end
|
||||
|
||||
-- the palette-group (0-7) a tile GRAPHIC id resolves to in this tileset,
|
||||
-- with the current map's tile-id exceptions (if any) applied first
|
||||
function PaletteFX.worldGroupAt(tileset, mapId, tileId)
|
||||
local pack = PaletteFX.gbcPack()
|
||||
local w = pack and pack.world
|
||||
local w = PaletteFX.worldPack()
|
||||
local groups = w and w.tileGroups[tileset]
|
||||
if not groups then return nil end
|
||||
local exc = TILE_GROUP_EXCEPTIONS[mapId]
|
||||
@@ -642,8 +678,7 @@ end
|
||||
-- Saffron's roof colors while the player stands in its top 2 cell rows,
|
||||
-- like pokered's wYCoord check -- data is Game.data, for the map lookup)
|
||||
function PaletteFX.worldGroupColors(data, tileset, mapId, playerCellY)
|
||||
local pack = PaletteFX.gbcPack()
|
||||
local w = pack and pack.world
|
||||
local w = PaletteFX.worldPack()
|
||||
local base = w and w.groupColors[tileset]
|
||||
if not base then return nil end
|
||||
if not w.roofGroup[tileset] then return darkGroups(base) end
|
||||
@@ -678,17 +713,18 @@ end
|
||||
-- here): a stable hash instead, so the same NPC instance always shows the
|
||||
-- same one of the 4 SPR_PAL_* colors.
|
||||
function PaletteFX.spriteObp(spriteDef, seed)
|
||||
local pack = PaletteFX.gbcPack()
|
||||
local w = pack and pack.world
|
||||
local w = PaletteFX.worldPack()
|
||||
local src = spriteDef and (spriteDef.paletteSource or spriteDef.source)
|
||||
if not (w and src) then return nil end
|
||||
local idx = tonumber(src:match("%[(%d+)%]"))
|
||||
-- RedBikeSprite and SurfingPikachuSprite load outside
|
||||
-- SpriteSheetPointerTable, so their source has no bracketed index;
|
||||
-- they wear the player's OBP palette (spriteAssignment[0]).
|
||||
if not idx and (src:find("RedBikeSprite", 1, true)
|
||||
or src:find("SurfingPikachuSprite", 1, true)) then
|
||||
-- they wear the player's OBP palette (spriteAssignment[0]) on Red/Blue.
|
||||
-- On Yellow, Surfing Pikachu uses the Pikachu yellow OBJ group (#1639).
|
||||
if not idx and src:find("RedBikeSprite", 1, true) then
|
||||
idx = 0
|
||||
elseif not idx and src:find("SurfingPikachuSprite", 1, true) then
|
||||
idx = GameVersion.isYellow() and 60 or 0
|
||||
end
|
||||
local group = idx and w.spriteAssignment[idx]
|
||||
if group == nil then return nil end
|
||||
|
||||
@@ -338,6 +338,7 @@ function Renderer:beginFrame(transparent)
|
||||
-- warp-fade overlay from Transition (issue #121); cleared each frame so
|
||||
-- a popped transition cannot leave a sticky black veil
|
||||
self.worldFadeAlpha = nil
|
||||
self.worldFadeColor = nil
|
||||
-- battle-transition wipe, drawn over the whole surface (BattleTransition)
|
||||
self.battleWipe = nil
|
||||
-- whole-surface veil in screen space (battle-transition flash, the
|
||||
@@ -1045,7 +1046,8 @@ function Renderer:endFrame(zones, worldZones)
|
||||
-- the screen-space overlays the flat path draws over its composite
|
||||
local fade = self.worldFadeAlpha
|
||||
if fade and fade > 0 then
|
||||
love.graphics.setColor(0, 0, 0, fade)
|
||||
local c = self.worldFadeColor or { 0, 0, 0 }
|
||||
love.graphics.setColor(c[1], c[2], c[3], fade)
|
||||
love.graphics.rectangle("fill", vux, vuy, vuw, vuh)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
@@ -1132,7 +1134,8 @@ function Renderer:endFrame(zones, worldZones)
|
||||
-- composite normally if one is ever stacked that way.
|
||||
local fade = self.worldFadeAlpha
|
||||
if fade and fade > 0 then
|
||||
love.graphics.setColor(0, 0, 0, fade)
|
||||
local c = self.worldFadeColor or { 0, 0, 0 }
|
||||
love.graphics.setColor(c[1], c[2], c[3], fade)
|
||||
love.graphics.rectangle("fill", vux, vuy, vuw, vuh)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
@@ -65,16 +65,24 @@ end
|
||||
-- (ViridianGym.asm .afterBeat, RocketHideoutB4F BeatGiovanniScript) call
|
||||
-- GBFadeOutToBlack -> GBFadeInFromBlack instead, so the default keeps the
|
||||
-- symmetric 32-frame fade back in (home/fade.asm:21, b = 4).
|
||||
function Transition.new(game, onMidpoint, onDone, warp)
|
||||
--
|
||||
-- opts.color = {r,g,b} in 0..1 (default black). opts.frames / opts.framesIn
|
||||
-- override duration. Fly/Teleport/Dig/Escape Rope use white
|
||||
-- GBFadeOutToWhite / GBFadeInFromWhite (#1644).
|
||||
function Transition.new(game, onMidpoint, onDone, warp, opts)
|
||||
opts = opts or {}
|
||||
local self = setmetatable({}, Transition)
|
||||
self.game = game
|
||||
self.onMidpoint = onMidpoint
|
||||
self.onDone = onDone
|
||||
self.t = 0
|
||||
self.phase = "out"
|
||||
self.color = opts.color or { 0, 0, 0 }
|
||||
local style = styleOf(game, "warp_fade")
|
||||
self.frames = style.frames or FRAMES
|
||||
if warp then
|
||||
self.frames = opts.frames or style.frames or FRAMES
|
||||
if opts.framesIn ~= nil then
|
||||
self.framesIn = opts.framesIn
|
||||
elseif warp then
|
||||
-- a style may still ask for a fade in (mods, and the record is
|
||||
-- data-driven); the built-in warp is 0, matching hardware
|
||||
self.framesIn = style.framesIn or FRAMES_IN
|
||||
@@ -125,6 +133,7 @@ end
|
||||
|
||||
function Transition:draw()
|
||||
local alpha = self:alpha()
|
||||
local c = self.color or { 0, 0, 0 }
|
||||
-- Survey zoom draws the overworld into a window-filling world canvas
|
||||
-- while the UI pass stays the classic 160x144 letterbox. A rect on the
|
||||
-- UI canvas only darkens that center box (issue #121); when the world
|
||||
@@ -133,9 +142,10 @@ function Transition:draw()
|
||||
local r = self.game and self.game.renderer
|
||||
if r and r.worldActive then
|
||||
r.worldFadeAlpha = alpha
|
||||
r.worldFadeColor = c
|
||||
return
|
||||
end
|
||||
love.graphics.setColor(0, 0, 0, alpha)
|
||||
love.graphics.setColor(c[1], c[2], c[3], alpha)
|
||||
love.graphics.rectangle("fill", 0, 0, 160, 144)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
+19
-4
@@ -54,6 +54,21 @@ local function showMessages(game, msgs, onDone, opts)
|
||||
game.stack:push(TextBox.new(game, table.concat(msgs, "\f"), onDone, opts))
|
||||
end
|
||||
|
||||
-- PrintItemUseTextAndRemoveItem: used-line TextBox carries Heal_Ailment, then
|
||||
-- optional afterMessages (X Stat effect line) before onDone (#1635).
|
||||
local function showUseMessages(game, msgs, onDone, extra)
|
||||
local opts = (extra and extra.useJingle)
|
||||
and TextBox.soundOpts(game, "Heal_Ailment") or nil
|
||||
local after = extra and extra.afterMessages
|
||||
if after and #after > 0 then
|
||||
showMessages(game, msgs, function()
|
||||
showMessages(game, after, onDone)
|
||||
end, opts)
|
||||
else
|
||||
showMessages(game, msgs, onDone, opts)
|
||||
end
|
||||
end
|
||||
|
||||
-- run the use-flow for an item on a chosen target. `picker` is the party
|
||||
-- menu when it was opened with keepOpen (HP medicine only): it is still on
|
||||
-- the stack, so every exit that prints has to close it afterwards. For
|
||||
@@ -115,7 +130,7 @@ local function vanillaUseOn(game, battle, id, target, list, moveIndex, picker)
|
||||
if result == "consumed_escape" then -- Poké Doll
|
||||
consume(game, id, list)
|
||||
list:close()
|
||||
showMessages(game, payload, function()
|
||||
showUseMessages(game, payload, function()
|
||||
-- ItemUsePokeDoll sets wEscapedFromBattle and never touches
|
||||
-- wBattleResult, so a script that reads the result afterwards sees
|
||||
-- 0 -- "defeated". The ghost MAROWAK's script keys on exactly that
|
||||
@@ -125,7 +140,7 @@ local function vanillaUseOn(game, battle, id, target, list, moveIndex, picker)
|
||||
battle.result = "run"
|
||||
battle.afterQueue = "finish"
|
||||
battle.phase = "messages"
|
||||
end)
|
||||
end, extra)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -403,9 +418,9 @@ local function vanillaUseOn(game, battle, id, target, list, moveIndex, picker)
|
||||
end
|
||||
if battle then
|
||||
list:close()
|
||||
showMessages(game, payload, function() battle:itemUsed({}) end)
|
||||
showUseMessages(game, payload, function() battle:itemUsed({}) end, extra)
|
||||
else
|
||||
showMessages(game, payload, closePicker)
|
||||
showUseMessages(game, payload, closePicker, extra)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
@@ -4818,6 +4818,15 @@ function OverworldState:startWarpTo(mapId, x, y, facing, onDone, opts)
|
||||
require("src.core.Sound").play(Game.data,
|
||||
outdoor and "Go_Outside" or "Go_Inside")
|
||||
end
|
||||
-- Fly/Teleport/Dig/Escape Rope: GBFadeOutToWhite / GBFadeInFromWhite
|
||||
-- (player_animations.asm). Door warps stay black with no fade-in (#1644).
|
||||
local Timing = require("src.core.Timing")
|
||||
local specialWarp = arriveWarp == "fly" or arriveWarp == "teleport"
|
||||
local fadeOpts = specialWarp and {
|
||||
color = { 1, 1, 1 },
|
||||
frames = Timing.FADE_OUT_TO_WHITE,
|
||||
framesIn = Timing.FADE_IN_FROM_WHITE,
|
||||
} or nil
|
||||
Game.stack:push(Transition.new(Game, function()
|
||||
self:setMap(mapId, x, y, facing or "down", opts)
|
||||
-- the departure-side hide from flyAnim/teleportOut ends here, on the new
|
||||
@@ -4884,7 +4893,7 @@ function OverworldState:startWarpTo(mapId, x, y, facing, onDone, opts)
|
||||
end, function()
|
||||
self.transitioning = false
|
||||
if onDone then onDone() end
|
||||
end, true)) -- warp shape: no fade back in (LoadGBPal restores in one write)
|
||||
end, not specialWarp, fadeOpts))
|
||||
end
|
||||
|
||||
-- Re-read a map record after its data changed (WorldAPI:invalidateMap,
|
||||
|
||||
Reference in New Issue
Block a user