mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Cleanup
This commit is contained in:
parent
feeccc2ff3
commit
b22ee24362
@ -34,90 +34,6 @@ impl<S: Eq> PartialOrd for PathEntry<S> {
|
||||
}
|
||||
}
|
||||
|
||||
fn reconstruct_path<S>(came_from: &HashMap<S, S>, target: &S) -> Vec<S>
|
||||
where
|
||||
S: Clone + Eq + Hash,
|
||||
{
|
||||
let mut path = Vec::new();
|
||||
path.push(target.to_owned());
|
||||
let mut cur_node = target;
|
||||
while let Some(node) = came_from.get(cur_node) {
|
||||
path.push(node.to_owned());
|
||||
cur_node = node;
|
||||
}
|
||||
path
|
||||
}
|
||||
|
||||
pub fn astar<S, I>(
|
||||
initial: S,
|
||||
target: S,
|
||||
mut heuristic: impl FnMut(&S, &S) -> f32,
|
||||
mut neighbors: impl FnMut(&S) -> I,
|
||||
mut transition_cost: impl FnMut(&S, &S) -> f32,
|
||||
) -> Option<Vec<S>>
|
||||
where
|
||||
S: Clone + Eq + Hash,
|
||||
I: IntoIterator<Item = S>,
|
||||
{
|
||||
// Set of discovered nodes so far
|
||||
let mut potential_nodes = BinaryHeap::new();
|
||||
potential_nodes.push(PathEntry {
|
||||
cost: 0.0f32,
|
||||
node: initial.clone(),
|
||||
});
|
||||
|
||||
// For entry e, contains the cheapest node preceding it on the known path from start to e
|
||||
let mut came_from = HashMap::new();
|
||||
|
||||
// Contains cheapest cost from 'initial' to the current entry
|
||||
let mut cheapest_scores = HashMap::new();
|
||||
cheapest_scores.insert(initial.clone(), 0.0f32);
|
||||
|
||||
// Contains cheapest score to get to node + heuristic to the end, for an entry
|
||||
let mut final_scores = HashMap::new();
|
||||
final_scores.insert(initial.clone(), heuristic(&initial, &target));
|
||||
|
||||
// Set of nodes we have already visited
|
||||
let mut visited = HashSet::new();
|
||||
visited.insert(initial.clone());
|
||||
|
||||
let mut iters = 0;
|
||||
while let Some(PathEntry { node: current, .. }) = potential_nodes.pop() {
|
||||
if current == target {
|
||||
return Some(reconstruct_path(&came_from, ¤t));
|
||||
}
|
||||
|
||||
let current_neighbors = neighbors(¤t);
|
||||
for neighbor in current_neighbors {
|
||||
let current_cheapest_score = cheapest_scores.get(¤t).unwrap_or(&f32::MAX);
|
||||
let neighbor_cheapest_score = cheapest_scores.get(&neighbor).unwrap_or(&f32::MAX);
|
||||
let score = current_cheapest_score + transition_cost(¤t, &neighbor);
|
||||
if score < *neighbor_cheapest_score {
|
||||
// Path to the neighbor is better than anything yet recorded
|
||||
came_from.insert(neighbor.to_owned(), current.to_owned());
|
||||
cheapest_scores.insert(neighbor.clone(), score);
|
||||
let neighbor_score = score + heuristic(&neighbor, &target);
|
||||
final_scores.insert(neighbor.clone(), neighbor_score);
|
||||
|
||||
if visited.insert(neighbor.clone()) {
|
||||
potential_nodes.push(PathEntry {
|
||||
node: neighbor.clone(),
|
||||
cost: neighbor_score,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iters += 1;
|
||||
if iters >= 10000 {
|
||||
println!("Ran out of turns!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub enum PathResult<T> {
|
||||
None(Path<T>),
|
||||
Exhausted(Path<T>),
|
||||
|
@ -94,9 +94,8 @@ impl<'a> System<'a> for Sys {
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(wander_pos) = wander_pos {
|
||||
if let Some(bearing) = chaser.chase(&*terrain, pos.0, *wander_pos, 2.0)
|
||||
{
|
||||
if let Some(wp) = wander_pos {
|
||||
if let Some(bearing) = chaser.chase(&*terrain, pos.0, *wp, 2.0) {
|
||||
inputs.move_dir =
|
||||
Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero());
|
||||
inputs.jump.set_state(bearing.z > 1.0);
|
||||
@ -227,153 +226,6 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
const PET_DIST: f32 = 6.0;
|
||||
const MAX_PET_DIST: f32 = 16.0;
|
||||
const PATROL_DIST: f32 = 32.0;
|
||||
const SIGHT_DIST: f32 = 24.0;
|
||||
const MIN_ATTACK_DIST: f32 = 3.25;
|
||||
const CHASE_TIME_MIN: f64 = 4.0;
|
||||
|
||||
let mut chase_tgt = None;
|
||||
let mut choose_target = false;
|
||||
let mut new_target = None;
|
||||
|
||||
if let Some((target, aggro_time)) = agent.target {
|
||||
// Chase / attack target
|
||||
if let (Some(tgt_pos), stats) = (positions.get(target), stats.get(target)) {
|
||||
if stats.map(|s| s.is_dead).unwrap_or(false) {
|
||||
// Don't target dead entities
|
||||
choose_target = true;
|
||||
} else if pos.0.distance(tgt_pos.0) < SIGHT_DIST
|
||||
|| (time.0 - aggro_time) < CHASE_TIME_MIN
|
||||
{
|
||||
chase_tgt = Some((tgt_pos.0, 1.5, true))
|
||||
} else {
|
||||
// Lose sight of enemies
|
||||
choose_target = true;
|
||||
}
|
||||
} else {
|
||||
choose_target = true;
|
||||
}
|
||||
} else {
|
||||
choose_target = thread_rng().gen::<f32>() < 0.05;
|
||||
}
|
||||
|
||||
// Return to owner
|
||||
if let Some(owner) = agent.owner {
|
||||
if let Some(tgt_pos) = positions.get(owner) {
|
||||
let dist = pos.0.distance(tgt_pos.0);
|
||||
if dist > MAX_PET_DIST || (dist > PET_DIST && agent.target.is_none()) {
|
||||
// Follow owner
|
||||
chase_tgt = Some((tgt_pos.0, 6.0, false));
|
||||
} else if agent.target.is_none() {
|
||||
choose_target = thread_rng().gen::<f32>() < 0.02;
|
||||
}
|
||||
} else {
|
||||
agent.owner = None;
|
||||
}
|
||||
} else if let Some(patrol_origin) = agent.patrol_origin {
|
||||
if pos.0.distance(patrol_origin) > PATROL_DIST {
|
||||
// Return to patrol origin
|
||||
chase_tgt = Some((patrol_origin, 64.0, false));
|
||||
}
|
||||
}
|
||||
|
||||
// Attack a target that's attacking us
|
||||
if let Some(stats) = stats.get(entity) {
|
||||
match stats.health.last_change.1.cause {
|
||||
comp::HealthSource::Attack { by } => {
|
||||
if agent.target.is_none() {
|
||||
new_target = uid_allocator.retrieve_entity_internal(by.id());
|
||||
} else if thread_rng().gen::<f32>() < 0.005 {
|
||||
new_target = uid_allocator.retrieve_entity_internal(by.id());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Choose a new target
|
||||
if choose_target {
|
||||
// Search for new targets
|
||||
let entities = (&entities, &positions, &stats, alignments.maybe())
|
||||
.join()
|
||||
.filter(|(e, e_pos, e_stats, e_alignment)| {
|
||||
(e_pos.0 - pos.0).magnitude() < SIGHT_DIST
|
||||
&& *e != entity
|
||||
&& !e_stats.is_dead
|
||||
&& alignment
|
||||
.and_then(|a| e_alignment.map(|b| a.hostile_towards(*b)))
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.map(|(e, _, _, _)| e)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
new_target = (&entities).choose(&mut thread_rng()).cloned();
|
||||
}
|
||||
|
||||
// Update target when attack begins
|
||||
match agent.target {
|
||||
Some((tgt, time)) if Some(tgt) == new_target => {},
|
||||
_ => agent.target = new_target.map(|tgt| (tgt, time.0))
|
||||
}
|
||||
|
||||
// Chase target
|
||||
if let Some((tgt_pos, min_dist, aggressive)) = chase_tgt {
|
||||
if let Some(bearing) = agent.chaser.chase(&*terrain, pos.0, tgt_pos, min_dist) {
|
||||
inputs.move_dir = Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero());
|
||||
inputs.jump.set_state(bearing.z > 1.0);
|
||||
}
|
||||
|
||||
if aggressive && pos.0.distance(tgt_pos) < MIN_ATTACK_DIST {
|
||||
inputs.look_dir = tgt_pos - pos.0;
|
||||
inputs.move_dir = Vec2::from(tgt_pos - pos.0)
|
||||
.try_normalized()
|
||||
.unwrap_or(Vec2::zero())
|
||||
* 0.01;
|
||||
inputs.primary.set_state(true);
|
||||
}
|
||||
|
||||
// We're not wandering
|
||||
agent.wander_pos = None;
|
||||
} else {
|
||||
if let Some(wander_pos) = agent.wander_pos {
|
||||
if pos.0.distance(wander_pos) < 4.0 {
|
||||
agent.wander_pos = None;
|
||||
} else {
|
||||
if let Some(bearing) = agent.chaser.chase(&*terrain, pos.0, wander_pos, 3.0)
|
||||
{
|
||||
inputs.move_dir =
|
||||
Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero()) * 0.5;
|
||||
inputs.jump.set_state(bearing.z > 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Choose new wander position
|
||||
/*
|
||||
if agent.wander_pos.is_none() || thread_rng().gen::<f32>() < 0.005 {
|
||||
agent.wander_pos = if thread_rng().gen::<f32>() < 0.5 {
|
||||
let max_dist = if agent.owner.is_some() {
|
||||
PET_DIST
|
||||
} else {
|
||||
PATROL_DIST
|
||||
};
|
||||
Some(
|
||||
agent
|
||||
.patrol_origin
|
||||
.unwrap_or(pos.0)
|
||||
.map(|e| e + (thread_rng().gen::<f32>() - 0.5) * max_dist),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
*/
|
||||
}
|
||||
*/
|
||||
|
||||
debug_assert!(inputs.move_dir.map(|e| !e.is_nan()).reduce_and());
|
||||
debug_assert!(inputs.look_dir.map(|e| !e.is_nan()).reduce_and());
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use common::{
|
||||
npc::{get_npc_name, NpcKind},
|
||||
state::TimeOfDay,
|
||||
sync::{Uid, WorldSyncExt},
|
||||
terrain::{Block, BlockKind, TerrainChunkSize},
|
||||
terrain::TerrainChunkSize,
|
||||
vol::RectVolSize,
|
||||
};
|
||||
use rand::Rng;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use common::comp::{Player, Pos, Waypoint, WaypointArea};
|
||||
use specs::{Entities, Join, Read, ReadStorage, System, Write, WriteStorage};
|
||||
use specs::{Entities, Join, ReadStorage, System, WriteStorage};
|
||||
|
||||
/// This system will handle loading generated chunks and unloading uneeded chunks.
|
||||
/// 1. Inserts newly generated chunks into the TerrainGrid
|
||||
|
Loading…
Reference in New Issue
Block a user