head database for aim and ai
This commit is contained in:
16
Cargo.lock
generated
16
Cargo.lock
generated
@@ -679,6 +679,19 @@ dependencies = [
|
|||||||
"wgpu-types",
|
"wgpu-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bevy_common_assets"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3521990269672c442f2bf0fbed0fce9db719e3dd136dd4012a97809464a4389d"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bevy",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_core"
|
name = "bevy_core"
|
||||||
version = "0.15.3"
|
version = "0.15.3"
|
||||||
@@ -2971,12 +2984,15 @@ dependencies = [
|
|||||||
"bevy-ui-gradients",
|
"bevy-ui-gradients",
|
||||||
"bevy_asset_loader",
|
"bevy_asset_loader",
|
||||||
"bevy_ballistic",
|
"bevy_ballistic",
|
||||||
|
"bevy_common_assets",
|
||||||
"bevy_debug_log",
|
"bevy_debug_log",
|
||||||
"bevy_polyline",
|
"bevy_polyline",
|
||||||
"bevy_sprite3d",
|
"bevy_sprite3d",
|
||||||
"bevy_trenchbroom",
|
"bevy_trenchbroom",
|
||||||
"nil",
|
"nil",
|
||||||
"rand",
|
"rand",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ bevy-steamworks = "0.13.0"
|
|||||||
bevy_ballistic = "0.1.0"
|
bevy_ballistic = "0.1.0"
|
||||||
bevy-ui-gradients = "0.2.0"
|
bevy-ui-gradients = "0.2.0"
|
||||||
bevy_debug_log = "0.5.0"
|
bevy_debug_log = "0.5.0"
|
||||||
|
bevy_common_assets = { version = "0.12.0", features = ["ron"] }
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
ron = "0.8"
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
too_many_arguments = "allow"
|
too_many_arguments = "allow"
|
||||||
|
|||||||
20
assets/all.headsdb.ron
Normal file
20
assets/all.headsdb.ron
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
([
|
||||||
|
(key:"angry demonstrator", ability:Thrown, range:80),
|
||||||
|
(key:"carnival knife thrower", range:60),
|
||||||
|
(key:"chicago gangster", ability:Gun, range:60),
|
||||||
|
(key:"commando", ability:Gun, range:60),
|
||||||
|
(key:"field medic"),
|
||||||
|
(key:"geisha"),
|
||||||
|
(key:"goblin", ability:Arrow, range:60),
|
||||||
|
(key:"green grocer", range:60),
|
||||||
|
(key:"highland hammer thrower", ability:Thrown, range:80),
|
||||||
|
(key:"legionnaire", ability:Gun, range:60),
|
||||||
|
(key:"mig pilot", ability:Gun, range:60),
|
||||||
|
(key:"nanny", ability:Thrown, range:60),
|
||||||
|
(key:"panic attack"),
|
||||||
|
(key:"salty sea dog"),
|
||||||
|
(key:"snow plough operator"),
|
||||||
|
(key:"soldier ant"),
|
||||||
|
(key:"super market shopper", ability:Thrown, range:80),
|
||||||
|
(key:"troll", ability:Thrown, range:80),
|
||||||
|
])
|
||||||
@@ -5,6 +5,7 @@ use crate::{
|
|||||||
GameState,
|
GameState,
|
||||||
aim::AimTarget,
|
aim::AimTarget,
|
||||||
global_observer,
|
global_observer,
|
||||||
|
head_asset::HeadsDatabase,
|
||||||
heads::ActiveHeads,
|
heads::ActiveHeads,
|
||||||
hitpoints::Hit,
|
hitpoints::Hit,
|
||||||
physics_layers::GameLayer,
|
physics_layers::GameLayer,
|
||||||
@@ -14,6 +15,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use avian3d::prelude::*;
|
use avian3d::prelude::*;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct Projectile {
|
pub struct Projectile {
|
||||||
@@ -29,8 +31,9 @@ pub enum TriggerState {
|
|||||||
#[derive(Event, Reflect)]
|
#[derive(Event, Reflect)]
|
||||||
pub struct TriggerCashHeal;
|
pub struct TriggerCashHeal;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Reflect)]
|
#[derive(Debug, Copy, Clone, PartialEq, Reflect, Default, Serialize, Deserialize)]
|
||||||
pub enum HeadAbility {
|
pub enum HeadAbility {
|
||||||
|
#[default]
|
||||||
None,
|
None,
|
||||||
Arrow,
|
Arrow,
|
||||||
Thrown,
|
Thrown,
|
||||||
@@ -112,6 +115,7 @@ fn on_trigger_state(
|
|||||||
player_rot: Query<&Transform, With<PlayerBodyMesh>>,
|
player_rot: Query<&Transform, With<PlayerBodyMesh>>,
|
||||||
player_query: Query<(&Transform, &AimTarget), With<Player>>,
|
player_query: Query<(&Transform, &AimTarget), With<Player>>,
|
||||||
mut active_heads: ResMut<ActiveHeads>,
|
mut active_heads: ResMut<ActiveHeads>,
|
||||||
|
heads_db: Res<HeadsDatabase>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
) {
|
) {
|
||||||
if matches!(trigger.event(), TriggerState::Active) {
|
if matches!(trigger.event(), TriggerState::Active) {
|
||||||
@@ -143,7 +147,8 @@ fn on_trigger_state(
|
|||||||
|
|
||||||
active_heads.use_ammo(time.elapsed_secs());
|
active_heads.use_ammo(time.elapsed_secs());
|
||||||
|
|
||||||
match state.ability {
|
let ability = heads_db.head_stats(state.head).ability;
|
||||||
|
match ability {
|
||||||
HeadAbility::Thrown => commands.trigger(TriggerThrow(trigger_state)),
|
HeadAbility::Thrown => commands.trigger(TriggerThrow(trigger_state)),
|
||||||
HeadAbility::Gun => commands.trigger(TriggerGun(trigger_state)),
|
HeadAbility::Gun => commands.trigger(TriggerGun(trigger_state)),
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
GameState,
|
GameState,
|
||||||
abilities::{TriggerData, TriggerThrow},
|
abilities::{HeadAbility, TriggerData, TriggerThrow},
|
||||||
aim::AimTarget,
|
aim::AimTarget,
|
||||||
|
head_asset::HeadsDatabase,
|
||||||
npc::Npc,
|
npc::Npc,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -19,12 +20,20 @@ fn update(
|
|||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut query: Query<(&mut Npc, &AimTarget, &Transform), With<Ai>>,
|
mut query: Query<(&mut Npc, &AimTarget, &Transform), With<Ai>>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
|
heads_db: Res<HeadsDatabase>,
|
||||||
) {
|
) {
|
||||||
for (mut npc, target, t) in query.iter_mut() {
|
for (mut npc, target, t) in query.iter_mut() {
|
||||||
if target.0.is_none() {
|
if target.0.is_none() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ability = heads_db.head_stats(npc.head).ability;
|
||||||
|
|
||||||
|
//TODO: support other abilities
|
||||||
|
if ability != HeadAbility::Thrown {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let can_shoot_again = npc.last_use + 1. < time.elapsed_secs();
|
let can_shoot_again = npc.last_use + 1. < time.elapsed_secs();
|
||||||
|
|
||||||
if can_shoot_again && npc.has_ammo() {
|
if can_shoot_again && npc.has_ammo() {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ mod target_ui;
|
|||||||
use crate::{
|
use crate::{
|
||||||
GameState,
|
GameState,
|
||||||
head::ActiveHead,
|
head::ActiveHead,
|
||||||
|
head_asset::HeadsDatabase,
|
||||||
physics_layers::GameLayer,
|
physics_layers::GameLayer,
|
||||||
player::{Player, PlayerBodyMesh},
|
player::{Player, PlayerBodyMesh},
|
||||||
tb_entities::EnemySpawn,
|
tb_entities::EnemySpawn,
|
||||||
@@ -53,15 +54,15 @@ fn add_aim(mut commands: Commands, query: Query<Entity, Added<ActiveHead>>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn head_change(mut query: Query<(&ActiveHead, &mut AimState), Changed<ActiveHead>>) {
|
fn head_change(
|
||||||
|
mut query: Query<(&ActiveHead, &mut AimState), Changed<ActiveHead>>,
|
||||||
|
heads_db: Res<HeadsDatabase>,
|
||||||
|
) {
|
||||||
for (head, mut state) in query.iter_mut() {
|
for (head, mut state) in query.iter_mut() {
|
||||||
// info!("head changed: {}", head.0);
|
// info!("head changed: {}", head.0);
|
||||||
// state.max_angle = if head.0 == 0 { PI / 8. } else { PI / 2. }
|
// state.max_angle = if head.0 == 0 { PI / 8. } else { PI / 2. }
|
||||||
state.range = match head.0 {
|
let stats = heads_db.head_stats(head.0);
|
||||||
0 => 80.,
|
state.range = stats.range;
|
||||||
3 => 60.,
|
|
||||||
_ => 40.,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
54
src/head_asset.rs
Normal file
54
src/head_asset.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
use crate::abilities::HeadAbility;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Reflect, Serialize, Deserialize)]
|
||||||
|
pub struct HeadStats {
|
||||||
|
pub key: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub ability: HeadAbility,
|
||||||
|
#[serde(default)]
|
||||||
|
pub range: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Asset, Reflect, Serialize, Deserialize)]
|
||||||
|
pub struct HeadDatabaseAsset(pub Vec<HeadStats>);
|
||||||
|
|
||||||
|
#[derive(Debug, Resource, Reflect)]
|
||||||
|
#[reflect(Resource)]
|
||||||
|
pub struct HeadsDatabase {
|
||||||
|
pub heads: Vec<HeadStats>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HeadsDatabase {
|
||||||
|
pub fn head_key(&self, id: usize) -> &str {
|
||||||
|
&self.heads[id].key
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn head_stats(&self, id: usize) -> &HeadStats {
|
||||||
|
&self.heads[id]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[cfg(test)]
|
||||||
|
// mod test {
|
||||||
|
// use super::*;
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn test_serialize() {
|
||||||
|
// let asset = HeadDatabaseAsset(vec![
|
||||||
|
// HeadStats {
|
||||||
|
// key: String::from("foo"),
|
||||||
|
// range: 90.,
|
||||||
|
// ..Default::default()
|
||||||
|
// },
|
||||||
|
// HeadStats {
|
||||||
|
// key: String::from("bar"),
|
||||||
|
// ability: HeadAbility::Gun,
|
||||||
|
// range: 0.,
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
// std::fs::write("assets/test.headsb.ron", ron::to_string(&asset).unwrap()).unwrap();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@@ -2,11 +2,11 @@ mod heads_ui;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
GameState,
|
GameState,
|
||||||
abilities::HeadAbility,
|
|
||||||
backpack::{BackbackSwapEvent, Backpack},
|
backpack::{BackbackSwapEvent, Backpack},
|
||||||
global_observer,
|
global_observer,
|
||||||
|
head_asset::HeadsDatabase,
|
||||||
hitpoints::Hitpoints,
|
hitpoints::Hitpoints,
|
||||||
player::{Player, head_id_to_str},
|
player::Player,
|
||||||
sounds::PlaySound,
|
sounds::PlaySound,
|
||||||
};
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
@@ -22,7 +22,6 @@ pub struct HeadsImages {
|
|||||||
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
|
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
|
||||||
pub struct HeadState {
|
pub struct HeadState {
|
||||||
pub head: usize,
|
pub head: usize,
|
||||||
pub ability: HeadAbility,
|
|
||||||
pub health: u32,
|
pub health: u32,
|
||||||
pub health_max: u32,
|
pub health_max: u32,
|
||||||
pub ammo: u32,
|
pub ammo: u32,
|
||||||
@@ -39,17 +38,11 @@ impl HeadState {
|
|||||||
health_max: 100,
|
health_max: 100,
|
||||||
ammo,
|
ammo,
|
||||||
ammo_max: ammo,
|
ammo_max: ammo,
|
||||||
ability: HeadAbility::None,
|
|
||||||
reload_duration: 5.,
|
reload_duration: 5.,
|
||||||
last_use: 0.,
|
last_use: 0.,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_ability(mut self, ability: HeadAbility) -> Self {
|
|
||||||
self.ability = ability;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_ammo(&self) -> bool {
|
pub fn has_ammo(&self) -> bool {
|
||||||
self.ammo > 0
|
self.ammo > 0
|
||||||
}
|
}
|
||||||
@@ -119,11 +112,11 @@ pub fn plugin(app: &mut App) {
|
|||||||
|
|
||||||
app.insert_resource(ActiveHeads {
|
app.insert_resource(ActiveHeads {
|
||||||
heads: [
|
heads: [
|
||||||
Some(HeadState::new(0, 10).with_ability(HeadAbility::Thrown)),
|
Some(HeadState::new(0, 10)),
|
||||||
Some(HeadState::new(3, 10).with_ability(HeadAbility::Gun)),
|
Some(HeadState::new(3, 10)),
|
||||||
Some(HeadState::new(6, 10).with_ability(HeadAbility::Arrow)),
|
Some(HeadState::new(6, 10)),
|
||||||
Some(HeadState::new(8, 10).with_ability(HeadAbility::Thrown)),
|
Some(HeadState::new(8, 10)),
|
||||||
Some(HeadState::new(9, 10).with_ability(HeadAbility::Gun)),
|
Some(HeadState::new(9, 10)),
|
||||||
],
|
],
|
||||||
current_slot: 0,
|
current_slot: 0,
|
||||||
});
|
});
|
||||||
@@ -138,10 +131,10 @@ pub fn plugin(app: &mut App) {
|
|||||||
global_observer!(app, on_swap_backpack);
|
global_observer!(app, on_swap_backpack);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, heads: Res<HeadsDatabase>) {
|
||||||
// TODO: load via asset loader
|
// TODO: load via asset loader
|
||||||
let heads = (0usize..HEAD_COUNT)
|
let heads = (0usize..HEAD_COUNT)
|
||||||
.map(|i| asset_server.load(format!("ui/heads/{}.png", head_id_to_str(i))))
|
.map(|i| asset_server.load(format!("ui/heads/{}.png", heads.head_key(i))))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
commands.insert_resource(HeadsImages { heads });
|
commands.insert_resource(HeadsImages { heads });
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use crate::GameState;
|
use crate::{
|
||||||
|
GameState,
|
||||||
|
head_asset::{HeadDatabaseAsset, HeadsDatabase},
|
||||||
|
};
|
||||||
use bevy::{prelude::*, utils::HashMap};
|
use bevy::{prelude::*, utils::HashMap};
|
||||||
use bevy_asset_loader::prelude::*;
|
use bevy_asset_loader::prelude::*;
|
||||||
|
|
||||||
@@ -43,6 +46,12 @@ pub struct AudioAssets {
|
|||||||
pub head: HashMap<AssetFileName, Handle<AudioSource>>,
|
pub head: HashMap<AssetFileName, Handle<AudioSource>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(AssetCollection, Resource)]
|
||||||
|
struct HeadsAssets {
|
||||||
|
#[asset(path = "all.headsdb.ron")]
|
||||||
|
heads: Handle<HeadDatabaseAsset>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(AssetCollection, Resource)]
|
#[derive(AssetCollection, Resource)]
|
||||||
pub struct UIAssets {
|
pub struct UIAssets {
|
||||||
#[asset(path = "font.ttf")]
|
#[asset(path = "font.ttf")]
|
||||||
@@ -98,12 +107,26 @@ pub struct GameAssets {
|
|||||||
pub struct LoadingPlugin;
|
pub struct LoadingPlugin;
|
||||||
impl Plugin for LoadingPlugin {
|
impl Plugin for LoadingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_systems(OnExit(GameState::AssetLoading), on_exit);
|
||||||
app.add_loading_state(
|
app.add_loading_state(
|
||||||
LoadingState::new(GameState::AssetLoading)
|
LoadingState::new(GameState::AssetLoading)
|
||||||
.continue_to_state(GameState::MapLoading)
|
.continue_to_state(GameState::MapLoading)
|
||||||
.load_collection::<AudioAssets>()
|
.load_collection::<AudioAssets>()
|
||||||
.load_collection::<GameAssets>()
|
.load_collection::<GameAssets>()
|
||||||
|
.load_collection::<HeadsAssets>()
|
||||||
.load_collection::<UIAssets>(),
|
.load_collection::<UIAssets>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_exit(
|
||||||
|
mut cmds: Commands,
|
||||||
|
res: Res<HeadsAssets>,
|
||||||
|
mut assets: ResMut<Assets<HeadDatabaseAsset>>,
|
||||||
|
) {
|
||||||
|
let asset = assets
|
||||||
|
.remove(res.heads.id())
|
||||||
|
.expect("headsdb failed to load");
|
||||||
|
|
||||||
|
cmds.insert_resource(HeadsDatabase { heads: asset.0 });
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ mod cutscene;
|
|||||||
mod debug;
|
mod debug;
|
||||||
mod gates;
|
mod gates;
|
||||||
mod head;
|
mod head;
|
||||||
|
mod head_asset;
|
||||||
mod heads;
|
mod heads;
|
||||||
mod hitpoints;
|
mod hitpoints;
|
||||||
mod keys;
|
mod keys;
|
||||||
@@ -33,6 +34,7 @@ use bevy::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
render::view::ColorGrading,
|
render::view::ColorGrading,
|
||||||
};
|
};
|
||||||
|
use bevy_common_assets::ron::RonAssetPlugin;
|
||||||
use bevy_polyline::PolylinePlugin;
|
use bevy_polyline::PolylinePlugin;
|
||||||
use bevy_sprite3d::Sprite3dPlugin;
|
use bevy_sprite3d::Sprite3dPlugin;
|
||||||
use bevy_steamworks::{FriendFlags, SteamworksClient, SteamworksPlugin};
|
use bevy_steamworks::{FriendFlags, SteamworksClient, SteamworksPlugin};
|
||||||
@@ -40,6 +42,7 @@ use bevy_trenchbroom::prelude::*;
|
|||||||
use bevy_ui_gradients::UiGradientsPlugin;
|
use bevy_ui_gradients::UiGradientsPlugin;
|
||||||
use camera::MainCamera;
|
use camera::MainCamera;
|
||||||
use control::controller::CharacterControllerPlugin;
|
use control::controller::CharacterControllerPlugin;
|
||||||
|
use head_asset::HeadDatabaseAsset;
|
||||||
use loading_assets::AudioAssets;
|
use loading_assets::AudioAssets;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use utils::{billboards, sprite_3d_animation, squish_animation};
|
use utils::{billboards, sprite_3d_animation, squish_animation};
|
||||||
@@ -108,6 +111,7 @@ fn main() {
|
|||||||
app.add_plugins(Sprite3dPlugin);
|
app.add_plugins(Sprite3dPlugin);
|
||||||
app.add_plugins(TrenchBroomPlugin(TrenchBroomConfig::new("hedz")));
|
app.add_plugins(TrenchBroomPlugin(TrenchBroomConfig::new("hedz")));
|
||||||
app.add_plugins(UiGradientsPlugin);
|
app.add_plugins(UiGradientsPlugin);
|
||||||
|
app.add_plugins(RonAssetPlugin::<HeadDatabaseAsset>::new(&["headsdb.ron"]));
|
||||||
|
|
||||||
#[cfg(feature = "dbg")]
|
#[cfg(feature = "dbg")]
|
||||||
{
|
{
|
||||||
|
|||||||
10
src/npc.rs
10
src/npc.rs
@@ -2,10 +2,10 @@ use crate::{
|
|||||||
GameState,
|
GameState,
|
||||||
ai::Ai,
|
ai::Ai,
|
||||||
head::ActiveHead,
|
head::ActiveHead,
|
||||||
|
head_asset::HeadsDatabase,
|
||||||
heads::{HEAD_COUNT, HeadState},
|
heads::{HEAD_COUNT, HeadState},
|
||||||
hitpoints::{Hitpoints, Kill},
|
hitpoints::{Hitpoints, Kill},
|
||||||
keys::KeySpawn,
|
keys::KeySpawn,
|
||||||
player::head_id_to_str,
|
|
||||||
tb_entities::EnemySpawn,
|
tb_entities::EnemySpawn,
|
||||||
};
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
@@ -19,18 +19,20 @@ pub fn plugin(app: &mut App) {
|
|||||||
app.add_systems(OnEnter(GameState::Playing), init);
|
app.add_systems(OnEnter(GameState::Playing), init);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(mut commands: Commands, query: Query<(Entity, &EnemySpawn)>) {
|
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();
|
let mut names: HashMap<String, usize> = HashMap::default();
|
||||||
for i in 0..HEAD_COUNT {
|
for i in 0..HEAD_COUNT {
|
||||||
names.insert(head_id_to_str(i).to_string(), i);
|
names.insert(heads_db.head_key(i).to_string(), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (e, spawn) in query.iter() {
|
for (e, spawn) in query.iter() {
|
||||||
let id = names[&spawn.head];
|
let id = names[&spawn.head];
|
||||||
commands
|
commands
|
||||||
.entity(e)
|
.entity(e)
|
||||||
.insert((
|
.insert((
|
||||||
Hitpoints::new(100),
|
Hitpoints::new(100),
|
||||||
Npc(HeadState::new(id, 10).with_ability(crate::abilities::HeadAbility::Thrown)),
|
Npc(HeadState::new(id, 10)),
|
||||||
ActiveHead(id),
|
ActiveHead(id),
|
||||||
Ai,
|
Ai,
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
global_observer,
|
global_observer,
|
||||||
head::ActiveHead,
|
head::ActiveHead,
|
||||||
|
head_asset::HeadsDatabase,
|
||||||
heads::HeadChanged,
|
heads::HeadChanged,
|
||||||
hitpoints::Hitpoints,
|
hitpoints::Hitpoints,
|
||||||
loading_assets::GameAssets,
|
loading_assets::GameAssets,
|
||||||
@@ -251,6 +252,7 @@ fn on_update_head(
|
|||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
head: Query<Entity, With<PlayerHeadMesh>>,
|
head: Query<Entity, With<PlayerHeadMesh>>,
|
||||||
mut player_head: Query<&mut ActiveHead, With<Player>>,
|
mut player_head: Query<&mut ActiveHead, With<Player>>,
|
||||||
|
head_db: Res<HeadsDatabase>,
|
||||||
) {
|
) {
|
||||||
let Ok(head) = head.get_single() else {
|
let Ok(head) = head.get_single() else {
|
||||||
return;
|
return;
|
||||||
@@ -262,7 +264,7 @@ fn on_update_head(
|
|||||||
|
|
||||||
player.0 = trigger.0;
|
player.0 = trigger.0;
|
||||||
|
|
||||||
let head_str = head_id_to_str(trigger.0);
|
let head_str = head_db.head_key(trigger.0);
|
||||||
|
|
||||||
commands.trigger(PlaySound::Head(head_str.to_string()));
|
commands.trigger(PlaySound::Head(head_str.to_string()));
|
||||||
|
|
||||||
@@ -271,27 +273,3 @@ fn on_update_head(
|
|||||||
|
|
||||||
commands.entity(head).insert(SceneRoot(mesh));
|
commands.entity(head).insert(SceneRoot(mesh));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn head_id_to_str(head: usize) -> &'static str {
|
|
||||||
match head {
|
|
||||||
0 => "angry demonstrator",
|
|
||||||
1 => "carnival knife thrower",
|
|
||||||
2 => "chicago gangster",
|
|
||||||
3 => "commando",
|
|
||||||
4 => "field medic",
|
|
||||||
5 => "geisha",
|
|
||||||
6 => "goblin",
|
|
||||||
7 => "green grocer",
|
|
||||||
8 => "highland hammer thrower",
|
|
||||||
9 => "legionnaire",
|
|
||||||
10 => "mig pilot",
|
|
||||||
11 => "nanny",
|
|
||||||
12 => "panic attack",
|
|
||||||
13 => "salty sea dog",
|
|
||||||
14 => "snow plough operator",
|
|
||||||
15 => "soldier ant",
|
|
||||||
16 => "super market shopper",
|
|
||||||
17 => "troll",
|
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user