Decode STINIT initial object states

This commit is contained in:
gamer147
2026-07-23 09:47:22 -04:00
parent 9c05451369
commit 1a9989b3ce
9 changed files with 98 additions and 30 deletions

View File

@@ -396,12 +396,15 @@ def extract_name(scr):
@cache
def object_type_definitions() -> dict[int, dict]:
"""Load OBINIT's authoritative names and descriptions keyed by object type id."""
"""Load OBINIT's authoritative display and state-row metadata by object type id."""
records, _ = extract_name(sys4load.load(resolve("OBINIT")))
return {
record["id"]: {
"name": record["name"],
**({"description": record["desc"]} if record.get("desc") else {}),
"uses_runtime_state_sprite_row": (
record.get("fields", {}).get("0xe6dee") == 1
),
}
for record in records
}
@@ -639,6 +642,10 @@ def attach_stage_object_placements(
obj["card_generation_list_id"] = payload.pop("0xe73bb")
elif 18 <= type_id <= 25 and "0xe73bb" in payload:
obj["non_triggering_faction_id"] = payload.pop("0xe73bb")
elif (definition
and definition["uses_runtime_state_sprite_row"]
and "0xe73bb" in payload):
obj["initial_object_state_id"] = payload.pop("0xe73bb")
unknown = payload
if unknown:
obj["unknown_fields"] = unknown

View File

@@ -166,13 +166,29 @@ def test_real_mixed_table() -> None:
for obj in all_objects
if "non_triggering_faction_id" in obj
} == {1, 2, 3}, "STINIT faction gates retain all observed faction ids")
state_objects = [
obj for obj in all_objects if "initial_object_state_id" in obj
]
check(len(state_objects) == 78,
"STINIT state-row metadata decodes every remaining initialized object state")
check({
obj["type_id"] for obj in state_objects
} == {11, 17, 26}, "STINIT state-row payloads remain scoped to proven object types")
deployment_flags = [
obj for obj in state_objects if obj["type_id"] == 26
]
check(len(deployment_flags) == 61
and {obj["initial_object_state_id"] for obj in deployment_flags} == {2},
"STINIT deployment flags expose their initial object state")
spike = next(
obj for obj in all_objects
if obj["type_id"] == 17 and "unknown_fields" in obj
obj for obj in state_objects if obj["type_id"] == 17
)
check(spike["unknown_fields"] == {"0xe73bb": 2},
"STINIT spike payload remains raw because FIELD excludes type 17 from the gate")
check(sum("unknown_fields" in obj for obj in all_objects) == 81,
check(spike["initial_object_state_id"] == 2
and "non_triggering_faction_id" not in spike,
"STINIT spikes expose state without inventing the excluded faction gate")
unknown_objects = [obj for obj in all_objects if "unknown_fields" in obj]
check(len(unknown_objects) == 3
and {obj["type_id"] for obj in unknown_objects} == {27},
"STINIT preserves unresolved tagged object payloads as raw evidence")
extract_init.attach_stage_enemy_spawns(records)
first_spawn = records[0]["enemy_spawns"][0]
@@ -195,6 +211,20 @@ def test_real_mixed_table() -> None:
"STINIT preserves weighted object-linked enemy alternatives")
check(sum(len(record["enemy_spawns"]) for record in records) == 1378,
"STINIT assembles every populated enemy spawn slot")
linked_deployment_spawns = []
for record in records:
objects_by_slot = {
obj["slot"]: obj for obj in record["object_placements"]
}
linked_deployment_spawns.extend(
spawn
for spawn in record["enemy_spawns"]
if (object_slot := spawn.get("object_slot")) in objects_by_slot
and objects_by_slot[object_slot]["type_id"] == 26
)
check(len(linked_deployment_spawns) == 63
and {spawn["faction_id"] for spawn in linked_deployment_spawns} == {2},
"STINIT deployment flags correlate with all linked enemy-faction spawns")
check(sum(
spawn.get("first_clear_only", False)
for record in records