mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'enemies' into 'master'
Enemies See merge request veloren/veloren!186 Former-commit-id: f920608508868119aad286cbe45599342dc1942b
This commit is contained in:
commit
2fc4e9a2f8
@ -8,6 +8,9 @@ pub enum Agent {
|
|||||||
target: EcsEntity,
|
target: EcsEntity,
|
||||||
offset: Vec2<f32>,
|
offset: Vec2<f32>,
|
||||||
},
|
},
|
||||||
|
Enemy {
|
||||||
|
target: Option<EcsEntity>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Agent {
|
impl Component for Agent {
|
||||||
|
@ -1,25 +1,31 @@
|
|||||||
// Library
|
// Library
|
||||||
|
use rand::Rng;
|
||||||
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
// Crate
|
// Crate
|
||||||
use crate::comp::{phys::Pos, Agent, Control, Jumping};
|
use crate::{
|
||||||
|
comp::{phys::Pos, Agent, Attacking, Control, Jumping},
|
||||||
|
state::Time,
|
||||||
|
};
|
||||||
|
|
||||||
// Basic ECS AI agent system
|
// Basic ECS AI agent system
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
|
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
|
Read<'a, Time>,
|
||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
WriteStorage<'a, Agent>,
|
WriteStorage<'a, Agent>,
|
||||||
ReadStorage<'a, Pos>,
|
ReadStorage<'a, Pos>,
|
||||||
WriteStorage<'a, Control>,
|
WriteStorage<'a, Control>,
|
||||||
WriteStorage<'a, Jumping>,
|
WriteStorage<'a, Jumping>,
|
||||||
|
WriteStorage<'a, Attacking>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
&mut self,
|
&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
|
for (entity, agent, pos, control) in
|
||||||
(&entities, &mut agents, &positions, &mut controls).join()
|
(&entities, &mut agents, &positions, &mut controls).join()
|
||||||
@ -65,6 +71,45 @@ impl<'a> System<'a> for Sys {
|
|||||||
* 10.0;
|
* 10.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Agent::Enemy { target } => {
|
||||||
|
let choose_new = match target.map(|tgt| positions.get(tgt)).flatten() {
|
||||||
|
Some(tgt_pos) => {
|
||||||
|
let dist = Vec2::<f32>::from(tgt_pos.0 - pos.0).magnitude();
|
||||||
|
if dist < 2.0 {
|
||||||
|
control.move_dir = Vec2::zero();
|
||||||
|
|
||||||
|
if rand::random::<f32>() < 0.2 {
|
||||||
|
attackings.insert(entity, Attacking::start());
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
} else if dist < 60.0 {
|
||||||
|
control.move_dir =
|
||||||
|
Vec2::<f32>::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::<f32>::from(e_pos.0 - pos.0).magnitude() < 30.0
|
||||||
|
})
|
||||||
|
.map(|(e, _)| e)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
*target = rand::thread_rng().choose(&entities).cloned();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,12 @@ lazy_static! {
|
|||||||
"/wolf : Spawn a test wolf NPC",
|
"/wolf : Spawn a test wolf NPC",
|
||||||
handle_petwolf
|
handle_petwolf
|
||||||
),
|
),
|
||||||
|
ChatCommand::new(
|
||||||
|
"enemy",
|
||||||
|
"{}",
|
||||||
|
"/enemy : Spawn a test enemy NPC",
|
||||||
|
handle_enemy
|
||||||
|
),
|
||||||
ChatCommand::new(
|
ChatCommand::new(
|
||||||
"help", "", "/help: Display this message", handle_help)
|
"help", "", "/help: Display this message", handle_help)
|
||||||
];
|
];
|
||||||
@ -266,6 +272,30 @@ fn handle_petwolf(server: &mut Server, entity: EcsEntity, args: String, action:
|
|||||||
.notify(entity, ServerMsg::Chat("You have no position!".to_owned())),
|
.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::<comp::phys::Pos>(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) {
|
fn handle_help(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) {
|
||||||
for cmd in CHAT_COMMANDS.iter() {
|
for cmd in CHAT_COMMANDS.iter() {
|
||||||
server
|
server
|
||||||
|
@ -143,12 +143,13 @@ impl Server {
|
|||||||
.ecs_mut()
|
.ecs_mut()
|
||||||
.create_entity_synced()
|
.create_entity_synced()
|
||||||
.with(pos)
|
.with(pos)
|
||||||
.with(comp::Control::default())
|
|
||||||
.with(comp::phys::Vel(Vec3::zero()))
|
.with(comp::phys::Vel(Vec3::zero()))
|
||||||
.with(comp::phys::Dir(Vec3::unit_y()))
|
.with(comp::phys::Dir(Vec3::unit_y()))
|
||||||
|
.with(comp::Control::default())
|
||||||
.with(comp::AnimationInfo::default())
|
.with(comp::AnimationInfo::default())
|
||||||
.with(comp::Actor::Character { name, body })
|
.with(comp::Actor::Character { name, body })
|
||||||
.with(comp::Stats::default())
|
.with(comp::Stats::default())
|
||||||
|
.with(comp::phys::ForceUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_player_character(
|
pub fn create_player_character(
|
||||||
|
Loading…
Reference in New Issue
Block a user