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) { //TODO: move into HeadsDatabase let mut names: HashMap = 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, 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())); } }