poke_data/models/
pokemon_move.rs

1use crate::data::link_context::LinkContext;
2use crate::data::linkable::Linkable;
3use crate::models::contest_effect::{ContestEffect, ContestEffectId};
4use crate::models::contest_type::{ContestType, ContestTypeId};
5use crate::models::damage_class::{DamageClass, DamageClassId};
6use crate::models::flavor_texts::FlavorTexts;
7use crate::models::generation::{Generation, GenerationId};
8use crate::models::localized_names::LocalizedStrings;
9use crate::models::pokemon_move::changelog::{PokemonMoveChangelog, UnlinkedPokemonMoveChangelog};
10use crate::models::pokemon_move::meta::{PokemonMoveMeta, UnlinkedPokemonMoveMeta};
11use crate::models::pokemon_move_effect::{PokemonMoveEffect, PokemonMoveEffectId};
12use crate::models::pokemon_move_flag::{PokemonMoveFlag, PokemonMoveFlagId};
13use crate::models::pokemon_move_target::{PokemonMoveTarget, PokemonMoveTargetId};
14use crate::models::super_contest_effect::{SuperContestEffect, SuperContestEffectId};
15use crate::models::version_group::VersionGroupId;
16use crate::traits::has_identifier::HasIdentifier;
17use crate::traits::has_localized_names::HasLocalizedNames;
18use crate::types::pokemon_type::Type;
19use serde::{Deserialize, Serialize};
20use std::collections::HashMap;
21use std::sync::Arc;
22
23pub mod changelog;
24pub mod meta;
25
26pub type PokemonMoveId = u16;
27
28#[derive(Debug)]
29pub struct PokemonMove {
30    pub id: PokemonMoveId,
31    pub identifier: String,
32    pub names: LocalizedStrings,
33    pub flavor_texts: FlavorTexts,
34    pub generation: Arc<Generation>,
35    pub pokemon_type: Type,
36    pub power: Option<u8>,
37    pub pp: Option<u8>,
38    pub accuracy: Option<u8>,
39    pub priority: i8,
40    pub target: Arc<PokemonMoveTarget>,
41    pub damage_class: Arc<DamageClass>,
42    pub effect: Option<Arc<PokemonMoveEffect>>,
43    pub effect_chance: Option<u8>,
44    pub contest_type: Option<Arc<ContestType>>,
45    pub contest_effect: Option<Arc<ContestEffect>>,
46    pub super_contest_effect: Option<Arc<SuperContestEffect>>,
47    pub changelogs: HashMap<VersionGroupId, PokemonMoveChangelog>,
48    pub flags: Vec<Arc<PokemonMoveFlag>>,
49    pub meta_data: Option<PokemonMoveMeta>,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct UnlinkedPokemonMove {
54    pub id: PokemonMoveId,
55    pub identifier: String,
56    pub names: LocalizedStrings,
57    pub flavor_texts: FlavorTexts,
58    pub generation_id: GenerationId,
59    pub pokemon_type: Type,
60    pub power: Option<u8>,
61    pub pp: Option<u8>,
62    pub accuracy: Option<u8>,
63    pub priority: i8,
64    pub target_id: PokemonMoveTargetId,
65    pub damage_class_id: DamageClassId,
66    pub effect_id: Option<PokemonMoveEffectId>,
67    pub effect_chance: Option<u8>,
68    pub contest_type_id: Option<ContestTypeId>,
69    pub contest_effect_id: Option<ContestEffectId>,
70    pub super_contest_effect_id: Option<SuperContestEffectId>,
71    pub changelogs: HashMap<VersionGroupId, UnlinkedPokemonMoveChangelog>,
72    pub flag_ids: Vec<PokemonMoveFlagId>,
73    pub meta_data: Option<UnlinkedPokemonMoveMeta>,
74}
75
76impl Linkable for UnlinkedPokemonMove {
77    type Linked = Arc<PokemonMove>;
78
79    fn link(&self, context: &LinkContext) -> Self::Linked {
80        let generation = context
81            .generations
82            .get(&self.generation_id)
83            .unwrap_or_else(|| {
84                panic!(
85                    "No generation '{}' found for move '{}'",
86                    self.generation_id, self.id
87                )
88            })
89            .clone();
90
91        let target = context
92            .move_targets
93            .get(&self.target_id)
94            .unwrap_or_else(|| {
95                panic!(
96                    "No move target '{}' found for move '{}'",
97                    self.target_id, self.id
98                )
99            })
100            .clone();
101
102        let damage_class = context
103            .damage_classes
104            .get(&self.damage_class_id)
105            .unwrap_or_else(|| {
106                panic!(
107                    "No move damage class '{}' found for move '{}'",
108                    self.damage_class_id, self.id
109                )
110            })
111            .clone();
112
113        let effect = self.effect_id.map(|effect_id| {
114            context
115                .move_effects
116                .get(&effect_id)
117                .unwrap_or_else(|| {
118                    panic!(
119                        "No move effect '{}' found for move '{}'",
120                        effect_id, self.id
121                    )
122                })
123                .clone()
124        });
125
126        let contest_type = self.contest_type_id.map(|contest_type_id| {
127            context
128                .contest_types
129                .get(&contest_type_id)
130                .unwrap_or_else(|| {
131                    panic!(
132                        "No contest type '{}' found for move '{}'",
133                        contest_type_id, self.id
134                    )
135                })
136                .clone()
137        });
138
139        let contest_effect = self.contest_effect_id.map(|contest_effect_id| {
140            context
141                .contest_effects
142                .get(&contest_effect_id)
143                .unwrap_or_else(|| {
144                    panic!(
145                        "No contest effect '{}' found for move '{}'",
146                        contest_effect_id, self.id
147                    )
148                })
149                .clone()
150        });
151
152        let super_contest_effect = self.super_contest_effect_id.map(|super_contest_effect_id| {
153            context
154                .super_contest_effects
155                .get(&super_contest_effect_id)
156                .unwrap_or_else(|| {
157                    panic!(
158                        "No super contest effect '{}' found for move '{}'",
159                        super_contest_effect_id, self.id
160                    )
161                })
162                .clone()
163        });
164
165        let changelogs = self
166            .changelogs
167            .iter()
168            .map(|(version_group_id, changelog)| (*version_group_id, changelog.link(context)))
169            .collect();
170
171        let flags = self
172            .flag_ids
173            .iter()
174            .map(|flag_id| {
175                context
176                    .move_flags
177                    .get(flag_id)
178                    .unwrap_or_else(|| {
179                        panic!("No move flag '{}' found for move '{}'", flag_id, self.id)
180                    })
181                    .clone()
182            })
183            .collect();
184
185        let meta_data = self.meta_data.clone().map(|data| data.link(context));
186
187        let pokemon_move = PokemonMove {
188            id: self.id,
189            identifier: self.identifier.clone(),
190            names: self.names.clone(),
191            flavor_texts: self.flavor_texts.clone(),
192            generation,
193            pokemon_type: self.pokemon_type,
194            power: self.power,
195            pp: self.pp,
196            accuracy: self.accuracy,
197            priority: self.priority,
198            target,
199            damage_class,
200            effect,
201            effect_chance: self.effect_chance,
202            contest_type,
203            contest_effect,
204            super_contest_effect,
205            changelogs,
206            flags,
207            meta_data,
208        };
209
210        Arc::new(pokemon_move)
211    }
212}
213
214impl HasIdentifier for PokemonMove {
215    fn identifier(&self) -> &str {
216        &self.identifier
217    }
218}
219
220impl HasLocalizedNames for PokemonMove {
221    fn localized_names(&self) -> &LocalizedStrings {
222        &self.names
223    }
224}