Branch data Line data Source code
1 : : use anyhow::{anyhow, Result};
2 : : use indexmap::IndexMap;
3 : : use std::{path::Path, vec};
4 : :
5 : : use serde::{Deserialize, Serialize};
6 : :
7 : : use crate::{
8 : : common::{
9 : : all_target_const::{TARGET_ALLY, TARGET_ENNEMY},
10 : : reach_const::INDIVIDUAL,
11 : : stats_const::HP,
12 : : },
13 : : effect::EffectParam,
14 : : utils,
15 : : };
16 : :
17 : : #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
18 : : pub struct AtksInfo {
19 : : pub atk_name: String,
20 : : pub nb_use: i64,
21 : : pub all_damages_by_target: IndexMap<String, i64>, // key target, i64 dmg or heal accumulated
22 : : }
23 : :
24 : : /// Defines the parameters of an attack.
25 : : #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
26 : : #[serde(default)]
27 : : pub struct AttackType {
28 : : /// Name of the attack
29 : : #[serde(rename = "Nom")]
30 : : pub name: String,
31 : : #[serde(rename = "Niveau")]
32 : : pub level: u8,
33 : : #[serde(rename = "Coût de mana")]
34 : : pub mana_cost: u64,
35 : : #[serde(rename = "Coût de vigueur")]
36 : : pub vigor_cost: u64,
37 : : #[serde(rename = "Coût de rage")]
38 : : pub berseck_cost: u64,
39 : : #[serde(rename = "Cible")]
40 : : pub target: String,
41 : : #[serde(rename = "Portée")]
42 : : pub reach: String,
43 : : #[serde(rename = "Photo")]
44 : : pub name_photo: String,
45 : : #[serde(rename = "Effet")]
46 : : pub all_effects: Vec<EffectParam>,
47 : : #[serde(rename = "Forme")]
48 : : pub form: String,
49 : : #[serde(rename = "Aggro")]
50 : : pub aggro: i64,
51 : : #[serde(rename = "Durée")]
52 : : pub turns_duration: i64,
53 : : }
54 : :
55 : : impl Default for AttackType {
56 : 249 : fn default() -> Self {
57 : 249 : AttackType {
58 : 249 : name: "".to_owned(),
59 : 249 : level: 0,
60 : 249 : mana_cost: 0,
61 : 249 : vigor_cost: 0,
62 : 249 : berseck_cost: 0,
63 : 249 : target: TARGET_ALLY.to_owned(),
64 : 249 : reach: INDIVIDUAL.to_owned(),
65 : 249 : name_photo: "".to_owned(),
66 : 249 : all_effects: vec![],
67 : 249 : form: "".to_owned(),
68 : 249 : aggro: 0,
69 : 249 : turns_duration: 0,
70 : 249 : }
71 : 249 : }
72 : : }
73 : :
74 : : impl AttackType {
75 : 218 : pub fn try_new_from_json<P: AsRef<Path>>(path: P) -> Result<AttackType> {
76 : 218 : if let Ok(value) = utils::read_from_json::<_, AttackType>(&path) {
77 : 218 : Ok(value)
78 : : } else {
79 : 0 : Err(anyhow!("Unknown file: {:?}", path.as_ref()))
80 : : }
81 : 218 : }
82 : :
83 : 0 : pub fn has_only_heal_effect(&self) -> bool {
84 : 0 : let mut is_only_heal_effect = false;
85 : 0 : for e in &self.all_effects {
86 : 0 : if e.stats_name == HP && e.value < 0 {
87 : 0 : return false;
88 : 0 : }
89 : 0 : if e.stats_name == HP && e.value > 0 {
90 : 0 : is_only_heal_effect = true;
91 : 0 : }
92 : : }
93 : 0 : if self.target != TARGET_ENNEMY && is_only_heal_effect {
94 : 0 : return true;
95 : 0 : }
96 : 0 : false
97 : 0 : }
98 : : }
99 : :
100 : : #[cfg(test)]
101 : : mod tests {
102 : : use crate::{
103 : : attack_type::AttackType,
104 : : common::{
105 : : all_target_const::TARGET_ENNEMY, character_json_key::STANDARD_CLASS,
106 : : effect_const::EFFECT_VALUE_CHANGE, reach_const::INDIVIDUAL, stats_const::HP,
107 : : },
108 : : };
109 : :
110 : : #[test]
111 : 1 : fn unit_try_new_from_json() {
112 : 1 : let file_path = "./tests/offlines/attack/test/SimpleAtk.json"; // Path to the JSON file
113 : 1 : let atk_type = AttackType::try_new_from_json(file_path);
114 : 1 : assert!(atk_type.is_ok());
115 : 1 : let atk_type: AttackType = atk_type.unwrap();
116 : 1 : assert_eq!(atk_type.name, "SimpleAtk");
117 : 1 : assert_eq!(atk_type.level, 1);
118 : 1 : assert_eq!(atk_type.mana_cost, 9);
119 : 1 : assert_eq!(atk_type.vigor_cost, 0);
120 : 1 : assert_eq!(atk_type.berseck_cost, 0);
121 : 1 : assert_eq!(atk_type.target, TARGET_ENNEMY);
122 : 1 : assert_eq!(atk_type.reach, INDIVIDUAL);
123 : 1 : assert_eq!(atk_type.name_photo, "SimpleAtk.png");
124 : 1 : assert_eq!(atk_type.form, STANDARD_CLASS);
125 : 1 : assert_eq!(atk_type.aggro, 0);
126 : : // decode the effect
127 : 1 : assert_eq!(atk_type.all_effects.len(), 1);
128 : 1 : assert_eq!(atk_type.all_effects[0].stats_name, HP);
129 : 1 : assert_eq!(atk_type.all_effects[0].value, -35);
130 : 1 : assert_eq!(atk_type.all_effects[0].target, TARGET_ENNEMY);
131 : 1 : assert_eq!(atk_type.all_effects[0].reach, INDIVIDUAL);
132 : 1 : assert_eq!(atk_type.all_effects[0].effect_type, EFFECT_VALUE_CHANGE);
133 : 1 : assert_eq!(atk_type.all_effects[0].sub_value_effect, 0);
134 : 1 : }
135 : : }
|