API fixes
parent
855eb0680b
commit
308e380241
|
@ -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,
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue