rpfm_extensions/startpos/world/
factions.rs1use getset::{CopyGetters, Getters};
19
20use rpfm_lib::error::{RLibError, Result};
21
22use super::{CampaignIndex, FactionEntry};
23use crate::startpos::tables::{Row, StartposTables};
24
25#[cfg(test)] #[path = "factions_test.rs"] mod factions_test;
26
27#[derive(Debug, Clone, PartialEq, Eq, Default, Getters, CopyGetters)]
33pub struct FactionFlag {
34
35 #[getset(get = "pub")]
37 path: String,
38
39 #[getset(get_copy = "pub")]
41 colours: [[u8; 3]; 3],
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Default, Getters, CopyGetters)]
46pub struct FactionSummary {
47
48 #[getset(get = "pub")]
50 key: String,
51
52 #[getset(get = "pub")]
54 capital: Option<String>,
55
56 #[getset(get_copy = "pub")]
58 region_count: usize,
59
60 #[getset(get = "pub")]
62 victory_regions: Vec<String>,
63
64 #[getset(get = "pub")]
66 client_state_of: Option<String>,
67
68 #[getset(get = "pub")]
70 vassal_of: Option<String>,
71
72 #[getset(get = "pub")]
74 subjects: Vec<String>,
75
76 #[getset(get_copy = "pub")]
78 has_war_or_vassal: bool,
79
80 #[getset(get_copy = "pub")]
82 horde: Option<bool>,
83
84 #[getset(get_copy = "pub")]
86 without_characters: bool,
87
88 #[getset(get = "pub")]
90 progenitor: Option<String>,
91}
92
93pub fn faction_flags(tables: &StartposTables, faction: &str) -> Result<[FactionFlag; 2]> {
113 let row = faction_row(tables, faction)?;
114 Ok([
115 flag(&row, "flags_path", ["primary_colour_hex", "secondary_colour_hex", "uniform_colour_hex"])?,
116 flag(&row, "republican_flag_path", ["alt_primary_colour_hex", "alt_secondary_colour_hex", "alt_uniform_colour_hex"])?,
117 ])
118}
119
120pub fn faction_summary(tables: &StartposTables, index: &CampaignIndex, faction: &FactionEntry) -> Result<FactionSummary> {
132 let key = faction.key();
133 let mut summary = FactionSummary {
134 key: key.to_owned(),
135 capital: index.capital_of(key).map(|region| region.key().to_owned()),
136 region_count: index.regions_of(key).count(),
137 without_characters: index.characters_of(key).all(|character| !character.death_type().is_empty()),
138 progenitor: index.characters_of(key).find(|character| character.progenitor()).map(|character| character.id().to_owned()),
139 ..Default::default()
140 };
141
142 for row in tables.table("start_pos_victory_conditions")?.rows() {
143 if row.str("start_pos_faction")? == *faction.id() {
144 summary.victory_regions.push(row.str("region")?.into_owned());
145 }
146 }
147
148 for row in tables.table("start_pos_diplomacy")?.rows() {
149 let (Some(first), Some(second)) = (index.faction_by_id(&row.str("faction1")?), index.faction_by_id(&row.str("faction2")?)) else { continue };
150 if first.key() != key && second.key() != key {
151 continue;
152 }
153
154 let stance = row.str("stance")?;
155 summary.has_war_or_vassal |= stance == "war" || stance == "vassal";
156 match stance.as_ref() {
157 "client_state" | "vassal" if second.key() == key => summary.subjects.push(first.key().to_owned()),
158 "client_state" => summary.client_state_of = Some(second.key().to_owned()),
159 "vassal" => summary.vassal_of = Some(second.key().to_owned()),
160 _ => {},
161 }
162 }
163
164 let order = index.factions_in_startpos_order();
165 summary.subjects.sort_by_key(|subject| order.iter().position(|faction| faction.key() == subject));
166
167 if faction_row(tables, key)?.bool("can_be_horde")? {
168 summary.horde = Some(summary.region_count == 0);
169 }
170
171 Ok(summary)
172}
173
174pub(crate) fn faction_row<'a>(tables: &'a StartposTables, faction: &str) -> Result<Row<'a>> {
176 for row in tables.table("factions")?.rows() {
177 if row.str("key")? == faction {
178 return Ok(row);
179 }
180 }
181 Err(RLibError::StartposInvalidValue("factions".to_owned(), "key".to_owned(), faction.to_owned()))
182}
183
184pub(crate) fn flag(row: &Row, path_column: &str, colour_columns: [&str; 3]) -> Result<FactionFlag> {
186 let mut colours = [[0; 3]; 3];
187 for (colour, column) in colours.iter_mut().zip(colour_columns) {
188 *colour = row.colour(column)?;
189 }
190 Ok(FactionFlag { path: row.str(path_column)?.into_owned(), colours })
191}