use std::collections::HashMap; use anyhow::{bail, Result}; use crate::{handle::SpriteHandle, Content, ContentBuildContext, OutfitHandle, OutfitSpace}; pub(crate) mod syntax { use crate::part::outfitspace; use serde::Deserialize; // Raw serde syntax structs. // These are never seen by code outside this crate. #[derive(Debug, Deserialize)] pub struct Outfit { pub engine: Option, pub steering: Option, pub space: outfitspace::syntax::OutfitSpace, pub shield: Option, } #[derive(Debug, Deserialize)] pub struct Shield { pub strength: Option, pub generation: Option, pub delay: Option, // more stats: permiability, shield armor, ramp, etc } #[derive(Debug, Deserialize)] pub struct Engine { pub thrust: f32, pub flare_sprite: String, } #[derive(Debug, Deserialize)] pub struct Steering { pub power: f32, } } /// Represents an outfit that may be attached to a ship. #[derive(Debug, Clone)] pub struct Outfit { /// How much space this outfit requires pub space: OutfitSpace, /// This outfit's handle pub handle: OutfitHandle, /// The name of this outfit pub name: String, /// How much engine thrust this outfit produces pub engine_thrust: f32, /// How much steering power this outfit provids pub steer_power: f32, /// The engine flare sprite this outfit creates. /// Its location and size is determined by a ship's /// engine points. pub engine_flare_sprite: Option, /// Shield hit points pub shield_strength: f32, /// Shield regeneration rate, per second pub shield_generation: f32, /// Wait this many seconds after taking damage before regenerating shields pub shield_delay: f32, } impl crate::Build for Outfit { type InputSyntaxType = HashMap; fn build( outfits: Self::InputSyntaxType, _build_context: &mut ContentBuildContext, content: &mut Content, ) -> Result<()> { for (outfit_name, outfit) in outfits { let handle = OutfitHandle { index: content.outfits.len(), }; let mut o = Self { handle, name: outfit_name.clone(), engine_thrust: 0.0, steer_power: 0.0, engine_flare_sprite: None, space: OutfitSpace::from(outfit.space), shield_delay: 0.0, shield_generation: 0.0, shield_strength: 0.0, }; // Engine stats if let Some(engine) = outfit.engine { let th = match content.sprite_index.get(&engine.flare_sprite) { None => bail!( "In outfit `{}`: flare sprite `{}` doesn't exist", outfit_name, engine.flare_sprite ), Some(t) => *t, }; o.engine_thrust = engine.thrust; o.engine_flare_sprite = Some(th); } // Steering stats if let Some(steer) = outfit.steering { o.steer_power = steer.power; } // Shield stats if let Some(shield) = outfit.shield { o.shield_delay = shield.delay.unwrap_or(0.0); o.shield_generation = shield.generation.unwrap_or(0.0); o.shield_strength = shield.strength.unwrap_or(0.0); } content.outfits.push(o); } return Ok(()); } }