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,
|
||||
handle_wants_maxrotation,
|
||||
handle_wants_maxvelocity,
|
||||
handle_gforce,
|
||||
));
|
||||
app.add_systems(Update, (
|
||||
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 PlayerDrivesThis; // Attached to the entered vehicle
|
||||
#[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 ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||
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() {
|
||||
if *entity1 == player || *entity2 == player {
|
||||
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Crash));
|
||||
|
@ -322,10 +339,6 @@ fn handle_collisions(
|
|||
|
||||
if player_maybe.is_some() {
|
||||
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 {
|
||||
actor.insert(actor::LifeForm::default());
|
||||
actor.insert(actor::ExperiencesGForce::default());
|
||||
actor.insert(actor::Suit {
|
||||
oxygen: state.oxygen,
|
||||
oxygen_max: nature::OXY_D,
|
||||
|
|
|
@ -29,7 +29,7 @@ actor 10 -30 20 MeteorAceGT
|
|||
relativeto player
|
||||
scale 5
|
||||
vehicle yes
|
||||
thrust 70 13.7 9.4 200000 20
|
||||
thrust 35 6.85 4.7 200000 20
|
||||
engine ion
|
||||
collider sphere 1.5
|
||||
camdistance 50
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use bevy::prelude::*;
|
||||
use crate::{settings, camera};
|
||||
use crate::{actor, camera, settings};
|
||||
|
||||
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(Update, spawn_effects);
|
||||
app.add_systems(Update, update_fadeblack);
|
||||
app.add_systems(Update, update_blackout);
|
||||
app.add_event::<SpawnEffectEvent>();
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +19,7 @@ pub enum Effects {
|
|||
FadeIn(Color),
|
||||
}
|
||||
|
||||
#[derive(Component)] pub struct BlackOutOverlay;
|
||||
#[derive(Component)] pub struct FadeBlack;
|
||||
#[derive(Component)]
|
||||
pub struct Effect {
|
||||
|
@ -32,12 +34,28 @@ pub struct SpawnEffectEvent {
|
|||
}
|
||||
|
||||
pub fn setup(
|
||||
mut commands: Commands,
|
||||
settings: Res<settings::Settings>,
|
||||
mut ew_effect: EventWriter<SpawnEffectEvent>,
|
||||
) {
|
||||
if !settings.dev_mode {
|
||||
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(
|
||||
|
@ -90,3 +108,15 @@ pub fn update_fadeblack(
|
|||
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>,
|
||||
time: Res<Time>,
|
||||
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>>,
|
||||
mut timer: ResMut<FPSUpdateTimer>,
|
||||
mut query: Query<&mut Text, With<GaugesText>>,
|
||||
|
@ -479,7 +479,7 @@ fn update(
|
|||
let q_camera_result = q_camera.get_single();
|
||||
let player = player.get_single();
|
||||
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();
|
||||
for mut text in &mut query {
|
||||
text.sections[3].value = format!("2524-03-12 03:02");
|
||||
|
@ -505,7 +505,8 @@ fn update(
|
|||
let adrenaline = lifeform.adrenaline * 990.0 + 10.0;
|
||||
text.sections[11].value = format!("{adrenaline:.0}pg/mL");
|
||||
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();
|
||||
text.sections[15].value = format!("{all_actors:.0}");
|
||||
let integrity = suit.integrity * 100.0;
|
||||
|
|
Loading…
Reference in a new issue