mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Switched to _squared(), added comments, parallelised waypoint gen
This commit is contained in:
parent
9d2d7a93e0
commit
e4c745e88d
@ -1,6 +1,6 @@
|
|||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![type_length_limit = "1664759"]
|
#![type_length_limit = "1664759"]
|
||||||
#![feature(trait_alias, arbitrary_enum_discriminant)]
|
#![feature(trait_alias, arbitrary_enum_discriminant, label_break_value)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
@ -89,8 +89,7 @@ impl Route {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chaser: A self-contained system that attempts to chase a moving target
|
/// A self-contained system that attempts to chase a moving target, only performing pathfinding if necessary
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
pub struct Chaser {
|
pub struct Chaser {
|
||||||
last_search_tgt: Option<Vec3<f32>>,
|
last_search_tgt: Option<Vec3<f32>>,
|
||||||
|
@ -80,6 +80,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
let mut do_idle = false;
|
let mut do_idle = false;
|
||||||
let mut choose_target = false;
|
let mut choose_target = false;
|
||||||
|
|
||||||
|
'activity: {
|
||||||
match &mut agent.activity {
|
match &mut agent.activity {
|
||||||
Activity::Idle(bearing) => {
|
Activity::Idle(bearing) => {
|
||||||
*bearing += Vec2::new(
|
*bearing += Vec2::new(
|
||||||
@ -106,14 +107,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
if let (Some(tgt_pos), _tgt_stats) =
|
if let (Some(tgt_pos), _tgt_stats) =
|
||||||
(positions.get(*target), stats.get(*target))
|
(positions.get(*target), stats.get(*target))
|
||||||
{
|
{
|
||||||
let dist = pos.0.distance(tgt_pos.0);
|
let dist_sqrd = pos.0.distance_squared(tgt_pos.0);
|
||||||
// Follow, or return to idle
|
// Follow, or return to idle
|
||||||
if dist > AVG_FOLLOW_DIST {
|
if dist_sqrd > AVG_FOLLOW_DIST.powf(2.0) {
|
||||||
if let Some(bearing) =
|
if let Some(bearing) =
|
||||||
chaser.chase(&*terrain, pos.0, tgt_pos.0, AVG_FOLLOW_DIST)
|
chaser.chase(&*terrain, pos.0, tgt_pos.0, AVG_FOLLOW_DIST)
|
||||||
{
|
{
|
||||||
inputs.move_dir =
|
inputs.move_dir = Vec2::from(bearing)
|
||||||
Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero());
|
.try_normalized()
|
||||||
|
.unwrap_or(Vec2::zero());
|
||||||
inputs.jump.set_state(bearing.z > 1.0);
|
inputs.jump.set_state(bearing.z > 1.0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -130,14 +132,18 @@ impl<'a> System<'a> for Sys {
|
|||||||
alignments.get(*target),
|
alignments.get(*target),
|
||||||
) {
|
) {
|
||||||
// Don't attack aligned entities
|
// Don't attack aligned entities
|
||||||
if let (Some(alignment), Some(tgt_alignment)) = (alignment, tgt_alignment) {
|
// TODO: This is a bit of a hack, find a better way to do this
|
||||||
|
if let (Some(alignment), Some(tgt_alignment)) =
|
||||||
|
(alignment, tgt_alignment)
|
||||||
|
{
|
||||||
if !tgt_alignment.hostile_towards(*alignment) {
|
if !tgt_alignment.hostile_towards(*alignment) {
|
||||||
do_idle = true;
|
do_idle = true;
|
||||||
|
break 'activity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dist = pos.0.distance(tgt_pos.0);
|
let dist_sqrd = pos.0.distance_squared(tgt_pos.0);
|
||||||
if dist < MIN_ATTACK_DIST {
|
if dist_sqrd < MIN_ATTACK_DIST.powf(2.0) {
|
||||||
// Close-range attack
|
// Close-range attack
|
||||||
inputs.look_dir = tgt_pos.0 - pos.0;
|
inputs.look_dir = tgt_pos.0 - pos.0;
|
||||||
inputs.move_dir = Vec2::from(tgt_pos.0 - pos.0)
|
inputs.move_dir = Vec2::from(tgt_pos.0 - pos.0)
|
||||||
@ -145,11 +151,14 @@ impl<'a> System<'a> for Sys {
|
|||||||
.unwrap_or(Vec2::unit_y())
|
.unwrap_or(Vec2::unit_y())
|
||||||
* 0.01;
|
* 0.01;
|
||||||
inputs.primary.set_state(true);
|
inputs.primary.set_state(true);
|
||||||
} else if dist < MAX_CHASE_DIST {
|
} else if dist_sqrd < MAX_CHASE_DIST.powf(2.0) {
|
||||||
// Long-range chase
|
// Long-range chase
|
||||||
if let Some(bearing) = chaser.chase(&*terrain, pos.0, tgt_pos.0, 1.25) {
|
if let Some(bearing) =
|
||||||
inputs.move_dir =
|
chaser.chase(&*terrain, pos.0, tgt_pos.0, 1.25)
|
||||||
Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero());
|
{
|
||||||
|
inputs.move_dir = Vec2::from(bearing)
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or(Vec2::zero());
|
||||||
inputs.jump.set_state(bearing.z > 1.0);
|
inputs.jump.set_state(bearing.z > 1.0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -160,17 +169,21 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if do_idle {
|
if do_idle {
|
||||||
agent.activity = Activity::Idle(Vec2::zero());
|
agent.activity = Activity::Idle(Vec2::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Choose a new target to attack: only go out of our way to attack targets we are
|
||||||
|
// hostile toward!
|
||||||
if choose_target {
|
if choose_target {
|
||||||
// Search for new targets
|
// Search for new targets (this looks expensive, but it's only run occasionally)
|
||||||
|
// TODO: Replace this with a better system that doesn't consider *all* entities
|
||||||
let entities = (&entities, &positions, &stats, alignments.maybe())
|
let entities = (&entities, &positions, &stats, alignments.maybe())
|
||||||
.join()
|
.join()
|
||||||
.filter(|(e, e_pos, e_stats, e_alignment)| {
|
.filter(|(e, e_pos, e_stats, e_alignment)| {
|
||||||
(e_pos.0 - pos.0).magnitude() < SIGHT_DIST
|
(e_pos.0 - pos.0).magnitude_squared() < SIGHT_DIST.powf(2.0)
|
||||||
&& *e != entity
|
&& *e != entity
|
||||||
&& !e_stats.is_dead
|
&& !e_stats.is_dead
|
||||||
&& alignment
|
&& alignment
|
||||||
@ -206,8 +219,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
// Follow owner if we're too far, or if they're under attack
|
// Follow owner if we're too far, or if they're under attack
|
||||||
if let Some(owner) = agent.owner {
|
if let Some(owner) = agent.owner {
|
||||||
if let Some(owner_pos) = positions.get(owner) {
|
if let Some(owner_pos) = positions.get(owner) {
|
||||||
let dist = pos.0.distance(owner_pos.0);
|
let dist_sqrd = pos.0.distance_squared(owner_pos.0);
|
||||||
if dist > MAX_FOLLOW_DIST && !agent.activity.is_follow() {
|
if dist_sqrd > MAX_FOLLOW_DIST.powf(2.0) && !agent.activity.is_follow() {
|
||||||
agent.activity = Activity::Follow(owner, Chaser::default());
|
agent.activity = Activity::Follow(owner, Chaser::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1088,10 +1088,11 @@ fn handle_remove_lights(
|
|||||||
match opt_player_pos {
|
match opt_player_pos {
|
||||||
Some(player_pos) => {
|
Some(player_pos) => {
|
||||||
let ecs = server.state.ecs();
|
let ecs = server.state.ecs();
|
||||||
for (entity, pos, _, _) in (
|
for (entity, pos, _, _, _) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<comp::Pos>(),
|
&ecs.read_storage::<comp::Pos>(),
|
||||||
&ecs.read_storage::<comp::LightEmitter>(),
|
&ecs.read_storage::<comp::LightEmitter>(),
|
||||||
|
!&ecs.read_storage::<comp::WaypointArea>(),
|
||||||
!&ecs.read_storage::<comp::Player>(),
|
!&ecs.read_storage::<comp::Player>(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
use common::comp::{Player, Pos, Waypoint, WaypointArea};
|
use common::comp::{Player, Pos, Waypoint, WaypointArea};
|
||||||
use specs::{Entities, Join, ReadStorage, System, WriteStorage};
|
use specs::{Entities, Join, ReadStorage, System, WriteStorage};
|
||||||
|
|
||||||
/// This system will handle loading generated chunks and unloading uneeded chunks.
|
/// This system updates player waypoints
|
||||||
/// 1. Inserts newly generated chunks into the TerrainGrid
|
/// TODO: Make this faster by only considering local waypoints
|
||||||
/// 2. Sends new chunks to neaby clients
|
|
||||||
/// 3. Handles the chunk's supplement (e.g. npcs)
|
|
||||||
/// 4. Removes chunks outside the range of players
|
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
|
@ -1454,7 +1454,12 @@ impl WorldSim {
|
|||||||
.map(|i| {
|
.map(|i| {
|
||||||
(0..WORLD_SIZE.y)
|
(0..WORLD_SIZE.y)
|
||||||
.step_by(WAYPOINT_EVERY)
|
.step_by(WAYPOINT_EVERY)
|
||||||
.filter_map(move |j| {
|
.map(move |j| (i, j))
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_par_iter()
|
||||||
|
.filter_map(|(i, j)| {
|
||||||
let mut pos = Vec2::new(i as i32, j as i32);
|
let mut pos = Vec2::new(i as i32, j as i32);
|
||||||
|
|
||||||
// Slide the waypoints down hills
|
// Slide the waypoints down hills
|
||||||
@ -1472,9 +1477,7 @@ impl WorldSim {
|
|||||||
{
|
{
|
||||||
const MAX_HEIGHT_DIFF: f32 = 8.0;
|
const MAX_HEIGHT_DIFF: f32 = 8.0;
|
||||||
let tgt_chunk = this.get(pos + *dir)?;
|
let tgt_chunk = this.get(pos + *dir)?;
|
||||||
if tgt_chunk.alt + MAX_HEIGHT_DIFF < chunk.alt
|
if tgt_chunk.alt + MAX_HEIGHT_DIFF < chunk.alt && !tgt_chunk.is_underwater {
|
||||||
&& !tgt_chunk.is_underwater
|
|
||||||
{
|
|
||||||
pos += *dir;
|
pos += *dir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1486,8 +1489,6 @@ impl WorldSim {
|
|||||||
|
|
||||||
Some(pos)
|
Some(pos)
|
||||||
})
|
})
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for waypoint in waypoints {
|
for waypoint in waypoints {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user