use crate::{ GameState, billboards::Billboard, global_observer, heads_database::HeadsDatabase, loading_assets::HeadDropAssets, physics_layers::GameLayer, player::Player, sounds::PlaySound, squish_animation::SquishAnimation, tb_entities::SecretHead, }; use avian3d::prelude::*; use bevy::{ ecs::{relationship::RelatedSpawner, spawn::SpawnWith}, prelude::*, }; use std::f32::consts::PI; #[derive(Event, Reflect)] pub struct HeadDrops { pos: Vec3, head_id: usize, impulse: bool, } impl HeadDrops { pub fn new(pos: Vec3, head_id: usize) -> Self { Self { pos, head_id, impulse: true, } } fn new_static(pos: Vec3, head_id: usize) -> Self { Self { pos, head_id, impulse: false, } } } #[derive(Component, Reflect)] #[reflect(Component)] struct HeadDrop { pub head_id: usize, } #[derive(Component, Reflect)] #[reflect(Component)] struct HeadDropEnableTime(f32); #[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, enable_collectible.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)>) { for (e, t, head) in query { commands.trigger(HeadDrops::new_static( t.translation() + Vec3::new(0., 2., 0.), head.head_id, )); commands.entity(e).despawn(); } } fn on_head_drop( trigger: Trigger, mut commands: Commands, assets: Res, heads_db: Res, gltf_assets: Res>, time: Res