Files
HEDZReloaded/src/npc.rs
2025-05-13 23:25:58 +02:00

73 lines
1.9 KiB
Rust

use crate::{
GameState,
ai::Ai,
character::AnimatedCharacter,
head::ActiveHead,
head_drop::HeadDrops,
heads::{ActiveHeads, HEAD_COUNT, HeadState},
heads_database::HeadsDatabase,
hitpoints::{Hitpoints, Kill},
keys::KeySpawn,
tb_entities::EnemySpawn,
};
use bevy::prelude::*;
use std::collections::HashMap;
#[derive(Component, Reflect)]
#[reflect(Component)]
pub struct Npc;
pub fn plugin(app: &mut App) {
app.add_systems(OnEnter(GameState::Playing), init);
}
fn init(mut commands: Commands, query: Query<(Entity, &EnemySpawn)>, heads_db: Res<HeadsDatabase>) {
//TODO: move into HeadsDatabase
let mut names: HashMap<String, usize> = HashMap::default();
for i in 0..HEAD_COUNT {
names.insert(heads_db.head_key(i).to_string(), i);
}
for (e, spawn) in query.iter() {
let id = names[&spawn.head];
commands
.entity(e)
.insert((
Hitpoints::new(100),
Npc,
ActiveHead(id),
ActiveHeads::new([
Some(HeadState::new(id, heads_db.as_ref())),
None,
None,
None,
None,
]),
))
.insert_if(Ai, || !spawn.disable_ai)
.with_child((
Name::from("body-rig"),
AnimatedCharacter::new(id).with_rotation(),
))
.observe(on_kill);
}
}
fn on_kill(
trigger: Trigger<Kill>,
mut commands: Commands,
query: Query<(&Transform, &EnemySpawn, &ActiveHead)>,
) {
let Ok((transform, enemy, head)) = query.get(trigger.target()) else {
return;
};
commands.trigger(HeadDrops(transform.translation, head.0));
commands.entity(trigger.target()).despawn();
if !enemy.key.is_empty() {
commands.trigger(KeySpawn(transform.translation, enemy.key.clone()));
}
}