Broaden cargo packed event condition coverage

This commit is contained in:
Jan Petykiewicz 2026-04-16 14:23:43 -07:00
commit 0c4a90c16c
11 changed files with 434 additions and 23 deletions

View file

@ -60,11 +60,12 @@ catalog context. The remaining recovered scalar world families execute too: carg
`230..240` lower into `cargo_production_overrides`, and descriptor `453` lowers into
`world_restore.territory_access_cost`. Whole-game ordinary-condition breadth now aligns with those
same world-scalar runtime surfaces too: named locomotive availability thresholds, named
locomotive cost thresholds, aggregate cargo-production thresholds, limited-track-building-amount
thresholds, and territory-access-cost thresholds all gate imported runtime records through the
same service path. Families the current checked-in metadata still does not ground, such as `All
Factory Production`, now remain explicitly visible on `blocked_unmapped_world_condition` rather
than collapsing back to generic residue. Explicit unmapped world-condition and world-descriptor
locomotive cost thresholds, named cargo-production slot thresholds, aggregate cargo-production
thresholds, limited-track-building-amount thresholds, and territory-access-cost thresholds all
gate imported runtime records through the same service path. Families the current checked-in
metadata still does not ground, such as `All Factory Production`, now remain explicitly visible on
`blocked_unmapped_world_condition` rather than collapsing back to generic residue. Explicit
unmapped world-condition and world-descriptor
frontier buckets still remain where current checked-in metadata stops, and
`blocked_missing_locomotive_catalog_context` is now reserved for intentionally incomplete save-side
catalog context instead of the normal save-slice path. Shell purchase-flow, Trainbuy refresh,

View file

