thrown projectiles area damage

This commit is contained in:
2025-04-01 21:11:01 +08:00
parent 7c9249fa8f
commit 7fbf24a49b

View File

@@ -1,10 +1,10 @@
use super::TriggerState;
use crate::{
GameState,
abilities::Projectile,
aim::AimState,
billboards::Billboard,
loading_assets::GameAssets,
npc::Hit,
physics_layers::GameLayer,
player::{Player, PlayerRig},
sounds::PlaySound,
@@ -23,6 +23,13 @@ struct ThrownProjectile;
#[reflect(Component)]
struct AutoRotation(Quat);
#[derive(Event, Debug)]
struct Explosion {
position: Vec3,
radius: f32,
damage: u32,
}
#[derive(Resource)]
struct ShotAssets {
image: Handle<Image>,
@@ -36,6 +43,33 @@ pub fn plugin(app: &mut App) {
app.add_systems(Update, shot_collision.run_if(in_state(GameState::Playing)));
app.add_systems(FixedUpdate, update_auto_rotation);
app.add_observer(on_trigger_state);
app.add_observer(on_explosion);
}
fn on_explosion(
explosion: Trigger<Explosion>,
mut commands: Commands,
spatial_query: SpatialQuery,
) {
let explosion = explosion.event();
let intersections = {
spatial_query.shape_intersections(
&Collider::sphere(explosion.radius),
explosion.position,
Quat::default(),
&SpatialQueryFilter::default().with_mask(LayerMask(
GameLayer::Npc.to_bits() | GameLayer::Player.to_bits(),
)),
)
};
for entity in intersections.iter() {
if let Some(mut e) = commands.get_entity(*entity) {
e.trigger(Hit {
damage: explosion.damage,
});
}
}
}
fn setup(mut commands: Commands, assets: Res<GameAssets>, mut sprite_params: Sprite3dParams) {
@@ -103,13 +137,13 @@ fn on_trigger_state(
.spawn((
Name::new("projectile-thrown"),
ThrownProjectile,
Projectile { damage: 20 },
Collider::sphere(0.5),
CollisionLayers::new(
LayerMask(GameLayer::Projectile.to_bits()),
LayerMask(GameLayer::Npc.to_bits() | GameLayer::Level.to_bits()),
),
RigidBody::Dynamic,
Mass(0.01),
LinearVelocity(vel),
Visibility::default(),
t,
@@ -140,12 +174,14 @@ fn shot_collision(
commands.entity(shot_entity).despawn_recursive();
let texture_atlas = TextureAtlas {
layout: assets.layout.clone(),
index: 0,
};
commands.trigger(PlaySound::ThrowHit);
commands.trigger(Explosion {
damage: 20,
position: shot_pos,
radius: 2.,
});
commands
.spawn(
Sprite3dBuilder {
@@ -155,7 +191,13 @@ fn shot_collision(
unlit: true,
..default()
}
.bundle_with_atlas(&mut sprite_params, texture_atlas),
.bundle_with_atlas(
&mut sprite_params,
TextureAtlas {
layout: assets.layout.clone(),
index: 0,
},
),
)
.insert((
Billboard,