ck3_history_extractor/structures/
lineage.rs

1use jomini::common::Date;
2use serde::{ser::SerializeStruct, Serialize};
3
4use super::{
5    super::{
6        game_data::{GameData, Localizable, LocalizationError, Localize},
7        parser::{GameObjectMap, GameObjectMapping, GameState, ParsingError, SaveFileValue},
8        types::{GameString, Wrapper},
9    },
10    Character, EntityRef, FromGameObject, GameObjectDerived, GameRef,
11};
12
13/// A struct representing a lineage node in the game
14pub struct LineageNode {
15    character: GameRef<Character>,
16    date: Date,
17    score: i32,
18    prestige: i32,
19    piety: i32,
20    dread: f32,
21    lifestyle: Option<GameString>,
22    perks: Vec<GameString>, //in older CK3 version this was a list, guess it no longer is
23}
24
25impl LineageNode {
26    /// Gets the character associated with the lineage node
27    pub fn get_character(&self) -> GameRef<Character> {
28        self.character.clone()
29    }
30}
31
32impl FromGameObject for LineageNode {
33    fn from_game_object(
34        base: &GameObjectMap,
35        game_state: &mut GameState,
36    ) -> Result<Self, ParsingError> {
37        let mut perks = Vec::new();
38        if let Some(perks_node) = base.get("perk") {
39            if let SaveFileValue::Object(o) = perks_node {
40                for perk in o.as_array()? {
41                    perks.push(perk.as_string()?)
42                }
43            } else {
44                perks.push(perks_node.as_string()?);
45            }
46        }
47        Ok(LineageNode {
48            character: game_state.get_character(&base.get_game_id("character")?),
49            date: base.get_date("date")?,
50            score: if let Some(score_node) = base.get("score") {
51                score_node.as_integer()? as i32
52            } else {
53                0
54            },
55            prestige: if let Some(prestige_node) = base.get("prestige") {
56                prestige_node.as_integer()? as i32
57            } else {
58                0
59            },
60            piety: if let Some(piety_node) = base.get("piety") {
61                piety_node.as_integer()? as i32
62            } else {
63                0
64            },
65            dread: if let Some(dread_node) = base.get("dread") {
66                dread_node.as_real()? as f32
67            } else {
68                0.0
69            },
70            lifestyle: if let Some(lifestyle_node) = base.get("lifestyle") {
71                Some(lifestyle_node.as_string()?)
72            } else {
73                None
74            },
75            perks: perks,
76        })
77    }
78}
79
80impl GameObjectDerived for LineageNode {
81    fn get_name(&self) -> GameString {
82        self.character
83            .get_internal()
84            .inner()
85            .expect("Character in lineage must be initialized")
86            .get_name()
87    }
88
89    fn get_references<E: From<EntityRef>, C: Extend<E>>(&self, collection: &mut C) {
90        collection.extend([E::from(self.character.clone().into())]);
91    }
92}
93
94impl Localizable for LineageNode {
95    fn localize(&mut self, localization: &GameData) -> Result<(), LocalizationError> {
96        if let Some(lifestyle) = &self.lifestyle {
97            self.lifestyle = Some(localization.localize(lifestyle.to_string() + "_name")?);
98        }
99        for perk in self.perks.iter_mut() {
100            let mut perk_key = perk.to_string();
101            if perk_key == "family_man_perk" {
102                perk_key += if self
103                    .character
104                    .get_internal()
105                    .inner()
106                    .expect("Character in lineage must be initialized")
107                    .get_female()
108                {
109                    "_female_name"
110                } else {
111                    "_male_name"
112                }
113            } else {
114                perk_key += "_name";
115            }
116            *perk = localization.localize(perk_key)?;
117        }
118        Ok(())
119    }
120}
121
122impl Serialize for LineageNode {
123    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
124    where
125        S: serde::Serializer,
126    {
127        let mut state = serializer.serialize_struct("LineageNode", 8)?;
128        state.serialize_field("character", &*self.character.get_internal())?;
129        state.serialize_field("date", &self.date)?;
130        state.serialize_field("score", &self.score)?;
131        state.serialize_field("prestige", &self.prestige)?;
132        state.serialize_field("piety", &self.piety)?;
133        state.serialize_field("dread", &self.dread)?;
134        state.serialize_field("lifestyle", &self.lifestyle)?;
135        state.serialize_field("perks", &self.perks)?;
136        state.end()
137    }
138}