mod gun; mod thrown; use crate::{ GameState, heads::ActiveHeads, npc::Hit, player::{Player, PlayerRig}, tb_entities::EnemySpawn, }; use avian3d::prelude::*; use bevy::prelude::*; #[derive(Component)] pub struct Projectile { pub damage: u32, } #[derive(Event, Reflect)] pub enum TriggerState { Active, Inactive, } #[derive(Debug, Copy, Clone, PartialEq, Reflect)] pub enum HeadAbility { None, Arrow, Thrown, Gun, } #[derive(Debug, Reflect, Clone, Copy)] pub struct PlayerTriggerState { dir: Dir3, rot: Quat, pos: Vec3, } #[derive(Event, Reflect)] pub struct TriggerGun(pub PlayerTriggerState); #[derive(Event, Reflect)] pub struct TriggerThrow(pub PlayerTriggerState); pub fn plugin(app: &mut App) { app.add_plugins(gun::plugin); app.add_plugins(thrown::plugin); app.add_systems(Update, enemy_hit.run_if(in_state(GameState::Playing))); app.add_observer(on_trigger_state); } fn enemy_hit( mut commands: Commands, mut collision_event_reader: EventReader, query_shot: Query<&Projectile>, query_npc: Query<&EnemySpawn>, ) { for CollisionStarted(e1, e2) in collision_event_reader.read() { if !query_shot.contains(*e1) && !query_shot.contains(*e2) { continue; } if !query_npc.contains(*e1) && !query_npc.contains(*e2) { continue; } let (enemy_entity, projectile) = if query_npc.contains(*e1) { (*e1, query_shot.get(*e2)) } else { (*e2, query_shot.get(*e1)) }; let damage = projectile.map(|p| p.damage).unwrap_or_default(); commands.entity(enemy_entity).trigger(Hit { damage }); } } fn on_trigger_state( trigger: Trigger, mut commands: Commands, player_rot: Query<&Transform, With>, player_transform: Query<&Transform, With>, mut active_heads: ResMut, time: Res