API fixes

master
Mark 2024-02-16 13:25:50 -08:00
parent 855eb0680b
commit 308e380241
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
4 changed files with 164 additions and 61 deletions

View File

@ -5,6 +5,7 @@ use galactica_system::{
}; };
use galactica_util::to_degrees; use galactica_util::to_degrees;
use log::error; use log::error;
use nalgebra::Vector2;
use rapier2d::dynamics::RigidBody; use rapier2d::dynamics::RigidBody;
use rhai::{Array, CustomType, Dynamic, ImmutableString, TypeBuilder}; use rhai::{Array, CustomType, Dynamic, ImmutableString, TypeBuilder};
use std::sync::Arc; use std::sync::Arc;
@ -89,18 +90,16 @@ impl CustomType for ShipState {
.with_fn("content_index", |s: &mut Self| { .with_fn("content_index", |s: &mut Self| {
s.get_content().display_name.clone() s.get_content().display_name.clone()
}) })
.with_fn("thumbnail", |s: &mut Self| { .with_fn("thumbnail", |s: &mut Self| -> ImmutableString {
s.get_content().thumbnail.clone() s.get_content().thumbnail.index.clone().into()
}) })
.with_fn("landed_on", |s: &mut Self| s.landed_on()) .with_fn("landed_on", |s: &mut Self| s.landed_on())
.with_fn("get_shields", |s: &mut Self| { .with_fn("current_shields", |s: &mut Self| {
s.get_ship().get_data().get_shields() s.get_ship().get_data().get_shields()
}) })
.with_fn("get_total_shields", |s: &mut Self| { .with_fn("total_hull", |s: &mut Self| s.get_content().hull)
s.get_ship().get_data().get_outfits().get_total_shields() .with_fn("empty_mass", |s: &mut Self| s.get_content().mass)
}) .with_fn("current_hull", |s: &mut Self| {
.with_fn("get_total_hull", |s: &mut Self| s.get_content().hull)
.with_fn("get_hull", |s: &mut Self| {
s.get_ship().get_data().get_hull() s.get_ship().get_data().get_hull()
}) })
.with_fn("get_size", |s: &mut Self| s.get_content().size) .with_fn("get_size", |s: &mut Self| s.get_content().size)
@ -113,25 +112,132 @@ impl CustomType for ShipState {
let h = s.get_ship().get_data().get_faction(); let h = s.get_ship().get_data().get_faction();
let c = h.color; let c = h.color;
Color::new(c[0], c[1], c[2], 1.0) Color::new(c[0], c[1], c[2], 1.0)
})
//
// Stat getters
//
.with_fn("stat_thrust", |s: &mut Self| {
s.get_ship()
.get_data()
.get_outfits()
.get_stats()
.engine_thrust
})
.with_fn("stat_steer_power", |s: &mut Self| {
s.get_ship()
.get_data()
.get_outfits()
.get_stats()
.steer_power
})
.with_fn("stat_shield_strength", |s: &mut Self| {
s.get_ship()
.get_data()
.get_outfits()
.get_stats()
.shield_strength
})
.with_fn("stat_max_shield_generation", |s: &mut Self| {
s.get_ship()
.get_data()
.get_outfits()
.get_stats()
.shield_generation
}); });
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct OutfitState { pub struct OutfitState {
outfit: Arc<Outfit>, outfit: Option<Arc<Outfit>>,
} }
impl OutfitState {} impl OutfitState {
pub fn new(outfit: Arc<Outfit>) -> Self {
Self {
outfit: Some(outfit),
}
}
pub fn new_none() -> Self {
Self { outfit: None }
}
}
impl CustomType for OutfitState { impl CustomType for OutfitState {
fn build(mut builder: TypeBuilder<Self>) { fn build(mut builder: TypeBuilder<Self>) {
builder builder
.with_name("OutfitState") .with_name("OutfitState")
.with_fn("display_name", |s: &mut Self| s.outfit.display_name.clone()) .with_fn("is_some", |s: &mut Self| s.outfit.is_some())
.with_fn("index", |s: &mut Self| s.outfit.index.to_string()) .with_fn("display_name", |s: &mut Self| {
s.outfit
.as_ref()
.map(|x| x.display_name.clone())
.unwrap_or("".to_string())
})
.with_fn("desc", |s: &mut Self| {
s.outfit
.as_ref()
.map(|x| x.desc.clone())
.unwrap_or("".to_string())
})
.with_fn("index", |s: &mut Self| {
s.outfit
.as_ref()
.map(|x| x.index.to_string())
.unwrap_or("".to_string())
})
.with_fn("thumbnail", |s: &mut Self| { .with_fn("thumbnail", |s: &mut Self| {
s.outfit.thumbnail.index.to_string() s.outfit
.as_ref()
.map(|x| x.thumbnail.index.to_string())
.unwrap_or("".to_string())
})
//
// Stat getters
//
.with_fn("stat_thrust", |s: &mut Self| {
s.outfit
.as_ref()
.map(|x| x.stats.steer_power)
.unwrap_or(0.0)
})
.with_fn("stat_steer_power", |s: &mut Self| {
s.outfit
.as_ref()
.map(|x| x.stats.steer_power)
.unwrap_or(0.0)
})
.with_fn("stat_shield_strength", |s: &mut Self| {
s.outfit
.as_ref()
.map(|x| x.stats.shield_strength)
.unwrap_or(0.0)
})
.with_fn("stat_shield_generation", |s: &mut Self| {
s.outfit
.as_ref()
.map(|x| x.stats.shield_generation)
.unwrap_or(0.0)
})
.with_fn("stat_shield_delay", |s: &mut Self| {
s.outfit
.as_ref()
.map(|x| x.stats.shield_delay)
.unwrap_or(0.0)
})
.with_fn("stat_shield_dps", |s: &mut Self| {
s.outfit
.as_ref()
.map(|x| {
if x.gun.is_some() {
(1.0 / x.gun.as_ref().unwrap().rate)
* x.gun.as_ref().unwrap().projectile.damage
} else {
0.0
}
})
.unwrap_or(0.0)
}); });
} }
} }
@ -153,7 +259,7 @@ impl SystemObjectState {
.unwrap() .unwrap()
.outfitter .outfitter
{ {
a.push(Dynamic::from(OutfitState { outfit: o.clone() })); a.push(Dynamic::from(OutfitState::new(o.clone())));
} }
return a; return a;
} }
@ -234,6 +340,7 @@ impl CustomType for SystemObjectState {
pub struct State { pub struct State {
input: Arc<RenderInput>, input: Arc<RenderInput>,
window_aspect: f32, window_aspect: f32,
window_size: Vector2<u32>,
} }
// TODO: remove this // TODO: remove this
@ -245,6 +352,7 @@ impl State {
Self { Self {
input: input.clone(), input: input.clone(),
window_aspect: state.window_aspect, window_aspect: state.window_aspect,
window_size: Vector2::new(state.window_size.width, state.window_size.height),
} }
} }
@ -284,6 +392,12 @@ impl CustomType for State {
.with_fn("player_ship", Self::player_ship) .with_fn("player_ship", Self::player_ship)
.with_fn("ships", Self::ships) .with_fn("ships", Self::ships)
.with_fn("objects", Self::objects) .with_fn("objects", Self::objects)
.with_fn("window_aspect", |s: &mut Self| s.window_aspect); .with_fn("window_aspect", |s: &mut Self| s.window_aspect)
.with_fn("window_size", |s: &mut Self| {
UiVector::new(
s.window_size.x as f32 / s.input.ct.config.ui_scale,
s.window_size.y as f32 / s.input.ct.config.ui_scale,
)
});
} }
} }

