diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f4aefa2ed..2272482f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index f703138577..bd6ddc6775 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -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 { diff --git a/common/sys/src/agent.rs b/common/sys/src/agent.rs index 5cf9b0b19c..d31f69fb03 100644 --- a/common/sys/src/agent.rs +++ b/common/sys/src/agent.rs @@ -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) diff --git a/common/sys/src/melee.rs b/common/sys/src/melee.rs index c6dc4c2798..dffb3b4407 100644 --- a/common/sys/src/melee.rs +++ b/common/sys/src/melee.rs @@ -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