Files
gen1recomp/tests/engine/game3_virtual_objects_drawhook_test.lua
T
Shane McGovern 41935aa2a2 fix(game3): wave 2 - 118 review fixes, seam work, and the gate to 282 suites
Second batch of the Gen 3 review work: the review lanes closed their queues
and the test gate grew with them.

Review census: 139 routed findings -- 118 fixed, 14 invalid (the report had
Gen 4+ semantics in more than one place), 6 struck as stale after
re-verification, 1 re-routed. Every fix carries its own pret citation in
docs/game3/review-v3-triage.md; the E10 opcode closure is itemised in
docs/game3/e10-opcode-spec.md (18 ops wired, 2 reclassified to the seam class).

Representative ROM-grounded changes:
- The POKéMON start-menu entry is now gated on FLAG_SYS_POKEMON_GET the way
  retail does it (pokefirered/src/start_menu.c:217-218, flag 0x828).
- Money ops read their amount raw and gate the change on the disable byte
  (pokefirered/src/scrcmd.c:1798-1830, pokefirered/asm/macros/event.inc:1166-1186);
  random and the warp family VarGet theirs
  (pokefirered/src/scrcmd.c:455-461, :719-731).
- The HM table matches FRLG: there is no Whirlpool HM
  (pokefirered/include/constants/items.h:411-418).
- The day-care party-full guard follows src/daycare.c:525, :1081.
- Knock Off keeps its battle-scoped send-out mask
  (pokefirered/src/battle_script_commands.c:2730-2752, :4489), carried from
  the first batch.

Structural work: the I6/I9/J1 architecture items landed as seams (profile
selector, capability flags, font provider, virtual-object layer), the adopted
footprint register keeps a KEEP verdict, the quantizer target is met, and the
30 drain items plus carves 1-4 are folded in.

Tests: T6 now runs 282 top-level suites (273 + 9 new), the re-sweep ends at
267 pass / 0 fail, the engine tier is 634 suites, modkit 37, and the full
gate ran green twice with T3 active on an imported Red cache. Documented
skips are the lua5.4 oversize-save oracle where lua5.4 is absent and the
config-partials listed in docs/game3/game3-artifact-conversions-v3.md.

Docs shipped: review-v3-triage.md, e10-opcode-spec.md, rse-seams.md,
game3-suite-sweep-v113.md, game3-artifact-conversions-v3.md,
test-baseline-v3.md (plus the first-batch docs already on the branch).
2026-09-22 18:23:06 +01:00

59 lines
2.5 KiB
Lua

-- rse-seams e10 spec 5.3 draw hookup: virtual objects reach the same draw pass
-- as event objects (Objects.forDraw) and stay invisible to collision queries.
-- pret src/event_object_movement.c:1719 CreateVirtualObject (sprite, not an object event)
-- pret src/event_object_movement.c:9225 DestroyVirtualObjects (map unload)
-- lua: luajit tests/engine/game3_virtual_objects_drawhook_test.lua
package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
love = love or require("tests.love_stub")
local Objects = require("src.core.game3.objects")
local VirtualObjects = require("src.core.game3.virtual_objects")
local GfxIds = require("src.core.game3.scripting.gfx_ids")
local savedMap, savedOrder, savedById = Objects._mapId, Objects._order, Objects._byId
Objects._mapId = "FR_TEST_DRAWHOOK"
Objects._order = {}
Objects._byId = {}
VirtualObjects.clear()
-- 1. A spawned virtual object shows up in the draw list with the fields
-- field_view reads, and stays out of the collision store.
VirtualObjects.spawn(1, 40, 5, 6, 4, 1)
local found
for _, eo in ipairs(Objects.forDraw()) do
if eo.virtualId == 1 then found = eo end
end
check(found ~= nil, "forDraw yields the virtual object")
eq(found and found.cellX, 5, "tile x reaches the draw pass")
eq(found and found.cellY, 6, "tile y reaches the draw pass")
eq(found and found.elevation, 4, "elevation reaches the draw pass (actorPriority uses it)")
eq(found and found.facing, "down", "DIR_SOUTH maps to the down-facing sprite")
eq(found and found.graphicsId, 40, "graphicsId reaches OwSprites.draw")
eq(found and found.sprite, GfxIds.spriteFor(40), "sprite name reaches the non-OW fallback")
eq(Objects._byId[1], nil, "the registry is not in the object store (no collision)")
eq(Objects.at(5, 6), nil, "Objects.at cannot see it")
-- 2. turnvobject re-emerges on the next draw with the new direction.
VirtualObjects.turn(1, 2)
local turned
for _, eo in ipairs(Objects.forDraw()) do
if eo.virtualId == 1 then turned = eo end
end
eq(turned and turned.facing, "up", "turn(1, DIR_NORTH) shows on the next draw")
-- 3. Map unload teardown empties the draw list again.
VirtualObjects.clear()
local gone = false
for _, eo in ipairs(Objects.forDraw()) do
if eo.virtualId == 1 then gone = true end
end
eq(gone, false, "clear() removes it (DestroyVirtualObjects on map unload)")
Objects._mapId, Objects._order, Objects._byId = savedMap, savedOrder, savedById
T.finish("game3_virtual_objects_drawhook_test")