mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-10-04 00:20:01 -04:00
406 lines
13 KiB
Lua
406 lines
13 KiB
Lua
-- pokefirered/src/learn_move.c:476 MoveRelearnerStateMachine
|
|
|
|
local Stack = require("src.ui.game3.stack")
|
|
local Window = require("src.ui.game3.window")
|
|
local FrlgFont = require("src.ui.game3.frlg_font")
|
|
local Pokemon = require("src.core.game3.pokemon")
|
|
local MoveLearn = require("src.core.game3.move_learn")
|
|
local LearnMove = require("src.core.game3.battle.learn_move")
|
|
local SummaryChrome = require("src.ui.game3.summary_chrome")
|
|
local SummaryData = require("src.core.game3.summary_data")
|
|
local Strings = require("src.core.Strings")
|
|
local RomText = require("src.core.game3.rom_text")
|
|
|
|
local MoveRelearner = { isMenu = true }
|
|
|
|
MoveRelearner.open = false
|
|
MoveRelearner.state = "list"
|
|
MoveRelearner.cursor = 1
|
|
MoveRelearner.scroll = 0
|
|
MoveRelearner.yesNoCursor = 1
|
|
|
|
-- pokefirered/src/learn_move.c:339
|
|
local VISIBLE = 7
|
|
-- pokefirered/src/new_menu_helpers.c:84 FONT_NORMAL maxLetterHeight
|
|
local ROW_H = 14
|
|
local CACHE_SUB = "move_relearner"
|
|
|
|
-- pokefirered/src/learn_move.c:845 LoadMoveInfoUI
|
|
local LABEL_OPTS = { small = true, colors = FrlgFont.COLOR.DARK_GRAY }
|
|
local VALUE_OPTS = { colors = FrlgFont.COLOR.NORMAL }
|
|
local DESC_OPTS = { maxWidth = 116, linePitch = 14, colors = FrlgFont.COLOR.NORMAL }
|
|
local ROW_OPTS = { maxWidth = 72, colors = FrlgFont.COLOR.NORMAL }
|
|
local PROMPT_OPTS = { maxWidth = 204, linePitch = 15, colors = FrlgFont.COLOR.NORMAL }
|
|
-- pokefirered/src/learn_move.c:254 sWindowTemplates
|
|
local WIN_LIST = Window.template(19, 1, 10, 12)
|
|
local WIN_PROMPT = Window.template(2, 15, 26, 4)
|
|
-- pokefirered/src/learn_move.c:329 sMoveRelearnerYesNoMenuTemplate
|
|
local WIN_YESNO = Window.template(21, 8, 6, 4)
|
|
local SE = require("src.core.game3.se_ids")
|
|
|
|
local function se(id)
|
|
pcall(function()
|
|
local Audio = require("src.core.game3.audio")
|
|
if Audio and Audio.playSe then Audio.playSe(id) end
|
|
end)
|
|
end
|
|
|
|
local function read_bytes(rel)
|
|
local okD, Dataset = pcall(require, "src.core.game3.dataset")
|
|
if okD and Dataset and Dataset.cache then
|
|
local ok, d = pcall(function() return Dataset.cache():read(rel) end)
|
|
if ok and type(d) == "string" and #d > 0 then return d end
|
|
end
|
|
local okC, CacheFs = pcall(require, "src.import.CacheFs")
|
|
if okC and CacheFs and CacheFs.readActive then
|
|
local ok, d = pcall(CacheFs.readActive, rel)
|
|
if ok and type(d) == "string" and #d > 0 then return d end
|
|
end
|
|
if love and love.filesystem and love.filesystem.read then
|
|
local ok, d = pcall(love.filesystem.read, rel)
|
|
if ok and type(d) == "string" and #d > 0 then return d end
|
|
end
|
|
local f = io.open(rel, "rb")
|
|
if f then
|
|
local d = f:read("*a")
|
|
f:close()
|
|
if d and #d > 0 then return d end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function chrome_root()
|
|
local okE, Extract = pcall(require, "src.import.gba.extract_island1")
|
|
local root = (okE and Extract and Extract.CACHE_ROOT) or "data/generated/gba"
|
|
return root .. "/" .. CACHE_SUB
|
|
end
|
|
|
|
-- pokefirered/src/learn_move.c:403 MoveRelearnerLoadBgGfx
|
|
function MoveRelearner.chrome()
|
|
if MoveRelearner._chromeTried then return MoveRelearner._bg end
|
|
MoveRelearner._chromeTried = true
|
|
if not (love and love.image and love.graphics) then return nil end
|
|
local rgba = read_bytes(chrome_root() .. "/bg.rgba")
|
|
if not rgba or #rgba < 240 * 160 * 4 then return nil end
|
|
local okI, data = pcall(love.image.newImageData, 240, 160)
|
|
if not (okI and data) then return nil end
|
|
local okW = pcall(function()
|
|
for y = 0, 159 do
|
|
for x = 0, 239 do
|
|
local o = (y * 240 + x) * 4
|
|
data:setPixel(x, y, rgba:byte(o + 1) / 255, rgba:byte(o + 2) / 255,
|
|
rgba:byte(o + 3) / 255, rgba:byte(o + 4) / 255)
|
|
end
|
|
end
|
|
end)
|
|
if not okW then return nil end
|
|
local okG, img = pcall(love.graphics.newImage, data)
|
|
if not okG then return nil end
|
|
MoveRelearner._bg = img
|
|
return img
|
|
end
|
|
|
|
function MoveRelearner.isOpen()
|
|
return MoveRelearner.open
|
|
end
|
|
|
|
function MoveRelearner.moves()
|
|
return MoveRelearner._moves or {}
|
|
end
|
|
|
|
local function total_rows()
|
|
return #MoveRelearner.moves() + 1
|
|
end
|
|
|
|
local function clamp_cursor()
|
|
local total = total_rows()
|
|
if MoveRelearner.cursor > total then MoveRelearner.cursor = total end
|
|
if MoveRelearner.cursor < 1 then MoveRelearner.cursor = 1 end
|
|
if MoveRelearner.cursor <= MoveRelearner.scroll then
|
|
MoveRelearner.scroll = MoveRelearner.cursor - 1
|
|
end
|
|
if MoveRelearner.cursor > MoveRelearner.scroll + VISIBLE then
|
|
MoveRelearner.scroll = MoveRelearner.cursor - VISIBLE
|
|
end
|
|
if MoveRelearner.scroll < 0 then MoveRelearner.scroll = 0 end
|
|
end
|
|
|
|
local function mon_name()
|
|
return Pokemon.displayMonName(MoveRelearner._mon)
|
|
end
|
|
|
|
-- pokefirered/src/learn_move.c:690
|
|
local function to_list()
|
|
MoveRelearner.state = "list"
|
|
MoveRelearner.prompt = RomText.plain("gText_TeachWhichMoveToMon", { stringVars = { mon_name() } })
|
|
end
|
|
|
|
local function push_message(text, cb)
|
|
MoveRelearner.state = "message"
|
|
MoveRelearner.prompt = text
|
|
MoveRelearner._messageCb = cb
|
|
end
|
|
|
|
local function ask_yes_no(text, cb)
|
|
MoveRelearner.state = "yesno"
|
|
MoveRelearner.prompt = text
|
|
MoveRelearner.yesNoCursor = 1
|
|
MoveRelearner._yesNoCb = cb
|
|
end
|
|
|
|
local function party_slot()
|
|
local party = MoveRelearner._session and MoveRelearner._session.party
|
|
if type(party) == "table" then
|
|
for i = 1, #party do
|
|
if party[i] == MoveRelearner._mon then return party, i end
|
|
end
|
|
end
|
|
return { MoveRelearner._mon }, 1
|
|
end
|
|
|
|
-- pokefirered/src/learn_move.c:603 ShowSelectMovePokemonSummaryScreen
|
|
local function open_forget_screen(_labels, cb)
|
|
local okS, SummaryMenu = pcall(require, "src.ui.game3.summary_menu")
|
|
if not (okS and SummaryMenu and SummaryMenu.openMenu) then
|
|
if cb then cb(nil) end
|
|
return
|
|
end
|
|
local party, slot = party_slot()
|
|
local okOpen = pcall(SummaryMenu.openMenu, party, slot, {
|
|
session = MoveRelearner._session,
|
|
mode = "select_move",
|
|
moveToLearn = MoveRelearner._pendingMoveId,
|
|
onSelectMove = function(slotIdx)
|
|
if cb then cb(slotIdx) end
|
|
end,
|
|
})
|
|
if not okOpen and cb then cb(nil) end
|
|
end
|
|
|
|
function MoveRelearner.finish(learned)
|
|
if not MoveRelearner.open then return end
|
|
MoveRelearner.open = false
|
|
MoveRelearner.state = "list"
|
|
MoveRelearner._messageCb = nil
|
|
MoveRelearner._yesNoCb = nil
|
|
Stack.pop("move_relearner")
|
|
local cb = MoveRelearner._onDone
|
|
MoveRelearner._onDone = nil
|
|
if cb then cb(learned == true) end
|
|
end
|
|
|
|
-- pokefirered/src/learn_move.c:512
|
|
local function start_learn(moveId)
|
|
MoveRelearner._pendingMoveId = moveId
|
|
LearnMove.begin({
|
|
mon = MoveRelearner._mon,
|
|
moveId = moveId,
|
|
relearner = true,
|
|
displayName = mon_name(),
|
|
pushMsg = push_message,
|
|
askYesNo = ask_yes_no,
|
|
askForget = open_forget_screen,
|
|
onDone = function(learned)
|
|
if learned then
|
|
MoveRelearner.finish(true)
|
|
else
|
|
-- pokefirered/src/learn_move.c:591
|
|
MoveRelearner._moves = MoveLearn.relearnableMoves(MoveRelearner._mon)
|
|
clamp_cursor()
|
|
to_list()
|
|
end
|
|
end,
|
|
})
|
|
end
|
|
|
|
function MoveRelearner.show(mon, opts)
|
|
opts = opts or {}
|
|
MoveRelearner.open = true
|
|
MoveRelearner._mon = mon
|
|
MoveRelearner._session = opts.session
|
|
MoveRelearner._onDone = opts.onDone
|
|
MoveRelearner._moves = MoveLearn.relearnableMoves(mon)
|
|
MoveRelearner._pendingMoveId = nil
|
|
MoveRelearner._messageCb = nil
|
|
MoveRelearner._yesNoCb = nil
|
|
MoveRelearner.cursor = 1
|
|
MoveRelearner.scroll = 0
|
|
clamp_cursor()
|
|
to_list()
|
|
Stack.push("move_relearner", MoveRelearner, { hideBelow = true, fullscreen = true })
|
|
end
|
|
|
|
function MoveRelearner.handleInput(input)
|
|
if not MoveRelearner.open then return end
|
|
|
|
if MoveRelearner.state == "message" then
|
|
if input:wasPressed("a") or input:wasPressed("b") then
|
|
se(SE.SE_SELECT)
|
|
local cb = MoveRelearner._messageCb
|
|
MoveRelearner._messageCb = nil
|
|
to_list()
|
|
if cb then cb() end
|
|
end
|
|
return
|
|
end
|
|
|
|
if MoveRelearner.state == "yesno" then
|
|
if input:wasPressed("up") or input:wasPressed("down") then
|
|
MoveRelearner.yesNoCursor = MoveRelearner.yesNoCursor == 1 and 2 or 1
|
|
se(SE.SE_SELECT)
|
|
elseif input:wasPressed("a") then
|
|
se(SE.SE_SELECT)
|
|
local yes = MoveRelearner.yesNoCursor == 1
|
|
local cb = MoveRelearner._yesNoCb
|
|
MoveRelearner._yesNoCb = nil
|
|
to_list()
|
|
if cb then cb(yes) end
|
|
elseif input:wasPressed("b") then
|
|
se(SE.SE_SELECT)
|
|
local cb = MoveRelearner._yesNoCb
|
|
MoveRelearner._yesNoCb = nil
|
|
to_list()
|
|
if cb then cb(false) end
|
|
end
|
|
return
|
|
end
|
|
|
|
local total = total_rows()
|
|
if input:wasPressed("up") then
|
|
if MoveRelearner.cursor > 1 then
|
|
MoveRelearner.cursor = MoveRelearner.cursor - 1
|
|
clamp_cursor()
|
|
se(SE.SE_SELECT)
|
|
end
|
|
elseif input:wasPressed("down") then
|
|
if MoveRelearner.cursor < total then
|
|
MoveRelearner.cursor = MoveRelearner.cursor + 1
|
|
clamp_cursor()
|
|
se(SE.SE_SELECT)
|
|
end
|
|
elseif input:wasPressed("a") then
|
|
se(SE.SE_SELECT)
|
|
local moveId = MoveRelearner.moves()[MoveRelearner.cursor]
|
|
if moveId then
|
|
-- pokefirered/src/learn_move.c:784
|
|
ask_yes_no(RomText.plain("gText_TeachMoveQues",
|
|
{ stringVars = { mon_name(), Pokemon.moveName(moveId) } }), function(yes)
|
|
if yes then
|
|
start_learn(moveId)
|
|
else
|
|
to_list()
|
|
end
|
|
end)
|
|
else
|
|
MoveRelearner.giveUpPrompt()
|
|
end
|
|
elseif input:wasPressed("b") then
|
|
se(SE.SE_SELECT)
|
|
MoveRelearner.giveUpPrompt()
|
|
end
|
|
end
|
|
|
|
-- pokefirered/src/learn_move.c:789
|
|
function MoveRelearner.giveUpPrompt()
|
|
ask_yes_no(RomText.plain("gText_GiveUpTryingToTeachNewMove", { stringVars = { mon_name() } }), function(yes)
|
|
if yes then
|
|
-- pokefirered/src/learn_move.c:541
|
|
MoveRelearner.finish(false)
|
|
else
|
|
to_list()
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- pokefirered/src/learn_move.c:816 PrintMoveInfo
|
|
local function move_info(moveId)
|
|
local info = MoveRelearner._info
|
|
if info and info.id == moveId then return info end
|
|
local row = Pokemon.battleMove(moveId) or {}
|
|
local power = tonumber(row.power) or 0
|
|
local acc = tonumber(row.accuracy) or 0
|
|
local desc = SummaryData.moveDescription(moveId, Pokemon.moveName(moveId))
|
|
info = {
|
|
id = moveId,
|
|
badge = tostring(row.type or "NORMAL"):upper(),
|
|
power = power >= 2 and string.format("%3d", power) or "---",
|
|
accuracy = acc > 0 and string.format("%3d", acc) or "---",
|
|
pp = tostring(tonumber(row.pp) or 0),
|
|
desc = (desc and desc ~= "") and FrlgFont.wrap(desc, 116) or nil,
|
|
}
|
|
MoveRelearner._info = info
|
|
return info
|
|
end
|
|
|
|
local function draw_move_info(moveId)
|
|
local info = move_info(moveId)
|
|
SummaryChrome.drawTypeBadge(info.badge, 41, 4)
|
|
FrlgFont.draw(info.power, 121, 4, VALUE_OPTS)
|
|
FrlgFont.draw(info.accuracy, 121, 18, VALUE_OPTS)
|
|
FrlgFont.draw(info.pp, 42, 18, VALUE_OPTS)
|
|
if info.desc then
|
|
FrlgFont.draw(info.desc, 17, 48, DESC_OPTS)
|
|
end
|
|
end
|
|
|
|
function MoveRelearner.draw()
|
|
if not MoveRelearner.open then return end
|
|
if not (love and love.graphics) then return end
|
|
local moves = MoveRelearner.moves()
|
|
local total = total_rows()
|
|
|
|
local bg = MoveRelearner.chrome()
|
|
if bg then
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
love.graphics.draw(bg, 0, 0)
|
|
else
|
|
love.graphics.setColor(0.24, 0.35, 0.50, 1)
|
|
love.graphics.rectangle("fill", 0, 0, 240, 160)
|
|
-- pokefirered/src/learn_move.c:254 sWindowTemplates
|
|
love.graphics.setColor(0.88, 0.91, 0.95, 1)
|
|
love.graphics.rectangle("fill", 0, 0, 148, 48)
|
|
love.graphics.setColor(0.98, 0.98, 0.98, 1)
|
|
love.graphics.rectangle("fill", 16, 48, 120, 64)
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
end
|
|
-- pokefirered/src/learn_move.c:679 DrawTextBorderOnWindows6and7
|
|
Window.stdFrame(WIN_LIST)
|
|
Window.stdFrame(WIN_PROMPT)
|
|
|
|
-- pokefirered/src/learn_move.c:845 LoadMoveInfoUI
|
|
FrlgFont.draw(Strings("TYPE"), 1, 4, LABEL_OPTS)
|
|
FrlgFont.draw(Strings("POWER"), 80, 4, LABEL_OPTS)
|
|
FrlgFont.draw(Strings("PP"), 1, 19, LABEL_OPTS)
|
|
FrlgFont.draw(Strings("ACCURACY"), 80, 19, LABEL_OPTS)
|
|
FrlgFont.draw(Strings("EFFECT"), 1, 34, LABEL_OPTS)
|
|
|
|
local selected = moves[MoveRelearner.cursor]
|
|
if selected then draw_move_info(selected) end
|
|
|
|
-- pokefirered/src/learn_move.c:339 sMoveRelearnerListMenuTemplate
|
|
for i = 1, VISIBLE do
|
|
local idx = MoveRelearner.scroll + i
|
|
if idx > total then break end
|
|
local y = 8 + (i - 1) * ROW_H
|
|
if idx == MoveRelearner.cursor and MoveRelearner.state == "list" then
|
|
Window.cursorPx(152, y)
|
|
end
|
|
-- pokefirered/src/learn_move.c:761
|
|
local row = moves[idx] and Pokemon.moveName(moves[idx]) or RomText.plain("gFameCheckerText_Cancel")
|
|
FrlgFont.draw(row, 160, y, ROW_OPTS)
|
|
end
|
|
|
|
if MoveRelearner.prompt then
|
|
FrlgFont.draw(MoveRelearner.prompt, 16, 122, PROMPT_OPTS)
|
|
end
|
|
|
|
if MoveRelearner.state == "yesno" then
|
|
Window.stdFrame(WIN_YESNO)
|
|
FrlgFont.draw(RomText.plain("gText_Yes"), 176, 66, VALUE_OPTS)
|
|
FrlgFont.draw(RomText.plain("gText_No"), 176, 82, VALUE_OPTS)
|
|
Window.cursorPx(169, MoveRelearner.yesNoCursor == 1 and 66 or 82)
|
|
end
|
|
end
|
|
|
|
return MoveRelearner
|