Merge branch 'swilliams/hitbox-adjustments' into 'master'

General NPC Hitbox Adjustments

See merge request veloren/veloren!1723
This commit is contained in:
Samuel Keiffer 2021-01-24 04:00:57 +00:00
commit bdbed58b09
4 changed files with 95 additions and 79 deletions

View File

@ -37,7 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Changed camera smoothing to be off by default.
- Fixed AI behavior so only humanoids will attempt to roll
- Footstep SFX is now dependant on distance moved, not time since last play
- Increased the hitbox of the Stonework Defender and Mindflayer to better fit their models.
- Adjusted most NPCs hitboxes to better fit their models.
### Removed

View File

@ -141,49 +141,62 @@ impl Body {
// TODO: Improve these values (some might be reliant on more info in inner type)
match self {
Body::Humanoid(humanoid) => match (humanoid.species, humanoid.body_type) {
(humanoid::Species::Orc, humanoid::BodyType::Male) => 0.57,
(humanoid::Species::Orc, humanoid::BodyType::Female) => 0.51,
(humanoid::Species::Human, humanoid::BodyType::Male) => 0.51,
(humanoid::Species::Human, humanoid::BodyType::Female) => 0.48,
(humanoid::Species::Elf, humanoid::BodyType::Male) => 0.51,
(humanoid::Species::Elf, humanoid::BodyType::Female) => 0.48,
(humanoid::Species::Dwarf, humanoid::BodyType::Male) => 0.42,
(humanoid::Species::Dwarf, humanoid::BodyType::Female) => 0.39,
(humanoid::Species::Undead, humanoid::BodyType::Male) => 0.48,
(humanoid::Species::Undead, humanoid::BodyType::Female) => 0.45,
(humanoid::Species::Danari, humanoid::BodyType::Male) => 0.348,
(humanoid::Species::Danari, humanoid::BodyType::Female) => 0.348,
_ => 0.5,
(humanoid::Species::Orc, humanoid::BodyType::Male) => 0.75,
(humanoid::Species::Orc, humanoid::BodyType::Female) => 0.75,
(humanoid::Species::Human, humanoid::BodyType::Male) => 0.75,
(humanoid::Species::Human, humanoid::BodyType::Female) => 0.75,
(humanoid::Species::Elf, humanoid::BodyType::Male) => 0.75,
(humanoid::Species::Elf, humanoid::BodyType::Female) => 0.75,
(humanoid::Species::Dwarf, humanoid::BodyType::Male) => 0.75,
(humanoid::Species::Dwarf, humanoid::BodyType::Female) => 0.75,
(humanoid::Species::Undead, humanoid::BodyType::Male) => 0.75,
(humanoid::Species::Undead, humanoid::BodyType::Female) => 0.75,
(humanoid::Species::Danari, humanoid::BodyType::Male) => 0.75,
(humanoid::Species::Danari, humanoid::BodyType::Female) => 0.75,
_ => 0.75,
},
Body::QuadrupedSmall(_) => 0.4,
Body::QuadrupedSmall(_) => 0.7,
Body::QuadrupedMedium(body) => match body.species {
quadruped_medium::Species::Grolgar => 1.9,
quadruped_medium::Species::Tarasque => 1.8,
quadruped_medium::Species::Lion => 1.9,
quadruped_medium::Species::Saber => 1.8,
quadruped_medium::Species::Catoblepas => 1.7,
quadruped_medium::Species::Grolgar => 2.0,
quadruped_medium::Species::Tarasque => 2.0,
quadruped_medium::Species::Lion => 2.0,
quadruped_medium::Species::Saber => 2.0,
quadruped_medium::Species::Catoblepas => 2.0,
quadruped_medium::Species::Horse => 1.5,
quadruped_medium::Species::Deer => 1.5,
quadruped_medium::Species::Donkey => 1.5,
quadruped_medium::Species::Kelpie => 1.5,
_ => 1.5,
},
Body::QuadrupedLow(body) => match body.species {
quadruped_low::Species::Asp => 1.8,
quadruped_low::Species::Monitor => 1.75,
quadruped_low::Species::Crocodile => 2.1,
quadruped_low::Species::Salamander => 1.9,
quadruped_low::Species::Pangolin => 1.3,
quadruped_low::Species::Asp => 2.5,
quadruped_low::Species::Monitor => 2.3,
quadruped_low::Species::Crocodile => 2.4,
quadruped_low::Species::Salamander => 2.4,
quadruped_low::Species::Pangolin => 2.0,
quadruped_low::Species::Lavadrake => 2.5,
_ => 1.6,
},
Body::Theropod(body) => match body.species {
theropod::Species::Snowraptor => 0.5,
theropod::Species::Sandraptor => 0.5,
theropod::Species::Woodraptor => 0.5,
theropod::Species::Snowraptor => 1.5,
theropod::Species::Sandraptor => 1.5,
theropod::Species::Woodraptor => 1.5,
theropod::Species::Archaeos => 4.5,
theropod::Species::Odonto => 4.5,
_ => 1.8,
},
Body::BirdMedium(_) => 0.35,
Body::FishMedium(_) => 0.35,
Body::BirdMedium(_) => 1.0,
Body::FishMedium(_) => 1.0,
Body::Dragon(_) => 8.0,
Body::BirdSmall(_) => 0.3,
Body::FishSmall(_) => 0.3,
Body::BipedLarge(_) => 1.5,
Body::BirdSmall(_) => 0.6,
Body::FishSmall(_) => 0.6,
Body::BipedLarge(body) => match body.species {
biped_large::Species::Slysaurok => 2.3,
biped_large::Species::Occultsaurok => 2.8,
biped_large::Species::Mightysaurok => 2.3,
biped_large::Species::Mindflayer => 1.8,
_ => 4.6,
},
Body::Golem(_) => 2.5,
Body::Object(_) => 0.4,
}
@ -192,18 +205,18 @@ impl Body {
pub fn height(&self) -> f32 {
match self {
Body::Humanoid(humanoid) => match (humanoid.species, humanoid.body_type) {
(humanoid::Species::Orc, humanoid::BodyType::Male) => 2.17,
(humanoid::Species::Orc, humanoid::BodyType::Female) => 1.94,
(humanoid::Species::Human, humanoid::BodyType::Male) => 1.94,
(humanoid::Species::Human, humanoid::BodyType::Female) => 1.82,
(humanoid::Species::Elf, humanoid::BodyType::Male) => 1.94,
(humanoid::Species::Elf, humanoid::BodyType::Female) => 1.82,
(humanoid::Species::Dwarf, humanoid::BodyType::Male) => 1.60,
(humanoid::Species::Dwarf, humanoid::BodyType::Female) => 1.48,
(humanoid::Species::Undead, humanoid::BodyType::Male) => 1.82,
(humanoid::Species::Undead, humanoid::BodyType::Female) => 1.71,
(humanoid::Species::Danari, humanoid::BodyType::Male) => 1.32,
(humanoid::Species::Danari, humanoid::BodyType::Female) => 1.32,
(humanoid::Species::Orc, humanoid::BodyType::Male) => 2.3,
(humanoid::Species::Orc, humanoid::BodyType::Female) => 2.2,
(humanoid::Species::Human, humanoid::BodyType::Male) => 2.3,
(humanoid::Species::Human, humanoid::BodyType::Female) => 2.2,
(humanoid::Species::Elf, humanoid::BodyType::Male) => 2.3,
(humanoid::Species::Elf, humanoid::BodyType::Female) => 2.2,
(humanoid::Species::Dwarf, humanoid::BodyType::Male) => 1.9,
(humanoid::Species::Dwarf, humanoid::BodyType::Female) => 1.8,
(humanoid::Species::Undead, humanoid::BodyType::Male) => 2.2,
(humanoid::Species::Undead, humanoid::BodyType::Female) => 2.1,
(humanoid::Species::Danari, humanoid::BodyType::Male) => 1.5,
(humanoid::Species::Danari, humanoid::BodyType::Female) => 1.4,
},
Body::QuadrupedSmall(body) => match body.species {
quadruped_small::Species::Dodarock => 1.5,
@ -212,10 +225,10 @@ impl Body {
_ => 1.0,
},
Body::QuadrupedMedium(body) => match body.species {
quadruped_medium::Species::Tarasque => 2.5,
quadruped_medium::Species::Lion => 1.8,
quadruped_medium::Species::Saber => 1.8,
quadruped_medium::Species::Catoblepas => 2.8,
quadruped_medium::Species::Tarasque => 2.6,
quadruped_medium::Species::Lion => 2.0,
quadruped_medium::Species::Saber => 2.0,
quadruped_medium::Species::Catoblepas => 2.9,
_ => 1.6,
},
Body::QuadrupedLow(body) => match body.species {
@ -226,9 +239,9 @@ impl Body {
_ => 1.3,
},
Body::Theropod(body) => match body.species {
theropod::Species::Snowraptor => 2.5,
theropod::Species::Sandraptor => 2.5,
theropod::Species::Woodraptor => 2.5,
theropod::Species::Snowraptor => 2.6,
theropod::Species::Sandraptor => 2.6,
theropod::Species::Woodraptor => 2.6,
_ => 8.0,
},
Body::BirdMedium(body) => match body.species {

View File

@ -199,12 +199,13 @@ impl<'a> System<'a> for Sys {
const LISTEN_DIST: f32 = 16.0;
const SEARCH_DIST: f32 = 48.0;
const SIGHT_DIST: f32 = 80.0;
const MIN_ATTACK_DIST: f32 = 2.0;
const MAX_FLEE_DIST: f32 = 20.0;
const SNEAK_COEFFICIENT: f32 = 0.25;
let scale = scales.get(entity).map(|s| s.0).unwrap_or(1.0);
let min_attack_dist = body.map_or(2.0, |b| b.radius() * scale * 1.5);
// This controls how picky NPCs are about their pathfinding. Giants are larger
// and so can afford to be less precise when trying to move around
// the world (especially since they would otherwise get stuck on
@ -537,7 +538,7 @@ impl<'a> System<'a> for Sys {
// depending on the distance from the agent to the target
match tactic {
Tactic::Melee => {
if dist_sqrd < (MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (min_attack_dist * scale).powi(2) {
inputs.primary.set_state(true);
inputs.move_dir = Vec2::zero();
} else if dist_sqrd < MAX_CHASE_DIST.powi(2)
@ -575,7 +576,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::Axe => {
if dist_sqrd < (MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
if *powerup > 6.0 {
inputs.secondary.set_state(false);
@ -624,7 +625,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::Hammer => {
if dist_sqrd < (MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
if *powerup > 4.0 {
inputs.secondary.set_state(false);
@ -688,7 +689,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::Sword => {
if dist_sqrd < (MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
if stats.skill_set.has_skill(Skill::Sword(SwordSkill::UnlockSpin)) && *powerup < 2.0 && energy.current() > 600 {
inputs.ability3.set_state(true);
@ -747,7 +748,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::Bow => {
if body.map(|b| b.is_humanoid()).unwrap_or(false) && dist_sqrd < (2.0 * MIN_ATTACK_DIST * scale).powi(2) {
if body.map(|b| b.is_humanoid()).unwrap_or(false) && dist_sqrd < (2.0 * min_attack_dist * scale).powi(2) {
inputs.roll.set_state(true);
} else if dist_sqrd < MAX_CHASE_DIST.powi(2)
|| (dist_sqrd < SIGHT_DIST.powi(2) && !*been_close)
@ -813,10 +814,10 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::Staff => {
if body.map(|b| b.is_humanoid()).unwrap_or(false) && dist_sqrd < (MIN_ATTACK_DIST * scale).powi(2) {
if body.map(|b| b.is_humanoid()).unwrap_or(false) && dist_sqrd < (min_attack_dist * scale).powi(2) {
inputs.roll.set_state(true);
} else if dist_sqrd
< (5.0 * MIN_ATTACK_DIST * scale).powi(2)
< (5.0 * min_attack_dist * scale).powi(2)
{
if *powerup < 1.5 {
inputs.move_dir = (tgt_pos.0 - pos.0)
@ -890,7 +891,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::StoneGolemBoss => {
if dist_sqrd < (MIN_ATTACK_DIST * scale * 2.0).powi(2) { // 2.0 is temporary correction factor to allow them to melee with their large hitbox
if dist_sqrd < (min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
inputs.primary.set_state(true);
} else if dist_sqrd < MAX_CHASE_DIST.powi(2)
@ -942,23 +943,23 @@ impl<'a> System<'a> for Sys {
radius,
circle_time,
} => {
if dist_sqrd < (MIN_ATTACK_DIST * scale).powi(2)
if dist_sqrd < (min_attack_dist * scale).powi(2)
&& thread_rng().gen_bool(0.5)
{
inputs.move_dir = Vec2::zero();
inputs.primary.set_state(true);
} else if dist_sqrd
< (radius as f32 * MIN_ATTACK_DIST * scale).powi(2)
< (radius as f32 * min_attack_dist * scale).powi(2)
{
inputs.move_dir = (pos.0 - tgt_pos.0)
.xy()
.try_normalized()
.unwrap_or(Vec2::unit_y());
} else if dist_sqrd
< ((radius as f32 + 1.0) * MIN_ATTACK_DIST * scale)
< ((radius as f32 + 1.0) * min_attack_dist * scale)
.powi(2)
&& dist_sqrd
> (radius as f32 * MIN_ATTACK_DIST * scale).powi(2)
> (radius as f32 * min_attack_dist * scale).powi(2)
{
if *powerup < circle_time as f32 {
inputs.move_dir = (tgt_pos.0 - pos.0)
@ -1012,7 +1013,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::QuadLowRanged => {
if dist_sqrd < (5.0 * MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (5.0 * min_attack_dist * scale).powi(2) {
inputs.move_dir = (tgt_pos.0 - pos.0)
.xy()
.try_normalized()
@ -1074,7 +1075,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::TailSlap => {
if dist_sqrd < (1.5 * MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (1.5 * min_attack_dist * scale).powi(2) {
if *powerup > 4.0 {
inputs.primary.set_state(false);
*powerup = 0.0;
@ -1119,12 +1120,12 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::QuadLowQuick => {
if dist_sqrd < (1.5 * MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (1.5 * min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
inputs.secondary.set_state(true);
} else if dist_sqrd
< (3.0 * MIN_ATTACK_DIST * scale).powi(2)
&& dist_sqrd > (2.0 * MIN_ATTACK_DIST * scale).powi(2)
< (3.0 * min_attack_dist * scale).powi(2)
&& dist_sqrd > (2.0 * min_attack_dist * scale).powi(2)
{
inputs.primary.set_state(true);
inputs.move_dir = (tgt_pos.0 - pos.0)
@ -1161,7 +1162,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::QuadLowBasic => {
if dist_sqrd < (1.5 * MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (1.5 * min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
if *powerup > 5.0 {
*powerup = 0.0;
@ -1201,11 +1202,11 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::QuadMedJump => {
if dist_sqrd < (1.5 * MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (1.5 * min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
inputs.secondary.set_state(true);
} else if dist_sqrd
< (5.0 * MIN_ATTACK_DIST * scale).powi(2)
< (5.0 * min_attack_dist * scale).powi(2)
{
inputs.ability3.set_state(true);
} else if dist_sqrd < MAX_CHASE_DIST.powi(2)
@ -1246,7 +1247,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::QuadMedBasic => {
if dist_sqrd < (MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
if *powerup < 2.0 {
inputs.secondary.set_state(true);
@ -1286,11 +1287,11 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::Lavadrake => {
if dist_sqrd < (2.5 * MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (2.5 * min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
inputs.secondary.set_state(true);
} else if dist_sqrd
< (7.0 * MIN_ATTACK_DIST * scale).powi(2)
< (7.0 * min_attack_dist * scale).powi(2)
{
if *powerup < 2.0 {
inputs.move_dir = (tgt_pos.0 - pos.0)
@ -1343,7 +1344,7 @@ impl<'a> System<'a> for Sys {
}
},
Tactic::Theropod => {
if dist_sqrd < (2.0 * MIN_ATTACK_DIST * scale).powi(2) {
if dist_sqrd < (2.0 * min_attack_dist * scale).powi(2) {
inputs.move_dir = Vec2::zero();
inputs.primary.set_state(true);
} else if dist_sqrd < MAX_CHASE_DIST.powi(2)

View File

@ -58,13 +58,14 @@ impl<'a> System<'a> for Sys {
let mut server_emitter = server_bus.emitter();
let _local_emitter = local_bus.emitter();
// Attacks
for (entity, uid, pos, ori, scale_maybe, attack) in (
for (entity, uid, pos, ori, scale_maybe, attack, body) in (
&entities,
&uids,
&positions,
&orientations,
scales.maybe(),
&mut attacking_storage,
&bodies,
)
.join()
{
@ -92,6 +93,7 @@ impl<'a> System<'a> for Sys {
// Scales
let scale = scale_maybe.map_or(1.0, |s| s.0);
let scale_b = scale_b_maybe.map_or(1.0, |s| s.0);
let rad = body.radius() * scale;
let rad_b = body_b.radius() * scale_b;
// Check if entity is dodging
@ -101,7 +103,7 @@ impl<'a> System<'a> for Sys {
if entity != b
&& !health_b.is_dead
// Spherical wedge shaped attack field
&& pos.0.distance_squared(pos_b.0) < (rad_b + scale * attack.range).powi(2)
&& pos.0.distance_squared(pos_b.0) < (rad + rad_b + scale * attack.range).powi(2)
&& ori2.angle_between(pos_b2 - pos2) < attack.max_angle + (rad_b / pos2.distance(pos_b2)).atan()
{
// See if entities are in the same group