mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-27 08:51:27 +02:00
227 lines
7.6 KiB
Lua
227 lines
7.6 KiB
Lua
-- ../pokecrystal/engine/events/unown_walls.asm:102 DisplayUnownWords, and the
|
|
-- Unown alphabet it writes out of ../pokecrystal/constants/charmap.asm:424;
|
|
-- :1 HoOhChamber, :13 OmanyteChamber, :54 SpecialAerodactylChamber and :81
|
|
-- SpecialKabutoChamber, the four routines that open the chambers' walls.
|
|
|
|
local Assets = require("src.render.Assets")
|
|
local Chrome = require("src.ui.gen2.Chrome")
|
|
local Font = require("src.render.Font")
|
|
local GbcPalette = require("src.render.GbcPalette")
|
|
local Palettes = require("src.world.gen2.Palettes")
|
|
local Sound = require("src.core.Sound")
|
|
|
|
local UnownWords = {}
|
|
UnownWords.__index = UnownWords
|
|
UnownWords.isOpaque = false
|
|
|
|
-- engine/tilesets/map_palettes.asm:40, ../pokecrystal/constants/tileset_constants.asm:55
|
|
UnownWords.BANK1 = 0x80
|
|
UnownWords.BROWN = 6
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:225 .YChar, :237 .ZChar, :249 .DashChar
|
|
local FIXED = {
|
|
[0x60] = { 0x5b, 0x5c, 0x4d, 0x5d },
|
|
[0x62] = { 0x4e, 0x4f, 0x5e, 0x5f },
|
|
[0x64] = { 0x02, 0x03, 0x03, 0x02 },
|
|
}
|
|
|
|
function UnownWords.square(char)
|
|
local fixed = FIXED[char]
|
|
if fixed then return fixed[1], fixed[2], fixed[3], fixed[4] end
|
|
local base = UnownWords.BANK1 + char
|
|
return base, base + 1, base + 0x10, base + 0x11
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:122-127
|
|
function UnownWords.origin(wall)
|
|
return (wall.x1 or 0) + 1, (wall.y1 or 0) + 2
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:119 MenuBox, home/menu.asm:131 GetMenuBoxDims
|
|
function UnownWords.boxRect(wall)
|
|
local x1, y1 = wall.x1 or 0, wall.y1 or 0
|
|
return x1, y1, (wall.x2 or x1) - x1 + 1, (wall.y2 or y1) - y1 + 1
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:182 _DisplayUnownWords_CopyWord
|
|
function UnownWords.layout(wall)
|
|
local tx, ty = UnownWords.origin(wall)
|
|
local out = {}
|
|
for index, char in ipairs(wall.chars or {}) do
|
|
local tl, tr, bl, br = UnownWords.square(char)
|
|
out[index] = {
|
|
tx = tx + (index - 1) * 2, ty = ty,
|
|
tl = tl, tr = tr, bl = bl, br = br,
|
|
}
|
|
end
|
|
return out
|
|
end
|
|
|
|
-- ../pokecrystal/constants/event_flags.asm:486-489, the four Crystal-only
|
|
-- EVENT_WALL_OPENED_IN_*_CHAMBER bits.
|
|
UnownWords.WALL_OPENED = {
|
|
HO_OH = 806,
|
|
KABUTO = 807,
|
|
OMANYTE = 808,
|
|
AERODACTYL = 809,
|
|
}
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:60, :87 -- the
|
|
-- GetMapAttributesPointer compare the two non-special routines are gated on.
|
|
UnownWords.CHAMBER_MAPS = {
|
|
HO_OH = "RUINS_OF_ALPH_HO_OH_CHAMBER",
|
|
KABUTO = "RUINS_OF_ALPH_KABUTO_CHAMBER",
|
|
OMANYTE = "RUINS_OF_ALPH_OMANYTE_CHAMBER",
|
|
AERODACTYL = "RUINS_OF_ALPH_AERODACTYL_CHAMBER",
|
|
}
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:4, :22
|
|
UnownWords.HO_OH = "HO_OH"
|
|
UnownWords.WATER_STONE = "WATER_STONE"
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:16 EventFlagAction CHECK_FLAG
|
|
function UnownWords.wallOpened(events, chamber)
|
|
local flag = UnownWords.WALL_OPENED[chamber]
|
|
if not (events and flag) then return false end
|
|
return events:get(flag) and true or false
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:8 EventFlagAction SET_FLAG
|
|
function UnownWords.openWall(events, chamber)
|
|
local flag = UnownWords.WALL_OPENED[chamber]
|
|
if not (events and flag) then return false end
|
|
if events:get(flag) then return false end
|
|
events:set(flag, true)
|
|
return true
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:2-5: wPartySpecies[0], which
|
|
-- holds EGG rather than the hatchling's species while a slot is an egg.
|
|
function UnownWords.leadIsHoOh(party)
|
|
local lead = party and party[1]
|
|
if not lead or lead.isEgg then return false end
|
|
return lead.species == UnownWords.HO_OH
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:28-43: wPartyCount down to 1,
|
|
-- MON_ITEM on each, so the LAST slot holding one is the one it stops at.
|
|
function UnownWords.waterStoneSlot(party)
|
|
party = party or {}
|
|
for slot = #party, 1, -1 do
|
|
local mon = party[slot]
|
|
if mon and mon.item == UnownWords.WATER_STONE then return slot end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:54, whose carry FlashFunction
|
|
-- jumps on at ../pokecrystal/engine/events/overworld.asm:285.
|
|
function UnownWords.aerodactylChamber(events, mapId)
|
|
if mapId ~= UnownWords.CHAMBER_MAPS.AERODACTYL then return false end
|
|
UnownWords.openWall(events, "AERODACTYL")
|
|
return true
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:81, off the escape rope arm of
|
|
-- EscapeRopeOrDig (../pokecrystal/engine/events/overworld.asm:809).
|
|
function UnownWords.kabutoChamber(events, mapId)
|
|
if mapId ~= UnownWords.CHAMBER_MAPS.KABUTO then return false end
|
|
UnownWords.openWall(events, "KABUTO")
|
|
return true
|
|
end
|
|
|
|
-- ../pokecrystal/constants/script_constants.asm:319 UNOWNWORDS_*
|
|
function UnownWords.wallFor(data, scriptVar)
|
|
local walls = data and data.gen2EventTables and data.gen2EventTables.unownWalls
|
|
if not walls then return nil end
|
|
return walls[(scriptVar or 0) + 1]
|
|
end
|
|
|
|
-- opts: wall (an events.unownWalls row), world, onClose()
|
|
function UnownWords.new(game, opts)
|
|
opts = opts or {}
|
|
local self = setmetatable({}, UnownWords)
|
|
self.game = game
|
|
self.wall = opts.wall
|
|
self.world = opts.world
|
|
self.onClose = opts.onClose
|
|
self.done = false
|
|
self.squares = self.wall and UnownWords.layout(self.wall) or {}
|
|
return self
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:155 _DisplayUnownWords_FillAttr
|
|
function UnownWords:tileset()
|
|
local world = self.world
|
|
local map = world and world.map
|
|
local def = map and map.def
|
|
local tileset = def and world.tilesets and world.tilesets[def.tileset]
|
|
if not tileset or not tileset.image then return nil end
|
|
if self.atlas == nil then
|
|
local ok, image = pcall(Assets.image, tileset.image)
|
|
self.atlas = ok and image or false
|
|
if self.atlas then self.atlas:setFilter("nearest", "nearest") end
|
|
local set = world.palettes
|
|
and Palettes.bgSet(world.palettes, def, world.daytime or "DAY")
|
|
self.colors = set and set[UnownWords.BROWN] or nil
|
|
end
|
|
if not self.atlas then return nil end
|
|
return tileset, self.atlas
|
|
end
|
|
|
|
-- ../pokecrystal/engine/events/unown_walls.asm:147 PlayClickSFX, :148 CloseWindow
|
|
function UnownWords:finish()
|
|
if self.done then return end
|
|
self.done = true
|
|
local game = self.game
|
|
if game and game.data then Sound.play(game.data, "SFX_READ_TEXT_2") end
|
|
if game and game.stack then game.stack:pop() end
|
|
if self.onClose then self.onClose() end
|
|
end
|
|
|
|
function UnownWords:update(_dt)
|
|
if self.done then return end
|
|
local input = self.game and self.game.input
|
|
if not input then return end
|
|
if input:wasPressed("a") or input:wasPressed("b") then self:finish() end
|
|
end
|
|
|
|
function UnownWords:draw()
|
|
local wall = self.wall
|
|
if not wall then return end
|
|
local bx, by, bw, bh = UnownWords.boxRect(wall)
|
|
Chrome.paletteBox(bx, by, bw, bh)
|
|
local tileset, atlas = self:tileset()
|
|
if not tileset then return end
|
|
local perRow = tileset.tilesPerRow or 16
|
|
local aw, ah = atlas:getDimensions()
|
|
local quads = {}
|
|
local function quadFor(tile)
|
|
local q = quads[tile]
|
|
if not q then
|
|
q = love.graphics.newQuad((tile % perRow) * 8,
|
|
math.floor(tile / perRow) * 8, 8, 8, aw, ah)
|
|
quads[tile] = q
|
|
end
|
|
return q
|
|
end
|
|
local function body()
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
for _, square in ipairs(self.squares) do
|
|
local x, y = square.tx * 8, square.ty * 8
|
|
love.graphics.draw(atlas, quadFor(square.tl), x, y)
|
|
love.graphics.draw(atlas, quadFor(square.tr), x + 8, y)
|
|
love.graphics.draw(atlas, quadFor(square.bl), x, y + 8)
|
|
love.graphics.draw(atlas, quadFor(square.br), x + 8, y + 8)
|
|
end
|
|
end
|
|
if self.colors and GbcPalette.available() then
|
|
GbcPalette.with(self.colors, body)
|
|
else
|
|
body()
|
|
end
|
|
love.graphics.setColor(0, 0, 0, 1)
|
|
end
|
|
|
|
return UnownWords
|