nil_core/military/squad/
mod.rs1pub mod size;
5
6use crate::error::{Error, Result};
7use crate::military::unit::stats::haul::Haul;
8use crate::military::unit::stats::power::{AttackPower, DefensePower, Power};
9use crate::military::unit::stats::speed::Speed;
10use crate::military::unit::{Unit, UnitBox, UnitId, UnitKind};
11use crate::ranking::score::Score;
12use crate::resources::maintenance::Maintenance;
13use crate::world::config::WorldConfig;
14use serde::{Deserialize, Serialize};
15use size::SquadSize;
16use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
17
18#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
20#[serde(rename_all = "camelCase")]
21#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
22pub struct Squad {
23 unit: UnitBox,
24 size: SquadSize,
25}
26
27impl Squad {
28 pub fn new(id: UnitId, size: impl Into<SquadSize>) -> Self {
29 Self {
30 unit: UnitBox::from(id),
31 size: size.into(),
32 }
33 }
34
35 #[inline]
36 pub fn unit(&self) -> &dyn Unit {
37 self.unit.as_dyn()
38 }
39
40 #[inline]
41 pub fn id(&self) -> UnitId {
42 self.unit.id()
43 }
44
45 #[inline]
46 pub fn kind(&self) -> UnitKind {
47 self.unit.kind()
48 }
49
50 #[inline]
51 pub fn size(&self) -> SquadSize {
52 self.size
53 }
54
55 #[inline]
56 pub fn score(&self) -> Score {
57 self.size * self.unit.score()
58 }
59
60 #[inline]
61 pub fn is_empty(&self) -> bool {
62 self.size == 0u32
63 }
64
65 pub fn maintenance(&self) -> Maintenance {
66 let chunk = self.unit.chunk();
67 let c_size = chunk.size();
68 let c_maintenance = chunk.maintenance();
69 (self.size() * c_maintenance) / c_size
70 }
71
72 #[inline]
74 pub fn power(&self) -> Power {
75 self.unit.power() * self.size
76 }
77
78 #[inline]
79 pub fn attack(&self) -> AttackPower {
80 self.unit.attack() * self.size
81 }
82
83 #[inline]
84 pub fn defense(&self) -> DefensePower {
85 self.unit.defense() * self.size
86 }
87
88 #[inline]
89 pub fn speed(&self, config: &WorldConfig) -> Speed {
90 self.unit.speed(config)
91 }
92
93 #[inline]
94 pub fn haul(&self) -> Haul {
95 self.unit.haul() * self.size
96 }
97
98 pub fn checked_sub(&self, rhs: &Self) -> Result<Option<Self>> {
99 if self.unit == rhs.unit {
100 Ok(try { Self::new(self.id(), self.size.checked_sub(rhs.size)?) })
101 } else {
102 Err(Error::UnexpectedUnit(self.id(), rhs.id()))
103 }
104 }
105}
106
107impl From<UnitId> for Squad {
108 fn from(id: UnitId) -> Self {
109 Squad::new(id, SquadSize::new(0))
110 }
111}
112
113impl Add for Squad {
114 type Output = Squad;
115
116 fn add(mut self, rhs: Self) -> Self::Output {
117 self += rhs;
118 self
119 }
120}
121
122impl Add<SquadSize> for Squad {
123 type Output = Squad;
124
125 fn add(mut self, rhs: SquadSize) -> Self::Output {
126 self += rhs;
127 self
128 }
129}
130
131impl AddAssign for Squad {
132 fn add_assign(&mut self, rhs: Self) {
133 if self.id() == rhs.id() {
134 self.size += rhs.size;
135 }
136 }
137}
138
139impl AddAssign<SquadSize> for Squad {
140 fn add_assign(&mut self, rhs: SquadSize) {
141 self.size += rhs;
142 }
143}
144
145impl Sub for Squad {
146 type Output = Squad;
147
148 fn sub(mut self, rhs: Self) -> Self::Output {
149 self -= rhs;
150 self
151 }
152}
153
154impl Sub<SquadSize> for Squad {
155 type Output = Squad;
156
157 fn sub(mut self, rhs: SquadSize) -> Self::Output {
158 self -= rhs;
159 self
160 }
161}
162
163impl SubAssign for Squad {
164 fn sub_assign(&mut self, rhs: Self) {
165 if self.id() == rhs.id() {
166 self.size -= rhs.size;
167 }
168 }
169}
170
171impl SubAssign<SquadSize> for Squad {
172 fn sub_assign(&mut self, rhs: SquadSize) {
173 self.size -= rhs;
174 }
175}
176
177impl Mul<f64> for Squad {
178 type Output = Squad;
179
180 fn mul(mut self, rhs: f64) -> Self::Output {
181 self *= rhs;
182 self
183 }
184}
185
186impl MulAssign<f64> for Squad {
187 fn mul_assign(&mut self, rhs: f64) {
188 self.size *= rhs;
189 }
190}