secret heads and collecting sound
This commit is contained in:
@@ -1591,3 +1591,9 @@
|
|||||||
"origin" "104 552 568"
|
"origin" "104 552 568"
|
||||||
"targetname" "test_target_2"
|
"targetname" "test_target_2"
|
||||||
}
|
}
|
||||||
|
// entity 44
|
||||||
|
{
|
||||||
|
"classname" "secret_head"
|
||||||
|
"origin" "2712 5240 792"
|
||||||
|
"head_id" "13"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
GameState, billboards::Billboard, global_observer, loading_assets::GameAssets,
|
GameState, billboards::Billboard, global_observer, loading_assets::GameAssets,
|
||||||
physics_layers::GameLayer, player::Player, sounds::PlaySound,
|
physics_layers::GameLayer, player::Player, sounds::PlaySound,
|
||||||
squish_animation::SquishAnimation,
|
squish_animation::SquishAnimation, tb_entities::SecretHead,
|
||||||
};
|
};
|
||||||
use avian3d::prelude::*;
|
use avian3d::prelude::*;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
@@ -14,15 +14,50 @@ pub struct HeadDrops(pub Vec3, pub usize);
|
|||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct HeadDrop(pub usize);
|
struct HeadDrop(pub usize);
|
||||||
|
|
||||||
|
#[derive(Component, Reflect)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
struct SecretHeadMarker;
|
||||||
|
|
||||||
#[derive(Event, Reflect)]
|
#[derive(Event, Reflect)]
|
||||||
pub struct HeadCollected(pub usize);
|
pub struct HeadCollected(pub usize);
|
||||||
|
|
||||||
pub fn plugin(app: &mut App) {
|
pub fn plugin(app: &mut App) {
|
||||||
app.add_systems(Update, collect_head.run_if(in_state(GameState::Playing)));
|
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);
|
global_observer!(app, on_head_drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spawn(
|
||||||
|
mut commands: Commands,
|
||||||
|
query: Query<(Entity, &GlobalTransform, &SecretHead)>,
|
||||||
|
assets: Res<GameAssets>,
|
||||||
|
) {
|
||||||
|
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<HeadDrops>, mut commands: Commands, assets: Res<GameAssets>) {
|
fn on_head_drop(trigger: Trigger<HeadDrops>, mut commands: Commands, assets: Res<GameAssets>) {
|
||||||
let HeadDrops(position, id) = trigger.event();
|
let HeadDrops(position, id) = trigger.event();
|
||||||
|
|
||||||
@@ -57,6 +92,7 @@ fn collect_head(
|
|||||||
mut collision_event_reader: EventReader<CollisionStarted>,
|
mut collision_event_reader: EventReader<CollisionStarted>,
|
||||||
query_player: Query<&Player>,
|
query_player: Query<&Player>,
|
||||||
query_collectable: Query<&HeadDrop>,
|
query_collectable: Query<&HeadDrop>,
|
||||||
|
query_secret: Query<&SecretHeadMarker>,
|
||||||
) {
|
) {
|
||||||
for CollisionStarted(e1, e2) in collision_event_reader.read() {
|
for CollisionStarted(e1, e2) in collision_event_reader.read() {
|
||||||
let collectable = if query_player.contains(*e1) && query_collectable.contains(*e2) {
|
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();
|
let key = query_collectable.get(collectable).unwrap();
|
||||||
|
|
||||||
|
let is_secret = query_secret.contains(collectable);
|
||||||
|
|
||||||
|
if is_secret {
|
||||||
|
commands.trigger(PlaySound::SecretHeadCollect);
|
||||||
|
} else {
|
||||||
commands.trigger(PlaySound::HeadCollect);
|
commands.trigger(PlaySound::HeadCollect);
|
||||||
|
}
|
||||||
commands.trigger(HeadCollected(key.0));
|
commands.trigger(HeadCollected(key.0));
|
||||||
commands.entity(collectable).despawn();
|
commands.entity(collectable).despawn();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ pub struct AudioAssets {
|
|||||||
|
|
||||||
#[asset(path = "sfx/effects/head_collect.ogg")]
|
#[asset(path = "sfx/effects/head_collect.ogg")]
|
||||||
pub head_collect: Handle<AudioSource>,
|
pub head_collect: Handle<AudioSource>,
|
||||||
|
#[asset(path = "sfx/effects/secret_collected.ogg")]
|
||||||
|
pub secret_head_collect: Handle<AudioSource>,
|
||||||
#[asset(path = "sfx/effects/head_drop.ogg")]
|
#[asset(path = "sfx/effects/head_drop.ogg")]
|
||||||
pub head_drop: Handle<AudioSource>,
|
pub head_drop: Handle<AudioSource>,
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ pub enum PlaySound {
|
|||||||
Gate,
|
Gate,
|
||||||
CashCollect,
|
CashCollect,
|
||||||
HeadCollect,
|
HeadCollect,
|
||||||
|
SecretHeadCollect,
|
||||||
HeadDrop,
|
HeadDrop,
|
||||||
Selection,
|
Selection,
|
||||||
Invalid,
|
Invalid,
|
||||||
@@ -57,6 +58,7 @@ fn on_spawn_sounds(
|
|||||||
PlaySound::CashHeal => assets.cash_heal.clone(),
|
PlaySound::CashHeal => assets.cash_heal.clone(),
|
||||||
PlaySound::HeadDrop => assets.head_drop.clone(),
|
PlaySound::HeadDrop => assets.head_drop.clone(),
|
||||||
PlaySound::HeadCollect => assets.head_collect.clone(),
|
PlaySound::HeadCollect => assets.head_collect.clone(),
|
||||||
|
PlaySound::SecretHeadCollect => assets.secret_head_collect.clone(),
|
||||||
PlaySound::MissileExplosion => assets.missile_explosion.clone(),
|
PlaySound::MissileExplosion => assets.missile_explosion.clone(),
|
||||||
PlaySound::Backpack { open } => {
|
PlaySound::Backpack { open } => {
|
||||||
if *open {
|
if *open {
|
||||||
|
|||||||
@@ -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) {
|
pub fn plugin(app: &mut App) {
|
||||||
app.register_type::<SpawnPoint>();
|
app.register_type::<SpawnPoint>();
|
||||||
app.register_type::<Worldspawn>();
|
app.register_type::<Worldspawn>();
|
||||||
@@ -191,4 +199,5 @@ pub fn plugin(app: &mut App) {
|
|||||||
app.register_type::<CutsceneCameraMovementEnd>();
|
app.register_type::<CutsceneCameraMovementEnd>();
|
||||||
app.register_type::<EnemySpawn>();
|
app.register_type::<EnemySpawn>();
|
||||||
app.register_type::<CashSpawn>();
|
app.register_type::<CashSpawn>();
|
||||||
|
app.register_type::<SecretHead>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,11 @@
|
|||||||
targetname(string) : "targetname" : "" : ""
|
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
|
@PointClass base(__transform) model({ "path": "models/spawn.glb" }) = spawn_point
|
||||||
[
|
[
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user