2024-05-12 21:57:21 +00:00
|
|
|
// ▄████████▄ + ███ + ▄█████████ ███ +
|
|
|
|
// ███▀ ▀███ + + ███ ███▀ + ███ + +
|
|
|
|
// ███ + ███ ███ ███ █████████ ███ ███ ███ ███
|
|
|
|
// ███ +███ ███ ███ ███ ███▐██████ ███ ███ ███
|
|
|
|
// ███ + ███ ███+ ███ +███ ███ + ███ ███ + ███
|
|
|
|
// ███▄ ▄███ ███▄ ███ ███ + ███ + ███ ███▄ ███
|
|
|
|
// ▀████████▀ + ▀███████ ███▄ ███▄ ▀████ ▀███████
|
|
|
|
// + + + ███
|
|
|
|
// + ▀████████████████████████████████████████████████████▀
|
|
|
|
//
|
|
|
|
// This module handles player input, and coordinates interplay between other modules
|
|
|
|
|
|
|
|
use crate::prelude::*;
|
|
|
|
use bevy::prelude::*;
|
|
|
|
use bevy::math::DVec3;
|
2024-05-12 22:10:13 +00:00
|
|
|
use bevy::pbr::ExtendedMaterial;
|
2024-05-12 21:57:21 +00:00
|
|
|
use bevy::scene::SceneInstance;
|
|
|
|
use bevy_xpbd_3d::prelude::*;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
pub struct GamePlugin;
|
|
|
|
impl Plugin for GamePlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
app.add_systems(Update, handle_cheats);
|
2024-05-12 22:10:13 +00:00
|
|
|
app.add_systems(Update, debug);
|
2024-05-12 21:57:21 +00:00
|
|
|
app.add_systems(PreUpdate, handle_player_death);
|
|
|
|
app.add_systems(PostUpdate, update_id2pos);
|
|
|
|
app.insert_resource(Id2Pos(HashMap::new()));
|
|
|
|
app.add_event::<PlayerDiesEvent>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Event)] pub struct PlayerDiesEvent(pub actor::DamageType);
|
|
|
|
#[derive(Resource)] pub struct Id2Pos(pub HashMap<String, DVec3>);
|
|
|
|
|
|
|
|
fn handle_player_death(
|
|
|
|
mut cmd: Commands,
|
|
|
|
mut er_playerdies: EventReader<PlayerDiesEvent>,
|
|
|
|
q_scenes: Query<(Entity, &SceneInstance), With<world::DespawnOnPlayerDeath>>,
|
|
|
|
q_noscenes: Query<Entity, (With<world::DespawnOnPlayerDeath>, Without<SceneInstance>)>,
|
|
|
|
mut scene_spawner: ResMut<SceneSpawner>,
|
|
|
|
mut active_asteroids: ResMut<world::ActiveAsteroids>,
|
|
|
|
mut ew_effect: EventWriter<visual::SpawnEffectEvent>,
|
|
|
|
mut ew_deathscreen: EventWriter<menu::DeathScreenEvent>,
|
|
|
|
mut log: ResMut<hud::Log>,
|
|
|
|
mut settings: ResMut<Settings>,
|
|
|
|
) {
|
|
|
|
for death in er_playerdies.read() {
|
|
|
|
if settings.god_mode {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
settings.reset_player_settings();
|
|
|
|
active_asteroids.0.clear();
|
|
|
|
for entity in &q_noscenes {
|
|
|
|
cmd.entity(entity).despawn();
|
|
|
|
}
|
|
|
|
for (entity, sceneinstance) in &q_scenes {
|
|
|
|
cmd.entity(entity).despawn();
|
|
|
|
scene_spawner.despawn_instance(**sceneinstance);
|
|
|
|
}
|
|
|
|
log.clear();
|
|
|
|
|
|
|
|
match death.0 {
|
|
|
|
actor::DamageType::Mental => {
|
|
|
|
settings.death_cause = "Brain Damage".to_string();
|
|
|
|
ew_effect.send(visual::SpawnEffectEvent {
|
|
|
|
class: visual::Effects::FadeIn(Color::BLACK),
|
|
|
|
duration: 4.0,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
actor::DamageType::Asphyxiation => {
|
|
|
|
settings.death_cause = "Suffocation".to_string();
|
|
|
|
ew_effect.send(visual::SpawnEffectEvent {
|
|
|
|
class: visual::Effects::FadeIn(Color::BLACK),
|
|
|
|
duration: 1.0,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
actor::DamageType::Trauma => {
|
|
|
|
settings.death_cause = "Trauma".to_string();
|
|
|
|
ew_effect.send(visual::SpawnEffectEvent {
|
|
|
|
class: visual::Effects::FadeIn(Color::MAROON),
|
|
|
|
duration: 1.0,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
actor::DamageType::GForce => {
|
|
|
|
settings.death_cause = "Trauma from excessive g forces".to_string();
|
|
|
|
ew_effect.send(visual::SpawnEffectEvent {
|
|
|
|
class: visual::Effects::FadeIn(Color::MAROON),
|
|
|
|
duration: 1.0,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
settings.death_cause = "Unknown".to_string();
|
|
|
|
ew_effect.send(visual::SpawnEffectEvent {
|
|
|
|
class: visual::Effects::FadeIn(Color::MAROON),
|
|
|
|
duration: 1.0,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ew_deathscreen.send(menu::DeathScreenEvent::Show);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn handle_cheats(
|
|
|
|
key_input: Res<ButtonInput<KeyCode>>,
|
|
|
|
mut q_player: Query<(&Transform, &mut Position, &mut LinearVelocity), With<actor::PlayerCamera>>,
|
|
|
|
mut q_life: Query<(&mut actor::LifeForm, &mut actor::ExperiencesGForce), With<actor::Player>>,
|
|
|
|
q_target: Query<(&Transform, &Position, Option<&LinearVelocity>), (With<hud::IsTargeted>, Without<actor::PlayerCamera>)>,
|
|
|
|
mut ew_playerdies: EventWriter<PlayerDiesEvent>,
|
|
|
|
mut settings: ResMut<Settings>,
|
|
|
|
id2pos: Res<Id2Pos>,
|
|
|
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
|
|
|
) {
|
|
|
|
if q_player.is_empty() || q_life.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let (trans, mut pos, mut v) = q_player.get_single_mut().unwrap();
|
|
|
|
let (mut lifeform, mut gforce) = q_life.get_single_mut().unwrap();
|
|
|
|
let boost = if key_input.pressed(KeyCode::ShiftLeft) {
|
|
|
|
1e6
|
|
|
|
} else {
|
|
|
|
1e3
|
|
|
|
};
|
|
|
|
if key_input.just_pressed(settings.key_cheat_god_mode) {
|
|
|
|
settings.god_mode ^= true;
|
|
|
|
if settings.god_mode {
|
|
|
|
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::EnterVehicle));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !settings.god_mode && !settings.dev_mode {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if key_input.just_pressed(settings.key_cheat_stop) {
|
|
|
|
gforce.ignore_gforce_seconds = 1.0;
|
|
|
|
v.0 = DVec3::ZERO;
|
|
|
|
}
|
|
|
|
if key_input.pressed(settings.key_cheat_speed) {
|
|
|
|
gforce.ignore_gforce_seconds = 1.0;
|
|
|
|
v.0 += DVec3::from(trans.rotation * Vec3::new(0.0, 0.0, boost));
|
|
|
|
}
|
|
|
|
if key_input.pressed(settings.key_cheat_speed_backward) {
|
|
|
|
gforce.ignore_gforce_seconds = 1.0;
|
|
|
|
v.0 += DVec3::from(trans.rotation * Vec3::new(0.0, 0.0, -boost));
|
|
|
|
}
|
|
|
|
if key_input.just_pressed(settings.key_cheat_teleport) {
|
|
|
|
if let Ok((transform, target_pos, target_v)) = q_target.get_single() {
|
|
|
|
let offset: DVec3 = 4.0 * (**pos - **target_pos).normalize() * transform.scale.as_dvec3();
|
|
|
|
pos.0 = **target_pos + offset;
|
|
|
|
if let Some(target_v) = target_v {
|
|
|
|
*v = target_v.clone();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !settings.dev_mode {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if key_input.just_pressed(settings.key_cheat_pizza) {
|
|
|
|
if let Some(target) = id2pos.0.get(&"pizzeria".to_string()) {
|
|
|
|
pos.0 = *target + DVec3::new(-60.0, 0.0, 0.0);
|
|
|
|
gforce.ignore_gforce_seconds = 1.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if key_input.just_pressed(settings.key_cheat_farview1) {
|
|
|
|
if let Some(target) = id2pos.0.get(&"busstopclippy2".to_string()) {
|
|
|
|
pos.0 = *target + DVec3::new(0.0, -1000.0, 0.0);
|
|
|
|
gforce.ignore_gforce_seconds = 1.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if key_input.just_pressed(settings.key_cheat_farview2) {
|
|
|
|
if let Some(target) = id2pos.0.get(&"busstopclippy3".to_string()) {
|
|
|
|
pos.0 = *target + DVec3::new(0.0, -1000.0, 0.0);
|
|
|
|
gforce.ignore_gforce_seconds = 1.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if key_input.pressed(settings.key_cheat_adrenaline_zero) {
|
|
|
|
lifeform.adrenaline = 0.0;
|
|
|
|
}
|
|
|
|
if key_input.pressed(settings.key_cheat_adrenaline_mid) {
|
|
|
|
lifeform.adrenaline = 0.5;
|
|
|
|
}
|
|
|
|
if key_input.pressed(settings.key_cheat_adrenaline_max) {
|
|
|
|
lifeform.adrenaline = 1.0;
|
|
|
|
}
|
|
|
|
if key_input.just_pressed(settings.key_cheat_die) {
|
|
|
|
settings.god_mode = false;
|
|
|
|
ew_playerdies.send(PlayerDiesEvent(actor::DamageType::Trauma));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn update_id2pos(
|
|
|
|
mut id2pos: ResMut<Id2Pos>,
|
|
|
|
q_id: Query<(&Position, &actor::Identifier)>,
|
|
|
|
) {
|
|
|
|
id2pos.0.clear();
|
|
|
|
for (pos, id) in &q_id {
|
|
|
|
id2pos.0.insert(id.0.clone(), pos.0);
|
|
|
|
}
|
|
|
|
}
|
2024-05-12 22:10:13 +00:00
|
|
|
|
|
|
|
fn debug(
|
|
|
|
settings: Res<var::Settings>,
|
|
|
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut extended_materials: ResMut<Assets<ExtendedMaterial<StandardMaterial, load::AsteroidSurface>>>,
|
|
|
|
materials: Query<(Entity, Option<&Name>, &Handle<Mesh>)>,
|
|
|
|
) {
|
|
|
|
if settings.dev_mode && keyboard_input.pressed(KeyCode::KeyP) {
|
|
|
|
for (entity, _name, mesh) in &materials {
|
|
|
|
dbg!(mesh);
|
|
|
|
let mut entity = commands.entity(entity);
|
|
|
|
entity.remove::<Handle<StandardMaterial>>();
|
|
|
|
let material = extended_materials.add(load::AsteroidSurface::material());
|
|
|
|
entity.insert(material);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|