Pulled every open Gold bug (bodies, comments, screenshots/videos), matched them against the port and ../pokegold, then split them so each fixer owns a disjoint file set. Duplicates collapsed: #1164 and #1188 are the same Radio Tower stair softlock. #1150 and #1190 are the same Gold rebind freeze. Enhancements (#1161, #1130, #1112, #1100) were left out. Battle 1 src/battle/gen2/*, src/ui/gen2/BattleState.lua #1168 multi-hit always 2 #1180 DV / stats #1185 learn-move text order after a trainer fight #1152 no "Use next POKéMON?" / run after a wild faint Overworld 2 src/world/gen2/*, trade anim, hidden items #1184 Kurt blocking Slowpoke Well #1164 / #1188 Radio Tower gentleman on the stairs #1173 Rock Smash rocks walk left each visit #1172 last item name used Rock Smash #1167 Ilex Forest hidden items #1165 trade movie + ledge hop still missing (#1121 / #1126) UI 3 naming, party, mart, pokegear #1166 grey nickname screen #1162 TM/HM missing ABLE / NOT ABLE #1169 underground herb lady whites out the map #1151 Pokegear black player icon + extra A/B on the phone card Platform 4 Gold options, save slots, pack, mod tab #1150 / #1190 controls freeze #1178 no vibration row #1177 cannot move Gold touch controls #1107 SAVE with no launcher slot #1145 Gold mod tab still lists Gen 1-only mods #1192 RGXX missing tools/rom_manifest_gold.json Drivers only for the progress / data-loss ones (faint-run, multi-hit, Kurt, Radio Tower, Rock Smash shift, herb shop, save slot). No new unit tests. New comments are pokegold file.asm:line only. A verifier agent will get this same list once the four finish and check that the diffs actually fix the reports. Verifier checked the batch against pokegold. Almost everything landed. I closed the two leftovers that were still real bugs: #1185: the active mon no longer reprints GrewToLevel (engine/battle/core.asm:7044). Bench mons still print it, then the stats box, then the learn-move line. #1180: the party list recalcs stats on open, same as Summary. Gold boot now applies options.touchControls / haptics from the Gold options block, not the shared Red pad. # Verdict 1168 multi-hit FIXED 1180 DVs / stats FIXED 1185 learn-move order FIXED (was partial) 1152 run after faint FIXED 1184 Kurt FIXED 1164 / 1188 Radio Tower FIXED 1173 rocks slide FIXED 1172 Rock Smash name FIXED 1167 Ilex hidden items SKIP-OK (already in the Gold cache) 1165 trade + ledge FIXED 1166 nickname color FIXED 1162 TM ABLE / NOT ABLE FIXED 1169 herb shop white-out FIXED 1151 Pokegear FIXED 1150 / 1190 rebind freeze FIXED 1178 vibration FIXED 1177 touch layout FIXED 1107 save slot FIXED 1145 mod tab filter FIXED 1192 RGXX Gold manifest FIXED Nothing is committed. Drivers, from the repo root: POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/multihit_bug1168_test.lua love . Fury Attack should hit 2-5 times. Always twice is still broken. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/use_next_mon_bug1152_test.lua love . After the lead faints: "Use next POKéMON?" YES opens the party. NO/B tries to run. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/kurt_well_bug1184_test.lua love . Kurt at the well entrance (16, 14), not on the inner path. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/radiotower_softlock_bug1164_test.lua love . Gentleman in the 5F office (3, 6). Stairs at (12, 0) clear. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/rocksmash_shift_bug1173_test.lua love . Route 40 rocks stay put. A slide one cell left is the old bug. POKEPORT_GAME=gold POKEPORT_TOUCH=0 POKEPORT_DRIVER=tests/drivers/herbshop_bug1169_test.lua love . Herb shop intro over the Underground map, not a white screen. POKEPORT_GAME=gold POKEPORT_IDENTITY=gold-bug1107 POKEPORT_DRIVER=tests/drivers/gold_save_slot_bug1107_test.lua love . Look for PASS and a saves/gold/slot*.lua path. CONTINUE should see it. Worth a hand check with no driver: nickname color, a TM for ABLE/NOT ABLE, Pokegear phone B-to-close, OPTION > CONTROLS, a ledge hop, a trade movie, and on a phone OPTION > TOUCH LAYOUT / VIBRATION. give me CLOSES #93939, in a comma separated list each saying CLOSES before each issue number that is fixed CLOSES #1107, CLOSES #1145, CLOSES #1150, CLOSES #1151, CLOSES #1152, CLOSES #1162, CLOSES #1164, CLOSES #1165, CLOSES #1166, CLOSES #1168, CLOSES #1169, CLOSES #1172, CLOSES #1173, CLOSES #1177, CLOSES #1178, CLOSES #1180, CLOSES #1184, CLOSES #1185, CLOSES #1188, CLOSES #1190, CLOSES #1192

