Entry 98
Event 4 as a player plays it: the dungeon's boxes and Gott statue, their menus, the Fortune Wire and the trap room's doors
Documented in Leaving the town - Kite in a field and its dungeon.
Filescrates/piney-battle/src/gimmick.rscrates/piney-battle/src/prim.rscrates/piney-battle/src/entry.rscrates/piney-battle/src/affect.rscrates/piney-battle/src/chara.rscrates/piney-battle/src/enemy_motion.rscrates/piney-battle/src/lib.rscrates/piney-battle/examples/battle_probe/spawn.rscrates/piney-battle/examples/battle_probe/enemy_motion.rscrates/piney-fieldui/src/menus/useitem.rscrates/piney-fieldui/src/menus/getitem.rscrates/piney-fieldui/src/menus/item.rscrates/piney-fieldui/src/menus/mod.rscrates/piney-fieldui/src/menus/target.rscrates/piney-fieldui/src/ctrl.rscrates/piney-fieldui/src/lib.rscrates/piney-fieldui/src/tables.rscrates/piney-fieldui/src/world.rscrates/piney-fieldui/examples/fieldui_probe.rscrates/piney-world/src/field_world.rscrates/piney-world/src/dungeon_area.rscrates/piney-world/src/combat/mod.rscrates/piney-world/src/combat/stage.rscrates/piney-world/src/combat/cast.rscrates/piney-world/src/foe.rscrates/piney-game/src/area.rscrates/piney-game/src/area_host.rscrates/piney-game/src/fx.rscrates/piney-game/src/session.rscrates/piney-game/src/world.rstools/test_battle_spawn_rs.pytools/test_fieldui_rs.pydocs/engine/battle.mddocs/engine/dungeon.mddocs/engine/field-ui.mddocs/engine/field-walk.md
The user played --mode story:4 and reported these problems:
- no treasure box was drawn;
- the Gott statue was missing;
- the locked room's doors played oddly;
- room changes were a little buggy;
- the minimap was lost after the stairs.
Event 4 (TEACH-D) now plays through its dungeon as a player plays it.
The dungeon's objects
WORLD_MAN::EntryGimmick's dungeon setters now run once per dungeon:
DUNGEON::SetItemBoxplaces the boxes;DUNGEON::SetMagicCircleplaces the portals;DUNGEON::SetIDOLplaces the idols.
piney-battle now has two of the objects' classes (gimmick.rs).
ccGimBox. Its constructor rolls the trap. ItsmainrunsboxMain,objectMainorvirusMain;invokeTrapandbreakObjectare ported too.ccGimIdol. Its three clips: standing, opening, open.- The opening's rays. They are
ccPrimRadiatewithccGimBoxRad::ctrl(prim.rs).
piney-world does the rest:
- it draws the boxes and idols with their rows' palettes, and the rays on the effect layer;
- it carries a trap out on its opener;
- it keeps a dungeon's objects across its rooms, since every room is a
scene change (
g_entryList's keep andrestoreEntry); - a box's or an idol's rays follow it to its new scene index.
A trap went off without landing. The damage roll saw the box already
off the command lists, so it always missed. In the game invokeTrap
runs before deleteCmnd in the same frame. The port now records the lists
as the call saw them.
The menus that open them, and the Fortune Wire
The action button on a box, a trapped box or an idol asked for menus 32, 33 and 38. The field UI closed them at once, so no box but the tutorial's could be opened. Four menus are now ported:
- 32,
ItemBoxMenu: the box's item, or a draw from the danger list or the box list. - 33,
TrapBoxMenu: the trap goes off, then "Set off trap!" and the trap's line, then a dud. - 38,
ItemIdolMenu: three items, through - 67,
DataDrainSubMenu.
Nothing carried out an item used from the menus. ccUseItemRequest is one
blocking call on the menu task: it opens and waits on the menu's own
windows and breathes the task. In the port:
- the menu task stops at the call;
- the area applies
item::use_item_request's rules and answers with its steps in the same frame; - the menu task plays them where the call stood, and hands the world's
steps back one at a time (
useitem.rs).
So the Fortune Wire disarms a trapped box as in the game: "Disarmed trap." until the button, then the untrapped twin in the box's place. The recovery items, the books and the ocarina's steps now reach the world as well.
In event 4 itself the player never uses the wire: block 4 runs
remove_trap and then says "Orca used the Fortune Wire!". So two tests
cover the player's own path on a box put in the first room: the wire, and
the trapped box opened as it is.
The trap room's doors
How it looked. In the port the gate's bars sank from shut into the floor, then jumped back up.
The event. Block 6 runs open_door, waits a frame, then close_door.
It opens the doors so that the camera sees them shut.
The game's order. ccThEntryCtrl's first slice comes before the
event's first pass that plays. That slice sets up the entry control,
including ccEntryEventMng, whose CloseDoor shuts the room's doors;
only then does it breathe. ccSetupGameCtrl starts the task in the same
slice as ccEnableThEvent(4).
The port's order. It ran the set-up in the entry control's first loop
frame, after that pass, so the doors were shut again after open_door.
The set-up now runs a frame earlier (FieldWorld::entry_setup). The bars
come down from open over 46 frames with no jump, as in shots5's sequence.
The rest
- Room changes and the minimap. Shot a frame at a time over three
doors and the stairs, and compared with
GotoNextRoom,SetRoom,ClearRoomandDUNGEON::Draw:- the old room is dropped while the fade runs, as the game does;
- the party is placed and faces as in the game, and the camera resets;
- floor 1's minimap is drawn;
- the missing piece was the entry control's objects: nothing was kept, so each room's boxes and portals were lost.
- Cameras. A shot at each of event 4's camera instructions, all inside
their rooms. Walked into and along the first room's four walls for 600
frames: no frame has a wall between Kite's head and the camera.
cameraPosCalc's line test holds it 10 short of the wall. - Hosts. area_host has these now:
item_get_menuanditem_get_menu_end;remove_trap's effect;game_overfromcompulsionGameOver;clear_gate_hack;- the stream through
StreamPlayer::eventwith the area'sStreamGame.
Checked
eemu. Each of these compares the port with the game's own code run in eemu.
tools/test_battle_spawn_rs.py(all 6 tests pass):- the boxes' and idols' native constructors and
mains, with the virus crystal now inside the entry control's frames (frame); gim_frame: 150 cases, 0 mismatches;frame: 150 cases, 0 mismatches;circle_mainandframe_enemies: 150 cases each, 0 mismatches;SetItemBoxandSetIDOL: pass.
- the boxes' and idols' native constructors and
tools/test_fieldui_rs.py(36 tests): new scenarios for menus 32, 33 and 38 with 67 and 29. A mutated item count fails it.- The other suites:
- the fieldui personal, talk, trade, shop and option suites;
- dungeon_rt and dungeon_rs;
- world, foe, battle_enemy_motion, battle, battle_event and battle_items.
Runtime. cargo test -p piney-game runs these:
story_4_plays_through, which covers:- the 12 legs, and the rooms in order;
- each block's calls in its room;
- the tutorial's boxes, and the disarmed twin in the trapped box's place;
- Kite's HP unchanged through Orca's wire;
- floor 1's minimap;
- the dead end's box opened through 32;
- the Gott statue opened through 38;
- the save: the Resurrect and the spell one each, the idol's item,
itemBoxCount3 up,itemIdolCount1 up; - the desktop, with no host call left at its default.
the_fortune_wire_disarms_a_trapped_box.a_trapped_box_opened_as_it_is_goes_off.
The rest. The workspace's tests, clippy, fmt and the docs check pass.
- Palettes and sounds. The doors' palettes for clutType 3 and 4 (
ChangeClut) and their sound ids. - Missing effects.effOpenTrapBox,effStatueOfGod,effVirusCrystal, the breakables'effCrush*and the idol's dust ring are not in piney-effect. - Not ported yet: -EntryBreakObject; - the objects' menus 34-37 and 39; -DataDrainMenu(66). - Item steps without a runtime: - the map (WaitMapis 20 menu frames); - the Grunty ride; - the book viewer; - the epitaphs; -DisableThEvent. - The party AI's items. ItsUseItemRequeststill does nothing in the field. - The exact frame. WhetherccThEntryCtrl's first slice runs in the frame ofccEnableThEvent(4)or the next is inferred from the task order, not measured. What is certain is that the slice comes before the event's first pass that plays: event 4'sopen_door/close_doordepend on it.