Added outfit space calculations

master
Mark 2023-12-30 21:05:06 -08:00
parent 19fd1a91f2
commit 0de278cb03
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
11 changed files with 131 additions and 6 deletions

View File

@ -1,5 +1,7 @@
[gun."blaster"] [gun."blaster"]
space.weapon = 10
# Angle of fire cone # Angle of fire cone
# Smaller angle = more accurate # Smaller angle = more accurate
spread = 2 spread = 2

View File

@ -1,4 +1,7 @@
[outfit."plasma engines"] [outfit."plasma engines"]
space.engine = 20
engine.thrust = 100 engine.thrust = 100
engine.flare_texture = "flare::ion" engine.flare_texture = "flare::ion"
steering.power = 20 steering.power = 20

View File

@ -6,6 +6,11 @@ hull = 200
linear_drag = 0.2 linear_drag = 0.2
angular_drag = 0.2 angular_drag = 0.2
space.outfit = 200
space.engine = 50
space.weapon = 50
engines = [{ x = 0.0, y = -1.05, size = 50.0 }] engines = [{ x = 0.0, y = -1.05, size = 50.0 }]
guns = [{ x = 0.0, y = 1 }, { x = 0.1, y = 0.80 }, { x = -0.1, y = 0.80 }] guns = [{ x = 0.0, y = 1 }, { x = 0.1, y = 0.80 }, { x = -0.1, y = 0.80 }]

View File

