From 97929504cc9bbb74ec93a55b0021e12289f7f91d Mon Sep 17 00:00:00 2001 From: extrawurst Date: Thu, 22 May 2025 22:42:12 +0200 Subject: [PATCH] secret heads and collecting sound --- assets/maps/map1.map | 6 +++++ src/head_drop.rs | 46 +++++++++++++++++++++++++++++++++++++-- src/loading_assets.rs | 2 ++ src/sounds.rs | 2 ++ src/tb_entities.rs | 9 ++++++++ trenchbroom/hedz/hedz.fgd | 5 +++++ 6 files changed, 68 insertions(+), 2 deletions(-) diff --git a/assets/maps/map1.map b/assets/maps/map1.map index c5fb22a..7a96024 100644 --- a/assets/maps/map1.map +++ b/assets/maps/map1.map @@ -1591,3 +1591,9 @@ "origin" "104 552 568" "targetname" "test_target_2" } +// entity 44 +{ +"classname" "secret_head" +"origin" "2712 5240 792" +"head_id" "13" +} diff --git a/src/head_drop.rs b/src/head_drop.rs index a336e8d..957c861 100644 --- a/src/head_drop.rs +++ b/src/head_drop.rs @@ -1,7 +1,7 @@ use crate::{ GameState, billboards::Billboard, global_observer, loading_assets::GameAssets, physics_layers::GameLayer, player::Player, sounds::PlaySound, - squish_animation::SquishAnimation, + squish_animation::SquishAnimation, tb_entities::SecretHead, }; use avian3d::prelude::*; use bevy::prelude::*; @@ -14,15 +14,50 @@ pub struct HeadDrops(pub Vec3, pub usize); #[reflect(Component)] struct HeadDrop(pub usize); +#[derive(Component, Reflect)] +#[reflect(Component)] +struct SecretHeadMarker; + #[derive(Event, Reflect)] pub struct HeadCollected(pub usize); pub fn plugin(app: &mut App) { app.add_systems(Update, collect_head.run_if(in_state(GameState::Playing))); + app.add_systems(OnEnter(GameState::Playing), spawn); global_observer!(app, on_head_drop); } +fn spawn( + mut commands: Commands, + query: Query<(Entity, &GlobalTransform, &SecretHead)>, + assets: Res, +) { + for (e, t, head) in query { + commands + .spawn(( + Name::new("headdrop"), + SecretHeadMarker, + HeadDrop(head.head_id), + Transform::from_translation(t.translation() + Vec3::new(0., 2., 0.)), + Visibility::default(), + Collider::sphere(1.5), + LockedAxes::ROTATION_LOCKED, + RigidBody::Dynamic, + CollisionLayers::new(LayerMask(GameLayer::Collectibles.to_bits()), LayerMask::ALL), + CollisionEventsEnabled, + Restitution::new(0.6), + )) + .with_child(( + Billboard, + SquishAnimation(2.6), + SceneRoot(assets.mesh_head_drop.clone()), + )); + + commands.entity(e).despawn(); + } +} + fn on_head_drop(trigger: Trigger, mut commands: Commands, assets: Res) { let HeadDrops(position, id) = trigger.event(); @@ -57,6 +92,7 @@ fn collect_head( mut collision_event_reader: EventReader, query_player: Query<&Player>, query_collectable: Query<&HeadDrop>, + query_secret: Query<&SecretHeadMarker>, ) { for CollisionStarted(e1, e2) in collision_event_reader.read() { let collectable = if query_player.contains(*e1) && query_collectable.contains(*e2) { @@ -69,7 +105,13 @@ fn collect_head( let key = query_collectable.get(collectable).unwrap(); - commands.trigger(PlaySound::HeadCollect); + let is_secret = query_secret.contains(collectable); + + if is_secret { + commands.trigger(PlaySound::SecretHeadCollect); + } else { + commands.trigger(PlaySound::HeadCollect); + } commands.trigger(HeadCollected(key.0)); commands.entity(collectable).despawn(); } diff --git a/src/loading_assets.rs b/src/loading_assets.rs index df323fb..1073d2f 100644 --- a/src/loading_assets.rs +++ b/src/loading_assets.rs @@ -50,6 +50,8 @@ pub struct AudioAssets { #[asset(path = "sfx/effects/head_collect.ogg")] pub head_collect: Handle, + #[asset(path = "sfx/effects/secret_collected.ogg")] + pub secret_head_collect: Handle, #[asset(path = "sfx/effects/head_drop.ogg")] pub head_drop: Handle, diff --git a/src/sounds.rs b/src/sounds.rs index 75fb371..18c02df 100644 --- a/src/sounds.rs +++ b/src/sounds.rs @@ -11,6 +11,7 @@ pub enum PlaySound { Gate, CashCollect, HeadCollect, + SecretHeadCollect, HeadDrop, Selection, Invalid, @@ -57,6 +58,7 @@ fn on_spawn_sounds( PlaySound::CashHeal => assets.cash_heal.clone(), PlaySound::HeadDrop => assets.head_drop.clone(), PlaySound::HeadCollect => assets.head_collect.clone(), + PlaySound::SecretHeadCollect => assets.secret_head_collect.clone(), PlaySound::MissileExplosion => assets.missile_explosion.clone(), PlaySound::Backpack { open } => { if *open { diff --git a/src/tb_entities.rs b/src/tb_entities.rs index f690943..d01b3e2 100644 --- a/src/tb_entities.rs +++ b/src/tb_entities.rs @@ -176,6 +176,14 @@ impl CashSpawn { } } +#[derive(PointClass, Component, Reflect, Default)] +#[reflect(QuakeClass, Component)] +#[base(Transform)] +#[model({ "path": "models/head_drop.glb" })] +pub struct SecretHead { + pub head_id: usize, +} + pub fn plugin(app: &mut App) { app.register_type::(); app.register_type::(); @@ -191,4 +199,5 @@ pub fn plugin(app: &mut App) { app.register_type::(); app.register_type::(); app.register_type::(); + app.register_type::(); } diff --git a/trenchbroom/hedz/hedz.fgd b/trenchbroom/hedz/hedz.fgd index c8e0c1f..9b82845 100644 --- a/trenchbroom/hedz/hedz.fgd +++ b/trenchbroom/hedz/hedz.fgd @@ -79,6 +79,11 @@ targetname(string) : "targetname" : "" : "" ] +@PointClass base(__transform) model({ "path": "models/head_drop.glb" }) = secret_head +[ + head_id(integer) : "head_id" : 0 : "" +] + @PointClass base(__transform) model({ "path": "models/spawn.glb" }) = spawn_point [ ]