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