Decode RTINIT movement providers 7 10 and 12

This commit is contained in:
gamer147
2026-07-23 15:32:20 -04:00
parent 7b3421a961
commit 52780d92a0
12 changed files with 228 additions and 36 deletions

View File

@@ -102,6 +102,62 @@ MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
"destination tile (or its linked type-6 stage-object exit tile)"
),
},
7: {
"behavior": "approach_injured_ally",
"parameter_fields": {
"movement_parameter_1": "maximum_target_route_steps",
"movement_parameter_2": "maximum_target_hp_percent",
},
"parameter_notes": {
"maximum_target_route_steps": (
"maximum flood-fill step distance from the acting entity; "
"shipped values are 5 or 10"
),
"maximum_target_hp_percent": (
"inclusive current-HP percentage cutoff; shipped values are "
"50, 70, or 80"
),
},
"target_selection": (
"nearest active non-self entity of the same faction whose current "
"HP percentage is at or below the cutoff; choose randomly among "
"ties, then approach a reachable tile nearest that ally"
),
"completion": (
"advance the current step's progress counter after producing a "
"valid movement destination toward the selected ally"
),
},
10: {
"behavior": "approach_healing_feather",
"parameter_fields": {
"movement_parameter_1": "resource_index",
"movement_parameter_2": "maximum_resource_percent",
},
"parameter_defaults": {
"movement_parameter_1": 0,
},
"parameter_notes": {
"resource_index": (
"0=HP, 1=SP, 2=FS; all shipped RTINIT cells are unwritten and "
"therefore use the zero/HP default"
),
"maximum_resource_percent": (
"inclusive current/max percentage cutoff; shipped values are "
"30 or 50"
),
},
"target_selection": (
"nearest active stage object of OBINIT type 15 (Healing Feather) "
"or 16 (single-use red Healing Feather), then approach a reachable "
"tile nearest that object"
),
"completion": (
"produce a movement result only when the selected resource's "
"maximum is nonzero, its current percentage is at or below the "
"cutoff, and a reachable Healing Feather exists"
),
},
11: {
"behavior": "cycle_destination_waypoints",
"parameter_fields": {
@@ -125,6 +181,22 @@ MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
"linked type-6 stage-object exit tile)"
),
},
12: {
"behavior": "approach_destination_tile_avoiding_foreign_entities",
"parameter_fields": {
"movement_parameter_1": "destination_tile_x",
"movement_parameter_2": "destination_tile_y",
},
"routing": (
"same destination and completion logic as RTN_M005, but MVSEEK "
"mode 2 masks the doubled-coordinate terrain cells occupied by "
"active entities of another faction before its flood fill"
),
"completion": (
"advance the current step's progress counter after reaching the "
"destination tile (or its linked type-6 stage-object exit tile)"
),
},
}
UNIT_STAT_COLUMNS = (
@@ -937,19 +1009,24 @@ def _movement_provider_names(names: dict[int, str]) -> dict[int, str]:
return providers
def _join_movement_provider_semantics(step: dict) -> int:
def _join_movement_provider_semantics(step: dict) -> tuple[int, int]:
"""Add selector-specific RTN_M semantics while retaining every raw bank."""
selector = step.get("movement_provider_selector")
schema = MOVEMENT_PROVIDER_PARAMETER_SCHEMAS.get(selector)
if schema is None:
return 0
return 0, 0
step["provider_behavior"] = schema["behavior"]
joined = 0
defaulted = 0
defaults = schema.get("parameter_defaults", {})
for raw_field, semantic_field in schema["parameter_fields"].items():
if raw_field in step:
step[semantic_field] = step[raw_field]
joined += 1
return joined
elif raw_field in defaults:
step[semantic_field] = defaults[raw_field]
defaulted += 1
return joined, defaulted
def extract_banked(scr):
@@ -969,6 +1046,7 @@ def extract_banked(scr):
bank_cells: dict[int, set[tuple[int, int]]] = collections.defaultdict(set)
decoded_movement_step_count = 0
decoded_movement_parameter_count = 0
decoded_movement_defaulted_parameter_count = 0
for offset, destination, value, bank_index, record_id, slot in writes:
bank_base = ROUTINE_BANK_ROOT + bank_index * ROUTINE_BANK_SPAN
@@ -1016,10 +1094,16 @@ def extract_banked(scr):
if selector is not None else {}
),
}
joined_parameter_count = _join_movement_provider_semantics(step)
(
joined_parameter_count,
defaulted_parameter_count,
) = _join_movement_provider_semantics(step)
if selector in MOVEMENT_PROVIDER_PARAMETER_SCHEMAS:
decoded_movement_step_count += 1
decoded_movement_parameter_count += joined_parameter_count
decoded_movement_defaulted_parameter_count += (
defaulted_parameter_count
)
movement_steps.append(step)
battle = {
@@ -1122,6 +1206,9 @@ def extract_banked(scr):
),
"decoded_movement_step_count": decoded_movement_step_count,
"decoded_movement_parameter_count": decoded_movement_parameter_count,
"decoded_movement_defaulted_parameter_count": (
decoded_movement_defaulted_parameter_count
),
"battle_provider_scripts": {
str(selector): name
for selector, name in sorted(battle_providers.items())