Compare commits
No commits in common. "18b1d6feae9c62c6deb46a8f43e840da806ccab8" and "ae3e9c9b481f61b00ce3ba56fbfe75cb025f96e8" have entirely different histories.
18b1d6feae
...
ae3e9c9b48
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -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
|
||||
|
||||
|
|
|
@ -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?
|
||||
|
|
44
src/actor.rs
44
src/actor.rs
|
@ -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 {
|
||||
|
|
|
@ -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()),
|
||||
|
|
13
src/hud.rs
13
src/hud.rs
|
@ -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
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
45
src/menu.rs
45
src/menu.rs
|
@ -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 => {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue