Fix Gen 1/2 battle, menu, PC and audio parity gaps; wire luacheck into CI

CLOSES #1484, CLOSES #1486, CLOSES #1513, CLOSES #1517, CLOSES #1556, CLOSES #1564, CLOSES #1567
This commit is contained in:
bryanthaboi
2026-08-21 19:22:34 -04:00
parent 087a275189
commit c0f4315cd8
45 changed files with 2487 additions and 168 deletions
+34 -4
View File
@@ -808,6 +808,31 @@ local function buildOverworld()
local Movement = rawRequire("src.script.gen2.Movement")
local HiddenItems = rawRequire("src.world.gen2.HiddenItems")
local Bike = rawRequire("src.world.gen2.Bike")
local FieldMoves = rawRequire("src.world.gen2.FieldMoves")
-- home/map.asm:1869
local function stepAllowed(world, entity, dir)
local d = Map2.DELTA[dir]
if not (world.map and d and entity and entity.cellX) then return true end
if not Permissions.stepPermitted(
function(cx, cy) return world:cellCollisionAcross(world.map, cx, cy) end,
entity.cellX, entity.cellY, dir) then
return false
end
local map = world.map
if entity == world.player and FieldMoves.isSurfing(world.playerState) then
map = world:surfMap(world.map)
end
local tx, ty = entity.cellX + d[1], entity.cellY + d[2]
if not map:inBounds(tx, ty) or not map:isWalkable(tx, ty) then return false end
for _, e in ipairs(world.entities or {}) do
if e ~= entity and not e.passable then
if e.cellX == tx and e.cellY == ty then return false end
if e.moving and e.targetX == tx and e.targetY == ty then return false end
end
end
return true
end
local api = nil
-- one WorldAPI instance, so queueScript reuses the five-verb allow list
@@ -1011,20 +1036,25 @@ local function buildOverworld()
-- Gold has ONE movement slot; a second concurrent call is refused with a
-- reason rather than dropped (src/world/gen2/WorldAPI.lua:171's recipe).
function ow.scriptMove(entity, dir, tiles, onDone)
function ow.scriptMove(entity, dir, tiles, onDone, opts)
local world = w("scriptMove")
if not world then return nil, "no overworld" end
if world.moveState then return nil, "a movement is already running" end
local step = Movement.stepByte(dir)
if not step then return nil, "unknown direction: " .. tostring(dir) end
local bytes = {}
for _ = 1, math.max(0, tiles or 1) do bytes[#bytes + 1] = step end
bytes[#bytes + 1] = Movement.STEP_END
local objectId = objectIdOf(world, entity)
if not objectId then
return nil, "no Gen 2 objectId for that entity: only the player and a "
.. "mapped object (def.index) can be moved"
end
local n = math.max(0, tiles or 1)
if opts and opts.collide and n > 0 and not stepAllowed(world, entity, dir) then
entity.facing = dir
n = 0
end
local bytes = {}
for _ = 1, n do bytes[#bytes + 1] = step end
bytes[#bytes + 1] = Movement.STEP_END
world:beginMovement(objectId, bytes, onDone)
return true
end
+12
View File
@@ -119,6 +119,17 @@ local GEN1_ONLY_MODULES = {
["src.ui.OptionsMenu"] = true,
}
local function crossGenerationDenial(name, generation)
if type(name) ~= "string" or generation ~= 1 then return nil end
if not (name:find("^src%.[%w_]+%.gen2%.") or name == "src.core.Game2") then
return nil
end
return ("%s is a Gen 2 engine module and this is a Gen 1 game; the structs "
.. "it reads and writes are not this game's, so anything it stores lands "
.. "on the save in the wrong shape. Take the game from mod.game and the "
.. "world from mod.world, which resolve per generation"):format(name)
end
-- the src.* modules the mod surface points authors at: another mod's
-- exports carry a version string that wants range-checking before use, and
-- ChipAsm is the authoring path for chip music and sfx
@@ -214,6 +225,7 @@ function Loader:_installDevShim()
if owner or callerIsMod(3) then
local id = type(owner) == "string" and owner or nil
local denial = Sandbox.moduleDenial(name, devShim.permissions[id])
or (id and crossGenerationDenial(name, devShim.generation))
if denial then error(("[%s] %s"):format(id or "mod", denial), 0) end
end
if devShim.dev or devShim.generation ~= 1 then scanRequire(name) end