rrt/docs/control-loop-atlas/station-detail-overlay.md

21 KiB

Input, Save/Load, and Simulation: Station-detail Overlay

Station-detail overlay

The shell-side candidate preview pair now has a grounded world consumer too. world_render_station_candidate_service_map_overlay at 0x0043f640 reads the active (station id, candidate id) pair from world_store_station_detail_candidate_service_preview_pair_globals 0x0043f620 and world_clear_station_detail_candidate_service_preview_pair_globals 0x0043f610, scans the placed-structure collection, and then splits the legend by candidate mode. When the active candidate carries a nonzero route-style byte at [candidate+0x46], the overlay uses the heavier helper placed_structure_query_candidate_directional_route_overlay_summary at 0x0047e690 in both directions between the preview station and each scanned site and formats the resulting directional rows as 3874 Coming To %1 and 3875 Going From %1. When that byte is zero, the same overlay falls back to the direct local-service path through placed_structure_query_candidate_local_service_metrics and formats the two legend rows instead as 3876 Current Supply @ < %1 and 3877 Current Demand @ > %1. Empty directional lanes collapse to 3878 --None--, and one title lane falls back to literal All. Current disassembly no longer supports treating 3872 Already Connected by Another Company or 3873 Not Connected as direct overlay-body emits.

Corrected boundary

The neighboring connection-state note pair now appears to live in a city connection-bonus label formatter, not in 0x0043f640. That formatter is now bounded as city_site_format_connection_bonus_status_label at 0x004207d0: it directly chooses localized ids 3868 through 3873 after consulting the reusable city-peer scan city_connection_bonus_exists_matching_peer_site at 0x00420030. Separately, 3879 Out of Sync is grounded under the multiplayer preview dataset path instead: multiplayer_preview_dataset_service_launch_state_and_warn_out_of_sync at 0x0046b780 checks global 0x006cd91c, raises the Out of Sync shell status through 0x5386e0, and then continues through the wider multiplayer preview launch-state service. So the station-detail overlay currently owns only the Coming To, Going From, Current Supply, Current Demand, --None--, and All legend lanes.

The shell-side preview arm or clear path above that overlay is explicit now too. shell_station_detail_clear_active_candidate_service_preview 0x00504a90 resets the shared (station id, candidate id) pair, drops the local preview latch at [window+0x7c], decrements the sibling global refcount 0x0062be84, and on matching live world-preview state tails into world_clear_aux_preview_mode_0x2171_and_overlay_companion_live_flag 0x00452d30. shell_station_detail_set_active_candidate_service_preview 0x00504ae0 first clears any prior preview, then for a nonzero candidate id pushes the current station and candidate through the world-side setter strip 0x00452f60, 0x00452d80, 0x00452db0, and 0x00452ca0 before latching [window+0x7c], incrementing 0x0062be84, and storing the active pair back into 0x005ee4fc/0x005ee500. That closes the shell-to-world preview seam end-to-end: row callbacks arm or clear one explicit candidate pair, and the world-side overlay consumes exactly that pair.

That formatter boundary is tighter now too. 0x004207d0 returns 0 immediately when preview-global 0x0062be84 is armed, forwards directly into the shared fallback formatter 0x00455860 when subtype dword [this+0x23e] is nonzero, and only otherwise runs its own connection-status path. On that main path it rounds the current normalized city coordinates, samples one world-view-dependent alpha byte through world_view_query_city_label_alpha_byte_from_normalized_xy_and_view_scalars 0x0043ad50, and then tries to resolve one linked station-or-transit site through the active selection or scenario fallback object. When that linked-site path succeeds, the formatter forces a highlighted top color lane with alpha 0xff and appends localized id 207 (Connected); when it does not, it only reuses the sampled byte from 0x0043ad50 when that value is nonzero and below 0xff. The tail also splits cleanly now: one branch returns style code 1, while the other derives one label-priority scalar from [this+0x25e] or the piecewise-scaled [this+0x312] path, clamps that priority to 0x95, resolves the final style through 0x0053de00, and returns style code 3.

Ownership side

One reusable site helper is grounded now too. placed_structure_query_linked_company_id at 0x0047efe0 resolves the current placed structure's linked instance through 0x0062b26c and returns its company id from [instance+0x276]; the adjacent city bonus formatter at 0x004207d0 compares that id against the active company selector before choosing whether a scanned site should carry 3871 Connected By Another Company or 3872 Already Connected by Another Company. The larger caller boundary is no longer open either: the first bounded announcement owner above this formatter family is now company_evaluate_and_publish_city_connection_bonus_news at 0x00406050, which re-enters the peer-route candidate builder at 0x004046a0 and later publishes one of the localized city-connection bonus news strings 2888, 2890, or 2921 through the shell news path.

