Skip to content

Commit fdee231

Browse files
sp00ktoberclaude
andcommitted
feat(mhfu-port): a port's turn curves leave its clips module for <port>_turns.lua
Only `mhfu move play --curve` reads them, and moves carry their own copy, so the game never loads the 31 KB module (the Zinogre's clips module: 35.8 -> 4.5 KB). mhfu.inject names a port's libraries for both packages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 7953152 commit fdee231

19 files changed

Lines changed: 76 additions & 50 deletions

File tree

‎apps/studio/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ on the floor of the view (T hides it) is the turn: an arrow for frame 0, one for
6666
a handle for the end, which drags the clip's `turn`, or a fixed steer's angle, in whole degrees
6767
(Shift: 15). Every edit is one undo step.
6868

69-
Play in game saves, writes the port's clips and moves modules to the memory stick's `mods/lib` as
69+
Play in game saves, writes the port's modules to the memory stick's `mods/lib` as
7070
`mhfu-port inject` does, and asks the running port to play the move by name; it refuses a move
7171
whose clip sits in another anim than in the saved manifest, since the game holds the build
7272
injected from the file. It writes only the modules that changed, and asks for the move from the

‎framework/include/mhfu/steer.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ typedef struct {
7272
uint8_t stuck_main, stuck_sub, stuck_mode; /* entered on a class-2 wall: em75's (0,6) mode 1 */
7373
uint8_t _pad[3];
7474
uint16_t keys[MHFU_STEER_KEYS]; /* YAW every KEY_STEP clip frames, the last at the clip's end:
75-
* the clips module's `_turns` (mhfu_port.travel.Turn) */
75+
* the port's turns module (mhfu_port.travel.Turn) */
7676
} mhfu_steer_spec_t;
7777

7878
/* struct STEER_STATE in addresses.toml */

‎framework/lua/meta/mhfu.d.lua‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ function mhfu.move_block() end
647647

648648
---How a move turns and stops (mhfu/steer.h); every field is optional.
649649
---@class mhfu.MoveSteer
650-
---@field curve? string YAW while the clip plays: the entry's string in the clips module's `_turns`
650+
---@field curve? string YAW while the clip plays: the entry's string in `<port>_turns.lua`
651651
---@field turn? "still"|"hunter"|"away"|"fixed" also: toward or away from the hunter at `rate`, or `total` over `frames`
652652
---@field rate? integer YAW units an AI frame toward or away, default 64 (the Tigrex charge's)
653653
---@field total? number degrees for "fixed", positive the way YAW grows

‎framework/mods/lua_host/bind_move.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ static int hex(int c)
7474

7575
/* t.steer (mhfu/steer.h): turn = "still" | "hunter" | "away" | "fixed", rate (YAW units a
7676
* frame), total (degrees) over frames, dir (degrees), walls, stuck = { main, sub, mode }, curve
77-
* = the clips module's _turns string for the entry */
77+
* = the entry's string in the port's turns module */
7878
static void steer_of(lua_State *L, int t, mhfu_steer_spec_t *sp)
7979
{
8080
mhfu_steer_init_spec(sp);

‎packages/mhfu-port/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ A manifest in `ports/` names the donor's files, the host and the build settings
1717
[`ports/`](../../ports)), and is the only input:
1818

1919
```bash
20-
uv run mhfu-port build ports/zinogre.toml # zinogre.bin, the model PAC, and zinogre_clips.lua
20+
uv run mhfu-port build ports/zinogre.toml # zinogre.bin, the model PAC, and its Lua modules
2121
uv run mhfu-port inject ports/zinogre.toml # the same, placed for the framework to load
2222
```
2323

‎packages/mhfu-port/src/mhfu_port/cli/build.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,13 @@ def _listed(written: list[Path]) -> str:
6565

6666

6767
def modules(m: manifest.Manifest, built: Built, where: Path, games: data.Data) -> list[Path]:
68-
"""Write the port's clips and moves modules into `where`, each whole and only when it
68+
"""Write the port's clips, turns and moves modules into `where`, each whole and only when it
6969
changed, since the game re-runs a module that changed on disk; those written. Raises
70-
`ManifestError` for a move the moves module cannot carry, before either is written."""
70+
`ManifestError` for a move the moves module cannot carry, before any is written."""
7171
known = moves.records(games.fu, m.port.host_species)
7272
texts = {
7373
layout.module_name(m): layout.lua(m, built.layout),
74+
layout.turns_module_name(m): layout.turns_lua(m, built.layout),
7475
moves.module_name(m): moves.lua(m, built.layout, known),
7576
}
7677
where.mkdir(parents=True, exist_ok=True)

‎packages/mhfu-port/src/mhfu_port/layout.py‎

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from collections.abc import Collection, Mapping
2020
from dataclasses import dataclass, field
2121

22+
from mhfu import inject
2223
from mhfu.entries import ENTRY_BANK, PART_STREAMS
2324
from mhp_formats.anim import AnimPack
2425

@@ -31,8 +32,7 @@
3132
ENTRIES = {75: 123}
3233
"""Executor entries per host species: the rows of its overlay's descriptor table (em75: dumped
3334
live). An unknown host gets one bank, or up to the last entry its own pack fills."""
34-
LIB = "lib"
35-
"""Where `require` finds a library, under the framework's mods directory."""
35+
LIB = inject.LIB
3636

3737

3838
class LayoutError(manifest.ManifestError):
@@ -249,20 +249,27 @@ def names(m: manifest.Manifest, layout: Layout) -> dict[int, str]:
249249

250250
def module_name(m: manifest.Manifest) -> str:
251251
"""The Lua module `mhfu_port`'s `P.define` requires for the port's clips."""
252-
return f"{m.port.name}_clips.lua"
252+
return inject.port_module(m.port.name, "clips")
253+
254+
255+
def turns_module_name(m: manifest.Manifest) -> str:
256+
"""The Lua module with the port's turn curves, which no mod needs: moves carry their own."""
257+
return inject.port_module(m.port.name, "turns")
253258

254259

255260
_IDENT = re.compile(r"[A-Za-z_][A-Za-z0-9_]*")
256-
TURNS = "_turns"
257-
"""The clips module's key for `Layout.turns`; no clip may take the name."""
261+
262+
263+
def _source(m: manifest.Manifest) -> str:
264+
return f"ports/{m.path.name}" if m.path is not None else f"the {m.port.name} manifest"
258265

259266

260267
def lua(m: manifest.Manifest, layout: Layout) -> str:
261268
"""The module: each clip's name -> its executor entry, and the MHP3rd id it holds."""
262-
src = f"ports/{m.path.name}" if m.path is not None else f"the {m.port.name} manifest"
263269
named = names(m, layout)
264270
out = [
265-
f"-- {module_name(m)}, GENERATED by mhfu-port from {src}: {len(layout.entries)} clips of",
271+
f"-- {module_name(m)}, GENERATED by mhfu-port from {_source(m)}: {len(layout.entries)}"
272+
" clips of",
266273
f"-- MHP3rd file {m.source.anim} by executor entry. Do not edit: rebuild. mhfu_port's",
267274
"-- P.define reads it as the port's clips (name -> entry).",
268275
"return {",
@@ -271,16 +278,22 @@ def lua(m: manifest.Manifest, layout: Layout) -> str:
271278
name = named.get(e)
272279
if name is None:
273280
continue
274-
if name == TURNS:
275-
raise LayoutError(f"clip name {TURNS} is the module's own key")
276281
key = name if _IDENT.fullmatch(name) else f'["{name}"]'
277282
out.append(f" {key} = {e}, -- MHP3rd {cid}")
278-
if layout.turns:
279-
out.append(
280-
f" -- entry -> YAW while it plays: 4 hex digits (0x10000 a turn) every {KEY_STEP}"
281-
" clip frames, the last at its end"
282-
)
283-
out.append(f" {TURNS} = {{")
284-
out += [f' [{e}] = "{t.lua()}",' for e, t in sorted(layout.turns.items())]
285-
out.append(" },")
286283
return "\n".join([*out, "}", ""])
284+
285+
286+
def turns_lua(m: manifest.Manifest, layout: Layout) -> str:
287+
"""The turns module: entry -> YAW while it plays. `mhfu move play --curve` reads it."""
288+
return "\n".join(
289+
[
290+
f"-- {turns_module_name(m)}, GENERATED by mhfu-port from {_source(m)}: entry -> YAW"
291+
" while it plays,",
292+
f"-- 4 hex digits (0x10000 a turn) every {KEY_STEP} clip frames, the last at its end."
293+
" Do not edit: rebuild.",
294+
"return {",
295+
*(f' [{e}] = "{t.lua()}",' for e, t in sorted(layout.turns.items())),
296+
"}",
297+
"",
298+
]
299+
)

‎packages/mhfu-port/src/mhfu_port/moves.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from collections.abc import Collection, Mapping
1818
from typing import Any
1919

20-
from mhfu import addresses, hitbox
20+
from mhfu import addresses, hitbox, inject
2121
from mhfu.files import Extracted, em_overlay
2222

2323
from .layout import Layout
@@ -41,7 +41,7 @@ def hub(species: int) -> Pair | None:
4141

4242
def module_name(m: Manifest) -> str:
4343
"""The Lua module `P.define` requires for the port's moves and rules."""
44-
return f"{m.port.name}_moves.lua"
44+
return inject.port_module(m.port.name, "moves")
4545

4646

4747
BUILD = re.compile(r"^ build = 0x([0-9A-F]{8}),$", re.M)

‎packages/mhfu-port/src/mhfu_port/travel.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ def at(self, frame: ArrayLike) -> fk.Floats:
338338
return _curve(_grid(self.frames), np.asarray(self.keys, dtype=np.float64))(frame)
339339

340340
def lua(self) -> str:
341-
"""The keys as 4 hex digits each, YAW's own 16 bits: the clips module's `_turns`."""
341+
"""The keys as 4 hex digits each, YAW's own 16 bits: the port's turns module."""
342342
return "".join(f"{k & 0xFFFF:04x}" for k in self.keys)
343343

344344

‎packages/mhfu-port/tests/test_build.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ def test_cli(data, tmp_path):
172172
port = m.port
173173
assert (tmp_path / port.pac).read_bytes() == out.read_bytes()
174174
assert (tmp_path / port.orig).read_bytes() == data.fu.read(port.host_frame)
175-
for module in (layout.module_name(m), moves.module_name(m)):
175+
for module in (layout.module_name(m), layout.turns_module_name(m), moves.module_name(m)):
176176
assert (lib / module).read_text() == (out.parent / module).read_text()
177177
assert " charge = 61, -- MHP3rd 61\n" in (lib / layout.module_name(m)).read_text()
178178
stamp = (lib / moves.module_name(m)).stat().st_mtime_ns

0 commit comments

Comments
 (0)