-- Gen 3 Pokémon Release Sequence (emotional upward shrink & float animation). -- "Release this POKéMON?" -> [YES/NO] -> float/shrink animation -> " was released." -> "Bye-bye, !". local Window = require("src.ui.game3.window") local FrlgFont = require("src.ui.game3.frlg_font") local Pokemon = require("src.core.game3.pokemon") local Storage = require("src.core.game3.storage") local RomText = require("src.core.game3.rom_text") local ReleaseSeq = {} ReleaseSeq.active = false ReleaseSeq.state = "idle" -- idle | confirm | anim | bye | done ReleaseSeq.mon = nil ReleaseSeq.boxId = 1 ReleaseSeq.slotIdx = 1 ReleaseSeq.session = nil ReleaseSeq.onComplete = nil ReleaseSeq.yesNoCursor = 2 -- default to NO ReleaseSeq.animT = 0 ReleaseSeq.startX = 0 ReleaseSeq.startY = 0 local SE = require("src.core.game3.se_ids") local function se(id) pcall(function() require("src.core.game3.audio").playSe(id) end) end function ReleaseSeq.start(opts) opts = opts or {} do local StayMessage = package.loaded["src.ui.game3.message"] if StayMessage and StayMessage.closeStay then StayMessage.closeStay() end end ReleaseSeq.active = true ReleaseSeq.state = "confirm" ReleaseSeq.session = opts.session ReleaseSeq.mon = opts.mon ReleaseSeq.boxId = opts.boxId or 1 ReleaseSeq.slotIdx = opts.slotIdx or 1 ReleaseSeq.onComplete = opts.onComplete ReleaseSeq.yesNoCursor = 2 -- Default to NO ReleaseSeq.animT = 0 ReleaseSeq.startX = opts.startX or 80 ReleaseSeq.startY = opts.startY or 60 se(SE.SE_SELECT) end function ReleaseSeq.isActive() return ReleaseSeq.active end local function anyKey(input) return input:wasPressed("a") or input:wasPressed("b") or input:wasPressed("up") or input:wasPressed("down") or input:wasPressed("left") or input:wasPressed("right") end function ReleaseSeq.handleInput(input) if not ReleaseSeq.active then return end if ReleaseSeq.state == "confirm" then if input:wasPressed("up") or input:wasPressed("down") then ReleaseSeq.yesNoCursor = (ReleaseSeq.yesNoCursor == 1) and 2 or 1 se(SE.SE_SELECT) elseif input:wasPressed("a") then se(SE.SE_SELECT) -- pokefirered/src/menu.c:376 if ReleaseSeq.yesNoCursor == 1 then -- Confirmed YES ReleaseSeq.state = "anim" ReleaseSeq.animT = 0 else -- Chose NO ReleaseSeq.close(false) end elseif input:wasPressed("b") then ReleaseSeq.close(false) end return end if ReleaseSeq.state == "released" then -- pokefirered/src/pokemon_storage_system_tasks.c:1308 if anyKey(input) then ReleaseSeq.state = "bye" end return end if ReleaseSeq.state == "bye" then -- pokefirered/src/pokemon_storage_system_tasks.c:1315 if anyKey(input) then ReleaseSeq.close(true) end return end end function ReleaseSeq.update(dt) if not ReleaseSeq.active then return end if ReleaseSeq.state == "anim" then ReleaseSeq.animT = ReleaseSeq.animT + (dt or (1 / 60)) if ReleaseSeq.animT >= 0.8 then -- Finalize data deletion in storage if ReleaseSeq.session and ReleaseSeq.boxId and ReleaseSeq.slotIdx then Storage.releaseMon(ReleaseSeq.session, ReleaseSeq.boxId, ReleaseSeq.slotIdx) end -- pokefirered/src/pokemon_storage_system_tasks.c:1304 ReleaseSeq.state = "released" se(SE.SE_SELECT) end end end function ReleaseSeq.close(released) ReleaseSeq.active = false ReleaseSeq.state = "idle" local cb = ReleaseSeq.onComplete ReleaseSeq.onComplete = nil if cb then cb(released) end end function ReleaseSeq.draw() if not ReleaseSeq.active then return end -- pokefirered/src/pokemon_storage_system_tasks.c:2570 local dynamic = { [0] = Pokemon.displayName(ReleaseSeq.mon) } if ReleaseSeq.state == "confirm" then -- Bottom dialogue box Window.dialogueFrame() Window.printPx(RomText.plain("gText_ReleaseThisPokemon"), 16, 120) -- YES/NO Confirmation Box Window.stdFrame(Window.template(21, 8, 6, 4)) Window.printPx(RomText.plain("gText_Yes"), 184, 68) Window.printPx(RomText.plain("gText_No"), 184, 84) Window.cursorPx(174, ReleaseSeq.yesNoCursor == 1 and 68 or 84) return end if ReleaseSeq.state == "anim" then -- Draw upward shrinking sprite local progress = math.min(1.0, ReleaseSeq.animT / 0.8) local scale = math.max(0.01, 1.0 - progress * 0.85) local alpha = math.max(0.0, 1.0 - progress) local curX = ReleaseSeq.startX local curY = ReleaseSeq.startY - (progress * 40) -- float upward 40px local icon = ReleaseSeq.mon and Pokemon.monIcon(ReleaseSeq.mon) if icon and icon.image then local q = icon.quads and icon.quads[0] love.graphics.setColor(1, 1, 1, alpha) if q then love.graphics.draw(icon.image, q, curX, curY, 0, scale, scale, 16, 16) else love.graphics.draw(icon.image, curX, curY, 0, scale, scale, 16, 16) end love.graphics.setColor(1, 1, 1, 1) end return end if ReleaseSeq.state == "released" then Window.dialogueFrame() Window.printPx(RomText.plain("gText_PkmnWasReleased", { dynamic = dynamic }), 16, 120) return end if ReleaseSeq.state == "bye" then Window.dialogueFrame() Window.printPx(RomText.plain("gText_ByeByePkmn", { dynamic = dynamic }), 16, 120) return end end return ReleaseSeq