1use crate::{
2 comp::{Density, Mass},
3 consts::{AIR_DENSITY, IRON_DENSITY, WATER_DENSITY},
4};
5use common_base::enum_iter;
6use rand::{prelude::IndexedRandom, rng};
7use serde::{Deserialize, Serialize};
8use vek::Vec3;
9
10enum_iter! {
11 ~const_array(ALL)
12 #[derive(
13 Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
14 )]
15 #[repr(u32)]
16 pub enum Body {
17 Arrow = 0,
18 Bomb = 1,
19 Scarecrow = 2,
20 Pumpkin = 3,
21 Campfire = 4,
22 BoltFire = 5,
23 ArrowSnake = 6,
24 CampfireLit = 7,
25 BoltFireBig = 8,
26 TrainingDummy = 9,
27 FireworkBlue = 10,
28 FireworkGreen = 11,
29 FireworkPurple = 12,
30 FireworkRed = 13,
31 FireworkWhite = 14,
32 FireworkYellow = 15,
33 MultiArrow = 16,
34 BoltNature = 17,
35 ToughMeat = 18,
36 BeastMeat = 19,
37 Crossbow = 20,
38 ArrowTurret = 21,
39 ClayRocket = 22,
40 HaniwaSentry = 23,
41 SeaLantern = 24,
42 Snowball = 25,
43 Tornado = 26,
44 Apple = 27,
45 Hive = 28,
46 Coconut = 29,
47 SpitPoison = 30,
48 BoltIcicle = 31,
49 Dart = 32,
50 GnarlingTotemRed = 33,
51 GnarlingTotemGreen = 34,
52 GnarlingTotemWhite = 35,
53 DagonBomb = 36,
54 BarrelOrgan = 37,
55 IceBomb = 38,
56 SpectralSwordSmall = 39,
57 SpectralSwordLarge = 40,
58 LaserBeam = 41,
59 AdletSpear = 42,
60 AdletTrap = 43,
61 Flamethrower = 44,
62 Mine = 45,
63 LightningBolt = 46,
64 SpearIcicle = 47,
65 Portal = 48,
66 PortalActive = 49,
67 FieryTornado = 50,
68 FireRainDrop = 51,
69 ArrowClay = 52,
70 GrenadeClay = 53,
71 Pebble = 54,
72 LaserBeamSmall = 55,
73 TerracottaStatue = 56,
74 TerracottaDemolisherBomb = 57,
75 BoltBesieger = 58,
76 SurpriseEgg = 59,
77 BubbleBomb = 60,
78 IronPikeBomb = 61,
79 Lavathrower = 62,
80 PoisonBall = 63,
81 StrigoiHead = 64,
82 HarlequinDagger = 65,
83 BloodBomb = 66,
84 MinotaurAxe = 67,
85 BorealTrap = 68,
86 Crux = 69,
87 ArrowHeavy = 70,
88 FireRing = 71,
89 PyroclasmBolt = 72,
90 NapalmShot = 73,
91 NapalmPool = 74,
92 ThornStake = 75,
93 }
94}
95
96impl Body {
97 pub fn random() -> Self {
98 let mut rng = rng();
99 *ALL_OBJECTS.choose(&mut rng).unwrap()
100 }
101}
102
103pub const ALL_OBJECTS: [Body; Body::NUM_KINDS] = Body::ALL;
104
105impl From<Body> for super::Body {
106 fn from(body: Body) -> Self { super::Body::Object(body) }
107}
108
109impl Body {
110 pub fn to_string(self) -> &'static str {
111 match self {
112 Body::Arrow => "arrow",
113 Body::Bomb => "bomb",
114 Body::Scarecrow => "scarecrow",
115 Body::Pumpkin => "pumpkin",
116 Body::Campfire => "campfire",
117 Body::CampfireLit => "campfire_lit",
118 Body::BoltFire => "bolt_fire",
119 Body::BoltFireBig => "bolt_fire_big",
120 Body::ArrowSnake => "arrow_snake",
121 Body::TrainingDummy => "training_dummy",
122 Body::FireworkBlue => "firework_blue",
123 Body::FireworkGreen => "firework_green",
124 Body::FireworkPurple => "firework_purple",
125 Body::FireworkRed => "firework_red",
126 Body::FireworkWhite => "firework_white",
127 Body::FireworkYellow => "firework_yellow",
128 Body::MultiArrow => "multi_arrow",
129 Body::BoltNature => "bolt_nature",
130 Body::ToughMeat => "tough_meat",
131 Body::BeastMeat => "beast_meat",
132 Body::Crossbow => "crossbow",
133 Body::ArrowTurret => "arrow_turret",
134 Body::ClayRocket => "clay_rocket",
135 Body::HaniwaSentry => "haniwa_sentry",
136 Body::SeaLantern => "sea_lantern",
137 Body::Snowball => "snowball",
138 Body::Tornado => "tornado",
139 Body::Apple => "apple",
140 Body::Hive => "hive",
141 Body::Coconut => "coconut",
142 Body::SpitPoison => "spit_poison",
143 Body::BoltIcicle => "bolt_icicle",
144 Body::Dart => "dart",
145 Body::GnarlingTotemRed => "gnarling_totem_red",
146 Body::GnarlingTotemGreen => "gnarling_totem_green",
147 Body::GnarlingTotemWhite => "gnarling_totem_white",
148 Body::DagonBomb => "dagon_bomb",
149 Body::TerracottaDemolisherBomb => "terracotta_demolisher_bomb",
150 Body::BarrelOrgan => "barrel_organ",
151 Body::IceBomb => "ice_bomb",
152 Body::SpectralSwordSmall => "spectral_sword_small",
153 Body::SpectralSwordLarge => "spectral_sword_large",
154 Body::LaserBeam => "laser_beam",
155 Body::LaserBeamSmall => "laser_beam_small",
156 Body::AdletSpear => "adlet_spear",
157 Body::AdletTrap => "adlet_trap",
158 Body::Flamethrower => "flamethrower",
159 Body::Lavathrower => "lavathrower",
160 Body::Mine => "mine",
161 Body::LightningBolt => "lightning_bolt",
162 Body::SpearIcicle => "spear_icicle",
163 Body::Portal => "portal",
164 Body::PortalActive => "portal_active",
165 Body::FieryTornado => "fiery_tornado",
166 Body::FireRainDrop => "fire_rain_drop",
167 Body::ArrowClay => "arrow_clay",
168 Body::GrenadeClay => "grenade_clay",
169 Body::Pebble => "pebble",
170 Body::TerracottaStatue => "terracotta_statue",
171 Body::BoltBesieger => "besieger_bolt",
172 Body::SurpriseEgg => "surprise_egg",
173 Body::BubbleBomb => "bubble_bomb",
174 Body::IronPikeBomb => "iron_pike_bomb",
175 Body::PoisonBall => "poison_ball",
176 Body::StrigoiHead => "strigoi_head",
177 Body::HarlequinDagger => "harlequin_dagger",
178 Body::BloodBomb => "blood_bomb",
179 Body::MinotaurAxe => "minotaur_axe",
180 Body::BorealTrap => "boreal_trap",
181 Body::Crux => "crux",
182 Body::ArrowHeavy => "heavy_arrow",
183 Body::FireRing => "fire_ring",
184 Body::PyroclasmBolt => "pyroclasm_bolt",
185 Body::NapalmShot => "napalm_shot",
186 Body::NapalmPool => "napalm_pool",
187 Body::ThornStake => "thorn_stake",
188 }
189 }
190
191 pub fn density(&self) -> Density {
192 let density = match self {
193 Body::Arrow
194 | Body::ArrowSnake
195 | Body::ArrowTurret
196 | Body::MultiArrow
197 | Body::ArrowClay
198 | Body::BoltBesieger
199 | Body::Dart
200 | Body::DagonBomb
201 | Body::TerracottaDemolisherBomb
202 | Body::SpectralSwordSmall
203 | Body::SpectralSwordLarge
204 | Body::AdletSpear
205 | Body::HarlequinDagger
206 | Body::AdletTrap
207 | Body::Flamethrower
208 | Body::Lavathrower
209 | Body::BorealTrap
210 | Body::BloodBomb
211 | Body::ArrowHeavy
212 | Body::ThornStake => 500.0,
213 Body::Bomb | Body::Mine | Body::SurpriseEgg => 2000.0, Body::Scarecrow => 900.0,
216 Body::TrainingDummy => 2000.0,
217 Body::Snowball => 0.9 * WATER_DENSITY,
218 Body::Pebble => 1000.0,
219 Body::Crux | Body::FireRing | Body::PyroclasmBolt => AIR_DENSITY,
220 _ => 1.1 * WATER_DENSITY,
222 };
223
224 Density(density)
225 }
226
227 pub fn mass(&self) -> Mass {
228 let m = match self {
229 Body::Arrow | Body::ArrowSnake | Body::ArrowTurret | Body::MultiArrow | Body::Dart => {
231 0.003
232 },
233 Body::SpectralSwordSmall => 0.5,
234 Body::SpectralSwordLarge => 50.0,
235 Body::BoltFire
236 | Body::BoltFireBig
237 | Body::BoltNature
238 | Body::BoltIcicle
239 | Body::FireRainDrop
240 | Body::ArrowClay
241 | Body::Pebble
242 | Body::BubbleBomb
243 | Body::IronPikeBomb
244 | Body::BoltBesieger
245 | Body::PoisonBall
246 | Body::ArrowHeavy
247 | Body::FireRing
248 | Body::PyroclasmBolt
249 | Body::NapalmShot
250 | Body::ThornStake => 1.0,
251 Body::SpitPoison => 100.0,
252 Body::Bomb
253 | Body::DagonBomb
254 | Body::SurpriseEgg
255 | Body::TerracottaDemolisherBomb
256 | Body::BloodBomb => {
257 0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3)
258 },
259 Body::Campfire
260 | Body::CampfireLit
261 | Body::BarrelOrgan
262 | Body::TerracottaStatue
263 | Body::NapalmPool => 300.0,
264 Body::Crossbow => 200.0,
265 Body::Flamethrower | Body::Lavathrower => 200.0,
266 Body::FireworkBlue
267 | Body::FireworkGreen
268 | Body::FireworkPurple
269 | Body::FireworkRed
270 | Body::FireworkWhite
271 | Body::FireworkYellow => 1.0,
272 Body::ToughMeat => 50.0,
273 Body::BeastMeat => 50.0,
274 Body::Pumpkin | Body::StrigoiHead => 10.0,
275 Body::Scarecrow => 50.0,
276 Body::TrainingDummy => 60.0,
277 Body::ClayRocket | Body::GrenadeClay => 50.0,
278 Body::HaniwaSentry => 300.0,
279 Body::SeaLantern => 1000.0,
280 Body::MinotaurAxe => 100000.0,
281 Body::Snowball => 7360.0, Body::Tornado | Body::FieryTornado => 50.0,
283 Body::Apple => 2.0,
284 Body::Hive => 2.0,
285 Body::Coconut => 2.0,
286 Body::GnarlingTotemRed | Body::GnarlingTotemGreen | Body::GnarlingTotemWhite => 100.0,
287 Body::IceBomb => 12298.0, Body::LaserBeam | Body::LaserBeamSmall => 80000.0,
289 Body::AdletSpear => 1.5,
290 Body::AdletTrap => 10.0,
291 Body::Mine => 100.0,
292 Body::HarlequinDagger => 1.5,
293 Body::BorealTrap => 10.0,
294 Body::LightningBolt | Body::SpearIcicle => 20000.0,
295 Body::Portal | Body::PortalActive => 10.0, Body::Crux => 100.0,
297 };
298
299 Mass(m)
300 }
301
302 pub fn dimensions(&self) -> Vec3<f32> {
303 match self {
304 Body::Arrow
305 | Body::ArrowSnake
306 | Body::MultiArrow
307 | Body::ArrowTurret
308 | Body::ArrowClay
309 | Body::BoltBesieger
310 | Body::Dart
311 | Body::HarlequinDagger
312 | Body::AdletSpear => Vec3::new(0.01, 0.8, 0.01),
313 Body::AdletTrap => Vec3::new(1.0, 0.6, 0.3),
314 Body::BoltFire | Body::PoisonBall | Body::NapalmShot => Vec3::new(0.1, 0.1, 0.1),
315 Body::SpectralSwordSmall => Vec3::new(0.2, 0.9, 0.1),
316 Body::SpectralSwordLarge => Vec3::new(0.2, 1.5, 0.1),
317 Body::Crossbow => Vec3::new(3.0, 3.0, 1.5),
318 Body::Flamethrower => Vec3::new(3.0, 3.0, 2.5),
319 Body::Lavathrower => Vec3::new(3.0, 3.0, 2.0),
320 Body::HaniwaSentry => Vec3::new(0.8, 0.8, 1.4),
321 Body::SeaLantern => Vec3::new(0.8, 0.8, 1.4),
322 Body::Snowball => Vec3::broadcast(2.5),
323 Body::Tornado | Body::FieryTornado => Vec3::new(2.0, 2.0, 3.4),
324 Body::TrainingDummy => Vec3::new(1.5, 1.5, 3.0),
325 Body::BorealTrap => Vec3::new(1.0, 0.6, 0.3),
326 Body::GnarlingTotemRed | Body::GnarlingTotemGreen | Body::GnarlingTotemWhite => {
327 Vec3::new(0.8, 0.8, 1.4)
328 },
329 Body::BarrelOrgan => Vec3::new(4.0, 2.0, 3.0),
330 Body::TerracottaStatue => Vec3::new(5.0, 5.0, 5.0),
331 Body::IceBomb => Vec3::broadcast(2.5),
332 Body::LaserBeam => Vec3::new(8.0, 8.0, 8.0),
333 Body::LaserBeamSmall => Vec3::new(1.0, 1.0, 1.0),
334 Body::Mine => Vec3::new(0.8, 0.8, 0.5),
335 Body::LightningBolt | Body::SpearIcicle => Vec3::new(1.0, 1.0, 1.0),
336 Body::FireRainDrop => Vec3::new(0.01, 0.01, 0.02),
337 Body::Pebble => Vec3::new(0.4, 0.4, 0.4),
338 Body::MinotaurAxe => Vec3::new(5.0, 5.0, 5.0),
339 Body::Crux => Vec3::new(2.0, 2.0, 2.0),
340 Body::ArrowHeavy | Body::ThornStake => Vec3::new(0.1, 0.9, 0.1),
341 _ => Vec3::broadcast(0.5),
343 }
344 }
345}