spawn npcs in order
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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>>,
|
||||
|
||||
46
src/npc.rs
46
src/npc.rs
@@ -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();
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -120,6 +120,7 @@ pub struct EnemySpawn {
|
||||
pub head: String,
|
||||
pub key: String,
|
||||
pub disable_ai: bool,
|
||||
pub spawn_order: Option<u32>,
|
||||
}
|
||||
|
||||
impl EnemySpawn {
|
||||
|
||||
Reference in New Issue
Block a user