Peer-selector side

The city bonus formatter no longer depends only on boolean peer existence. The companion helper city_connection_bonus_select_first_matching_peer_site at 0x00420280 is now grounded as the first-match selector paired with city_connection_bonus_exists_matching_peer_site: it walks the same city-peer candidate set, applies the same site-class table plus the narrower station-or-transit and linked-instance class-byte flags, and returns one representative matching peer site id instead of a boolean. city_site_format_connection_bonus_status_label reuses that selector after the note checks so it can recover one linked company context from the selected peer. The broader caller side can now be carried conservatively as the city-connection and company-start announcement ladder above this formatter family, not as another unresolved edge inside the peer-scan pair itself.

Caller side

The reusable bridge between the status formatter and the company news lane is now bounded too. city_connection_bonus_build_peer_route_candidate at 0x004046a0 reuses city_connection_bonus_select_first_matching_peer_site with both selector flags forced on, rounds both the source-city and selected-peer normalized coordinates through 0x005a10d0, and then first tries the shared heavy builder city_connection_try_build_route_with_optional_direct_site_placement 0x00402cb0 when the caller already supplied a live route-anchor tuple. When that direct attempt does not apply or no peer survives, it falls back to the smaller wrapper city_connection_bonus_try_compact_route_builder_from_region_entry 0x00404640; and when both early attempts fail it builds one mixed 10-byte candidate list from the dense pair store 0x006cfcb4 and the route-entry store 0x006cfca8, marks only route-anchor-eligible class-2 sites through the 0x0048a1c0/0x0048a1a0/0x0048f290 route-anchor tests, and then retries 0x00402cb0 with the best surviving span-ranked candidate. The score side of that announcement lane is tighter now as well: city_compute_connection_bonus_candidate_weight at 0x004010f0 provides the per-city opportunity weight, company_query_min_linked_site_distance_to_xy at 0x00405920 provides the nearest linked-site distance term, company_count_linked_transit_sites at 0x00426590 provides one of the company-side caps, company_compute_connection_bonus_value_ladder at 0x00425320 supplies the bounded company-side value scalar, and company_compute_prime_rate_from_issue39_scenario_baseline at 0x00424580 now bounds the shared prime-rate-side helper that this lane reuses beside the raw issue-0x39 total, scenario_state_sum_issue_opinion_terms_raw at 0x00436710 now bounds the raw additive issue-total helper beneath that term, and company_connection_bonus_lane_is_unlocked at 0x00427590 is the small boolean gate above the ladder. Wider governance and CompanyDetail xrefs now tighten slot 0x2b into the rolling net-profits lane reused by annual finance checks and a per-share/history formatter, while the report-history descriptor table now aligns raw slot 0x09 with the Income Statement fuel-cost lane surfaced by tooltip 1309. The wider result now reads more like recent net profits minus recent fuel burden than a governance-pressure term. That now also sharpens the annual finance lane at 0x00401c50: the first bankruptcy branch reads as sustained cash-and-debt stress over recent profits and fuel burden, the later fallback branch as a deeper -300000 cash / three bad years cleanup trigger, and the later stock-issue branch reads as a price-to-book-versus-coupon approval ladder rather than a generic support vote. The tail is cleaner now too: it compares total retired versus newly issued principal to choose the 2882..2886 debt headline family, then publishes 2887 separately from the accumulated repurchased-share count. The sibling news owner above the same city-pair route family is bounded now too: simulation_try_select_and_publish_company_start_or_city_connection_news 0x00404ce0 filters and scores candidate city entries, re-enters the same shared heavy builder through city_connection_try_build_route_between_region_entry_pair 0x00404c60 for the dense pair sweep and the final retry, and then publishes 2889 %1 has started a new company - the %2 or 2890 %1 has connected %2 to %3. through the shell news path. Wider governance and shell xrefs now close that last 0x39 ambiguity too: company_compute_prime_rate_from_issue39_scenario_baseline 0x00424580, the CompanyDetail and bond-side notes, and the already-grounded Prime Rate label family all point at the same metric, so this city-connection branch is reusing the explicit issue-0x39 prime-rate lane rather than a separate public-opinion or management-attitude family. The local static seam on this branch is therefore closed: 0x39 itself is no longer ambiguous here, and the wider company-start or city-connection ladder can now be carried conservatively as a recent-profit/fuel-burden pressure lane layered beside the already- grounded prime-rate term.