View File

@ -1,6 +1,6 @@
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
use galactica_content::{ContentIndex, GunPoint, Outfit, OutfitSpace}; use galactica_content::{ContentIndex, GunPoint, Outfit, OutfitSpace, OutfitStats};
/// Possible outcomes when adding an outfit /// Possible outcomes when adding an outfit
pub enum OutfitAddResult { pub enum OutfitAddResult {
@ -61,12 +61,17 @@ pub struct OutfitSet {
/// if value is Some, this point is taken. /// if value is Some, this point is taken.
gun_points: HashMap<GunPoint, Option<Arc<Outfit>>>, gun_points: HashMap<GunPoint, Option<Arc<Outfit>>>,
/// Outfit values /// The combined stats of all outfits in this set.
/// This isn't strictly necessary, but we don't want to /// There are two things to note here:
/// re-compute this on each frame. /// First, shield_delay is always zero. That is handled
engine_thrust: f32, /// seperately, since it is different for every outfit.
steer_power: f32, /// Second, shield_generation represents the MAXIMUM POSSIBLE
shield_strength: f32, /// shield generation, after all delays have expired.
///
/// Note that this field isn't strictly necessary... we could compute stats
/// by iterating over the outfits in this set. We don't want to do this every
/// frame, though, so we keep track of the total sum here.
stats: OutfitStats,
/// All shield generators in this outfit set /// All shield generators in this outfit set
// These can't be summed into one value, since each has a // These can't be summed into one value, since each has a
@ -81,10 +86,7 @@ impl OutfitSet {
total_space: available_space, total_space: available_space,
used_space: OutfitSpace::new(), used_space: OutfitSpace::new(),
gun_points: gun_points.iter().map(|x| (x.clone(), None)).collect(), gun_points: gun_points.iter().map(|x| (x.clone(), None)).collect(),
stats: OutfitStats::zero(),
engine_thrust: 0.0,
steer_power: 0.0,
shield_strength: 0.0,
shield_generators: Vec::new(), shield_generators: Vec::new(),
} }
} }
@ -111,13 +113,12 @@ impl OutfitSet {
self.used_space += o.space; self.used_space += o.space;
self.engine_thrust += o.engine_thrust; self.stats.add(&o.stats);
self.steer_power += o.steer_power;
self.shield_strength += o.shield_strength;
self.shield_generators.push(ShieldGenerator { self.shield_generators.push(ShieldGenerator {
outfit: o.clone(), outfit: o.clone(),
delay: o.shield_delay, delay: o.stats.shield_delay,
generation: o.shield_generation, generation: o.stats.shield_generation,
}); });
if self.outfits.contains_key(&o.index) { if self.outfits.contains_key(&o.index) {
@ -143,9 +144,7 @@ impl OutfitSet {
self.used_space -= o.space; self.used_space -= o.space;
self.engine_thrust -= o.engine_thrust; self.stats.subtract(&o.stats);
self.steer_power -= o.steer_power;
self.shield_strength -= o.shield_strength;
{ {
// This index will exist, since we checked the hashmap // This index will exist, since we checked the hashmap
@ -183,11 +182,6 @@ impl OutfitSet {
self.shield_generators.iter() self.shield_generators.iter()
} }
/// Get maximum possible shield regen
pub fn get_max_shield_regen(&self) -> f32 {
self.shield_generators.iter().map(|x| x.generation).sum()
}
/// Get the outfit attached to the given gun point /// Get the outfit attached to the given gun point
/// Will panic if this gunpoint is not in this outfit set. /// Will panic if this gunpoint is not in this outfit set.
pub fn get_gun(&self, point: &GunPoint) -> Option<Arc<Outfit>> { pub fn get_gun(&self, point: &GunPoint) -> Option<Arc<Outfit>> {
@ -204,18 +198,13 @@ impl OutfitSet {
&self.used_space &self.used_space
} }
/// Total foward thrust /// Get the combined stats of all outfits in this set.
pub fn get_engine_thrust(&self) -> f32 { /// There are two things to note here:
self.engine_thrust /// First, shield_delay is always zero. That is handled
} /// seperately, since it is different for every outfit.
/// Second, shield_generation represents the MAXIMUM POSSIBLE
/// Total steer power /// shield generation, after all delays have expired.
pub fn get_steer_power(&self) -> f32 { pub fn get_stats(&self) -> &OutfitStats {
self.steer_power &self.stats
}
/// Total shield strength
pub fn get_total_shields(&self) -> f32 {
self.shield_strength
} }
} }

View File

@ -178,7 +178,7 @@ impl ShipData {
/// Add an outfit to this ship /// Add an outfit to this ship
pub fn add_outfit(&mut self, o: &Arc<Outfit>) -> super::OutfitAddResult { pub fn add_outfit(&mut self, o: &Arc<Outfit>) -> super::OutfitAddResult {
let r = self.outfits.add(o); let r = self.outfits.add(o);
self.shields = self.outfits.get_total_shields(); self.shields = self.outfits.get_stats().shield_strength;
return r; return r;
} }
@ -245,8 +245,8 @@ impl ShipData {
} }
// Regenerate shields // Regenerate shields
if self.shields != self.outfits.get_total_shields() { if self.shields != self.outfits.get_stats().shield_strength {
self.shields = self.outfits.get_total_shields(); self.shields = self.outfits.get_stats().shield_strength;
} }
} }
@ -260,12 +260,12 @@ impl ShipData {
// Regenerate shields // Regenerate shields
let time_since = self.last_hit.elapsed().as_secs_f32(); let time_since = self.last_hit.elapsed().as_secs_f32();
if self.shields != self.outfits.get_total_shields() { if self.shields != self.outfits.get_stats().shield_strength {
for g in self.outfits.iter_shield_generators() { for g in self.outfits.iter_shield_generators() {
if time_since >= g.delay { if time_since >= g.delay {
self.shields += g.generation * t; self.shields += g.generation * t;
if self.shields > self.outfits.get_total_shields() { if self.shields > self.outfits.get_stats().shield_strength {
self.shields = self.outfits.get_total_shields(); self.shields = self.outfits.get_stats().shield_strength;
break; break;
} }
} }

View File

@ -390,21 +390,21 @@ impl PhysShip {
if self.controls.thrust { if self.controls.thrust {
rigid_body.apply_impulse( rigid_body.apply_impulse(
vector![engine_force.x, engine_force.y] vector![engine_force.x, engine_force.y]
* self.data.get_outfits().get_engine_thrust(), * self.data.get_outfits().get_stats().engine_thrust,
true, true,
); );
} }
if self.controls.right { if self.controls.right {
rigid_body.apply_torque_impulse( rigid_body.apply_torque_impulse(
self.data.get_outfits().get_steer_power() * -100.0 * res.t, self.data.get_outfits().get_stats().steer_power * -100.0 * res.t,
true, true,
); );
} }
if self.controls.left { if self.controls.left {
rigid_body.apply_torque_impulse( rigid_body.apply_torque_impulse(
self.data.get_outfits().get_steer_power() * 100.0 * res.t, self.data.get_outfits().get_stats().steer_power * 100.0 * res.t,
true, true,
); );
} }