1647 lines
61 KiB
Rust
1647 lines
61 KiB
Rust
use super::*;
|
|
use crate::test_support::empty_runtime_state;
|
|
|
|
pub(super) fn state() -> RuntimeState {
|
|
empty_runtime_state()
|
|
}
|
|
|
|
pub(super) fn packed_text_bands() -> Vec<SmpLoadedPackedEventTextBandSummary> {
|
|
vec![
|
|
SmpLoadedPackedEventTextBandSummary {
|
|
label: "primary_text_band".to_string(),
|
|
packed_len: 5,
|
|
present: true,
|
|
preview: "Alpha".to_string(),
|
|
},
|
|
SmpLoadedPackedEventTextBandSummary {
|
|
label: "secondary_text_band_0".to_string(),
|
|
packed_len: 0,
|
|
present: false,
|
|
preview: "".to_string(),
|
|
},
|
|
SmpLoadedPackedEventTextBandSummary {
|
|
label: "secondary_text_band_1".to_string(),
|
|
packed_len: 0,
|
|
present: false,
|
|
preview: "".to_string(),
|
|
},
|
|
SmpLoadedPackedEventTextBandSummary {
|
|
label: "secondary_text_band_2".to_string(),
|
|
packed_len: 0,
|
|
present: false,
|
|
preview: "".to_string(),
|
|
},
|
|
SmpLoadedPackedEventTextBandSummary {
|
|
label: "secondary_text_band_3".to_string(),
|
|
packed_len: 0,
|
|
present: false,
|
|
preview: "".to_string(),
|
|
},
|
|
SmpLoadedPackedEventTextBandSummary {
|
|
label: "secondary_text_band_4".to_string(),
|
|
packed_len: 0,
|
|
present: false,
|
|
preview: "".to_string(),
|
|
},
|
|
]
|
|
}
|
|
|
|
pub(super) fn real_condition_rows() -> Vec<SmpLoadedPackedEventConditionRowSummary> {
|
|
vec![SmpLoadedPackedEventConditionRowSummary {
|
|
row_index: 0,
|
|
raw_condition_id: -1,
|
|
subtype: 4,
|
|
flag_bytes: vec![0x30; 25],
|
|
candidate_name: Some("AutoPlant".to_string()),
|
|
comparator: None,
|
|
metric: None,
|
|
semantic_family: None,
|
|
semantic_preview: None,
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
requires_candidate_name_binding: false,
|
|
notes: vec!["negative sentinel-style condition row id".to_string()],
|
|
}]
|
|
}
|
|
|
|
pub(super) fn synthetic_packed_record(
|
|
record_index: usize,
|
|
live_entry_id: u32,
|
|
effect: RuntimeEffect,
|
|
) -> SmpLoadedPackedEventRecordSummary {
|
|
SmpLoadedPackedEventRecordSummary {
|
|
record_index,
|
|
live_entry_id,
|
|
payload_offset: Some(0x7200 + (live_entry_id as usize * 0x20)),
|
|
payload_len: Some(64),
|
|
decode_status: "parity_only".to_string(),
|
|
payload_family: "synthetic_harness".to_string(),
|
|
trigger_kind: Some(7),
|
|
active: Some(true),
|
|
marks_collection_dirty: Some(false),
|
|
one_shot: Some(false),
|
|
compact_control: None,
|
|
text_bands: packed_text_bands(),
|
|
standalone_condition_row_count: 0,
|
|
standalone_condition_rows: vec![],
|
|
negative_sentinel_scope: None,
|
|
grouped_effect_row_counts: vec![0, 0, 0, 0],
|
|
grouped_effect_rows: vec![],
|
|
decoded_conditions: Vec::new(),
|
|
decoded_actions: vec![effect],
|
|
executable_import_ready: false,
|
|
notes: vec!["synthetic test record".to_string()],
|
|
}
|
|
}
|
|
|
|
pub(super) fn company_negative_sentinel_scope(
|
|
company_test_scope: RuntimeCompanyConditionTestScope,
|
|
) -> SmpLoadedPackedEventNegativeSentinelScopeSummary {
|
|
SmpLoadedPackedEventNegativeSentinelScopeSummary {
|
|
company_test_scope,
|
|
player_test_scope: RuntimePlayerConditionTestScope::Disabled,
|
|
territory_scope_selector_is_0x63: false,
|
|
source_row_indexes: vec![0],
|
|
}
|
|
}
|
|
|
|
pub(super) fn territory_negative_sentinel_scope() -> SmpLoadedPackedEventNegativeSentinelScopeSummary
|
|
{
|
|
SmpLoadedPackedEventNegativeSentinelScopeSummary {
|
|
company_test_scope: RuntimeCompanyConditionTestScope::AllCompanies,
|
|
player_test_scope: RuntimePlayerConditionTestScope::Disabled,
|
|
territory_scope_selector_is_0x63: true,
|
|
source_row_indexes: vec![0],
|
|
}
|
|
}
|
|
|
|
pub(super) fn player_negative_sentinel_scope() -> SmpLoadedPackedEventNegativeSentinelScopeSummary {
|
|
SmpLoadedPackedEventNegativeSentinelScopeSummary {
|
|
company_test_scope: RuntimeCompanyConditionTestScope::AllCompanies,
|
|
player_test_scope: RuntimePlayerConditionTestScope::AllPlayers,
|
|
territory_scope_selector_is_0x63: false,
|
|
source_row_indexes: vec![0],
|
|
}
|
|
}
|
|
|
|
pub(super) fn selected_chairman_negative_sentinel_scope()
|
|
-> SmpLoadedPackedEventNegativeSentinelScopeSummary {
|
|
SmpLoadedPackedEventNegativeSentinelScopeSummary {
|
|
company_test_scope: RuntimeCompanyConditionTestScope::Disabled,
|
|
player_test_scope: RuntimePlayerConditionTestScope::SelectedPlayerOnly,
|
|
territory_scope_selector_is_0x63: false,
|
|
source_row_indexes: vec![0],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_grouped_rows() -> Vec<SmpLoadedPackedEventGroupedEffectRowSummary> {
|
|
vec![SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 2,
|
|
descriptor_label: Some("Company Cash".to_string()),
|
|
target_mask_bits: Some(0x01),
|
|
parameter_family: Some("company_finance_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 8,
|
|
raw_scalar_value: 7,
|
|
value_byte_0x09: 1,
|
|
value_dword_0x0d: 12,
|
|
value_byte_0x11: 2,
|
|
value_byte_0x12: 3,
|
|
value_word_0x14: 24,
|
|
value_word_0x16: 36,
|
|
row_shape: "multivalue_scalar".to_string(),
|
|
semantic_family: Some("multivalue_scalar".to_string()),
|
|
semantic_preview: Some("Set Company Cash to 7 with aux [2, 3, 24, 36]".to_string()),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: Some("Mikado".to_string()),
|
|
notes: vec!["grouped effect row carries locomotive-name side string".to_string()],
|
|
}]
|
|
}
|
|
|
|
pub(super) fn real_deactivate_company_row(
|
|
enabled: bool,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 13,
|
|
descriptor_label: Some("Deactivate Company".to_string()),
|
|
target_mask_bits: Some(0x01),
|
|
parameter_family: Some("company_lifecycle_toggle".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 1,
|
|
raw_scalar_value: if enabled { 1 } else { 0 },
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "bool_toggle".to_string(),
|
|
semantic_family: Some("bool_toggle".to_string()),
|
|
semantic_preview: Some(format!(
|
|
"Set Deactivate Company to {}",
|
|
if enabled { "TRUE" } else { "FALSE" }
|
|
)),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_track_capacity_row(value: i32) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 16,
|
|
descriptor_label: Some("Company Track Pieces Buildable".to_string()),
|
|
target_mask_bits: Some(0x01),
|
|
parameter_family: Some("company_build_limit_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set Company Track Pieces Buildable to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_credit_rating_row(value: i32) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 56,
|
|
descriptor_label: Some("Credit Rating".to_string()),
|
|
target_mask_bits: Some(0x0b),
|
|
parameter_family: Some("company_governance_scalar".to_string()),
|
|
grouped_target_subject: Some("company".to_string()),
|
|
grouped_target_scope: Some("selected_company".to_string()),
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set Credit Rating to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_merger_premium_shell_row(
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 58,
|
|
descriptor_label: Some("Merger Premium".to_string()),
|
|
target_mask_bits: Some(0x0b),
|
|
parameter_family: Some("company_finance_shell_scalar".to_string()),
|
|
grouped_target_subject: Some("company".to_string()),
|
|
grouped_target_scope: Some("selected_company".to_string()),
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set Merger Premium to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![
|
|
"descriptor is recovered in the checked-in effect table as shell_owned parity"
|
|
.to_string(),
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_stock_prices_shell_row(
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 55,
|
|
descriptor_label: Some("Stock Prices".to_string()),
|
|
target_mask_bits: Some(0x0b),
|
|
parameter_family: Some("company_finance_shell_scalar".to_string()),
|
|
grouped_target_subject: Some("company".to_string()),
|
|
grouped_target_scope: Some("selected_company".to_string()),
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set Stock Prices to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![
|
|
"descriptor is recovered in the checked-in effect table as shell_owned parity"
|
|
.to_string(),
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_deactivate_player_row(
|
|
enabled: bool,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 14,
|
|
descriptor_label: Some("Deactivate Player".to_string()),
|
|
target_mask_bits: Some(0x02),
|
|
parameter_family: Some("player_lifecycle_toggle".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 1,
|
|
raw_scalar_value: if enabled { 1 } else { 0 },
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "bool_toggle".to_string(),
|
|
semantic_family: Some("bool_toggle".to_string()),
|
|
semantic_preview: Some(format!(
|
|
"Set Deactivate Player to {}",
|
|
if enabled { "TRUE" } else { "FALSE" }
|
|
)),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_territory_access_row(
|
|
enabled: bool,
|
|
notes: Vec<String>,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 3,
|
|
descriptor_label: Some("Territory - Allow All".to_string()),
|
|
target_mask_bits: Some(0x05),
|
|
parameter_family: Some("territory_access_toggle".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 1,
|
|
raw_scalar_value: if enabled { 1 } else { 0 },
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "bool_toggle".to_string(),
|
|
semantic_family: Some("bool_toggle".to_string()),
|
|
semantic_preview: Some(format!(
|
|
"Set Territory - Allow All to {}",
|
|
if enabled { "TRUE" } else { "FALSE" }
|
|
)),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes,
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_economic_status_row(value: i32) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 8,
|
|
descriptor_label: Some("Economic Status".to_string()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("whole_game_state_enum".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set Economic Status to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_limited_track_building_amount_row(
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 122,
|
|
descriptor_label: Some("Limited Track Building Amount".to_string()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("world_track_build_limit_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set Limited Track Building Amount to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_special_condition_row(
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 108,
|
|
descriptor_label: Some("Use Wartime Cargos".to_string()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("special_condition_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set Use Wartime Cargos to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_candidate_availability_row(
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 109,
|
|
descriptor_label: Some("Turbo Diesel Availability".to_string()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("candidate_availability_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set Turbo Diesel Availability to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_locomotive_availability_row(
|
|
descriptor_id: u32,
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
fn grounded_locomotive_name(locomotive_id: u32) -> Option<&'static str> {
|
|
match locomotive_id {
|
|
1 => Some("2-D-2"),
|
|
2 => Some("E-88"),
|
|
3 => Some("Adler 2-2-2"),
|
|
4 => Some("USA 103"),
|
|
5 => Some("American 4-4-0"),
|
|
6 => Some("Atlantic 4-4-2"),
|
|
7 => Some("Baldwin 0-6-0"),
|
|
8 => Some("Be 5/7"),
|
|
9 => Some("Beuth 2-2-2"),
|
|
10 => Some("Big Boy 4-8-8-4"),
|
|
11 => Some("C55 Deltic"),
|
|
12 => Some("Camelback 0-6-0"),
|
|
13 => Some("Challenger 4-6-6-4"),
|
|
14 => Some("Class 01 4-6-2"),
|
|
15 => Some("Class 103"),
|
|
16 => Some("Class 132"),
|
|
17 => Some("Class 500 4-6-0"),
|
|
18 => Some("Class 9100"),
|
|
19 => Some("Class EF 66"),
|
|
20 => Some("Class 6E"),
|
|
21 => Some("Consolidation 2-8-0"),
|
|
22 => Some("Crampton 4-2-0"),
|
|
23 => Some("DD 080-X"),
|
|
24 => Some("DD40AX"),
|
|
25 => Some("Duke Class 4-4-0"),
|
|
26 => Some("E18"),
|
|
27 => Some("E428"),
|
|
28 => Some("Brenner E412"),
|
|
29 => Some("E60CP"),
|
|
30 => Some("Eight Wheeler 4-4-0"),
|
|
31 => Some("EP-2 Bipolar"),
|
|
32 => Some("ET22"),
|
|
33 => Some("F3"),
|
|
34 => Some("Fairlie 0-6-6-0"),
|
|
35 => Some("Firefly 2-2-2"),
|
|
36 => Some("FP45"),
|
|
37 => Some("Ge 6/6 Crocodile"),
|
|
38 => Some("GG1"),
|
|
39 => Some("GP7"),
|
|
40 => Some("H10 2-8-2"),
|
|
41 => Some("HST 125"),
|
|
42 => Some("Kriegslok 2-10-0"),
|
|
43 => Some("Mallard 4-6-2"),
|
|
44 => Some("Norris 4-2-0"),
|
|
45 => Some("Northern 4-8-4"),
|
|
46 => Some("Orca NX462"),
|
|
47 => Some("Pacific 4-6-2"),
|
|
48 => Some("Planet 2-2-0"),
|
|
49 => Some("Re 6/6"),
|
|
50 => Some("Red Devil 4-8-4"),
|
|
51 => Some("S3 4-4-0"),
|
|
52 => Some("NA-90D"),
|
|
53 => Some("Shay (2-Truck)"),
|
|
54 => Some("Shinkansen Series 0"),
|
|
55 => Some("Stirling 4-2-2"),
|
|
56 => Some("Trans-Euro"),
|
|
57 => Some("V200"),
|
|
58 => Some("VL80T"),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
let recovered_locomotive_id = match descriptor_id {
|
|
241..=351 => Some(descriptor_id - 240),
|
|
_ => None,
|
|
};
|
|
let descriptor_label = match descriptor_id {
|
|
457..=474 => {
|
|
format!(
|
|
"Upper-Band Locomotive Availability Slot {}",
|
|
descriptor_id - 456
|
|
)
|
|
}
|
|
_ => recovered_locomotive_id
|
|
.map(|loco_id| {
|
|
grounded_locomotive_name(loco_id)
|
|
.map(|name| format!("{name} Availability"))
|
|
.unwrap_or_else(|| format!("Locomotive {loco_id} Availability"))
|
|
})
|
|
.unwrap_or_else(|| "Locomotive Availability".to_string()),
|
|
};
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id,
|
|
descriptor_label: Some(descriptor_label.clone()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("locomotive_availability_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set {descriptor_label} to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_locomotive_cost_row(
|
|
descriptor_id: u32,
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
fn grounded_locomotive_name(locomotive_id: u32) -> Option<&'static str> {
|
|
match locomotive_id {
|
|
1 => Some("2-D-2"),
|
|
2 => Some("E-88"),
|
|
3 => Some("Adler 2-2-2"),
|
|
4 => Some("USA 103"),
|
|
5 => Some("American 4-4-0"),
|
|
6 => Some("Atlantic 4-4-2"),
|
|
7 => Some("Baldwin 0-6-0"),
|
|
8 => Some("Be 5/7"),
|
|
9 => Some("Beuth 2-2-2"),
|
|
10 => Some("Big Boy 4-8-8-4"),
|
|
11 => Some("C55 Deltic"),
|
|
12 => Some("Camelback 0-6-0"),
|
|
13 => Some("Challenger 4-6-6-4"),
|
|
14 => Some("Class 01 4-6-2"),
|
|
15 => Some("Class 103"),
|
|
16 => Some("Class 132"),
|
|
17 => Some("Class 500 4-6-0"),
|
|
18 => Some("Class 9100"),
|
|
19 => Some("Class EF 66"),
|
|
20 => Some("Class 6E"),
|
|
21 => Some("Consolidation 2-8-0"),
|
|
22 => Some("Crampton 4-2-0"),
|
|
23 => Some("DD 080-X"),
|
|
24 => Some("DD40AX"),
|
|
25 => Some("Duke Class 4-4-0"),
|
|
26 => Some("E18"),
|
|
27 => Some("E428"),
|
|
28 => Some("Brenner E412"),
|
|
29 => Some("E60CP"),
|
|
30 => Some("Eight Wheeler 4-4-0"),
|
|
31 => Some("EP-2 Bipolar"),
|
|
32 => Some("ET22"),
|
|
33 => Some("F3"),
|
|
34 => Some("Fairlie 0-6-6-0"),
|
|
35 => Some("Firefly 2-2-2"),
|
|
36 => Some("FP45"),
|
|
37 => Some("Ge 6/6 Crocodile"),
|
|
38 => Some("GG1"),
|
|
39 => Some("GP7"),
|
|
40 => Some("H10 2-8-2"),
|
|
41 => Some("HST 125"),
|
|
42 => Some("Kriegslok 2-10-0"),
|
|
43 => Some("Mallard 4-6-2"),
|
|
44 => Some("Norris 4-2-0"),
|
|
45 => Some("Northern 4-8-4"),
|
|
46 => Some("Orca NX462"),
|
|
47 => Some("Pacific 4-6-2"),
|
|
48 => Some("Planet 2-2-0"),
|
|
49 => Some("Re 6/6"),
|
|
50 => Some("Red Devil 4-8-4"),
|
|
51 => Some("S3 4-4-0"),
|
|
52 => Some("NA-90D"),
|
|
53 => Some("Shay (2-Truck)"),
|
|
54 => Some("Shinkansen Series 0"),
|
|
55 => Some("Stirling 4-2-2"),
|
|
56 => Some("Trans-Euro"),
|
|
57 => Some("V200"),
|
|
58 => Some("VL80T"),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
let recovered_locomotive_id = match descriptor_id {
|
|
352..=451 => Some(descriptor_id - 351),
|
|
_ => None,
|
|
};
|
|
let descriptor_label = match descriptor_id {
|
|
475..=502 => format!("Upper-Band Locomotive Cost Slot {}", descriptor_id - 474),
|
|
_ => recovered_locomotive_id
|
|
.map(|loco_id| {
|
|
grounded_locomotive_name(loco_id)
|
|
.map(|name| format!("{name} Cost"))
|
|
.unwrap_or_else(|| format!("Locomotive {loco_id} Cost"))
|
|
})
|
|
.unwrap_or_else(|| "Locomotive Cost".to_string()),
|
|
};
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id,
|
|
descriptor_label: Some(descriptor_label.clone()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("locomotive_cost_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set {descriptor_label} to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn default_save_named_locomotive_name(index: usize) -> String {
|
|
match index {
|
|
0 => "2-D-2",
|
|
1 => "E-88",
|
|
2 => "Adler 2-2-2",
|
|
3 => "USA 103",
|
|
4 => "American 4-4-0",
|
|
5 => "Atlantic 4-4-2",
|
|
6 => "Baldwin 0-6-0",
|
|
7 => "Be 5/7",
|
|
8 => "Beuth 2-2-2",
|
|
9 => "Big Boy 4-8-8-4",
|
|
10 => "C55 Deltic",
|
|
11 => "Camelback 0-6-0",
|
|
12 => "Challenger 4-6-6-4",
|
|
13 => "Class 01 4-6-2",
|
|
14 => "Class 103",
|
|
15 => "Class 132",
|
|
16 => "Class 500 4-6-0",
|
|
17 => "Class 9100",
|
|
18 => "Class EF 66",
|
|
19 => "Class 6E",
|
|
20 => "Consolidation 2-8-0",
|
|
21 => "Crampton 4-2-0",
|
|
22 => "DD 080-X",
|
|
23 => "DD40AX",
|
|
24 => "Duke Class 4-4-0",
|
|
25 => "E18",
|
|
26 => "E428",
|
|
27 => "Brenner E412",
|
|
28 => "E60CP",
|
|
29 => "Eight Wheeler 4-4-0",
|
|
30 => "EP-2 Bipolar",
|
|
31 => "ET22",
|
|
32 => "F3",
|
|
33 => "Fairlie 0-6-6-0",
|
|
34 => "Firefly 2-2-2",
|
|
35 => "FP45",
|
|
36 => "Ge 6/6 Crocodile",
|
|
37 => "GG1",
|
|
38 => "GP7",
|
|
39 => "H10 2-8-2",
|
|
40 => "HST 125",
|
|
41 => "Kriegslok 2-10-0",
|
|
42 => "Mallard 4-6-2",
|
|
43 => "Norris 4-2-0",
|
|
44 => "Northern 4-8-4",
|
|
45 => "Orca NX462",
|
|
46 => "Pacific 4-6-2",
|
|
47 => "Planet 2-2-0",
|
|
48 => "Re 6/6",
|
|
49 => "Red Devil 4-8-4",
|
|
50 => "S3 4-4-0",
|
|
51 => "NA-90D",
|
|
52 => "Shay (2-Truck)",
|
|
53 => "Shinkansen Series 0",
|
|
54 => "Stirling 4-2-2",
|
|
55 => "Trans-Euro",
|
|
56 => "V200",
|
|
57 => "VL80T",
|
|
58 => "GP 35",
|
|
59 => "U1",
|
|
60 => "Zephyr",
|
|
_ => return format!("Locomotive {}", index + 1),
|
|
}
|
|
.to_string()
|
|
}
|
|
|
|
pub(super) fn save_named_locomotive_table_with_names(
|
|
names: &[String],
|
|
) -> SmpLoadedNamedLocomotiveAvailabilityTable {
|
|
let count = names.len();
|
|
SmpLoadedNamedLocomotiveAvailabilityTable {
|
|
source_kind: "runtime-save-direct-serializer".to_string(),
|
|
semantic_family: "scenario-named-locomotive-availability-table".to_string(),
|
|
header_offset: None,
|
|
entries_offset: Some(0x7c78),
|
|
entries_end_offset: Some(0x7c78 + count * 0x41),
|
|
observed_entry_count: count,
|
|
zero_availability_count: 0,
|
|
zero_availability_names: vec![],
|
|
entries: names
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(index, name)| SmpRt3105SaveNameTableEntry {
|
|
index,
|
|
offset: 0x7c78 + index * 0x41,
|
|
text: name.clone(),
|
|
availability_dword: 1,
|
|
availability_dword_hex: "0x00000001".to_string(),
|
|
trailer_word: 1,
|
|
trailer_word_hex: "0x00000001".to_string(),
|
|
})
|
|
.collect(),
|
|
}
|
|
}
|
|
|
|
pub(super) fn save_named_locomotive_table(
|
|
count: usize,
|
|
) -> SmpLoadedNamedLocomotiveAvailabilityTable {
|
|
let names = (0..count)
|
|
.map(default_save_named_locomotive_name)
|
|
.collect::<Vec<_>>();
|
|
|
|
save_named_locomotive_table_with_names(&names)
|
|
}
|
|
|
|
pub(super) fn save_cargo_catalog(
|
|
entries: &[(u32, crate::event::targets::RuntimeCargoClass)],
|
|
) -> SmpLoadedCargoCatalog {
|
|
SmpLoadedCargoCatalog {
|
|
source_kind: "recipe-book-summary-slot-catalog".to_string(),
|
|
semantic_family: "scenario-save-derived-cargo-catalog".to_string(),
|
|
root_offset: Some(0x0fe7),
|
|
observed_entry_count: entries.len(),
|
|
entries: entries
|
|
.iter()
|
|
.enumerate()
|
|
.map(
|
|
|(index, (slot_id, cargo_class))| SmpLoadedCargoCatalogEntry {
|
|
slot_id: *slot_id,
|
|
label: format!("Cargo Production Slot {slot_id}"),
|
|
cargo_class: *cargo_class,
|
|
book_index: index,
|
|
max_annual_production_word: 0,
|
|
mode_word: 0,
|
|
runtime_import_branch_kind: "zero-mode-skipped".to_string(),
|
|
annual_amount_word: 0,
|
|
supplied_cargo_token_word: 0,
|
|
supplied_cargo_token_probable_high16_ascii_stem: None,
|
|
demanded_cargo_token_word: 0,
|
|
demanded_cargo_token_probable_high16_ascii_stem: None,
|
|
},
|
|
)
|
|
.collect(),
|
|
}
|
|
}
|
|
|
|
pub(super) fn save_company_roster() -> SmpLoadedCompanyRoster {
|
|
SmpLoadedCompanyRoster {
|
|
source_kind: "tracked-save-slice-company-roster".to_string(),
|
|
semantic_family: "save-slice-runtime-company-context".to_string(),
|
|
observed_entry_count: 2,
|
|
selected_company_id: Some(1),
|
|
entries: vec![
|
|
SmpLoadedCompanyRosterEntry {
|
|
company_id: 1,
|
|
active: true,
|
|
controller_kind: RuntimeCompanyControllerKind::Human,
|
|
current_cash: 150,
|
|
debt: 80,
|
|
credit_rating_score: Some(650),
|
|
prime_rate: Some(5),
|
|
available_track_laying_capacity: Some(6),
|
|
track_piece_counts: RuntimeTrackPieceCounts {
|
|
total: 20,
|
|
single: 5,
|
|
double: 8,
|
|
transition: 1,
|
|
electric: 3,
|
|
non_electric: 17,
|
|
},
|
|
linked_chairman_profile_id: Some(1),
|
|
book_value_per_share: 2620,
|
|
investor_confidence: 37,
|
|
management_attitude: 58,
|
|
takeover_cooldown_year: Some(1839),
|
|
merger_cooldown_year: Some(1838),
|
|
preferred_locomotive_engine_type_raw_u8: Some(2),
|
|
market_state: Some(crate::state::RuntimeCompanyMarketState {
|
|
outstanding_shares: 20_000,
|
|
bond_count: 2,
|
|
live_bond_slots: Vec::new(),
|
|
largest_live_bond_principal: Some(500_000),
|
|
highest_coupon_live_bond_principal: Some(350_000),
|
|
mutable_support_scalar_raw_u32: 0x3f99999a,
|
|
young_company_support_scalar_raw_u32: 0x42700000,
|
|
support_progress_word: 12,
|
|
recent_per_share_cache_absolute_counter: 0,
|
|
recent_per_share_cached_value_bits: 0,
|
|
recent_per_share_subscore_raw_u32: 0x420c0000,
|
|
cached_share_price_raw_u32: 0x42200000,
|
|
chairman_salary_baseline: 24,
|
|
chairman_salary_current: 30,
|
|
chairman_bonus_year: 1832,
|
|
chairman_bonus_amount: 900,
|
|
founding_year: 1831,
|
|
last_bankruptcy_year: 0,
|
|
last_dividend_year: 1837,
|
|
current_issue_calendar_word: 5,
|
|
current_issue_calendar_word_2: 6,
|
|
prior_issue_calendar_word: 4,
|
|
prior_issue_calendar_word_2: 5,
|
|
city_connection_latch: true,
|
|
linked_transit_latch: false,
|
|
linked_transit_route_anchor_entry_id: Some(77),
|
|
linked_transit_route_anchor_fallback_counts: vec![3, 5, 8],
|
|
stat_band_root_0cfb_candidates: Vec::new(),
|
|
stat_band_root_0d7f_candidates: Vec::new(),
|
|
stat_band_root_1c47_candidates: Vec::new(),
|
|
year_stat_family_qword_bits: Vec::new(),
|
|
special_stat_family_232a_qword_bits: Vec::new(),
|
|
issue_opinion_terms_raw_i32: Vec::new(),
|
|
direct_control_transfer_float_fields_raw_u32: BTreeMap::new(),
|
|
direct_control_transfer_int_fields_raw_u32: BTreeMap::new(),
|
|
}),
|
|
},
|
|
SmpLoadedCompanyRosterEntry {
|
|
company_id: 2,
|
|
active: true,
|
|
controller_kind: RuntimeCompanyControllerKind::Ai,
|
|
current_cash: 90,
|
|
debt: 40,
|
|
credit_rating_score: Some(480),
|
|
prime_rate: Some(6),
|
|
available_track_laying_capacity: Some(2),
|
|
track_piece_counts: RuntimeTrackPieceCounts {
|
|
total: 8,
|
|
single: 2,
|
|
double: 2,
|
|
transition: 0,
|
|
electric: 1,
|
|
non_electric: 7,
|
|
},
|
|
linked_chairman_profile_id: Some(2),
|
|
book_value_per_share: 1400,
|
|
investor_confidence: 22,
|
|
management_attitude: 31,
|
|
takeover_cooldown_year: None,
|
|
merger_cooldown_year: None,
|
|
preferred_locomotive_engine_type_raw_u8: Some(0),
|
|
market_state: Some(crate::state::RuntimeCompanyMarketState {
|
|
outstanding_shares: 18_000,
|
|
bond_count: 1,
|
|
live_bond_slots: Vec::new(),
|
|
largest_live_bond_principal: Some(300_000),
|
|
highest_coupon_live_bond_principal: Some(300_000),
|
|
mutable_support_scalar_raw_u32: 0x3f4ccccd,
|
|
young_company_support_scalar_raw_u32: 0x42580000,
|
|
support_progress_word: 9,
|
|
recent_per_share_cache_absolute_counter: 0,
|
|
recent_per_share_cached_value_bits: 0,
|
|
recent_per_share_subscore_raw_u32: 0x41f00000,
|
|
cached_share_price_raw_u32: 0x41f80000,
|
|
chairman_salary_baseline: 20,
|
|
chairman_salary_current: 22,
|
|
chairman_bonus_year: 0,
|
|
chairman_bonus_amount: 0,
|
|
founding_year: 1833,
|
|
last_bankruptcy_year: 0,
|
|
last_dividend_year: 0,
|
|
current_issue_calendar_word: 3,
|
|
current_issue_calendar_word_2: 4,
|
|
prior_issue_calendar_word: 2,
|
|
prior_issue_calendar_word_2: 3,
|
|
city_connection_latch: false,
|
|
linked_transit_latch: true,
|
|
linked_transit_route_anchor_entry_id: Some(41),
|
|
linked_transit_route_anchor_fallback_counts: vec![13, 21, 34],
|
|
stat_band_root_0cfb_candidates: Vec::new(),
|
|
stat_band_root_0d7f_candidates: Vec::new(),
|
|
stat_band_root_1c47_candidates: Vec::new(),
|
|
year_stat_family_qword_bits: Vec::new(),
|
|
special_stat_family_232a_qword_bits: Vec::new(),
|
|
issue_opinion_terms_raw_i32: Vec::new(),
|
|
direct_control_transfer_float_fields_raw_u32: BTreeMap::new(),
|
|
direct_control_transfer_int_fields_raw_u32: BTreeMap::new(),
|
|
}),
|
|
},
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn save_placed_structure_collection() -> SmpLoadedPlacedStructureCollection {
|
|
SmpLoadedPlacedStructureCollection {
|
|
source_kind: "save-placed-structure-record-triplets".to_string(),
|
|
semantic_family: "scenario-save-placed-structure-triplet-collection".to_string(),
|
|
observed_entry_count: 2,
|
|
entries: vec![
|
|
SmpLoadedPlacedStructureEntry {
|
|
record_index: 0,
|
|
primary_name: "FarmCorn".to_string(),
|
|
secondary_name: "FarmSet".to_string(),
|
|
policy_trailing_word: 1,
|
|
policy_trailing_word_hex: "0x0001".to_string(),
|
|
profile_payload_dword: 0,
|
|
profile_payload_dword_hex: "0x00000000".to_string(),
|
|
profile_status_kind: "farm_growth_stage_bucket".to_string(),
|
|
farm_growth_stage_index: Some(4),
|
|
profile_companion_byte_u8: Some(0),
|
|
profile_companion_byte_hex: Some("0x00".to_string()),
|
|
},
|
|
SmpLoadedPlacedStructureEntry {
|
|
record_index: 1,
|
|
primary_name: "StationA".to_string(),
|
|
secondary_name: "StationSetA".to_string(),
|
|
policy_trailing_word: 1,
|
|
policy_trailing_word_hex: "0x0001".to_string(),
|
|
profile_payload_dword: 0x00005dc1,
|
|
profile_payload_dword_hex: "0x00005dc1".to_string(),
|
|
profile_status_kind: "opaque_nondefault".to_string(),
|
|
farm_growth_stage_index: None,
|
|
profile_companion_byte_u8: Some(7),
|
|
profile_companion_byte_hex: Some("0x07".to_string()),
|
|
},
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn save_placed_structure_dynamic_side_buffer_summary()
|
|
-> SmpLoadedPlacedStructureDynamicSideBufferSummary {
|
|
SmpLoadedPlacedStructureDynamicSideBufferSummary {
|
|
source_kind: "save-placed-structure-dynamic-side-buffer-records".to_string(),
|
|
semantic_family: "scenario-save-placed-structure-dynamic-side-buffer-summary".to_string(),
|
|
observed_entry_count: 118,
|
|
owner_shared_dword_hex: "0xff0000ff".to_string(),
|
|
unique_embedded_name_pair_count: 9,
|
|
decoded_embedded_name_row_count: 118,
|
|
first_prefix_leading_dword_hex: "0xff0000ff".to_string(),
|
|
first_prefix_trailing_word_hex: "0x0001".to_string(),
|
|
first_prefix_separator_byte_hex: "0xff".to_string(),
|
|
triplet_alignment_overlap_count: 2,
|
|
triplet_alignment_side_buffer_only_name_pair_count: 7,
|
|
compact_prefix_pattern_summaries: vec![
|
|
SmpSavePlacedStructureDynamicSideBufferPrefixPatternSummary {
|
|
prefix_leading_dword: 0xff0000ff,
|
|
prefix_leading_dword_hex: "0xff0000ff".to_string(),
|
|
prefix_trailing_word: 1,
|
|
prefix_trailing_word_hex: "0x0001".to_string(),
|
|
prefix_separator_byte: 0xff,
|
|
prefix_separator_byte_hex: "0xff".to_string(),
|
|
count: 3,
|
|
first_name_tag_relative_offset: 0x24,
|
|
prefix_leading_dword_matches_embedded_profile_tag: true,
|
|
section_like_primary_name_count: 0,
|
|
cap_like_primary_name_count: 0,
|
|
other_primary_name_count: 3,
|
|
first_primary_name: Some("FarmCorn".to_string()),
|
|
first_secondary_name: Some("FarmSet".to_string()),
|
|
},
|
|
],
|
|
name_pair_summaries: vec![SmpSavePlacedStructureDynamicSideBufferNamePairSummary {
|
|
primary_name: "FarmCorn".to_string(),
|
|
secondary_name: "FarmSet".to_string(),
|
|
count: 3,
|
|
first_name_tag_relative_offset: 0x24,
|
|
unique_compact_prefix_pattern_count: 1,
|
|
dominant_prefix_leading_dword: 0xff0000ff,
|
|
dominant_prefix_leading_dword_hex: "0xff0000ff".to_string(),
|
|
dominant_prefix_trailing_word: 1,
|
|
dominant_prefix_trailing_word_hex: "0x0001".to_string(),
|
|
dominant_prefix_separator_byte: 0xff,
|
|
dominant_prefix_separator_byte_hex: "0xff".to_string(),
|
|
dominant_prefix_count: 3,
|
|
}],
|
|
}
|
|
}
|
|
|
|
pub(super) fn save_region_collection() -> SmpLoadedRegionCollection {
|
|
SmpLoadedRegionCollection {
|
|
source_kind: "save-region-record-triplets".to_string(),
|
|
semantic_family: "scenario-save-region-triplet-collection".to_string(),
|
|
observed_entry_count: 2,
|
|
entries: vec![
|
|
SmpLoadedRegionEntry {
|
|
record_index: 0,
|
|
name: "Marker09".to_string(),
|
|
pre_name_prefix_len: 0,
|
|
policy_leading_f32_0: 368.0,
|
|
policy_leading_f32_1: 0.0,
|
|
policy_leading_f32_2: 92.0,
|
|
policy_reserved_dwords: vec![0, 0, 0],
|
|
policy_trailing_word: 1,
|
|
policy_trailing_word_hex: "0x0001".to_string(),
|
|
profile_collection: Some(SmpLoadedRegionProfileCollection {
|
|
direct_collection_flag: 1,
|
|
entry_stride: 0x22,
|
|
live_id_bound: 18,
|
|
live_record_count: 17,
|
|
trailing_padding_len: 2,
|
|
entries: vec![
|
|
SmpLoadedRegionProfileEntry {
|
|
entry_index: 0,
|
|
name: "House".to_string(),
|
|
trailing_weight_f32: 0.2,
|
|
},
|
|
SmpLoadedRegionProfileEntry {
|
|
entry_index: 1,
|
|
name: "Farm Corn".to_string(),
|
|
trailing_weight_f32: 0.2,
|
|
},
|
|
],
|
|
}),
|
|
},
|
|
SmpLoadedRegionEntry {
|
|
record_index: 1,
|
|
name: "Marker10".to_string(),
|
|
pre_name_prefix_len: 8,
|
|
policy_leading_f32_0: 552.0,
|
|
policy_leading_f32_1: 0.0,
|
|
policy_leading_f32_2: 276.0,
|
|
policy_reserved_dwords: vec![0, 4, 0],
|
|
policy_trailing_word: 1,
|
|
policy_trailing_word_hex: "0x0001".to_string(),
|
|
profile_collection: Some(SmpLoadedRegionProfileCollection {
|
|
direct_collection_flag: 1,
|
|
entry_stride: 0x22,
|
|
live_id_bound: 26,
|
|
live_record_count: 24,
|
|
trailing_padding_len: 0,
|
|
entries: vec![SmpLoadedRegionProfileEntry {
|
|
entry_index: 0,
|
|
name: "Farm Corn".to_string(),
|
|
trailing_weight_f32: 0.2,
|
|
}],
|
|
}),
|
|
},
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn save_region_fixed_row_run_summary() -> SmpLoadedRegionFixedRowRunSummary {
|
|
SmpLoadedRegionFixedRowRunSummary {
|
|
source_kind: "save-region-fixed-row-run-candidates".to_string(),
|
|
semantic_family: "scenario-save-region-fixed-row-run-summary".to_string(),
|
|
target_row_count: 2,
|
|
target_row_stride: 0xbc,
|
|
target_row_stride_hex: "0xbc".to_string(),
|
|
candidates: vec![SmpSaveRegionFixedRowRunCandidate {
|
|
count_offset: 0x5300,
|
|
count_offset_hex: "0x5300".to_string(),
|
|
row_count: 2,
|
|
row_stride: 0xbc,
|
|
row_stride_hex: "0xbc".to_string(),
|
|
rows_offset: 0x5310,
|
|
rows_offset_hex: "0x5310".to_string(),
|
|
rows_end_offset: 0x5488,
|
|
rows_end_offset_hex: "0x5488".to_string(),
|
|
distance_to_region_metadata_tag: 0x110,
|
|
distance_to_region_metadata_tag_hex: "0x110".to_string(),
|
|
dword_lane_summaries: vec![],
|
|
shape_signature: "dword0:f32,dword1:zero".to_string(),
|
|
shape_family_signature: "family-a".to_string(),
|
|
trailing_byte_zero_count: 2,
|
|
trailing_byte_nonzero_count: 0,
|
|
trailing_byte_distinct_value_count: 1,
|
|
trailing_byte_sample_values_hex: vec!["0x00".to_string()],
|
|
best_probable_density_lane_relative_offset_hex: Some("0x24".to_string()),
|
|
}],
|
|
}
|
|
}
|
|
|
|
pub(super) fn save_chairman_profile_table() -> SmpLoadedChairmanProfileTable {
|
|
SmpLoadedChairmanProfileTable {
|
|
source_kind: "tracked-save-slice-chairman-profile-table".to_string(),
|
|
semantic_family: "save-slice-runtime-chairman-context".to_string(),
|
|
observed_entry_count: 2,
|
|
selected_chairman_profile_id: Some(1),
|
|
entries: vec![
|
|
SmpLoadedChairmanProfileEntry {
|
|
profile_id: 1,
|
|
name: "Chairman One".to_string(),
|
|
active: true,
|
|
current_cash: 500,
|
|
linked_company_id: Some(1),
|
|
company_holdings: BTreeMap::from([(1, 1000)]),
|
|
holdings_value_total: 700,
|
|
net_worth_total: 1200,
|
|
purchasing_power_total: 1500,
|
|
personality_byte_0x291: Some(12),
|
|
issue_opinion_terms_raw_i32: Vec::new(),
|
|
},
|
|
SmpLoadedChairmanProfileEntry {
|
|
profile_id: 2,
|
|
name: "Chairman Two".to_string(),
|
|
active: true,
|
|
current_cash: 250,
|
|
linked_company_id: Some(2),
|
|
company_holdings: BTreeMap::from([(2, 900)]),
|
|
holdings_value_total: 600,
|
|
net_worth_total: 900,
|
|
purchasing_power_total: 1100,
|
|
personality_byte_0x291: Some(20),
|
|
issue_opinion_terms_raw_i32: Vec::new(),
|
|
},
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_cargo_production_row(
|
|
descriptor_id: u32,
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
let slot = descriptor_id.saturating_sub(229);
|
|
let descriptor_label = format!("Cargo Production Slot {slot}");
|
|
let recovered_cargo_class = match slot {
|
|
1..=4 => Some("factory".to_string()),
|
|
5..=8 => Some("farm_mine".to_string()),
|
|
9..=11 => Some("other".to_string()),
|
|
_ => None,
|
|
};
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id,
|
|
descriptor_label: Some(descriptor_label.clone()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("cargo_production_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set {descriptor_label} to {value}")),
|
|
recovered_cargo_slot: Some(slot),
|
|
recovered_cargo_class,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_all_cargo_price_row(value: i32) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 105,
|
|
descriptor_label: Some("All Cargo Prices".to_string()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("cargo_price_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set All Cargo Prices to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![
|
|
"descriptor recovered from checked-in EventEffects semantic catalog".to_string(),
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_named_cargo_price_row(
|
|
descriptor_id: u32,
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
let cargo_label = grounded_named_cargo_price_label(descriptor_id).map(ToString::to_string);
|
|
let descriptor_label = cargo_label
|
|
.as_deref()
|
|
.map(|label| format!("{label} Price"))
|
|
.unwrap_or_else(|| {
|
|
format!(
|
|
"Named Cargo Price Slot {}",
|
|
descriptor_id.saturating_sub(105)
|
|
)
|
|
});
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id,
|
|
descriptor_label: Some(descriptor_label.clone()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("cargo_price_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set {descriptor_label} to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: cargo_label,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![
|
|
"descriptor recovered from checked-in EventEffects semantic catalog".to_string(),
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_aggregate_cargo_production_row(
|
|
descriptor_id: u32,
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
let (label, recovered_cargo_class) = match descriptor_id {
|
|
177 => ("All Cargo Production", None),
|
|
178 => ("All Factory Production", Some("factory".to_string())),
|
|
179 => ("All Farm/Mine Production", Some("farm_mine".to_string())),
|
|
_ => ("Unknown Cargo Production", None),
|
|
};
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id,
|
|
descriptor_label: Some(label.to_string()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("cargo_production_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set {label} to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![
|
|
"descriptor recovered from checked-in EventEffects semantic catalog".to_string(),
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_named_cargo_production_row(
|
|
descriptor_id: u32,
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
let cargo_label = match descriptor_id {
|
|
180 => Some("Alcohol".to_string()),
|
|
_ => None,
|
|
};
|
|
let descriptor_label = cargo_label
|
|
.as_ref()
|
|
.map(|label| format!("{label} Production"))
|
|
.unwrap_or_else(|| "Unknown Cargo Production".to_string());
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id,
|
|
descriptor_label: Some(descriptor_label.clone()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("cargo_production_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set {descriptor_label} to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: cargo_label,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![
|
|
"descriptor recovered from checked-in EventEffects semantic catalog".to_string(),
|
|
],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_territory_access_cost_row(
|
|
value: i32,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 453,
|
|
descriptor_label: Some("Territory Access Cost".to_string()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("territory_access_cost_scalar".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 3,
|
|
raw_scalar_value: value,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "scalar_assignment".to_string(),
|
|
semantic_family: Some("scalar_assignment".to_string()),
|
|
semantic_preview: Some(format!("Set Territory Access Cost to {value}")),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_world_flag_row(
|
|
descriptor_id: u32,
|
|
label: &str,
|
|
enabled: bool,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id,
|
|
descriptor_label: Some(label.to_string()),
|
|
target_mask_bits: Some(0x08),
|
|
parameter_family: Some("world_flag_toggle".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 0,
|
|
raw_scalar_value: if enabled { 1 } else { 0 },
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "bool_toggle".to_string(),
|
|
semantic_family: Some("bool_toggle".to_string()),
|
|
semantic_preview: Some(format!(
|
|
"Set {label} to {}",
|
|
if enabled { "TRUE" } else { "FALSE" }
|
|
)),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_confiscate_all_row(
|
|
enabled: bool,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 9,
|
|
descriptor_label: Some("Confiscate All".to_string()),
|
|
target_mask_bits: Some(0x01),
|
|
parameter_family: Some("company_confiscation_variant".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 1,
|
|
raw_scalar_value: if enabled { 1 } else { 0 },
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "bool_toggle".to_string(),
|
|
semantic_family: Some("bool_toggle".to_string()),
|
|
semantic_preview: Some(format!(
|
|
"Set Confiscate All to {}",
|
|
if enabled { "TRUE" } else { "FALSE" }
|
|
)),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_retire_train_row(
|
|
enabled: bool,
|
|
locomotive_name: Option<&str>,
|
|
notes: Vec<String>,
|
|
) -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 0,
|
|
row_index: 0,
|
|
descriptor_id: 15,
|
|
descriptor_label: Some("Retire Train".to_string()),
|
|
target_mask_bits: Some(0x0d),
|
|
parameter_family: Some("company_or_territory_asset_toggle".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 1,
|
|
raw_scalar_value: if enabled { 1 } else { 0 },
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "bool_toggle".to_string(),
|
|
semantic_family: Some("bool_toggle".to_string()),
|
|
semantic_preview: Some(format!(
|
|
"Set Retire Train to {}",
|
|
if enabled { "TRUE" } else { "FALSE" }
|
|
)),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: locomotive_name.map(ToString::to_string),
|
|
notes,
|
|
}
|
|
}
|
|
|
|
pub(super) fn unsupported_real_grouped_row() -> SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
SmpLoadedPackedEventGroupedEffectRowSummary {
|
|
group_index: 1,
|
|
row_index: 0,
|
|
descriptor_id: 9,
|
|
descriptor_label: Some("Confiscate All".to_string()),
|
|
target_mask_bits: Some(0x01),
|
|
parameter_family: Some("company_confiscation_variant".to_string()),
|
|
grouped_target_subject: None,
|
|
grouped_target_scope: None,
|
|
opcode: 1,
|
|
raw_scalar_value: 0,
|
|
value_byte_0x09: 0,
|
|
value_dword_0x0d: 0,
|
|
value_byte_0x11: 0,
|
|
value_byte_0x12: 0,
|
|
value_word_0x14: 0,
|
|
value_word_0x16: 0,
|
|
row_shape: "bool_toggle".to_string(),
|
|
semantic_family: Some("bool_toggle".to_string()),
|
|
semantic_preview: Some("Set Confiscate All to FALSE".to_string()),
|
|
recovered_cargo_slot: None,
|
|
recovered_cargo_class: None,
|
|
recovered_cargo_label: None,
|
|
recovered_locomotive_id: None,
|
|
locomotive_name: None,
|
|
notes: vec![],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_compact_control() -> SmpLoadedPackedEventCompactControlSummary {
|
|
SmpLoadedPackedEventCompactControlSummary {
|
|
mode_byte_0x7ef: 6,
|
|
primary_selector_0x7f0: 0x63,
|
|
grouped_mode_0x7f4: 2,
|
|
one_shot_header_0x7f5: 1,
|
|
modifier_flag_0x7f9: 1,
|
|
modifier_flag_0x7fa: 0,
|
|
grouped_target_scope_ordinals_0x7fb: vec![0, 1, 2, 3],
|
|
grouped_scope_checkboxes_0x7ff: vec![1, 0, 1, 0],
|
|
summary_toggle_0x800: 1,
|
|
grouped_territory_selectors_0x80f: vec![-1, 10, -1, 22],
|
|
}
|
|
}
|
|
|
|
pub(super) fn real_compact_control_without_symbolic_company_scope()
|
|
-> SmpLoadedPackedEventCompactControlSummary {
|
|
SmpLoadedPackedEventCompactControlSummary {
|
|
mode_byte_0x7ef: 6,
|
|
primary_selector_0x7f0: 0x63,
|
|
grouped_mode_0x7f4: 2,
|
|
one_shot_header_0x7f5: 1,
|
|
modifier_flag_0x7f9: 1,
|
|
modifier_flag_0x7fa: 0,
|
|
grouped_target_scope_ordinals_0x7fb: vec![8, 9, 10, 11],
|
|
grouped_scope_checkboxes_0x7ff: vec![1, 0, 1, 0],
|
|
summary_toggle_0x800: 1,
|
|
grouped_territory_selectors_0x80f: vec![-1, 10, -1, 22],
|
|
}
|
|
}
|