pub mod biped_large; pub mod bird_medium; pub mod bird_small; pub mod critter; pub mod dragon; pub mod fish_medium; pub mod fish_small; pub mod humanoid; pub mod object; pub mod quadruped_medium; pub mod quadruped_small; use crate::{ assets::{self, Asset}, npc::NpcKind, }; use specs::{Component, FlaggedStorage}; use specs_idvs::IDVStorage; use std::{fs::File, io::BufReader, sync::Arc}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[repr(u32)] pub enum Body { Humanoid(humanoid::Body) = 0, QuadrupedSmall(quadruped_small::Body) = 1, QuadrupedMedium(quadruped_medium::Body) = 2, BirdMedium(bird_medium::Body) = 3, FishMedium(fish_medium::Body) = 4, Dragon(dragon::Body) = 5, BirdSmall(bird_small::Body) = 6, FishSmall(fish_small::Body) = 7, BipedLarge(biped_large::Body) = 8, Object(object::Body) = 9, Critter(critter::Body) = 10, } /// Data representing data generic to the body together with per-species data. /// /// NOTE: Deliberately don't (yet?) implement serialize. #[derive(Clone, Debug, Deserialize)] pub struct BodyData { /// Shared metadata for this whole body type. pub body: BodyMeta, /// All the metadata for species with this body type. pub species: SpeciesData, } /// Metadata intended to be stored per-body, together with data intended to be /// stored for each species for each body. /// /// NOTE: Deliberately don't (yet?) implement serialize. #[derive(Clone, Debug, Deserialize)] pub struct AllBodies { pub humanoid: BodyData>, pub quadruped_small: BodyData>, pub quadruped_medium: BodyData>, pub bird_medium: BodyData>, pub biped_large: BodyData>, pub critter: BodyData>, } /// Can only retrieve body metadata by direct index. impl core::ops::Index for AllBodies { type Output = BodyMeta; fn index(&self, index: NpcKind) -> &Self::Output { match index { NpcKind::Humanoid => &self.humanoid.body, NpcKind::Pig => &self.quadruped_small.body, NpcKind::Wolf => &self.quadruped_medium.body, NpcKind::Duck => &self.bird_medium.body, NpcKind::Giant => &self.biped_large.body, NpcKind::Rat => &self.critter.body, } } } impl< BodyMeta: Send + Sync + for<'de> serde::Deserialize<'de>, SpeciesMeta: Send + Sync + for<'de> serde::Deserialize<'de>, > Asset for AllBodies { const ENDINGS: &'static [&'static str] = &["json"]; fn parse(buf_reader: BufReader) -> Result { serde_json::de::from_reader(buf_reader).map_err(|e| assets::Error::Internal(Arc::new(e))) } } impl Body { pub fn is_humanoid(&self) -> bool { match self { Body::Humanoid(_) => true, _ => false, } } // Note: this might need to be refined to something more complex for realistic // behavior with less cylindrical bodies (e.g. wolfs) pub fn radius(&self) -> f32 { // TODO: Improve these values (some might be reliant on more info in inner type) match self { Body::Humanoid(_) => 0.5, Body::QuadrupedSmall(_) => 0.6, Body::QuadrupedMedium(_) => 0.9, Body::Critter(_) => 0.5, Body::BirdMedium(_) => 0.5, Body::FishMedium(_) => 0.5, Body::Dragon(_) => 2.5, Body::BirdSmall(_) => 0.2, Body::FishSmall(_) => 0.2, Body::BipedLarge(_) => 1.0, Body::Object(_) => 0.3, } } } impl Component for Body { type Storage = FlaggedStorage>; }