mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Improve NPC aiming and humanoid hitboxes
This commit is contained in:
parent
7ad330af4c
commit
6085edaa34
@ -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
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
inputs.secondary.set_state(false);
|
||||||
*powerup = 0.0;
|
*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 {
|
} else {
|
||||||
|
inputs.secondary.set_state(false);
|
||||||
inputs.primary.set_state(true);
|
inputs.primary.set_state(true);
|
||||||
*powerup += dt.0;
|
*powerup += dt.0;
|
||||||
}
|
}
|
||||||
} else if let Tactic::Sword = tactic {
|
},
|
||||||
|
Tactic::Sword => {
|
||||||
if *powerup > 4.0 {
|
if *powerup > 4.0 {
|
||||||
inputs.secondary.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::Staff => {
|
||||||
inputs.primary.set_state(true);
|
inputs.primary.set_state(true);
|
||||||
} else if let Tactic::Hammer = tactic {
|
},
|
||||||
|
Tactic::Hammer => {
|
||||||
if *powerup > 5.0 {
|
if *powerup > 5.0 {
|
||||||
inputs.ability3.set_state(true);
|
inputs.ability3.set_state(true);
|
||||||
*powerup = 0.0;
|
*powerup = 0.0;
|
||||||
} else {
|
} else {
|
||||||
*powerup += dt.0;
|
*powerup += dt.0;
|
||||||
}
|
}
|
||||||
} else if let Tactic::StoneGolemBoss = tactic {
|
},
|
||||||
|
Tactic::StoneGolemBoss => {
|
||||||
if *powerup > 5.0 {
|
if *powerup > 5.0 {
|
||||||
inputs.secondary.set_state(true);
|
inputs.secondary.set_state(true);
|
||||||
*powerup = 0.0;
|
*powerup = 0.0;
|
||||||
} else {
|
} else {
|
||||||
*powerup += dt.0;
|
*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))
|
||||||
|
Loading…
Reference in New Issue
Block a user