mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add CustomPath to Travel enum
Defines a custom path to follow, instead of using one from the World. Airships use this to slightly adjust their course to reduce collisions.
This commit is contained in:
parent
7f9ec9e19b
commit
be67ba1e63
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -2650,6 +2650,12 @@ version = "0.1.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
|
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
@ -3345,6 +3351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"libm 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3587,7 +3594,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
|
checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
"libm",
|
"libm 0.1.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3965,6 +3972,16 @@ dependencies = [
|
|||||||
"getrandom 0.2.2",
|
"getrandom 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_distr"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da9e8f32ad24fb80d07d2323a9a2ce8b30d68a62b8cb4df88119ff49a698f038"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
"rand 0.8.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_hc"
|
name = "rand_hc"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -5574,6 +5591,7 @@ dependencies = [
|
|||||||
"prometheus",
|
"prometheus",
|
||||||
"prometheus-hyper",
|
"prometheus-hyper",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
|
"rand_distr",
|
||||||
"rayon",
|
"rayon",
|
||||||
"ron",
|
"ron",
|
||||||
"scan_fmt",
|
"scan_fmt",
|
||||||
|
@ -49,6 +49,7 @@ diesel = { version = "1.4.3", features = ["sqlite"] }
|
|||||||
diesel_migrations = "1.4.0"
|
diesel_migrations = "1.4.0"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
slab = "0.4"
|
slab = "0.4"
|
||||||
|
rand_distr = "0.4.0"
|
||||||
|
|
||||||
# Plugins
|
# Plugins
|
||||||
plugin-api = { package = "veloren-plugin-api", path = "../plugin/api"}
|
plugin-api = { package = "veloren-plugin-api", path = "../plugin/api"}
|
||||||
|
@ -6,6 +6,8 @@ use common::{
|
|||||||
store::Id,
|
store::Id,
|
||||||
terrain::TerrainGrid,
|
terrain::TerrainGrid,
|
||||||
};
|
};
|
||||||
|
use rand_distr::{Distribution, Normal};
|
||||||
|
use std::f32::consts::PI;
|
||||||
use world::{
|
use world::{
|
||||||
civ::{Site, Track},
|
civ::{Site, Track},
|
||||||
util::RandomPerm,
|
util::RandomPerm,
|
||||||
@ -132,56 +134,107 @@ impl Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self, time: &Time, terrain: &TerrainGrid, world: &World, index: &IndexRef) {
|
pub fn tick(&mut self, time: &Time, terrain: &TerrainGrid, world: &World, index: &IndexRef) {
|
||||||
self.brain.route = match self.brain.route {
|
self.brain.route = match self.brain.route.clone() {
|
||||||
Travel::Lost => {
|
Travel::Lost => {
|
||||||
if !self.get_body().is_humanoid() {
|
match self.get_body() {
|
||||||
if let Some(target_id) = world
|
comp::Body::Humanoid(_) => {
|
||||||
.civs()
|
if let Some(nearest_site_id) = world
|
||||||
.sites
|
.civs()
|
||||||
.iter()
|
.sites
|
||||||
.filter(|s| match self.get_body() {
|
.iter()
|
||||||
comp::Body::Ship(_) => s.1.is_settlement(),
|
.min_by_key(|(_, site)| {
|
||||||
_ => s.1.is_dungeon(),
|
let wpos = site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);
|
||||||
})
|
wpos.map(|e| e as f32).distance(self.pos.xy()) as u32
|
||||||
.filter(|_| thread_rng().gen_range(0i32..4) == 0)
|
})
|
||||||
.min_by_key(|(_, site)| {
|
.map(|(id, _)| id)
|
||||||
let wpos = site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);
|
{
|
||||||
let dist = wpos.map(|e| e as f32).distance(self.pos.xy()) as u32;
|
let nearest_site = &world.civs().sites[nearest_site_id];
|
||||||
dist + if dist < 96 { 100_000 } else { 0 }
|
let site_wpos =
|
||||||
})
|
nearest_site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);
|
||||||
.map(|(id, _)| id)
|
let dist = site_wpos.map(|e| e as f32).distance(self.pos.xy()) as u32;
|
||||||
{
|
if dist < 32 {
|
||||||
Travel::Direct { target_id }
|
Travel::InSite {
|
||||||
} else {
|
site_id: nearest_site_id,
|
||||||
Travel::Lost
|
}
|
||||||
}
|
} else {
|
||||||
} else if let Some(nearest_site_id) = world
|
Travel::Direct {
|
||||||
.civs()
|
target_id: nearest_site_id,
|
||||||
.sites
|
}
|
||||||
.iter()
|
}
|
||||||
.min_by_key(|(_, site)| {
|
} else {
|
||||||
let wpos = site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);
|
// Somehow no nearest site could be found
|
||||||
wpos.map(|e| e as f32).distance(self.pos.xy()) as u32
|
// Logically this should never happen, but if it does the rtsim entity
|
||||||
})
|
// will just sit tight
|
||||||
.map(|(id, _)| id)
|
Travel::Lost
|
||||||
{
|
|
||||||
let nearest_site = &world.civs().sites[nearest_site_id];
|
|
||||||
let site_wpos = nearest_site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);
|
|
||||||
let dist = site_wpos.map(|e| e as f32).distance(self.pos.xy()) as u32;
|
|
||||||
if dist < 32 {
|
|
||||||
Travel::InSite {
|
|
||||||
site_id: nearest_site_id,
|
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
Travel::Direct {
|
comp::Body::Ship(_) => {
|
||||||
target_id: nearest_site_id,
|
if let Some((target_id, site)) = world
|
||||||
|
.civs()
|
||||||
|
.sites
|
||||||
|
.iter()
|
||||||
|
.filter(|s| match self.get_body() {
|
||||||
|
comp::Body::Ship(_) => s.1.is_settlement(),
|
||||||
|
_ => s.1.is_dungeon(),
|
||||||
|
})
|
||||||
|
.filter(|_| thread_rng().gen_range(0i32..4) == 0)
|
||||||
|
.min_by_key(|(_, site)| {
|
||||||
|
let wpos = site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);
|
||||||
|
let dist = wpos.map(|e| e as f32).distance(self.pos.xy()) as u32;
|
||||||
|
dist + if dist < 96 { 100_000 } else { 0 }
|
||||||
|
})
|
||||||
|
{
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
if let (Ok(normalpos), Ok(normalrad)) =
|
||||||
|
(Normal::new(0.0, 64.0), (Normal::new(0.0, PI / 8.0)))
|
||||||
|
{
|
||||||
|
let mut path = Vec::<Vec2<i32>>::default();
|
||||||
|
let target_site_pos = site.center.map(|e| e as f32)
|
||||||
|
* TerrainChunk::RECT_SIZE.map(|e| e as f32);
|
||||||
|
let offset_site_pos =
|
||||||
|
target_site_pos.map(|v| v + normalpos.sample(&mut rng));
|
||||||
|
let dir_vec = (offset_site_pos - self.pos.xy()).normalized();
|
||||||
|
let dist = (offset_site_pos - self.pos.xy()).magnitude();
|
||||||
|
let inbetween_dir = dir_vec.rotated_z(normalrad.sample(&mut rng));
|
||||||
|
let inbetween_pos = self.pos.xy() + (inbetween_dir * (dist / 2.0));
|
||||||
|
|
||||||
|
path.push(inbetween_pos.map(|e| e as i32));
|
||||||
|
path.push(target_site_pos.map(|e| e as i32));
|
||||||
|
|
||||||
|
Travel::CustomPath {
|
||||||
|
target_id,
|
||||||
|
path,
|
||||||
|
progress: 0,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Travel::Direct { target_id }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Travel::Lost
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
} else {
|
_ => {
|
||||||
// Somehow no nearest site could be found
|
if let Some(target_id) = world
|
||||||
// Logically this should never happen, but if it does the rtsim entity will just
|
.civs()
|
||||||
// sit tight
|
.sites
|
||||||
Travel::Lost
|
.iter()
|
||||||
|
.filter(|s| match self.get_body() {
|
||||||
|
comp::Body::Ship(_) => s.1.is_settlement(),
|
||||||
|
_ => s.1.is_dungeon(),
|
||||||
|
})
|
||||||
|
.filter(|_| thread_rng().gen_range(0i32..4) == 0)
|
||||||
|
.min_by_key(|(_, site)| {
|
||||||
|
let wpos = site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);
|
||||||
|
let dist = wpos.map(|e| e as f32).distance(self.pos.xy()) as u32;
|
||||||
|
dist + if dist < 96 { 100_000 } else { 0 }
|
||||||
|
})
|
||||||
|
.map(|(id, _)| id)
|
||||||
|
{
|
||||||
|
Travel::Direct { target_id }
|
||||||
|
} else {
|
||||||
|
Travel::Lost
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Travel::InSite { site_id } => {
|
Travel::InSite { site_id } => {
|
||||||
@ -251,6 +304,60 @@ impl Entity {
|
|||||||
Travel::Direct { target_id }
|
Travel::Direct { target_id }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Travel::CustomPath {
|
||||||
|
target_id,
|
||||||
|
path,
|
||||||
|
progress,
|
||||||
|
} => {
|
||||||
|
let site = &world.civs().sites[target_id];
|
||||||
|
let destination_name = site
|
||||||
|
.site_tmp
|
||||||
|
.map_or("".to_string(), |id| index.sites[id].name().to_string());
|
||||||
|
|
||||||
|
if let Some(wpos) = &path.get(progress) {
|
||||||
|
let dist = wpos.map(|e| e as f32).distance(self.pos.xy()) as u32;
|
||||||
|
if dist < 64 {
|
||||||
|
if progress + 1 < path.len() {
|
||||||
|
Travel::CustomPath {
|
||||||
|
target_id,
|
||||||
|
path,
|
||||||
|
progress: progress + 1,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Travel::InSite { site_id: target_id }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let travel_to = self.pos.xy()
|
||||||
|
+ Vec3::from(
|
||||||
|
(wpos.map(|e| e as f32 + 0.5) - self.pos.xy())
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_else(Vec2::zero),
|
||||||
|
) * 64.0;
|
||||||
|
let travel_to_alt = world
|
||||||
|
.sim()
|
||||||
|
.get_alt_approx(travel_to.map(|e| e as i32))
|
||||||
|
.unwrap_or(0.0) as i32;
|
||||||
|
let travel_to = terrain
|
||||||
|
.find_space(Vec3::new(
|
||||||
|
travel_to.x as i32,
|
||||||
|
travel_to.y as i32,
|
||||||
|
travel_to_alt,
|
||||||
|
))
|
||||||
|
.map(|e| e as f32)
|
||||||
|
+ Vec3::new(0.5, 0.5, 0.0);
|
||||||
|
|
||||||
|
self.controller.travel_to = Some((travel_to, destination_name));
|
||||||
|
self.controller.speed_factor = 0.70;
|
||||||
|
Travel::CustomPath {
|
||||||
|
target_id,
|
||||||
|
path,
|
||||||
|
progress,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Travel::Direct { target_id }
|
||||||
|
}
|
||||||
|
},
|
||||||
Travel::Path {
|
Travel::Path {
|
||||||
target_id,
|
target_id,
|
||||||
track_id,
|
track_id,
|
||||||
@ -345,6 +452,7 @@ impl Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
enum Travel {
|
enum Travel {
|
||||||
Lost,
|
Lost,
|
||||||
InSite {
|
InSite {
|
||||||
@ -353,6 +461,11 @@ enum Travel {
|
|||||||
Direct {
|
Direct {
|
||||||
target_id: Id<Site>,
|
target_id: Id<Site>,
|
||||||
},
|
},
|
||||||
|
CustomPath {
|
||||||
|
target_id: Id<Site>,
|
||||||
|
path: Vec<Vec2<i32>>,
|
||||||
|
progress: usize,
|
||||||
|
},
|
||||||
Path {
|
Path {
|
||||||
target_id: Id<Site>,
|
target_id: Id<Site>,
|
||||||
track_id: Id<Track>,
|
track_id: Id<Track>,
|
||||||
|
Loading…
Reference in New Issue
Block a user