spawn npcs in order

This commit is contained in:
2025-06-21 12:06:56 +02:00
parent 28ad53fd68
commit 241b96fcc7
8 changed files with 78 additions and 23 deletions

View File

@@ -5,6 +5,7 @@ use crate::{
GameState,
head::ActiveHead,
heads_database::HeadsDatabase,
hitpoints::Hitpoints,
physics_layers::GameLayer,
player::{Player, PlayerBodyMesh},
tb_entities::EnemySpawn,
@@ -68,12 +69,12 @@ fn head_change(
fn update_player_aim(
mut commands: Commands,
potential_targets: Query<(Entity, &Transform), With<EnemySpawn>>,
potential_targets: Query<(Entity, &Transform), With<Hitpoints>>,
player_rot: Query<(&Transform, &GlobalTransform), With<PlayerBodyMesh>>,
mut player_aim: Query<(&AimState, &mut AimTarget), With<Player>>,
mut player_aim: Query<(Entity, &AimState, &mut AimTarget), With<Player>>,
spatial_query: SpatialQuery,
) {
let Some((state, mut aim_target)) = player_aim.iter_mut().next() else {
let Some((player, state, mut aim_target)) = player_aim.iter_mut().next() else {
return;
};
@@ -89,6 +90,10 @@ fn update_player_aim(
let mut target_distance = f32::MAX;
for (e, t) in potential_targets.iter() {
if e == player {
continue;
}
let delta = player_pos - t.translation;
let distance = delta.length();

View File

@@ -54,6 +54,8 @@ pub struct AudioAssets {
pub secret_head_collect: Handle<AudioSource>,
#[asset(path = "sfx/effects/head_drop.ogg")]
pub head_drop: Handle<AudioSource>,
#[asset(path = "sfx/effects/beam_in_out.ogg")]
pub beaming: Handle<AudioSource>,
#[asset(path = "sfx/hit", collection(typed))]
pub hit: Vec<Handle<AudioSource>>,

View File

@@ -2,12 +2,14 @@ use crate::{
GameState,
ai::Ai,
character::AnimatedCharacter,
global_observer,
head::ActiveHead,
head_drop::HeadDrops,
heads::{ActiveHeads, HEAD_COUNT, HeadState},
heads_database::HeadsDatabase,
hitpoints::{Hitpoints, Kill},
keys::KeySpawn,
sounds::PlaySound,
tb_entities::EnemySpawn,
};
use bevy::prelude::*;
@@ -17,11 +19,34 @@ use std::collections::HashMap;
#[reflect(Component)]
pub struct Npc;
pub fn plugin(app: &mut App) {
app.add_systems(OnEnter(GameState::Playing), init);
#[derive(Resource, Reflect, Default)]
#[reflect(Resource)]
struct NpcSpawning {
spawn_index: u32,
}
fn init(mut commands: Commands, query: Query<(Entity, &EnemySpawn)>, heads_db: Res<HeadsDatabase>) {
#[derive(Event)]
struct OnCheckSpawns;
pub fn plugin(app: &mut App) {
app.init_resource::<NpcSpawning>();
app.add_systems(OnEnter(GameState::Playing), setup);
global_observer!(app, on_spawn_check);
}
fn setup(mut commands: Commands) {
commands.init_resource::<NpcSpawning>();
commands.trigger(OnCheckSpawns);
}
fn on_spawn_check(
_trigger: Trigger<OnCheckSpawns>,
mut commands: Commands,
query: Query<(Entity, &EnemySpawn), Without<Npc>>,
heads_db: Res<HeadsDatabase>,
spawning: Res<NpcSpawning>,
) {
//TODO: move into HeadsDatabase
let mut names: HashMap<String, usize> = HashMap::default();
for i in 0..HEAD_COUNT {
@@ -29,6 +54,12 @@ fn init(mut commands: Commands, query: Query<(Entity, &EnemySpawn)>, heads_db: R
}
for (e, spawn) in query.iter() {
if let Some(order) = spawn.spawn_order {
if order > spawning.spawn_index {
continue;
}
}
let id = names[&spawn.head];
commands
.entity(e)
@@ -47,6 +78,8 @@ fn init(mut commands: Commands, query: Query<(Entity, &EnemySpawn)>, heads_db: R
.insert_if(Ai, || !spawn.disable_ai)
.with_child((Name::from("body-rig"), AnimatedCharacter::new(id)))
.observe(on_kill);
commands.trigger(PlaySound::Beaming);
}
}
@@ -59,7 +92,14 @@ fn on_kill(
return;
};
if let Some(order) = enemy.spawn_order {
commands.insert_resource(NpcSpawning {
spawn_index: order + 1,
});
}
commands.trigger(HeadDrops::new(transform.translation, head.0));
commands.trigger(OnCheckSpawns);
commands.entity(trigger.target()).despawn();

View File

@@ -19,6 +19,7 @@ pub enum PlaySound {
Reloaded,
CashHeal,
Crossbow,
Beaming,
Backpack { open: bool },
Head(String),
}
@@ -60,6 +61,7 @@ fn on_spawn_sounds(
PlaySound::HeadCollect => assets.head_collect.clone(),
PlaySound::SecretHeadCollect => assets.secret_head_collect.clone(),
PlaySound::MissileExplosion => assets.missile_explosion.clone(),
PlaySound::Beaming => assets.beaming.clone(),
PlaySound::Backpack { open } => {
if *open {
assets.backpack_open.clone()

View File

@@ -120,6 +120,7 @@ pub struct EnemySpawn {
pub head: String,
pub key: String,
pub disable_ai: bool,
pub spawn_order: Option<u32>,
}
impl EnemySpawn {