2024-01-08 20:43:58 -08:00

131 lines
3.0 KiB
Rust

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<Engine>,
pub steering: Option<Steering>,
pub space: outfitspace::syntax::OutfitSpace,
pub shield: Option<Shield>,
}
#[derive(Debug, Deserialize)]
pub struct Shield {
pub strength: Option<f32>,
pub generation: Option<f32>,
pub delay: Option<f32>,
// 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<SpriteHandle>,
/// 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<String, syntax::Outfit>;
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(());
}
}