Skip to main content

veloren_common/comp/body/
object.rs

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