ck3_history_extractor/structures/
artifact.rs1use jomini::common::Date;
2use serde::Serialize;
3
4use crate::types::Wrapper;
5
6use super::{
7 super::{
8 game_data::{GameData, Localizable, LocalizationError, Localize},
9 parser::{GameObjectMap, GameObjectMapping, GameState, ParsingError},
10 types::GameString,
11 },
12 Character, EntityRef, FromGameObject, GameObjectDerived, GameRef,
13};
14
15#[derive(Serialize)]
16pub struct Artifact {
17 name: GameString,
18 description: GameString,
19 r#type: GameString,
20 rarity: GameString,
21 quality: u32,
22 wealth: u32,
23 owner: GameRef<Character>,
24 history: Vec<(
25 GameString,
26 Date,
27 Option<GameRef<Character>>,
28 Option<GameRef<Character>>,
29 )>,
30}
31
32impl FromGameObject for Artifact {
33 fn from_game_object(
34 base: &GameObjectMap,
35 game_state: &mut GameState,
36 ) -> Result<Self, ParsingError> {
37 let mut artifact = Self {
38 name: base.get_string("name")?,
39 description: base.get_string("description")?,
40 r#type: base.get_string("type")?,
41 rarity: base.get_string("rarity")?,
42 quality: base
43 .get("quality")
44 .map_or(Ok(0), |n| n.as_integer().and_then(|v| Ok(v as u32)))?,
45 wealth: base
46 .get("wealth")
47 .map_or(Ok(0), |n| n.as_integer().and_then(|v| Ok(v as u32)))?,
48 owner: game_state.get_character(&base.get_game_id("owner")?),
49 history: Vec::default(),
50 };
51 if let Some(history_node) = base.get("history") {
52 let history_node = history_node.as_object()?;
53 if let Ok(map) = history_node.as_map() {
54 if let Some(entries_node) = map.get("entries") {
55 for h in entries_node.as_object()?.as_array()? {
56 let h = h.as_object()?.as_map()?;
57 let actor = if let Some(actor_node) = h.get("actor") {
58 Some(game_state.get_character(&actor_node.as_id()?))
59 } else {
60 None
61 };
62 let recipient = if let Some(recipient_node) = h.get("recipient") {
63 Some(game_state.get_character(&recipient_node.as_id()?))
64 } else {
65 None
66 };
67 artifact.history.push((
68 h.get_string("type")?,
69 h.get_date("date")?,
70 actor,
71 recipient,
72 ));
73 }
74 }
75 }
76 }
77 Ok(artifact)
78 }
79}
80
81impl GameObjectDerived for Artifact {
82 fn get_name(&self) -> GameString {
83 self.name.clone()
84 }
85
86 fn get_references<E: From<EntityRef>, C: Extend<E>>(&self, collection: &mut C) {
87 for h in self.history.iter() {
88 if let Some(actor) = &h.2 {
89 collection.extend([E::from(actor.clone().into())]);
90 }
91 if let Some(recipient) = &h.3 {
92 collection.extend([E::from(recipient.clone().into())]);
93 }
94 }
95 }
96}
97
98fn handle_tooltips(text: &GameString) -> String {
99 let mut result = String::new();
100 let mut in_tooltip = false;
101 let mut in_tooltip_text = false;
102 for c in text.chars() {
103 match c {
104 '\x15' => {
105 in_tooltip = true;
107 in_tooltip_text = false;
108 }
109 ' ' => {
110 if in_tooltip && !in_tooltip_text {
111 in_tooltip_text = true;
112 } else {
113 result.push(c);
114 }
115 }
116 '!' => {
117 if in_tooltip {
119 in_tooltip = false;
120 in_tooltip_text = false;
121 } else {
122 result.push(c);
123 }
124 }
125 _ => {
126 if !in_tooltip || in_tooltip_text {
127 result.push(c);
128 }
129 }
130 }
131 }
132 return result;
133}
134
135impl Localizable for Artifact {
136 fn localize(&mut self, localization: &GameData) -> Result<(), LocalizationError> {
137 self.rarity = localization.localize(&self.rarity)?;
138 self.r#type = localization.localize("artifact_".to_string() + self.r#type.as_ref())?;
139 self.description = handle_tooltips(&self.description).into();
140 self.name = handle_tooltips(&self.name).into();
141 Ok(())
142 }
143}
144
145impl Serialize for GameRef<Artifact> {
146 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
147 where
148 S: serde::Serializer,
149 {
150 self.get_internal().serialize(serializer)
151 }
152}