implement g-forces and passing out
This commit is contained in:
parent
7d655ca6c6
commit
a869a7704e
50
src/actor.rs
50
src/actor.rs
|
@ -18,6 +18,7 @@ impl Plugin for ActorPlugin {
|
||||||
update_physics_lifeforms,
|
update_physics_lifeforms,
|
||||||
handle_wants_maxrotation,
|
handle_wants_maxrotation,
|
||||||
handle_wants_maxvelocity,
|
handle_wants_maxvelocity,
|
||||||
|
handle_gforce,
|
||||||
));
|
));
|
||||||
app.add_systems(Update, (
|
app.add_systems(Update, (
|
||||||
handle_input,
|
handle_input,
|
||||||
|
@ -73,6 +74,22 @@ impl Default for HitPoints {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct ExperiencesGForce {
|
||||||
|
pub gforce: f32,
|
||||||
|
pub damage_threshold: f32,
|
||||||
|
pub blackout_threshold: f32,
|
||||||
|
pub blackout: f32,
|
||||||
|
pub last_linear_velocity: DVec3,
|
||||||
|
}
|
||||||
|
impl Default for ExperiencesGForce { fn default() -> Self { Self {
|
||||||
|
gforce: 0.0,
|
||||||
|
damage_threshold: 50.0,
|
||||||
|
blackout_threshold: 20.0,
|
||||||
|
blackout: 0.0,
|
||||||
|
last_linear_velocity: DVec3::splat(0.0),
|
||||||
|
}}}
|
||||||
|
|
||||||
#[derive(Component)] pub struct Player; // Attached to the suit of the player
|
#[derive(Component)] pub struct Player; // Attached to the suit of the player
|
||||||
#[derive(Component)] pub struct PlayerDrivesThis; // Attached to the entered vehicle
|
#[derive(Component)] pub struct PlayerDrivesThis; // Attached to the entered vehicle
|
||||||
#[derive(Component)] pub struct PlayerCamera; // Attached to the actor to use as point of view
|
#[derive(Component)] pub struct PlayerCamera; // Attached to the actor to use as point of view
|
||||||
|
@ -312,9 +329,9 @@ fn handle_collisions(
|
||||||
mut collision_event_reader: EventReader<CollisionStarted>,
|
mut collision_event_reader: EventReader<CollisionStarted>,
|
||||||
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
q_player: Query<(Entity, Option<&Player>), With<PlayerCamera>>,
|
q_player: Query<(Entity, Option<&Player>), With<PlayerCamera>>,
|
||||||
mut q_player_lifeform: Query<(&mut LifeForm, &mut Suit, &mut HitPoints), With<Player>>,
|
mut q_player_lifeform: Query<(&mut LifeForm, &mut Suit), With<Player>>,
|
||||||
) {
|
) {
|
||||||
if let (Ok((player, player_maybe)), Ok((mut lifeform, mut suit, mut hp))) = (q_player.get_single(), q_player_lifeform.get_single_mut()) {
|
if let (Ok((player, player_maybe)), Ok((mut lifeform, mut suit))) = (q_player.get_single(), q_player_lifeform.get_single_mut()) {
|
||||||
for CollisionStarted(entity1, entity2) in collision_event_reader.read() {
|
for CollisionStarted(entity1, entity2) in collision_event_reader.read() {
|
||||||
if *entity1 == player || *entity2 == player {
|
if *entity1 == player || *entity2 == player {
|
||||||
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Crash));
|
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Crash));
|
||||||
|
@ -322,10 +339,6 @@ fn handle_collisions(
|
||||||
|
|
||||||
if player_maybe.is_some() {
|
if player_maybe.is_some() {
|
||||||
suit.integrity -= 0.03;
|
suit.integrity -= 0.03;
|
||||||
hp.damage += 10.0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
hp.damage += 3.0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,3 +436,28 @@ fn handle_damage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_gforce(
|
||||||
|
time: Res<Time>,
|
||||||
|
mut q_actor: Query<(&LinearVelocity, &mut HitPoints, &mut ExperiencesGForce)>,
|
||||||
|
) {
|
||||||
|
let dt = time.delta_seconds();
|
||||||
|
let factor = 1.0 / dt / 9.81;
|
||||||
|
for (v, mut hp, mut gforce) in &mut q_actor {
|
||||||
|
gforce.gforce = factor * (v.0 - gforce.last_linear_velocity).length() as f32;
|
||||||
|
gforce.last_linear_velocity = v.0;
|
||||||
|
if gforce.gforce > gforce.damage_threshold {
|
||||||
|
hp.damage += (gforce.gforce - gforce.damage_threshold).powf(2.0) / 3000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if gforce.blackout > 0.0001 {
|
||||||
|
gforce.blackout *= 0.998;
|
||||||
|
}
|
||||||
|
else if gforce.blackout > 0.0 {
|
||||||
|
gforce.blackout = 0.0;
|
||||||
|
}
|
||||||
|
if gforce.gforce > gforce.blackout_threshold {
|
||||||
|
gforce.blackout += (gforce.gforce - gforce.blackout_threshold).powf(2.0) / 300000.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -651,6 +651,7 @@ fn spawn_entities(
|
||||||
}
|
}
|
||||||
if state.is_lifeform {
|
if state.is_lifeform {
|
||||||
actor.insert(actor::LifeForm::default());
|
actor.insert(actor::LifeForm::default());
|
||||||
|
actor.insert(actor::ExperiencesGForce::default());
|
||||||
actor.insert(actor::Suit {
|
actor.insert(actor::Suit {
|
||||||
oxygen: state.oxygen,
|
oxygen: state.oxygen,
|
||||||
oxygen_max: nature::OXY_D,
|
oxygen_max: nature::OXY_D,
|
||||||
|
|
|
@ -29,7 +29,7 @@ actor 10 -30 20 MeteorAceGT
|
||||||
relativeto player
|
relativeto player
|
||||||
scale 5
|
scale 5
|
||||||
vehicle yes
|
vehicle yes
|
||||||
thrust 70 13.7 9.4 200000 20
|
thrust 35 6.85 4.7 200000 20
|
||||||
engine ion
|
engine ion
|
||||||
collider sphere 1.5
|
collider sphere 1.5
|
||||||
camdistance 50
|
camdistance 50
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use crate::{settings, camera};
|
use crate::{actor, camera, settings};
|
||||||
|
|
||||||
pub struct EffectsPlugin;
|
pub struct EffectsPlugin;
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ impl Plugin for EffectsPlugin {
|
||||||
app.add_systems(Startup, spawn_effects.after(setup).after(camera::setup_camera));
|
app.add_systems(Startup, spawn_effects.after(setup).after(camera::setup_camera));
|
||||||
app.add_systems(Update, spawn_effects);
|
app.add_systems(Update, spawn_effects);
|
||||||
app.add_systems(Update, update_fadeblack);
|
app.add_systems(Update, update_fadeblack);
|
||||||
|
app.add_systems(Update, update_blackout);
|
||||||
app.add_event::<SpawnEffectEvent>();
|
app.add_event::<SpawnEffectEvent>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +19,7 @@ pub enum Effects {
|
||||||
FadeIn(Color),
|
FadeIn(Color),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component)] pub struct BlackOutOverlay;
|
||||||
#[derive(Component)] pub struct FadeBlack;
|
#[derive(Component)] pub struct FadeBlack;
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct Effect {
|
pub struct Effect {
|
||||||
|
@ -32,12 +34,28 @@ pub struct SpawnEffectEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(
|
pub fn setup(
|
||||||
|
mut commands: Commands,
|
||||||
settings: Res<settings::Settings>,
|
settings: Res<settings::Settings>,
|
||||||
mut ew_effect: EventWriter<SpawnEffectEvent>,
|
mut ew_effect: EventWriter<SpawnEffectEvent>,
|
||||||
) {
|
) {
|
||||||
if !settings.dev_mode {
|
if !settings.dev_mode {
|
||||||
ew_effect.send(SpawnEffectEvent { class: Effects::FadeIn(Color::BLACK), duration: 4.0 });
|
ew_effect.send(SpawnEffectEvent { class: Effects::FadeIn(Color::BLACK), duration: 4.0 });
|
||||||
}
|
}
|
||||||
|
commands.spawn((
|
||||||
|
BlackOutOverlay,
|
||||||
|
NodeBundle {
|
||||||
|
style: Style {
|
||||||
|
width: Val::Vw(100.0),
|
||||||
|
height: Val::Vh(100.0),
|
||||||
|
position_type: PositionType::Absolute,
|
||||||
|
top: Val::Px(0.0),
|
||||||
|
left: Val::Px(0.0),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
background_color: Color::BLACK.into(),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_effects(
|
pub fn spawn_effects(
|
||||||
|
@ -90,3 +108,15 @@ pub fn update_fadeblack(
|
||||||
bgcolor.0.set_a(alpha as f32);
|
bgcolor.0.set_a(alpha as f32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_blackout(
|
||||||
|
mut q_effect: Query<&mut BackgroundColor, With<BlackOutOverlay>>,
|
||||||
|
q_player: Query<&actor::ExperiencesGForce, With<actor::Player>>
|
||||||
|
) {
|
||||||
|
if let (Ok(gforce), Ok(mut bgcolor)) = (q_player.get_single(), q_effect.get_single_mut()) {
|
||||||
|
let threshold = 0.3;
|
||||||
|
let factor = 1.0 / (1.0 - threshold);
|
||||||
|
let alpha = (factor * (gforce.blackout - threshold)).clamp(0.0, 1.0);
|
||||||
|
bgcolor.0.set_a(alpha as f32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -464,7 +464,7 @@ fn update(
|
||||||
diagnostics: Res<DiagnosticsStore>,
|
diagnostics: Res<DiagnosticsStore>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut log: ResMut<Log>,
|
mut log: ResMut<Log>,
|
||||||
player: Query<(&actor::HitPoints, &actor::Suit, &actor::LifeForm), With<actor::Player>>,
|
player: Query<(&actor::HitPoints, &actor::Suit, &actor::LifeForm, &actor::ExperiencesGForce), With<actor::Player>>,
|
||||||
q_camera: Query<(&Position, &LinearVelocity), With<actor::PlayerCamera>>,
|
q_camera: Query<(&Position, &LinearVelocity), With<actor::PlayerCamera>>,
|
||||||
mut timer: ResMut<FPSUpdateTimer>,
|
mut timer: ResMut<FPSUpdateTimer>,
|
||||||
mut query: Query<&mut Text, With<GaugesText>>,
|
mut query: Query<&mut Text, With<GaugesText>>,
|
||||||
|
@ -479,7 +479,7 @@ fn update(
|
||||||
let q_camera_result = q_camera.get_single();
|
let q_camera_result = q_camera.get_single();
|
||||||
let player = player.get_single();
|
let player = player.get_single();
|
||||||
if player.is_ok() && q_camera_result.is_ok() {
|
if player.is_ok() && q_camera_result.is_ok() {
|
||||||
let (hp, suit, lifeform) = player.unwrap();
|
let (hp, suit, lifeform, gforce) = player.unwrap();
|
||||||
let (pos, cam_v) = q_camera_result.unwrap();
|
let (pos, cam_v) = q_camera_result.unwrap();
|
||||||
for mut text in &mut query {
|
for mut text in &mut query {
|
||||||
text.sections[3].value = format!("2524-03-12 03:02");
|
text.sections[3].value = format!("2524-03-12 03:02");
|
||||||
|
@ -505,7 +505,8 @@ fn update(
|
||||||
let adrenaline = lifeform.adrenaline * 990.0 + 10.0;
|
let adrenaline = lifeform.adrenaline * 990.0 + 10.0;
|
||||||
text.sections[11].value = format!("{adrenaline:.0}pg/mL");
|
text.sections[11].value = format!("{adrenaline:.0}pg/mL");
|
||||||
let vitals = 100.0 * hp.current / hp.max;
|
let vitals = 100.0 * hp.current / hp.max;
|
||||||
text.sections[13].value = format!("{vitals:.0}%");
|
let gforce = gforce.gforce;
|
||||||
|
text.sections[13].value = format!("{vitals:.0}% [{gforce}g]");
|
||||||
let all_actors = query_all_actors.iter().len();
|
let all_actors = query_all_actors.iter().len();
|
||||||
text.sections[15].value = format!("{all_actors:.0}");
|
text.sections[15].value = format!("{all_actors:.0}");
|
||||||
let integrity = suit.integrity * 100.0;
|
let integrity = suit.integrity * 100.0;
|
||||||
|
|
Loading…
Reference in a new issue