Skip to content

feat: hybrid ports wave 2: studio clips, walking, hit push, every clip in game, engine walls - #52

Merged
sp00ktober merged 64 commits into
mainfrom
hybrid/wave2
Oct 6, 2026
Merged

sp00ktober merged 64 commits into
mainfrom
hybrid/wave2

Conversation

@sp00ktober

@sp00ktober sp00ktober commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Wave 2 of hybrid ports: clips named and played from the studio, walking and area changes by named points, live hit-table pushes, every Zinogre clip measured in the game, and the engine's wall, movement, spawn and reaction functions. For sp00ktober/MHFU-ModKit#97, #98, #99, #100, #101.

  • Clips in the studio (studio, mhfu-port): every donor clip by MHP3rd id, previewed (also those no entry holds), named and placed; a name pins nothing ([clips.x] with source only), a placement pins and swaps, undo works, the manifest round-trips. Play in game holds the clip's entry through mhfu.live.clips (3/3 body parts, ~3.5 s, measured live).
  • Packing (mhfu-port): every donor id under the host's entry count goes to its own entry, so 100–122 carry the odd streams (the Tigrex's brain asks for them). Zinogre: 20 stream-1 clips in 100–122, the four stream-2 clips in 50/53/55/56.
  • Every clip in the game (mhfu clips ride|play|sweep|release, cli_bridge.lua): cold boot with a port riding the Tigrex, hold each entry, read every part's clip block. Zinogre 102/102 on every part (re-measured after the merge), Brute 77/77.
  • Walking (mhfu rig goto|walk, mhfu.points, studio Point tool and Points panel): named points in map.toml; goto changes area by a GameTask request in ~2 s (camp → section 8: 15/15). walk routes over every stage's collision from the extracted files, with climbs (material 9/10 walls and roots), ledges and drops: camp → section 8, → section 3 and → section 7 through section 2, each 3/3. Departure press no longer loses ~12 s.
  • Hit push (studio port push, Push to game): one write plan for hurtboxes, grid and hitboxes, with guard bytes; the Lua module carries the same plan as data. Read-back 0.03–0.22 s; on the native Tigrex the charge's damage halved with its power (72 → 36 HP).
  • Engine functions (addresses.toml, mhfu observe): wall contact and the stuck state, position/yaw/ground writers, the attack spawner (callable from the debugger), the reaction check; trace() now flushes the JIT so every armed breakpoint fires.
  • Lanes: the memory stick (inject, studio) follows MHFU_LANE; a lane hides its window once it listens.
  • Shared: mhfu.entries (MIT, stdlib only) owns the entry arithmetic mhfu-port and the live tools use; ENTITY.PREV_MAIN/SUB are TICK_MAIN/SUB, the pair the action tick last ran.

Tests: 2124 passed, 45 skipped (GL, Blender, live), with both games' data, studio, hud and blender included; pre-commit clean. Live gates measured in lanes 1–4.

🤖 Generated with Claude Code

sp00ktober and others added 30 commits October 6, 2026 17:01
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The packer's layout is the base and each manifest clip pins on top of it: the
clip the packer had in a pinned entry takes the entry the pin freed. Naming a
clip where it sits moves nothing; placing it swaps. pin, place and moved are
the edits and their diff.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… latch

mhfu_port owns the one Lua executor hook, so a second registration
replaced it. The bridge now loads the runtime first, latches the port
that drives the target, and registers its own hook only for a monster no
port drives, filtered to that monster.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CLIP_BLOCK is one body part's clip player: cursor, speed, end and the
clip node inside the animation pack. structs.entry_clip is the
resolver's arithmetic, the stream and slot a part plays for an entry.
Bridge.request sends a command and waits for its ack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… writes

ppsspp-debug's trace() also arms log-only write watchpoints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed as lua

runtime.plan computes every hit-table write from the manifest and the host's
intel: where each record goes, how many fit, and guard bytes no write changes.
The generated <name>_hit.lua carries the plan as data and mhfu_port.lua only
applies it; `studio port push` and the panels' Push to game write the same
plan through the debugger and read it back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t's clip

clips.play holds an entry through the bridge, restarts the action when
no dispatch comes, and reads every part's clip block: the clip node
against the animation pack's slot tables in RAM, its frames and its
cursor. sweep checks a whole build against `mhfu-port slots`; ride
deploys the bridge, the runtime and a rider mod for a port and cold
boots into the quest it replaces a monster in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…time

A lane given as --lane, not MHFU_LANE, sent the rider to the owner's
stick. deploy now also removes a rider it generated for another port, so
two never replace the same monster.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PPSSPP retranslates only the last address a breakpoint change touched in a
frame; a watchpoint change drops all translated code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e hunter's exit flag

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…retch it

walk_path also stops on until and passes patience and detours on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ayed in game

ClipBrowser lists the donor's clips against the document's layout and
places one as a document edit; a clip the layout leaves out plays from a
one-clip build on the port's rig. The workspace builds the port again when
an edit or its undo moves a clip. clip_game forces a clip's anim on the
running big monster through cli_bridge.lua, refused while the anim differs
from the saved manifest's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…live

Floor.read takes the chunk (the floor by default) and Floor.triangles yields each triangle
with its surface, material and exclude mask.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Some Tigrex handlers put the body and tail back on their idle right
after a dispatch, so a forced entry reaches the head alone now and then;
a second play gets the whole body.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both halves of the resolver's arithmetic are measured now: the Zinogre
port's 102 clips, 100-103 among them, and a variant's 104-122 play on
every body part at the frames the build holds. An empty slot keeps the
part's clip, and the Tigrex's 24 and 25 reach the head alone. The clip
blocks and `mhfu clips` are how to read it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rows by id with the anim each plays in; the arrow keys step and play,
Return in Shows names the clip and moves to the next. Place moves a clip to
another anim; Play in game and Release drive the running big monster.
Without the donor the panel lists the build's anims as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… built

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Under mhfu_port cli_bridge.lua ticks at 2 Hz, and one tick in forty ran
past the old 1 s, which ended a clips sweep.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A quest hunter does not move on a stick of 0.5 or less (measured in the snowy camp), so the old
ease-off stopped him about 100 units short and every close arrival read as blocked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed anim's

The anim picked last, from any panel, names the clip; a placed clip is
picked again in its new anim, and the viewport follows it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A brain in a pair that dispatches every frame restarts a held clip each
time, so its cursor stands at 0; a pause off the hold and another try
gets it playing. The pair at the read goes into the sweep's CSV.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d spawner functions

The previous-pair cells are the pair the action tick last dispatched; the
attack spawner ignores its first argument.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sp00ktober and others added 26 commits October 6, 2026 18:12
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t run on

Measured: fast-forwarded, the 5 s hold after the second section-1 ledge carried the hunter
through two areas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`mhfu clips sweep` on the Brute build: 77 of 77 entries on the build's
clip and frames in every body part.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h --calm

A calmed species keeps a zero sight radius after the walk, which would leave the next
experiment's monster blind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	packages/mhfu/src/mhfu/addresses.toml
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… its own entry

Entries 100-122 play the odd streams in the game, and the Tigrex's brain asks for them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	packages/mhfu/src/mhfu/structs.py
… pack base, as measured

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
open -j leaves a cold boot's window on screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mhfu.live.clips

The bridge acked a held anim that an idle Tigrex never dispatched; clips.play kicks it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fu-port imports

mhfu.entries replaces the copies in mhfu.structs and mhfu_port.fk; mhfu.inject loads ppsspp_debug
only for a lane again, so the Blender add-on imports it without psutil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the loader does

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e route crosses stages by their files

Material 9 and 10 faces and the hunter-height steps no material marks become climbs from the
collision. Map.route floods each stage's file from where the hunter enters it, so an exit counts
only if a walk and its climbs reach it; it replaces the fewest-exits route.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…context

A workspace's refresh may rebuild GL objects (the monster workspace builds
the port again when an undo moves a clip); like an act, it now runs inside
gl_current.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clip.slot is optional: a name alone records the MHP3rd source and pins
nothing, a slot pins. layout.plan stays the one owner of placement; every
reader of a clip's anim (the studio's tracking, validation, alignment,
actions, scene names, commands and mhfu-port slots) asks it through
layout.where. The studio names without pinning, also a clip in no anim, and
Place pins only the clip it moves, a pinned clip in its way swapping.

The shipped ports' 22 named clips (Zinogre 21, Brute 1) sat in their packer
entries; they are names now, no slot, and both layouts are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tick last ran

Every species' tick copies the current pair there first thing, so they never held the previous one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nce, kinds and drops named

A climb ran fast-forwarded missed its grab about half the time; one started from a sample
behind a fence walked into the fence. Faces are joined transitively; a hand-set climb point
replaces the found climbs beside it; walking off a cliff is a Drop step; climbs say whether a
climbable wall, a ledge or a point gave them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cliff face walls the samples at its foot, which a walk keeps off; the planner found no way
off section 3's shelf. Levels next to a wall are now entered by a drop only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sp00ktober
sp00ktober merged commit 2fda613 into main Oct 6, 2026
5 checks passed
@sp00ktober
sp00ktober deleted the hybrid/wave2 branch October 6, 2026 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant