1use crate::{make_case_elim, make_proj_elim};
2use rand::{seq::SliceRandom, thread_rng};
3use serde::{Deserialize, Serialize};
4
5make_proj_elim!(
6 body,
7 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
8 pub struct Body {
9 pub species: Species,
10 pub body_type: BodyType,
11 }
12);
13
14impl Body {
15 pub fn random() -> Self {
16 let mut rng = thread_rng();
17 let species = *ALL_SPECIES.choose(&mut rng).unwrap();
18 Self::random_with(&mut rng, &species)
19 }
20
21 #[inline]
22 pub fn random_with(rng: &mut impl rand::Rng, &species: &Species) -> Self {
23 let body_type = *ALL_BODY_TYPES.choose(rng).unwrap();
24 Self { species, body_type }
25 }
26}
27
28impl From<Body> for super::Body {
29 fn from(body: Body) -> Self { super::Body::BipedSmall(body) }
30}
31
32make_case_elim!(
33 species,
34 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
35 #[repr(u32)]
36 pub enum Species {
37 Gnome = 0,
38 Sahagin = 1,
39 Adlet = 2,
40 Gnarling = 3,
41 Mandragora = 4,
42 Kappa = 5,
43 Cactid = 6,
44 Gnoll = 7,
45 Haniwa = 8,
46 Myrmidon = 9,
47 Husk = 10,
48 Boreal = 11,
49 Bushly = 12,
50 Irrwurz = 13,
51 IronDwarf = 14,
52 Flamekeeper = 15,
53 ShamanicSpirit = 16,
54 Jiangshi = 17,
55 TreasureEgg = 18,
56 GnarlingChieftain = 19,
57 BloodmoonHeiress = 20,
58 Bloodservant = 21,
59 Harlequin = 22,
60 GoblinThug = 23,
61 GoblinChucker = 24,
62 GoblinRuffian = 25,
63 GreenLegoom = 26,
64 OchreLegoom = 27,
65 PurpleLegoom = 28,
66 RedLegoom = 29,
67 }
68);
69
70#[derive(Clone, Debug, Deserialize)]
74pub struct AllSpecies<SpeciesMeta> {
75 pub gnome: SpeciesMeta,
76 pub sahagin: SpeciesMeta,
77 pub adlet: SpeciesMeta,
78 pub gnarling: SpeciesMeta,
79 pub mandragora: SpeciesMeta,
80 pub kappa: SpeciesMeta,
81 pub cactid: SpeciesMeta,
82 pub gnoll: SpeciesMeta,
83 pub haniwa: SpeciesMeta,
84 pub myrmidon: SpeciesMeta,
85 pub husk: SpeciesMeta,
86 pub boreal: SpeciesMeta,
87 pub bushly: SpeciesMeta,
88 pub irrwurz: SpeciesMeta,
89 pub iron_dwarf: SpeciesMeta,
90 pub flamekeeper: SpeciesMeta,
91 pub shamanic_spirit: SpeciesMeta,
92 pub jiangshi: SpeciesMeta,
93 pub treasure_egg: SpeciesMeta,
94 pub gnarling_chieftain: SpeciesMeta,
95 pub bloodmoon_heiress: SpeciesMeta,
96 pub bloodservant: SpeciesMeta,
97 pub harlequin: SpeciesMeta,
98 pub goblin_thug: SpeciesMeta,
99 pub goblin_chucker: SpeciesMeta,
100 pub goblin_ruffian: SpeciesMeta,
101 pub green_legoom: SpeciesMeta,
102 pub ochre_legoom: SpeciesMeta,
103 pub purple_legoom: SpeciesMeta,
104 pub red_legoom: SpeciesMeta,
105}
106
107impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta> {
108 type Output = SpeciesMeta;
109
110 #[inline]
111 fn index(&self, &index: &'a Species) -> &Self::Output {
112 match index {
113 Species::Gnome => &self.gnome,
114 Species::Sahagin => &self.sahagin,
115 Species::Adlet => &self.adlet,
116 Species::Gnarling => &self.gnarling,
117 Species::Mandragora => &self.mandragora,
118 Species::Kappa => &self.kappa,
119 Species::Cactid => &self.cactid,
120 Species::Gnoll => &self.gnoll,
121 Species::Haniwa => &self.haniwa,
122 Species::Myrmidon => &self.myrmidon,
123 Species::Husk => &self.husk,
124 Species::Boreal => &self.boreal,
125 Species::Bushly => &self.bushly,
126 Species::Irrwurz => &self.irrwurz,
127 Species::IronDwarf => &self.iron_dwarf,
128 Species::Flamekeeper => &self.flamekeeper,
129 Species::ShamanicSpirit => &self.shamanic_spirit,
130 Species::Jiangshi => &self.jiangshi,
131 Species::TreasureEgg => &self.treasure_egg,
132 Species::GnarlingChieftain => &self.gnarling_chieftain,
133 Species::BloodmoonHeiress => &self.bloodmoon_heiress,
134 Species::Bloodservant => &self.bloodservant,
135 Species::Harlequin => &self.harlequin,
136 Species::GoblinThug => &self.goblin_thug,
137 Species::GoblinChucker => &self.goblin_chucker,
138 Species::GoblinRuffian => &self.goblin_ruffian,
139 Species::GreenLegoom => &self.green_legoom,
140 Species::OchreLegoom => &self.ochre_legoom,
141 Species::PurpleLegoom => &self.purple_legoom,
142 Species::RedLegoom => &self.red_legoom,
143 }
144 }
145}
146
147pub const ALL_SPECIES: [Species; 30] = [
148 Species::Gnome,
149 Species::Sahagin,
150 Species::Adlet,
151 Species::Gnarling,
152 Species::Mandragora,
153 Species::Kappa,
154 Species::Cactid,
155 Species::Gnoll,
156 Species::Haniwa,
157 Species::Myrmidon,
158 Species::Husk,
159 Species::Boreal,
160 Species::Bushly,
161 Species::Irrwurz,
162 Species::IronDwarf,
163 Species::Flamekeeper,
164 Species::ShamanicSpirit,
165 Species::Jiangshi,
166 Species::TreasureEgg,
167 Species::GnarlingChieftain,
168 Species::BloodmoonHeiress,
169 Species::Bloodservant,
170 Species::Harlequin,
171 Species::GoblinThug,
172 Species::GoblinChucker,
173 Species::GoblinRuffian,
174 Species::GreenLegoom,
175 Species::OchreLegoom,
176 Species::PurpleLegoom,
177 Species::RedLegoom,
178];
179
180impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
181 type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
182 type Item = Species;
183
184 fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
185}
186
187make_case_elim!(
188 body_type,
189 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
190 #[repr(u32)]
191 pub enum BodyType {
192 Female = 0,
193 Male = 1,
194 }
195);
196pub const ALL_BODY_TYPES: [BodyType; 2] = [BodyType::Female, BodyType::Male];