mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-17 11:11:10 +02:00
Bug squashing and translation mods (#311)
* audio timing stuff * bug fixes and translation additions * translation stuff * Update modkit.py * better asset resolution
This commit is contained in:
+29
-20
@@ -9,6 +9,7 @@ local TextBox = require("src.render.TextBox")
|
||||
local BagMenu = {}
|
||||
|
||||
local Bag = require("src.inventory.Bag")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
-- acquisition order like wBagItems (Bag.order), not alphabetical
|
||||
local function buildItems(game)
|
||||
@@ -108,13 +109,13 @@ local function useOn(game, battle, id, target, list, moveIndex)
|
||||
if game.save.onBike then
|
||||
game.save.onBike = false
|
||||
Music.playMap(game.data, ow and ow.map.id, false)
|
||||
showMessages(game, { save_name(game) .. " got off\nthe BICYCLE." })
|
||||
showMessages(game, { Strings("%s got off\nthe BICYCLE.", save_name(game)) })
|
||||
elseif bikeAllowed() then
|
||||
game.save.onBike = true
|
||||
Music.playMap(game.data, ow.map.id, true)
|
||||
showMessages(game, { save_name(game) .. " got on\nthe BICYCLE!" })
|
||||
showMessages(game, { Strings("%s got on\nthe BICYCLE!", save_name(game)) })
|
||||
else
|
||||
showMessages(game, { "No cycling\nallowed here." })
|
||||
showMessages(game, { Strings("No cycling\nallowed here.") })
|
||||
end
|
||||
return
|
||||
end
|
||||
@@ -130,13 +131,14 @@ local function useOn(game, battle, id, target, list, moveIndex)
|
||||
return
|
||||
end
|
||||
end
|
||||
showMessages(game, { "No good! It's not\neven near water." })
|
||||
showMessages(game, { Strings("No good! It's not\neven near water.") })
|
||||
return
|
||||
end
|
||||
|
||||
if result == "ball" then
|
||||
if not battle then
|
||||
showMessages(game, { "OAK: " .. game.save.player.name .. "!\nThis isn't the\ntime to use that!" })
|
||||
showMessages(game, { Strings("OAK: %s!\nThis isn't the\ntime to use that!",
|
||||
game.save.player.name) })
|
||||
return
|
||||
end
|
||||
consume(game, id)
|
||||
@@ -151,7 +153,7 @@ local function useOn(game, battle, id, target, list, moveIndex)
|
||||
local function teach()
|
||||
if #target.moves < 4 then
|
||||
table.insert(target.moves, { id = moveId, pp = mdef.pp })
|
||||
showMessages(game, { ("%s learned\n%s!"):format(target.nickname or
|
||||
showMessages(game, { Strings("%s learned\n%s!", target.nickname or
|
||||
game.data.pokemon[target.species].name, mdef.name) })
|
||||
if result == "learn" then consume(game, id) end
|
||||
else
|
||||
@@ -172,7 +174,7 @@ local function useOn(game, battle, id, target, list, moveIndex)
|
||||
require("src.ui.Screens").push(game, "TownMap")
|
||||
end)
|
||||
if not ok then
|
||||
showMessages(game, { "The TOWN MAP is\nunreadable here." })
|
||||
showMessages(game, { Strings("The TOWN MAP is\nunreadable here.") })
|
||||
end
|
||||
return
|
||||
end
|
||||
@@ -184,10 +186,10 @@ local function useOn(game, battle, id, target, list, moveIndex)
|
||||
local t = game.data.text
|
||||
if ow and ow:hasHiddenItemLeft() then
|
||||
showMessages(game, { t._ItemfinderFoundItemText
|
||||
or "Yes! ITEMFINDER\nindicates there's\nan item nearby." })
|
||||
or Strings("Yes! ITEMFINDER\nindicates there's\nan item nearby.") })
|
||||
else
|
||||
showMessages(game, { t._ItemfinderFoundNothingText
|
||||
or "Nope! ITEMFINDER\nisn't responding." })
|
||||
or Strings("Nope! ITEMFINDER\nisn't responding.") })
|
||||
end
|
||||
return
|
||||
end
|
||||
@@ -219,8 +221,9 @@ local function useOn(game, battle, id, target, list, moveIndex)
|
||||
-- departure helper -- the same path Dig/Teleport take from the party menu
|
||||
ow:beginTeleportOut()
|
||||
else
|
||||
showMessages(game, { "OAK: " .. game.save.player.name
|
||||
.. "!\nThis isn't the\ntime to use that!" })
|
||||
showMessages(game, { Strings(
|
||||
"OAK: %s!\nThis isn't the\ntime to use that!",
|
||||
game.save.player.name) })
|
||||
end
|
||||
return
|
||||
end
|
||||
@@ -264,7 +267,7 @@ local function useOn(game, battle, id, target, list, moveIndex)
|
||||
if #target.moves < 4 then
|
||||
table.insert(target.moves, { id = moveId, pp = mdef.pp })
|
||||
local name = target.nickname or def.name
|
||||
showMessages(game, { ("%s learned\n%s!"):format(name, mdef.name) },
|
||||
showMessages(game, { Strings("%s learned\n%s!", name, mdef.name) },
|
||||
nextStep)
|
||||
else
|
||||
require("src.ui.Screens").push(game, "MoveLearnMenu",
|
||||
@@ -354,8 +357,8 @@ local function useItem(game, battle, id, list)
|
||||
local moveDef = game.data.moves[def.machine.move]
|
||||
local moveName = moveDef and moveDef.name or def.machine.move
|
||||
local booted = def.machine.kind == "HM"
|
||||
and "Booted up an HM!" or "Booted up a TM!"
|
||||
showMessages(game, { booted, ("It contained\n%s!"):format(moveName) },
|
||||
and "Booted up an HM!" or Strings("Booted up a TM!")
|
||||
showMessages(game, { booted, Strings("It contained\n%s!", moveName) },
|
||||
function() pickTargetAndUse(game, battle, id, list) end)
|
||||
return
|
||||
end
|
||||
@@ -402,17 +405,23 @@ function BagMenu.new(game, opts)
|
||||
useItem(game, battle, id, list)
|
||||
return
|
||||
end
|
||||
-- USE / TOSS submenu (the original's item options)
|
||||
-- USE / TOSS submenu (the original's item options).
|
||||
-- data/text_boxes.asm USE_TOSS_MENU_TEMPLATE: box (13,10)-(19,14),
|
||||
-- text at (15,11); start_sub_menus.asm then sets wTopMenuItemY/X to
|
||||
-- 11/14 for the cursor. Menu's own geometry reproduces all of that
|
||||
-- from the box alone, so this needs opts rather than a change to the
|
||||
-- shared Menu. The old 12/10/8/6 box was a column too wide and a row
|
||||
-- too tall, which left the labels stranded near its top edge (#284).
|
||||
local Menu = require("src.ui.Menu")
|
||||
game.stack:push(Menu.new(game, {
|
||||
{ label = "USE", onSelect = function()
|
||||
{ label = Strings("USE"), onSelect = function()
|
||||
useItem(game, battle, id, list)
|
||||
end },
|
||||
{ label = "TOSS", onSelect = function()
|
||||
{ label = Strings("TOSS"), onSelect = function()
|
||||
-- KeyItemFlags + HMs decide tossability (not price:
|
||||
-- MOON STONE is price 0 but tossable)
|
||||
if not def or def.keyItem or id:find("^HM_") then
|
||||
showMessages(game, { "That's too impor-\ntant to toss!" })
|
||||
showMessages(game, { Strings("That's too impor-\ntant to toss!") })
|
||||
return
|
||||
end
|
||||
local QuantityBox = require("src.ui.QuantityBox")
|
||||
@@ -426,12 +435,12 @@ function BagMenu.new(game, opts)
|
||||
Bag.remove(game.save, id, qty)
|
||||
list.items = buildItems(game)
|
||||
list.index = math.min(list.index, math.max(1, #list.items))
|
||||
showMessages(game, { ("Threw away\n%s."):format(def and def.name or id) })
|
||||
showMessages(game, { Strings("Threw away\n%s.", def and def.name or id) })
|
||||
end))
|
||||
end,
|
||||
}))
|
||||
end },
|
||||
}, { tx = 12, ty = 10, tw = 8, th = 6 }))
|
||||
}, { tx = 13, ty = 10, tw = 7, th = 5 }))
|
||||
end,
|
||||
})
|
||||
return list
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
local Font = require("src.render.Font")
|
||||
local ListMenu = require("src.ui.ListMenu")
|
||||
local Input = require("src.core.Input")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local BindingsMenu = setmetatable({}, { __index = ListMenu })
|
||||
BindingsMenu.__index = BindingsMenu
|
||||
@@ -55,7 +56,9 @@ function BindingsMenu.new(game)
|
||||
and game.save.options.bindings
|
||||
local items = {}
|
||||
for i, def in ipairs(BUTTONS) do
|
||||
items[i] = { label = def.label,
|
||||
-- translated here, not in ROWS: that table is built at require
|
||||
-- time, before Strings.load has a catalog to look in
|
||||
items[i] = { label = Strings(def.label),
|
||||
right = boundRight(overlay, def), button = def }
|
||||
end
|
||||
local self = setmetatable(ListMenu.new(game, "CONTROLS", items, {}),
|
||||
@@ -111,7 +114,7 @@ function BindingsMenu:draw()
|
||||
if self.capture then
|
||||
Font.drawBox(1, 6, 18, 4)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("PRESS A BUTTON", 24, 60)
|
||||
Font.draw(Strings("PRESS A BUTTON"), 24, 60)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
+26
-25
@@ -8,12 +8,13 @@ local ListMenu = require("src.ui.ListMenu")
|
||||
local Menu = require("src.ui.Menu")
|
||||
local Party = require("src.pokemon.Party")
|
||||
local TextBox = require("src.render.TextBox")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local BoxMenu = {}
|
||||
|
||||
local function monLabel(game, mon)
|
||||
local def = game.data.pokemon[mon.species]
|
||||
return ("%s :L%d"):format(mon.nickname or def.name, mon.level)
|
||||
return Strings("%s :L%d", mon.nickname or def.name, mon.level)
|
||||
end
|
||||
|
||||
local function monName(game, mon)
|
||||
@@ -28,13 +29,13 @@ local function monSubmenu(game, action, mon, onAction)
|
||||
game.stack:push(Menu.new(game, {
|
||||
{ label = action, onSelect = onAction },
|
||||
{
|
||||
label = "STATS",
|
||||
label = Strings("STATS"),
|
||||
keepOpen = true,
|
||||
onSelect = function()
|
||||
require("src.ui.Screens").push(game, "SummaryMenu", mon)
|
||||
end,
|
||||
},
|
||||
{ label = "CANCEL" },
|
||||
{ label = Strings("CANCEL") },
|
||||
}, { tx = 9, ty = 10, tw = 11, th = 8, noSound = true }))
|
||||
end
|
||||
|
||||
@@ -50,12 +51,12 @@ local function withdraw(game)
|
||||
local t = game.data.text
|
||||
if #box == 0 then
|
||||
game.stack:push(TextBox.new(game, t._NoMonText
|
||||
or "What? There are\nno POKéMON here!"))
|
||||
or Strings("What? There are\nno POKéMON here!")))
|
||||
return
|
||||
end
|
||||
if #game.save.party >= Party.MAX then
|
||||
game.stack:push(TextBox.new(game, t._CantTakeMonText
|
||||
or "You can't take\nany more POKéMON.\fDeposit POKéMON\nfirst."))
|
||||
or Strings("You can't take\nany more POKéMON.\fDeposit POKéMON\nfirst.")))
|
||||
return
|
||||
end
|
||||
local items = {}
|
||||
@@ -63,7 +64,7 @@ local function withdraw(game)
|
||||
table.insert(items, { label = monLabel(game, mon), value = i })
|
||||
end
|
||||
game.stack:push(ListMenu.new(game,
|
||||
("BOX %d (WITHDRAW)"):format(game.save.currentBox), items, {
|
||||
Strings("BOX %d (WITHDRAW)", game.save.currentBox), items, {
|
||||
onChoose = function(item, list)
|
||||
local mon = box[item.value]
|
||||
if not mon then return end
|
||||
@@ -78,7 +79,7 @@ local function withdraw(game)
|
||||
game.stringBuffer = name
|
||||
require("src.core.Sound").playCry(game.data, mon.species)
|
||||
afterTransfer(game, list, t._MonIsTakenOutText
|
||||
or (name .. " is\ntaken out.\vGot " .. name .. "."))
|
||||
or Strings("%s is\ntaken out.\vGot %s.", name, name))
|
||||
end)
|
||||
end,
|
||||
}))
|
||||
@@ -88,13 +89,13 @@ local function deposit(game)
|
||||
local t = game.data.text
|
||||
if #game.save.party <= 1 then
|
||||
game.stack:push(TextBox.new(game, t._CantDepositLastMonText
|
||||
or "You can't deposit\nthe last POKéMON!"))
|
||||
or Strings("You can't deposit\nthe last POKéMON!")))
|
||||
return
|
||||
end
|
||||
local box = Boxes.active(game.save)
|
||||
if #box >= Boxes.CAPACITY then
|
||||
game.stack:push(TextBox.new(game, t._BoxFullText
|
||||
or "Oops! This Box is\nfull of POKéMON."))
|
||||
or Strings("Oops! This Box is\nfull of POKéMON.")))
|
||||
return
|
||||
end
|
||||
local items = {}
|
||||
@@ -107,12 +108,12 @@ local function deposit(game)
|
||||
if not mon then return end
|
||||
monSubmenu(game, "DEPOSIT", mon, function()
|
||||
if #game.save.party <= 1 then
|
||||
list.footer = "You need at least\none POKéMON!"
|
||||
list.footer = Strings("You need at least\none POKéMON!")
|
||||
return
|
||||
end
|
||||
local active = Boxes.active(game.save)
|
||||
if #active >= Boxes.CAPACITY then
|
||||
list.footer = ("BOX %d is full!"):format(game.save.currentBox)
|
||||
list.footer = Strings("BOX %d is full!", game.save.currentBox)
|
||||
return
|
||||
end
|
||||
table.remove(game.save.party, item.value)
|
||||
@@ -122,7 +123,7 @@ local function deposit(game)
|
||||
game.boxNumString = tostring(game.save.currentBox)
|
||||
require("src.core.Sound").playCry(game.data, mon.species)
|
||||
afterTransfer(game, list, t._MonWasStoredText
|
||||
or (name .. " was\nstored in Box " .. game.boxNumString .. "."))
|
||||
or Strings("%s was\nstored in Box %s.", name, game.boxNumString))
|
||||
end)
|
||||
end,
|
||||
}))
|
||||
@@ -135,7 +136,7 @@ local function release(game)
|
||||
local t = game.data.text
|
||||
if #box == 0 then
|
||||
game.stack:push(TextBox.new(game, t._NoMonText
|
||||
or "What? There are\nno POKéMON here!"))
|
||||
or Strings("What? There are\nno POKéMON here!")))
|
||||
return
|
||||
end
|
||||
local items = {}
|
||||
@@ -143,20 +144,20 @@ local function release(game)
|
||||
table.insert(items, { label = monLabel(game, mon), value = i })
|
||||
end
|
||||
game.stack:push(ListMenu.new(game,
|
||||
("BOX %d (RELEASE)"):format(game.save.currentBox), items, {
|
||||
Strings("BOX %d (RELEASE)", game.save.currentBox), items, {
|
||||
onChoose = function(_, list)
|
||||
local mon = box[list.index]
|
||||
if not mon then return end
|
||||
local name = monName(game, mon)
|
||||
local ChoiceBox = require("src.ui.ChoiceBox")
|
||||
game.stack:push(TextBox.new(game,
|
||||
"Once released,\n" .. name .. " is\ngone forever. OK?", function()
|
||||
Strings("Once released,\n%s is\ngone forever. OK?", name), function()
|
||||
game.stack:push(ChoiceBox.new(game, function(yes)
|
||||
if not yes then return end
|
||||
table.remove(box, list.index)
|
||||
require("src.core.Sound").playCry(game.data, mon.species)
|
||||
game.stack:push(TextBox.new(game,
|
||||
("%s was\nreleased outside.\fBye %s!"):format(name, name)))
|
||||
Strings("%s was\nreleased outside.\fBye %s!", name, name)))
|
||||
list:removeCurrent()
|
||||
end, { defaultNo = true, noSound = true }))
|
||||
end))
|
||||
@@ -170,7 +171,7 @@ local function changeBox(game)
|
||||
for i = 1, Boxes.COUNT do
|
||||
local mark = i == game.save.currentBox and "*" or " "
|
||||
table.insert(items, {
|
||||
label = ("%sBOX %2d"):format(mark, i),
|
||||
label = Strings("%sBOX %2d", mark, i),
|
||||
right = ("%d/%d"):format(#boxes[i], Boxes.CAPACITY),
|
||||
value = i,
|
||||
})
|
||||
@@ -181,7 +182,7 @@ local function changeBox(game)
|
||||
-- BOX, data will be saved. OK?"); declining aborts the change
|
||||
local ChoiceBox = require("src.ui.ChoiceBox")
|
||||
game.stack:push(TextBox.new(game,
|
||||
"When you change a\nPOKéMON BOX, data\nwill be saved. OK?", function()
|
||||
Strings("When you change a\nPOKéMON BOX, data\nwill be saved. OK?"), function()
|
||||
game.stack:push(ChoiceBox.new(game, function(yes)
|
||||
if not yes then return end
|
||||
game.save.currentBox = item.value
|
||||
@@ -197,10 +198,10 @@ end
|
||||
local function drawChrome(game)
|
||||
Font.drawBox(0, 12, 20, 6)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("What?", 8, 112)
|
||||
Font.draw(Strings("What?"), 8, 112)
|
||||
Font.drawBox(9, 14, 11, 4)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("BOX No.", 80, 128)
|
||||
Font.draw(Strings("BOX No."), 80, 128)
|
||||
local n = game.save.currentBox or 1
|
||||
if n >= 10 then
|
||||
Font.draw(tostring(n), 136, 128)
|
||||
@@ -217,15 +218,15 @@ function BoxMenu.new(game)
|
||||
-- full interior (cursor col + label). keepOpen so WITHDRAW/DEPOSIT/
|
||||
-- RELEASE/CHANGE BOX leave this menu underneath (jp BillsPCMenu).
|
||||
local menu = Menu.new(game, {
|
||||
{ label = "WITHDRAW <PK><MN>", keepOpen = true,
|
||||
{ label = Strings("WITHDRAW <PK><MN>"), keepOpen = true,
|
||||
onSelect = function() withdraw(game) end },
|
||||
{ label = "DEPOSIT <PK><MN>", keepOpen = true,
|
||||
{ label = Strings("DEPOSIT <PK><MN>"), keepOpen = true,
|
||||
onSelect = function() deposit(game) end },
|
||||
{ label = "RELEASE <PK><MN>", keepOpen = true,
|
||||
{ label = Strings("RELEASE <PK><MN>"), keepOpen = true,
|
||||
onSelect = function() release(game) end },
|
||||
{ label = "CHANGE BOX", keepOpen = true,
|
||||
{ label = Strings("CHANGE BOX"), keepOpen = true,
|
||||
onSelect = function() changeBox(game) end },
|
||||
{ label = "SEE YA!" },
|
||||
{ label = Strings("SEE YA!") },
|
||||
-- Bill's PC runs silent end to end (BIT_NO_MENU_BUTTON_SOUND,
|
||||
-- engine/menus/pokemon_pc.asm)
|
||||
}, { tx = 0, ty = 0, tw = 14, th = 12, noSound = true })
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
local Font = require("src.render.Font")
|
||||
local Theme = require("src.ui.Theme")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local ChoiceBox = {}
|
||||
ChoiceBox.__index = ChoiceBox
|
||||
@@ -46,8 +47,8 @@ function ChoiceBox:draw()
|
||||
local tx, ty, tw, th = self.tx, self.ty, self.tw, self.th
|
||||
Font.drawBox(tx, ty, tw, th)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("YES", (tx + 2) * 8, (ty + 1) * 8)
|
||||
Font.draw("NO", (tx + 2) * 8, (ty + 3) * 8)
|
||||
Font.draw(Strings("YES"), (tx + 2) * 8, (ty + 1) * 8)
|
||||
Font.draw(Strings("NO"), (tx + 2) * 8, (ty + 3) * 8)
|
||||
Font.drawCode(Theme.cursor, (tx + 1) * 8,
|
||||
(ty + (self.index == 1 and 1 or 3)) * 8)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
+6
-5
@@ -31,6 +31,7 @@
|
||||
|
||||
local Font = require("src.render.Font")
|
||||
local Music = require("src.core.Music")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local Credits = {}
|
||||
Credits.__index = Credits
|
||||
@@ -261,14 +262,14 @@ function Credits:drawCopyright(xoff)
|
||||
love.graphics.draw(self.gfImg, xoff + 80, 88)
|
||||
else
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("GAME FREAK", xoff + 80, 88)
|
||||
Font.draw(Strings("GAME FREAK"), xoff + 80, 88)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
else
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("Nintendo", xoff + 80, 56)
|
||||
Font.draw("Creatures inc.", xoff + 80, 72)
|
||||
Font.draw("GAME FREAK inc.", xoff + 16, 88)
|
||||
Font.draw(Strings("Nintendo"), xoff + 80, 56)
|
||||
Font.draw(Strings("Creatures inc."), xoff + 80, 72)
|
||||
Font.draw(Strings("GAME FREAK inc."), xoff + 16, 88)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
@@ -298,7 +299,7 @@ function Credits:drawTheEnd()
|
||||
end
|
||||
else
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw((te and te.display) or "T H E E N D", 32, 64)
|
||||
Font.draw((te and te.display) or Strings("T H E E N D"), 32, 64)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
-- without permanently marking the mon owned.
|
||||
|
||||
local Font = require("src.render.Font")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local DexEntryMenu = {}
|
||||
DexEntryMenu.__index = DexEntryMenu
|
||||
@@ -76,8 +77,8 @@ function DexEntryMenu:draw()
|
||||
-- feet/inches use the dex screen's ′/″ glyphs ("HT ?′??″" in
|
||||
-- pokedex.asm; the tiles come from gfx/pokedex/pokedex.png via
|
||||
-- engine/gfx/load_pokedex_tiles.asm)
|
||||
Font.draw(("HT %d′%02d″"):format(e.heightFt, e.heightIn or 0), 72, 44)
|
||||
Font.draw(("WT %.1flb"):format((e.weight or 0) / 10), 72, 54)
|
||||
Font.draw(Strings("HT %d′%02d″", e.heightFt, e.heightIn or 0), 72, 44)
|
||||
Font.draw(Strings("WT %.1flb", (e.weight or 0) / 10), 72, 54)
|
||||
end
|
||||
local text = owned and e.text and self.game.data.text[e.text] or nil
|
||||
local y = 72
|
||||
@@ -88,7 +89,7 @@ function DexEntryMenu:draw()
|
||||
y = y + 10
|
||||
end
|
||||
else
|
||||
Font.draw("Data unknown.", 8, y)
|
||||
Font.draw(Strings("Data unknown."), 8, y)
|
||||
end
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
+19
-13
@@ -1,14 +1,17 @@
|
||||
-- The evolution movie (engine/movie/evolution.asm): the mon's pic
|
||||
-- flashes back and forth with the evolved form, speeding up, then the
|
||||
-- new form appears with its cry and the congratulations text.
|
||||
-- pokered engine/pokemon/evos_moves.asm (EvolveMon) polls hJoyHeld during
|
||||
-- the flash: holding B aborts the evolution -- the mon keeps its species
|
||||
-- and _StoppedEvolvingText ("Huh? MON stopped evolving!") prints. The
|
||||
-- lone exception is trade evolutions (wLinkState == LINK_STATE_TRADING),
|
||||
-- which skip that poll and cannot be cancelled (#213).
|
||||
-- pokered engine/movie/evolution.asm (Evolution_CheckForCancel) polls the
|
||||
-- joypad during the flash: holding B aborts the evolution -- the mon keeps
|
||||
-- its species and _StoppedEvolvingText ("Huh? MON stopped evolving!")
|
||||
-- prints. Two kinds are exempt: trade evolutions, which evos_moves.asm
|
||||
-- routes past the poll entirely (wLinkState == LINK_STATE_TRADING, #213),
|
||||
-- and stone evolutions, where the B press is read but thrown away because
|
||||
-- ItemUseEvoStone left wForceEvolution set (#290).
|
||||
|
||||
local Font = require("src.render.Font")
|
||||
local Music = require("src.core.Music")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local EvolutionState = {}
|
||||
EvolutionState.__index = EvolutionState
|
||||
@@ -43,9 +46,12 @@ function EvolutionState.new(game, mon, newSpecies, onDone, via)
|
||||
self.newSpecies = newSpecies
|
||||
self.onDone = onDone
|
||||
self.via = via
|
||||
-- evos_moves.asm: only trade evolutions (LINK_STATE_TRADING) skip the
|
||||
-- B-cancel poll; level-up, stone and rare-candy evos are all cancelable.
|
||||
self.cancelable = (via ~= "TRADE")
|
||||
-- evolution.asm Evolution_CheckForCancel: a B press is discarded when
|
||||
-- wForceEvolution is set, and ItemUseEvoStone sets it before calling
|
||||
-- TryEvolvingMon, so a stone evolution (via == "ITEM") cannot be
|
||||
-- cancelled either. Only level-up and rare-candy evolutions run with
|
||||
-- wForceEvolution clear and so honour B (#290, #213).
|
||||
self.cancelable = (via ~= "TRADE" and via ~= "ITEM")
|
||||
self.oldName = mon.nickname or game.data.pokemon[mon.species].name
|
||||
self.oldSprite = frontSprite(game, mon.species, mon)
|
||||
self.newSprite = frontSprite(game, newSpecies, mon)
|
||||
@@ -69,7 +75,7 @@ function EvolutionState:update(dt)
|
||||
local TextBox = require("src.render.TextBox")
|
||||
-- mirrors data/generated/text.lua _StoppedEvolvingText
|
||||
game.stack:push(TextBox.new(game,
|
||||
("Huh? %s\nstopped evolving!"):format(self.oldName),
|
||||
Strings("Huh? %s\nstopped evolving!", self.oldName),
|
||||
function()
|
||||
Music.restoreMap(game.data)
|
||||
game.stack:pop() -- the evolution screen itself
|
||||
@@ -85,8 +91,8 @@ function EvolutionState:update(dt)
|
||||
local TextBox = require("src.render.TextBox")
|
||||
local newName = game.data.pokemon[self.newSpecies].name
|
||||
game.stack:push(TextBox.new(game,
|
||||
("Congratulations!\nYour %s\nevolved into\n%s!")
|
||||
:format(self.oldName, newName),
|
||||
Strings("Congratulations!\nYour %s\nevolved into\n%s!",
|
||||
self.oldName, newName),
|
||||
function()
|
||||
Music.restoreMap(game.data)
|
||||
game.stack:pop() -- the evolution screen itself
|
||||
@@ -121,9 +127,9 @@ function EvolutionState:draw()
|
||||
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
if not self.done then
|
||||
Font.draw("What?", 8, 104)
|
||||
Font.draw(Strings("What?"), 8, 104)
|
||||
Font.draw(self.oldName .. " is", 8, 114)
|
||||
Font.draw("evolving!", 8, 124)
|
||||
Font.draw(Strings("evolving!"), 8, 124)
|
||||
end
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
+16
-11
@@ -7,10 +7,12 @@
|
||||
-- name/time/money boxes plus the dex rating. Plays Music_HallOfFame
|
||||
-- when the audio data has it. Calls onDone() after popping itself.
|
||||
|
||||
local Assets = require("src.render.Assets")
|
||||
local Font = require("src.render.Font")
|
||||
local Music = require("src.core.Music")
|
||||
local Sound = require("src.core.Sound")
|
||||
local TypeChart = require("src.battle.TypeChart")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local HallOfFame = {}
|
||||
HallOfFame.__index = HallOfFame
|
||||
@@ -47,9 +49,11 @@ local FADE_FRAMES = 20
|
||||
-- HoFPrintTextAndDelay after each dex line
|
||||
local DEX_HOLD = 120
|
||||
|
||||
-- through Assets.resolve so an enabled mod's overrides/ shadows these the
|
||||
-- same way it shadows every other generated asset
|
||||
local function tryImage(path)
|
||||
if not path then return nil end
|
||||
local ok, img = pcall(love.graphics.newImage, path)
|
||||
local ok, img = pcall(love.graphics.newImage, Assets.resolve(path))
|
||||
return ok and img or nil
|
||||
end
|
||||
|
||||
@@ -79,7 +83,8 @@ function HallOfFame.new(game, onDone)
|
||||
self.timer = 0
|
||||
self.phase = "mons"
|
||||
self.sprites = {} -- species -> image or false
|
||||
self.playerPic = tryImage("assets/generated/trainer_card/red.png")
|
||||
self.playerPic = tryImage(require("src.pokemon.Sprites").playerPath(
|
||||
game.data, "front", { kind = "hof" }))
|
||||
self.scrollX = PIC_X
|
||||
self.showHofBanner = false
|
||||
self.fade = 0
|
||||
@@ -206,13 +211,13 @@ function HallOfFame:drawMonInfo(mon)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
local name = mon.nickname or (def and def.name) or mon.species
|
||||
Font.draw(name, 1 * 8, 4 * 8)
|
||||
Font.draw("LEVEL/", 2 * 8, 6 * 8)
|
||||
Font.draw("TYPE1/", 2 * 8, 7 * 8)
|
||||
Font.draw(Strings("LEVEL/"), 2 * 8, 6 * 8)
|
||||
Font.draw(Strings("TYPE1/"), 2 * 8, 7 * 8)
|
||||
local t1 = def and def.types and def.types[1]
|
||||
local t2 = def and def.types and def.types[2]
|
||||
local dual = t2 and t2 ~= t1
|
||||
if dual then
|
||||
Font.draw("TYPE2/", 2 * 8, 8 * 8)
|
||||
Font.draw(Strings("TYPE2/"), 2 * 8, 8 * 8)
|
||||
end
|
||||
-- PrintLevelCommon at (8,7): bare level digits (no <LV> tile here)
|
||||
Font.draw(tostring(mon.level), 8 * 8, 7 * 8)
|
||||
@@ -229,7 +234,7 @@ end
|
||||
function HallOfFame:drawHofBanner()
|
||||
Font.drawBox(2, 13, 16, 5)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("HALL OF FAME", 4 * 8, 15 * 8)
|
||||
Font.draw(Strings("HALL OF FAME"), 4 * 8, 15 * 8)
|
||||
end
|
||||
|
||||
function HallOfFame:drawPic(img)
|
||||
@@ -249,11 +254,11 @@ function HallOfFame:drawPlayerStats()
|
||||
-- play time / money box: TextBoxBorder (0,4) b=6,c=10 → drawBox(0,4,12,8)
|
||||
Font.drawBox(0, 4, 12, 8)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("PLAY TIME", 1 * 8, 6 * 8)
|
||||
Font.draw(Strings("PLAY TIME"), 1 * 8, 6 * 8)
|
||||
local t = math.floor(save.playTime or 0)
|
||||
Font.draw(("%3d:%02d"):format(math.floor(t / 3600), math.floor(t / 60) % 60),
|
||||
5 * 8, 7 * 8)
|
||||
Font.draw("MONEY", 1 * 8, 9 * 8)
|
||||
Font.draw(Strings("MONEY"), 1 * 8, 9 * 8)
|
||||
-- PrintBCDNumber with MONEY_SIGN; port uses ¥ like TrainerCard
|
||||
Font.draw(("¥%d"):format(save.money or 0), 4 * 8, 10 * 8)
|
||||
end
|
||||
@@ -266,16 +271,16 @@ function HallOfFame:drawDexBox(kind)
|
||||
if kind == "seen" then
|
||||
local seen, owned = self:dexSeenOwned()
|
||||
local seenOwned = text._DexSeenOwnedText
|
||||
or "POKéDEX Seen:{NUM:wDexRatingNumMonsSeen, 1, 3}\n Owned:{NUM:wDexRatingNumMonsOwned, 1, 3}"
|
||||
or Strings("POKéDEX Seen:{NUM:wDexRatingNumMonsSeen, 1, 3}\n Owned:{NUM:wDexRatingNumMonsOwned, 1, 3}")
|
||||
seenOwned = seenOwned
|
||||
:gsub("{NUM:wDexRatingNumMonsSeen[^}]*}", tostring(seen))
|
||||
:gsub("{NUM:wDexRatingNumMonsOwned[^}]*}", tostring(owned))
|
||||
drawTextBlock(seenOwned, 1 * 8, 14 * 8, 17 * 8)
|
||||
else
|
||||
local _, owned = self:dexSeenOwned()
|
||||
local ratingHeader = (text._DexRatingText or "POKéDEX Rating{COLON}"):gsub("{COLON}", ":")
|
||||
local ratingHeader = (text._DexRatingText or Strings("POKéDEX Rating{COLON}")):gsub("{COLON}", ":")
|
||||
Font.draw(ratingHeader, 1 * 8, 14 * 8)
|
||||
local rating = text[dexRatingKey(owned)] or "Keep it up!"
|
||||
local rating = text[dexRatingKey(owned)] or Strings("Keep it up!")
|
||||
drawTextBlock(rating, 1 * 8, 15 * 8, 17 * 8)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
local Font = require("src.render.Font")
|
||||
local Music = require("src.core.Music")
|
||||
local Sound = require("src.core.Sound")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local IntroMovie = {}
|
||||
IntroMovie.__index = IntroMovie
|
||||
@@ -287,7 +288,7 @@ function IntroMovie:drawSplash()
|
||||
end
|
||||
-- custom studio name (replaces the GAME FREAK splash text)
|
||||
love.graphics.setColor(0, 0, 0, dim and 0.35 or 1)
|
||||
local card = self.studio.card or "bois club games"
|
||||
local card = self.studio.card or Strings("bois club games")
|
||||
Font.draw(card, (160 - #card * 8) / 2, TEXT_Y)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
@@ -348,7 +349,7 @@ function IntroMovie:drawFight()
|
||||
|
||||
if not gengar and not nido then
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("GENGAR VS NIDORINO", (160 - 18 * 8) / 2, 64)
|
||||
Font.draw(Strings("GENGAR VS NIDORINO"), (160 - 18 * 8) / 2, 64)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
drawBars()
|
||||
@@ -366,7 +367,7 @@ function IntroMovie:draw()
|
||||
-- custom boot card (replaces the Nintendo / GAME FREAK copyright
|
||||
-- card; no (c) glyph in the charmap, keep it ASCII-safe)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
local credit = self.studio.credit or "bois club"
|
||||
local credit = self.studio.credit or Strings("bois club")
|
||||
Font.draw("2026", (160 - 4 * 8) / 2, 48)
|
||||
Font.draw(credit, (160 - #credit * 8) / 2, 64)
|
||||
Font.draw("bryanthaboi", (160 - 11 * 8) / 2, 80)
|
||||
|
||||
+6
-2
@@ -5,6 +5,7 @@
|
||||
local Font = require("src.render.Font")
|
||||
local Runtime = require("src.mods.Runtime")
|
||||
local Theme = require("src.ui.Theme")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local ListMenu = {}
|
||||
ListMenu.__index = ListMenu
|
||||
@@ -192,7 +193,7 @@ function ListMenu:draw()
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw(self.title, 8, 4)
|
||||
if #self.items == 0 then
|
||||
Font.draw("Nothing here.", 16, 64)
|
||||
Font.draw(Strings("Nothing here."), 16, 64)
|
||||
end
|
||||
for row = 1, self.rows do
|
||||
local i = self.scroll + row
|
||||
@@ -201,7 +202,10 @@ function ListMenu:draw()
|
||||
local y = 8 + row * 16
|
||||
Font.draw(item.label, 16, y)
|
||||
if item.ball then -- the Pokédex owned-ball marker tile
|
||||
local bx = 16 + (#item.label + 1) * 8 + 3
|
||||
-- one blank glyph after the name, measured in glyph advances rather
|
||||
-- than bytes: NIDORAN♂/♀ carry a multi-byte charmap entry, so
|
||||
-- `#item.label` overcounted by 2 and pushed their ball 16px right (#285)
|
||||
local bx = 16 + Font.width(item.label) + 8 + 3
|
||||
local by = y + 3
|
||||
love.graphics.circle("fill", bx, by, 3.5)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
+12
-11
@@ -4,6 +4,7 @@
|
||||
-- can't be forgotten; B / CANCEL gives up on the new move.
|
||||
|
||||
local Font = require("src.render.Font")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local MoveLearnMenu = {}
|
||||
MoveLearnMenu.__index = MoveLearnMenu
|
||||
@@ -43,9 +44,9 @@ function MoveLearnMenu:enter()
|
||||
local name = self:monName()
|
||||
self.selecting = false
|
||||
game.stack:push(TextBox.new(game,
|
||||
("%s is\ntrying to learn\v%s!\fBut, %s\ncan't learn more\vthan 4 moves!\f")
|
||||
:format(name, mdef.name, name) ..
|
||||
("Delete an older\nmove to make room\vfor %s?"):format(mdef.name),
|
||||
Strings("%s is\ntrying to learn\v%s!\fBut, %s\ncan't learn more\vthan 4 moves!\f",
|
||||
name, mdef.name, name) ..
|
||||
Strings("Delete an older\nmove to make room\vfor %s?", mdef.name),
|
||||
nil, {
|
||||
choice = function(yes)
|
||||
if yes then
|
||||
@@ -76,7 +77,7 @@ function MoveLearnMenu:update(dt)
|
||||
-- HMCantDeleteText, then back to the forget list
|
||||
local TextBox = require("src.render.TextBox")
|
||||
self.game.stack:push(TextBox.new(self.game,
|
||||
"HM techniques\ncan't be deleted!"))
|
||||
Strings("HM techniques\ncan't be deleted!")))
|
||||
return
|
||||
end
|
||||
local mdef = self.game.data.moves[self.newMoveId]
|
||||
@@ -96,7 +97,7 @@ function MoveLearnMenu:confirmAbandon()
|
||||
local mdef = game.data.moves[self.newMoveId]
|
||||
self.selecting = false
|
||||
game.stack:push(TextBox.new(game,
|
||||
("Abandon learning\n%s?"):format(mdef.name), nil, {
|
||||
Strings("Abandon learning\n%s?", mdef.name), nil, {
|
||||
choice = function(yes)
|
||||
if yes then self:finish(false) else self:enter() end
|
||||
end,
|
||||
@@ -113,11 +114,11 @@ function MoveLearnMenu:finish(learned)
|
||||
local msg
|
||||
if learned then
|
||||
-- OneTwoAndText/PoofText/ForgotAndText
|
||||
msg = ("1, 2 and... Poof!\f%s forgot\n%s!\fAnd...\f%s learned\n%s!")
|
||||
:format(name, self.forgot, name, mdef.name)
|
||||
msg = Strings("1, 2 and... Poof!\f%s forgot\n%s!\fAnd...\f%s learned\n%s!",
|
||||
name, self.forgot, name, mdef.name)
|
||||
else
|
||||
-- DidNotLearnText
|
||||
msg = ("%s\ndid not learn\v%s!"):format(name, mdef.name)
|
||||
msg = Strings("%s\ndid not learn\v%s!", name, mdef.name)
|
||||
end
|
||||
game.stack:push(TextBox.new(game, msg, function()
|
||||
if self.onDone then self.onDone(learned) end
|
||||
@@ -133,12 +134,12 @@ function MoveLearnMenu:draw()
|
||||
for i, mv in ipairs(self.mon.moves) do
|
||||
Font.draw(self.game.data.moves[mv.id].name, 48, (5 + i) * 8)
|
||||
end
|
||||
Font.draw("CANCEL", 48, (6 + #self.mon.moves) * 8)
|
||||
Font.draw(Strings("CANCEL"), 48, (6 + #self.mon.moves) * 8)
|
||||
Font.drawCode(CURSOR, 40, (5 + self.index) * 8)
|
||||
-- WhichMoveToForgetText in the bottom dialogue box
|
||||
Font.drawBox(0, 12, 20, 6)
|
||||
Font.draw("Which move should", 8, 14 * 8)
|
||||
Font.draw("be forgotten?", 8, 16 * 8)
|
||||
Font.draw(Strings("Which move should"), 8, 14 * 8)
|
||||
Font.draw(Strings("be forgotten?"), 8, 16 * 8)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ local Font = require("src.render.Font")
|
||||
local Runtime = require("src.mods.Runtime")
|
||||
local Sound = require("src.core.Sound")
|
||||
local Theme = require("src.ui.Theme")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local NamingScreen = {}
|
||||
NamingScreen.__index = NamingScreen
|
||||
@@ -64,7 +65,7 @@ function NamingScreen.new(game, opts)
|
||||
opts = opts or {}
|
||||
local self = setmetatable({}, NamingScreen)
|
||||
self.game = game
|
||||
self.title = opts.title or "YOUR NAME?"
|
||||
self.title = opts.title or Strings("YOUR NAME?")
|
||||
self.presets = opts.presets
|
||||
self.maxLen = opts.maxLen or 7
|
||||
self.default = opts.default
|
||||
@@ -78,7 +79,7 @@ end
|
||||
function NamingScreen:enter()
|
||||
if self.presets and #self.presets > 0 then
|
||||
local Menu = require("src.ui.Menu")
|
||||
local items = { { label = "NEW NAME" } }
|
||||
local items = { { label = Strings("NEW NAME") } }
|
||||
for _, preset in ipairs(self.presets) do
|
||||
table.insert(items, {
|
||||
label = preset,
|
||||
|
||||
+14
-7
@@ -7,12 +7,14 @@
|
||||
-- mod can insertBefore("name_player", ...) without counting indices.
|
||||
-- Calls onDone() after popping itself.
|
||||
|
||||
local Assets = require("src.render.Assets")
|
||||
local Sound = require("src.core.Sound")
|
||||
local Music = require("src.core.Music")
|
||||
local Logger = require("src.core.Logger")
|
||||
local Runtime = require("src.mods.Runtime")
|
||||
local TextBox = require("src.render.TextBox")
|
||||
local Font = require("src.render.Font")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local OakSpeech = {}
|
||||
OakSpeech.__index = OakSpeech
|
||||
@@ -51,9 +53,11 @@ local function textOr(game, key)
|
||||
return (t and t[key]) or FALLBACKS[key]
|
||||
end
|
||||
|
||||
-- through Assets.resolve so an enabled mod's overrides/ shadows these the
|
||||
-- same way it shadows every other generated asset
|
||||
local function tryImage(path)
|
||||
if not path then return nil end
|
||||
local ok, img = pcall(love.graphics.newImage, path)
|
||||
local ok, img = pcall(love.graphics.newImage, Assets.resolve(path))
|
||||
return ok and img or nil
|
||||
end
|
||||
|
||||
@@ -101,7 +105,9 @@ function OakSpeech.resolvePic(game, desc, speech)
|
||||
if speech and speech.playerPic and not desc.path then
|
||||
return speech.playerPic, false
|
||||
end
|
||||
return tryImage(desc.path or "assets/generated/trainer_card/red.png"), false
|
||||
if desc.path then return tryImage(desc.path), false end
|
||||
return tryImage(require("src.pokemon.Sprites").playerPath(
|
||||
game.data, "front", { kind = "intro" })), false
|
||||
elseif t == "image" then
|
||||
return tryImage(desc.path), desc.flip and true or false
|
||||
elseif t == "sprite" then
|
||||
@@ -140,7 +146,7 @@ function OakSpeech.defaultSteps(speech)
|
||||
id = "name_player",
|
||||
kind = "name",
|
||||
who = "player",
|
||||
title = "YOUR NAME?",
|
||||
title = Strings("YOUR NAME?"),
|
||||
presetsWho = "player",
|
||||
presetsFallback = { "RED", "ASH", "JACK" },
|
||||
},
|
||||
@@ -154,7 +160,7 @@ function OakSpeech.defaultSteps(speech)
|
||||
id = "name_rival",
|
||||
kind = "name",
|
||||
who = "rival",
|
||||
title = "HIS NAME?",
|
||||
title = Strings("HIS NAME?"),
|
||||
presetsWho = "rival",
|
||||
presetsFallback = { "BLUE", "GARY", "JOHN" },
|
||||
},
|
||||
@@ -220,7 +226,8 @@ function OakSpeech.new(game, onDone)
|
||||
self.nameLen = constants.playerNameLength or 7
|
||||
-- RedPicFront (gfx/player/red.png, shared with the trainer card) and
|
||||
-- the ShrinkPic1/ShrinkPic2 frames (gfx/player/shrink{1,2}.png)
|
||||
self.playerPic = tryImage("assets/generated/trainer_card/red.png")
|
||||
self.playerPic = tryImage(require("src.pokemon.Sprites").playerPath(
|
||||
game.data, "front", { kind = "intro" }))
|
||||
self.shrinkPic1 = tryImage(oakGfx.shrink1
|
||||
or "assets/generated/intro/shrink1.png")
|
||||
self.shrinkPic2 = tryImage(oakGfx.shrink2
|
||||
@@ -337,7 +344,7 @@ function OakSpeech:runStep(step)
|
||||
self.picFlip = true
|
||||
self:revealPic("wipe", function()
|
||||
Sound.playCry(self.game.data, self.demoSpecies)
|
||||
self:say("_OakSpeechText2A", function() self:advance() end)
|
||||
self:say(Strings("_OakSpeechText2A"), function() self:advance() end)
|
||||
end)
|
||||
elseif kind == "name" then
|
||||
local who = step.who or "player"
|
||||
@@ -345,7 +352,7 @@ function OakSpeech:runStep(step)
|
||||
or namePresets(self.game, step.presetsWho or who,
|
||||
step.presetsFallback or { "RED" })
|
||||
require("src.ui.Screens").push(self.game, "NamingScreen", {
|
||||
title = step.title or (who == "rival" and "HIS NAME?" or "YOUR NAME?"),
|
||||
title = step.title or (who == "rival" and "HIS NAME?" or Strings("YOUR NAME?")),
|
||||
presets = presets,
|
||||
maxLen = step.maxLen or self.nameLen,
|
||||
onDone = function(name)
|
||||
|
||||
+19
-18
@@ -22,6 +22,7 @@ local Logger = require("src.core.Logger")
|
||||
local Runtime = require("src.mods.Runtime")
|
||||
local OptionRows = require("src.ui.OptionRows")
|
||||
local Renderer = require("src.render.Renderer")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local OptionsMenu = {}
|
||||
OptionsMenu.__index = OptionsMenu
|
||||
@@ -116,14 +117,14 @@ local function sameRows(_, rows) return rows end
|
||||
-- ladder's, so the save.options mutations are unchanged
|
||||
local function buildRows(game)
|
||||
local rows = {
|
||||
{ id = "textSpeed", label = "TEXT SPEED",
|
||||
{ id = "textSpeed", label = Strings("TEXT SPEED"),
|
||||
value = function(g) return SPEEDS[speedIndex(g)][2] end,
|
||||
step = function(g)
|
||||
local i = speedIndex(g) % #SPEEDS + 1
|
||||
g.save.options.textSpeed = SPEEDS[i][1]
|
||||
return true
|
||||
end },
|
||||
{ id = "animations", label = "BATTLE ANIMATION",
|
||||
{ id = "animations", label = Strings("BATTLE ANIMATION"),
|
||||
value = function(g)
|
||||
return g.save.options.animations == false and "OFF" or "ON"
|
||||
end,
|
||||
@@ -132,7 +133,7 @@ local function buildRows(game)
|
||||
o.animations = o.animations == false and true or false
|
||||
return true
|
||||
end },
|
||||
{ id = "battleStyle", label = "BATTLE STYLE",
|
||||
{ id = "battleStyle", label = Strings("BATTLE STYLE"),
|
||||
value = function(g)
|
||||
return g.save.options.battleStyle == "set" and "SET" or "SHIFT"
|
||||
end,
|
||||
@@ -141,7 +142,7 @@ local function buildRows(game)
|
||||
o.battleStyle = o.battleStyle == "set" and "shift" or "set"
|
||||
return true
|
||||
end },
|
||||
{ id = "ruleset", label = "RULESET",
|
||||
{ id = "ruleset", label = Strings("RULESET"),
|
||||
value = function(g) return rulesetName(g) end,
|
||||
step = function(g, dir)
|
||||
local ids = rulesetIds(g)
|
||||
@@ -150,7 +151,7 @@ local function buildRows(game)
|
||||
g.save.options.ruleset = ids[wrapIndex(i - 1 + dir, #ids) + 1]
|
||||
return true
|
||||
end },
|
||||
{ id = "musicVol", label = "MUSIC VOL",
|
||||
{ id = "musicVol", label = Strings("MUSIC VOL"),
|
||||
value = function(g) return volLabel(g.save.options.musicVol) end,
|
||||
step = function(g, dir)
|
||||
local o = g.save.options
|
||||
@@ -158,7 +159,7 @@ local function buildRows(game)
|
||||
require("src.core.Music").setVolumeLevel(o.musicVol)
|
||||
return true
|
||||
end },
|
||||
{ id = "sfxVol", label = "SFX VOL",
|
||||
{ id = "sfxVol", label = Strings("SFX VOL"),
|
||||
value = function(g) return volLabel(g.save.options.sfxVol) end,
|
||||
step = function(g, dir)
|
||||
local o = g.save.options
|
||||
@@ -166,7 +167,7 @@ local function buildRows(game)
|
||||
require("src.core.Sound").setVolumeLevel(o.sfxVol)
|
||||
return true
|
||||
end },
|
||||
{ id = "musicFilter", label = "MUSIC FILTER",
|
||||
{ id = "musicFilter", label = Strings("MUSIC FILTER"),
|
||||
value = function(g)
|
||||
return FILTERS[(g.save.options.musicFilter or 0) + 1]
|
||||
end,
|
||||
@@ -176,7 +177,7 @@ local function buildRows(game)
|
||||
require("src.core.Music").setFilterLevel(o.musicFilter)
|
||||
return true
|
||||
end },
|
||||
{ id = "colors", label = "COLORS",
|
||||
{ id = "colors", label = Strings("COLORS"),
|
||||
value = function(g)
|
||||
return PaletteFX.modeLabel(g.save.options.colors or "gbc")
|
||||
end,
|
||||
@@ -188,7 +189,7 @@ local function buildRows(game)
|
||||
PaletteFX.setMode(o.colors)
|
||||
return true
|
||||
end },
|
||||
{ id = "tilt", label = "TILT",
|
||||
{ id = "tilt", label = Strings("TILT"),
|
||||
value = function(g) return Tilt.levelLabel(g.save.options.tilt or 0) end,
|
||||
step = function(g, dir)
|
||||
local o = g.save.options
|
||||
@@ -205,7 +206,7 @@ local function buildRows(game)
|
||||
end
|
||||
return true
|
||||
end },
|
||||
{ id = "gbcfx", label = "GBC FX",
|
||||
{ id = "gbcfx", label = Strings("GBC FX"),
|
||||
value = function(g)
|
||||
return GBCFX.levelLabel(g.save.options.gbcfx or 0)
|
||||
end,
|
||||
@@ -215,7 +216,7 @@ local function buildRows(game)
|
||||
GBCFX.setLevel(o.gbcfx)
|
||||
return true
|
||||
end },
|
||||
{ id = "zoom", label = "ZOOM",
|
||||
{ id = "zoom", label = Strings("ZOOM"),
|
||||
value = function(g)
|
||||
return Zoom.offsetLabel(g.save.options.zoom or 0)
|
||||
end,
|
||||
@@ -230,7 +231,7 @@ local function buildRows(game)
|
||||
Zoom.offset = off
|
||||
return true
|
||||
end },
|
||||
{ id = "voidFill", label = "VOID FILL",
|
||||
{ id = "voidFill", label = Strings("VOID FILL"),
|
||||
value = function(g)
|
||||
return TileRenderer.voidFillLabel(g.save.options.voidFill)
|
||||
end,
|
||||
@@ -246,7 +247,7 @@ local function buildRows(game)
|
||||
TileRenderer.setVoidFill(o.voidFill)
|
||||
return true
|
||||
end },
|
||||
{ id = "videoMode", label = "VIDEO MODE",
|
||||
{ id = "videoMode", label = Strings("VIDEO MODE"),
|
||||
value = function(g)
|
||||
return VideoMode.modeLabel(g.save.options.videoMode)
|
||||
end,
|
||||
@@ -259,7 +260,7 @@ local function buildRows(game)
|
||||
-- hard render cap (issue #88): bounds the present rate so a
|
||||
-- driver-forced vsync-off run cannot spin at thousands of FPS. Logic
|
||||
-- is fixed-step off dt, so this touches presentation only.
|
||||
{ id = "fpsCap", label = "MAX FPS",
|
||||
{ id = "fpsCap", label = Strings("MAX FPS"),
|
||||
value = function(g)
|
||||
return FrameCap.label(g.save.options.fpsCap)
|
||||
end,
|
||||
@@ -271,7 +272,7 @@ local function buildRows(game)
|
||||
end },
|
||||
-- fast-forward the logic clock only; music and sfx keep their tempo
|
||||
-- (src/core/GameSpeed.lua), so this is safe to leave on
|
||||
{ id = "speed", label = "GAME SPEED",
|
||||
{ id = "speed", label = Strings("GAME SPEED"),
|
||||
value = function(g)
|
||||
return GameSpeed.levelLabel(g.save.options.speed)
|
||||
end,
|
||||
@@ -282,17 +283,17 @@ local function buildRows(game)
|
||||
end },
|
||||
-- the manager's discoverable home (18-mod-manager-ux); inert until
|
||||
-- opened, so the row costs a vanilla install nothing
|
||||
{ id = "mods", label = "MODS",
|
||||
{ id = "mods", label = Strings("MODS"),
|
||||
value = function(g)
|
||||
local status = g.modStatus or {}
|
||||
return ("%d INSTALLED"):format(#(status.available or {}))
|
||||
return Strings("%d INSTALLED", #(status.available or {}))
|
||||
end,
|
||||
activate = function(g)
|
||||
require("src.ui.Screens").push(g, "ManagerState")
|
||||
end },
|
||||
-- rebinding UI (gap C2, 12-ui-extensibility 4.4); captured inputs
|
||||
-- live in options.bindings, so the row costs a vanilla install nothing
|
||||
{ id = "controls", label = "CONTROLS",
|
||||
{ id = "controls", label = Strings("CONTROLS"),
|
||||
activate = function(g)
|
||||
require("src.ui.Screens").push(g, "BindingsMenu")
|
||||
end },
|
||||
|
||||
+39
-33
@@ -17,6 +17,7 @@ local Screens = require("src.ui.Screens")
|
||||
local Theme = require("src.ui.Theme")
|
||||
local FieldDefaults = require("src.world.FieldDefaults")
|
||||
local Map = require("src.world.Map")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local PartyMenu = {}
|
||||
PartyMenu.__index = PartyMenu
|
||||
@@ -204,7 +205,7 @@ function PartyMenu:update(dt)
|
||||
self.game.save.flashLit = true
|
||||
self.game.stack:push(TextBox.new(self.game,
|
||||
self.game.data.text._FlashLightsAreaText
|
||||
or "A blinding FLASH\nlights the area!", function()
|
||||
or Strings("A blinding FLASH\nlights the area!"), function()
|
||||
self.game.stack:push(Transition.whiteFlash(self.game))
|
||||
end))
|
||||
return
|
||||
@@ -247,7 +248,7 @@ function PartyMenu:update(dt)
|
||||
current = "_CurrentTooFastText",
|
||||
no_place = "_SurfingNoPlaceToGetOffText" })[reason]
|
||||
or "_NoSurfingHereText"
|
||||
local txt = (self.game.data.text[key] or "No SURFing here!")
|
||||
local txt = (self.game.data.text[key] or Strings("No SURFing here!"))
|
||||
:gsub("{RAM:wNameBuffer}", mon.nickname or def.name)
|
||||
if reason == "no_place" then
|
||||
-- .cannotStopSurfing prints _SurfingNoPlaceToGetOffText but
|
||||
@@ -278,7 +279,7 @@ function PartyMenu:update(dt)
|
||||
local def = self.game.data.pokemon[mon.species]
|
||||
local key = (reason == "no_badge") and "_NewBadgeRequiredText"
|
||||
or "_NothingToCutText"
|
||||
local txt = (self.game.data.text[key] or "Nothing to CUT!")
|
||||
local txt = (self.game.data.text[key] or Strings("Nothing to CUT!"))
|
||||
:gsub("{RAM:wNameBuffer}", mon.nickname or def.name)
|
||||
self.game.stack:push(TextBox.new(self.game, txt))
|
||||
return -- .loop: submenu stays open behind the message
|
||||
@@ -300,9 +301,9 @@ function PartyMenu:update(dt)
|
||||
self.game.stack:pop() -- close the party menu (jp .goBackToMap)
|
||||
ow.strengthActive = true
|
||||
local t1 = (self.game.data.text._UsedStrengthText
|
||||
or "{RAM:wNameBuffer} used\nSTRENGTH."):gsub("{RAM:wNameBuffer}", name)
|
||||
or Strings("{RAM:wNameBuffer} used\nSTRENGTH.")):gsub("{RAM:wNameBuffer}", name)
|
||||
local t2 = (self.game.data.text._CanMoveBouldersText
|
||||
or "{RAM:wNameBuffer} can\nmove boulders."):gsub("{RAM:wNameBuffer}", name)
|
||||
or Strings("{RAM:wNameBuffer} can\nmove boulders.")):gsub("{RAM:wNameBuffer}", name)
|
||||
self.game.stack:push(TextBox.new(self.game, t1, function()
|
||||
self.game.stack:push(TextBox.new(self.game, t2, function()
|
||||
self.game.stack:push(Transition.whiteFlash(self.game))
|
||||
@@ -348,7 +349,7 @@ function PartyMenu:update(dt)
|
||||
or user.hp <= heal then
|
||||
self.softboiledFrom = nil
|
||||
local TextBox = require("src.render.TextBox")
|
||||
self.game.stack:push(TextBox.new(self.game, "It won't have\nany effect."))
|
||||
self.game.stack:push(TextBox.new(self.game, Strings("It won't have\nany effect.")))
|
||||
else
|
||||
user.hp = user.hp - heal
|
||||
mon.hp = math.min(mon.stats.hp, mon.hp + heal)
|
||||
@@ -357,7 +358,7 @@ function PartyMenu:update(dt)
|
||||
local def = self.game.data.pokemon[mon.species]
|
||||
local TextBox = require("src.render.TextBox")
|
||||
self.game.stack:push(TextBox.new(self.game,
|
||||
("%s's HP\nwas restored!"):format(mon.nickname or def.name)))
|
||||
Strings("%s's HP\nwas restored!", mon.nickname or def.name)))
|
||||
end
|
||||
elseif self.swapFrom then
|
||||
if self.swapFrom ~= self.index then
|
||||
@@ -375,14 +376,14 @@ function PartyMenu:update(dt)
|
||||
local ow = self.game.overworld
|
||||
if self.battle and self.onSwitch then
|
||||
-- SwitchStatsCancelText (core.asm PartyMenuOrRockOrRun)
|
||||
items = { { label = "SWITCH", action = "battle_switch" },
|
||||
{ label = "STATS", action = "stats" },
|
||||
{ label = "CANCEL", action = "cancel" } }
|
||||
items = { { label = Strings("SWITCH"), action = "battle_switch" },
|
||||
{ label = Strings("STATS"), action = "stats" },
|
||||
{ label = Strings("CANCEL"), action = "cancel" } }
|
||||
else
|
||||
-- STATS/SWITCH plus this mon's field moves (start_sub_menus.asm
|
||||
-- builds the same dynamic list)
|
||||
items = { { label = "STATS", action = "stats" },
|
||||
{ label = "SWITCH", action = "switch" } }
|
||||
items = { { label = Strings("STATS"), action = "stats" },
|
||||
{ label = Strings("SWITCH"), action = "switch" } }
|
||||
-- Field moves (HMs/TMs) are usable out of battle even when the mon
|
||||
-- is fainted -- Gen 1 does not require HP for Cut/Fly/Surf/etc.
|
||||
-- Battle still excludes this list via `not self.battle`. Softboiled
|
||||
@@ -395,35 +396,35 @@ function PartyMenu:update(dt)
|
||||
for _, mv in ipairs(mon.moves) do
|
||||
if mv.id == "FLY" and outside
|
||||
and self.game.save.inventory.THUNDERBADGE then
|
||||
table.insert(items, { label = "FLY", action = "fly" })
|
||||
table.insert(items, { label = Strings("FLY"), action = "fly" })
|
||||
elseif mv.id == "FLASH" and ow.dark
|
||||
and self.game.save.inventory.BOULDERBADGE then
|
||||
table.insert(items, { label = "FLASH", action = "flash" })
|
||||
table.insert(items, { label = Strings("FLASH"), action = "flash" })
|
||||
elseif mv.id == "CUT" and self.game.save.inventory.CASCADEBADGE then
|
||||
-- CUT/SURF/STRENGTH are party-menu field moves too
|
||||
-- (start_sub_menus.asm .outOfBattleMovePointers); listed here
|
||||
-- with the same list-time badge filter this file already uses
|
||||
-- for FLY/FLASH. The facing-tile/activation check happens on
|
||||
-- selection (useCutFieldMove/useSurfFieldMove).
|
||||
table.insert(items, { label = "CUT", action = "cut" })
|
||||
table.insert(items, { label = Strings("CUT"), action = "cut" })
|
||||
elseif mv.id == "SURF" and self.game.save.inventory.SOULBADGE then
|
||||
table.insert(items, { label = "SURF", action = "surf" })
|
||||
table.insert(items, { label = Strings("SURF"), action = "surf" })
|
||||
elseif mv.id == "STRENGTH" and self.game.save.inventory.RAINBOWBADGE then
|
||||
table.insert(items, { label = "STRENGTH", action = "strength" })
|
||||
table.insert(items, { label = Strings("STRENGTH"), action = "strength" })
|
||||
elseif mv.id == "SOFTBOILED" then
|
||||
table.insert(items, { label = "SOFTBOILED", action = "softboiled" })
|
||||
table.insert(items, { label = Strings("SOFTBOILED"), action = "softboiled" })
|
||||
elseif mv.id == "TELEPORT" and outside then
|
||||
-- TELEPORT works only OUTDOORS (start_sub_menus.asm
|
||||
-- .teleport -> CheckIfInOutsideMap); dark maps don't
|
||||
-- block it
|
||||
table.insert(items, { label = "TELEPORT", action = "escape" })
|
||||
table.insert(items, { label = Strings("TELEPORT"), action = "escape" })
|
||||
elseif mv.id == "DIG" and DIG_TILESETS[ow.map.def.tileset]
|
||||
and ow.map.id ~= "AGATHAS_ROOM" then
|
||||
-- DIG runs ItemUseEscapeRope (.dig sets wCurItem =
|
||||
-- ESCAPE_ROPE): usable in the dungeon tilesets of
|
||||
-- escape_rope_tilesets.asm minus Agatha's room, even in
|
||||
-- the dark (Rock Tunnel)
|
||||
table.insert(items, { label = "DIG", action = "escape" })
|
||||
table.insert(items, { label = Strings("DIG"), action = "escape" })
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -456,13 +457,13 @@ function PartyMenu:bottomMessage()
|
||||
return "Use on which one?"
|
||||
elseif self.tmhm then
|
||||
return self.game.data.text._PartyMenuUseTMText
|
||||
or "Use TM on which\nPOKéMON?"
|
||||
or Strings("Use TM on which\nPOKéMON?")
|
||||
elseif self.battle then
|
||||
return self.game.data.text._PartyMenuBattleText
|
||||
or "Bring out which\nPOKéMON?"
|
||||
or Strings("Bring out which\nPOKéMON?")
|
||||
else
|
||||
return self.game.data.text._PartyMenuNormalText
|
||||
or "Choose a POKéMON."
|
||||
or Strings("Choose a POKéMON.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -480,7 +481,7 @@ function PartyMenu:draw()
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
local party = self.party or self.game.save.party
|
||||
if #party == 0 then
|
||||
Font.draw("No POKéMON!", 16, 64)
|
||||
Font.draw(Strings("No POKéMON!"), 16, 64)
|
||||
end
|
||||
local HudTiles = require("src.render.HudTiles")
|
||||
for i, mon in ipairs(party) do
|
||||
@@ -512,13 +513,13 @@ function PartyMenu:draw()
|
||||
end
|
||||
-- right-aligned so the shorter "ABLE" shares "NOT ABLE"'s right edge
|
||||
if can then
|
||||
Font.draw("ABLE", 120, y + 8)
|
||||
Font.draw(Strings("ABLE"), 120, y + 8)
|
||||
else
|
||||
Font.draw("NOT ABLE", 88, y + 8)
|
||||
Font.draw(Strings("NOT ABLE"), 88, y + 8)
|
||||
end
|
||||
else
|
||||
if mon.hp <= 0 then
|
||||
Font.draw("FNT", 136, y)
|
||||
Font.draw(Strings("FNT"), 136, y)
|
||||
elseif mon.status then
|
||||
Font.draw(mon.status, 136, y)
|
||||
end
|
||||
@@ -528,17 +529,22 @@ function PartyMenu:draw()
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw(("%3d/%3d"):format(mon.hp, mon.stats.hp), 104, y + 8)
|
||||
end
|
||||
-- home/pokemon.asm PartyMenuInit seeds wTopMenuItemY/X with 1/0, so the
|
||||
-- cursor sits on the entry's *second* tile row (the level/HP line),
|
||||
-- level with the middle of the two-row icon -- not on the name row that
|
||||
-- entryY returns. Drawing it at y put it a tile too high (#278).
|
||||
local cursorY = y + 8
|
||||
if i == self.index then
|
||||
Font.drawCode(Theme.cursor, 0, y)
|
||||
Font.drawCode(Theme.cursor, 0, cursorY)
|
||||
end
|
||||
if i == self.swapFrom or i == self.softboiledFrom then
|
||||
Font.drawCode(Theme.cursorHollow, 0, y) -- the unfilled swap arrow
|
||||
Font.drawCode(Theme.cursorHollow, 0, cursorY) -- the unfilled swap arrow
|
||||
end
|
||||
end
|
||||
if self.swapFrom then
|
||||
Font.draw("Move to where?", 8, 136)
|
||||
Font.draw(Strings("Move to where?"), 8, 136)
|
||||
elseif self.softboiledFrom then
|
||||
Font.draw("Use on which one?", 8, 136)
|
||||
Font.draw(Strings("Use on which one?"), 8, 136)
|
||||
elseif self.tmhm then
|
||||
-- "Use TM on which\nPOKeMON?" in the standard bottom text box
|
||||
-- (party_menu.asm keeps the message box for the TM/HM menu); box + line
|
||||
@@ -546,14 +552,14 @@ function PartyMenu:draw()
|
||||
Font.drawBox(0, 12, 20, 6)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
local prompt = self.game.data.text._PartyMenuUseTMText
|
||||
or "Use TM on which\nPOKéMON?"
|
||||
or Strings("Use TM on which\nPOKéMON?")
|
||||
local ly = 112
|
||||
for line in (prompt .. "\n"):gmatch("([^\n]*)\n") do
|
||||
Font.draw(line, 8, ly)
|
||||
ly = ly + 16
|
||||
end
|
||||
elseif self.pickOnly then
|
||||
Font.draw("Use on which one?", 8, 136)
|
||||
Font.draw(Strings("Use on which one?"), 8, 136)
|
||||
else
|
||||
-- default field party menu (StartMenu) and the battle voluntary-switch
|
||||
-- (BattleState:openParty): Gen1 prints PartyMenuNormalText / PartyMenuBattleText
|
||||
|
||||
+12
-11
@@ -10,6 +10,7 @@ local ChoiceBox = require("src.ui.ChoiceBox")
|
||||
local ListMenu = require("src.ui.ListMenu")
|
||||
local Menu = require("src.ui.Menu")
|
||||
local Sound = require("src.core.Sound")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local PlayerPC = {}
|
||||
|
||||
@@ -76,14 +77,14 @@ local function withdraw(game)
|
||||
askQuantity(game, list, pc[item.value] or 1, item.value, function(qty)
|
||||
local Bag = require("src.inventory.Bag")
|
||||
if not Bag.add(game.save, item.value, qty) then
|
||||
list.footer = "You can't carry\nany more items."
|
||||
list.footer = Strings("You can't carry\nany more items.")
|
||||
return
|
||||
end
|
||||
pc[item.value] = pc[item.value] - qty
|
||||
if pc[item.value] <= 0 then pc[item.value] = nil end
|
||||
refreshRow(list, pc, item.value)
|
||||
Sound.play(game.data, "Withdraw_Deposit")
|
||||
list.footer = ("Withdrew\n%s."):format(itemName(game, item.value))
|
||||
list.footer = Strings("Withdrew\n%s.", itemName(game, item.value))
|
||||
end)
|
||||
end,
|
||||
}))
|
||||
@@ -112,14 +113,14 @@ local function deposit(game)
|
||||
onChoose = function(item, list)
|
||||
askQuantity(game, list, inv[item.value] or 1, item.value, function(qty)
|
||||
if pcFull(game, pc, item.value) then
|
||||
list.footer = "No room left to\nstore items."
|
||||
list.footer = Strings("No room left to\nstore items.")
|
||||
return
|
||||
end
|
||||
require("src.inventory.Bag").remove(game.save, item.value, qty)
|
||||
pc[item.value] = (pc[item.value] or 0) + qty
|
||||
refreshRow(list, inv, item.value)
|
||||
Sound.play(game.data, "Withdraw_Deposit")
|
||||
list.footer = ("%s was\nstored via PC."):format(itemName(game, item.value))
|
||||
list.footer = Strings("%s was\nstored via PC.", itemName(game, item.value))
|
||||
end)
|
||||
end,
|
||||
}))
|
||||
@@ -132,7 +133,7 @@ local function toss(game)
|
||||
onChoose = function(item, list)
|
||||
local def = game.data.items[item.value]
|
||||
if (def and def.keyItem) or item.value:find("^HM_") then
|
||||
list.footer = "That's too impor-\ntant to toss!"
|
||||
list.footer = Strings("That's too impor-\ntant to toss!")
|
||||
return
|
||||
end
|
||||
local QuantityBox = require("src.ui.QuantityBox")
|
||||
@@ -140,13 +141,13 @@ local function toss(game)
|
||||
max = pc[item.value] or 1,
|
||||
onDone = function(qty)
|
||||
if not qty then return end
|
||||
list.footer = ("Toss %s?"):format(itemName(game, item.value))
|
||||
list.footer = Strings("Toss %s?", itemName(game, item.value))
|
||||
game.stack:push(ChoiceBox.new(game, function(yes)
|
||||
if yes then
|
||||
pc[item.value] = pc[item.value] - qty
|
||||
if pc[item.value] <= 0 then pc[item.value] = nil end
|
||||
refreshRow(list, pc, item.value)
|
||||
list.footer = ("Threw away %s."):format(itemName(game, item.value))
|
||||
list.footer = Strings("Threw away %s.", itemName(game, item.value))
|
||||
else
|
||||
list.footer = nil
|
||||
end
|
||||
@@ -163,10 +164,10 @@ function PlayerPC.new(game)
|
||||
-- keepOpen so B in the item lists returns here instead of dropping the
|
||||
-- whole PC session (players_pc.asm re-shows the PC menu); same pattern
|
||||
-- as BoxMenu's rows
|
||||
{ label = "WITHDRAW ITEM", keepOpen = true, onSelect = function() withdraw(game) end },
|
||||
{ label = "DEPOSIT ITEM", keepOpen = true, onSelect = function() deposit(game) end },
|
||||
{ label = "TOSS ITEM", keepOpen = true, onSelect = function() toss(game) end },
|
||||
{ label = "LOG OFF" },
|
||||
{ label = Strings("WITHDRAW ITEM"), keepOpen = true, onSelect = function() withdraw(game) end },
|
||||
{ label = Strings("DEPOSIT ITEM"), keepOpen = true, onSelect = function() deposit(game) end },
|
||||
{ label = Strings("TOSS ITEM"), keepOpen = true, onSelect = function() toss(game) end },
|
||||
{ label = Strings("LOG OFF") },
|
||||
-- silent PC session (BIT_NO_MENU_BUTTON_SOUND); players_pc.asm
|
||||
-- PlayersPCMenu TextBoxBorder (0,0) b=8 c=14 → 16x10
|
||||
}, { tx = 0, ty = 0, tw = 16, th = 10, noSound = true })
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
-- Minimal Pokédex: dex-ordered list with seen/owned markers.
|
||||
|
||||
local ListMenu = require("src.ui.ListMenu")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local PokedexMenu = {}
|
||||
|
||||
@@ -46,7 +47,7 @@ function PokedexMenu.new(game, opts)
|
||||
end
|
||||
end
|
||||
local list = ListMenu.new(game, "POKéDEX", items, {
|
||||
footer = ("SEEN %d OWNED %d"):format(seen, owned),
|
||||
footer = Strings("SEEN %d OWNED %d", seen, owned),
|
||||
pageJump = true, -- Left/Right page jumps like the original
|
||||
onCancel = opts.onCancel, -- B returns to the start menu when opened from it
|
||||
onChoose = function(item)
|
||||
@@ -57,16 +58,16 @@ function PokedexMenu.new(game, opts)
|
||||
local Menu = require("src.ui.Menu")
|
||||
local Screens = require("src.ui.Screens")
|
||||
game.stack:push(Menu.new(game, {
|
||||
{ label = "DATA", onSelect = function()
|
||||
{ label = Strings("DATA"), onSelect = function()
|
||||
Screens.push(game, "DexEntryMenu", item.value)
|
||||
end },
|
||||
{ label = "CRY", keepOpen = true, onSelect = function()
|
||||
{ label = Strings("CRY"), keepOpen = true, onSelect = function()
|
||||
require("src.core.Sound").playCry(game.data, item.value)
|
||||
end },
|
||||
{ label = "AREA", onSelect = function()
|
||||
{ label = Strings("AREA"), onSelect = function()
|
||||
Screens.push(game, "TownMap", { nestSpecies = item.value })
|
||||
end },
|
||||
{ label = "QUIT" },
|
||||
{ label = Strings("QUIT") },
|
||||
}, { tx = 12, ty = 8, tw = 8, th = 10 }))
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
local Font = require("src.render.Font")
|
||||
local SaveData = require("src.core.SaveData")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local QuarantineReport = {}
|
||||
QuarantineReport.__index = QuarantineReport
|
||||
@@ -38,12 +39,12 @@ local function buildLines(report, meta)
|
||||
end
|
||||
local rows = {}
|
||||
for _, mon in ipairs(report.lostMons or {}) do
|
||||
rows[#rows + 1] = ("%s (%s)"):format(mon.species or "?", mon.from or "?")
|
||||
rows[#rows + 1] = Strings("%s (%s)", mon.species or "?", mon.from or "?")
|
||||
end
|
||||
section(lines, "Moved to LOST box:", rows)
|
||||
rows = {}
|
||||
for _, item in ipairs(report.lostItems or {}) do
|
||||
rows[#rows + 1] = ("%s x%d"):format(item.id or "?", item.count or 1)
|
||||
rows[#rows + 1] = Strings("%s x%d", item.id or "?", item.count or 1)
|
||||
end
|
||||
section(lines, "Items removed:", rows)
|
||||
rows = {}
|
||||
@@ -51,16 +52,16 @@ local function buildLines(report, meta)
|
||||
if map.to then
|
||||
rows[#rows + 1] = ("%s>%s"):format(map.id or "?", map.to)
|
||||
else
|
||||
rows[#rows + 1] = ("%s (%s)"):format(map.id or "?", map.field or "?")
|
||||
rows[#rows + 1] = Strings("%s (%s)", map.id or "?", map.field or "?")
|
||||
end
|
||||
end
|
||||
section(lines, "Location reset:", rows)
|
||||
rows = {}
|
||||
for _, mon in ipairs(report.restoredMons or {}) do
|
||||
rows[#rows + 1] = ("%s to box %d"):format(mon.species or "?", mon.box or 0)
|
||||
rows[#rows + 1] = Strings("%s to box %d", mon.species or "?", mon.box or 0)
|
||||
end
|
||||
for _, item in ipairs(report.restoredItems or {}) do
|
||||
rows[#rows + 1] = ("%s x%d"):format(item.id or "?", item.count or 1)
|
||||
rows[#rows + 1] = Strings("%s x%d", item.id or "?", item.count or 1)
|
||||
end
|
||||
section(lines, "Restored:", rows)
|
||||
local notice = SaveData.modsDiffNotice(report.modsDiff, meta)
|
||||
@@ -113,7 +114,7 @@ function QuarantineReport:draw()
|
||||
love.graphics.rectangle("fill", 0, 0, 160, 144)
|
||||
Font.drawBox(0, 0, 20, 18)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("LOAD REPORT", 8, 8)
|
||||
Font.draw(Strings("LOAD REPORT"), 8, 8)
|
||||
for row = 1, VISIBLE do
|
||||
local line = self.lines[self.offset + row]
|
||||
if line then Font.draw(line, 8, 12 + row * 8) end
|
||||
@@ -121,7 +122,7 @@ function QuarantineReport:draw()
|
||||
if self.offset < self:maxOffset() then
|
||||
Font.drawCode(require("src.ui.Theme").moreArrow, 144, 124)
|
||||
end
|
||||
Font.draw("A:CONTINUE", 8, 130)
|
||||
Font.draw(Strings("A:CONTINUE"), 8, 130)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
|
||||
+10
-9
@@ -12,6 +12,7 @@ local ChoiceBox = require("src.ui.ChoiceBox")
|
||||
local ListMenu = require("src.ui.ListMenu")
|
||||
local Menu = require("src.ui.Menu")
|
||||
local QuantityBox = require("src.ui.QuantityBox")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local ShopMenu = {}
|
||||
|
||||
@@ -33,7 +34,7 @@ local function buy(game, stock)
|
||||
end
|
||||
local greet = txt(game, "_PokemartBuyingGreetingText", "Take your time.")
|
||||
local notEnough = txt(game, "_PokemartNotEnoughMoneyText",
|
||||
"You don't have\nenough money.")
|
||||
Strings("You don't have\nenough money."))
|
||||
local list
|
||||
list = ListMenu.new(game, "BUY", items, {
|
||||
dialogue = true,
|
||||
@@ -56,7 +57,7 @@ local function buy(game, stock)
|
||||
end
|
||||
local cost = qty * def.price
|
||||
-- _PokemartTellBuyPriceText + yes/no confirm
|
||||
list.footer = ("%s?\nThat will be\n¥%d. OK?"):format(def.name, cost)
|
||||
list.footer = Strings("%s?\nThat will be\n¥%d. OK?", def.name, cost)
|
||||
game.stack:push(ChoiceBox.new(game, function(yes)
|
||||
if not yes then
|
||||
list.footer = greet
|
||||
@@ -68,13 +69,13 @@ local function buy(game, stock)
|
||||
end
|
||||
if not Bag.add(game.save, item.value, qty) then
|
||||
list.footer = txt(game, "_PokemartItemBagFullText",
|
||||
"You can't carry\nany more items.")
|
||||
Strings("You can't carry\nany more items."))
|
||||
return
|
||||
end
|
||||
require("src.core.Sound").play(game.data, "Purchase")
|
||||
game.save.money = game.save.money - cost
|
||||
list.footer = txt(game, "_PokemartBoughtItemText",
|
||||
"Here you are!\nThank you!")
|
||||
Strings("Here you are!\nThank you!"))
|
||||
end))
|
||||
end,
|
||||
}))
|
||||
@@ -112,7 +113,7 @@ local function sell(game)
|
||||
-- ITEM_NONE "0" from Blue's House before that pickup was fixed (#11).
|
||||
if not def or def.keyItem or item.value:find("^HM_") then
|
||||
list.footer = txt(game, "_PokemartUnsellableItemText",
|
||||
"I can't put a\nprice on that.")
|
||||
Strings("I can't put a\nprice on that."))
|
||||
return
|
||||
end
|
||||
local unit = math.floor(def.price / 2)
|
||||
@@ -125,7 +126,7 @@ local function sell(game)
|
||||
return
|
||||
end
|
||||
-- _PokemartTellSellPriceText + yes/no confirm
|
||||
list.footer = ("I can pay you\n¥%d for that."):format(unit * qty)
|
||||
list.footer = Strings("I can pay you\n¥%d for that.", unit * qty)
|
||||
game.stack:push(ChoiceBox.new(game, function(yes)
|
||||
if not yes then
|
||||
list.footer = greet
|
||||
@@ -152,9 +153,9 @@ function ShopMenu.new(game, stock, onQuit)
|
||||
-- keepOpen: the mart menu stays underneath its list so closing the
|
||||
-- list lands back here; only QUIT (or B) leaves and fires onQuit
|
||||
local menu = Menu.new(game, {
|
||||
{ label = "BUY", keepOpen = true, onSelect = function() buy(game, stock) end },
|
||||
{ label = "SELL", keepOpen = true, onSelect = function() sell(game) end },
|
||||
{ label = "QUIT", onSelect = onQuit },
|
||||
{ label = Strings("BUY"), keepOpen = true, onSelect = function() buy(game, stock) end },
|
||||
{ label = Strings("SELL"), keepOpen = true, onSelect = function() sell(game) end },
|
||||
{ label = Strings("QUIT"), onSelect = onQuit },
|
||||
}, { tx = 0, ty = 0, tw = 8, th = 8 })
|
||||
menu.onCancel = onQuit
|
||||
return menu
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
local Font = require("src.render.Font")
|
||||
local Sound = require("src.core.Sound")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local SlotMachine = {}
|
||||
SlotMachine.__index = SlotMachine
|
||||
@@ -356,7 +357,7 @@ function SlotMachine:resolveWin(win)
|
||||
-- SlotReward300Func prints "Yeah!" (text_pause) before the flash; the port
|
||||
-- shows it in the box while the screen flashes. LinedUpText follows.
|
||||
self.yeah = (sym == "7")
|
||||
self.message = ("%s lined up!\nScored %d coins!"):format(sym, pay)
|
||||
self.message = Strings("%s lined up!\nScored %d coins!", sym, pay)
|
||||
-- .flashScreenLoop: flip rBGP, wait 5 frames, b times. The coins are not
|
||||
-- credited until the player dismisses the "lined up" text (see startPayout).
|
||||
self.stage = "flash"
|
||||
@@ -394,7 +395,7 @@ end
|
||||
-- delay then CloseTextDisplay), otherwise ask "One more go?".
|
||||
function SlotMachine:afterSpin()
|
||||
if coins(self) == 0 then
|
||||
self.message = "Darn!\nRan out of coins!"
|
||||
self.message = Strings("Darn!\nRan out of coins!")
|
||||
self.stage = "message"
|
||||
self.afterMessage = nil
|
||||
self.exitTimer = 60
|
||||
@@ -515,7 +516,7 @@ function SlotMachine:update(dt)
|
||||
self.bet = 3 - self.betIndex
|
||||
if input:wasPressed("a") then
|
||||
if coins(self) < self.bet then
|
||||
self.message = "Not enough\ncoins!"
|
||||
self.message = Strings("Not enough\ncoins!")
|
||||
self.afterMessage = "bet"
|
||||
self.stage = "message"
|
||||
return
|
||||
@@ -671,8 +672,8 @@ function SlotMachine:drawBottom()
|
||||
local by = self.stage == "intro" and 6 or 11
|
||||
Font.drawBox(13, by, 6, 5)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("YES", 15 * 8, (by + 1) * 8)
|
||||
Font.draw("NO", 15 * 8, (by + 2) * 8)
|
||||
Font.draw(Strings("YES"), 15 * 8, (by + 1) * 8)
|
||||
Font.draw(Strings("NO"), 15 * 8, (by + 2) * 8)
|
||||
Font.drawCode(0xED, 14 * 8, (by + 1 + (self.yesno == 1 and 0 or 1)) * 8)
|
||||
end
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
@@ -723,8 +724,8 @@ function SlotMachine:drawPlain(art)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.rectangle("fill", 0, 0, 160, 144)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("SLOT MACHINE", 32, 4)
|
||||
Font.draw(("COINS %4d"):format(coins(self)), 8, 16)
|
||||
Font.draw(Strings("SLOT MACHINE"), 32, 4)
|
||||
Font.draw(Strings("COINS %4d", coins(self)), 8, 16)
|
||||
if art then self:drawReels(art) end
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw(">", 12, 56)
|
||||
|
||||
+17
-16
@@ -10,6 +10,7 @@ local Menu = require("src.ui.Menu")
|
||||
local Renderer = require("src.render.Renderer")
|
||||
local Runtime = require("src.mods.Runtime")
|
||||
local Screens = require("src.ui.Screens")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local StartMenu = {}
|
||||
|
||||
@@ -26,19 +27,19 @@ function StartMenu.new(game)
|
||||
|
||||
-- POKéDEX: only after Oak hands it over
|
||||
if flags.EVENT_GOT_POKEDEX then
|
||||
table.insert(items, { label = "POKéDEX", onSelect = function()
|
||||
table.insert(items, { label = Strings("POKéDEX"), onSelect = function()
|
||||
Screens.push(game, "PokedexMenu", { onCancel = reopen })
|
||||
end })
|
||||
end
|
||||
|
||||
-- POKéMON is always listed (draw_start_menu.asm prints it even with
|
||||
-- an empty party; selecting it then just no-ops)
|
||||
table.insert(items, { label = "POKéMON", onSelect = function()
|
||||
table.insert(items, { label = Strings("POKéMON"), onSelect = function()
|
||||
if #game.save.party == 0 then return end
|
||||
Screens.push(game, "PartyMenu", { onCancel = reopen })
|
||||
end })
|
||||
|
||||
table.insert(items, { label = "ITEM", onSelect = function()
|
||||
table.insert(items, { label = Strings("ITEM"), onSelect = function()
|
||||
Screens.push(game, "BagMenu", { onCancel = reopen })
|
||||
end })
|
||||
|
||||
@@ -50,7 +51,7 @@ function StartMenu.new(game)
|
||||
|
||||
-- SAVE shows the player/badges/dex/time panel then asks to confirm
|
||||
-- (PrintSaveScreenText)
|
||||
table.insert(items, { label = "SAVE", onSelect = function()
|
||||
table.insert(items, { label = Strings("SAVE"), onSelect = function()
|
||||
local TextBox = require("src.render.TextBox")
|
||||
local ChoiceBox = require("src.ui.ChoiceBox")
|
||||
local badges = require("src.inventory.Badges").count(game.data, game.save)
|
||||
@@ -59,32 +60,32 @@ function StartMenu.new(game)
|
||||
owned = owned + 1
|
||||
end
|
||||
local t = math.floor(game.save.playTime or 0)
|
||||
local panel = ("PLAYER %s\nBADGES %d\nPOKéDEX %3d\nTIME %6d:%02d")
|
||||
:format(game.save.player.name or "RED", badges, owned,
|
||||
math.floor(t / 3600), math.floor(t / 60) % 60)
|
||||
local panel = Strings("PLAYER %s\nBADGES %d\nPOKéDEX %3d\nTIME %6d:%02d",
|
||||
game.save.player.name or "RED", badges, owned,
|
||||
math.floor(t / 3600), math.floor(t / 60) % 60)
|
||||
game.stack:push(TextBox.new(game,
|
||||
panel .. "\fWould you like to\nSAVE the game?", function()
|
||||
panel .. Strings("\fWould you like to\nSAVE the game?"), function()
|
||||
game.stack:push(ChoiceBox.new(game, function(yes)
|
||||
if not yes then return end
|
||||
-- "Now saving..." beat before the write (save.asm
|
||||
-- NowSavingString), then GameSavedText + SFX_SAVE
|
||||
game.stack:push(TextBox.new(game, "Now saving...", function()
|
||||
game.stack:push(TextBox.new(game, Strings("Now saving..."), function()
|
||||
game:writeSave()
|
||||
require("src.core.Sound").play(game.data, "Save")
|
||||
game.stack:push(TextBox.new(game,
|
||||
(game.save.player.name or "RED") .. " saved\nthe game!"))
|
||||
Strings("%s saved\nthe game!", game.save.player.name or "RED")))
|
||||
end))
|
||||
end))
|
||||
end))
|
||||
end })
|
||||
|
||||
table.insert(items, { label = "OPTION", onSelect = function()
|
||||
table.insert(items, { label = Strings("OPTION"), onSelect = function()
|
||||
Screens.push(game, "OptionsMenu", { onCancel = reopen })
|
||||
end })
|
||||
|
||||
-- LINK needs a party
|
||||
if #game.save.party > 0 then
|
||||
table.insert(items, { label = "LINK", onSelect = function()
|
||||
table.insert(items, { label = Strings("LINK"), onSelect = function()
|
||||
local LinkState = require("src.link.LinkState")
|
||||
game.stack:push(LinkState.new(game))
|
||||
end })
|
||||
@@ -94,7 +95,7 @@ function StartMenu.new(game)
|
||||
-- one discovered mod so a vanilla install's menu is unchanged
|
||||
local status = game.modStatus
|
||||
if status and #(status.available or {}) > 0 then
|
||||
table.insert(items, { label = "MODS", onSelect = function()
|
||||
table.insert(items, { label = Strings("MODS"), onSelect = function()
|
||||
Screens.push(game, "ManagerState")
|
||||
end })
|
||||
end
|
||||
@@ -102,10 +103,10 @@ function StartMenu.new(game)
|
||||
-- the original's EXIT just closed the menu (CloseStartMenu); with a
|
||||
-- window close button covering that, QUIT instead power-cycles back
|
||||
-- to the title after a confirm (defaultNo guards accidental quits)
|
||||
table.insert(items, { label = "QUIT", onSelect = function()
|
||||
table.insert(items, { label = Strings("QUIT"), onSelect = function()
|
||||
local TextBox = require("src.render.TextBox")
|
||||
local ChoiceBox = require("src.ui.ChoiceBox")
|
||||
game.stack:push(TextBox.new(game, "RETURN TO MAIN\nMENU?", function()
|
||||
game.stack:push(TextBox.new(game, Strings("RETURN TO MAIN\nMENU?"), function()
|
||||
game.stack:push(ChoiceBox.new(game, function(yes)
|
||||
if yes then game:returnToTitle() end
|
||||
end, { defaultNo = true }))
|
||||
@@ -155,7 +156,7 @@ function StartMenu.new(game)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw(("%3d"):format(math.floor(safari.steps or 0)), 8, 8)
|
||||
Font.draw("/500", 32, 8)
|
||||
Font.draw("BALL", 8, 24)
|
||||
Font.draw(Strings("BALL"), 8, 24)
|
||||
Font.draw(("%2d"):format(math.floor(safari.balls or 0)), 48, 24)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
@@ -12,6 +12,7 @@ local Font = require("src.render.Font")
|
||||
-- TypeChart.displayName maps it back to "PSYCHIC", like HallOfFame and the
|
||||
-- battle move-type box already do (#214).
|
||||
local TypeChart = require("src.battle.TypeChart")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local SummaryMenu = {}
|
||||
SummaryMenu.__index = SummaryMenu
|
||||
@@ -90,7 +91,7 @@ function SummaryMenu:draw()
|
||||
drawLineBox(19, 1, 6, 10)
|
||||
HudTiles.drawHPBar(data, 11, 3, mon, 1) -- wHPBarType 1
|
||||
Font.draw(("%3d/%3d"):format(mon.hp, mon.stats.hp), 96, 32)
|
||||
Font.draw("STATUS/", 72, 48)
|
||||
Font.draw(Strings("STATUS/"), 72, 48)
|
||||
Font.draw(mon.status or "OK", 128, 48)
|
||||
|
||||
-- stats box (0,8) 10x10: names rows 9/11/13/15, values indented
|
||||
@@ -107,27 +108,27 @@ function SummaryMenu:draw()
|
||||
|
||||
-- TYPE1/TYPE2/IDNo/OT column (10,9) with values indented (11,10)
|
||||
drawLineBox(19, 9, 8, 6)
|
||||
Font.draw("TYPE1/", 80, 72)
|
||||
Font.draw(Strings("TYPE1/"), 80, 72)
|
||||
Font.draw(def.types[1] and TypeChart.displayName(def.types[1]) or "", 88, 80)
|
||||
if def.types[2] then
|
||||
Font.draw("TYPE2/", 80, 88)
|
||||
Font.draw(Strings("TYPE2/"), 80, 88)
|
||||
Font.draw(TypeChart.displayName(def.types[2]), 88, 96)
|
||||
end
|
||||
Font.draw("IDNo/", 80, 104)
|
||||
Font.draw(Strings("IDNo/"), 80, 104)
|
||||
-- the trainer ID is rolled at new game (SaveData.newGame) and
|
||||
-- backfilled on load for old saves
|
||||
Font.draw(("%05d"):format(mon.otId or game.save.player.id or 0), 96, 112)
|
||||
Font.draw("OT/", 80, 120)
|
||||
Font.draw(Strings("OT/"), 80, 120)
|
||||
Font.draw(mon.ot or game.save.player.name or "RED", 96, 128)
|
||||
else
|
||||
-- page 2: EXP + the moves with PP (StatusScreen2)
|
||||
drawLineBox(19, 1, 6, 10)
|
||||
Font.draw("EXP POINTS", 72, 24)
|
||||
Font.draw(Strings("EXP POINTS"), 72, 24)
|
||||
Font.draw(("%d"):format(mon.exp), 96, 32)
|
||||
-- StatusScreen2: "LEVEL UP" at (9,5); next-exp PrintNumber 7 cols
|
||||
-- at (7,6); space at (14,6); PrintLevel at (16,6). The old
|
||||
-- "%d to L%d" string at x=88 overflowed the DrawLineBox edge.
|
||||
Font.draw("LEVEL UP", 72, 40)
|
||||
Font.draw(Strings("LEVEL UP"), 72, 40)
|
||||
local Growth = require("src.pokemon.Growth")
|
||||
local nextExp = mon.level < 100
|
||||
and (Growth.expForLevel(def.growthRate, mon.level + 1) - mon.exp) or 0
|
||||
@@ -141,7 +142,7 @@ function SummaryMenu:draw()
|
||||
if mv then
|
||||
local mdef = data.moves[mv.id]
|
||||
Font.draw(mdef.name, 16, y)
|
||||
Font.draw("PP", 88, y + 8)
|
||||
Font.draw(Strings("PP"), 88, y + 8)
|
||||
Font.draw(("%2d/%2d"):format(mv.pp, mdef.pp), 112, y + 8)
|
||||
else
|
||||
Font.draw("-", 16, y)
|
||||
|
||||
+11
-10
@@ -6,6 +6,7 @@
|
||||
local Font = require("src.render.Font")
|
||||
local Music = require("src.core.Music")
|
||||
local GameVersion = require("src.core.GameVersion")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local TitleState = {}
|
||||
TitleState.__index = TitleState
|
||||
@@ -165,19 +166,19 @@ function ContinueInfo:draw()
|
||||
-- box at (4,7), 8x14 content; labels double-spaced from (5,9)
|
||||
Font.drawBox(4, 7, 16, 10)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("PLAYER", 40, 72)
|
||||
Font.draw(Strings("PLAYER"), 40, 72)
|
||||
Font.draw((save.player and save.player.name) or "RED", 96, 72)
|
||||
local badges = require("src.inventory.Badges").count(self.game.data, save)
|
||||
Font.draw("BADGES", 40, 88)
|
||||
Font.draw(Strings("BADGES"), 40, 88)
|
||||
Font.draw(("%2d"):format(badges), 128, 88)
|
||||
local owned = 0
|
||||
for _ in pairs(save.pokedex and save.pokedex.owned or {}) do
|
||||
owned = owned + 1
|
||||
end
|
||||
Font.draw("POKéDEX", 40, 104)
|
||||
Font.draw(Strings("POKéDEX"), 40, 104)
|
||||
Font.draw(("%3d"):format(owned), 120, 104)
|
||||
local t = math.floor(save.playTime or 0)
|
||||
Font.draw("TIME", 40, 120)
|
||||
Font.draw(Strings("TIME"), 40, 120)
|
||||
Font.draw(("%3d:%02d"):format(math.floor(t / 3600),
|
||||
math.floor(t / 60) % 60), 104, 120)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
@@ -188,7 +189,7 @@ function TitleState:openMenu()
|
||||
local game = self.game
|
||||
local items = {}
|
||||
if hasSave() then
|
||||
table.insert(items, { label = "CONTINUE", onSelect = function()
|
||||
table.insert(items, { label = Strings("CONTINUE"), onSelect = function()
|
||||
-- peek at the save for the info window; fall through if the
|
||||
-- file can't be read
|
||||
local ok, loaded = pcall(require("src.core.SaveData").load)
|
||||
@@ -199,13 +200,13 @@ function TitleState:openMenu()
|
||||
end
|
||||
end })
|
||||
end
|
||||
table.insert(items, { label = "NEW GAME", onSelect = function()
|
||||
table.insert(items, { label = Strings("NEW GAME"), onSelect = function()
|
||||
if self.onNewGame then self.onNewGame() end
|
||||
end })
|
||||
table.insert(items, { label = "OPTION", onSelect = function()
|
||||
table.insert(items, { label = Strings("OPTION"), onSelect = function()
|
||||
require("src.ui.Screens").push(game, "OptionsMenu")
|
||||
end })
|
||||
table.insert(items, { label = "EXIT GAME", onSelect = function()
|
||||
table.insert(items, { label = Strings("EXIT GAME"), onSelect = function()
|
||||
if love.event and love.event.quit then
|
||||
love.event.quit()
|
||||
end
|
||||
@@ -254,7 +255,7 @@ function TitleState:draw()
|
||||
love.graphics.draw(self.logo, 16, 8)
|
||||
else
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw(self.blue and "POKéMON BLUE" or "POKéMON RED",
|
||||
Font.draw(self.blue and "POKéMON BLUE" or Strings("POKéMON RED"),
|
||||
(160 - 12 * 8) / 2, 24)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
@@ -290,7 +291,7 @@ function TitleState:draw()
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
-- the copyright row (tile 2,17); copyrightText because field.title's
|
||||
-- copyright key already names the extracted image strip
|
||||
Font.draw(self.title.copyrightText or "2026 bois club games", 1, 136)
|
||||
Font.draw(self.title.copyrightText or Strings("2026 bois club games"), 1, 136)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
local Font = require("src.render.Font")
|
||||
local Sound = require("src.core.Sound")
|
||||
local TextBox = require("src.render.TextBox")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local TradeAnim = {}
|
||||
TradeAnim.__index = TradeAnim
|
||||
@@ -343,7 +344,7 @@ function TradeAnim:drawMonInfo(mon, ot, otId, boxTy)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw(no, 56, y0)
|
||||
Font.draw(speciesName(self.game, mon), 40, y0 + 16)
|
||||
Font.draw("OT/" .. (ot or "????"), 40, y0 + 32)
|
||||
Font.draw(Strings("OT/%s", ot or "????"), 40, y0 + 32)
|
||||
Font.draw(("IDNo.%05d"):format(otId or 0), 40, y0 + 48)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
+10
-4
@@ -4,8 +4,10 @@
|
||||
-- are built from the real trainer_info.png frame tiles (the patterned
|
||||
-- band + line style).
|
||||
|
||||
local Assets = require("src.render.Assets")
|
||||
local Badges = require("src.inventory.Badges")
|
||||
local Font = require("src.render.Font")
|
||||
local Strings = require("src.core.Strings")
|
||||
|
||||
local TrainerCard = {}
|
||||
TrainerCard.__index = TrainerCard
|
||||
@@ -16,8 +18,11 @@ function TrainerCard:sgbPalettes(game)
|
||||
return require("src.render.PaletteFX").wholeNamed(game.data, "MEWMON")
|
||||
end
|
||||
|
||||
-- through Assets.resolve so an enabled mod's overrides/ shadows these the
|
||||
-- same way it shadows every other generated asset
|
||||
local function tryImage(path)
|
||||
local ok, img = pcall(love.graphics.newImage, path)
|
||||
if not path then return nil end
|
||||
local ok, img = pcall(love.graphics.newImage, Assets.resolve(path))
|
||||
return ok and img or nil
|
||||
end
|
||||
|
||||
@@ -62,7 +67,8 @@ function TrainerCard.new(game, opts)
|
||||
end
|
||||
end
|
||||
self.circle = tryImage("assets/generated/trainer_card/circle_tile.png")
|
||||
self.pic = tryImage("assets/generated/trainer_card/red.png")
|
||||
self.pic = tryImage(require("src.pokemon.Sprites").playerPath(
|
||||
game.data, "front", { kind = "trainer_card" }))
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -114,7 +120,7 @@ function TrainerCard:draw()
|
||||
love.graphics.draw(self.pic, 104, 4)
|
||||
end
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("NAME/" .. (save.player.name or "RED"), 16, 16)
|
||||
Font.draw(Strings("NAME/%s", save.player.name or "RED"), 16, 16)
|
||||
Font.draw(("MONEY/¥%d"):format(save.money or 0), 16, 32)
|
||||
local t = math.floor(save.playTime or 0)
|
||||
Font.draw(("TIME/%3d:%02d"):format(math.floor(t / 3600),
|
||||
@@ -123,7 +129,7 @@ function TrainerCard:draw()
|
||||
-- the circle-dotted BADGES banner (TrainerInfo_BadgesText)
|
||||
self:frameBox(0, 8, 20, 3)
|
||||
love.graphics.setColor(0, 0, 0, 1)
|
||||
Font.draw("BADGES", 56, 72)
|
||||
Font.draw(Strings("BADGES"), 56, 72)
|
||||
if self.circle then
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.draw(self.circle, 48, 72)
|
||||
|
||||
Reference in New Issue
Block a user