Add chairman packed event runtime support
This commit is contained in:
parent
377de45631
commit
86cf89b26c
23 changed files with 1431 additions and 41 deletions
|
|
@ -3,10 +3,10 @@ use std::collections::BTreeSet;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
RuntimeCargoClass, RuntimeCompanyControllerKind, RuntimeCompanyMetric, RuntimeCompanyTarget,
|
||||
RuntimeCondition, RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecordTemplate,
|
||||
RuntimePlayerTarget, RuntimeState, RuntimeSummary, RuntimeTerritoryMetric,
|
||||
RuntimeTerritoryTarget, RuntimeTrackMetric, RuntimeTrackPieceCounts,
|
||||
RuntimeCargoClass, RuntimeChairmanMetric, RuntimeChairmanTarget, RuntimeCompanyControllerKind,
|
||||
RuntimeCompanyMetric, RuntimeCompanyTarget, RuntimeCondition, RuntimeConditionComparator,
|
||||
RuntimeEffect, RuntimeEventRecordTemplate, RuntimePlayerTarget, RuntimeState, RuntimeSummary,
|
||||
RuntimeTerritoryMetric, RuntimeTerritoryTarget, RuntimeTrackMetric, RuntimeTrackPieceCounts,
|
||||
calendar::BoundaryEventKind,
|
||||
};
|
||||
|
||||
|
|
@ -87,6 +87,8 @@ struct AppliedEffectsSummary {
|
|||
struct ResolvedConditionContext {
|
||||
matching_company_ids: BTreeSet<u32>,
|
||||
matching_player_ids: BTreeSet<u32>,
|
||||
#[allow(dead_code)]
|
||||
matching_chairman_profile_ids: BTreeSet<u32>,
|
||||
}
|
||||
|
||||
pub fn execute_step_command(
|
||||
|
|
@ -346,6 +348,21 @@ fn apply_runtime_effects(
|
|||
mutated_player_ids.insert(player_id);
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetChairmanCash { target, value } => {
|
||||
let profile_ids = resolve_chairman_target_ids(state, target, condition_context)?;
|
||||
for profile_id in profile_ids {
|
||||
let chairman = state
|
||||
.chairman_profiles
|
||||
.iter_mut()
|
||||
.find(|profile| profile.profile_id == profile_id)
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"missing chairman profile_id {profile_id} while applying cash effect"
|
||||
)
|
||||
})?;
|
||||
chairman.current_cash = *value;
|
||||
}
|
||||
}
|
||||
RuntimeEffect::DeactivatePlayer { target } => {
|
||||
let player_ids = resolve_player_target_ids(state, target, condition_context)?;
|
||||
for player_id in player_ids {
|
||||
|
|
@ -365,6 +382,39 @@ fn apply_runtime_effects(
|
|||
}
|
||||
}
|
||||
}
|
||||
RuntimeEffect::DeactivateChairman { target } => {
|
||||
let profile_ids = resolve_chairman_target_ids(state, target, condition_context)?;
|
||||
for profile_id in profile_ids.iter().copied() {
|
||||
let linked_company_id = state
|
||||
.chairman_profiles
|
||||
.iter()
|
||||
.find(|profile| profile.profile_id == profile_id)
|
||||
.and_then(|profile| profile.linked_company_id);
|
||||
let chairman = state
|
||||
.chairman_profiles
|
||||
.iter_mut()
|
||||
.find(|profile| profile.profile_id == profile_id)
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"missing chairman profile_id {profile_id} while applying deactivate effect"
|
||||
)
|
||||
})?;
|
||||
chairman.active = false;
|
||||
chairman.linked_company_id = None;
|
||||
if state.selected_chairman_profile_id == Some(profile_id) {
|
||||
state.selected_chairman_profile_id = None;
|
||||
}
|
||||
if let Some(linked_company_id) = linked_company_id {
|
||||
for other in &mut state.chairman_profiles {
|
||||
if other.profile_id != profile_id
|
||||
&& other.linked_company_id == Some(linked_company_id)
|
||||
{
|
||||
other.linked_company_id = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCompanyTerritoryAccess {
|
||||
target,
|
||||
territory,
|
||||
|
|
@ -607,6 +657,7 @@ fn evaluate_record_conditions(
|
|||
}
|
||||
|
||||
let mut company_matches: Option<BTreeSet<u32>> = None;
|
||||
let mut chairman_matches: Option<BTreeSet<u32>> = None;
|
||||
|
||||
for condition in conditions {
|
||||
match condition {
|
||||
|
|
@ -657,6 +708,41 @@ fn evaluate_record_conditions(
|
|||
return Ok(None);
|
||||
}
|
||||
}
|
||||
RuntimeCondition::ChairmanNumericThreshold {
|
||||
target,
|
||||
metric,
|
||||
comparator,
|
||||
value,
|
||||
} => {
|
||||
let resolved = resolve_chairman_target_ids(
|
||||
state,
|
||||
target,
|
||||
&ResolvedConditionContext::default(),
|
||||
)?;
|
||||
let matching = resolved
|
||||
.into_iter()
|
||||
.filter(|profile_id| {
|
||||
state
|
||||
.chairman_profiles
|
||||
.iter()
|
||||
.find(|profile| profile.profile_id == *profile_id)
|
||||
.is_some_and(|profile| {
|
||||
compare_condition_value(
|
||||
chairman_metric_value(profile, *metric),
|
||||
*comparator,
|
||||
*value,
|
||||
)
|
||||
})
|
||||
})
|
||||
.collect::<BTreeSet<_>>();
|
||||
if matching.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
intersect_chairman_matches(&mut chairman_matches, matching);
|
||||
if chairman_matches.as_ref().is_some_and(BTreeSet::is_empty) {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
RuntimeCondition::CompanyTerritoryNumericThreshold {
|
||||
target,
|
||||
territory,
|
||||
|
|
@ -840,6 +926,7 @@ fn evaluate_record_conditions(
|
|||
Ok(Some(ResolvedConditionContext {
|
||||
matching_company_ids: company_matches.unwrap_or_default(),
|
||||
matching_player_ids: BTreeSet::new(),
|
||||
matching_chairman_profile_ids: chairman_matches.unwrap_or_default(),
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -854,6 +941,17 @@ fn intersect_company_matches(company_matches: &mut Option<BTreeSet<u32>>, next:
|
|||
}
|
||||
}
|
||||
|
||||
fn intersect_chairman_matches(chairman_matches: &mut Option<BTreeSet<u32>>, next: BTreeSet<u32>) {
|
||||
match chairman_matches {
|
||||
Some(existing) => {
|
||||
existing.retain(|profile_id| next.contains(profile_id));
|
||||
}
|
||||
None => {
|
||||
*chairman_matches = Some(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_company_target_ids(
|
||||
state: &RuntimeState,
|
||||
target: &RuntimeCompanyTarget,
|
||||
|
|
@ -1043,6 +1141,53 @@ fn resolve_player_target_ids(
|
|||
}
|
||||
}
|
||||
|
||||
fn resolve_chairman_target_ids(
|
||||
state: &RuntimeState,
|
||||
target: &RuntimeChairmanTarget,
|
||||
_condition_context: &ResolvedConditionContext,
|
||||
) -> Result<Vec<u32>, String> {
|
||||
match target {
|
||||
RuntimeChairmanTarget::AllActive => Ok(state
|
||||
.chairman_profiles
|
||||
.iter()
|
||||
.filter(|profile| profile.active)
|
||||
.map(|profile| profile.profile_id)
|
||||
.collect()),
|
||||
RuntimeChairmanTarget::Ids { ids } => {
|
||||
let known_ids = state
|
||||
.chairman_profiles
|
||||
.iter()
|
||||
.map(|profile| profile.profile_id)
|
||||
.collect::<BTreeSet<_>>();
|
||||
for profile_id in ids {
|
||||
if !known_ids.contains(profile_id) {
|
||||
return Err(format!(
|
||||
"target references unknown chairman profile_id {profile_id}"
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(ids.clone())
|
||||
}
|
||||
RuntimeChairmanTarget::SelectedChairman => {
|
||||
let selected_profile_id = state.selected_chairman_profile_id.ok_or_else(|| {
|
||||
"target requires selected_chairman_profile_id context".to_string()
|
||||
})?;
|
||||
if state
|
||||
.chairman_profiles
|
||||
.iter()
|
||||
.any(|profile| profile.profile_id == selected_profile_id && profile.active)
|
||||
{
|
||||
Ok(vec![selected_profile_id])
|
||||
} else {
|
||||
Err(
|
||||
"target requires selected_chairman_profile_id to reference an active chairman profile"
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_territory_target_ids(
|
||||
state: &RuntimeState,
|
||||
target: &RuntimeTerritoryTarget,
|
||||
|
|
@ -1090,6 +1235,18 @@ fn company_metric_value(company: &crate::RuntimeCompany, metric: RuntimeCompanyM
|
|||
}
|
||||
}
|
||||
|
||||
fn chairman_metric_value(
|
||||
profile: &crate::RuntimeChairmanProfile,
|
||||
metric: RuntimeChairmanMetric,
|
||||
) -> i64 {
|
||||
match metric {
|
||||
RuntimeChairmanMetric::CurrentCash => profile.current_cash,
|
||||
RuntimeChairmanMetric::HoldingsValueTotal => profile.holdings_value_total,
|
||||
RuntimeChairmanMetric::NetWorthTotal => profile.net_worth_total,
|
||||
RuntimeChairmanMetric::PurchasingPowerTotal => profile.purchasing_power_total,
|
||||
}
|
||||
}
|
||||
|
||||
fn territory_metric_value(
|
||||
state: &RuntimeState,
|
||||
territory_ids: &[u32],
|
||||
|
|
@ -1277,6 +1434,8 @@ mod tests {
|
|||
selected_company_id: None,
|
||||
players: Vec::new(),
|
||||
selected_player_id: None,
|
||||
chairman_profiles: Vec::new(),
|
||||
selected_chairman_profile_id: None,
|
||||
trains: Vec::new(),
|
||||
locomotive_catalog: Vec::new(),
|
||||
cargo_catalog: Vec::new(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue