From 2641a62106fad9d8440023c0796fec0fb38ed385 Mon Sep 17 00:00:00 2001 From: gamer147 Date: Fri, 24 Jul 2026 00:08:33 -0400 Subject: [PATCH] Decode selected movement routes --- docs/global-reference.md | 11 ++--- docs/name-resolution.md | 20 +++++++++- docs/phase-a-slice-plan.md | 24 +++++++++++ docs/vm-mapping-plan.md | 3 +- tools/test_globals.py | 82 ++++++++++++++++++++++++++++++++++++++ vm-map/globals.toml | 55 +++++++++++++++++++++++++ 6 files changed, 187 insertions(+), 8 deletions(-) diff --git a/docs/global-reference.md b/docs/global-reference.md index d43c934..db9c326 100644 --- a/docs/global-reference.md +++ b/docs/global-reference.md @@ -1,7 +1,7 @@ # Global Variable Reference (generated) -4275 globals (423 curated, 3852 auto shape-inferred). Source of truth: `vm-map/globals.toml`. +4276 globals (428 curated, 3848 auto shape-inferred). Source of truth: `vm-map/globals.toml`. ## choice-output @@ -195,9 +195,12 @@ | `0xb240e` | pathfinding_movement_costs | high | investigation | MVSEEK's row-major movement-cost work grid, indexed as [tile_y][tile_x] with stride 27. FIELD and RTN_M providers accept candidate destinations only when this cost is within the acting entity's current FS or a provider-specific override. | | `0xb8d86` | action_range_distance_grid | high | investigation | ATSEEK's row-major action-range flood-fill grid. It starts from the acting entity, expands through map-valid doubled-coordinate neighbors up to usable_action_max_range, and stores 1 for the first range band, 2 for the next, and so on. RTN_M051/052 select offensive targets from it; RTN_M061 selects in-range healing targets. | | `0xbf6fe` | pathfinding_filtered_route_scores | high | investigation | SETMVWORK begins by copying pathfinding_remaining_route_steps, then filters occupied entity cells according to faction and the acting entity's usable offensive-action mask/effectiveness. RTN_M providers combine this target-proximity score with a movement-limited MVSEEK grid to select a reachable tile nearest an entity or stage object. | +| `0xc6077` | selected_movement_route_steps | high | investigation | Selected movement-route work grid indexed as [tile_y][tile_x]. MVRTN, FIELD, and SETROUTE clear all 27,000 cells. SETROUTE starts at map_target_tile_x/y, copies pathfinding_remaining_route_steps into the route, and follows the cardinal neighbor whose score is one greater until it reaches the acting entity. FIELD uses the monotone values to draw directional route markers and drive movement; SELACT tests whether an action target follows movement; seventeen RTN_M providers reject candidate endpoints whose route cell is zero. | | `0xcc9f4` | offensive_action_scope_masks | high | investigation | CALCSCOPE clears ten encoded-range cells, sets bit 0 over the equipped/default attack's range, and sets bits 1..4 over each usable offensive skill's range. SETMVWORK uses the range-0 mask and paired attack elements when filtering target cells; RTN_M003/006/016/017/018 require its normal-attack bit. Columns: 0=range_0, 1=range_1, 2=range_2, 3=range_3, 4=range_4, 5=range_5, 6=range_6, 7=range_7, 8=range_8, 9=range_9. | | `0xcc9fe` | healing_action_scope_masks | high | investigation | CALCSCOPE clears ten encoded-range cells and sets the equipped-slot bit for each usable category-7 healing skill over its applicable range. RTN_M061 uses the masks to restrict ally targets and to select the range-enabled healing skill. Columns: 0=range_0, 1=range_1, 2=range_2, 3=range_3, 4=range_4, 5=range_5, 6=range_6, 7=range_7, 8=range_8, 9=range_9. | | `0xcca08` | offensive_action_attack_elements | high | investigation | CALCSCOPE stores the normal attack element in action column 0 and each usable equipped skill's attack element in columns 1..4 for every applicable range band. SETMVWORK and RTN_M051/052 test these elements against attack_element_effectiveness_percent. | +| `0xccbcf` | cardinal_tile_delta_x | high | investigation | INIT2's shared no-move-plus-four-cardinal-neighbor X offsets. SETROUTE uses indices 1..4 while tracing a selected route toward the acting entity; MVSEEK, ATSEEK, FIELD, SALLY, and DRAWMAP use the same neighbor order. | +| `0xccbd4` | cardinal_tile_delta_y | high | investigation | INIT2's Y offsets paired with cardinal_tile_delta_x. Indices 1..4 enumerate positive Y, negative X, negative Y, and positive X neighbors; index zero leaves the coordinate unchanged. | | `0xccc93` | stage_terrain_atlas | high | investigation | Immutable sparse half-tile terrain atlas loaded by MPINIT. Each footer copy writes fifty cells at row stride 53. FIELD doubles STINIT2's tile bounds and copies the selected rectangle into current_stage_terrain_grid; DRAWMINIMAP reads the atlas outside the active rectangle for border context, and RESETLAND restores changed cells from it. | | `0xe6aa4` | terrain_texture_slot_indices | high | investigation | LAINIT mapping from terrain id to the index in stage_map_texture_asset_overrides. DRAWMAP uses the selected slot to choose the current stage's tiled terrain surface. | | `0xe6ac2` | terrain_area_fill_flags | high | investigation | LAINIT terrain topology flag. DRAWMAP and CALCOCC use neighboring values to expand room-like regions across the alternating half-tile grid; DRAWMINIMAP uses the same distinction when joining adjacent revealed cells. | @@ -405,8 +408,6 @@ | `0xaba5f` | — | low | auto-shape | array | | `0xcca3a` | — | low | auto-shape | array | | `0xccb66` | — | low | auto-shape | array | -| `0xccbcf` | — | low | auto-shape | array | -| `0xccbd4` | — | low | auto-shape | array | | `0xccbd9` | — | low | auto-shape | array | | `0xccbf8` | — | low | auto-shape | array | | `0xccc11` | — | low | auto-shape | array | @@ -445,6 +446,8 @@ | `0x8c877` | current_item_id | high | investigation | Shared item-id argument/selection slot. Item menus and gameplay scripts write a chosen item id, use it to index ITINIT arrays, and dispatch through item_handler_script_id; ITMES compares it against all 287 item ids to select the matching player-facing title and description. | | `0xa6e59` | current_skill_id | high | investigation | Shared skill-id argument/selection slot. Skill menus and combat scripts write the chosen skill id and use it to index SKINIT arrays; SKMES compares it against all 131 skill ids to select the matching player-facing title and description. | | `0xaac76` | current_condition_id | high | investigation | Shared condition selector consumed by CALCILL, ADDILL, ADDILLSUB, DISARM, FIELD, and related condition handlers. It indexes the 30-column runtime condition rows and ILINIT definition arrays. | +| `0xccc0a` | map_target_tile_x | high | investigation | Shared map target/focus X coordinate. Seventeen RTN_M providers unpack candidate coordinates here before testing selected_movement_route_steps, FIELD and SETROUTE use it as the selected destination, and LOOK converts it to the centered world X coordinate when no enemy spawn slot is selected. Fifty-five scripts reference the paired target coordinates. | +| `0xccc0b` | map_target_tile_y | high | investigation | Shared map target/focus Y coordinate paired with map_target_tile_x. Movement providers unpack the low sixteen bits of candidate coordinates here; FIELD and SETROUTE select the route endpoint, while story scripts and LOOK use the same pair to center the battlefield camera on scripted map locations. | | `0xeff75` | current_routine_set_id | high | investigation | Shared RTINIT row selector. MVRTN loads the current entity's difficulty-selected movement routine set; BTRTN loads its battle routine set. Both then iterate routine_step_index across the selected twenty-slot row. | | `0xeff76` | routine_step_index | high | investigation | Shared RTINIT step selector. MVRTN and BTRTN iterate it from zero through nineteen and use it as the column index in every routine bank and matching per-entity runtime row. | | `0x1519f8` | current_card_id | high | investigation | FIELD's selected card-definition row. Card generation copies a surviving CDINIT card id here, uses it to test CDINIT2 story-flag gates, retains it through weighted selection, and indexes the chosen card's effects, graphics, name, and result text. | @@ -3766,10 +3769,8 @@ | `0x62ccb` | — | low | auto-shape | index/counter? | | `0x81c96` | — | med | auto-shape | record-table[stride 3] | | `0x8284e` | — | med | auto-shape | record-table[stride 3] | -| `0xc6077` | — | med | auto-shape | record-table[stride 27] | | `0xcc9f0` | — | low | auto-shape | index/counter? | | `0xccbdc` | — | med | auto-shape | record-table[stride 14] | -| `0xccc0b` | — | low | auto-shape | index/counter? | | `0xccc33` | — | med | auto-shape | record-table[stride 3] | | `0xe6c5e` | — | med | auto-shape | obinit-field | | `0xe6cc2` | — | med | auto-shape | obinit-field | diff --git a/docs/name-resolution.md b/docs/name-resolution.md index ddd1a08..bdb34c9 100644 --- a/docs/name-resolution.md +++ b/docs/name-resolution.md @@ -606,6 +606,21 @@ mode 2 additionally applies the foreign-entity terrain mask described above. Eve decrements `pathfinding_remaining_route_steps`, so origin minus target is the route-step distance used by M006/007/015. +The formerly unnamed `G[0xc6077]` stride-27 table closes the other half of that pathfinding ABI. It is +the reserved `1000 × 27` `selected_movement_route_steps` grid, not another search surface. MVRTN, +FIELD, and SETROUTE each clear all 27,000 cells. SETROUTE begins at `map_target_tile_x/y`, copies the +matching `pathfinding_remaining_route_steps` value, then walks the four `cardinal_tile_delta_x/y` +neighbors until it finds the cell whose score is one greater; it copies that score and repeats until +reaching the acting entity. The result is a one-cell-wide monotone route from actor to destination. + +FIELD reads that trail both to draw direction-specific route markers and to drive movement along +successive scores. SELACT checks whether an action target follows movement, while every provider from +RTN_M002 through RTN_M018 tests its candidate endpoint for a nonzero selected-route cell. Across the +corpus the grid has exactly 51 two-dimensional lookups and five clears in 21 scripts. INIT2 proves the +shared cardinal vectors as `[0, 0, -1, 0, 1]` for X and `[0, 1, 0, -1, 0]` for Y. The target coordinate +pair is broader than routing: 55 scripts also pass scripted map locations through it to LOOK, which +centers the battlefield camera on the selected tile. + `movement_steps` now carry these selector-scoped semantic fields beside the original `movement_parameter_1..4`, and top-level `movement_provider_parameter_schemas` records the reusable mapping, target-selection rules, zero/unwritten behavior, and authored fields proven unread by their @@ -618,8 +633,9 @@ The supporting runtime joins are now curated too: current HP/SP/FS, `entity_skill_flags`, the paired carried-item id/count slots, `stage_object_runtime_flags`, `movement_search_mode`, `offensive_action_scope_masks`, `pathfinding_remaining_route_steps`, -`pathfinding_filtered_route_scores`, `pathfinding_movement_costs`, and the per-entity patrol waypoint -index. The faction-specific terrain masks used by M013 are curated as +`selected_movement_route_steps`, `pathfinding_filtered_route_scores`, `pathfinding_movement_costs`, +the map-target coordinate pair and cardinal neighbor vectors, and the per-entity patrol waypoint index. +The faction-specific terrain masks used by M013 are curated as `tile_faction_traversal_masks`. M051's shared action-selection ABI also names `acting_entity_index`, `target_entity_index`, `action_range_distance_grid`, the shared usable-action range bounds, the offensive and healing range masks, the offensive element tables, diff --git a/docs/phase-a-slice-plan.md b/docs/phase-a-slice-plan.md index a9cc23f..060c992 100644 --- a/docs/phase-a-slice-plan.md +++ b/docs/phase-a-slice-plan.md @@ -3243,3 +3243,27 @@ Registry tests protect all 24 initialized slot cells, use of all three columns i INIT2 handle constants, and the canonical global/column names. **Next:** rank the next unnamed row table by shipped-reader evidence. + +## Data-semantics sidebar: selected movement-route grid (2026-07-23) + +The highest-use remaining auto-shaped row table, `G[0xc6077]`, is now closed as +`selected_movement_route_steps`. It is a reserved `1000 × 27` row-major map work grid. MVRTN, +FIELD, and SETROUTE clear all 27,000 cells; the complete corpus has 51 two-dimensional lookups and +five clears across 21 scripts. + +SETROUTE begins at `map_target_tile_x/y`, copies the matching +`pathfinding_remaining_route_steps` score into the selected-route grid, and follows the cardinal +neighbor whose score is one greater until it reaches the acting entity. This leaves a one-cell-wide +monotone trail from destination back to origin. FIELD uses that trail to draw directional arrows and +execute movement, SELACT tests whether an action target follows movement, and all seventeen providers +RTN_M002..RTN_M018 reject candidate endpoints with a zero route cell. + +INIT2's paired five-cell arrays are now named `cardinal_tile_delta_x/y`: the exact values are +`[0, 0, -1, 0, 1]` and `[0, 1, 0, -1, 0]`, preserving the no-move cell plus four-neighbor order. +The target coordinate pair also drives LOOK's scripted battlefield-camera centering and is referenced +by 55 scripts, so its names deliberately describe shared map targets rather than only AI destinations. + +Evidence regressions protect the exact corpus xrefs and clear geometry, all seventeen provider +readers, both SETROUTE flood-score copies, the INIT2 cardinal vectors, and every canonical name. + +**Next:** investigate the remaining unnamed stride-300 table at `G[0x15261f]`. diff --git a/docs/vm-mapping-plan.md b/docs/vm-mapping-plan.md index 52fdc72..67112c3 100644 --- a/docs/vm-mapping-plan.md +++ b/docs/vm-mapping-plan.md @@ -70,8 +70,9 @@ - [x] **2.3m — Extract `BTANINIT`/`BTANINIT2`'s battle-animation registry.** BTANINIT2 specialization classifies all 1,018 instructions into 122 sparse six-effect timelines, 573 effect references, paired start delays, and 111 complete durations. BTANINIT dispatch specialization classifies all 4,472 instructions into 202 visual/audio/hit-pulse definitions. BTL proves movie/sprite playback, blend, anchor, geometry, sound, and pulse semantics; SKINIT/ITINIT resolve skill and weapon-class selection. - [x] **2.3n — Extract `STINIT2`'s stage-definition registry.** Name/string-matrix specialization corrects the generic 321-record view to 74 sparse stages plus 296 strings in six pre/post-clear description slots, classifying all 1,634 instructions. FORT, FIELD, SELSTAGE, and STAGECLEAR prove main/EX flags, seven-column story gates, unlock groups, numbered/event presentation, map/minimap geometry, base point and three-coin rewards, and the loader contract. All 174 entry/clear/failure decisions resolve through SCINIT and all 74 loader ids resolve to STINIT. The remaining `0xedc4d` array has no shipped reader and is retained at medium confidence as the authoring-only stage difficulty tier: values 1..8 correlate with challenge/reward progression but have no runtime effect. - [x] **2.3o — Name the ADV layer surface-slot registry.** `G[0x3239]` is an eight-by-three primary/alternate/transition surface bank initialized by 143 scripts and read across 309. The common CG loader proves double-buffer selection and transition staging; INIT2 supplies the paired retained-object handles, and the companion resource, layer-index, live-slot, and handle globals are curated. +- [x] **2.3p — Name the selected movement-route grid.** `G[0xc6077]` is a reserved 1000-by-27 work grid carrying the one-cell-wide route copied from MVSEEK's remaining-step scores. SETROUTE proves the cardinal backtrace, FIELD proves route rendering and execution, SELACT proves move-before-action use, and RTN_M002..018 prove candidate-endpoint testing. The shared map target coordinates and INIT2 cardinal vectors are curated with it. - [x] **2.4 — Partial global-var map BUILT + wired into the disassembler.** `tools/global_map.py` → `build/global-var-map.{json,md}` (16,354/49,435 globals labelled: string tables, `*INIT` field arrays, 122 record tables w/ strides, current-entity index pointers). `sys4load` renders the labels inline (`=rec[s30]`, `=current-entity-index?`). See `docs/name-resolution.md`. -- [ ] **2.5 — Grow the global-var map (future, incremental).** Static first: RTINIT is closed at 1,043/1,043 movement steps; the RECOVER/ILINIT condition ABI, ALINIT recipes, AFINIT affinity/progression tables, CTINIT name palette, CVINIT character-voice registry, LAINIT terrain definitions, MPINIT stage-terrain atlas, SPINIT H-scene gallery, TRINIT training actions, CDINIT/CDINIT2 card selection/effects, BTANINIT/BTANINIT2 battle animations, STINIT2's complete stage surface, and the 309-script ADV layer surface-slot registry are closed; ITMES/SKMES/VIMES/EIMES/CIMES/MAMES are joined to their definitions; and the non-table INFOMES/MES ABIs are classified. Next, continue remaining consumer-led 2D table naming. Full detail: `docs/name-resolution.md` → "Future step — growing the map". Packed `call-script` ids, SCJUMP decision-to-scene dispatch, the shipped RTINIT movement-provider join, and the six completed message joins are resolved. +- [ ] **2.5 — Grow the global-var map (future, incremental).** Static first: RTINIT is closed at 1,043/1,043 movement steps; the RECOVER/ILINIT condition ABI, ALINIT recipes, AFINIT affinity/progression tables, CTINIT name palette, CVINIT character-voice registry, LAINIT terrain definitions, MPINIT stage-terrain atlas, SPINIT H-scene gallery, TRINIT training actions, CDINIT/CDINIT2 card selection/effects, BTANINIT/BTANINIT2 battle animations, STINIT2's complete stage surface, the 309-script ADV layer surface-slot registry, and the selected movement-route grid are closed; ITMES/SKMES/VIMES/EIMES/CIMES/MAMES are joined to their definitions; and the non-table INFOMES/MES ABIs are classified. Next, continue remaining consumer-led 2D table naming. Full detail: `docs/name-resolution.md` → "Future step — growing the map". Packed `call-script` ids, SCJUMP decision-to-scene dispatch, the shipped RTINIT movement-provider join, and the six completed message joins are resolved. ## Phase 3 — Name the unnamed opcodes *(top ~20 BEFORE Phase 4; the rest on demand)* diff --git a/tools/test_globals.py b/tools/test_globals.py index 24402f4..f6e0a0b 100644 --- a/tools/test_globals.py +++ b/tools/test_globals.py @@ -163,6 +163,13 @@ def test_load_and_lint(): "stage-object targeting flags are curated") check(entries[0xb240e]["name"] == "pathfinding_movement_costs", "movement-cost work grid is curated") + check(entries[0xc6077]["name"] == "selected_movement_route_steps" + and entries[0xc6077]["type"] == "int[1000][27]" + and entries[0xccbcf]["name"] == "cardinal_tile_delta_x" + and entries[0xccbd4]["name"] == "cardinal_tile_delta_y" + and entries[0xccc0a]["name"] == "map_target_tile_x" + and entries[0xccc0b]["name"] == "map_target_tile_y", + "selected movement route grid and coordinate helpers are curated") # lint clean against a permissive address universe (curated addrs are self-consistent) errors, warnings = G.lint(entries, set(entries)) check(errors == [], f"globals.toml lints clean (errors={errors})") @@ -227,6 +234,80 @@ def test_adv_layer_surface_slot_evidence(): == expected_handles, "INIT2 seeds the nine ADV retained-object handles") +def test_selected_movement_route_grid_evidence(): + target = 0xc6077 + refs = [] + clears = [] + loaded = {} + for name, path in paths.scripts().items(): + if path.read_bytes()[:8] != b"SYS4422 ": + continue + script = sys4load.load(path) + loaded[name] = script + for index, instruction in enumerate(script.instructions): + if not any(arg[1] == target for arg in instruction.args): + continue + refs.append((name, instruction)) + if instruction.opcode == 0x6c: + clears.append((script, index, instruction)) + + check(len(refs) == 56 + and sum(instruction.opcode == 0x12c for _, instruction in refs) == 51 + and len(clears) == 5 + and len({name for name, _ in refs}) == 21, + "selected route grid has the exact 51 lookups and five clears in 21 scripts") + + clear_geometry_ok = True + for script, index, instruction in clears: + previous = script.instructions[index - 1] + clear_geometry_ok &= ( + previous.label == "mul" + and previous.args[1:] == [(0, 1000), (0, 27)] + and instruction.args[1] == previous.args[0] + ) + check(clear_geometry_ok, + "every selected route-grid clear covers the reserved 1000 by 27 cells") + + providers = { + name for name, instruction in refs + if name.startswith("RTN_M") and instruction.opcode == 0x12c + } + check(providers == {f"RTN_M{provider:03d}.BIN" for provider in range(2, 19)}, + "all seventeen RTN_M002..RTN_M018 providers test selected route endpoints") + + setroute = loaded["SETROUTE.BIN"].instructions + copy_pairs = 0 + for index in range(len(setroute) - 2): + first, second, third = setroute[index:index + 3] + if (first.opcode == 0x12c + and (3, 0xaba96) in first.args + and second.opcode == 0x12c + and (3, target) in second.args + and third.label == "mov" + and third.args == [(12, 1), (12, 0)]): + copy_pairs += 1 + check(copy_pairs == 2, + "SETROUTE copies flood-fill scores into the destination and each traced route tile") + + init2 = loaded["INIT2.BIN"] + footer_refs = { + instruction.args[0][1]: instruction.args[1][1] + for instruction in init2.instructions + if instruction.opcode == 0x64 + and instruction.args[0] in {(3, 0xccbcf), (3, 0xccbd4)} + } + vectors = {} + for address, offset in footer_refs.items(): + count = init2.dwords[offset] + vectors[address] = [ + value if value < 0x80000000 else value - 0x100000000 + for value in init2.dwords[offset + 1:offset + 1 + count] + ] + check(vectors == { + 0xccbcf: [0, 0, -1, 0, 1], + 0xccbd4: [0, 1, 0, -1, 0], + }, "INIT2 defines the no-move plus four-cardinal-neighbor vectors") + def test_merge_precedence(): curated, _ = G.load_toml(paths.VM_MAP / "globals.toml") auto = G.load_auto(paths.BUILD / "global-var-map.json") @@ -290,6 +371,7 @@ if __name__ == "__main__": test_load_and_lint() test_lint_catches_bad_vocab() test_adv_layer_surface_slot_evidence() + test_selected_movement_route_grid_evidence() test_merge_precedence() test_sys4load_labels_from_registry() test_miner_finds_known_flags() diff --git a/vm-map/globals.toml b/vm-map/globals.toml index 53f6f7e..2887dfc 100644 --- a/vm-map/globals.toml +++ b/vm-map/globals.toml @@ -1817,6 +1817,61 @@ source = "investigation" confidence = "high" depends_on = ["0x4e11b", "0x5231f", "0x52351", "0xcc9f1"] +[[global]] +address = "0xc6077" +name = "selected_movement_route_steps" +category = "data-table" +type = "int[1000][27]" +value_domain = "0 outside the selected route; positive remaining flood-fill score on route tiles" +usage = "Selected movement-route work grid indexed as [tile_y][tile_x]. MVRTN, FIELD, and SETROUTE clear all 27,000 cells. SETROUTE starts at map_target_tile_x/y, copies pathfinding_remaining_route_steps into the route, and follows the cardinal neighbor whose score is one greater until it reaches the acting entity. FIELD uses the monotone values to draw directional route markers and drive movement; SELACT tests whether an action target follows movement; seventeen RTN_M providers reject candidate endpoints whose route cell is zero." +source = "investigation" +confidence = "high" +depends_on = ["0x5231f", "0x52351", "0xaba96", "0xccbcf", "0xccbd4", "0xccc0a", "0xccc0b"] + +[[global]] +address = "0xccbcf" +name = "cardinal_tile_delta_x" +category = "data-table" +type = "int[5]" +value_domain = "[0, 0, -1, 0, 1]" +usage = "INIT2's shared no-move-plus-four-cardinal-neighbor X offsets. SETROUTE uses indices 1..4 while tracing a selected route toward the acting entity; MVSEEK, ATSEEK, FIELD, SALLY, and DRAWMAP use the same neighbor order." +source = "investigation" +confidence = "high" +depends_on = ["0xccbd4"] + +[[global]] +address = "0xccbd4" +name = "cardinal_tile_delta_y" +category = "data-table" +type = "int[5]" +value_domain = "[0, 1, 0, -1, 0]" +usage = "INIT2's Y offsets paired with cardinal_tile_delta_x. Indices 1..4 enumerate positive Y, negative X, negative Y, and positive X neighbors; index zero leaves the coordinate unchanged." +source = "investigation" +confidence = "high" +depends_on = ["0xccbcf"] + +[[global]] +address = "0xccc0a" +name = "map_target_tile_x" +category = "index-pointer" +type = "int" +value_domain = "map tile X coordinate; shipped immediate assignments are 2..24" +usage = "Shared map target/focus X coordinate. Seventeen RTN_M providers unpack candidate coordinates here before testing selected_movement_route_steps, FIELD and SETROUTE use it as the selected destination, and LOOK converts it to the centered world X coordinate when no enemy spawn slot is selected. Fifty-five scripts reference the paired target coordinates." +source = "investigation" +confidence = "high" +depends_on = ["0xc6077", "0xccc0b"] + +[[global]] +address = "0xccc0b" +name = "map_target_tile_y" +category = "index-pointer" +type = "int" +value_domain = "map tile Y coordinate; shipped immediate assignments are 77..663" +usage = "Shared map target/focus Y coordinate paired with map_target_tile_x. Movement providers unpack the low sixteen bits of candidate coordinates here; FIELD and SETROUTE select the route endpoint, while story scripts and LOOK use the same pair to center the battlefield camera on scripted map locations." +source = "investigation" +confidence = "high" +depends_on = ["0xc6077", "0xccc0a"] + [[global]] address = "0xbf6fe" name = "pathfinding_filtered_route_scores"