Implement whole-game packed event conditions

This commit is contained in:
Jan Petykiewicz 2026-04-15 21:41:40 -07:00
commit cc54a00e25
16 changed files with 1184 additions and 42 deletions

View file

@ -651,6 +651,46 @@ fn evaluate_record_conditions(
return Ok(None);
}
}
RuntimeCondition::SpecialConditionThreshold {
label,
comparator,
value,
} => {
let actual = state
.special_conditions
.get(label)
.copied()
.map(i64::from)
.unwrap_or(0);
if !compare_condition_value(actual, *comparator, *value) {
return Ok(None);
}
}
RuntimeCondition::CandidateAvailabilityThreshold {
name,
comparator,
value,
} => {
let actual = state
.candidate_availability
.get(name)
.copied()
.map(i64::from)
.unwrap_or(0);
if !compare_condition_value(actual, *comparator, *value) {
return Ok(None);
}
}
RuntimeCondition::EconomicStatusCodeThreshold { comparator, value } => {
let actual = state
.world_restore
.economic_status_code
.map(i64::from)
.unwrap_or(0);
if !compare_condition_value(actual, *comparator, *value) {
return Ok(None);
}
}
}
}
@ -1039,7 +1079,8 @@ fn set_company_territory_access_pairs(
}
} else {
access_entries.retain(|entry| {
!(company_ids.contains(&entry.company_id) && territory_ids.contains(&entry.territory_id))
!(company_ids.contains(&entry.company_id)
&& territory_ids.contains(&entry.territory_id))
});
}
}
@ -1785,6 +1826,78 @@ mod tests {
assert!(error.contains("condition-evaluation context"));
}
#[test]
fn evaluates_world_state_conditions_before_effects_run() {
let mut state = RuntimeState {
world_restore: RuntimeWorldRestoreState {
economic_status_code: Some(3),
..RuntimeWorldRestoreState::default()
},
candidate_availability: BTreeMap::from([(String::from("Mogul"), 2)]),
special_conditions: BTreeMap::from([(String::from("Use Wartime Cargos"), 1)]),
event_runtime_records: vec![
RuntimeEventRecord {
record_id: 23,
trigger_kind: 7,
active: true,
service_count: 0,
marks_collection_dirty: false,
one_shot: false,
has_fired: false,
conditions: vec![
RuntimeCondition::SpecialConditionThreshold {
label: "Use Wartime Cargos".to_string(),
comparator: RuntimeConditionComparator::Ge,
value: 1,
},
RuntimeCondition::CandidateAvailabilityThreshold {
name: "Mogul".to_string(),
comparator: RuntimeConditionComparator::Eq,
value: 2,
},
RuntimeCondition::EconomicStatusCodeThreshold {
comparator: RuntimeConditionComparator::Eq,
value: 3,
},
],
effects: vec![RuntimeEffect::SetWorldFlag {
key: "world_condition_passed".to_string(),
value: true,
}],
},
RuntimeEventRecord {
record_id: 24,
trigger_kind: 7,
active: true,
service_count: 0,
marks_collection_dirty: false,
one_shot: false,
has_fired: false,
conditions: vec![RuntimeCondition::SpecialConditionThreshold {
label: "Disable Cargo Economy".to_string(),
comparator: RuntimeConditionComparator::Gt,
value: 0,
}],
effects: vec![RuntimeEffect::SetWorldFlag {
key: "world_condition_failed".to_string(),
value: true,
}],
},
],
..state()
};
let result = execute_step_command(
&mut state,
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
)
.expect("world-state conditions should evaluate successfully");
assert_eq!(result.service_events[0].serviced_record_ids, vec![23]);
assert_eq!(state.world_flags.get("world_condition_passed"), Some(&true));
assert_eq!(state.world_flags.get("world_condition_failed"), None);
}
#[test]
fn one_shot_record_only_fires_once() {
let mut state = RuntimeState {