veloren_common/comp/body/
item.rs
1use crate::{
2 comp::{
3 Density, Mass, Ori, ThrownItem,
4 item::{
5 Item, ItemKind, Utility,
6 armor::ArmorKind,
7 tool::{Tool, ToolKind},
8 },
9 },
10 consts::WATER_DENSITY,
11 make_case_elim,
12 util::Dir,
13};
14use rand::prelude::*;
15use serde::{Deserialize, Serialize};
16use std::f32::consts::PI;
17use vek::Vec3;
18
19make_case_elim!(
20 armor,
21 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
22 #[repr(u32)]
23 pub enum ItemArmorKind {
24 Shoulder = 0,
25 Chest = 1,
26 Belt = 2,
27 Hand = 3,
28 Pants = 4,
29 Foot = 5,
30 Back = 6,
31 Ring = 7,
32 Neck = 8,
33 Head = 9,
34 Tabard = 10,
35 Bag = 11,
36 }
37);
38
39make_case_elim!(
40 body,
41 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
42 #[repr(u32)]
43 pub enum Body {
44 Tool(tool: ToolKind) = 0,
45 ModularComponent = 1,
46 Lantern = 2,
47 Glider = 3,
48 Armor(armor: ItemArmorKind) = 4,
49 Utility = 5,
50 Consumable = 6,
51 Throwable = 7,
52 Ingredient = 8,
53 Coins = 9,
54 CoinPouch = 10,
55 Empty = 11,
56 Thrown(tool: ToolKind) = 12,
57 }
58);
59
60impl From<Body> for super::Body {
61 fn from(body: Body) -> Self { super::Body::Item(body) }
62}
63
64impl From<&Item> for Body {
65 fn from(item: &Item) -> Self {
66 match &*item.kind() {
67 ItemKind::Tool(Tool { kind, .. }) => Body::Tool(*kind),
68 ItemKind::ModularComponent(_) => Body::ModularComponent,
69 ItemKind::Lantern(_) => Body::Lantern,
70 ItemKind::Glider => Body::Glider,
71 ItemKind::Armor(armor) => match armor.kind {
72 ArmorKind::Shoulder => Body::Armor(ItemArmorKind::Shoulder),
73 ArmorKind::Chest => Body::Armor(ItemArmorKind::Chest),
74 ArmorKind::Belt => Body::Armor(ItemArmorKind::Belt),
75 ArmorKind::Hand => Body::Armor(ItemArmorKind::Hand),
76 ArmorKind::Pants => Body::Armor(ItemArmorKind::Pants),
77 ArmorKind::Foot => Body::Armor(ItemArmorKind::Foot),
78 ArmorKind::Back => Body::Armor(ItemArmorKind::Back),
79 ArmorKind::Backpack => Body::Armor(ItemArmorKind::Back),
80 ArmorKind::Ring => Body::Armor(ItemArmorKind::Ring),
81 ArmorKind::Neck => Body::Armor(ItemArmorKind::Neck),
82 ArmorKind::Head => Body::Armor(ItemArmorKind::Head),
83 ArmorKind::Tabard => Body::Armor(ItemArmorKind::Tabard),
84 ArmorKind::Bag => Body::Armor(ItemArmorKind::Bag),
85 },
86 ItemKind::Utility { kind, .. } => match kind {
87 Utility::Coins => {
88 if item.amount() > 100 {
89 Body::CoinPouch
90 } else {
91 Body::Coins
92 }
93 },
94 _ => Body::Utility,
95 },
96 ItemKind::Consumable { .. } => Body::Consumable,
97 ItemKind::Ingredient { .. } => Body::Ingredient,
98 _ => Body::Empty,
99 }
100 }
101}
102
103impl From<&ThrownItem> for Body {
104 fn from(thrown_item: &ThrownItem) -> Self {
105 match &*thrown_item.0.kind() {
106 ItemKind::Tool(Tool { kind, .. }) => Body::Thrown(*kind),
107 _ => Body::Empty,
108 }
109 }
110}
111
112impl Body {
113 pub fn to_string(self) -> &'static str {
114 match self {
115 Body::Tool(_) => "tool",
116 Body::ModularComponent => "modular_component",
117 Body::Lantern => "lantern",
118 Body::Glider => "glider",
119 Body::Armor(_) => "armor",
120 Body::Utility => "utility",
121 Body::Consumable => "consumable",
122 Body::Throwable => "throwable",
123 Body::Ingredient => "ingredient",
124 Body::Coins => "coins",
125 Body::CoinPouch => "coin_pouch",
126 Body::Empty => "empty",
127 Body::Thrown(_) => "thrown",
128 }
129 }
130
131 pub fn density(&self) -> Density { Density(1.1 * WATER_DENSITY) }
132
133 pub fn mass(&self) -> Mass { Mass(2.0) }
134
135 pub fn dimensions(&self) -> Vec3<f32> { Vec3::new(0.0, 0.1, 0.0) }
136
137 pub fn orientation(&self, rng: &mut impl Rng) -> Ori {
138 let random = rng.gen_range(-1.0..1.0f32);
139 let default = Ori::default();
140 match self {
141 Body::Tool(_) | Body::Thrown(_) => default
142 .pitched_down(PI / 2.0)
143 .yawed_left(PI / 2.0)
144 .pitched_towards(
145 Dir::from_unnormalized(Vec3::new(
146 random,
147 rng.gen_range(-1.0..1.0f32),
148 rng.gen_range(-1.0..1.0f32),
149 ))
150 .unwrap_or_default(),
151 ),
152
153 Body::Armor(ItemArmorKind::Neck | ItemArmorKind::Back | ItemArmorKind::Tabard) => {
154 default.yawed_left(random).pitched_down(PI / 2.0)
155 },
156 _ => default.yawed_left(random),
157 }
158 }
159}