The ordinary StationDetail.win caller strip is tighter now too. In the non-scenario, non-class 3/4 branch, shell_station_detail_window_refresh_controls 0x00506610 rebuilds the nearby-site lane first through shell_station_detail_refresh_nearby_structure_jump_rows 0x00505470, then rebuilds the paired hauled-traffic widgets through two calls to shell_station_detail_build_to_from_haul_summary_widget 0x00505150. That hauled-traffic helper does more than publish a heading: it normalizes the incoming float lane into a bounded ten-step fill count, resolves per-step styles through 0x0053de00/0x00552560, and on first build wires the matching 0xb3f6 or 0xb3f7 click target back to shell_station_detail_present_to_from_haul_stats_popup 0x00504770 through 0x00540120. The nearby-site helper has a similarly concrete split now: for each of the fixed five categories it counts entries through 0x0047dc90, emits the descriptive text block through 0x0051b700 -> 0x0053f9c0, and then builds the paired jump-control payload through 0x0053b070 -> 0x0055a040 -> 0x0053f9c0, with text rows under 0xb40a..0xb40e and jump controls under 0xb410..0xb414. So the local static seam in the ordinary branch is closed: the ownership of those lanes now belongs to the concrete refresh helpers named here, and the later callers above them can now be carried conservatively as the ordinary station-summary presentation lane rather than as a separate unresolved user-facing family. The helper strip directly beneath that ordinary branch is explicit now too. shell_station_detail_clear_dynamic_rows_and_haul_widgets_if_dirty 0x005042c0 uses dirty latch 0x006d16f0 plus the live window singleton 0x006d16d8 to clear the candidate-service and nearby-site row bands 0xb414..0xb5a3, 0xb40a..0xb413, and 0xb400..0xb409, then disables the paired haul controls 0xb3f6 and 0xb3f7 before resetting the latch. The current-subject gates above the lower action strip are tighter in the same way: shell_station_detail_has_valid_selected_station 0x00504370 is the narrow selected-station presence probe over detail-manager state [0x006d0818+0x90], while shell_station_detail_selected_station_belongs_to_selected_company 0x00504390 resolves that same station and compares its linked company through placed_structure_query_linked_company_id 0x0047efe0 against the active selected company from 0x004337a0. The ownership-blocked modal above that gate is explicit too: shell_station_detail_present_selected_station_not_controlled_notice 0x005043f0 formats localized id 3595 with the owning railroad name when that owner resolves and otherwise falls back to the empty-string root before opening the standard shell message-box path at 0x004c98a0. One remaining local helper is no longer anonymous either: shell_station_detail_refresh_class_partitioned_action_controls_0xb3bb_to_0xb3bf 0x005044b0 restyles the lower action controls into affordance states 0x65 or 0x87 according to the linked candidate class byte [candidate+0x8c], keeping 0xb3bb/0xb3bd/0xb3be active only for class 0 and 0xb3bc/0xb3bf active only for class 1. That closes the helper seam beneath shell_station_detail_window_handle_message 0x00505e50 and shell_station_detail_window_refresh_controls 0x00506610: the branch now reads cleanly as the linked-site mutation action lane above those message and refresh owners, not as a remaining helper-side seam. One layer higher, the lower action dispatch is no longer opaque either. In the message-0xcb path, shell_station_detail_window_handle_message first reduces the clicked control to one small family split: 0xb3bd selects family 1, while the sibling controls select family 2. It then reduces linked-site flag bits [entry+0xc3] to one action index 0..5 and resolves the resulting (action_index, family) pair through aux_candidate_collection_find_entry_id_by_station_detail_action_index_and_family 0x00419590, which formats one localized action stem from the fixed tables at 0x005f3c6c/0x005f3c80 and scans the auxiliary candidate pool 0x0062b2fc for the first matching stem at [entry+0x04]. Only after that auxiliary id resolves does the branch enter the deeper world-side validation owner placed_structure_validate_station_detail_aux_candidate_action_and_optionally_apply_linked_site_mutation 0x0040dc40 plus the two confirmation-modal branches rooted at localized ids 0x0bfe and 0x0bff. The constructor-side special-action strip is explicit now too: shell_station_detail_window_construct 0x005068c0 wires action controls 0xb3b7/0xb3b8, navigation controls 0xb3b3/0xb3b4, and helper roots 0x006d16dc..0x006d16ec; then it restyles special control 0xb3f8 with one exact three-way split. When editor-map latch [0x006cec74+0x68] is clear, 0xb3f8 is forced to style 0x87. When that latch is set and scenario slot [0x006cec78+0x4af7] is nonzero, the same control takes style 0x74 if selected-station byte [station+0x5c9] is nonzero and style 0x65 otherwise. So that control is no longer just “some editor or scenario action”; the local branch now grounds it as one editor-gated, scenario-gated, selected-station-special-case affordance under the main StationDetail constructor. That deeper owner then continues into 0x0bff. That deeper owner is no longer just a black box either: it first requires the linked peer at [site+0x2a8] to pass the station-or-transit class gate, resolves the auxiliary candidate, computes one projected scalar cost from candidate field [candidate+0x22], owner company [site+0x276], current world coords, and scenario-side scale owner 0x00436590(0x3b, ...), and returns that scalar through the optional out-float. When the caller supplies the optional notice sink and the current owner company exists, the helper compares that scalar against company metric (0x0d, 0x2329) and on failure formats localized notice 0x0b52 before returning. The success side is tighter too: it materializes one packed projected-cell list through 0x00417840, runs the shared placement validator 0x004197e0, restores the temporary compact-grid replay bits through 0x004142c0/0x004142d0, and only then commits the linked-site mutation through 0x0040d1f0, 0x00480710, 0x0045b160, 0x0045b9b0, 0x00418be0, and 0x0040cd70, posting the signed scalar into the owner company through 0x0042a040 and accumulating the running total in [site+0x27a]. So the lower action band is now grounded as a real validate-or-apply linked-site mutation path with an explicit affordability notice branch, not just one anonymous modal gate.

