spawn npcs in order
This commit is contained in:
@@ -1117,6 +1117,7 @@
|
||||
"head" "field medic"
|
||||
"key" "fence_gate"
|
||||
"disable_ai" "true"
|
||||
"spawn_order" "0"
|
||||
}
|
||||
// entity 3
|
||||
{
|
||||
@@ -1130,6 +1131,7 @@
|
||||
"head" "field medic"
|
||||
"angles" "0 180 0"
|
||||
"disable_ai" "true"
|
||||
"spawn_order" "1"
|
||||
}
|
||||
// entity 5
|
||||
{
|
||||
@@ -1386,6 +1388,7 @@
|
||||
"origin" "2568 4504 -232"
|
||||
"angles" "0 0 0"
|
||||
"head" "super market shopper"
|
||||
"spawn_order" "2"
|
||||
}
|
||||
// entity 24
|
||||
{
|
||||
@@ -1394,6 +1397,7 @@
|
||||
"angles" "0 -90 0"
|
||||
"head" "green grocer"
|
||||
"key" "fence_shaft"
|
||||
"spawn_order" "3"
|
||||
}
|
||||
// entity 25
|
||||
{
|
||||
@@ -1600,8 +1604,8 @@
|
||||
// entity 45
|
||||
{
|
||||
"classname" "enemy_spawn"
|
||||
"origin" "552 -680 -232"
|
||||
"angles" "0 90 0"
|
||||
"origin" "-184 -584 -232"
|
||||
"angles" "0 0 0"
|
||||
"head" "commando"
|
||||
"key" ""
|
||||
"disable_ai" "true"
|
||||
@@ -1609,8 +1613,8 @@
|
||||
// entity 46
|
||||
{
|
||||
"classname" "enemy_spawn"
|
||||
"origin" "456 -680 -232"
|
||||
"angles" "0 90 0"
|
||||
"origin" "-184 -504 -232"
|
||||
"angles" "0 0 0"
|
||||
"head" "angry demonstrator"
|
||||
"key" ""
|
||||
"disable_ai" "true"
|
||||
@@ -1618,8 +1622,8 @@
|
||||
// entity 47
|
||||
{
|
||||
"classname" "enemy_spawn"
|
||||
"origin" "360 -680 -232"
|
||||
"angles" "0 90 0"
|
||||
"origin" "-184 -440 -232"
|
||||
"angles" "0 0 0"
|
||||
"head" "goblin"
|
||||
"key" ""
|
||||
"disable_ai" "true"
|
||||
@@ -1627,8 +1631,8 @@
|
||||
// entity 48
|
||||
{
|
||||
"classname" "enemy_spawn"
|
||||
"origin" "264 -680 -232"
|
||||
"angles" "0 90 0"
|
||||
"origin" "-184 -360 -232"
|
||||
"angles" "0 0 0"
|
||||
"head" "green grocer"
|
||||
"key" ""
|
||||
"disable_ai" "true"
|
||||
@@ -1636,8 +1640,8 @@
|
||||
// entity 49
|
||||
{
|
||||
"classname" "enemy_spawn"
|
||||
"origin" "168 -680 -232"
|
||||
"angles" "0 90 0"
|
||||
"origin" "-184 -280 -232"
|
||||
"angles" "0 0 0"
|
||||
"head" "highland hammer thrower"
|
||||
"key" ""
|
||||
"disable_ai" "true"
|
||||
@@ -1645,8 +1649,8 @@
|
||||
// entity 50
|
||||
{
|
||||
"classname" "enemy_spawn"
|
||||
"origin" "72 -680 -232"
|
||||
"angles" "0 90 0"
|
||||
"origin" "-184 -184 -232"
|
||||
"angles" "0 0 0"
|
||||
"head" "legionnaire"
|
||||
"key" ""
|
||||
"disable_ai" "true"
|
||||
@@ -1654,8 +1658,8 @@
|
||||
// entity 51
|
||||
{
|
||||
"classname" "enemy_spawn"
|
||||
"origin" "-24 -680 -232"
|
||||
"angles" "0 90 0"
|
||||
"origin" "-184 -104 -232"
|
||||
"angles" "0 0 0"
|
||||
"head" "mig pilot"
|
||||
"key" ""
|
||||
"disable_ai" "true"
|
||||
@@ -1663,8 +1667,8 @@
|
||||
// entity 52
|
||||
{
|
||||
"classname" "enemy_spawn"
|
||||
"origin" "-104 -680 -232"
|
||||
"angles" "0 90 0"
|
||||
"origin" "-184 -8 -232"
|
||||
"angles" "0 0 0"
|
||||
"head" "soldier ant"
|
||||
"key" ""
|
||||
"disable_ai" "true"
|
||||
@@ -1673,7 +1677,7 @@
|
||||
{
|
||||
"classname" "enemy_spawn"
|
||||
"origin" "-184 -680 -232"
|
||||
"angles" "0 90 0"
|
||||
"angles" "0 0 0"
|
||||
"head" "super market shopper"
|
||||
"key" ""
|
||||
"disable_ai" "true"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"true" : "true"
|
||||
"false" : "false"
|
||||
]
|
||||
spawn_order(integer) : "spawn_order" : : ""
|
||||
]
|
||||
|
||||
@SolidClass base(__transform, __target) = movable
|
||||
|
||||
Reference in New Issue
Block a user