Fix input drops/repetitions (#69)
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
use super::TriggerMissile;
|
||||
use crate::{
|
||||
GameState,
|
||||
abilities::BuildExplosionSprite,
|
||||
abilities::{ExplodingProjectile, ExplodingProjectileSet},
|
||||
heads_database::HeadsDatabase,
|
||||
physics_layers::GameLayer,
|
||||
protocol::{GltfSceneRoot, PlaySound},
|
||||
utils::{commands::CommandExt, explosions::Explosion, global_observer, trail::Trail},
|
||||
utils::{global_observer, trail::Trail},
|
||||
};
|
||||
use avian3d::prelude::*;
|
||||
use bevy::prelude::*;
|
||||
@@ -23,7 +23,10 @@ struct MissileProjectile {
|
||||
}
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.add_systems(Update, shot_collision.run_if(in_state(GameState::Playing)));
|
||||
app.add_systems(
|
||||
FixedUpdate,
|
||||
shot_collision.in_set(ExplodingProjectileSet::Mark),
|
||||
);
|
||||
app.add_systems(
|
||||
FixedUpdate,
|
||||
(update, timeout).run_if(in_state(GameState::Playing)),
|
||||
@@ -141,20 +144,14 @@ fn shot_collision(
|
||||
continue;
|
||||
};
|
||||
|
||||
commands.trigger(PlaySound::MissileExplosion);
|
||||
|
||||
commands.entity(shot_entity).despawn();
|
||||
|
||||
commands.trigger(Explosion {
|
||||
commands.entity(shot_entity).insert(ExplodingProjectile {
|
||||
sound: PlaySound::MissileExplosion,
|
||||
damage,
|
||||
position: shot_pos,
|
||||
radius: 6.,
|
||||
});
|
||||
|
||||
commands.trigger_server(BuildExplosionSprite {
|
||||
pos: shot_pos,
|
||||
pixels_per_meter: 16.,
|
||||
time: 0.01,
|
||||
radius: 6.0,
|
||||
animation: true,
|
||||
anim_pixels_per_meter: 16.0,
|
||||
anim_time: 0.01,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,23 +6,27 @@ pub mod missile;
|
||||
pub mod thrown;
|
||||
|
||||
use crate::{
|
||||
GameState,
|
||||
aim::AimTarget,
|
||||
character::CharacterHierarchy,
|
||||
global_observer,
|
||||
heads::ActiveHeads,
|
||||
heads_database::HeadsDatabase,
|
||||
GameState, global_observer,
|
||||
loading_assets::GameAssets,
|
||||
physics_layers::GameLayer,
|
||||
player::{Player, PlayerBodyMesh},
|
||||
protocol::PlaySound,
|
||||
utils::{billboards::Billboard, sprite_3d_animation::AnimationTimer},
|
||||
};
|
||||
#[cfg(feature = "server")]
|
||||
use crate::{control::ControlState, head::ActiveHead};
|
||||
use crate::{
|
||||
aim::AimTarget,
|
||||
character::CharacterHierarchy,
|
||||
control::ControlState,
|
||||
head::ActiveHead,
|
||||
heads::ActiveHeads,
|
||||
heads_database::HeadsDatabase,
|
||||
player::{Player, PlayerBodyMesh},
|
||||
utils::explosions::Explosion,
|
||||
};
|
||||
use bevy::{pbr::NotShadowCaster, prelude::*};
|
||||
use bevy_sprite3d::{Sprite3dBuilder, Sprite3dParams};
|
||||
pub use healing::Healing;
|
||||
#[cfg(feature = "server")]
|
||||
use healing::HealingStateChanged;
|
||||
#[cfg(feature = "server")]
|
||||
use lightyear::prelude::input::native::ActionState;
|
||||
@@ -86,6 +90,7 @@ pub struct TriggerCurver(pub TriggerData);
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct TriggerStateRes {
|
||||
#[cfg(feature = "server")]
|
||||
next_trigger_timestamp: f32,
|
||||
active: bool,
|
||||
}
|
||||
@@ -96,6 +101,25 @@ impl TriggerStateRes {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
#[component(storage = "SparseSet")]
|
||||
#[allow(dead_code)]
|
||||
pub struct ExplodingProjectile {
|
||||
sound: PlaySound,
|
||||
damage: u32,
|
||||
position: Vec3,
|
||||
radius: f32,
|
||||
animation: bool,
|
||||
anim_pixels_per_meter: f32,
|
||||
anim_time: f32,
|
||||
}
|
||||
|
||||
#[derive(SystemSet, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum ExplodingProjectileSet {
|
||||
Mark,
|
||||
Explode,
|
||||
}
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.init_resource::<TriggerStateRes>();
|
||||
|
||||
@@ -106,20 +130,61 @@ pub fn plugin(app: &mut App) {
|
||||
app.add_plugins(healing::plugin);
|
||||
app.add_plugins(curver::plugin);
|
||||
|
||||
app.configure_sets(
|
||||
FixedUpdate,
|
||||
ExplodingProjectileSet::Explode
|
||||
.after(ExplodingProjectileSet::Mark)
|
||||
.run_if(in_state(GameState::Playing)),
|
||||
);
|
||||
|
||||
app.add_systems(OnEnter(GameState::Playing), setup);
|
||||
#[cfg(feature = "server")]
|
||||
app.add_systems(
|
||||
Update,
|
||||
(update, update_heal_ability).run_if(in_state(GameState::Playing)),
|
||||
FixedUpdate,
|
||||
(on_trigger_state, update, update_heal_ability)
|
||||
.chain()
|
||||
.run_if(in_state(GameState::Playing)),
|
||||
);
|
||||
#[cfg(feature = "server")]
|
||||
app.add_systems(
|
||||
FixedUpdate,
|
||||
on_trigger_state.run_if(in_state(GameState::Playing)),
|
||||
explode_projectiles.in_set(ExplodingProjectileSet::Explode),
|
||||
);
|
||||
|
||||
global_observer!(app, build_explosion_sprite);
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
fn explode_projectiles(mut commands: Commands, query: Query<(Entity, &ExplodingProjectile)>) {
|
||||
for (shot_entity, projectile) in query.iter() {
|
||||
if let Ok(mut entity) = commands.get_entity(shot_entity) {
|
||||
entity.try_despawn();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
commands.trigger(projectile.sound.clone());
|
||||
|
||||
commands.trigger(Explosion {
|
||||
damage: projectile.damage,
|
||||
position: projectile.position,
|
||||
//TODO: should be around 1 grid in distance
|
||||
radius: projectile.radius,
|
||||
});
|
||||
|
||||
//TODO: support different impact animations
|
||||
if projectile.animation {
|
||||
use crate::utils::commands::CommandExt;
|
||||
|
||||
commands.trigger_server(BuildExplosionSprite {
|
||||
pos: projectile.position,
|
||||
pixels_per_meter: projectile.anim_pixels_per_meter,
|
||||
time: projectile.anim_time,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
fn on_trigger_state(
|
||||
mut res: ResMut<TriggerStateRes>,
|
||||
@@ -136,6 +201,7 @@ fn on_trigger_state(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
fn update(
|
||||
mut res: ResMut<TriggerStateRes>,
|
||||
mut commands: Commands,
|
||||
@@ -201,6 +267,7 @@ fn update(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
fn update_heal_ability(
|
||||
res: Res<TriggerStateRes>,
|
||||
mut commands: Commands,
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
use super::TriggerThrow;
|
||||
use crate::{
|
||||
GameState,
|
||||
abilities::BuildExplosionSprite,
|
||||
abilities::{ExplodingProjectile, ExplodingProjectileSet},
|
||||
heads_database::HeadsDatabase,
|
||||
physics_layers::GameLayer,
|
||||
protocol::{GltfSceneRoot, PlaySound},
|
||||
utils::{
|
||||
auto_rotate::AutoRotation, commands::CommandExt, explosions::Explosion, global_observer,
|
||||
},
|
||||
utils::{auto_rotate::AutoRotation, global_observer},
|
||||
};
|
||||
use avian3d::prelude::*;
|
||||
use bevy::prelude::*;
|
||||
@@ -24,7 +21,10 @@ pub struct ThrownProjectile {
|
||||
}
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.add_systems(Update, shot_collision.run_if(in_state(GameState::Playing)));
|
||||
app.add_systems(
|
||||
FixedUpdate,
|
||||
shot_collision.in_set(ExplodingProjectileSet::Mark),
|
||||
);
|
||||
|
||||
global_observer!(app, on_trigger_thrown);
|
||||
}
|
||||
@@ -116,28 +116,14 @@ fn shot_collision(
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Ok(mut entity) = commands.get_entity(shot_entity) {
|
||||
entity.try_despawn();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
commands.trigger(PlaySound::ThrowHit);
|
||||
|
||||
commands.trigger(Explosion {
|
||||
commands.entity(shot_entity).insert(ExplodingProjectile {
|
||||
sound: PlaySound::ThrowHit,
|
||||
damage,
|
||||
position: shot_pos,
|
||||
//TODO: should be around 1 grid in distance
|
||||
radius: 5.,
|
||||
radius: 5.0,
|
||||
animation,
|
||||
anim_pixels_per_meter: 32.0,
|
||||
anim_time: 0.02,
|
||||
});
|
||||
|
||||
//TODO: support different impact animations
|
||||
if animation {
|
||||
commands.trigger_server(BuildExplosionSprite {
|
||||
pos: shot_pos,
|
||||
pixels_per_meter: 32.,
|
||||
time: 0.02,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user