Route-list side

The neighboring helper placed_structure_append_unique_route_entry at 0x0047f010 is now grounded as the append-if-missing builder for the six-byte route-entry list rooted at [site+0x462] and [site+0x466]. One tighter boundary closes the overlay-side uncertainty further: the directional overlay query at 0x0047e690 only consumes the leading u16 peer-site key when it walks that list and does not currently read the trailing u32 companion payload at all. So the local overlay-side seam is closed: route-list ownership and overlay dependence on that payload are no longer open here, and the trailing u32 can now be carried conservatively as the route-entry companion payload word for the non-overlay caller families that still preserve it.

Route-entry and Cache Side

The adjacent helper strip is tighter now too. placed_structure_service_candidate_local_service_comparison_cache_decay_and_row_propagation 0x0047df70 is the recurring age-and-propagation service pass over the paired comparison-cache float tables [site+0x3e] and [site+0x112] with age stamps at [site+0x1e6]; it zeroes stale entries older than 0x1d8800, decays younger ones by the fixed 0x005ce900/0x005ce8f8 scales, and then propagates stronger marked row values back through the three five-float row bands rooted at [site+0x24/+0x28/+0x2c]. The wrapper placed_structure_query_candidate_route_or_local_service_comparison_score 0x0047e9a0 is now bounded too: it delegates to placed_structure_query_candidate_directional_route_overlay_summary 0x0047e690 when the requested candidate carries a grouped routing class, otherwise it uses the simpler local [cell+0x103] lane and the current sample list at [site+0x34/+0x38] before writing back into the same comparison-cache bands. The route-entry strip beneath the linked-peer family is no longer open either: placed_structure_resolve_route_entry_anchor_record 0x0047f310 is the direct resolver over [site+0x08], and placed_structure_route_anchor_matches_or_reaches_route_entry_id 0x0047f250 is the boolean gate above it, first checking a direct match against [site+0x08] and then re-entering 0x0048e050(mode 2, fallback -1) on the resolved route-entry record. The route-link companion route_link_route_entry_reaches_peer_site_route_group 0x0047f2d0 is tighter now too: it reads the peer site's route-entry anchor from [peer+0x08], resolves the current link's own anchor, and re-enters 0x0048e3c0 to test whether the two anchors belong to the same reachable route-side family. One smaller linked-peer-side setter is grounded as well: placed_structure_set_overlay_mark_byte_and_refresh_linked_peer_overlay_if_changed 0x0047f290 updates byte [site+0x5bc] and then re-enters placed_structure_refresh_linked_peer_overlay_when_linked_peer_flagged 0x0040d2d0 when the byte changes.

Terrain-class Side

The nearby linked-instance raster wrappers are no longer anonymous. world_resolve_secondary_raster_class_record_at_float_xy 0x0044e270 is the world-side float-XY lookup over [world+0x2131] plus class table 0x006cfc9c; placed_structure_query_linked_instance_secondary_raster_class_id 0x0047f170 is the raw linked-instance wrapper that returns the shifted class id directly; and the paired record-returning wrappers placed_structure_resolve_linked_instance_secondary_raster_class_record 0x0047f0e0 and placed_structure_resolve_linked_instance_secondary_raster_class_record_via_world_query 0x0047f1f0 now bound the two record-returning lanes used by the later world-side and linked-peer filters. So the local static seam in this neighborhood is closed too: route-entry and terrain-class helper ownership are no longer open here, and the later callers can now be carried conservatively as linked-instance secondary-raster class filter families rather than one broader unnamed user-facing band.