1use enum_map::EnumMap;
2use hashbrown::HashMap;
3use hexx::Hex;
4use serde::Serialize;
5use uuid::Uuid;
6
7use crate::{
8 constants::{
9 general::UNIT_PART_WEIGHTS,
10 unit::{AGE_PER_GEN_PART, UNIT_AGE_EXP, UNIT_BASE_AGE},
11 },
12 intents::{self, Intent, Intents},
13 objects::{GameObjectKind, HasHealth, HasHex, HasId, HasStorage},
14 player::OwnerId, storage::Storage,
15};
16
17pub type Units = HashMap<Hex, Unit>;
18
19#[derive(Default, Serialize, Clone)]
20pub struct Unit {
21 pub id: Uuid,
22 pub kind: GameObjectKind,
23 pub owner_id: OwnerId,
24 pub health: u32,
25 pub hex: Hex,
26 pub energy: u32,
27 pub age: u32,
28 pub body: UnitBody,
29 pub storage: Storage,
30 #[serde(skip)]
31 pub future_health: u32,
32 #[serde(skip)]
33 pub future_energy: u32,
34 #[serde(skip)]
35 pub future_hex: Hex,
36}
37
38impl HasHealth for Unit {
39 fn health(&self) -> u32 {
40 self.health
41 }
42}
43
44impl HasId for Unit {
45 fn id(&self) -> Uuid {
46 self.id
47 }
48}
49
50impl HasHex for Unit {
51 fn hex(&self) -> Hex {
52 self.hex
53 }
54}
55
56impl HasStorage for Unit {
57 fn storage(&self) -> &Storage {
58 &self.storage
59 }
60}
61
62impl Unit {
63 pub fn new(hex: Hex) -> Self {
64 Self {
65 health: 100,
66 hex,
67 ..Default::default()
68 }
69 }
70
71 pub fn max_age(&self) -> u32 {
72 ((self.body[UnitPart::Generate] * AGE_PER_GEN_PART) as f32).powf(UNIT_AGE_EXP) as u32
73 + UNIT_BASE_AGE
74 }
75
76 pub fn weight(&self) -> u32 {
77 let mut weight = 0;
78
79 for (part, _) in UNIT_PART_WEIGHTS.iter() {
80 weight += UNIT_PART_WEIGHTS[part]
81 }
82
83 weight
84 }
85
86 pub fn range(&self) -> u32 {
87 self.body[UnitPart::Ranged]
88 }
89
90 pub fn damage(&self) -> u32 {
91 self.body[UnitPart::Ranged]
92 }
93
94 pub fn attack_cost(&self) -> u32 {
95 self.body[UnitPart::Ranged]
96 }
97
98 }
117
118pub type UnitBody = EnumMap<UnitPart, u32>;
119
120#[derive(enum_map::Enum, Serialize)]
121pub enum UnitPart {
122 Ranged,
123 Harvest,
124 Generate,
125 Work,
126 Battery,
127}