1pub mod arthropod;
2pub mod biped_large;
3pub mod biped_small;
4pub mod bird_large;
5pub mod bird_medium;
6pub mod crustacean;
7pub mod dragon;
8pub mod fish_medium;
9pub mod fish_small;
10pub mod golem;
11pub mod humanoid;
12pub mod item;
13pub mod object;
14pub mod parts;
15pub mod plugin;
16pub mod quadruped_low;
17pub mod quadruped_medium;
18pub mod quadruped_small;
19pub mod ship;
20pub mod theropod;
21
22use crate::{
23 assets::{self, Asset},
24 consts::{HUMAN_DENSITY, WATER_DENSITY},
25 npc::NpcKind,
26};
27use common_base::enum_iter;
28use common_i18n::Content;
29use serde::{Deserialize, Serialize};
30use specs::{Component, DerefFlaggedStorage};
31use strum::{Display, IntoEnumIterator};
32use vek::*;
33
34use super::{BuffKind, Collider, Density, Mass, Scale};
35
36enum_iter! {
37 #[derive(
38 Copy, Clone, Debug, Display, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize,
39 )]
40 #[repr(u32)]
41 pub enum Body {
42 Humanoid(humanoid::Body) = 0,
43 QuadrupedSmall(quadruped_small::Body) = 1,
44 QuadrupedMedium(quadruped_medium::Body) = 2,
45 BirdMedium(bird_medium::Body) = 3,
46 FishMedium(fish_medium::Body) = 4,
47 Dragon(dragon::Body) = 5,
48 BirdLarge(bird_large::Body) = 6,
49 FishSmall(fish_small::Body) = 7,
50 BipedLarge(biped_large::Body) = 8,
51 BipedSmall(biped_small::Body) = 9,
52 Object(object::Body) = 10,
53 Golem(golem::Body) = 11,
54 Theropod(theropod::Body) = 12,
55 QuadrupedLow(quadruped_low::Body) = 13,
56 Ship(ship::Body) = 14,
57 Arthropod(arthropod::Body) = 15,
58 Item(item::Body) = 16,
59 Crustacean(crustacean::Body) = 17,
60 Plugin(plugin::Body) = 18,
61 }
62}
63
64impl Default for Body {
66 fn default() -> Self {
67 Body::QuadrupedSmall(quadruped_small::Body {
68 species: quadruped_small::Species::Frog,
69 body_type: quadruped_small::BodyType::Female,
70 })
71 }
72}
73
74#[derive(Clone, Debug, Deserialize, Serialize)]
76pub struct BodyData<BodyMeta, SpeciesData> {
77 pub body: BodyMeta,
79 pub species: SpeciesData,
81}
82
83#[derive(Clone, Debug, Deserialize, Serialize)]
89pub struct AllBodies<BodyMeta, SpeciesMeta> {
90 pub humanoid: BodyData<BodyMeta, humanoid::AllSpecies<SpeciesMeta>>,
91 pub quadruped_small: BodyData<BodyMeta, quadruped_small::AllSpecies<SpeciesMeta>>,
92 pub quadruped_medium: BodyData<BodyMeta, quadruped_medium::AllSpecies<SpeciesMeta>>,
93 pub bird_medium: BodyData<BodyMeta, bird_medium::AllSpecies<SpeciesMeta>>,
94 pub fish_medium: BodyData<BodyMeta, fish_medium::AllSpecies<SpeciesMeta>>,
95 pub dragon: BodyData<BodyMeta, dragon::AllSpecies<SpeciesMeta>>,
96 pub bird_large: BodyData<BodyMeta, bird_large::AllSpecies<SpeciesMeta>>,
97 pub fish_small: BodyData<BodyMeta, fish_small::AllSpecies<SpeciesMeta>>,
98 pub biped_large: BodyData<BodyMeta, biped_large::AllSpecies<SpeciesMeta>>,
99 pub biped_small: BodyData<BodyMeta, biped_small::AllSpecies<SpeciesMeta>>,
100 pub object: BodyData<BodyMeta, ()>,
101 pub item: BodyData<BodyMeta, ()>,
102 pub golem: BodyData<BodyMeta, golem::AllSpecies<SpeciesMeta>>,
103 pub theropod: BodyData<BodyMeta, theropod::AllSpecies<SpeciesMeta>>,
104 pub quadruped_low: BodyData<BodyMeta, quadruped_low::AllSpecies<SpeciesMeta>>,
105 pub ship: BodyData<BodyMeta, ()>,
106 pub arthropod: BodyData<BodyMeta, arthropod::AllSpecies<SpeciesMeta>>,
107 pub crustacean: BodyData<BodyMeta, crustacean::AllSpecies<SpeciesMeta>>,
108 pub plugin: BodyData<BodyMeta, plugin::AllSpecies<SpeciesMeta>>,
109}
110
111impl<BodyMeta, SpeciesMeta> AllBodies<BodyMeta, SpeciesMeta> {
112 pub fn get_species_meta<'a>(&'a self, body: &Body) -> Option<&'a SpeciesMeta> {
117 Some(match body {
118 Body::Humanoid(b) => &self.humanoid.species[&b.species],
119 Body::QuadrupedSmall(b) => &self.quadruped_small.species[&b.species],
120 Body::QuadrupedMedium(b) => &self.quadruped_medium.species[&b.species],
121 Body::BirdMedium(b) => &self.bird_medium.species[&b.species],
122 Body::BirdLarge(b) => &self.bird_large.species[&b.species],
123 Body::FishMedium(b) => &self.fish_medium.species[&b.species],
124 Body::Dragon(b) => &self.dragon.species[&b.species],
125 Body::FishSmall(b) => &self.fish_small.species[&b.species],
126 Body::BipedLarge(b) => &self.biped_large.species[&b.species],
127 Body::BipedSmall(b) => &self.biped_small.species[&b.species],
128 Body::Golem(b) => &self.golem.species[&b.species],
129 Body::Theropod(b) => &self.theropod.species[&b.species],
130 Body::QuadrupedLow(b) => &self.quadruped_low.species[&b.species],
131 Body::Arthropod(b) => &self.arthropod.species[&b.species],
132 Body::Crustacean(b) => &self.crustacean.species[&b.species],
133 Body::Plugin(b) => &self.plugin.species[&b.species],
134 Body::Item(_) | Body::Ship(_) | Body::Object(_) => return None,
135 })
136 }
137}
138
139impl<BodyMeta, SpeciesMeta> core::ops::Index<NpcKind> for AllBodies<BodyMeta, SpeciesMeta> {
141 type Output = BodyMeta;
142
143 #[inline]
144 fn index(&self, index: NpcKind) -> &Self::Output {
145 match index {
146 NpcKind::Humanoid => &self.humanoid.body,
147 NpcKind::Pig => &self.quadruped_small.body,
148 NpcKind::Wolf => &self.quadruped_medium.body,
149 NpcKind::Duck => &self.bird_medium.body,
150 NpcKind::Phoenix => &self.bird_large.body,
151 NpcKind::Marlin => &self.fish_medium.body,
152 NpcKind::Clownfish => &self.fish_small.body,
153 NpcKind::Ogre => &self.biped_large.body,
154 NpcKind::Gnome => &self.biped_small.body,
155 NpcKind::StoneGolem => &self.golem.body,
156 NpcKind::Archaeos => &self.theropod.body,
157 NpcKind::Reddragon => &self.dragon.body,
158 NpcKind::Crocodile => &self.quadruped_low.body,
159 NpcKind::Tarantula => &self.arthropod.body,
160 NpcKind::Crab => &self.crustacean.body,
161 NpcKind::Plugin => &self.plugin.body,
162 }
163 }
164}
165
166impl<BodyMeta, SpeciesMeta> core::ops::Index<&Body> for AllBodies<BodyMeta, SpeciesMeta> {
168 type Output = BodyMeta;
169
170 #[inline]
171 fn index(&self, index: &Body) -> &Self::Output {
172 match index {
173 Body::Humanoid(_) => &self.humanoid.body,
174 Body::QuadrupedSmall(_) => &self.quadruped_small.body,
175 Body::QuadrupedMedium(_) => &self.quadruped_medium.body,
176 Body::BirdMedium(_) => &self.bird_medium.body,
177 Body::BirdLarge(_) => &self.bird_large.body,
178 Body::FishMedium(_) => &self.fish_medium.body,
179 Body::Dragon(_) => &self.dragon.body,
180 Body::FishSmall(_) => &self.fish_small.body,
181 Body::BipedLarge(_) => &self.biped_large.body,
182 Body::BipedSmall(_) => &self.biped_small.body,
183 Body::Object(_) => &self.object.body,
184 Body::Item(_) => &self.item.body,
185 Body::Golem(_) => &self.golem.body,
186 Body::Theropod(_) => &self.theropod.body,
187 Body::QuadrupedLow(_) => &self.quadruped_low.body,
188 Body::Arthropod(_) => &self.arthropod.body,
189 Body::Ship(_) => &self.ship.body,
190 Body::Crustacean(_) => &self.crustacean.body,
191 Body::Plugin(_) => &self.plugin.body,
192 }
193 }
194}
195
196impl<
197 BodyMeta: Send + Sync + for<'de> serde::Deserialize<'de> + 'static,
198 SpeciesMeta: Send + Sync + for<'de> serde::Deserialize<'de> + 'static,
199> Asset for AllBodies<BodyMeta, SpeciesMeta>
200{
201 type Loader = assets::RonLoader;
202
203 const EXTENSION: &'static str = "ron";
204}
205
206#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
217pub enum Gender {
218 Masculine,
219 Feminine,
220 Neuter,
221}
222
223impl Body {
224 pub fn is_same_species_as(&self, other: &Body) -> bool {
225 match self {
226 Body::Humanoid(b1) => match other {
227 Body::Humanoid(b2) => b1.species == b2.species,
228 _ => false,
229 },
230 Body::QuadrupedSmall(b1) => match other {
231 Body::QuadrupedSmall(b2) => b1.species == b2.species,
232 _ => false,
233 },
234 Body::QuadrupedMedium(b1) => match other {
235 Body::QuadrupedMedium(b2) => b1.species == b2.species,
236 _ => false,
237 },
238 Body::BirdMedium(b1) => match other {
239 Body::BirdMedium(b2) => b1.species == b2.species,
240 _ => false,
241 },
242 Body::BirdLarge(b1) => match other {
243 Body::BirdLarge(b2) => b1.species == b2.species,
244 _ => false,
245 },
246 Body::FishMedium(b1) => match other {
247 Body::FishMedium(b2) => b1.species == b2.species,
248 _ => false,
249 },
250 Body::Dragon(b1) => match other {
251 Body::Dragon(b2) => b1.species == b2.species,
252 _ => false,
253 },
254 Body::FishSmall(b1) => match other {
255 Body::FishSmall(b2) => b1.species == b2.species,
256 _ => false,
257 },
258 Body::BipedLarge(b1) => match other {
259 Body::BipedLarge(b2) => b1.species == b2.species,
260 _ => false,
261 },
262 Body::BipedSmall(b1) => match other {
263 Body::BipedSmall(b2) => b1.species == b2.species,
264 _ => false,
265 },
266 Body::Object(_) => false,
267 Body::Item(_) => false,
268 Body::Golem(b1) => match other {
269 Body::Golem(b2) => b1.species == b2.species,
270 _ => false,
271 },
272 Body::Theropod(b1) => match other {
273 Body::Theropod(b2) => b1.species == b2.species,
274 _ => false,
275 },
276 Body::QuadrupedLow(b1) => match other {
277 Body::QuadrupedLow(b2) => b1.species == b2.species,
278 _ => false,
279 },
280 Body::Arthropod(b1) => match other {
281 Body::Arthropod(b2) => b1.species == b2.species,
282 _ => false,
283 },
284 Body::Ship(_) => false,
285 Body::Crustacean(b1) => match other {
286 Body::Crustacean(b2) => b1.species == b2.species,
287 _ => false,
288 },
289 Body::Plugin(b1) => match other {
290 Body::Plugin(b2) => b1.species == b2.species,
291 _ => false,
292 },
293 }
294 }
295
296 pub fn heads(&self) -> Option<usize> {
298 match self {
299 Body::QuadrupedLow(body) => match body.species {
300 quadruped_low::Species::Hydra => Some(3),
301 _ => None,
302 },
303 _ => None,
304 }
305 }
306
307 pub fn is_humanoid(&self) -> bool { matches!(self, Body::Humanoid(_)) }
308
309 pub fn is_campfire(&self) -> bool { matches!(self, Body::Object(object::Body::CampfireLit)) }
310
311 pub fn is_portal(&self) -> bool {
312 matches!(
313 self,
314 Body::Object(object::Body::Portal | object::Body::PortalActive)
315 )
316 }
317
318 pub fn bleeds(&self) -> bool {
319 !matches!(
320 self,
321 Body::Object(_) | Body::Ship(_) | Body::Item(_) | Body::Golem(_)
322 )
323 }
324
325 pub fn stride_length(&self) -> f32 {
328 if let Body::Humanoid(body) = self {
329 body.scaler() * 3.75
330 } else {
331 let dims = self.dimensions();
333 0.65 + (dims.y + dims.z) * 0.6
334 }
335 }
336
337 pub fn scale(&self) -> Scale {
338 let s = match self {
339 Body::BirdMedium(bird_medium) => match bird_medium.species {
340 bird_medium::Species::Bat | bird_medium::Species::VampireBat => 0.5,
341 _ => 1.0,
342 },
343 _ => 1.0,
344 };
345 Scale(s)
346 }
347
348 pub fn density(&self) -> Density {
351 let d = match self {
352 Body::BirdMedium(_) => 700.0,
354 Body::BirdLarge(_) => 2_200.0,
355
356 Body::Dragon(_) => 5_000.0,
357
358 Body::Golem(_) => WATER_DENSITY * 2.5,
359 Body::Humanoid(_) => HUMAN_DENSITY,
360 Body::Ship(ship) => ship.density().0,
361 Body::Object(object) => object.density().0,
362 Body::Item(item) => item.density().0,
363 _ => HUMAN_DENSITY,
364 };
365 Density(d)
366 }
367
368 pub fn mass(&self) -> Mass {
372 let m = match self {
373 Body::BipedLarge(body) => match body.species {
374 biped_large::Species::Slysaurok => 400.0,
375 biped_large::Species::Occultsaurok => 400.0,
376 biped_large::Species::Mightysaurok => 400.0,
377 biped_large::Species::Mindflayer => 420.0,
378 biped_large::Species::Minotaur => 500.0,
379 biped_large::Species::Cavetroll => 600.0,
380 biped_large::Species::Mountaintroll => 600.0,
381 biped_large::Species::Swamptroll => 600.0,
382 biped_large::Species::Gigasfrost => 400.0,
383 biped_large::Species::AdletElder => 350.0,
384 biped_large::Species::HaniwaGeneral => 360.0,
385 biped_large::Species::TerracottaBesieger
386 | biped_large::Species::TerracottaDemolisher
387 | biped_large::Species::TerracottaPunisher
388 | biped_large::Species::TerracottaPursuer
389 | biped_large::Species::Cursekeeper => 380.0,
390 biped_large::Species::Forgemaster => 1600.0,
391 _ => 400.0,
392 },
393 Body::BipedSmall(body) => match body.species {
394 biped_small::Species::IronDwarf => 1000.0,
395 biped_small::Species::Flamekeeper => 1000.0,
396 biped_small::Species::Boreal => 270.0,
397 _ => 50.0,
398 },
399 Body::BirdMedium(body) => match body.species {
401 bird_medium::Species::SnowyOwl => 3.0,
402 bird_medium::Species::HornedOwl => 3.0,
403 bird_medium::Species::Duck => 3.5,
404 bird_medium::Species::Cockatiel => 2.0,
405 bird_medium::Species::Chicken => 2.5, bird_medium::Species::Bat => 1.5,
407 bird_medium::Species::Penguin => 10.0,
408 bird_medium::Species::Eagle => 7.0, bird_medium::Species::Goose => 3.5, bird_medium::Species::Parrot => 1.0,
411 bird_medium::Species::Peacock => 6.0,
412 bird_medium::Species::Crow => 3.0,
413 bird_medium::Species::Dodo => 4.0,
414 bird_medium::Species::Parakeet => 1.0,
415 bird_medium::Species::Puffin => 2.0,
416 bird_medium::Species::Toucan => 4.5,
417 bird_medium::Species::BloodmoonBat => 1.5,
418 bird_medium::Species::VampireBat => 1.5,
419 },
420 Body::BirdLarge(_) => 250.0,
421 Body::Dragon(_) => 20_000.0,
422 Body::FishMedium(_) => 5.0,
423 Body::FishSmall(_) => 1.0,
424 Body::Golem(_) => 10_000.0,
425 Body::Humanoid(humanoid) => {
426 65.0 * humanoid.height() / 1.75f32
435 },
436 Body::Object(obj) => obj.mass().0,
437 Body::Item(item) => item.mass().0,
438 Body::QuadrupedLow(body) => match body.species {
439 quadruped_low::Species::Alligator => 360.0, quadruped_low::Species::Snaretongue => 280.0,
441 quadruped_low::Species::Asp => 300.0,
442 quadruped_low::Species::Crocodile => 360.0,
445 quadruped_low::Species::SeaCrocodile => 410.0,
446 quadruped_low::Species::Deadwood => 200.0,
447 quadruped_low::Species::Monitor => 200.0,
448 quadruped_low::Species::Pangolin => 300.0,
449 quadruped_low::Species::Salamander => 350.0,
450 quadruped_low::Species::Elbst => 350.0,
451 quadruped_low::Species::Tortoise => 300.0,
452 quadruped_low::Species::Lavadrake => 700.0,
453 quadruped_low::Species::Icedrake => 700.0,
454 quadruped_low::Species::Mossdrake => 700.0,
455 quadruped_low::Species::Rocksnapper => 450.0,
456 quadruped_low::Species::Rootsnapper => 450.0,
457 quadruped_low::Species::Reefsnapper => 450.0,
458 quadruped_low::Species::Maneater => 80.0,
459 quadruped_low::Species::Sandshark => 450.0,
460 quadruped_low::Species::Hakulaq => 400.0,
461 quadruped_low::Species::Dagon => 600.0,
462 quadruped_low::Species::Basilisk => 800.0,
463 quadruped_low::Species::Driggle => 55.0,
464 quadruped_low::Species::Hydra => 800.0,
465 },
466 Body::QuadrupedMedium(body) => match body.species {
467 quadruped_medium::Species::Bear => 500.0, quadruped_medium::Species::Cattle => 575.0, quadruped_medium::Species::Deer => 80.0,
470 quadruped_medium::Species::Donkey => 200.0,
471 quadruped_medium::Species::Highland => 200.0,
472 quadruped_medium::Species::Horse => 300.0, quadruped_medium::Species::Kelpie => 250.0,
474 quadruped_medium::Species::Lion => 170.0, quadruped_medium::Species::Panda => 200.0,
476 quadruped_medium::Species::Saber => 130.0,
477 quadruped_medium::Species::Yak => 200.0,
478 quadruped_medium::Species::Dreadhorn => 500.0,
479 quadruped_medium::Species::Mammoth => 1500.0,
480 quadruped_medium::Species::Catoblepas => 300.0,
481 _ => 200.0,
482 },
483 Body::QuadrupedSmall(body) => match body.species {
484 quadruped_small::Species::Axolotl => 1.0,
485 quadruped_small::Species::Batfox => 10.0,
486 quadruped_small::Species::Beaver => 10.0,
487 quadruped_small::Species::Boar => 80.0, quadruped_small::Species::Cat => 4.0, quadruped_small::Species::Dog => 30.0, quadruped_small::Species::Fox => 10.0,
491 quadruped_small::Species::Frog => 1.0,
492 quadruped_small::Species::Fungome => 10.0,
493 quadruped_small::Species::Gecko => 1.0,
494 quadruped_small::Species::Goat => 50.0,
495 quadruped_small::Species::Hare => 10.0,
496 quadruped_small::Species::Holladon => 70.0,
497 quadruped_small::Species::Hyena => 70.0, quadruped_small::Species::Jackalope => 10.0,
499 quadruped_small::Species::Pig => 20.0,
500 quadruped_small::Species::Porcupine => 5.0,
501 quadruped_small::Species::Quokka => 10.0,
502 quadruped_small::Species::Rabbit => 2.0,
503 quadruped_small::Species::Raccoon => 30.0,
504 quadruped_small::Species::Rat => 1.0,
505 quadruped_small::Species::Sheep => 50.0,
506 quadruped_small::Species::Skunk => 5.0,
507 quadruped_small::Species::Squirrel => 1.0,
508 quadruped_small::Species::Truffler => 70.0,
509 quadruped_small::Species::Turtle => 40.0,
510 quadruped_small::Species::Seal => 15.0,
511 quadruped_small::Species::TreantSapling => 80.0,
512 quadruped_small::Species::MossySnail => 5.0,
513 },
514 Body::Theropod(body) => match body.species {
515 theropod::Species::Archaeos => 8_000.0,
518 theropod::Species::Ntouka => 8_000.0,
519 theropod::Species::Odonto => 8_000.0,
520 theropod::Species::Dodarock => 700.0,
521 theropod::Species::Sandraptor => 500.0,
522 theropod::Species::Snowraptor => 500.0,
523 theropod::Species::Sunlizard => 500.0,
524 theropod::Species::Woodraptor => 500.0,
525 theropod::Species::Yale => 1_000.0,
526 theropod::Species::Axebeak => 300.0,
527 },
528 Body::Ship(ship) => ship.mass().0,
529 Body::Arthropod(_) => 200.0,
530 Body::Crustacean(body) => match body.species {
532 crustacean::Species::Crab | crustacean::Species::SoldierCrab => 50.0,
533 crustacean::Species::Karkatha => 1200.0,
534 },
535 Body::Plugin(body) => body.mass().0,
536 };
537 Mass(m)
538 }
539
540 pub fn dimensions(&self) -> Vec3<f32> {
544 match self {
545 Body::BipedLarge(body) => match body.species {
546 biped_large::Species::Cyclops => Vec3::new(5.6, 3.0, 8.0),
547 biped_large::Species::Dullahan => Vec3::new(4.6, 3.0, 5.5),
548 biped_large::Species::Mightysaurok => Vec3::new(4.0, 3.0, 3.4),
549 biped_large::Species::Mindflayer => Vec3::new(4.4, 3.0, 8.0),
550 biped_large::Species::Minotaur => Vec3::new(6.0, 3.0, 8.0),
551 biped_large::Species::Occultsaurok => Vec3::new(4.0, 3.0, 3.4),
552 biped_large::Species::Slysaurok => Vec3::new(4.0, 3.0, 3.4),
553 biped_large::Species::Werewolf => Vec3::new(4.0, 3.0, 3.5),
554 biped_large::Species::Harvester => Vec3::new(4.6, 3.0, 5.4),
555 biped_large::Species::Cultistwarlord => Vec3::new(3.0, 3.0, 4.5),
556 biped_large::Species::Cultistwarlock => Vec3::new(3.0, 3.0, 3.5),
557 biped_large::Species::Huskbrute => Vec3::new(4.6, 3.0, 5.0),
558 biped_large::Species::Tursus => Vec3::new(4.0, 3.0, 4.0),
559 biped_large::Species::Gigasfrost => Vec3::new(6.0, 3.0, 8.0),
560 biped_large::Species::AdletElder => Vec3::new(3.5, 3.0, 5.0),
561 biped_large::Species::SeaBishop => Vec3::new(3.7, 2.5, 4.2),
562 biped_large::Species::HaniwaGeneral => Vec3::new(3.3, 2.3, 3.8),
563 biped_large::Species::TerracottaBesieger => Vec3::new(3.8, 3.0, 5.0),
564 biped_large::Species::TerracottaDemolisher => Vec3::new(3.3, 2.5, 3.8),
565 biped_large::Species::TerracottaPunisher => Vec3::new(3.3, 2.5, 3.8),
566 biped_large::Species::TerracottaPursuer => Vec3::new(3.3, 2.5, 3.8),
567 biped_large::Species::Cursekeeper => Vec3::new(3.8, 3.0, 5.0),
568 biped_large::Species::Forgemaster => Vec3::new(6.5, 5.0, 8.0),
569 biped_large::Species::Strigoi => Vec3::new(3.8, 3.0, 5.0),
570 biped_large::Species::Executioner => Vec3::new(2.8, 2.8, 4.7),
571 _ => Vec3::new(4.6, 3.0, 6.0),
572 },
573 Body::BipedSmall(body) => match body.species {
574 biped_small::Species::Gnarling => Vec3::new(1.0, 0.75, 1.4),
575 biped_small::Species::Haniwa => Vec3::new(1.3, 1.0, 2.2),
576 biped_small::Species::Adlet => Vec3::new(1.3, 1.0, 2.0),
577 biped_small::Species::Sahagin => Vec3::new(1.3, 2.0, 1.7),
578 biped_small::Species::Myrmidon => Vec3::new(1.3, 1.0, 2.2),
579 biped_small::Species::Husk => Vec3::new(1.7, 0.7, 2.7),
580 biped_small::Species::Boreal => Vec3::new(2.6, 2.0, 4.6),
581 biped_small::Species::Bushly => Vec3::new(1.2, 1.3, 1.6),
582 biped_small::Species::Cactid => Vec3::new(1.0, 0.75, 1.4),
583 biped_small::Species::Irrwurz => Vec3::new(1.5, 1.5, 2.0),
584 biped_small::Species::IronDwarf => Vec3::new(1.3, 2.0, 2.5),
585 biped_small::Species::ShamanicSpirit => Vec3::new(1.3, 2.0, 2.3),
586 biped_small::Species::Jiangshi => Vec3::new(1.3, 1.8, 2.5),
587 biped_small::Species::Flamekeeper => Vec3::new(1.5, 1.5, 2.5),
588 biped_small::Species::TreasureEgg => Vec3::new(1.1, 1.1, 1.4),
589 biped_small::Species::GnarlingChieftain => Vec3::new(1.0, 0.75, 1.4),
590 biped_small::Species::BloodmoonHeiress => Vec3::new(3.5, 3.5, 5.5),
591 biped_small::Species::Bloodservant => Vec3::new(1.3, 1.8, 2.5),
592 biped_small::Species::Harlequin => Vec3::new(1.3, 2.0, 2.5),
593 biped_small::Species::GoblinThug => Vec3::new(1.3, 1.0, 1.6),
594 biped_small::Species::GoblinChucker => Vec3::new(1.3, 1.0, 1.6),
595 biped_small::Species::GoblinRuffian => Vec3::new(1.3, 1.0, 1.6),
596 biped_small::Species::GreenLegoom => Vec3::new(1.4, 1.2, 1.8),
597 biped_small::Species::OchreLegoom => Vec3::new(1.4, 1.2, 1.8),
598 biped_small::Species::PurpleLegoom => Vec3::new(1.4, 1.2, 1.8),
599 biped_small::Species::RedLegoom => Vec3::new(1.4, 1.2, 1.8),
600 _ => Vec3::new(1.0, 0.75, 1.4),
601 },
602 Body::BirdLarge(body) => match body.species {
603 bird_large::Species::Cockatrice => Vec3::new(2.5, 5.5, 3.5),
604 bird_large::Species::Roc => Vec3::new(2.2, 7.5, 4.0),
605 bird_large::Species::FlameWyvern
606 | bird_large::Species::FrostWyvern
607 | bird_large::Species::CloudWyvern
608 | bird_large::Species::SeaWyvern
609 | bird_large::Species::WealdWyvern => Vec3::new(2.5, 9.0, 4.5),
610 _ => Vec3::new(2.0, 6.0, 4.4),
611 },
612 Body::Dragon(_) => Vec3::new(16.0, 10.0, 16.0),
613 Body::FishMedium(_) => Vec3::new(0.5, 2.0, 0.8),
614 Body::FishSmall(_) => Vec3::new(0.3, 1.2, 0.6),
615 Body::Golem(body) => match body.species {
616 golem::Species::CoralGolem => Vec3::new(3.0, 5.0, 4.0),
617 golem::Species::ClayGolem => Vec3::new(6.8, 3.5, 7.5),
618 golem::Species::AncientEffigy => Vec3::new(2.5, 2.5, 3.8),
619 golem::Species::Mogwai => Vec3::new(2.5, 2.5, 3.8),
620 _ => Vec3::new(5.0, 4.5, 7.5),
621 },
622 Body::Humanoid(humanoid) => {
623 let height = humanoid.height();
624 Vec3::new(height / 1.3, 1.75 / 2.0, height)
625 },
626 Body::Object(object) => object.dimensions(),
627 Body::Item(item) => item.dimensions(),
628 Body::QuadrupedMedium(body) => match body.species {
629 quadruped_medium::Species::Akhlut => Vec3::new(2.5, 7.0, 3.0),
630 quadruped_medium::Species::Barghest => Vec3::new(2.0, 4.4, 2.7),
631 quadruped_medium::Species::Bear => Vec3::new(2.0, 3.8, 3.0),
632 quadruped_medium::Species::Catoblepas => Vec3::new(2.0, 4.0, 2.3),
633 quadruped_medium::Species::Cattle => Vec3::new(2.0, 3.6, 2.4),
634 quadruped_medium::Species::Deer => Vec3::new(2.0, 3.0, 2.2),
635 quadruped_medium::Species::Dreadhorn => Vec3::new(3.5, 7.0, 4.0),
636 quadruped_medium::Species::Frostfang => Vec3::new(1.5, 3.0, 1.5),
637 quadruped_medium::Species::Grolgar => Vec3::new(2.0, 4.0, 2.0),
638 quadruped_medium::Species::Highland => Vec3::new(2.0, 3.6, 2.4),
639 quadruped_medium::Species::Horse => Vec3::new(1.6, 3.0, 2.4),
640 quadruped_medium::Species::Lion => Vec3::new(2.0, 3.3, 2.0),
641 quadruped_medium::Species::Moose => Vec3::new(2.0, 4.0, 2.5),
642 quadruped_medium::Species::Bristleback => Vec3::new(2.0, 3.0, 2.0),
643 quadruped_medium::Species::Roshwalr => Vec3::new(3.4, 5.2, 3.7),
644 quadruped_medium::Species::Saber => Vec3::new(2.0, 3.0, 2.0),
645 quadruped_medium::Species::Tarasque => Vec3::new(2.0, 4.0, 2.6),
646 quadruped_medium::Species::Yak => Vec3::new(2.0, 3.6, 3.0),
647 quadruped_medium::Species::Mammoth => Vec3::new(7.5, 11.5, 8.0),
648 quadruped_medium::Species::Ngoubou => Vec3::new(2.0, 3.2, 2.4),
649 quadruped_medium::Species::Llama => Vec3::new(2.0, 2.5, 2.6),
650 quadruped_medium::Species::ClaySteed => Vec3::new(2.2, 4.8, 4.0),
651 quadruped_medium::Species::Alpaca => Vec3::new(2.0, 2.0, 2.0),
652 quadruped_medium::Species::Camel => Vec3::new(2.0, 4.0, 3.5),
653 quadruped_medium::Species::Wolf => Vec3::new(1.25, 3.0, 1.8),
654 _ => Vec3::new(2.0, 3.0, 2.0),
656 },
657 Body::QuadrupedSmall(body) => match body.species {
658 quadruped_small::Species::Batfox => Vec3::new(1.4, 1.7, 1.3),
659 quadruped_small::Species::Holladon => Vec3::new(1.3, 1.9, 1.5),
660 quadruped_small::Species::Hyena => Vec3::new(1.2, 1.4, 1.3),
661 quadruped_small::Species::Truffler => Vec3::new(1.2, 1.8, 2.2),
662 quadruped_small::Species::MossySnail => Vec3::new(1.4, 1.4, 1.2),
663 _ => Vec3::new(1.2, 1.2, 1.0),
664 },
665 Body::QuadrupedLow(body) => match body.species {
666 quadruped_low::Species::Asp => Vec3::new(2.0, 3.0, 1.7),
667 quadruped_low::Species::Crocodile => Vec3::new(1.0, 2.8, 1.3),
668 quadruped_low::Species::SeaCrocodile => Vec3::new(1.2, 4.5, 1.3),
669 quadruped_low::Species::Deadwood => Vec3::new(1.3, 1.3, 1.4),
670 quadruped_low::Species::Hakulaq => Vec3::new(1.8, 3.0, 2.0),
671 quadruped_low::Species::Dagon => Vec3::new(3.0, 6.0, 2.0),
672 quadruped_low::Species::Icedrake => Vec3::new(2.0, 5.5, 2.5),
673 quadruped_low::Species::Lavadrake => Vec3::new(2.0, 5.5, 2.5),
674 quadruped_low::Species::Mossdrake => Vec3::new(2.0, 5.5, 2.5),
675 quadruped_low::Species::Maneater => Vec3::new(2.0, 3.7, 4.0),
676 quadruped_low::Species::Monitor => Vec3::new(1.4, 3.2, 1.3),
677 quadruped_low::Species::Pangolin => Vec3::new(1.0, 2.6, 1.1),
678 quadruped_low::Species::Rocksnapper => Vec3::new(2.5, 3.5, 2.9),
679 quadruped_low::Species::Rootsnapper => Vec3::new(2.5, 3.5, 2.9),
680 quadruped_low::Species::Reefsnapper => Vec3::new(2.5, 3.5, 2.9),
681 quadruped_low::Species::Sandshark => Vec3::new(2.1, 4.3, 1.7),
682 quadruped_low::Species::Basilisk => Vec3::new(2.7, 6.0, 2.9),
683 quadruped_low::Species::Salamander => Vec3::new(1.7, 4.0, 1.3),
684 quadruped_low::Species::Elbst => Vec3::new(1.7, 4.0, 1.3),
685 quadruped_low::Species::Tortoise => Vec3::new(1.7, 2.7, 1.5),
686 quadruped_low::Species::Driggle => Vec3::new(1.6, 2.7, 1.0),
687 quadruped_low::Species::Snaretongue => Vec3::new(2.0, 2.8, 1.6),
688 quadruped_low::Species::Hydra => Vec3::new(3.0, 5.0, 2.8),
689 _ => Vec3::new(1.0, 1.6, 1.3),
690 },
691 Body::Ship(ship) => ship.dimensions(),
692 Body::Theropod(body) => match body.species {
693 theropod::Species::Archaeos => Vec3::new(4.5, 8.5, 8.0),
694 theropod::Species::Ntouka => Vec3::new(4.5, 9.0, 6.6),
695 theropod::Species::Odonto => Vec3::new(4.5, 8.0, 6.6),
696 theropod::Species::Dodarock => Vec3::new(2.0, 3.0, 2.6),
697 theropod::Species::Sandraptor => Vec3::new(2.0, 3.0, 2.6),
698 theropod::Species::Snowraptor => Vec3::new(2.0, 3.0, 2.6),
699 theropod::Species::Sunlizard => Vec3::new(2.0, 3.6, 2.5),
700 theropod::Species::Woodraptor => Vec3::new(2.0, 3.0, 2.6),
701 theropod::Species::Yale => Vec3::new(2.0, 3.2, 4.0),
702 theropod::Species::Axebeak => Vec3::new(2.0, 3.6, 3.0),
703 },
704 Body::Arthropod(body) => match body.species {
705 arthropod::Species::Tarantula => Vec3::new(4.0, 4.0, 1.8),
706 arthropod::Species::Blackwidow => Vec3::new(4.0, 4.0, 2.0),
707 arthropod::Species::Antlion => Vec3::new(4.0, 4.0, 2.2),
708 arthropod::Species::Hornbeetle => Vec3::new(3.2, 3.2, 1.3),
709 arthropod::Species::Leafbeetle => Vec3::new(2.4, 2.8, 1.2),
710 arthropod::Species::Stagbeetle => Vec3::new(3.2, 3.2, 1.3),
711 arthropod::Species::Weevil => Vec3::new(2.2, 2.4, 1.1),
712 arthropod::Species::Cavespider => Vec3::new(4.0, 4.0, 1.4),
713 arthropod::Species::Moltencrawler => Vec3::new(3.2, 4.0, 1.5),
714 arthropod::Species::Mosscrawler => Vec3::new(3.2, 4.0, 1.4),
715 arthropod::Species::Sandcrawler => Vec3::new(3.2, 4.0, 1.4),
716 arthropod::Species::Dagonite => Vec3::new(3.2, 4.7, 1.4),
717 arthropod::Species::Emberfly => Vec3::new(1.3, 1.5, 0.9),
718 },
719 Body::BirdMedium(body) => match body.species {
720 bird_medium::Species::SnowyOwl => Vec3::new(1.2, 1.2, 0.9),
721 bird_medium::Species::HornedOwl => Vec3::new(1.2, 1.2, 0.9),
722 bird_medium::Species::Duck => Vec3::new(0.8, 1.3, 0.8),
723 bird_medium::Species::Cockatiel => Vec3::new(0.8, 1.0, 0.7),
724 bird_medium::Species::Chicken => Vec3::new(1.2, 1.5, 0.9),
725 bird_medium::Species::Bat => Vec3::new(2.0, 1.8, 1.3),
726 bird_medium::Species::Penguin => Vec3::new(1.0, 1.0, 1.2),
727 bird_medium::Species::Goose => Vec3::new(1.5, 1.5, 1.1),
728 bird_medium::Species::Peacock => Vec3::new(1.6, 1.8, 1.4),
729 bird_medium::Species::Eagle => Vec3::new(1.5, 2.2, 1.0),
730 bird_medium::Species::Parrot => Vec3::new(1.2, 1.5, 1.1),
731 bird_medium::Species::Crow => Vec3::new(1.0, 1.2, 0.8),
732 bird_medium::Species::Dodo => Vec3::new(1.2, 1.8, 1.1),
733 bird_medium::Species::Parakeet => Vec3::new(0.8, 0.9, 0.7),
734 bird_medium::Species::Puffin => Vec3::new(1.0, 1.0, 1.0),
735 bird_medium::Species::Toucan => Vec3::new(2.1, 1.1, 1.2),
736 bird_medium::Species::BloodmoonBat => Vec3::new(3.5, 3.5, 2.5),
737 bird_medium::Species::VampireBat => Vec3::new(2.0, 1.8, 1.3),
738 },
739 Body::Crustacean(body) => match body.species {
740 crustacean::Species::Crab => Vec3::new(1.2, 1.2, 0.7),
741 crustacean::Species::SoldierCrab => Vec3::new(1.2, 1.2, 1.0),
742 crustacean::Species::Karkatha => Vec3::new(10.0, 10.0, 7.5),
743 },
744 Body::Plugin(body) => body.dimensions(),
745 }
746 }
747
748 pub fn max_radius(&self) -> f32 {
752 let dim = self.dimensions();
753 let (x, y) = (dim.x, dim.y);
754
755 x.max(y) / 2.0
756 }
757
758 pub fn front_radius(&self) -> f32 { self.dimensions().y / 2.0 }
759
760 pub fn min_radius(&self) -> f32 {
761 let (_p0, _p1, radius) = self.sausage();
762
763 radius
764 }
765
766 pub fn sausage(&self) -> (Vec2<f32>, Vec2<f32>, f32) {
771 let dim = self.dimensions();
783 let (width, length) = (dim.x, dim.y);
785
786 if length > width {
787 let radius = width / 2.0;
789
790 let a = length - 2.0 * radius;
791
792 let p0 = Vec2::new(0.0, -a / 2.0);
793 let p1 = Vec2::new(0.0, a / 2.0);
794
795 (p0, p1, radius)
796 } else {
797 let radius = length / 2.0;
799
800 let a = width - 2.0 * radius;
801
802 let p0 = Vec2::new(-a / 2.0, 0.0);
803 let p1 = Vec2::new(a / 2.0, 0.0);
804
805 (p0, p1, radius)
806 }
807 }
808
809 pub fn collider(&self) -> Collider {
811 if let Body::Ship(ship) = self {
812 ship.make_collider()
813 } else {
814 let (p0, p1, radius) = self.sausage();
815
816 Collider::CapsulePrism {
817 p0,
818 p1,
819 radius,
820 z_min: 0.0,
821 z_max: self.height(),
822 }
823 }
824 }
825
826 pub fn spacing_radius(&self) -> f32 {
831 self.max_radius()
832 + match self {
833 Body::QuadrupedSmall(body) => match body.species {
834 quadruped_small::Species::Rat => 0.0,
835 _ => 2.0,
836 },
837 Body::QuadrupedLow(body) => match body.species {
838 quadruped_low::Species::Hakulaq => 0.0,
839 _ => 2.0,
840 },
841 Body::BipedSmall(body) => match body.species {
842 biped_small::Species::Husk => 3.0,
843 _ => 2.0,
844 },
845 _ => 2.0,
846 }
847 }
848
849 pub fn height(&self) -> f32 { self.dimensions().z }
851
852 pub fn base_energy(&self) -> u16 {
853 match self {
854 Body::BipedLarge(biped_large) => match biped_large.species {
855 biped_large::Species::Dullahan => 400,
856 biped_large::Species::Cultistwarlord | biped_large::Species::Cultistwarlock => 240,
857 _ => 300,
858 },
859 Body::BirdLarge(body) => match body.species {
860 bird_large::Species::Cockatrice => 400,
861 bird_large::Species::Phoenix => 600,
862 bird_large::Species::Roc => 500,
863 bird_large::Species::FlameWyvern => 600,
864 bird_large::Species::CloudWyvern => 600,
865 bird_large::Species::FrostWyvern => 600,
866 bird_large::Species::SeaWyvern => 600,
867 bird_large::Species::WealdWyvern => 600,
868 },
869 Body::Humanoid(_) => 100,
870 _ => 100,
871 }
872 }
873
874 pub fn has_death_protection(&self) -> bool { matches!(self, Body::Humanoid(_)) }
877
878 pub fn base_health(&self) -> u16 {
879 match self {
880 Body::Humanoid(_) => 100,
881 Body::QuadrupedSmall(quadruped_small) => match quadruped_small.species {
882 quadruped_small::Species::Batfox => 40,
884 quadruped_small::Species::Boar => 55,
885 quadruped_small::Species::Fox => 25,
886 quadruped_small::Species::Goat => 30,
887 quadruped_small::Species::Hare => 20,
888 quadruped_small::Species::Holladon => 25,
889 quadruped_small::Species::Jackalope => 30,
890 quadruped_small::Species::MossySnail => 15,
891 quadruped_small::Species::Porcupine => 25,
892 quadruped_small::Species::Sheep => 30,
893 quadruped_small::Species::TreantSapling => 20,
894 quadruped_small::Species::Truffler => 70,
895 quadruped_small::Species::Hyena => 85,
897 quadruped_small::Species::Beaver => 20,
899 quadruped_small::Species::Cat => 25,
900 quadruped_small::Species::Dog => 30,
901 quadruped_small::Species::Fungome => 15,
902 quadruped_small::Species::Pig => 25,
903 quadruped_small::Species::Quokka => 15,
904 quadruped_small::Species::Rabbit => 15,
905 quadruped_small::Species::Raccoon => 20,
906 quadruped_small::Species::Rat => 10,
907 quadruped_small::Species::Seal => 20,
908 quadruped_small::Species::Skunk => 20,
909 quadruped_small::Species::Turtle => 10,
910 _ => 5,
911 },
912 Body::QuadrupedMedium(quadruped_medium) => match quadruped_medium.species {
913 quadruped_medium::Species::Alpaca => 55,
915 quadruped_medium::Species::Antelope => 70,
916 quadruped_medium::Species::Darkhound => 80,
917 quadruped_medium::Species::Camel => 100,
918 quadruped_medium::Species::Cattle => 90,
919 quadruped_medium::Species::Deer => 55,
920 quadruped_medium::Species::Donkey => 65,
921 quadruped_medium::Species::Horse => 75,
922 quadruped_medium::Species::Llama => 65,
923 quadruped_medium::Species::Mouflon => 75,
924 quadruped_medium::Species::Zebra => 90,
925 quadruped_medium::Species::Barghest => 120,
927 quadruped_medium::Species::Bear => 240,
928 quadruped_medium::Species::Bristleback => 175,
929 quadruped_medium::Species::Bonerattler => 100,
930 quadruped_medium::Species::Frostfang => 185,
931 quadruped_medium::Species::Highland => 205,
932 quadruped_medium::Species::Kelpie => 150,
933 quadruped_medium::Species::Lion => 175,
934 quadruped_medium::Species::Moose => 265,
935 quadruped_medium::Species::Panda => 215,
936 quadruped_medium::Species::Saber => 210,
937 quadruped_medium::Species::Snowleopard => 175,
938 quadruped_medium::Species::Tiger => 205,
939 quadruped_medium::Species::Tuskram => 175,
940 quadruped_medium::Species::Wolf => 110,
941 quadruped_medium::Species::Yak => 215,
942 quadruped_medium::Species::Akhlut => 720,
944 quadruped_medium::Species::Catoblepas => 720,
945 quadruped_medium::Species::ClaySteed => 400,
946 quadruped_medium::Species::Dreadhorn => 690,
947 quadruped_medium::Species::Grolgar => 450,
948 quadruped_medium::Species::Hirdrasil => 480,
949 quadruped_medium::Species::Mammoth => 880,
950 quadruped_medium::Species::Ngoubou => 590,
951 quadruped_medium::Species::Roshwalr => 640,
952 quadruped_medium::Species::Tarasque => 370,
953 },
954 Body::FishMedium(fish_medium) => match fish_medium.species {
955 fish_medium::Species::Marlin => 50,
957 fish_medium::Species::Icepike => 90,
958 },
959 Body::Dragon(_) => 500,
960 Body::BirdLarge(bird_large) => match bird_large.species {
961 bird_large::Species::Cockatrice => 540,
963 bird_large::Species::Roc => 450,
964 bird_large::Species::FlameWyvern
966 | bird_large::Species::CloudWyvern
967 | bird_large::Species::FrostWyvern
968 | bird_large::Species::SeaWyvern
969 | bird_large::Species::WealdWyvern => 1000,
970 bird_large::Species::Phoenix => 2000,
971 },
972 Body::BirdMedium(bird_medium) => match bird_medium.species {
973 bird_medium::Species::Bat => 10,
975 bird_medium::Species::Chicken => 10,
976 bird_medium::Species::Cockatiel => 10,
977 bird_medium::Species::Dodo => 20,
978 bird_medium::Species::Duck => 10,
979 bird_medium::Species::Parakeet => 10,
980 bird_medium::Species::Peacock => 20,
981 bird_medium::Species::Penguin => 10,
982 bird_medium::Species::Puffin => 20,
983 bird_medium::Species::Crow => 15,
985 bird_medium::Species::Eagle => 35,
986 bird_medium::Species::Goose => 25,
987 bird_medium::Species::HornedOwl => 35,
988 bird_medium::Species::Parrot => 15,
989 bird_medium::Species::SnowyOwl => 35,
990 bird_medium::Species::Toucan => 15,
991 bird_medium::Species::VampireBat => 100,
993 bird_medium::Species::BloodmoonBat => 1200,
994 },
995 Body::FishSmall(fish_small) => match fish_small.species {
996 fish_small::Species::Clownfish => 5,
998 fish_small::Species::Piranha => 10,
1000 },
1001 Body::BipedLarge(biped_large) => match biped_large.species {
1002 biped_large::Species::Ogre => 320,
1003 biped_large::Species::Cyclops => 1000,
1004 biped_large::Species::Wendigo => 280,
1005 biped_large::Species::Cavetroll => 240,
1006 biped_large::Species::Mountaintroll => 240,
1007 biped_large::Species::Swamptroll => 240,
1008 biped_large::Species::Dullahan => 600,
1009 biped_large::Species::Mindflayer => 2000,
1010 biped_large::Species::Tidalwarrior => 1600,
1011 biped_large::Species::Yeti => 1800,
1012 biped_large::Species::Minotaur => 3000,
1013 biped_large::Species::Harvester => 1300,
1014 biped_large::Species::Blueoni => 240,
1015 biped_large::Species::Redoni => 240,
1016 biped_large::Species::Huskbrute => 800,
1017 biped_large::Species::Cultistwarlord => 200,
1018 biped_large::Species::Cultistwarlock => 200,
1019 biped_large::Species::Gigasfrost => 30000,
1020 biped_large::Species::AdletElder => 1500,
1021 biped_large::Species::Tursus => 300,
1022 biped_large::Species::SeaBishop => 550,
1023 biped_large::Species::HaniwaGeneral => 600,
1024 biped_large::Species::TerracottaBesieger
1025 | biped_large::Species::TerracottaDemolisher
1026 | biped_large::Species::TerracottaPunisher
1027 | biped_large::Species::TerracottaPursuer => 300,
1028 biped_large::Species::Cursekeeper => 3000,
1029 biped_large::Species::Forgemaster => 10000,
1030 biped_large::Species::Strigoi => 800,
1031 biped_large::Species::Executioner => 800,
1032 _ => 120,
1033 },
1034 Body::BipedSmall(biped_small) => match biped_small.species {
1035 biped_small::Species::GoblinThug
1036 | biped_small::Species::GoblinChucker
1037 | biped_small::Species::GoblinRuffian => 30,
1038 biped_small::Species::GreenLegoom
1039 | biped_small::Species::OchreLegoom
1040 | biped_small::Species::PurpleLegoom
1041 | biped_small::Species::RedLegoom => 40,
1042 biped_small::Species::Cactid => 50,
1043 biped_small::Species::Gnarling => 50,
1044 biped_small::Species::GnarlingChieftain => 150,
1045 biped_small::Species::Mandragora => 65,
1046 biped_small::Species::Adlet => 65,
1047 biped_small::Species::Sahagin => 85,
1048 biped_small::Species::Haniwa => 100,
1049 biped_small::Species::Myrmidon => 100,
1050 biped_small::Species::Husk => 50,
1051 biped_small::Species::Boreal => 800,
1052 biped_small::Species::IronDwarf => 250,
1053 biped_small::Species::Irrwurz => 100,
1054 biped_small::Species::ShamanicSpirit => 240,
1055 biped_small::Species::Jiangshi => 250,
1056 biped_small::Species::Flamekeeper => 2000,
1057 biped_small::Species::BloodmoonHeiress => 2000,
1058 biped_small::Species::Bloodservant => 300,
1059 biped_small::Species::Harlequin => 500,
1060 _ => 60,
1061 },
1062 Body::Object(object) => match object {
1063 object::Body::TrainingDummy => 60000,
1064 object::Body::Crossbow => 80,
1065 object::Body::Flamethrower => 80,
1066 object::Body::Lavathrower => 80,
1067 object::Body::BarrelOrgan => 500,
1068 object::Body::HaniwaSentry => 60,
1069 object::Body::SeaLantern => 100,
1070 object::Body::TerracottaStatue => 600,
1071 object::Body::GnarlingTotemGreen => 15,
1072 object::Body::GnarlingTotemRed | object::Body::GnarlingTotemWhite => 15,
1073 _ => 1000,
1074 },
1075 Body::Item(_) => 1000,
1076 Body::Golem(golem) => match golem.species {
1077 golem::Species::WoodGolem => 120,
1078 golem::Species::ClayGolem => 350,
1079 golem::Species::Gravewarden => 1000,
1080 golem::Species::CoralGolem => 550,
1081 golem::Species::AncientEffigy => 250,
1082 golem::Species::Mogwai => 500,
1083 golem::Species::IronGolem => 2500,
1084 _ => 1000,
1085 },
1086 Body::Theropod(theropod) => match theropod.species {
1087 theropod::Species::Dodarock => 20,
1089 theropod::Species::Axebeak => 275,
1091 theropod::Species::Sandraptor => 110,
1092 theropod::Species::Snowraptor => 110,
1093 theropod::Species::Sunlizard => 110,
1094 theropod::Species::Woodraptor => 110,
1095 theropod::Species::Yale => 610,
1097 theropod::Species::Archaeos => 880,
1099 theropod::Species::Ntouka => 880,
1100 theropod::Species::Odonto => 1320,
1101 },
1102 Body::QuadrupedLow(quadruped_low) => match quadruped_low.species {
1103 quadruped_low::Species::Driggle => 50,
1105 quadruped_low::Species::Pangolin => 20,
1106 quadruped_low::Species::Tortoise => 45,
1107 quadruped_low::Species::Alligator => 130,
1109 quadruped_low::Species::Asp => 175,
1110 quadruped_low::Species::Crocodile => 145,
1111 quadruped_low::Species::Deadwood => 85,
1112 quadruped_low::Species::Elbst => 145,
1113 quadruped_low::Species::Hakulaq => 155,
1114 quadruped_low::Species::Monitor => 95,
1115 quadruped_low::Species::Salamander => 210,
1116 quadruped_low::Species::SeaCrocodile => 180,
1117 quadruped_low::Species::Dagon => 1200,
1119 quadruped_low::Species::Icedrake => 340,
1120 quadruped_low::Species::Lavadrake => 340,
1121 quadruped_low::Species::Maneater => 510,
1122 quadruped_low::Species::Mossdrake => 340,
1123 quadruped_low::Species::Rocksnapper => 400,
1124 quadruped_low::Species::Reefsnapper => 400,
1125 quadruped_low::Species::Rootsnapper => 400,
1126 quadruped_low::Species::Sandshark => 540,
1127 quadruped_low::Species::Hydra => 1000,
1128 quadruped_low::Species::Basilisk => 660,
1130 quadruped_low::Species::Snaretongue => 1500,
1131 },
1132 Body::Arthropod(arthropod) => match arthropod.species {
1133 arthropod::Species::Dagonite => 70,
1135 arthropod::Species::Emberfly => 20,
1136 arthropod::Species::Leafbeetle => 40,
1137 arthropod::Species::Weevil => 40,
1138 arthropod::Species::Cavespider => 170,
1140 arthropod::Species::Hornbeetle => 170,
1141 arthropod::Species::Moltencrawler => 145,
1142 arthropod::Species::Mosscrawler => 145,
1143 arthropod::Species::Sandcrawler => 145,
1144 arthropod::Species::Stagbeetle => 170,
1145 arthropod::Species::Tarantula => 155,
1146 arthropod::Species::Antlion => 480,
1148 arthropod::Species::Blackwidow => 370,
1149 },
1150 Body::Ship(_) => 1000,
1151 Body::Crustacean(crustacean) => match crustacean.species {
1152 crustacean::Species::Crab => 40,
1154 crustacean::Species::SoldierCrab => 50,
1156 crustacean::Species::Karkatha => 2000,
1157 },
1158 Body::Plugin(body) => body.base_health(),
1159 }
1160 }
1161
1162 pub fn flying_height(&self) -> f32 {
1163 match self {
1164 Body::BirdLarge(_) => 50.0,
1165 Body::BirdMedium(_) => 40.0,
1166 Body::Dragon(_) => 60.0,
1167 Body::Ship(ship) => ship.flying_height(),
1168 _ => 0.0,
1169 }
1170 }
1171
1172 pub fn immune_to(&self, buff: BuffKind) -> bool {
1173 match buff {
1174 BuffKind::Bleeding => match self {
1175 Body::Golem(_) | Body::Ship(_) => true,
1176 Body::Object(object) => !matches!(object, object::Body::TrainingDummy),
1177 Body::BipedSmall(b) => matches!(
1178 b.species,
1179 biped_small::Species::Husk
1180 | biped_small::Species::Boreal
1181 | biped_small::Species::IronDwarf
1182 | biped_small::Species::Haniwa
1183 | biped_small::Species::ShamanicSpirit
1184 | biped_small::Species::Jiangshi
1185 ),
1186 Body::BipedLarge(b) => matches!(
1187 b.species,
1188 biped_large::Species::Huskbrute
1189 | biped_large::Species::Gigasfrost
1190 | biped_large::Species::Dullahan
1191 | biped_large::Species::HaniwaGeneral
1192 | biped_large::Species::TerracottaBesieger
1193 | biped_large::Species::TerracottaDemolisher
1194 | biped_large::Species::TerracottaPunisher
1195 | biped_large::Species::TerracottaPursuer
1196 | biped_large::Species::Cursekeeper
1197 ),
1198 Body::QuadrupedMedium(b) => {
1199 matches!(b.species, quadruped_medium::Species::ClaySteed)
1200 },
1201 _ => false,
1202 },
1203 BuffKind::Crippled => match self {
1204 Body::Golem(_) | Body::Ship(_) => true,
1205 Body::Object(object) => !matches!(object, object::Body::TrainingDummy),
1206 Body::BipedLarge(b) => matches!(
1207 b.species,
1208 biped_large::Species::Dullahan | biped_large::Species::HaniwaGeneral
1209 ),
1210 Body::BipedSmall(b) => matches!(b.species, biped_small::Species::Haniwa),
1211 Body::QuadrupedMedium(b) => {
1212 matches!(b.species, quadruped_medium::Species::ClaySteed)
1213 },
1214 _ => false,
1215 },
1216 BuffKind::Burning => match self {
1217 Body::Golem(g) => matches!(
1218 g.species,
1219 golem::Species::Gravewarden
1220 | golem::Species::AncientEffigy
1221 | golem::Species::IronGolem
1222 ),
1223 Body::BipedSmall(b) => matches!(
1224 b.species,
1225 biped_small::Species::Haniwa
1226 | biped_small::Species::Flamekeeper
1227 | biped_small::Species::IronDwarf
1228 ),
1229 Body::Object(object) => matches!(
1230 object,
1231 object::Body::HaniwaSentry
1232 | object::Body::Lavathrower
1233 | object::Body::Flamethrower
1234 | object::Body::TerracottaStatue
1235 ),
1236 Body::QuadrupedLow(q) => matches!(
1237 q.species,
1238 quadruped_low::Species::Lavadrake | quadruped_low::Species::Salamander
1239 ),
1240 Body::BirdLarge(b) => matches!(
1241 b.species,
1242 bird_large::Species::Phoenix
1243 | bird_large::Species::Cockatrice
1244 | bird_large::Species::FlameWyvern
1245 | bird_large::Species::CloudWyvern
1246 | bird_large::Species::FrostWyvern
1247 | bird_large::Species::SeaWyvern
1248 | bird_large::Species::WealdWyvern
1249 ),
1250 Body::Arthropod(b) => matches!(b.species, arthropod::Species::Moltencrawler),
1251 Body::BipedLarge(b) => matches!(
1252 b.species,
1253 biped_large::Species::Cyclops
1254 | biped_large::Species::Minotaur
1255 | biped_large::Species::Forgemaster
1256 ),
1257 _ => false,
1258 },
1259 BuffKind::Ensnared => match self {
1260 Body::BipedLarge(b) => matches!(b.species, biped_large::Species::Harvester),
1261 Body::Arthropod(_) => true,
1262 _ => false,
1263 },
1264 BuffKind::Regeneration => {
1265 matches!(
1266 self,
1267 Body::Object(
1268 object::Body::GnarlingTotemRed
1269 | object::Body::GnarlingTotemGreen
1270 | object::Body::GnarlingTotemWhite
1271 )
1272 )
1273 },
1274 BuffKind::Frozen => match self {
1275 Body::BipedLarge(b) => matches!(
1276 b.species,
1277 biped_large::Species::Yeti
1278 | biped_large::Species::Gigasfrost
1279 | biped_large::Species::Tursus
1280 ),
1281 Body::QuadrupedLow(q) => matches!(q.species, quadruped_low::Species::Icedrake),
1282 Body::BirdLarge(b) => matches!(b.species, bird_large::Species::FrostWyvern),
1283 Body::BipedSmall(b) => matches!(b.species, biped_small::Species::Boreal),
1284 Body::QuadrupedMedium(b) => matches!(
1285 b.species,
1286 quadruped_medium::Species::Roshwalr | quadruped_medium::Species::Frostfang
1287 ),
1288 _ => false,
1289 },
1290 BuffKind::ProtectingWard => matches!(self, Body::Object(object::Body::BarrelOrgan)),
1291 _ => false,
1292 }
1293 }
1294
1295 pub fn combat_multiplier(&self) -> f32 {
1299 match self {
1300 Body::Object(object) => match object {
1301 object::Body::BarrelOrgan | object::Body::ArrowTurret => 0.05,
1302 object::Body::TerracottaStatue => 1.5,
1303 _ => 0.0,
1304 },
1305 Body::Ship(_) => 0.0,
1306 Body::BipedLarge(b) => match b.species {
1307 biped_large::Species::Mindflayer => 4.35,
1308 biped_large::Species::Minotaur => 4.05,
1309 biped_large::Species::Tidalwarrior => 2.75,
1310 biped_large::Species::Yeti => 2.25,
1311 _ => 1.0,
1312 },
1313 Body::BipedSmall(b) => match b.species {
1314 biped_small::Species::IronDwarf => 2.0,
1315 biped_small::Species::Flamekeeper => 4.0,
1316 _ => 1.0,
1317 },
1318 Body::Golem(g) => match g.species {
1319 golem::Species::Gravewarden => 2.45,
1320 _ => 1.0,
1321 },
1322 Body::QuadrupedLow(b) => match b.species {
1323 quadruped_low::Species::Snaretongue => 2.0,
1324 _ => 1.0,
1325 },
1326 Body::QuadrupedSmall(b) => match b.species {
1327 quadruped_small::Species::Axolotl | quadruped_small::Species::Gecko => 0.6,
1328 _ => 1.0,
1329 },
1330 #[expect(unreachable_patterns)] Body::FishMedium(b) => match b.species {
1332 fish_medium::Species::Marlin | fish_medium::Species::Icepike => 0.6,
1333 _ => 1.0,
1334 },
1335 #[expect(unreachable_patterns)] Body::FishSmall(b) => match b.species {
1337 fish_small::Species::Clownfish | fish_small::Species::Piranha => 0.6,
1338 _ => 1.0,
1339 },
1340 Body::Crustacean(b) => match b.species {
1341 crustacean::Species::Crab | crustacean::Species::SoldierCrab => 0.6,
1342 _ => 1.0,
1343 },
1344 _ => 1.0,
1345 }
1346 }
1347
1348 pub fn base_poise(&self) -> u16 {
1349 match self {
1350 Body::Humanoid(_) => 100,
1351 Body::BipedLarge(biped_large) => match biped_large.species {
1352 biped_large::Species::Mindflayer => 777,
1353 biped_large::Species::Minotaur => 340,
1354 biped_large::Species::Forgemaster => 300,
1355 biped_large::Species::Gigasfrost => 990,
1356 _ => 300,
1357 },
1358 Body::BipedSmall(b) => match b.species {
1359 biped_small::Species::GnarlingChieftain => 130,
1360 biped_small::Species::IronDwarf | biped_small::Species::Flamekeeper => 300,
1361 biped_small::Species::Boreal => 470,
1362 _ => 100,
1363 },
1364 Body::BirdLarge(b) => match b.species {
1365 bird_large::Species::FlameWyvern
1366 | bird_large::Species::FrostWyvern
1367 | bird_large::Species::CloudWyvern
1368 | bird_large::Species::SeaWyvern
1369 | bird_large::Species::WealdWyvern => 220,
1370 _ => 165,
1371 },
1372 Body::Golem(_) => 365,
1373 Body::QuadrupedMedium(b) => match b.species {
1374 quadruped_medium::Species::Bear | quadruped_medium::Species::Grolgar => 195,
1375 quadruped_medium::Species::Cattle
1376 | quadruped_medium::Species::Llama
1377 | quadruped_medium::Species::Alpaca
1378 | quadruped_medium::Species::Camel
1379 | quadruped_medium::Species::ClaySteed
1380 | quadruped_medium::Species::Zebra
1381 | quadruped_medium::Species::Donkey
1382 | quadruped_medium::Species::Highland
1383 | quadruped_medium::Species::Horse
1384 | quadruped_medium::Species::Kelpie
1385 | quadruped_medium::Species::Hirdrasil
1386 | quadruped_medium::Species::Antelope => 165,
1387 quadruped_medium::Species::Deer => 140,
1388 quadruped_medium::Species::Wolf
1389 | quadruped_medium::Species::Tiger
1390 | quadruped_medium::Species::Barghest
1391 | quadruped_medium::Species::Bonerattler
1392 | quadruped_medium::Species::Darkhound
1393 | quadruped_medium::Species::Moose
1394 | quadruped_medium::Species::Snowleopard
1395 | quadruped_medium::Species::Akhlut
1396 | quadruped_medium::Species::Bristleback
1397 | quadruped_medium::Species::Catoblepas
1398 | quadruped_medium::Species::Lion => 190,
1399 quadruped_medium::Species::Panda => 150,
1400 quadruped_medium::Species::Saber
1401 | quadruped_medium::Species::Yak
1402 | quadruped_medium::Species::Frostfang
1403 | quadruped_medium::Species::Tarasque
1404 | quadruped_medium::Species::Tuskram
1405 | quadruped_medium::Species::Mouflon
1406 | quadruped_medium::Species::Roshwalr
1407 | quadruped_medium::Species::Dreadhorn => 205,
1408 quadruped_medium::Species::Mammoth | quadruped_medium::Species::Ngoubou => 230,
1409 },
1410 Body::QuadrupedLow(b) => match b.species {
1411 quadruped_low::Species::Dagon => 270,
1412 quadruped_low::Species::Crocodile
1413 | quadruped_low::Species::Deadwood
1414 | quadruped_low::Species::SeaCrocodile
1415 | quadruped_low::Species::Alligator
1416 | quadruped_low::Species::Sandshark
1417 | quadruped_low::Species::Snaretongue
1418 | quadruped_low::Species::Asp => 190,
1419 quadruped_low::Species::Tortoise
1420 | quadruped_low::Species::Rocksnapper
1421 | quadruped_low::Species::Rootsnapper
1422 | quadruped_low::Species::Reefsnapper
1423 | quadruped_low::Species::Maneater
1424 | quadruped_low::Species::Hakulaq
1425 | quadruped_low::Species::Lavadrake
1426 | quadruped_low::Species::Icedrake
1427 | quadruped_low::Species::Basilisk
1428 | quadruped_low::Species::Hydra
1429 | quadruped_low::Species::Mossdrake => 205,
1430 quadruped_low::Species::Elbst
1431 | quadruped_low::Species::Salamander
1432 | quadruped_low::Species::Monitor
1433 | quadruped_low::Species::Pangolin
1434 | quadruped_low::Species::Driggle => 130,
1435 },
1436 Body::Theropod(b) => match b.species {
1437 theropod::Species::Archaeos
1438 | theropod::Species::Ntouka
1439 | theropod::Species::Odonto => 240,
1440 theropod::Species::Yale => 220,
1441 _ => 195,
1442 },
1443 _ => 100,
1444 }
1445 }
1446
1447 pub fn eye_height(&self, scale: f32) -> f32 { self.height() * 0.9 * scale }
1449
1450 pub fn default_light_offset(&self) -> Vec3<f32> {
1451 match self {
1453 Body::Object(_) => Vec3::unit_z() * 0.5,
1454 _ => Vec3::unit_z(),
1455 }
1456 }
1457
1458 pub fn can_strafe(&self) -> bool {
1459 matches!(
1460 self,
1461 Body::Humanoid(_)
1462 | Body::BipedSmall(_)
1463 | Body::BipedLarge(_)
1464 | Body::Crustacean(crustacean::Body {
1465 species: crustacean::Species::Crab,
1466 ..
1467 })
1468 )
1469 }
1470
1471 pub fn mount_offset(&self) -> Vec3<f32> {
1474 match self {
1475 Body::Humanoid(_) => (self.dimensions() * Vec3::new(0.5, 0.0, 0.6)).into_tuple(),
1476 Body::QuadrupedSmall(b) => match (b.species, b.body_type) {
1477 (quadruped_small::Species::Pig, _) => (0.0, 0.1, 0.6),
1478 (quadruped_small::Species::Fox, _) => (0.0, 0.1, 0.6),
1479 (quadruped_small::Species::Sheep, _) => (0.0, 0.1, 0.7),
1480 (quadruped_small::Species::Boar, _) => (0.0, -0.2, 1.0),
1481 (quadruped_small::Species::Jackalope, _) => (0.0, -0.1, 0.5),
1482 (quadruped_small::Species::Skunk, _) => (0.0, 0.0, 0.55),
1483 (quadruped_small::Species::Cat, _) => (0.0, 0.0, 0.45),
1484 (quadruped_small::Species::Batfox, _) => (0.0, -0.1, 0.7),
1485 (quadruped_small::Species::Raccoon, _) => (0.0, 0.0, 0.65),
1486 (quadruped_small::Species::Quokka, _) => (0.0, 0.1, 0.7),
1487 (quadruped_small::Species::Goat, _) => (0.0, 0.2, 0.7),
1488 (quadruped_small::Species::Holladon, _) => (0.0, -0.3, 1.05),
1489 (quadruped_small::Species::Hyena, _) => (0.0, -0.4, 0.95),
1490 (quadruped_small::Species::Rabbit, _) => (0.0, -0.05, 0.4),
1491 (quadruped_small::Species::Truffler, _) => (0.0, -0.5, 1.84),
1492 (quadruped_small::Species::Frog, _) => (0.0, -0.07, 0.35),
1493 (quadruped_small::Species::Rat, _) => (0.0, 0.35, 0.35),
1494 (quadruped_small::Species::Axolotl, _) => (0.0, 0.095, 0.295),
1495 (quadruped_small::Species::Gecko, _) => (0.0, 0.35, 0.25),
1496 (quadruped_small::Species::Turtle, _) => (0.0, -0.16, 0.5),
1497 (quadruped_small::Species::Squirrel, _) => (0.0, 0.16, 0.24),
1498 (quadruped_small::Species::Fungome, _) => (0.0, 0.03, 0.43),
1499 (quadruped_small::Species::Porcupine, _) => (0.0, 0.56, 0.74),
1500 (quadruped_small::Species::Beaver, _) => (0.0, 0.18, 0.7),
1501 (quadruped_small::Species::Hare, quadruped_small::BodyType::Female) => {
1502 (0.0, -0.21, 0.44)
1503 },
1504 (quadruped_small::Species::Hare, quadruped_small::BodyType::Male) => {
1505 (0.0, -0.21, 0.54)
1506 },
1507 (quadruped_small::Species::Dog, _) => (0.0, -0.27, 0.76),
1508 (quadruped_small::Species::Seal, _) => (0.0, -0.14, 0.54),
1509 (quadruped_small::Species::TreantSapling, _) => (0.0, -0.2, 1.03),
1510 (quadruped_small::Species::MossySnail, _) => (0.0, -0.34, 0.96),
1511 },
1512 Body::QuadrupedMedium(b) => match (b.species, b.body_type) {
1513 (quadruped_medium::Species::Grolgar, _) => (0.0, 0.4, 1.98),
1514 (quadruped_medium::Species::Saber, _) => (0.0, -0.1, 1.3),
1515 (quadruped_medium::Species::Tiger, _) => (0.0, 0.2, 1.63),
1516 (quadruped_medium::Species::Tuskram, _) => (0.0, -0.5, 1.5),
1517 (quadruped_medium::Species::Lion, _) => (0.0, 0.3, 1.5),
1518 (quadruped_medium::Species::Tarasque, _) => (0.0, 0.6, 2.0),
1519 (quadruped_medium::Species::Wolf, _) => (0.0, 0.5, 1.3),
1520 (quadruped_medium::Species::Frostfang, _) => (0.0, 0.05, 1.2),
1521 (quadruped_medium::Species::Mouflon, _) => (0.0, 0.3, 1.2),
1522 (quadruped_medium::Species::Catoblepas, _) => (0.0, 0.0, 2.0),
1523 (quadruped_medium::Species::Bonerattler, _) => (0.0, 0.5, 1.2),
1524 (quadruped_medium::Species::Deer, _) => (0.0, 0.2, 1.3),
1525 (quadruped_medium::Species::Hirdrasil, _) => (0.0, 0.0, 1.4),
1526 (quadruped_medium::Species::Roshwalr, _) => (0.0, 0.9, 3.2),
1527 (quadruped_medium::Species::Donkey, _) => (0.0, 0.5, 1.6),
1528 (quadruped_medium::Species::Camel, _) => (0.0, -0.1, 2.7),
1529 (quadruped_medium::Species::Zebra, _) => (0.0, 0.5, 1.8),
1530 (quadruped_medium::Species::Antelope, _) => (0.0, 0.3, 1.4),
1531 (quadruped_medium::Species::Kelpie, _) => (0.0, 0.5, 1.9),
1532 (quadruped_medium::Species::Horse, _) => (0.0, 0.0, 2.0),
1533 (quadruped_medium::Species::Barghest, _) => (0.0, 0.5, 2.3),
1534 (quadruped_medium::Species::Cattle, quadruped_medium::BodyType::Male) => {
1535 (0.0, 0.5, 2.5)
1536 },
1537 (quadruped_medium::Species::Cattle, quadruped_medium::BodyType::Female) => {
1538 (0.0, 0.7, 2.3)
1539 },
1540 (quadruped_medium::Species::Darkhound, _) => (0.0, 0.5, 1.4),
1541 (quadruped_medium::Species::Highland, _) => (0.0, 0.5, 2.3),
1542 (quadruped_medium::Species::Yak, _) => (0.0, 0.0, 3.0),
1543 (quadruped_medium::Species::Panda, _) => (0.0, -0.2, 1.4),
1544 (quadruped_medium::Species::Bear, _) => (0.0, -0.4, 2.35),
1545 (quadruped_medium::Species::Dreadhorn, _) => (0.0, 0.2, 3.8),
1546 (quadruped_medium::Species::Moose, _) => (0.0, -0.6, 2.1),
1547 (quadruped_medium::Species::Snowleopard, _) => (0.0, -0.5, 1.4),
1548 (quadruped_medium::Species::Mammoth, _) => (0.0, 4.9, 7.2),
1549 (quadruped_medium::Species::Ngoubou, _) => (0.0, 0.3, 2.4),
1550 (quadruped_medium::Species::Llama, _) => (0.0, 0.1, 1.5),
1551 (quadruped_medium::Species::Alpaca, _) => (0.0, -0.1, 1.0),
1552 (quadruped_medium::Species::Akhlut, _) => (0.0, 1.9, 2.6),
1553 (quadruped_medium::Species::Bristleback, _) => (0.0, -0.4, 1.3),
1554 (quadruped_medium::Species::ClaySteed, _) => (0.0, -0.3, 2.8),
1555 },
1556 Body::BirdMedium(b) => match (b.species, b.body_type) {
1557 (bird_medium::Species::SnowyOwl, _) => (0.0, -0.25, 0.52),
1558 (bird_medium::Species::HornedOwl, _) => (0.0, -0.25, 0.45),
1559 (bird_medium::Species::Duck, _) => (0.0, -0.18, 0.47),
1560 (bird_medium::Species::Cockatiel, _) => (0.0, -0.05, 0.44),
1561 (bird_medium::Species::Chicken, bird_medium::BodyType::Female) => {
1562 (0.0, -0.13, 0.62)
1563 },
1564 (bird_medium::Species::Chicken, bird_medium::BodyType::Male) => (0.0, -0.1, 0.62),
1565 (bird_medium::Species::Bat, _) => (0.0, 0.02, 0.47),
1566 (bird_medium::Species::Penguin, _) => (0.0, -0.15, 0.88),
1567 (bird_medium::Species::Goose, _) => (0.0, -0.04, 0.74),
1568 (bird_medium::Species::Peacock, _) => (0.0, -0.18, 0.77),
1569 (bird_medium::Species::Eagle, _) => (0.0, -0.26, 0.64),
1570 (bird_medium::Species::Parrot, _) => (0.0, -0.18, 0.52),
1571 (bird_medium::Species::Crow, _) => (0.0, -0.08, 0.5),
1572 (bird_medium::Species::Dodo, _) => (0.0, -0.25, 0.7),
1573 (bird_medium::Species::Parakeet, _) => (0.0, -0.08, 0.42),
1574 (bird_medium::Species::Puffin, _) => (0.0, -0.21, 0.56),
1575 (bird_medium::Species::Toucan, _) => (0.0, -0.12, 0.52),
1576 (bird_medium::Species::BloodmoonBat, _) => (0.0, 0.1, 1.6),
1577 (bird_medium::Species::VampireBat, _) => (0.0, 0.02, 0.5),
1578 },
1579 Body::FishMedium(b) => match (b.species, b.body_type) {
1580 (fish_medium::Species::Marlin, _) => (0.0, 0.26, 0.6),
1581 (fish_medium::Species::Icepike, _) => (0.0, 0.34, 0.65),
1582 },
1583 Body::Dragon(b) => match (b.species, b.body_type) {
1584 (dragon::Species::Reddragon, _) => (0.0, 0.5, 20.5),
1585 },
1586 Body::BirdLarge(b) => match (b.species, b.body_type) {
1587 (bird_large::Species::Phoenix, _) => (0.0, 0.4, 3.1),
1588 (bird_large::Species::Cockatrice, _) => (0.0, 0.94, 2.98),
1589 (bird_large::Species::Roc, _) => (0.0, 2.18, 4.23),
1590 (bird_large::Species::FlameWyvern, _) => (0.0, 1.58, 3.28),
1591 (bird_large::Species::CloudWyvern, _) => (0.0, 1.7, 3.15),
1592 (bird_large::Species::FrostWyvern, _) => (0.0, 1.8, 3.09),
1593 (bird_large::Species::SeaWyvern, _) => (0.0, 1.41, 3.31),
1594 (bird_large::Species::WealdWyvern, _) => (0.0, 1.8, 3.46),
1595 },
1596 Body::FishSmall(b) => match (b.species, b.body_type) {
1597 (fish_small::Species::Clownfish, _) => (0.0, 0.05, 0.6),
1598 (fish_small::Species::Piranha, _) => (0.0, -0.065, 0.715),
1599 },
1600 Body::BipedLarge(b) => match (b.species, b.body_type) {
1601 (biped_large::Species::Ogre, biped_large::BodyType::Female) => (1.2, 0.2, 4.2),
1602 (biped_large::Species::Ogre, biped_large::BodyType::Male) => (1.5, -0.25, 4.5),
1603 (biped_large::Species::Cyclops, _) => (3.0, 1.1, 6.6),
1604 (biped_large::Species::Wendigo, _) => (1.25, -0.2, 4.3),
1605 (biped_large::Species::Cavetroll, _) => (1.8, 0.1, 4.1),
1606 (biped_large::Species::Mountaintroll, _) => (1.9, 0.5, 4.2),
1607 (biped_large::Species::Swamptroll, _) => (1.9, 0.0, 4.3),
1608 (biped_large::Species::Dullahan, _) => (0.0, -0.2, 4.5),
1609 (biped_large::Species::Werewolf, _) => (1.0, 1.0, 2.8),
1610 (biped_large::Species::Occultsaurok, _) => (0.0, 0.4, 3.4),
1611 (biped_large::Species::Mightysaurok, _) => (0.0, 0.4, 3.4),
1612 (biped_large::Species::Slysaurok, _) => (0.0, 0.4, 3.4),
1613 (biped_large::Species::Mindflayer, _) => (1.8, 0.6, 6.6),
1614 (biped_large::Species::Minotaur, _) => (2.1, 0.4, 6.6),
1615 (biped_large::Species::Tidalwarrior, _) => (0.0, -0.5, 7.4),
1616 (biped_large::Species::Yeti, _) => (1.6, 0.5, 3.7),
1617 (biped_large::Species::Harvester, _) => (1.3, 0.4, 2.6),
1618 (biped_large::Species::Blueoni, _) => (1.7, 0.4, 3.6),
1619 (biped_large::Species::Redoni, _) => (1.7, 0.4, 3.6),
1620 (biped_large::Species::Cultistwarlord, _) => (1.1, 0.3, 2.7),
1621 (biped_large::Species::Cultistwarlock, _) => (1.0, 0.3, 2.7),
1622 (biped_large::Species::Huskbrute, _) => (1.6, 0.2, 3.8),
1623 (biped_large::Species::Tursus, _) => (1.6, 0.5, 3.4),
1624 (biped_large::Species::Gigasfrost, _) => (2.5, 0.5, 7.3),
1625 (biped_large::Species::AdletElder, _) => (1.2, 0.6, 2.4),
1626 (biped_large::Species::SeaBishop, _) => (0.9, 0.2, 2.0),
1627 (biped_large::Species::HaniwaGeneral, _) => (1.2, 0.4, 2.4),
1628 (biped_large::Species::TerracottaBesieger, _) => (1.5, -0.2, 3.3),
1629 (biped_large::Species::TerracottaDemolisher, _) => (1.1, -0.1, 2.2),
1630 (biped_large::Species::TerracottaPunisher, _) => (1.1, -0.1, 2.1),
1631 (biped_large::Species::TerracottaPursuer, _) => (1.1, -0.1, 2.2),
1632 (biped_large::Species::Cursekeeper, _) => (1.3, -0.4, 3.0),
1633 (biped_large::Species::Forgemaster, _) => (2.6, 0.8, 6.1),
1634 (biped_large::Species::Strigoi, _) => (1.7, -0.1, 3.6),
1635 (biped_large::Species::Executioner, _) => (1.1, 0.1, 3.3),
1636 },
1637 Body::BipedSmall(b) => match (b.species, b.body_type) {
1638 (biped_small::Species::Gnome, _) => (0.0, -0.33, 1.22),
1639 (biped_small::Species::Sahagin, _) => (0.0, 0.0, 1.9),
1640 (biped_small::Species::Adlet, _) => (0.0, -0.35, 1.7),
1641 (biped_small::Species::Gnarling, _) => (0.0, -0.3, 1.07),
1642 (biped_small::Species::Mandragora, _) => (0.0, -0.25, 0.72),
1643 (biped_small::Species::Kappa, _) => (0.0, -0.34, 1.1),
1644 (biped_small::Species::Cactid, _) => (0.0, -0.25, 1.13),
1645 (biped_small::Species::Gnoll, _) => (0.0, -0.28, 1.25),
1646 (biped_small::Species::Haniwa, _) => (0.0, -0.6, 1.91),
1647 (biped_small::Species::Myrmidon, _) => (0.0, -0.89, 0.96),
1648 (biped_small::Species::Husk, _) => (0.0, -0.5, 2.32),
1649 (biped_small::Species::Boreal, _) => (0.0, -0.81, 4.4),
1650 (biped_small::Species::Bushly, _) => (0.0, -0.26, 1.81),
1651 (biped_small::Species::Irrwurz, _) => (0.0, -0.35, 1.42),
1652 (biped_small::Species::IronDwarf, _) => (0.0, -0.12, 2.98),
1653 (biped_small::Species::Flamekeeper, _) => (0.0, -0.31, 2.2),
1654 (biped_small::Species::ShamanicSpirit, _) => (0.0, -0.03, 2.29),
1655 (biped_small::Species::Jiangshi, _) => (0.0, -0.21, 2.53),
1656 (biped_small::Species::TreasureEgg, _) => (0.0, -0.31, 1.0),
1657 (biped_small::Species::GnarlingChieftain, _) => (0.0, -0.27, 1.28),
1658 (biped_small::Species::BloodmoonHeiress, _) => (0.0, -0.12, 5.22),
1659 (biped_small::Species::Bloodservant, _) => (0.0, -0.21, 2.26),
1660 (biped_small::Species::Harlequin, _) => (0.0, -0.26, 2.17),
1661 (biped_small::Species::GoblinThug, _) => (0.0, -0.37, 0.49),
1662 (biped_small::Species::GoblinChucker, _) => (0.0, -0.83, 0.49),
1663 (biped_small::Species::GoblinRuffian, _) => (0.0, -0.37, 0.49),
1664 (biped_small::Species::GreenLegoom, _) => (0.0, -0.4, 1.48),
1665 (biped_small::Species::OchreLegoom, _) => (0.0, -0.4, 1.2),
1666 (biped_small::Species::PurpleLegoom, _) => (0.0, -0.36, 1.66),
1667 (biped_small::Species::RedLegoom, _) => (0.0, -0.3, 1.4),
1668 },
1669 Body::Golem(b) => match (b.species, b.body_type) {
1670 (golem::Species::StoneGolem, _) => (0.0, 0.2, 8.8),
1671 (golem::Species::Treant, _) => (0.0, 3.6, 6.4),
1672 (golem::Species::ClayGolem, _) => (0.0, 0.0, 7.8),
1673 (golem::Species::WoodGolem, _) => (0.0, 0.5, 7.2),
1674 (golem::Species::CoralGolem, _) => (0.0, 0.0, 4.0),
1675 (golem::Species::Gravewarden, _) => (0.0, -0.5, 7.5),
1676 (golem::Species::AncientEffigy, _) => (0.0, -0.2, 3.5),
1677 (golem::Species::Mogwai, _) => (0.0, 0.4, 3.7),
1678 (golem::Species::IronGolem, _) => (0.0, 0.2, 10.2),
1679 },
1680 Body::Theropod(b) => match (b.species, b.body_type) {
1681 (theropod::Species::Archaeos, _) => (0.0, 2.2, 6.1),
1682 (theropod::Species::Odonto, _) => (0.0, 4.1, 4.0),
1683 (theropod::Species::Sandraptor, _) => (0.0, -0.15, 1.63),
1684 (theropod::Species::Snowraptor, _) => (0.0, -0.15, 1.58),
1685 (theropod::Species::Woodraptor, _) => (0.0, -0.14, 1.66),
1686 (theropod::Species::Sunlizard, _) => (0.0, -0.2, 1.75),
1687 (theropod::Species::Yale, _) => (0.0, -0.615, 2.75),
1688 (theropod::Species::Ntouka, _) => (0.0, -1.1, 5.5),
1689 (theropod::Species::Dodarock, _) => (0.0, -0.09, 1.49),
1690 (theropod::Species::Axebeak, _) => (0.0, -0.34, 1.85),
1691 },
1692 Body::QuadrupedLow(b) => match (b.species, b.body_type) {
1693 (quadruped_low::Species::Crocodile, _) => (0.0, 0.35, 0.8),
1694 (quadruped_low::Species::Alligator, _) => (0.0, 0.27, 0.8),
1695 (quadruped_low::Species::Salamander, _) => (0.0, 0.21, 0.9),
1696 (quadruped_low::Species::Monitor, _) => (0.0, 0.01, 0.64),
1697 (quadruped_low::Species::Asp, _) => (0.0, 0.21, 1.2),
1698 (quadruped_low::Species::Tortoise, _) => (0.0, 0.01, 1.37),
1699 (quadruped_low::Species::Pangolin, _) => (0.0, -0.08, 1.08),
1700 (quadruped_low::Species::Maneater, _) => (0.0, 1.3, 2.0),
1701 (quadruped_low::Species::Sandshark, _) => (0.0, -0.48, 1.62),
1702 (quadruped_low::Species::Hakulaq, _) => (0.0, 0.49, 1.51),
1703 (quadruped_low::Species::Lavadrake, _) => (0.0, 0.22, 1.61),
1704 (quadruped_low::Species::Basilisk, _) => (0.0, -0.17, 2.71),
1705 (quadruped_low::Species::Deadwood, _) => (0.0, -0.15, 1.21),
1706 (quadruped_low::Species::Icedrake, _) => (0.0, -0.7, 2.28),
1707 (quadruped_low::Species::SeaCrocodile, _) => (0.1, 0.35, 1.03),
1708 (quadruped_low::Species::Dagon, _) => (0.1, 0.92, 1.32),
1709 (quadruped_low::Species::Rocksnapper, _) => (0.0, 0.72, 2.73),
1710 (quadruped_low::Species::Rootsnapper, _) => (0.0, -0.18, 3.13),
1711 (quadruped_low::Species::Reefsnapper, _) => (0.0, 0.22, 2.32),
1712 (quadruped_low::Species::Elbst, _) => (0.0, 0.22, 0.8),
1713 (quadruped_low::Species::Mossdrake, _) => (0.0, 0.22, 2.02),
1714 (quadruped_low::Species::Driggle, _) => (0.0, 0.5, 0.8),
1715 (quadruped_low::Species::Snaretongue, _) => (0.0, -0.54, 1.35),
1716 (quadruped_low::Species::Hydra, _) => (0.0, 0.28, 2.71),
1717 },
1718 Body::Arthropod(b) => match (b.species, b.body_type) {
1719 (arthropod::Species::Tarantula, _) => (0.0, -0.65, 1.66),
1720 (arthropod::Species::Blackwidow, _) => (0.0, -0.82, 2.48),
1721 (arthropod::Species::Antlion, _) => (0.0, -0.49, 1.98),
1722 (arthropod::Species::Hornbeetle, _) => (0.0, 0.27, 1.98),
1723 (arthropod::Species::Leafbeetle, _) => (0.0, -0.06, 1.1),
1724 (arthropod::Species::Stagbeetle, _) => (0.0, 0.6, 1.48),
1725 (arthropod::Species::Weevil, _) => (0.0, -0.1, 1.02),
1726 (arthropod::Species::Cavespider, _) => (0.0, -0.65, 1.82),
1727 (arthropod::Species::Moltencrawler, _) => (0.0, 0.43, 1.82),
1728 (arthropod::Species::Mosscrawler, _) => (0.0, 0.6, 1.82),
1729 (arthropod::Species::Sandcrawler, _) => (0.0, 0.6, 1.82),
1730 (arthropod::Species::Dagonite, _) => (0.0, 1.1, 2.15),
1731 (arthropod::Species::Emberfly, _) => (0.0, -0.28, 0.36),
1732 },
1733 Body::Crustacean(b) => match (b.species, b.body_type) {
1734 (crustacean::Species::Crab, _) => (0.0, -0.22, 0.36),
1735 (crustacean::Species::SoldierCrab, _) => (0.0, -0.14, 0.5),
1736 (crustacean::Species::Karkatha, _) => (0.0, -0.23, 7.66),
1737 },
1738 Body::Ship(ship) => match ship {
1739 ship::Body::DefaultAirship => (0.0, 0.0, 10.0),
1740 ship::Body::AirBalloon => (0.0, 0.0, 5.0),
1741 ship::Body::SailBoat => (-2.0, -5.0, 4.0),
1742 ship::Body::Galleon => (-2.0, -5.0, 4.0),
1743 ship::Body::Skiff => (1.0, -2.0, 2.0),
1744 ship::Body::Submarine => (1.0, -2.0, 2.0),
1745 ship::Body::Carriage => (1.0, -2.0, 2.0),
1746 ship::Body::Cart => (1.0, -2.0, 2.0),
1747 ship::Body::Volume => (0.0, 0.0, 0.0),
1748 },
1749 _ => (0.0, 0.0, 0.0),
1750 }
1751 .into()
1752 }
1753
1754 pub fn rider_offset(&self) -> Vec3<f32> {
1756 match self {
1757 Body::Humanoid(_) => [0.0, 0.0, 0.0],
1758 _ => [0.0, 0.0, 0.0],
1759 }
1760 .into()
1761 }
1762
1763 pub fn tether_offset_leader(&self) -> Vec3<f32> {
1764 Vec3::new(0.0, self.dimensions().y * -0.4, self.dimensions().z * 0.7)
1765 }
1766
1767 pub fn tether_offset_follower(&self) -> Vec3<f32> {
1768 Vec3::new(0.0, self.dimensions().y * 0.6, self.dimensions().z * 0.7)
1769 }
1770
1771 pub fn localize_npc(&self) -> Content {
1776 fn try_localize(body: &Body) -> Option<Content> {
1777 match body {
1778 Body::BipedLarge(biped_large) => biped_large.localize_npc(),
1779 _ => None,
1780 }
1781 }
1782
1783 try_localize(self).unwrap_or_else(|| Content::localized("body-npc-speech-generic"))
1784 }
1785
1786 pub fn humanoid_gender(&self) -> Option<Gender> {
1788 match self {
1789 Body::Humanoid(b) => match b.body_type {
1790 humanoid::BodyType::Male => Some(Gender::Masculine),
1791 humanoid::BodyType::Female => Some(Gender::Feminine),
1792 },
1793 _ => None,
1794 }
1795 }
1796
1797 pub fn default_gender(&self) -> Gender {
1809 match self {
1810 Body::Humanoid(b) => match b.body_type {
1811 humanoid::BodyType::Male => Gender::Masculine,
1812 humanoid::BodyType::Female => Gender::Feminine,
1813 },
1814 Body::QuadrupedSmall(b) => match b.body_type {
1815 quadruped_small::BodyType::Male => Gender::Masculine,
1816 quadruped_small::BodyType::Female => Gender::Feminine,
1817 },
1818 Body::QuadrupedMedium(b) => match b.body_type {
1819 quadruped_medium::BodyType::Male => Gender::Masculine,
1820 quadruped_medium::BodyType::Female => Gender::Feminine,
1821 },
1822 Body::QuadrupedLow(b) => match b.body_type {
1823 quadruped_low::BodyType::Male => Gender::Masculine,
1824 quadruped_low::BodyType::Female => Gender::Feminine,
1825 },
1826 Body::BirdMedium(b) => match b.body_type {
1827 bird_medium::BodyType::Male => Gender::Masculine,
1828 bird_medium::BodyType::Female => Gender::Feminine,
1829 },
1830 Body::BirdLarge(b) => match b.body_type {
1831 bird_large::BodyType::Male => Gender::Masculine,
1832 bird_large::BodyType::Female => Gender::Feminine,
1833 },
1834 Body::FishMedium(b) => match b.body_type {
1835 fish_medium::BodyType::Male => Gender::Masculine,
1836 fish_medium::BodyType::Female => Gender::Feminine,
1837 },
1838 Body::FishSmall(b) => match b.body_type {
1839 fish_small::BodyType::Male => Gender::Masculine,
1840 fish_small::BodyType::Female => Gender::Feminine,
1841 },
1842 Body::Dragon(b) => match b.body_type {
1843 dragon::BodyType::Male => Gender::Masculine,
1844 dragon::BodyType::Female => Gender::Feminine,
1845 },
1846 Body::BipedLarge(b) => match b.body_type {
1847 biped_large::BodyType::Male => Gender::Masculine,
1848 biped_large::BodyType::Female => Gender::Feminine,
1849 },
1850 Body::BipedSmall(b) => match b.body_type {
1851 biped_small::BodyType::Male => Gender::Masculine,
1852 biped_small::BodyType::Female => Gender::Feminine,
1853 },
1854 Body::Golem(b) => match b.body_type {
1855 golem::BodyType::Male => Gender::Masculine,
1856 golem::BodyType::Female => Gender::Feminine,
1857 },
1858 Body::Theropod(b) => match b.body_type {
1859 theropod::BodyType::Male => Gender::Masculine,
1860 theropod::BodyType::Female => Gender::Feminine,
1861 },
1862 Body::Arthropod(b) => match b.body_type {
1863 arthropod::BodyType::Male => Gender::Masculine,
1864 arthropod::BodyType::Female => Gender::Feminine,
1865 },
1866 Body::Crustacean(b) => match b.body_type {
1867 crustacean::BodyType::Male => Gender::Masculine,
1868 crustacean::BodyType::Female => Gender::Feminine,
1869 },
1870 Body::Plugin(_) => Gender::Neuter,
1872 Body::Object(_) | Body::Ship(_) | Body::Item(_) => Gender::Neuter,
1873 }
1874 }
1875
1876 pub fn gender_attr(&self) -> &'static str {
1880 match self.default_gender() {
1881 Gender::Feminine => "fem",
1882 Gender::Masculine => "masc",
1883 Gender::Neuter => "neut",
1884 }
1885 }
1886}
1887
1888impl Component for Body {
1889 type Storage = DerefFlaggedStorage<Self, specs::VecStorage<Self>>;
1890}