Compare commits

..

No commits in common. "18b1d6feae9c62c6deb46a8f43e840da806ccab8" and "ae3e9c9b481f61b00ce3ba56fbfe75cb025f96e8" have entirely different histories.

7 changed files with 40 additions and 90 deletions

View file

@ -1,14 +1,13 @@
# v0.12.0-dev
- Implement space suit thruster particle effects
- Implement space suit modding
- Add power-hungry thruster booster
- Add power-hungry optional thruster boost
- Add different flashlight power settings
- Add different light amplification settings
- Add reactor overload and shutdown
- Add battery damage when overusing thruster booster
- Add radiation damage
- Fix radio stations
# v0.11.1
- Added space suit thruster particle effects
- Fixed radio stations
# v0.11.0

View file

@ -115,7 +115,7 @@ A variety of relatively simple game systems should interact with each other to c
- [X] Augmented Reality
- [X] Flashlight intensity
- [ ] AI assistance systems
- [X] Thruster boost
- [ ] Thruster boost
- [ ] G-force dampeners
- [ ] Life support, material recyclers (air, water, etc)
- [ ] High energy particle shield?

View file

@ -21,13 +21,10 @@ use bevy_xpbd_3d::prelude::*;
pub const ENGINE_SPEED_FACTOR: f32 = 30.0;
const MAX_TRANSMISSION_DISTANCE: f32 = 100.0;
const MAX_INTERACT_DISTANCE: f32 = 50.0;
pub const POWER_DRAIN_THRUSTER: [f32; 3] = [3e6, 3e6, 0.0];
pub const THRUSTER_BOOST_FACTOR: [f64; 3] = [3.0, 3.0, 0.0];
pub const POWER_DRAIN_FLASHLIGHT: [f32; 4] = [200e3, 1500e3, 2500e3, 10000e3];
pub const FLASHLIGHT_INTENSITY: [f32; 4] = [10e6, 400e6, 2e9, 100e9]; // in lumens
pub const POWER_DRAIN_LIGHTAMP: [f32; 4] = [0.0, 200e3, 400e3, 1400e3];
pub const POWER_DRAIN_AR: f32 = 300e3;
pub const POWER_GAIN_REACTOR: [f32; 3] = [0.0, 2000e3, 10000e3];
const POWER_DRAIN_THRUSTER: [f32; 3] = [3e6, 3e6, 0.0];
const THRUSTER_BOOST_FACTOR: [f64; 3] = [3.0, 3.0, 0.0];
const POWER_DRAIN_FLASHLIGHT: [f32; 3] = [200e3, 1500e3, 2500e3];
pub const FLASHLIGHT_INTENSITY: [f32; 3] = [10e6, 400e6, 2e9]; // in lumens
pub struct ActorPlugin;
impl Plugin for ActorPlugin {
@ -71,7 +68,7 @@ pub enum DamageType {
Asphyxiation,
Depressurization,
//Poison,
Radiation,
//Radiation,
//Freeze,
//Burn,
}
@ -175,7 +172,6 @@ pub struct OrbitsJupiter;
#[derive(Component)]
pub struct LifeForm {
pub is_alive: bool,
pub is_radioactively_damaged: bool,
pub adrenaline: f32,
pub adrenaline_baseline: f32,
pub adrenaline_jolt: f32,
@ -184,7 +180,6 @@ impl Default for LifeForm {
fn default() -> Self {
Self {
is_alive: true,
is_radioactively_damaged: false,
adrenaline: 0.3,
adrenaline_baseline: 0.3,
adrenaline_jolt: 0.0,
@ -262,6 +257,7 @@ const SUIT_SIMPLE: Suit = Suit {
pub struct Battery {
pub power: f32, // Watt-seconds
pub capacity: f32, // Watt-seconds
pub reactor: f32, // Watt (production)
pub overloaded_recovering: bool,
}
@ -270,6 +266,7 @@ impl Default for Battery {
Self {
power: 10e3 * 3600.0,
capacity: 10e3 * 3600.0, // 10kWh
reactor: 2000e3, // 2MW
overloaded_recovering: false,
}
}
@ -298,8 +295,8 @@ pub fn update_power(
}
}
if settings.hud_active {
let mut hud_drain = POWER_DRAIN_AR;
hud_drain += POWER_DRAIN_LIGHTAMP[prefs.light_amp];
let mut hud_drain = 300e3; // 300kW
hud_drain += prefs.light_amp as f32 * 200e3; // 200kW per level
battery.power -= hud_drain * d;
if battery.power <= 0.0 {
power_down = true;
@ -330,8 +327,7 @@ pub fn update_power(
if power_down {
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::PowerDown));
}
let reactor = POWER_GAIN_REACTOR[settings.reactor_state];
battery.power = (battery.power + reactor * d).clamp(0.0, battery.capacity);
battery.power = (battery.power + battery.reactor * d).clamp(0.0, battery.capacity);
if battery.overloaded_recovering && battery.power > battery.capacity * 0.5 {
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::PowerUp));
battery.overloaded_recovering = false;
@ -341,12 +337,10 @@ pub fn update_power(
pub fn update_physics_lifeforms(
time: Res<Time>,
settings: Res<Settings>,
id2pos: Res<game::Id2Pos>,
mut query: Query<(&mut LifeForm, &mut HitPoints, &mut Suit, &LinearVelocity, &Position, Option<&Player>)>,
mut query: Query<(&mut LifeForm, &mut HitPoints, &mut Suit, &LinearVelocity)>,
) {
let d = time.delta_seconds();
for (mut lifeform, mut hp, mut suit, velocity, pos, player) in query.iter_mut() {
for (mut lifeform, mut hp, mut suit, velocity) in query.iter_mut() {
if lifeform.adrenaline_jolt.abs() > 1e-3 {
lifeform.adrenaline_jolt *= 0.99;
} else {
@ -359,20 +353,6 @@ pub fn update_physics_lifeforms(
lifeform.adrenaline =
(lifeform.adrenaline - 0.0001 + lifeform.adrenaline_jolt * 0.01).clamp(0.0, 1.0);
if player.is_some() {
lifeform.is_radioactively_damaged = if settings.reactor_state == 2 {
true
} else if let Some(pos_jupiter) = id2pos.0.get(cmd::ID_JUPITER) {
pos_jupiter.distance(pos.0) < 140_000_000.0
} else {
false
};
if lifeform.is_radioactively_damaged {
hp.damage += 0.3 * d;
hp.damagetype = DamageType::Radiation;
}
}
let mut oxygen_drain = nature::OXY_S;
let integr_threshold = 0.5;
if suit.integrity < integr_threshold {

View file

@ -331,14 +331,7 @@ fn handle_player_death(
duration: 1.0,
});
}
actor::DamageType::Radiation => {
settings.death_cause = "Acute radiation poisoning".to_string();
ew_effect.send(visual::SpawnEffectEvent {
class: visual::Effects::FadeIn(Color::BLACK),
duration: 4.0,
});
}
actor::DamageType::Unknown => {
_ => {
settings.death_cause = "Unknown".to_string();
ew_effect.send(visual::SpawnEffectEvent {
class: visual::Effects::FadeIn(css::MAROON.into()),

View file

@ -682,7 +682,8 @@ pub fn setup(
fn update_dashboard(
timer: ResMut<FPSUpdateTimer>,
mut q_dashboard: Query<(&mut Visibility, &Dashboard)>,
q_player: Query<(&actor::Suit, &actor::Battery, &actor::LifeForm), With<actor::Player>>,
id2pos: Res<game::Id2Pos>,
q_player: Query<(&actor::Suit, &actor::Battery, &Position), With<actor::Player>>,
settings: Res<Settings>,
) {
if !settings.hud_active || !timer.0.just_finished() {
@ -692,7 +693,7 @@ fn update_dashboard(
if player.is_err() {
return;
}
let (suit, battery, lifeform) = player.unwrap();
let (suit, battery, pos) = player.unwrap();
for (mut vis, icon) in &mut q_dashboard {
*vis = bool2vis(match icon {
@ -701,7 +702,13 @@ fn update_dashboard(
Dashboard::Battery => battery.overloaded_recovering,
Dashboard::RotationStabiliser => !settings.rotation_stabilizer_active,
Dashboard::CruiseControl => settings.cruise_control_active,
Dashboard::Radioactivity => lifeform.is_radioactively_damaged,
Dashboard::Radioactivity => {
if let Some(pos_jupiter) = id2pos.0.get(cmd::ID_JUPITER) {
pos_jupiter.distance(pos.0) < 140_000_000.0
} else {
false
}
}
});
}
}

View file

@ -69,7 +69,6 @@ pub const MENUDEF: &[(&str, MenuAction)] = &[
("", MenuAction::ModLightAmp),
("", MenuAction::ModFlashlightPower),
("", MenuAction::ModThrusterBoost),
("", MenuAction::ModReactor),
("", MenuAction::ToggleSound),
("", MenuAction::ToggleMusic),
("", MenuAction::ToggleCamera),
@ -87,7 +86,6 @@ pub enum MenuAction {
ModLightAmp,
ModFlashlightPower,
ModThrusterBoost,
ModReactor,
ToggleSound,
ToggleMusic,
ToggleCamera,
@ -488,39 +486,24 @@ pub fn update_menu(
}
MenuAction::ToggleAR => {
let onoff = bool2string(settings.hud_active);
let p = if settings.hud_active { actor::POWER_DRAIN_AR / 1e3 } else { 0.0 };
let kw = if p > 0.0 { format!(" ({p}kW)") } else { String::from("") };
text.sections[i].value = format!("Augmented Reality: {onoff}{kw} [TAB]\n");
text.sections[i].value = format!("Augmented Reality: {onoff} [TAB]\n");
}
MenuAction::ModLightAmp => {
let p = actor::POWER_DRAIN_LIGHTAMP[prefs.light_amp] / 1e3;
text.sections[i].value = format!("Light Amplification: {p}kW\n");
let n = prefs.light_amp;
text.sections[i].value = format!("Light Amplification: {n}/3\n");
}
MenuAction::ModFlashlightPower => {
let p = actor::POWER_DRAIN_FLASHLIGHT[prefs.flashlight_power] / 1e3;
text.sections[i].value = format!("Flashlight Power: {p}kW\n");
let n = prefs.flashlight_power + 1;
text.sections[i].value = format!("Flashlight Power: {n}/3\n");
}
MenuAction::ModThrusterBoost => {
let state = match prefs.thruster_boost {
0 => "For braking",
1 => "Always",
0 => "Only when slowing down",
1 => "MAX POWER",
2 => "Off",
_ => "ERROR",
};
let p = actor::POWER_DRAIN_THRUSTER[prefs.thruster_boost] / 1e3;
let kw = if p > 0.0 { format!(" ({p}kW)") } else { String::from("") };
text.sections[i].value = format!("Thruster Boost: {state}{kw}\n");
}
MenuAction::ModReactor => {
let state = match settings.reactor_state {
0 => "Off",
1 => "On",
2 => "OVERLOAD",
_ => "ERROR",
};
let p = actor::POWER_GAIN_REACTOR[settings.reactor_state] / 1e3;
let kw = if p > 0.0 { format!(" (+{p}kW)") } else { String::from("") };
text.sections[i].value = format!("Reactor: {state}{kw}\n");
text.sections[i].value = format!("Thruster Boost: {state}\n");
}
MenuAction::ChangeARAvatar => {
if let Some(ava) = hud::PLAYER_AR_AVATARS.get(settings.ar_avatar) {
@ -625,16 +608,14 @@ pub fn handle_input(
if prefs.light_amp > 3 {
prefs.light_amp = 0;
}
prefs.save();
ew_updateoverlays.send(hud::UpdateOverlayVisibility);
ew_updatemenu.send(UpdateMenuEvent);
}
MenuAction::ModFlashlightPower => {
prefs.flashlight_power += 1;
if prefs.flashlight_power > 3 {
if prefs.flashlight_power > 2 {
prefs.flashlight_power = 0;
}
prefs.save();
ew_game.send(GameEvent::UpdateFlashlight);
ew_updatemenu.send(UpdateMenuEvent);
}
@ -643,14 +624,6 @@ pub fn handle_input(
if prefs.thruster_boost > 2 {
prefs.thruster_boost = 0;
}
prefs.save();
ew_updatemenu.send(UpdateMenuEvent);
}
MenuAction::ModReactor => {
settings.reactor_state += 1;
if settings.reactor_state > 2 {
settings.reactor_state = 0;
}
ew_updatemenu.send(UpdateMenuEvent);
}
MenuAction::ToggleMusic => {

View file

@ -86,7 +86,6 @@ pub struct Settings {
pub chat_speed: f32,
pub ar_avatar: usize,
pub flashlight_active: bool,
pub reactor_state: usize,
pub hud_active: bool,
pub map_active: bool,
pub deathscreen_active: bool,
@ -223,7 +222,6 @@ impl Default for Settings {
chat_speed: DEFAULT_CHAT_SPEED,
ar_avatar: 0,
flashlight_active: false,
reactor_state: 1,
hud_active: true,
map_active: false,
deathscreen_active: false,
@ -577,7 +575,7 @@ pub fn load_prefs() -> Preferences {
println!("Loaded preferences from internal defaults");
}
prefs.source_file = path;
prefs.flashlight_power = prefs.flashlight_power.clamp(0, 3);
prefs.flashlight_power = prefs.flashlight_power.clamp(0, 2);
prefs.light_amp = prefs.light_amp.clamp(0, 3);
prefs.thruster_boost = prefs.thruster_boost.clamp(0, 2);
prefs