Files
gen1recomp/src/ui/game3/hud.lua
T

302 lines
9.2 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- Game3 UI controller: input + open helpers.
-- Drawing is owned by display.lua / gfx.lua (FRLG 240×160).
local Message = require("src.ui.game3.message")
local Choice = require("src.ui.game3.choice")
local StartMenu = require("src.ui.game3.start_menu")
local BagMenu = require("src.ui.game3.bag_menu")
local RegionMap = require("src.ui.game3.region_map")
local PartyMenu = require("src.ui.game3.party_menu")
local Pokedex = require("src.ui.game3.pokedex")
local OptionMenu = require("src.ui.game3.option_menu")
local SaveMenu = require("src.ui.game3.save_menu")
local TrainerCard = require("src.ui.game3.trainer_card")
local PcMenu = require("src.ui.game3.pc_menu")
local SummaryMenu = require("src.ui.game3.summary_menu")
local ShopMenu = require("src.ui.game3.shop_menu")
local Stack = require("src.ui.game3.stack")
local Hud = {}
local function log(msg)
print("[game3] " .. tostring(msg))
end
function Hud.busy()
local Battle = package.loaded["src.core.game3.battle"]
if Battle and Battle.isActive and Battle.isActive() then return true end
local Naming = package.loaded["src.ui.game3.naming"]
local Fade = package.loaded["src.ui.game3.fade"]
return Message.isOpen() or Choice.active or Stack.busy()
or (Naming and Naming.isOpen and Naming.isOpen())
or (Fade and Fade.isActive and Fade.isActive())
or StartMenu.isOpen() or BagMenu.isOpen() or RegionMap.isOpen()
or PartyMenu.isOpen() or SummaryMenu.isOpen() or Pokedex.isOpen()
or OptionMenu.isOpen() or SaveMenu.isOpen()
or TrainerCard.isOpen() or PcMenu.isOpen()
or ShopMenu.isOpen()
or Hud._waitButton ~= nil
end
function Hud.armWaitButton(cb)
Hud._waitButton = cb
end
function Hud.clearWaitButton()
Hud._waitButton = nil
end
local function update_top_menu(input)
local top = Stack.top()
if top and top.mod then
if top.mod.handleInput then
top.mod.handleInput(input)
return true
end
end
if SaveMenu.isOpen() then
if input:wasPressed("left") or input:wasPressed("right")
or input:wasPressed("up") or input:wasPressed("down") then
SaveMenu.move(1)
elseif input:wasPressed("a") then SaveMenu.confirm()
elseif input:wasPressed("b") then SaveMenu.cancel()
end
return true
end
if OptionMenu.isOpen() then
if input:wasPressed("up") then OptionMenu.move(-1)
elseif input:wasPressed("down") then OptionMenu.move(1)
elseif input:wasPressed("left") then OptionMenu.adjust(-1)
elseif input:wasPressed("right") then OptionMenu.adjust(1)
elseif input:wasPressed("a") then OptionMenu.confirm()
elseif input:wasPressed("b") or input:wasPressed("start") then OptionMenu.close()
end
return true
end
if TrainerCard.isOpen() then
if input:wasPressed("b") or input:wasPressed("start") or input:wasPressed("a") then
TrainerCard.close()
end
return true
end
if PcMenu.isOpen() then
if PcMenu.handleInput then
PcMenu.handleInput(input)
end
return true
end
if ShopMenu.isOpen() then
if ShopMenu.handleInput then
ShopMenu.handleInput(input)
end
return true
end
if BagMenu.isOpen() then
if BagMenu.handleInput then
BagMenu.handleInput(input)
else
if input:wasPressed("b") or input:wasPressed("start") then BagMenu.close() end
end
return true
end
if RegionMap.isOpen() then
if input:wasPressed("left") then RegionMap.togglePage(-1)
elseif input:wasPressed("right") then RegionMap.togglePage(1)
elseif input:wasPressed("up") then RegionMap.moveCursor(-1)
elseif input:wasPressed("down") then RegionMap.moveCursor(1)
elseif input:wasPressed("b") or input:wasPressed("start") then RegionMap.close()
end
return true
end
if SummaryMenu.isOpen() then
if SummaryMenu.handleInput then
SummaryMenu.handleInput(input)
else
if input:wasPressed("b") or input:wasPressed("start") then SummaryMenu.close() end
end
return true
end
if PartyMenu.isOpen() then
if PartyMenu.handleInput then
PartyMenu.handleInput(input)
else
if input:wasPressed("b") or input:wasPressed("start") then PartyMenu.close() end
end
return true
end
if Pokedex.isOpen() then
if Pokedex.handleInput then
Pokedex.handleInput(input)
else
if input:wasPressed("b") or input:wasPressed("start") then Pokedex.close() end
end
return true
end
if StartMenu.isOpen() then
if input:wasPressed("up") then StartMenu.move(-1)
elseif input:wasPressed("down") then StartMenu.move(1)
elseif input:wasPressed("a") then StartMenu.confirm()
elseif input:wasPressed("b") or input:wasPressed("start") then StartMenu.close()
end
return true
end
return false
end
function Hud.update(game, _dt)
local dt = tonumber(_dt) or (1 / 60)
-- Active stack modal menu tick
local top = Stack.top()
if top and top.mod and top.mod.update then
pcall(top.mod.update, dt)
end
local input = game and game.input
if not input then return end
local inBattle = false
local Battle = package.loaded["src.core.game3.battle"]
if Battle and Battle.isActive and Battle.isActive() then
inBattle = true
end
-- Active stack modal menu input takes top precedence when NOT in battle.
-- When battle is active, Battle.update is the sole dispatcher for battle menus.
if not inBattle and Stack.busy() then
if update_top_menu(input) then
return
end
end
-- Choice in field/scripting (in battle, Choice is driven by Battle.update).
if not inBattle and Choice.active then
if input:wasPressed("up") then Choice.move(-1)
elseif input:wasPressed("down") then Choice.move(1)
elseif input:wasPressed("a") then Choice.confirm()
elseif input:wasPressed("b") then Choice.cancel()
end
return
end
if Message.isOpen() then
local held = input:isDown("a") or input:isDown("b")
if Message.setSpeedUp then Message.setSpeedUp(held) end
local aPress = input:wasPressed("a") or input:wasPressed("b")
if aPress then
local onLast = Message.isWaiting()
and Message._page >= #(Message._pages or {})
if Message._stay and onLast then
-- Stay on last page: waitbuttonpress / yesnobox own the A press.
if Hud._waitButton then
local cb = Hud._waitButton
Hud._waitButton = nil
cb()
end
else
Message.advance()
end
end
return
end
if Hud._waitButton then
if input:wasPressed("a") or input:wasPressed("b") then
local cb = Hud._waitButton
Hud._waitButton = nil
cb()
end
return
end
if inBattle then
return
end
if not Hud.busy() then
-- START opens pause menu when field is idle (Escape / gamepad Start).
-- Owned here (not Field) so the open press cannot also close same frame.
if input:wasPressed("start") then
local Field = package.loaded["src.core.game3.field"]
local Space = package.loaded["src.core.game3.scripting.space"]
local Runtime = package.loaded["src.core.game3.runtime"]
or require("src.core.game3.runtime")
local scriptBusy = Space and Space.vm and Space.vm.isRunning and Space.vm:isRunning()
local locked = Field and Field.locked
if not locked and not scriptBusy then
Hud.openStartMenu(game, (Field and Field._session)
or (Runtime.getSession and Runtime.getSession()))
end
end
return
end
if SummaryMenu.isOpen() and SummaryMenu.update then
SummaryMenu.update(_dt or (1 / 60))
end
if PartyMenu.isOpen() and PartyMenu.update then
PartyMenu.update(_dt or (1 / 60))
end
update_top_menu(input)
end
function Hud.openStartMenu(game, session)
if StartMenu.isOpen() then
log("Start Menu close (toggle)")
StartMenu.close()
return
end
-- Close other field menus first.
if BagMenu.isOpen() then BagMenu.close() end
if SummaryMenu.isOpen() then SummaryMenu.close() end
if PartyMenu.isOpen() then PartyMenu.close() end
if Pokedex.isOpen() then Pokedex.close() end
if RegionMap.isOpen() then RegionMap.close() end
if OptionMenu.isOpen() then OptionMenu.close() end
if SaveMenu.isOpen() then SaveMenu.close() end
if TrainerCard.isOpen() then TrainerCard.close() end
if PcMenu.isOpen() then PcMenu.close() end
-- pret FlagSet(FLAG_OPENED_START_MENU) on first open (Pallet sign lady).
do
local Space = package.loaded["src.core.game3.scripting.space"]
local Flags = package.loaded["src.core.game3.scripting.flags"]
or require("src.core.game3.scripting.flags")
local store = Space and Space.store
if store and Flags.IDS and Flags.IDS.OPENED_START_MENU then
Flags.setFlag(store, nil, Flags.IDS.OPENED_START_MENU, true)
if Space.persistSession then
pcall(Space.persistSession)
end
end
end
log("Start Menu on game3 display (FRLG 240x160)")
StartMenu.show({ session = session })
end
function Hud.openMessage(game, text, opts)
log("dialog on game3 display")
Message.show(text, opts)
end
function Hud.openMessageStay(game, text, opts)
opts = opts or {}
opts.stay = true
log("stay-dialog on game3 display")
Message.showStay(text, opts)
end
function Hud.openPc(game, session)
PcMenu.show({ session = session or (require("src.core.game3.runtime").getSession()) })
end
function Hud.ensure(_game, _mode)
return Hud
end
function Hud.new()
return Hud
end
return Hud