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

265 lines
21 KiB
Markdown

# 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_try_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_and_optionally_place_direct_site` `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_publish_startup_company_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 copies one source-kind name from `0x005f3c6c`, combines it with one style/theme entry from
the smaller subset table `0x005f3c80` through `"%1%2"` at `0x005c8730`, and then scans the
auxiliary candidate pool `0x0062b2fc` for the first exact combined-name match 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.