@ -1562,6 +1562,17 @@ fn lower_condition_targets_in_condition(
comparator: *comparator,
value: *value,
},
RuntimeCondition::CargoProductionSlotThreshold {
slot,
label,
comparator,
value,
} => RuntimeCondition::CargoProductionSlotThreshold {
slot: *slot,
label: label.clone(),
comparator: *comparator,
value: *value,
},
RuntimeCondition::CargoProductionTotalThreshold { comparator, value } => {
RuntimeCondition::CargoProductionTotalThreshold {
comparator: *comparator,
@ -1671,6 +1682,7 @@ fn condition_uses_condition_true_company(condition: &RuntimeCondition) -> bool {
| RuntimeCondition::CandidateAvailabilityThreshold { .. }
| RuntimeCondition::NamedLocomotiveAvailabilityThreshold { .. }
| RuntimeCondition::NamedLocomotiveCostThreshold { .. }
| RuntimeCondition::CargoProductionSlotThreshold { .. }
| RuntimeCondition::CargoProductionTotalThreshold { .. }
| RuntimeCondition::LimitedTrackBuildingAmountThreshold { .. }
| RuntimeCondition::TerritoryAccessCostThreshold { .. }
@ -2294,6 +2306,7 @@ fn runtime_condition_is_world_state(condition: &RuntimeCondition) -> bool {
| RuntimeCondition::CandidateAvailabilityThreshold { .. }
| RuntimeCondition::NamedLocomotiveAvailabilityThreshold { .. }
| RuntimeCondition::NamedLocomotiveCostThreshold { .. }
| RuntimeCondition::CargoProductionSlotThreshold { .. }
| RuntimeCondition::CargoProductionTotalThreshold { .. }
| RuntimeCondition::LimitedTrackBuildingAmountThreshold { .. }
| RuntimeCondition::TerritoryAccessCostThreshold { .. }
@ -2310,6 +2323,9 @@ fn ordinary_condition_row_is_world_state_family(
|| metric.contains("Candidate Availability")
|| metric.contains("Named Locomotive")
|| metric.contains("Cargo Production")
|| metric.contains("Factory Production")
|| metric.contains("Farm/Mine Production")
|| metric.contains("Other Cargo Production")
|| metric.contains("Limited Track Building Amount")
|| metric.contains("Territory Access Cost")
|| metric.contains("Economic Status")
@ -2388,6 +2404,7 @@ fn runtime_condition_company_target_import_blocker(
| RuntimeCondition::CandidateAvailabilityThreshold { .. }
| RuntimeCondition::NamedLocomotiveAvailabilityThreshold { .. }
| RuntimeCondition::NamedLocomotiveCostThreshold { .. }
| RuntimeCondition::CargoProductionSlotThreshold { .. }
| RuntimeCondition::CargoProductionTotalThreshold { .. }
| RuntimeCondition::LimitedTrackBuildingAmountThreshold { .. }
| RuntimeCondition::TerritoryAccessCostThreshold { .. }
@ -3001,6 +3018,8 @@ mod tests {
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()],
}]
@ -3085,6 +3104,8 @@ mod tests {
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_locomotive_id: None,
locomotive_name: Some("Mikado".to_string()),
notes: vec!["grouped effect row carries locomotive-name side string".to_string()],
@ -3115,6 +3136,8 @@ mod tests {
"Set Deactivate Company to {}",
if enabled { "TRUE" } else { "FALSE" }
)),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3140,6 +3163,8 @@ mod tests {
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_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3170,6 +3195,8 @@ mod tests {
"Set Deactivate Player to {}",
if enabled { "TRUE" } else { "FALSE" }
)),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3201,6 +3228,8 @@ mod tests {
"Set Territory - Allow All to {}",
if enabled { "TRUE" } else { "FALSE" }
)),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: None,
locomotive_name: None,
notes,
@ -3226,6 +3255,8 @@ mod tests {
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_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3253,6 +3284,8 @@ mod tests {
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_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3280,6 +3313,8 @@ mod tests {
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_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3307,6 +3342,8 @@ mod tests {
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_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3335,6 +3372,8 @@ mod tests {
row_shape: "scalar_assignment".to_string(),
semantic_family: Some("scalar_assignment".to_string()),
semantic_preview: Some(format!("Set Unknown Loco Available to {value}")),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: match descriptor_id {
241..=351 => Some(descriptor_id - 240),
457..=474 => Some(descriptor_id - 345),
@ -3375,6 +3414,8 @@ mod tests {
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_locomotive_id,
locomotive_name: None,
notes: vec![],
@ -3431,6 +3472,8 @@ mod tests {
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: None,
recovered_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3458,6 +3501,8 @@ mod tests {
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_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3490,6 +3535,8 @@ mod tests {
"Set {label} to {}",
if enabled { "TRUE" } else { "FALSE" }
)),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3520,6 +3567,8 @@ mod tests {
"Set Confiscate All to {}",
if enabled { "TRUE" } else { "FALSE" }
)),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -3552,6 +3601,8 @@ mod tests {
"Set Retire Train to {}",
if enabled { "TRUE" } else { "FALSE" }
)),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: None,
locomotive_name: locomotive_name.map(ToString::to_string),
notes,
@ -3577,6 +3628,8 @@ mod tests {
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_locomotive_id: None,
locomotive_name: None,
notes: vec![],
@ -5043,6 +5096,8 @@ mod tests {
metric: Some("Territory Track Pieces".to_string()),
semantic_family: Some("numeric_threshold".to_string()),
semantic_preview: Some("Test Territory Track Pieces >= 10".to_string()),
recovered_cargo_slot: None,
recovered_cargo_class: None,
requires_candidate_name_binding: false,
notes: Vec::new(),
},
@ -5223,6 +5278,8 @@ mod tests {
row_shape: "scalar_assignment".to_string(),
semantic_family: Some("scalar_assignment".to_string()),
semantic_preview: Some("Set Unknown Loco Available to 42".to_string()),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: Some(10),
locomotive_name: None,
notes: vec![],
@ -6324,6 +6381,8 @@ mod tests {
semantic_preview: Some(
"Set Company Cash to 250 with aux [2, 3, 24, 36]".to_string(),
),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: None,
locomotive_name: Some("Mikado".to_string()),
notes: vec![
@ -7855,6 +7914,8 @@ mod tests {
semantic_preview: Some(
"Test Disable Stock Buying and Selling == TRUE".to_string(),
),
recovered_cargo_slot: None,
recovered_cargo_class: None,
requires_candidate_name_binding: false,
notes: vec![
"checked-in whole-game condition metadata sample".to_string(),
@ -7881,6 +7942,8 @@ mod tests {
row_shape: "scalar_assignment".to_string(),
semantic_family: Some("scalar_assignment".to_string()),
semantic_preview: Some("Set Turbo Diesel Availability to 1".to_string()),
recovered_cargo_slot: None,
recovered_cargo_class: None,
recovered_locomotive_id: None,
locomotive_name: None,
notes: vec!["checked-in whole-game grouped-effect sample".to_string()],
@ -8006,7 +8069,7 @@ mod tests {
one_shot: Some(false),
compact_control: Some(real_compact_control()),
text_bands: packed_text_bands(),
standalone_condition_row_count: 5,
standalone_condition_row_count: 6,
standalone_condition_rows: vec![
crate::SmpLoadedPackedEventConditionRowSummary {
row_index: 0,
@ -8024,6 +8087,8 @@ mod tests {
semantic_preview: Some(
"Test Named Locomotive Availability: Big Boy == 42".to_string(),
),
recovered_cargo_slot: None,
recovered_cargo_class: None,
requires_candidate_name_binding: false,
notes: vec![],
},
@ -8044,11 +8109,37 @@ mod tests {
"Test Named Locomotive Cost: Locomotive 1 == 250000"
.to_string(),
),
recovered_cargo_slot: None,
recovered_cargo_class: None,
requires_candidate_name_binding: false,
notes: vec![],
},
crate::SmpLoadedPackedEventConditionRowSummary {
row_index: 2,
raw_condition_id: 200,
subtype: 4,
flag_bytes: {
let mut bytes = vec![0; 25];
bytes[0..4].copy_from_slice(&125_i32.to_le_bytes());
bytes
},
candidate_name: Some("Cargo Production Slot 1".to_string()),
comparator: Some("eq".to_string()),
metric: Some(
"Cargo Production: Cargo Production Slot 1".to_string(),
),
semantic_family: Some("world_scalar_threshold".to_string()),
semantic_preview: Some(
"Test Cargo Production: Cargo Production Slot 1 == 125"
.to_string(),
),
recovered_cargo_slot: Some(1),
recovered_cargo_class: None,
requires_candidate_name_binding: false,
notes: vec![],
},
crate::SmpLoadedPackedEventConditionRowSummary {
row_index: 3,
raw_condition_id: 2418,
subtype: 4,
flag_bytes: {
@ -8063,11 +8154,13 @@ mod tests {
semantic_preview: Some(
"Test Cargo Production Total == 125".to_string(),
),
recovered_cargo_slot: None,
recovered_cargo_class: None,
requires_candidate_name_binding: false,
notes: vec![],
},
crate::SmpLoadedPackedEventConditionRowSummary {
row_index: 3,
row_index: 4,
raw_condition_id: 2547,
subtype: 4,
flag_bytes: {
@ -8082,11 +8175,13 @@ mod tests {
semantic_preview: Some(
"Test Limited Track Building Amount == 18".to_string(),
),
recovered_cargo_slot: None,
recovered_cargo_class: None,
requires_candidate_name_binding: false,
notes: vec![],
},
crate::SmpLoadedPackedEventConditionRowSummary {
row_index: 4,
row_index: 5,
raw_condition_id: 1516,
subtype: 4,
flag_bytes: {
@ -8101,6 +8196,8 @@ mod tests {
semantic_preview: Some(
"Test Territory Access Cost == 750000".to_string(),
),
recovered_cargo_slot: None,
recovered_cargo_class: None,
requires_candidate_name_binding: false,
notes: vec![],
},
@ -8123,6 +8220,12 @@ mod tests {
comparator: RuntimeConditionComparator::Eq,
value: 250000,
},
RuntimeCondition::CargoProductionSlotThreshold {
slot: 1,
label: "Cargo Production Slot 1".to_string(),
comparator: RuntimeConditionComparator::Eq,
value: 125,
},
RuntimeCondition::CargoProductionTotalThreshold {
comparator: RuntimeConditionComparator::Eq,
value: 125,

View file

@ -254,6 +254,12 @@ pub enum RuntimeCondition {
comparator: RuntimeConditionComparator,
value: i64,
},
CargoProductionSlotThreshold {
slot: u32,
label: String,
comparator: RuntimeConditionComparator,
value: i64,
},
CargoProductionTotalThreshold {
comparator: RuntimeConditionComparator,
value: i64,
@ -1405,6 +1411,15 @@ fn validate_runtime_condition(
Ok(())
}
}
RuntimeCondition::CargoProductionSlotThreshold { slot, label, .. } => {
if !(1..=11).contains(slot) {
Err("slot must be in 1..=11".to_string())
} else if label.trim().is_empty() {
Err("label must not be empty".to_string())
} else {
Ok(())
}
}
RuntimeCondition::CargoProductionTotalThreshold { .. }
| RuntimeCondition::LimitedTrackBuildingAmountThreshold { .. }
| RuntimeCondition::TerritoryAccessCostThreshold { .. } => Ok(()),

View file

@ -242,7 +242,11 @@ enum RealWorldConditionKind {
CandidateAvailability,
NamedLocomotiveAvailability,
NamedLocomotiveCost,
CargoProductionSlot,
CargoProductionTotal,
FactoryProductionTotal,
FarmMineProductionTotal,
OtherCargoProductionTotal,
LimitedTrackBuildingAmount,
TerritoryAccessCost,
EconomicStatus,
@ -263,13 +267,17 @@ struct RealOrdinaryConditionMetadata {
}
const REAL_CANDIDATE_AVAILABILITY_CONDITION_TEMPLATE_ID: i32 = 435;
const REAL_CARGO_PRODUCTION_CONDITION_TEMPLATE_ID: i32 = 200;
const REAL_NAMED_LOCOMOTIVE_AVAILABILITY_CONDITION_ID: i32 = 2422;
const REAL_NAMED_LOCOMOTIVE_COST_CONDITION_ID: i32 = 2423;
const REAL_CARGO_PRODUCTION_TOTAL_CONDITION_ID: i32 = 2418;
const REAL_FACTORY_PRODUCTION_TOTAL_CONDITION_ID: i32 = 2419;
const REAL_FARM_MINE_PRODUCTION_TOTAL_CONDITION_ID: i32 = 2420;
const REAL_OTHER_CARGO_PRODUCTION_TOTAL_CONDITION_ID: i32 = 2421;
const REAL_LIMITED_TRACK_BUILDING_AMOUNT_CONDITION_ID: i32 = 2547;
const REAL_TERRITORY_ACCESS_COST_CONDITION_ID: i32 = 1516;
const REAL_ORDINARY_CONDITION_METADATA: [RealOrdinaryConditionMetadata; 29] = [
const REAL_ORDINARY_CONDITION_METADATA: [RealOrdinaryConditionMetadata; 33] = [
RealOrdinaryConditionMetadata {
raw_condition_id: 1802,
label: "Current Cash",
@ -429,6 +437,11 @@ const REAL_ORDINARY_CONDITION_METADATA: [RealOrdinaryConditionMetadata; 29] = [
label: "%1 Avail.",
kind: RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CandidateAvailability),
},
RealOrdinaryConditionMetadata {
raw_condition_id: REAL_CARGO_PRODUCTION_CONDITION_TEMPLATE_ID,
label: "%1 Production",
kind: RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CargoProductionSlot),
},
RealOrdinaryConditionMetadata {
raw_condition_id: REAL_NAMED_LOCOMOTIVE_AVAILABILITY_CONDITION_ID,
label: "Unknown Loco Available",
@ -446,6 +459,25 @@ const REAL_ORDINARY_CONDITION_METADATA: [RealOrdinaryConditionMetadata; 29] = [
label: "All Cargo Production",
kind: RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CargoProductionTotal),
},
RealOrdinaryConditionMetadata {
raw_condition_id: REAL_FACTORY_PRODUCTION_TOTAL_CONDITION_ID,
label: "All Factory Production",
kind: RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::FactoryProductionTotal),
},
RealOrdinaryConditionMetadata {
raw_condition_id: REAL_FARM_MINE_PRODUCTION_TOTAL_CONDITION_ID,
label: "All Farm/Mine Production",
kind: RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::FarmMineProductionTotal,
),
},
RealOrdinaryConditionMetadata {
raw_condition_id: REAL_OTHER_CARGO_PRODUCTION_TOTAL_CONDITION_ID,
label: "Unknown Cargo Production",
kind: RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::OtherCargoProductionTotal,
),
},
RealOrdinaryConditionMetadata {
raw_condition_id: REAL_LIMITED_TRACK_BUILDING_AMOUNT_CONDITION_ID,
label: "Limited Track Building Amount",
@ -1718,6 +1750,10 @@ pub struct SmpLoadedPackedEventConditionRowSummary {
#[serde(default)]
pub semantic_preview: Option<String>,
#[serde(default)]
pub recovered_cargo_slot: Option<u32>,
#[serde(default)]
pub recovered_cargo_class: Option<String>,
#[serde(default)]
pub requires_candidate_name_binding: bool,
#[serde(default)]
pub notes: Vec<String>,
@ -1748,6 +1784,10 @@ pub struct SmpLoadedPackedEventGroupedEffectRowSummary {
#[serde(default)]
pub semantic_preview: Option<String>,
#[serde(default)]
pub recovered_cargo_slot: Option<u32>,
#[serde(default)]
pub recovered_cargo_class: Option<String>,
#[serde(default)]
pub recovered_locomotive_id: Option<u32>,
#[serde(default)]
pub locomotive_name: Option<String>,
@ -2576,6 +2616,44 @@ fn parse_real_condition_row_summary(
}) {
notes.push("named locomotive condition row is missing its side-string binding".to_string());
}
if ordinary_metadata.is_some_and(|metadata| {
matches!(
metadata.kind,
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CargoProductionSlot)
) && candidate_name.is_none()
}) {
notes.push(
"named cargo-production condition row is missing its side-string binding".to_string(),
);
}
if ordinary_metadata.is_some_and(|metadata| {
matches!(
metadata.kind,
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::FactoryProductionTotal
| RealWorldConditionKind::FarmMineProductionTotal
| RealWorldConditionKind::OtherCargoProductionTotal
)
)
}) {
notes.push(
"checked-in RT3.lng label is known, but this cargo aggregate condition family is not yet lowered"
.to_string(),
);
}
if ordinary_metadata.is_some_and(|metadata| {
matches!(
metadata.kind,
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CargoProductionSlot)
) && candidate_name_ref
.and_then(recovered_cargo_production_slot_from_condition_name)
.is_none()
}) {
notes.push(
"named cargo-production condition side string does not yet map to a checked-in cargo slot"
.to_string(),
);
}
Some(SmpLoadedPackedEventConditionRowSummary {
row_index,
raw_condition_id,
@ -2596,6 +2674,24 @@ fn parse_real_condition_row_summary(
format!("Test {} {} {}", metric_label, comparator_text, value)
})
}),
recovered_cargo_slot: ordinary_metadata.and_then(|metadata| match metadata.kind {
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CargoProductionSlot) => {
candidate_name_ref.and_then(recovered_cargo_production_slot_from_condition_name)
}
_ => None,
}),
recovered_cargo_class: ordinary_metadata.and_then(|metadata| match metadata.kind {
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::FactoryProductionTotal,
) => Some("factory".to_string()),
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::FarmMineProductionTotal,
) => Some("farm_mine".to_string()),
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::OtherCargoProductionTotal,
) => Some("other".to_string()),
_ => None,
}),
requires_candidate_name_binding,
notes,
})
@ -2707,9 +2803,24 @@ fn real_ordinary_condition_metric_label(
None => "Named Locomotive Cost".to_string(),
}
}
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CargoProductionSlot) => {
match candidate_name {
Some(name) => format!("Cargo Production: {name}"),
None => "Cargo Production".to_string(),
}
}
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CargoProductionTotal) => {
"Cargo Production Total".to_string()
}
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::FactoryProductionTotal) => {
"Factory Production Total".to_string()
}
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::FarmMineProductionTotal) => {
"Farm/Mine Production Total".to_string()
}
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::OtherCargoProductionTotal,
) => "Other Cargo Production Total".to_string(),
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::LimitedTrackBuildingAmount,
) => "Limited Track Building Amount".to_string(),
@ -2736,7 +2847,11 @@ fn real_ordinary_condition_semantic_family(
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::NamedLocomotiveAvailability
| RealWorldConditionKind::NamedLocomotiveCost
| RealWorldConditionKind::CargoProductionSlot
| RealWorldConditionKind::CargoProductionTotal
| RealWorldConditionKind::FactoryProductionTotal
| RealWorldConditionKind::FarmMineProductionTotal
| RealWorldConditionKind::OtherCargoProductionTotal
| RealWorldConditionKind::LimitedTrackBuildingAmount
| RealWorldConditionKind::TerritoryAccessCost,
) => "world_scalar_threshold",
@ -2850,6 +2965,11 @@ fn parse_real_grouped_effect_row_summary(
"locomotive cost descriptor maps to live locomotive id {loco_id}"
));
}
if let Some(cargo_slot) = recovered_cargo_production_slot(descriptor_id) {
notes.push(format!(
"cargo-production descriptor maps to world production slot {cargo_slot}"
));
}
Some(SmpLoadedPackedEventGroupedEffectRowSummary {
group_index,
@ -2877,6 +2997,8 @@ fn parse_real_grouped_effect_row_summary(
value_word_0x14,
value_word_0x16,
)),
recovered_cargo_slot: recovered_cargo_production_slot(descriptor_id),
recovered_cargo_class: None,
recovered_locomotive_id: recovered_locomotive_availability_loco_id(descriptor_id)
.or_else(|| recovered_locomotive_cost_loco_id(descriptor_id)),
locomotive_name,
@ -2946,6 +3068,18 @@ fn decode_real_condition_row(
comparator,
value,
}),
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CargoProductionSlot) => {
row.candidate_name.as_ref().and_then(|name| {
recovered_cargo_production_slot_from_condition_name(name).map(|slot| {
RuntimeCondition::CargoProductionSlotThreshold {
slot,
label: name.clone(),
comparator,
value,
}
})
})
}
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::NamedLocomotiveAvailability,
) => row.candidate_name.as_ref().map(|name| {
@ -2966,6 +3100,11 @@ fn decode_real_condition_row(
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CargoProductionTotal) => {
Some(RuntimeCondition::CargoProductionTotalThreshold { comparator, value })
}
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::FactoryProductionTotal
| RealWorldConditionKind::FarmMineProductionTotal
| RealWorldConditionKind::OtherCargoProductionTotal,
) => None,
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::LimitedTrackBuildingAmount,
) => Some(RuntimeCondition::LimitedTrackBuildingAmountThreshold { comparator, value }),
@ -3028,6 +3167,11 @@ fn recovered_cargo_production_descriptor_metadata(
})
}
fn recovered_cargo_production_slot(descriptor_id: u32) -> Option<u32> {
let slot = descriptor_id.checked_sub(229)?;
(1..=11).contains(&slot).then_some(slot)
}
fn recovered_locomotive_availability_descriptor_metadata(
descriptor_id: u32,
) -> Option<RealGroupedEffectDescriptorMetadata> {
@ -3083,6 +3227,12 @@ fn recovered_cargo_production_label(descriptor_id: u32) -> Option<&'static str>
.copied()
}
fn recovered_cargo_production_slot_from_condition_name(name: &str) -> Option<u32> {
let suffix = name.strip_prefix("Cargo Production Slot ")?;
let slot = suffix.parse::<u32>().ok()?;
(1..=11).contains(&slot).then_some(slot)
}
fn recovered_locomotive_cost_loco_id(descriptor_id: u32) -> Option<u32> {
if (352..=451).contains(&descriptor_id) {
return Some(descriptor_id - 351);
@ -3761,6 +3911,7 @@ fn runtime_condition_supported_for_save_import(condition: &RuntimeCondition) ->
| RuntimeCondition::CandidateAvailabilityThreshold { .. }
| RuntimeCondition::NamedLocomotiveAvailabilityThreshold { .. }
| RuntimeCondition::NamedLocomotiveCostThreshold { .. }
| RuntimeCondition::CargoProductionSlotThreshold { .. }
| RuntimeCondition::CargoProductionTotalThreshold { .. }
| RuntimeCondition::LimitedTrackBuildingAmountThreshold { .. }
| RuntimeCondition::TerritoryAccessCostThreshold { .. }
@ -9668,6 +9819,72 @@ mod tests {
);
}
#[test]
fn decodes_real_named_cargo_production_threshold_from_checked_in_metadata() {
let condition_row = build_real_condition_row_with_threshold(
REAL_CARGO_PRODUCTION_CONDITION_TEMPLATE_ID,
4,
125,
Some("Cargo Production Slot 1"),
);
let record_body = build_real_event_record(
[b"World", b"", b"", b"", b"", b""],
Some(RealCompactControlSpec {
mode_byte_0x7ef: 7,
primary_selector_0x7f0: 0,
grouped_mode_0x7f4: 2,
one_shot_header_0x7f5: 0,
modifier_flag_0x7f9: 0,
modifier_flag_0x7fa: 0,
grouped_target_scope_ordinals_0x7fb: [0, 0, 0, 0],
grouped_scope_checkboxes_0x7ff: [0, 0, 0, 0],
summary_toggle_0x800: 1,
grouped_territory_selectors_0x80f: [-1, -1, -1, -1],
}),
&[condition_row],
[&[], &[], &[], &[]],
);
let mut bytes = Vec::new();
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_METADATA_TAG.to_le_bytes());
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_PACKED_STATE_VERSION.to_le_bytes());
let header_words = [1u32, 4, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for word in header_words {
bytes.extend_from_slice(&word.to_le_bytes());
}
bytes.extend_from_slice(&[0x00, 0x00]);
bytes.extend_from_slice(&[0xaa, 0xbb, 0xcc, 0xdd]);
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_RECORDS_TAG.to_le_bytes());
bytes.extend_from_slice(&record_body);
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_CLOSE_TAG.to_le_bytes());
let report = inspect_smp_bytes(&bytes);
let summary = report
.event_runtime_collection_summary
.as_ref()
.expect("event runtime collection summary should parse");
assert_eq!(
summary.records[0].standalone_condition_rows[0]
.metric
.as_deref(),
Some("Cargo Production: Cargo Production Slot 1")
);
assert_eq!(
summary.records[0].standalone_condition_rows[0].recovered_cargo_slot,
Some(1)
);
assert_eq!(
summary.records[0].decoded_conditions,
vec![RuntimeCondition::CargoProductionSlotThreshold {
slot: 1,
label: "Cargo Production Slot 1".to_string(),
comparator: RuntimeConditionComparator::Eq,
value: 125,
}]
);
}
#[test]
fn decodes_real_world_scalar_thresholds_from_checked_in_metadata() {
let condition_rows = vec![
@ -9821,6 +10038,11 @@ mod tests {
#[test]
fn looks_up_checked_in_world_scalar_condition_metadata() {
let named_cargo =
real_ordinary_condition_metadata(REAL_CARGO_PRODUCTION_CONDITION_TEMPLATE_ID)
.expect("named cargo condition metadata should exist");
assert_eq!(named_cargo.label, "%1 Production");
let availability =
real_ordinary_condition_metadata(REAL_NAMED_LOCOMOTIVE_AVAILABILITY_CONDITION_ID)
.expect("availability condition metadata should exist");
@ -9834,6 +10056,15 @@ mod tests {
.expect("cargo condition metadata should exist");
assert_eq!(cargo.label, "All Cargo Production");
let factory = real_ordinary_condition_metadata(REAL_FACTORY_PRODUCTION_TOTAL_CONDITION_ID)
.expect("factory production condition metadata should exist");
assert_eq!(factory.label, "All Factory Production");
let farm_mine =
real_ordinary_condition_metadata(REAL_FARM_MINE_PRODUCTION_TOTAL_CONDITION_ID)
.expect("farm/mine production condition metadata should exist");
assert_eq!(farm_mine.label, "All Farm/Mine Production");
let build_limit =
real_ordinary_condition_metadata(REAL_LIMITED_TRACK_BUILDING_AMOUNT_CONDITION_ID)
.expect("build-limit condition metadata should exist");
@ -10517,6 +10748,8 @@ mod tests {
metric: None,
semantic_family: None,
semantic_preview: None,
recovered_cargo_slot: None,
recovered_cargo_class: None,
requires_candidate_name_binding: false,
notes: vec![],
}];

View file

@ -752,6 +752,22 @@ fn evaluate_record_conditions(
return Ok(None);
}
}
RuntimeCondition::CargoProductionSlotThreshold {
slot,
comparator,
value,
..
} => {
let actual = state
.cargo_production_overrides
.get(slot)
.copied()
.map(i64::from)
.unwrap_or(0);
if !compare_condition_value(actual, *comparator, *value) {
return Ok(None);
}
}
RuntimeCondition::CargoProductionTotalThreshold { comparator, value } => {
let actual = state
.cargo_production_overrides
@ -2234,6 +2250,12 @@ mod tests {
comparator: RuntimeConditionComparator::Eq,
value: 175000,
},
RuntimeCondition::CargoProductionSlotThreshold {
slot: 1,
label: "Cargo Production Slot 1".to_string(),
comparator: RuntimeConditionComparator::Eq,
value: 125,
},
RuntimeCondition::CargoProductionTotalThreshold {
comparator: RuntimeConditionComparator::Eq,
value: 200,

View file

@ -139,9 +139,9 @@ The highest-value next passes are now:
world-side scalar landing surfaces: slot-indexed `cargo_production_overrides` and
`world_restore.territory_access_cost`
- world-scalar ordinary-condition coverage now matches those runtime surfaces too: checked-in
metadata lowers named locomotive availability, named locomotive cost, aggregate cargo
production, limited-track-building-amount, and territory-access-cost rows into explicit runtime
condition gates
metadata lowers named locomotive availability, named locomotive cost, named cargo-production
slot thresholds, aggregate cargo production, limited-track-building-amount, and
territory-access-cost rows into explicit runtime condition gates
- the remaining world-scalar condition frontier is now narrow and explicit: unsupported families
such as `All Factory Production` stay parity-only on `blocked_unmapped_world_condition`
- keep in mind that the current local `.gms` corpus still exports with no packed event collection,

View file

@ -98,9 +98,9 @@ Implemented today:
rows lower into slot-indexed `cargo_production_overrides`, and territory-access-cost descriptor
`453` lowers into `world_restore.territory_access_cost`
- world-scalar ordinary-condition coverage now aligns with those runtime surfaces too: checked-in
metadata lowers named locomotive availability, named locomotive cost, aggregate cargo
production, limited-track-building-amount, and territory-access-cost rows into explicit runtime
condition gates
metadata lowers named locomotive availability, named locomotive cost, named cargo-production
slot thresholds, aggregate cargo production, limited-track-building-amount, and
territory-access-cost rows into explicit runtime condition gates
- the remaining world-side condition frontier is now narrower and more honest: unsupported scalar
families such as `All Factory Production` stay visible on `blocked_unmapped_world_condition`
instead of falling back to generic placeholder ids

View file

@ -81,6 +81,8 @@
"row_shape": "scalar_assignment",
"semantic_family": "scalar_assignment",
"semantic_preview": "Set Cargo Production Slot 1 to 125",
"recovered_cargo_slot": 1,
"recovered_cargo_class": null,
"recovered_locomotive_id": null,
"locomotive_name": null,
"notes": []

View file

@ -69,6 +69,13 @@
"comparator": "eq",
"value": 250000
},
{
"kind": "cargo_production_slot_threshold",
"slot": 1,
"label": "Cargo Production Slot 1",
"comparator": "eq",
"value": 125
},
{
"kind": "cargo_production_total_threshold",
"comparator": "eq",

View file

@ -5,10 +5,10 @@
"description": "Tracked save-slice document proving grounded world-scalar ordinary conditions gate a whole-game effect.",
"original_save_filename": "captured-world-scalar-condition.gms",
"original_save_sha256": "world-scalar-condition-sample-sha256",
"notes": [
"tracked as JSON save-slice document rather than raw .smp",
"uses checked-in RT3.lng condition ids for named locomotive availability, named locomotive cost, aggregate cargo production, limited track building amount, and access rights cost"
]
"notes": [
"tracked as JSON save-slice document rather than raw .smp",
"uses checked-in RT3.lng condition ids for named locomotive availability, named locomotive cost, named cargo-production slot, aggregate cargo production, limited track building amount, and access rights cost"
]
},
"save_slice": {
"file_extension_hint": "gms",
@ -130,6 +130,8 @@
"row_shape": "scalar_assignment",
"semantic_family": "scalar_assignment",
"semantic_preview": "Set Cargo Production Slot 1 to 125",
"recovered_cargo_slot": 1,
"recovered_cargo_class": null,
"recovered_locomotive_id": null,
"locomotive_name": null,
"notes": []
@ -232,7 +234,7 @@
"grouped_territory_selectors_0x80f": [-1, -1, -1, -1]
},
"text_bands": [],
"standalone_condition_row_count": 5,
"standalone_condition_row_count": 6,
"standalone_condition_rows": [
{
"row_index": 0,
@ -266,6 +268,23 @@
},
{
"row_index": 2,
"raw_condition_id": 200,
"subtype": 4,
"flag_bytes": [125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"candidate_name": "Cargo Production Slot 1",
"comparator": "eq",
"metric": "Cargo Production: Cargo Production Slot 1",
"semantic_family": "world_scalar_threshold",
"semantic_preview": "Test Cargo Production: Cargo Production Slot 1 == 125",
"recovered_cargo_slot": 1,
"recovered_cargo_class": null,
"requires_candidate_name_binding": false,
"notes": [
"checked-in world-scalar condition metadata sample"
]
},
{
"row_index": 3,
"raw_condition_id": 2418,
"subtype": 4,
"flag_bytes": [125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
@ -280,7 +299,7 @@
]
},
{
"row_index": 3,
"row_index": 4,
"raw_condition_id": 2547,
"subtype": 4,
"flag_bytes": [18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
@ -295,7 +314,7 @@
]
},
{
"row_index": 4,
"row_index": 5,
"raw_condition_id": 1516,
"subtype": 4,
"flag_bytes": [176, 113, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
@ -349,6 +368,13 @@
"comparator": "eq",
"value": 250000
},
{
"kind": "cargo_production_slot_threshold",
"slot": 1,
"label": "Cargo Production Slot 1",
"comparator": "eq",
"value": 125
},
{
"kind": "cargo_production_total_threshold",
"comparator": "eq",
@ -374,7 +400,7 @@
],
"executable_import_ready": true,
"notes": [
"world-scalar conditions gate a whole-game effect"
"world-scalar conditions gate a whole-game effect, including a checked-in named cargo-production slot threshold"
]
}
]

View file

@ -81,6 +81,8 @@
"row_shape": "scalar_assignment",
"semantic_family": "scalar_assignment",
"semantic_preview": "Set Cargo Production Slot 1 to 125",
"recovered_cargo_slot": 1,
"recovered_cargo_class": null,
"recovered_locomotive_id": null,
"locomotive_name": null,
"notes": []