From baf740a289ea826c39babdc5c7fac84723778ea4 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 27 May 2019 12:18:14 +0100 Subject: [PATCH] Added enemies Former-commit-id: 2c07c9e52a7cbfb85508e7098c528bddd9b12997 --- common/src/comp/agent.rs | 3 +++ common/src/sys/agent.rs | 48 +++++++++++++++++++++++++++++++++++++--- server/src/cmd.rs | 32 +++++++++++++++++++++++++++ server/src/lib.rs | 3 ++- 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index 37a9faf6e6..97fa052c6b 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -8,6 +8,9 @@ pub enum Agent { target: EcsEntity, offset: Vec2, }, + Enemy { + target: Option, + }, } impl Component for Agent { diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index 8a5687ccfe..8c8a7dd0b8 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -1,25 +1,31 @@ // Library use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; use vek::*; +use rand::Rng; // Crate -use crate::comp::{phys::Pos, Agent, Control, Jumping}; +use crate::{ + comp::{phys::Pos, Agent, Control, Jumping, Attacking}, + state::Time, +}; // Basic ECS AI agent system pub struct Sys; impl<'a> System<'a> for Sys { type SystemData = ( + Read<'a, Time>, Entities<'a>, WriteStorage<'a, Agent>, ReadStorage<'a, Pos>, WriteStorage<'a, Control>, WriteStorage<'a, Jumping>, + WriteStorage<'a, Attacking>, ); fn run( &mut self, - (entities, mut agents, positions, mut controls, mut jumpings): Self::SystemData, + (time, entities, mut agents, positions, mut controls, mut jumpings, mut attackings): Self::SystemData, ) { for (entity, agent, pos, control) in (&entities, &mut agents, &positions, &mut controls).join() @@ -64,7 +70,43 @@ impl<'a> System<'a> for Sys { Vec2::new(rand::random::() - 0.5, rand::random::() - 0.5) * 10.0; } - } + }, + Agent::Enemy { target } => { + let choose_new = match target.map(|tgt| positions.get(tgt)).flatten() { + Some(tgt_pos) => { + let dist = Vec2::::from(tgt_pos.0 - pos.0).magnitude(); + if dist < 2.0 { + control.move_dir = Vec2::zero(); + + if rand::random::() < 0.2 { + attackings.insert(entity, Attacking::start()); + } + + false + } else if dist < 60.0 { + control.move_dir = Vec2::::from(tgt_pos.0 - pos.0).normalized() * 0.96; + + false + } else { + true + } + }, + None => { + control.move_dir = Vec2::one(); + rand::random::().fract() < 0.25 + }, + }; + + if choose_new { + let entities = (&entities, &positions) + .join() + .filter(|(_, e_pos)| Vec2::::from(e_pos.0 - pos.0).magnitude() < 30.0) + .map(|(e, _)| e) + .collect::>(); + + *target = rand::thread_rng().choose(&entities).cloned(); + } + }, } } } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 74c975eccb..5771e06090 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -93,6 +93,12 @@ lazy_static! { "/wolf : Spawn a test wolf NPC", handle_petwolf ), + ChatCommand::new( + "enemy", + "{}", + "/enemy : Spawn a test enemy NPC", + handle_enemy + ), ChatCommand::new( "help", "", "/help: Display this message", handle_help) ]; @@ -266,6 +272,32 @@ fn handle_petwolf(server: &mut Server, entity: EcsEntity, args: String, action: .notify(entity, ServerMsg::Chat("You have no position!".to_owned())), } } +fn handle_enemy(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { + match server + .state + .read_component_cloned::(entity) + { + Some(mut pos) => { + pos.0.x += 1.0; // Temp fix TODO: Solve NaN issue with positions of pets + server + .create_npc( + pos, + "Tobermory".to_owned(), + comp::Body::Humanoid(comp::HumanoidBody::random()), + ) + .with(comp::Agent::Enemy { + target: None, + }) + .build(); + server + .clients + .notify(entity, ServerMsg::Chat("Spawned enemy!".to_owned())); + } + None => server + .clients + .notify(entity, ServerMsg::Chat("You have no position!".to_owned())), + } +} fn handle_help(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { for cmd in CHAT_COMMANDS.iter() { server diff --git a/server/src/lib.rs b/server/src/lib.rs index ca9e52afa2..23e055bbf9 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -136,12 +136,13 @@ impl Server { .ecs_mut() .create_entity_synced() .with(pos) - .with(comp::Control::default()) .with(comp::phys::Vel(Vec3::zero())) .with(comp::phys::Dir(Vec3::unit_y())) + .with(comp::Control::default()) .with(comp::AnimationInfo::default()) .with(comp::Actor::Character { name, body }) .with(comp::Stats::default()) + .with(comp::phys::ForceUpdate) } pub fn create_player_character(