From baf740a289ea826c39babdc5c7fac84723778ea4 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 27 May 2019 12:18:14 +0100 Subject: [PATCH 1/3] 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( From bfc70f4d78c4528b7695849d7d82d1f057385cab Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 28 May 2019 00:04:25 +0100 Subject: [PATCH 2/3] Sort of fixed enemy freezes Former-commit-id: 30933b3ff7d16428a107ade6163cb83562668b66 --- common/src/sys/agent.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index 8c8a7dd0b8..a9dcf46dc8 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -93,7 +93,7 @@ impl<'a> System<'a> for Sys { }, None => { control.move_dir = Vec2::one(); - rand::random::().fract() < 0.25 + true }, }; From 8407908af280e342e5c064ec894d345ae53eca47 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 28 May 2019 19:59:32 +0100 Subject: [PATCH 3/3] fmt Former-commit-id: 7535fe743722967dd59e383aa93cb78cb3be6e23 --- common/src/sys/agent.rs | 19 +++++++++++-------- server/src/cmd.rs | 4 +--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index a9dcf46dc8..1b8e359d31 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -1,11 +1,11 @@ // Library +use rand::Rng; use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; use vek::*; -use rand::Rng; // Crate use crate::{ - comp::{phys::Pos, Agent, Control, Jumping, Attacking}, + comp::{phys::Pos, Agent, Attacking, Control, Jumping}, state::Time, }; @@ -70,7 +70,7 @@ 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) => { @@ -84,29 +84,32 @@ impl<'a> System<'a> for Sys { false } else if dist < 60.0 { - control.move_dir = Vec2::::from(tgt_pos.0 - pos.0).normalized() * 0.96; + control.move_dir = + Vec2::::from(tgt_pos.0 - pos.0).normalized() * 0.96; false } else { true } - }, + } None => { control.move_dir = Vec2::one(); true - }, + } }; if choose_new { let entities = (&entities, &positions) .join() - .filter(|(_, e_pos)| Vec2::::from(e_pos.0 - pos.0).magnitude() < 30.0) + .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 5771e06090..d21c554416 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -285,9 +285,7 @@ fn handle_enemy(server: &mut Server, entity: EcsEntity, args: String, action: &C "Tobermory".to_owned(), comp::Body::Humanoid(comp::HumanoidBody::random()), ) - .with(comp::Agent::Enemy { - target: None, - }) + .with(comp::Agent::Enemy { target: None }) .build(); server .clients