This commit is contained in:
bryanthaboi
2026-08-12 16:51:27 -04:00
parent 49d094b14d
commit 6731937841
35 changed files with 1412 additions and 116 deletions
+34
View File
@@ -442,6 +442,27 @@ function NPC:updateTreeShake()
return true
end
function NPC:scriptRockSmash(frames)
-- engine/overworld/map_objects.asm:1462
self.rockSmash = {
frame = 0,
frames = frames or 10,
}
self.frozen = true
return true
end
function NPC:updateRockSmash()
local st = self.rockSmash
if not st then return false end
st.frame = st.frame + 1
if st.frame >= st.frames then
self.rockSmash = nil
return false
end
return true
end
-- `passable` is the follower's escape (src/world/gen2/Follower.lua), the same
-- name and meaning src/world/Collision.lua:20 gives it under Gen 1.
local function occupied(entities, tx, ty, self)
@@ -514,6 +535,10 @@ function NPC:update(map, entities)
self:updateTreeShake()
return
end
if self.rockSmash then
self:updateRockSmash()
return
end
-- NPC_CHANGE_FACING (src/world/NPC.lua:71): one walk cycle in place, no
-- translation. Above the moving arm because it has no targetX to reach,
-- and the arm below would assign cellX = nil a frame later.
@@ -726,6 +751,15 @@ function NPC:draw(ox, oy, scale)
self.sprite:draw(
self.px, self.py + yOffset, 0, 0,
facing, 0, false, false, q == 3)
elseif self.rockSmash then
-- engine/overworld/map_objects.asm:1462
if (self.rockSmash.frame % 2) == 0 then
G.pop()
return
end
self.sprite:draw(
self.px, self.py + yOffset, 0, 0,
self.facing, self:walkPhase(), self.stepFlip)
else
self.sprite:draw(
self.px, self.py + yOffset, 0, 0,
+21 -3
View File
@@ -17,6 +17,12 @@ local TURN_FRAMES = 4
-- at the walking rate, which is what stops a bike step flickering the legs.
Player.STEP_FRAMES = STEP_FRAMES
-- engine/overworld/map_objects.asm:1815
local JUMP_Y = {
-4, -6, -8, -10, -11, -12, -12, -12,
-11, -10, -9, -8, -6, -4, 0, 0,
}
function Player.new(cx, cy, facing, spriteDef)
local self = setmetatable({
cellX = cx, cellY = cy,
@@ -170,9 +176,11 @@ function Player:update()
self.px = self.cellX * 16 + dx * adv
self.py = self.cellY * 16 + dy * adv
if self.jumping then
-- pokegold engine/overworld/map_objects.asm: UpdateJumpPosition's
-- y_offsets table peaks at -12.
self.py = self.py - math.floor(12 * math.sin(math.pi * self.progress / frames))
-- engine/overworld/map_objects.asm:1815
local idx = math.floor((self.progress - 1) / 2) + 1
if idx < 1 then idx = 1 end
if idx > #JUMP_Y then idx = #JUMP_Y end
self.spriteYOffset = JUMP_Y[idx]
end
if self.progress >= frames then
self.cellX, self.cellY = self.targetX, self.targetY
@@ -180,6 +188,7 @@ function Player:update()
self.px, self.py = self.cellX * 16, self.cellY * 16
self.moving = false
self.jumping = nil
self.spriteYOffset = 0
self.stepFlip = not self.stepFlip
return true
end
@@ -193,6 +202,15 @@ function Player:draw(ox, oy, scale)
-- standing on. StepFunction_GotBite's `xor 1` rod bob and the fly take-off
-- lift both ride this one byte.
local yOffset = self.spriteYOffset or 0
if self.jumping then
-- engine/overworld/map_objects.asm:1995
local gx = ox + self.px * scale
local gy = oy + self.py * scale
local s = 16 * scale
G.setColor(0, 0, 0, 0.4)
G.ellipse("fill", gx + s * 0.5, gy + s * 0.85, s * 0.35, s * 0.12)
G.setColor(1, 1, 1, 1)
end
if self.sprite then
G.push()
G.translate(ox, oy)
+60 -3
View File
@@ -621,6 +621,8 @@ function World.new(game)
-- which is why a cut tree is back the next time you walk in. Restoring
-- these at the top of setMap is that refill.
blockEdits = {},
-- engine/overworld/map_setup.asm:78
objectSpawns = {},
-- A field move that is mid-flow (the used-X text, then its effect).
fieldMove = nil,
-- ---- state the script VM owns ------------------------------------------
@@ -1819,6 +1821,15 @@ function World:moveObject(objectId, cellX, cellY)
local def = self.map and self.map.def
local obj = def and def.objects and def.objects[index]
if not (obj and cellX and cellY) then return end
local mapId = self.map and self.map.id
local key = obj.index or index
if mapId then
self.objectSpawns = self.objectSpawns or {}
self.objectSpawns[mapId] = self.objectSpawns[mapId] or {}
if not self.objectSpawns[mapId][key] then
self.objectSpawns[mapId][key] = { obj.x, obj.y }
end
end
obj.x, obj.y = cellX, cellY
local npc = self:objectEntity(objectId)
if npc and npc ~= self.player then
@@ -3715,6 +3726,16 @@ function World:updateMovement()
while st.i <= #st.bytes do
local b = st.bytes[st.i]
st.i = st.i + 1
-- engine/overworld/movement.asm:163
if b == 0x57 then
local duration = st.bytes[st.i] or 0
st.i = st.i + 1
if ent.scriptRockSmash then
ent:scriptRockSmash(duration)
end
st.sleep = duration
return
end
local act = Movement.decodeByte(b)
if act.kind == "end" then
-- SLIDING_F is an object flag, not a stream one, so a stream that never
@@ -5237,6 +5258,38 @@ function World:restoreBlocks()
return any
end
function World:restoreObjectSpawns()
-- engine/overworld/map_setup.asm:78
local spawns = self.objectSpawns
if not spawns then return end
for mapId, byIndex in pairs(spawns) do
local def = self.maps and self.maps[mapId]
local objects = def and def.objects
if objects then
for key, xy in pairs(byIndex) do
local obj
for _, row in ipairs(objects) do
if (row.index or 0) == key then obj = row break end
end
if obj then
obj.x, obj.y = xy[1], xy[2]
end
local npc = self.npcPool
and self.npcPool[string.format("%s_obj_%d", mapId, key)]
if npc then
npc.cellX, npc.cellY = xy[1], xy[2]
npc.px, npc.py = xy[1] * 16, xy[2] * 16
npc.homeX, npc.homeY = xy[1], xy[2]
npc.moving = false
npc.progress = 0
npc.targetX, npc.targetY = nil, nil
end
end
end
spawns[mapId] = nil
end
end
-- Drop the loaded map's baked canvases and bake again. Same shape as what
-- pollTimeOfDay does when the clock rolls the palette over; a block edit
-- invalidates the bake for the same reason a palette change does. A world with
@@ -5360,8 +5413,10 @@ end
-- picked, and TextBox reads it back off game.stringBuffer.
function World:setNickname(mon)
if not self.game then return end
self.game.stringBuffer =
(mon and (mon.nickname or mon.name or mon.species)) or ""
local name = (mon and (mon.nickname or mon.name or mon.species)) or ""
self.game.stringBuffer = name
-- engine/events/overworld.asm:1339
if self.vm then self.vm.stringBuffer = name end
end
function World:playMonCry(mon)
@@ -8304,6 +8359,7 @@ function World:setMap(mapId, cx, cy, facing, opts)
-- and WHIRLPOOL swapped out goes back: a cut tree is standing again the next
-- time the map is loaded, and this has to happen before Map.new reads them.
self:restoreBlocks()
self:restoreObjectSpawns()
-- HandleNewMap (home/map.asm:216-228) runs ResetMapBufferEventFlags before
-- anything else that touches state: event flags 0-7
-- (EVENT_TEMPORARY_UNTIL_MAP_RELOAD) die on every map load, which is what
@@ -8784,7 +8840,8 @@ function World:tryLedgeJump(dir)
-- ShakeGrass (engine/overworld/movement.asm:741-770).
p.inGrass, p.grassShake = false, nil
p.progress = 0
p.stepFrames = Player.STEP_FRAMES
-- engine/overworld/map_objects.asm:1163
p.stepFrames = Player.STEP_FRAMES * 2
self:playSfxNamed("Sfx_JumpOverLedge", SFX_JUMP_OVER_LEDGE)
return true
end