veloren_common/comp/body/
object.rs

1use crate::{
2    comp::{Density, Mass, item::Reagent},
3    consts::{IRON_DENSITY, WATER_DENSITY},
4    make_case_elim,
5};
6use rand::{seq::SliceRandom, thread_rng};
7use serde::{Deserialize, Serialize};
8use vek::Vec3;
9
10make_case_elim!(
11    body,
12    #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
13    #[repr(u32)]
14    pub enum Body {
15        Arrow = 0,
16        Bomb = 1,
17        Scarecrow = 2,
18        Cauldron = 3,
19        ChestVines = 4,
20        Chest = 5,
21        ChestDark = 6,
22        ChestDemon = 7,
23        ChestGold = 8,
24        ChestLight = 9,
25        ChestOpen = 10,
26        ChestSkull = 11,
27        Pumpkin = 12,
28        Pumpkin2 = 13,
29        Pumpkin3 = 14,
30        Pumpkin4 = 15,
31        Pumpkin5 = 16,
32        Campfire = 17,
33        LanternGround = 18,
34        LanternGroundOpen = 19,
35        LanternStanding2 = 20,
36        LanternStanding = 21,
37        PotionBlue = 22,
38        PotionGreen = 23,
39        PotionRed = 24,
40        Crate = 25,
41        Tent = 26,
42        WindowSpooky = 27,
43        DoorSpooky = 28,
44        Anvil = 29,
45        Gravestone = 30,
46        Gravestone2 = 31,
47        Bench = 32,
48        Chair = 33,
49        Chair2 = 34,
50        Chair3 = 35,
51        Table = 36,
52        Table2 = 37,
53        Table3 = 38,
54        Drawer = 39,
55        BedBlue = 40,
56        Carpet = 41,
57        Bedroll = 42,
58        CarpetHumanRound = 43,
59        CarpetHumanSquare = 44,
60        CarpetHumanSquare2 = 45,
61        CarpetHumanSquircle = 46,
62        Pouch = 47,
63        CraftingBench = 48,
64        BoltFire = 49,
65        ArrowSnake = 50,
66        CampfireLit = 51,
67        BoltFireBig = 52,
68        TrainingDummy = 53,
69        FireworkBlue = 54,
70        FireworkGreen = 55,
71        FireworkPurple = 56,
72        FireworkRed = 57,
73        FireworkWhite = 58,
74        FireworkYellow = 59,
75        MultiArrow = 60,
76        BoltNature = 61,
77        ToughMeat = 62,
78        BeastMeat = 63,
79        Crossbow = 64,
80        ArrowTurret = 65,
81        Coins = 66,
82        GoldOre = 67,
83        SilverOre = 68,
84        ClayRocket = 69,
85        HaniwaSentry = 70,
86        SeaLantern = 71,
87        Snowball = 72,
88        BirdMeat = 73,
89        FishMeat = 74,
90        SmallMeat = 75,
91        Tornado = 76,
92        Apple = 77,
93        Hive = 78,
94        Coconut = 79,
95        SpitPoison = 80,
96        BoltIcicle = 81,
97        Dart = 82,
98        GnarlingTotemRed = 83,
99        GnarlingTotemGreen = 84,
100        GnarlingTotemWhite = 85,
101        DagonBomb = 86,
102        BarrelOrgan = 87,
103        IceBomb = 88,
104        SpectralSwordSmall = 89,
105        SpectralSwordLarge = 90,
106        LaserBeam = 91,
107        AdletSpear = 92,
108        AdletTrap = 93,
109        Flamethrower = 94,
110        Mine = 95,
111        LightningBolt = 96,
112        SpearIcicle = 97,
113        Portal = 98,
114        PortalActive = 99,
115        FieryTornado = 100,
116        FireRainDrop = 101,
117        ArrowClay = 102,
118        GrenadeClay = 103,
119        Pebble = 104,
120        LaserBeamSmall = 105,
121        TerracottaStatue = 106,
122        TerracottaDemolisherBomb = 107,
123        BoltBesieger = 108,
124        SurpriseEgg = 109,
125        BubbleBomb = 110,
126        IronPikeBomb = 111,
127        Lavathrower = 112,
128        Scroll = 113,
129        PoisonBall = 114,
130        StrigoiHead = 115,
131        HarlequinDagger = 116,
132        BloodBomb = 117,
133        MinotaurAxe = 118,
134        BorealTrap = 119,
135    }
136);
137
138impl Body {
139    pub fn random() -> Self {
140        let mut rng = thread_rng();
141        *ALL_OBJECTS.choose(&mut rng).unwrap()
142    }
143}
144
145pub const ALL_OBJECTS: [Body; 120] = [
146    Body::Arrow,
147    Body::Bomb,
148    Body::Scarecrow,
149    Body::Cauldron,
150    Body::ChestVines,
151    Body::Chest,
152    Body::ChestDark,
153    Body::ChestDemon,
154    Body::ChestGold,
155    Body::ChestLight,
156    Body::ChestOpen,
157    Body::ChestSkull,
158    Body::SpectralSwordSmall,
159    Body::SpectralSwordLarge,
160    Body::Pumpkin,
161    Body::Pumpkin2,
162    Body::Pumpkin3,
163    Body::Pumpkin4,
164    Body::Pumpkin5,
165    Body::Campfire,
166    Body::CampfireLit,
167    Body::LanternGround,
168    Body::LanternGroundOpen,
169    Body::LanternStanding,
170    Body::LanternStanding2,
171    Body::PotionRed,
172    Body::PotionBlue,
173    Body::PotionGreen,
174    Body::Crate,
175    Body::Tent,
176    Body::WindowSpooky,
177    Body::DoorSpooky,
178    Body::Anvil,
179    Body::Gravestone,
180    Body::Gravestone2,
181    Body::Bench,
182    Body::Chair,
183    Body::Chair2,
184    Body::Chair3,
185    Body::Table,
186    Body::Table2,
187    Body::Table3,
188    Body::Drawer,
189    Body::BedBlue,
190    Body::Carpet,
191    Body::Bedroll,
192    Body::CarpetHumanRound,
193    Body::CarpetHumanSquare,
194    Body::CarpetHumanSquare2,
195    Body::CarpetHumanSquircle,
196    Body::Pouch,
197    Body::CraftingBench,
198    Body::BoltFire,
199    Body::BoltFireBig,
200    Body::ArrowSnake,
201    Body::TrainingDummy,
202    Body::FireworkBlue,
203    Body::FireworkGreen,
204    Body::FireworkPurple,
205    Body::FireworkRed,
206    Body::FireworkWhite,
207    Body::FireworkYellow,
208    Body::MultiArrow,
209    Body::BoltNature,
210    Body::ToughMeat,
211    Body::BeastMeat,
212    Body::Crossbow,
213    Body::ArrowTurret,
214    Body::Coins,
215    Body::SilverOre,
216    Body::GoldOre,
217    Body::ClayRocket,
218    Body::HaniwaSentry,
219    Body::SeaLantern,
220    Body::Snowball,
221    Body::BirdMeat,
222    Body::FishMeat,
223    Body::SmallMeat,
224    Body::Tornado,
225    Body::Apple,
226    Body::Hive,
227    Body::Coconut,
228    Body::SpitPoison,
229    Body::BoltIcicle,
230    Body::Dart,
231    Body::GnarlingTotemRed,
232    Body::GnarlingTotemWhite,
233    Body::GnarlingTotemGreen,
234    Body::DagonBomb,
235    Body::TerracottaDemolisherBomb,
236    Body::BarrelOrgan,
237    Body::IceBomb,
238    Body::LaserBeam,
239    Body::LaserBeamSmall,
240    Body::AdletSpear,
241    Body::AdletTrap,
242    Body::Flamethrower,
243    Body::Mine,
244    Body::LightningBolt,
245    Body::SpearIcicle,
246    Body::Portal,
247    Body::PortalActive,
248    Body::FieryTornado,
249    Body::FireRainDrop,
250    Body::ArrowClay,
251    Body::GrenadeClay,
252    Body::Pebble,
253    Body::TerracottaStatue,
254    Body::BoltBesieger,
255    Body::SurpriseEgg,
256    Body::BubbleBomb,
257    Body::IronPikeBomb,
258    Body::Lavathrower,
259    Body::Scroll,
260    Body::PoisonBall,
261    Body::StrigoiHead,
262    Body::HarlequinDagger,
263    Body::BloodBomb,
264    Body::MinotaurAxe,
265    Body::BorealTrap,
266];
267
268impl From<Body> for super::Body {
269    fn from(body: Body) -> Self { super::Body::Object(body) }
270}
271
272impl Body {
273    pub fn to_string(self) -> &'static str {
274        match self {
275            Body::Arrow => "arrow",
276            Body::Bomb => "bomb",
277            Body::Scarecrow => "scarecrow",
278            Body::Cauldron => "cauldron",
279            Body::ChestVines => "chest_vines",
280            Body::Chest => "chest",
281            Body::ChestDark => "chest_dark",
282            Body::ChestDemon => "chest_demon",
283            Body::ChestGold => "chest_gold",
284            Body::ChestLight => "chest_light",
285            Body::ChestOpen => "chest_open",
286            Body::ChestSkull => "chest_skull",
287            Body::Pumpkin => "pumpkin",
288            Body::Pumpkin2 => "pumpkin_2",
289            Body::Pumpkin3 => "pumpkin_3",
290            Body::Pumpkin4 => "pumpkin_4",
291            Body::Pumpkin5 => "pumpkin_5",
292            Body::Campfire => "campfire",
293            Body::CampfireLit => "campfire_lit",
294            Body::LanternGround => "lantern_ground",
295            Body::LanternGroundOpen => "lantern_ground_open",
296            Body::LanternStanding => "lantern_standing",
297            Body::LanternStanding2 => "lantern_standing_2",
298            Body::PotionRed => "potion_red",
299            Body::PotionBlue => "potion_blue",
300            Body::PotionGreen => "potion_green",
301            Body::Crate => "crate",
302            Body::Tent => "tent",
303            Body::WindowSpooky => "window_spooky",
304            Body::DoorSpooky => "door_spooky",
305            Body::Anvil => "anvil",
306            Body::Gravestone => "gravestone",
307            Body::Gravestone2 => "gravestone_2",
308            Body::Bench => "bench",
309            Body::Chair => "chair",
310            Body::Chair2 => "chair_2",
311            Body::Chair3 => "chair_3",
312            Body::Table => "table",
313            Body::Table2 => "table_2",
314            Body::Table3 => "table_3",
315            Body::Drawer => "drawer",
316            Body::BedBlue => "bed_blue",
317            Body::Carpet => "carpet",
318            Body::Bedroll => "bedroll",
319            Body::CarpetHumanRound => "carpet_human_round",
320            Body::CarpetHumanSquare => "carpet_human_square",
321            Body::CarpetHumanSquare2 => "carpet_human_square_2",
322            Body::CarpetHumanSquircle => "carpet_human_squircle",
323            Body::Pouch => "pouch",
324            Body::CraftingBench => "crafting_bench",
325            Body::BoltFire => "bolt_fire",
326            Body::BoltFireBig => "bolt_fire_big",
327            Body::ArrowSnake => "arrow_snake",
328            Body::TrainingDummy => "training_dummy",
329            Body::FireworkBlue => "firework_blue",
330            Body::FireworkGreen => "firework_green",
331            Body::FireworkPurple => "firework_purple",
332            Body::FireworkRed => "firework_red",
333            Body::FireworkWhite => "firework_white",
334            Body::FireworkYellow => "firework_yellow",
335            Body::MultiArrow => "multi_arrow",
336            Body::BoltNature => "bolt_nature",
337            Body::ToughMeat => "tough_meat",
338            Body::BeastMeat => "beast_meat",
339            Body::Crossbow => "crossbow",
340            Body::ArrowTurret => "arrow_turret",
341            Body::Coins => "coins",
342            Body::SilverOre => "silver_ore",
343            Body::GoldOre => "gold_ore",
344            Body::ClayRocket => "clay_rocket",
345            Body::HaniwaSentry => "haniwa_sentry",
346            Body::SeaLantern => "sea_lantern",
347            Body::Snowball => "snowball",
348            Body::BirdMeat => "bird_meat",
349            Body::FishMeat => "fish_meat",
350            Body::SmallMeat => "small_meat",
351            Body::Tornado => "tornado",
352            Body::Apple => "apple",
353            Body::Hive => "hive",
354            Body::Coconut => "coconut",
355            Body::SpitPoison => "spit_poison",
356            Body::BoltIcicle => "bolt_icicle",
357            Body::Dart => "dart",
358            Body::GnarlingTotemRed => "gnarling_totem_red",
359            Body::GnarlingTotemGreen => "gnarling_totem_green",
360            Body::GnarlingTotemWhite => "gnarling_totem_white",
361            Body::DagonBomb => "dagon_bomb",
362            Body::TerracottaDemolisherBomb => "terracotta_demolisher_bomb",
363            Body::BarrelOrgan => "barrel_organ",
364            Body::IceBomb => "ice_bomb",
365            Body::SpectralSwordSmall => "spectral_sword_small",
366            Body::SpectralSwordLarge => "spectral_sword_large",
367            Body::LaserBeam => "laser_beam",
368            Body::LaserBeamSmall => "laser_beam_small",
369            Body::AdletSpear => "adlet_spear",
370            Body::AdletTrap => "adlet_trap",
371            Body::Flamethrower => "flamethrower",
372            Body::Lavathrower => "lavathrower",
373            Body::Mine => "mine",
374            Body::LightningBolt => "lightning_bolt",
375            Body::SpearIcicle => "spear_icicle",
376            Body::Portal => "portal",
377            Body::PortalActive => "portal_active",
378            Body::FieryTornado => "fiery_tornado",
379            Body::FireRainDrop => "fire_rain_drop",
380            Body::ArrowClay => "arrow_clay",
381            Body::GrenadeClay => "grenade_clay",
382            Body::Pebble => "pebble",
383            Body::TerracottaStatue => "terracotta_statue",
384            Body::BoltBesieger => "besieger_bolt",
385            Body::SurpriseEgg => "surprise_egg",
386            Body::BubbleBomb => "bubble_bomb",
387            Body::IronPikeBomb => "iron_pike_bomb",
388            Body::Scroll => "recipe",
389            Body::PoisonBall => "poison_ball",
390            Body::StrigoiHead => "strigoi_head",
391            Body::HarlequinDagger => "harlequin_dagger",
392            Body::BloodBomb => "blood_bomb",
393            Body::MinotaurAxe => "minotaur_axe",
394            Body::BorealTrap => "boreal_trap",
395        }
396    }
397
398    pub fn for_firework(reagent: Reagent) -> Body {
399        match reagent {
400            Reagent::Blue => Body::FireworkBlue,
401            Reagent::Green => Body::FireworkGreen,
402            Reagent::Purple => Body::FireworkPurple,
403            Reagent::Red => Body::FireworkRed,
404            Reagent::White => Body::FireworkWhite,
405            Reagent::Yellow => Body::FireworkYellow,
406            Reagent::Phoenix => Body::FireRainDrop,
407        }
408    }
409
410    pub fn density(&self) -> Density {
411        let density = match self {
412            Body::Anvil | Body::Cauldron => IRON_DENSITY,
413            Body::Arrow
414            | Body::ArrowSnake
415            | Body::ArrowTurret
416            | Body::MultiArrow
417            | Body::ArrowClay
418            | Body::BoltBesieger
419            | Body::Dart
420            | Body::DagonBomb
421            | Body::TerracottaDemolisherBomb
422            | Body::SpectralSwordSmall
423            | Body::SpectralSwordLarge
424            | Body::AdletSpear
425            | Body::HarlequinDagger
426            | Body::AdletTrap
427            | Body::Flamethrower
428            | Body::Lavathrower
429            | Body::BorealTrap
430            | Body::BloodBomb => 500.0,
431            Body::Bomb | Body::Mine | Body::SurpriseEgg => 2000.0, /* I have no idea what it's */
432            // supposed to be
433            Body::Crate => 300.0, // a lot of wood and maybe some contents
434            Body::Scarecrow => 900.0,
435            Body::TrainingDummy => 2000.0,
436            Body::Snowball => 0.9 * WATER_DENSITY,
437            Body::Pebble => 1000.0,
438            Body::Scroll => 0.5 * WATER_DENSITY,
439            // let them sink
440            _ => 1.1 * WATER_DENSITY,
441        };
442
443        Density(density)
444    }
445
446    pub fn mass(&self) -> Mass {
447        let m = match self {
448            // I think MultiArrow is one of several arrows, not several arrows combined?
449            Body::Anvil => 100.0,
450            Body::Arrow | Body::ArrowSnake | Body::ArrowTurret | Body::MultiArrow | Body::Dart => {
451                0.003
452            },
453            Body::SpectralSwordSmall => 0.5,
454            Body::SpectralSwordLarge => 50.0,
455            Body::BedBlue => 50.0,
456            Body::Bedroll => 3.0,
457            Body::Bench => 100.0,
458            Body::BoltFire
459            | Body::BoltFireBig
460            | Body::BoltNature
461            | Body::BoltIcicle
462            | Body::FireRainDrop
463            | Body::ArrowClay
464            | Body::Pebble
465            | Body::BubbleBomb
466            | Body::IronPikeBomb
467            | Body::BoltBesieger
468            | Body::PoisonBall => 1.0,
469            Body::SpitPoison => 100.0,
470            Body::Bomb
471            | Body::DagonBomb
472            | Body::SurpriseEgg
473            | Body::TerracottaDemolisherBomb
474            | Body::BloodBomb => {
475                0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3)
476            },
477            Body::Campfire | Body::CampfireLit | Body::BarrelOrgan | Body::TerracottaStatue => {
478                300.0
479            },
480            Body::Carpet
481            | Body::CarpetHumanRound
482            | Body::CarpetHumanSquare
483            | Body::CarpetHumanSquare2
484            | Body::CarpetHumanSquircle => 10.0,
485            Body::Cauldron => 5.0,
486            Body::Chair | Body::Chair2 | Body::Chair3 => 10.0,
487            Body::Chest
488            | Body::ChestDark
489            | Body::ChestDemon
490            | Body::ChestGold
491            | Body::ChestLight
492            | Body::ChestOpen
493            | Body::ChestSkull
494            | Body::ChestVines => 100.0,
495            Body::Coins | Body::Scroll => 1.0,
496            Body::CraftingBench => 100.0,
497            Body::Crate => 50.0,
498            Body::Crossbow => 200.0,
499            Body::Flamethrower | Body::Lavathrower => 200.0,
500            Body::DoorSpooky => 20.0,
501            Body::Drawer => 50.0,
502            Body::FireworkBlue
503            | Body::FireworkGreen
504            | Body::FireworkPurple
505            | Body::FireworkRed
506            | Body::FireworkWhite
507            | Body::FireworkYellow => 1.0,
508            Body::Gravestone => 100.0,
509            Body::Gravestone2 => 100.0,
510            Body::LanternGround
511            | Body::LanternGroundOpen
512            | Body::LanternStanding
513            | Body::LanternStanding2 => 3.0,
514            Body::ToughMeat => 50.0,
515            Body::BeastMeat => 50.0,
516            Body::PotionBlue | Body::PotionGreen | Body::PotionRed => 5.0,
517            Body::Pouch => 1.0,
518            Body::Pumpkin
519            | Body::Pumpkin2
520            | Body::Pumpkin3
521            | Body::Pumpkin4
522            | Body::Pumpkin5
523            | Body::StrigoiHead => 10.0,
524            Body::Scarecrow => 50.0,
525            Body::Table | Body::Table2 | Body::Table3 => 50.0,
526            Body::Tent => 50.0,
527            Body::TrainingDummy => 60.0,
528            Body::WindowSpooky => 10.0,
529            Body::SilverOre => 1000.0,
530            Body::GoldOre => 1000.0,
531            Body::ClayRocket | Body::GrenadeClay => 50.0,
532            Body::HaniwaSentry => 300.0,
533            Body::SeaLantern => 1000.0,
534            Body::MinotaurAxe => 100000.0,
535            Body::Snowball => 7360.0, // 2.5 m diamter
536            Body::FishMeat => 10.0,
537            Body::BirdMeat => 10.0,
538            Body::SmallMeat => 10.0,
539            Body::Tornado | Body::FieryTornado => 50.0,
540            Body::Apple => 2.0,
541            Body::Hive => 2.0,
542            Body::Coconut => 2.0,
543            Body::GnarlingTotemRed | Body::GnarlingTotemGreen | Body::GnarlingTotemWhite => 100.0,
544            Body::IceBomb => 12298.0, // 2.5 m diamter but ice
545            Body::LaserBeam | Body::LaserBeamSmall => 80000.0,
546            Body::AdletSpear => 1.5,
547            Body::AdletTrap => 10.0,
548            Body::Mine => 100.0,
549            Body::HarlequinDagger => 1.5,
550            Body::BorealTrap => 10.0,
551            Body::LightningBolt | Body::SpearIcicle => 20000.0,
552            Body::Portal | Body::PortalActive => 10., // I dont know really
553        };
554
555        Mass(m)
556    }
557
558    pub fn dimensions(&self) -> Vec3<f32> {
559        match self {
560            Body::Arrow
561            | Body::ArrowSnake
562            | Body::MultiArrow
563            | Body::ArrowTurret
564            | Body::ArrowClay
565            | Body::BoltBesieger
566            | Body::Dart
567            | Body::HarlequinDagger
568            | Body::AdletSpear => Vec3::new(0.01, 0.8, 0.01),
569            Body::AdletTrap => Vec3::new(1.0, 0.6, 0.3),
570            Body::BoltFire | Body::PoisonBall => Vec3::new(0.1, 0.1, 0.1),
571            Body::SpectralSwordSmall => Vec3::new(0.2, 0.9, 0.1),
572            Body::SpectralSwordLarge => Vec3::new(0.2, 1.5, 0.1),
573            Body::Crossbow => Vec3::new(3.0, 3.0, 1.5),
574            Body::Flamethrower => Vec3::new(3.0, 3.0, 2.5),
575            Body::Lavathrower => Vec3::new(3.0, 3.0, 2.0),
576            Body::HaniwaSentry => Vec3::new(0.8, 0.8, 1.4),
577            Body::SeaLantern => Vec3::new(0.8, 0.8, 1.4),
578            Body::Snowball => Vec3::broadcast(2.5),
579            Body::Tornado | Body::FieryTornado => Vec3::new(2.0, 2.0, 3.4),
580            Body::TrainingDummy => Vec3::new(1.5, 1.5, 3.0),
581            Body::BorealTrap => Vec3::new(1.0, 0.6, 0.3),
582            Body::GnarlingTotemRed | Body::GnarlingTotemGreen | Body::GnarlingTotemWhite => {
583                Vec3::new(0.8, 0.8, 1.4)
584            },
585            Body::BarrelOrgan => Vec3::new(4.0, 2.0, 3.0),
586            Body::TerracottaStatue => Vec3::new(5.0, 5.0, 5.0),
587            Body::IceBomb => Vec3::broadcast(2.5),
588            Body::LaserBeam => Vec3::new(8.0, 8.0, 8.0),
589            Body::LaserBeamSmall => Vec3::new(1.0, 1.0, 1.0),
590            Body::Mine => Vec3::new(0.8, 0.8, 0.5),
591            Body::LightningBolt | Body::SpearIcicle => Vec3::new(1.0, 1.0, 1.0),
592            Body::FireRainDrop => Vec3::new(0.01, 0.01, 0.02),
593            Body::Pebble => Vec3::new(0.4, 0.4, 0.4),
594            Body::MinotaurAxe => Vec3::new(5.0, 5.0, 5.0),
595            // FIXME: this *must* be exhaustive match
596            _ => Vec3::broadcast(0.5),
597        }
598    }
599}