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.