@ -18,7 +18,9 @@ use toml;
use walkdir::WalkDir; use walkdir::WalkDir;
pub use handle::{FactionHandle, TextureHandle}; pub use handle::{FactionHandle, TextureHandle};
pub use part::{EnginePoint, Faction, Gun, GunPoint, Outfit, Relationship, Ship, System, Texture}; pub use part::{
EnginePoint, Faction, Gun, GunPoint, Outfit, OutfitSpace, Relationship, Ship, System, Texture,
};
mod syntax { mod syntax {
use anyhow::{bail, Result}; use anyhow::{bail, Result};

View File

@ -5,7 +5,10 @@ use cgmath::Deg;
use crate::{handle::TextureHandle, Content}; use crate::{handle::TextureHandle, Content};
use super::OutfitSpace;
pub(crate) mod syntax { pub(crate) mod syntax {
use super::super::shared;
use serde::Deserialize; use serde::Deserialize;
// Raw serde syntax structs. // Raw serde syntax structs.
// These are never seen by code outside this crate. // These are never seen by code outside this crate.
@ -16,6 +19,7 @@ pub(crate) mod syntax {
pub spread: f32, pub spread: f32,
pub rate: f32, pub rate: f32,
pub rate_rng: f32, pub rate_rng: f32,
pub space: shared::syntax::OutfitSpace,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -53,6 +57,9 @@ pub struct Gun {
/// Random variation of projectile delay, in seconds. /// Random variation of projectile delay, in seconds.
/// Each shot waits (rate += rate_rng). /// Each shot waits (rate += rate_rng).
pub rate_rng: f32, pub rate_rng: f32,
/// How much space this gun uses
pub space: OutfitSpace,
} }
/// Represents a projectile that a [`Gun`] produces. /// Represents a projectile that a [`Gun`] produces.
@ -98,6 +105,7 @@ impl crate::Build for Gun {
ct.guns.push(Self { ct.guns.push(Self {
name: gun_name, name: gun_name,
space: gun.space.into(),
spread: Deg(gun.spread), spread: Deg(gun.spread),
rate: gun.rate, rate: gun.rate,
rate_rng: gun.rate_rng, rate_rng: gun.rate_rng,

View File

@ -3,6 +3,7 @@
pub mod faction; pub mod faction;
pub mod gun; pub mod gun;
pub mod outfit; pub mod outfit;
mod shared;
pub mod ship; pub mod ship;
pub mod system; pub mod system;
pub mod texture; pub mod texture;
@ -10,6 +11,7 @@ pub mod texture;
pub use faction::{Faction, Relationship}; pub use faction::{Faction, Relationship};
pub use gun::{Gun, Projectile}; pub use gun::{Gun, Projectile};
pub use outfit::Outfit; pub use outfit::Outfit;
pub use shared::OutfitSpace;
pub use ship::{EnginePoint, GunPoint, Ship}; pub use ship::{EnginePoint, GunPoint, Ship};
pub use system::{Object, System}; pub use system::{Object, System};
pub use texture::Texture; pub use texture::Texture;

View File

@ -4,7 +4,10 @@ use anyhow::{bail, Result};
use crate::{handle::TextureHandle, Content}; use crate::{handle::TextureHandle, Content};
use super::OutfitSpace;
pub(crate) mod syntax { pub(crate) mod syntax {
use super::super::shared;
use serde::Deserialize; use serde::Deserialize;
// Raw serde syntax structs. // Raw serde syntax structs.
// These are never seen by code outside this crate. // These are never seen by code outside this crate.
@ -13,6 +16,7 @@ pub(crate) mod syntax {
pub struct Outfit { pub struct Outfit {
pub engine: Option<Engine>, pub engine: Option<Engine>,
pub steering: Option<Steering>, pub steering: Option<Steering>,
pub space: shared::syntax::OutfitSpace,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -43,6 +47,9 @@ pub struct Outfit {
/// Its location and size is determined by a ship's /// Its location and size is determined by a ship's
/// engine points. /// engine points.
pub engine_flare_texture: Option<TextureHandle>, pub engine_flare_texture: Option<TextureHandle>,
/// How much space this outfit requires
pub space: OutfitSpace,
} }
impl crate::Build for Outfit { impl crate::Build for Outfit {
@ -55,6 +62,7 @@ impl crate::Build for Outfit {
engine_thrust: 0.0, engine_thrust: 0.0,
steer_power: 0.0, steer_power: 0.0,
engine_flare_texture: None, engine_flare_texture: None,
space: OutfitSpace::from(outfit.space),
}; };
// Engine stats // Engine stats

View File

@ -0,0 +1,67 @@
pub(crate) mod syntax {
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct OutfitSpace {
pub outfit: Option<u32>,
pub weapon: Option<u32>,
pub engine: Option<u32>,
}
}
/// Represents outfit space, either that available in a ship
/// or that used by an outfit.
#[derive(Debug, Clone, Copy)]
pub struct OutfitSpace {
/// Total available outfit space.
/// This should be greater than weapon and engine.
pub outfit: u32,
/// Space for weapons
pub weapon: u32,
/// Space for engine
pub engine: u32,
}
impl OutfitSpace {
/// Make a new, zero OutfitSpace
pub fn new() -> Self {
Self {
outfit: 0,
weapon: 0,
engine: 0,
}
}
/// Does this outfit contain `smaller`?
pub fn can_contain(&self, smaller: Self) -> bool {
self.outfit >= (smaller.outfit + smaller.weapon + smaller.engine)
&& self.weapon >= smaller.weapon
&& self.engine >= smaller.engine
}
/// Free outfit space
pub fn free(&mut self, rhs: &Self) {
self.outfit += rhs.outfit + rhs.weapon + rhs.engine;
self.weapon += rhs.weapon;
self.engine += rhs.engine;
}
/// Occupy outfit space
pub fn occupy(&mut self, rhs: &Self) {
self.outfit -= rhs.outfit + rhs.weapon + rhs.engine;
self.weapon -= rhs.weapon;
self.engine -= rhs.engine;
}
}
impl From<syntax::OutfitSpace> for OutfitSpace {
fn from(value: syntax::OutfitSpace) -> Self {
Self {
outfit: value.outfit.unwrap_or(0),
engine: value.engine.unwrap_or(0),
weapon: value.weapon.unwrap_or(0),
}
}
}

View File

@ -6,8 +6,12 @@ use nalgebra::{point, Point};
use crate::{handle::TextureHandle, Content}; use crate::{handle::TextureHandle, Content};
use super::OutfitSpace;
pub(crate) mod syntax { pub(crate) mod syntax {
use super::super::shared;
use serde::Deserialize; use serde::Deserialize;
// Raw serde syntax structs. // Raw serde syntax structs.
// These are never seen by code outside this crate. // These are never seen by code outside this crate.
@ -22,6 +26,7 @@ pub(crate) mod syntax {
pub collision: Collision, pub collision: Collision,
pub angular_drag: f32, pub angular_drag: f32,
pub linear_drag: f32, pub linear_drag: f32,
pub space: shared::syntax::OutfitSpace,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -86,6 +91,9 @@ pub struct Ship {
/// Reduction in velocity over time /// Reduction in velocity over time
pub linear_drag: f32, pub linear_drag: f32,
/// Outfit space in this ship
pub space: OutfitSpace,
} }
/// Collision shape for this ship /// Collision shape for this ship
@ -138,6 +146,7 @@ impl crate::Build for Ship {
name: ship_name, name: ship_name,
sprite_texture: th, sprite_texture: th,
mass: ship.mass, mass: ship.mass,
space: OutfitSpace::from(ship.space),
angular_drag: ship.angular_drag, angular_drag: ship.angular_drag,
linear_drag: ship.linear_drag, linear_drag: ship.linear_drag,
size, size,

View File

@ -53,7 +53,6 @@ impl Game {
let mut o2 = outfits::ShipOutfits::new(&ct.ships[0]); let mut o2 = outfits::ShipOutfits::new(&ct.ships[0]);
o2.add(ct.outfits[0].clone()); o2.add(ct.outfits[0].clone());
o2.add_gun(ct.guns[0].clone()); o2.add_gun(ct.guns[0].clone());
println!("{:?}", o2);
let h3 = physics.add_ship( let h3 = physics.add_ship(
&ct.ships[0], &ct.ships[0],
o2, o2,

View File

@ -1,5 +1,5 @@
use cgmath::{Deg, Point3}; use cgmath::{Deg, Point3};
use content::TextureHandle; use content::{OutfitSpace, TextureHandle};
use crate::{content, render::SubSprite}; use crate::{content, render::SubSprite};
@ -67,6 +67,9 @@ impl OutfitStatSum {
#[derive(Debug)] #[derive(Debug)]
pub struct ShipOutfits { pub struct ShipOutfits {
pub stats: OutfitStatSum, pub stats: OutfitStatSum,
pub total_space: OutfitSpace,
available_space: OutfitSpace,
outfits: Vec<content::Outfit>, outfits: Vec<content::Outfit>,
guns: Vec<ShipGun>, guns: Vec<ShipGun>,
enginepoints: Vec<content::EnginePoint>, enginepoints: Vec<content::EnginePoint>,
@ -83,16 +86,30 @@ impl<'a> ShipOutfits {
stats: OutfitStatSum::new(), stats: OutfitStatSum::new(),
outfits: Vec::new(), outfits: Vec::new(),
guns: Vec::new(), guns: Vec::new(),
available_space: content.space.clone(),
total_space: content.space.clone(),
enginepoints: content.engines.clone(), enginepoints: content.engines.clone(),
gunpoints: content.guns.clone(), gunpoints: content.guns.clone(),
engine_flare_sprites: vec![], engine_flare_sprites: vec![],
} }
} }
/// Does this outfit set contain the specified outfit?
pub fn contains_outfit(&self, o: &content::Outfit) -> bool {
match self.outfits.iter().position(|x| x.name == o.name) {
Some(_) => true,
None => false,
}
}
/// Add an outfit to this ship. /// Add an outfit to this ship.
/// Returns true on success, and false on failure /// Returns true on success, and false on failure
/// TODO: failure reason enum /// TODO: failure reason enum
pub fn add(&mut self, o: content::Outfit) -> bool { pub fn add(&mut self, o: content::Outfit) -> bool {
if !self.available_space.can_contain(o.space) {
return false;
}
self.available_space.occupy(&o.space);
self.stats.add(&o); self.stats.add(&o);
self.outfits.push(o); self.outfits.push(o);
self.update_engine_flares(); self.update_engine_flares();
@ -100,10 +117,13 @@ impl<'a> ShipOutfits {
} }
/// TODO: is outfit in set? /// TODO: is outfit in set?
/// TODO: don't remove nonexisting outfit
pub fn remove(&mut self, o: content::Outfit) { pub fn remove(&mut self, o: content::Outfit) {
self.outfits let i = match self.outfits.iter().position(|x| x.name == o.name) {
.remove(self.outfits.iter().position(|x| x.name == o.name).unwrap()); Some(i) => i,
None => panic!("Removed non-existing outfit"),
};
self.available_space.free(&o.space);
self.outfits.remove(i);
self.stats.remove(&o); self.stats.remove(&o);
self.update_engine_flares(); self.update_engine_flares();
} }