Improve NPC aiming and humanoid hitboxes

This commit is contained in:
James Melkonian 2020-11-11 04:36:40 +00:00 committed by Samuel Keiffer
parent 7ad330af4c
commit 6085edaa34
3 changed files with 124 additions and 50 deletions

View File

@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Flight - Flight
- Roll dodges melee attacks, and reduces the height of your hitbox - Roll dodges melee attacks, and reduces the height of your hitbox
- Persistent waypoints (start from the last camp fire you visited) - Persistent waypoints (start from the last camp fire you visited)
- NPCs use all three weapon skills in combat
### Changed ### Changed

View File

@ -140,7 +140,7 @@ impl Body {
pub fn radius(&self) -> f32 { pub fn radius(&self) -> f32 {
// TODO: Improve these values (some might be reliant on more info in inner type) // TODO: Improve these values (some might be reliant on more info in inner type)
match self { match self {
Body::Humanoid(body) => 0.35 * body.scale(), Body::Humanoid(body) => 0.5 * body.scale(),
Body::QuadrupedSmall(_) => 0.4, Body::QuadrupedSmall(_) => 0.4,
Body::QuadrupedMedium(body) => match body.species { Body::QuadrupedMedium(body) => match body.species {
quadruped_medium::Species::Grolgar => 1.9, quadruped_medium::Species::Grolgar => 1.9,
@ -172,12 +172,7 @@ impl Body {
pub fn height(&self) -> f32 { pub fn height(&self) -> f32 {
match self { match self {
Body::Humanoid(humanoid) => match humanoid.species { Body::Humanoid(body) => 1.9 * body.scale(),
humanoid::Species::Danari => 1.5 * humanoid.scale(),
humanoid::Species::Dwarf => 1.55 * humanoid.scale(),
humanoid::Species::Orc => 1.95 * humanoid.scale(),
_ => 1.8 * humanoid.scale(),
},
Body::QuadrupedSmall(body) => match body.species { Body::QuadrupedSmall(body) => match body.species {
quadruped_small::Species::Dodarock => 1.5, quadruped_small::Species::Dodarock => 1.5,
quadruped_small::Species::Holladon => 1.5, quadruped_small::Species::Holladon => 1.5,

View File

@ -308,7 +308,7 @@ impl<'a> System<'a> for Sys {
Axe, Axe,
Hammer, Hammer,
Sword, Sword,
RangedPowerup, Bow,
Staff, Staff,
StoneGolemBoss, StoneGolemBoss,
} }
@ -320,7 +320,7 @@ impl<'a> System<'a> for Sys {
None None
} }
}) { }) {
Some(ToolKind::Bow) => Tactic::RangedPowerup, Some(ToolKind::Bow) => Tactic::Bow,
Some(ToolKind::Staff) => Tactic::Staff, Some(ToolKind::Staff) => Tactic::Staff,
Some(ToolKind::Hammer) => Tactic::Hammer, Some(ToolKind::Hammer) => Tactic::Hammer,
Some(ToolKind::Sword) => Tactic::Sword, Some(ToolKind::Sword) => Tactic::Sword,
@ -341,10 +341,42 @@ impl<'a> System<'a> for Sys {
.unwrap_or(Alignment::Wild), .unwrap_or(Alignment::Wild),
), ),
) { ) {
if let Some(dir) = Dir::from_unnormalized(tgt_pos.0 - pos.0) { controller.actions.push(ControlAction::Wield);
let eye_offset = match body {
Some(body) => match body {
Body::Humanoid(body) => body.eye_height(),
_ => 0.4 * body.height(),
},
_ => 0.0,
};
let tgt_eye_offset = match bodies.get(*target) {
Some(body) => match body {
Body::Humanoid(body) => body.eye_height(),
_ => 0.4 * body.height(),
},
_ => 0.0,
};
let distance_offset = match tactic {
Tactic::Bow => 0.0004 * pos.0.distance_squared(tgt_pos.0),
Tactic::Staff => 0.0015 * pos.0.distance_squared(tgt_pos.0),
_ => 0.0,
};
if let Some(dir) = Dir::from_unnormalized(
Vec3::new(
tgt_pos.0.x,
tgt_pos.0.y,
tgt_pos.0.z + tgt_eye_offset + distance_offset,
) - Vec3::new(pos.0.x, pos.0.y, pos.0.z + eye_offset),
) {
inputs.look_dir = dir; inputs.look_dir = dir;
} }
//if let Some(dir) = Dir::from_unnormalized(tgt_pos.0 - pos.0) {
// inputs.look_dir = dir;
//}
// Don't attack entities we are passive towards // Don't attack entities we are passive towards
// TODO: This is here, it's a bit of a hack // TODO: This is here, it's a bit of a hack
if let Some(alignment) = alignment { if let Some(alignment) = alignment {
@ -388,7 +420,7 @@ impl<'a> System<'a> for Sys {
inputs.move_dir = inputs.move_dir =
bearing.xy().try_normalized().unwrap_or(Vec2::zero()) bearing.xy().try_normalized().unwrap_or(Vec2::zero())
* speed * speed
* 0.2; //Let small/slow animals flee slower than the player * 0.4; //Let small/slow animals flee slower than the player
inputs.jump.set_state(bearing.z > 1.5); inputs.jump.set_state(bearing.z > 1.5);
inputs.move_z = bearing.z; inputs.move_z = bearing.z;
} }
@ -407,14 +439,27 @@ impl<'a> System<'a> for Sys {
* 0.1; * 0.1;
match tactic { match tactic {
Tactic::Sword Tactic::Melee | Tactic::StoneGolemBoss => {
| Tactic::Melee inputs.primary.set_state(true)
| Tactic::Hammer },
| Tactic::StoneGolemBoss => inputs.primary.set_state(true), Tactic::Hammer => {
if *powerup > 4.0 {
inputs.secondary.set_state(false);
*powerup = 0.0;
} else if *powerup > 2.0 {
inputs.secondary.set_state(true);
*powerup += dt.0;
} else if energy.current() > 700 {
inputs.ability3.set_state(true);
*powerup += dt.0;
} else {
inputs.primary.set_state(true);
*powerup += dt.0;
}
},
Tactic::Staff => { Tactic::Staff => {
// Kind of arbitrary values, but feel right in game // Kind of arbitrary values, but feel right in game
if energy.current() > 800 && thread_rng().gen::<f32>() > 0.8 if energy.current() > 800 && thread_rng().gen_bool(0.2) {
{
inputs.ability3.set_state(true) inputs.ability3.set_state(true)
} else if energy.current() > 10 { } else if energy.current() > 10 {
inputs.secondary.set_state(true) inputs.secondary.set_state(true)
@ -422,19 +467,35 @@ impl<'a> System<'a> for Sys {
inputs.primary.set_state(true) inputs.primary.set_state(true)
} }
}, },
Tactic::Sword => {
if *powerup < 2.0 && energy.current() > 500 {
inputs.ability3.set_state(true);
*powerup += dt.0;
} else if *powerup > 2.0 {
*powerup = 0.0;
} else {
inputs.primary.set_state(true);
*powerup += dt.0;
}
},
Tactic::Axe => { Tactic::Axe => {
if *powerup > 6.0 { if *powerup > 6.0 {
inputs.secondary.set_state(false); inputs.secondary.set_state(false);
*powerup = 0.0; *powerup = 0.0;
} else if *powerup > 4.0 && energy.current() > 10 { } else if *powerup > 4.0 && energy.current() > 100 {
inputs.secondary.set_state(true); inputs.secondary.set_state(true);
*powerup += dt.0; *powerup += dt.0;
} else if energy.current() > 800
&& thread_rng().gen_bool(0.5)
{
inputs.ability3.set_state(true);
*powerup += dt.0;
} else { } else {
inputs.primary.set_state(true); inputs.primary.set_state(true);
*powerup += dt.0; *powerup += dt.0;
} }
}, },
Tactic::RangedPowerup => inputs.roll.set_state(true), Tactic::Bow => inputs.roll.set_state(true),
} }
} else if dist_sqrd < MAX_CHASE_DIST.powf(2.0) } else if dist_sqrd < MAX_CHASE_DIST.powf(2.0)
|| (dist_sqrd < SIGHT_DIST.powf(2.0) || (dist_sqrd < SIGHT_DIST.powf(2.0)
@ -449,37 +510,54 @@ impl<'a> System<'a> for Sys {
>= dist_sqrd; >= dist_sqrd;
if can_see_tgt { if can_see_tgt {
if let Tactic::RangedPowerup = tactic { match tactic {
if *powerup > 1.5 { Tactic::Bow => {
inputs.primary.set_state(false); if *powerup > 4.0 {
*powerup = 0.0; inputs.secondary.set_state(false);
} else { *powerup = 0.0;
} else if *powerup > 2.0 && energy.current() > 300 {
inputs.secondary.set_state(true);
*powerup += dt.0;
} else if energy.current() > 400
&& thread_rng().gen_bool(0.8)
{
inputs.secondary.set_state(false);
inputs.ability3.set_state(true);
*powerup += dt.0;
} else {
inputs.secondary.set_state(false);
inputs.primary.set_state(true);
*powerup += dt.0;
}
},
Tactic::Sword => {
if *powerup > 4.0 {
inputs.secondary.set_state(true);
*powerup = 0.0;
} else {
*powerup += dt.0;
}
},
Tactic::Staff => {
inputs.primary.set_state(true); inputs.primary.set_state(true);
*powerup += dt.0; },
} Tactic::Hammer => {
} else if let Tactic::Sword = tactic { if *powerup > 5.0 {
if *powerup > 4.0 { inputs.ability3.set_state(true);
inputs.secondary.set_state(true); *powerup = 0.0;
*powerup = 0.0; } else {
} else { *powerup += dt.0;
*powerup += dt.0; }
} },
} else if let Tactic::Staff = tactic { Tactic::StoneGolemBoss => {
inputs.primary.set_state(true); if *powerup > 5.0 {
} else if let Tactic::Hammer = tactic { inputs.secondary.set_state(true);
if *powerup > 5.0 { *powerup = 0.0;
inputs.ability3.set_state(true); } else {
*powerup = 0.0; *powerup += dt.0;
} else { }
*powerup += dt.0; },
} _ => {},
} else if let Tactic::StoneGolemBoss = tactic {
if *powerup > 5.0 {
inputs.secondary.set_state(true);
*powerup = 0.0;
} else {
*powerup += dt.0;
}
} }
} }
@ -502,7 +580,7 @@ impl<'a> System<'a> for Sys {
) { ) {
if can_see_tgt { if can_see_tgt {
match tactic { match tactic {
Tactic::RangedPowerup => { Tactic::Bow => {
inputs.move_dir = bearing inputs.move_dir = bearing
.xy() .xy()
.rotated_z(thread_rng().gen_range(0.5, 1.57)) .rotated_z(thread_rng().gen_range(0.5, 1.57))