-
Notifications
You must be signed in to change notification settings - Fork 2
Tutorial 11 Custom UI Screen
Goal. Add a Quest Log screen, open it from the Start menu, and open it from a script command.
Prerequisites. Tutorials 08 and 10;
Reference: The Mod Object (the mod.ui toolkit).
Files created.
mods/tutorial_11_ui/
├── manifest.json
└── main.lua
-
Register the screen. The
screensregistry maps an id to a factory (functionor{ new = fn }), resolved bysrc/ui/Screens.lua. A screen is a state-stack table: optionalenter/exit/update/draw/isOpaque, input polled fromgame.input:return function(mod) mod.content.screens:register("QuestLog", { new = function(game) local Font = mod.ui.Font local self = { game = game, isOpaque = true } function self:update(dt) if game.input:wasPressed("b") or game.input:wasPressed("a") then game.stack:pop() end end function self:draw() Font.drawBox(0, 0, 20, 18) -- full-screen GB frame Font.draw("QUEST LOG", 16, 16) local stage = mod.save:get("stage", 0) Font.draw(("NUGGET QUEST: %d"):format(stage), 16, 40) Font.draw("PRESS B TO EXIT", 16, 128) end return self end, }) end
isOpaque = truestops the overworld drawing underneath; the GB canvas is 160×144 with the frame drawn in 8px tiles. Outcome: the screen exists but nothing opens it yet. -
Add a Start-menu row. The menu-assembly hook hands you the item list; insert against a stable label with the
mod.uihelpers:mod.hooks:wrap("ui.start_menu.items", function(next, game, items) mod.ui.insertBefore(items, "OPTION", { label = "QUESTS", onSelect = function() mod.ui.push(game, "QuestLog") end, }) return next(game, items) end)
Outcome: a QUESTS row sits above OPTION and opens the log. With the mod disabled the row is gone — the hook chain is empty.
-
Open it from a script. The
push_screencommand instantiates through the same registry and blocks until the screen pops:mod.content.map_scripts:register("PALLET_TOWN", { talk = { TEXT_TUT8_GIVER = { { "show_text", "Let me show you\nyour progress." }, { "push_screen", "QuestLog" }, { "show_text", "Keep at it!" }, }, }, })
Outcome: the quest giver pops the log mid-conversation, and the dialogue resumes when the player closes it.
QUESTS appears in the Start menu with the mod on and is absent with it
off; the screen opens from both the menu and the script, draws in the GB
aesthetic, and closes on B. A screen factory that throws degrades: the
error is logged against the mod and, for an overridden builtin id, the
builtin screen is used instead (src/ui/Screens.lua).
-
Returning a non-table from a
ui.*hook. The engine keeps the vanilla list and logs the mistake; alwaysreturn next(game, items)(or the items table). -
Forgetting
isOpaque. The overworld bleeds through your screen. Set it unless you want an overlay. -
Hard-coding row positions. Menus are hook-assembled; anchor with
insertBefore/insertAfteron stable labels, not indices. -
Reading LÖVE input directly. Poll
game.input:wasPressed(...)inupdate— it respects the bindings menu and controllers.
Engine 1.0.0 · mod API 2 · repository · Discord
This project ships no ROM data. All game content is decoded on the player's machine from their own verified Pokemon Red ROM; mods ship recipes and original assets, never extracted content.
Start here
Concepts
Tutorials
- The ladder
- 01 Sprite and Text Tweak
- 02 Balance Patch
- 03 New Species
- 04 New Item and Ball
- 05 New Move
- 06 NPC and Dialogue
- 07 New Map
- 08 Quest
- 09 Custom Music
- 10 New Mechanic
- 11 Custom UI Screen
- 12 Mini Total Conversion
Reference
Guides
Playing