Fix NaN in agent sys, stop pushback from turning player around, account for Scale in melee attack hit detection

This commit is contained in:
Imbris 2019-12-01 18:40:05 -05:00
parent 8f7323f41b
commit bfaa18e010
5 changed files with 32 additions and 20 deletions

View File

@ -17,7 +17,7 @@ opt-level = 2
overflow-checks = true
debug-assertions = true
panic = "abort"
# debug = false
debug = false
codegen-units = 8
lto = false
incremental = true

View File

@ -1,6 +1,5 @@
use crate::comp::{
Agent, CharacterState, Controller, ControllerInputs, MountState, MovementState::Glide, Pos,
Stats,
Agent, CharacterState, Controller, MountState, MovementState::Glide, Pos, Stats,
};
use crate::pathfinding::WorldPath;
use crate::terrain::TerrainGrid;
@ -60,7 +59,7 @@ impl<'a> System<'a> for Sys {
controller.reset();
let mut inputs = ControllerInputs::default();
let mut inputs = &mut controller.inputs;
match agent {
Agent::Traveler { path } => {
@ -147,10 +146,10 @@ impl<'a> System<'a> for Sys {
let dist = Vec2::<f32>::from(target_pos.0 - pos.0).magnitude();
if target_stats.is_dead {
choose_new = true;
} else if dist < MIN_ATTACK_DIST
&& dist > 0.001
&& rand::random::<f32>() < 0.3
{
} else if dist < 0.001 {
// TODO: move back? (probably can only happen when entities are at a
// different z-level due to repulsion)
} else if dist < MIN_ATTACK_DIST {
// Fight (and slowly move closer)
inputs.move_dir =
Vec2::<f32>::from(target_pos.0 - pos.0).normalized() * 0.01;
@ -203,7 +202,8 @@ impl<'a> System<'a> for Sys {
}
}
controller.inputs = inputs;
debug_assert!(inputs.move_dir.map(|e| !e.is_nan()).reduce_and());
debug_assert!(inputs.look_dir.map(|e| !e.is_nan()).reduce_and());
}
}
}

View File

@ -1,7 +1,7 @@
use crate::{
comp::{
ActionState::*, CharacterState, Controller, HealthChange, HealthSource, Item, ItemKind,
Ori, Pos, Stats,
Ori, Pos, Scale, Stats,
},
event::{EventBus, LocalEvent, ServerEvent},
state::DeltaTime,
@ -13,7 +13,8 @@ use vek::*;
const BLOCK_EFFICIENCY: f32 = 0.9;
const ATTACK_RANGE: f32 = 4.0;
const ATTACK_RANGE: f32 = 3.5;
const ATTACK_ANGLE: f32 = 45.0;
const BLOCK_ANGLE: f32 = 180.0;
/// This system is responsible for handling accepted inputs like moving or attacking
@ -27,6 +28,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Uid>,
ReadStorage<'a, Pos>,
ReadStorage<'a, Ori>,
ReadStorage<'a, Scale>,
ReadStorage<'a, Controller>,
WriteStorage<'a, CharacterState>,
WriteStorage<'a, Stats>,
@ -42,6 +44,7 @@ impl<'a> System<'a> for Sys {
uids,
positions,
orientations,
scales,
controllers,
mut character_states,
stats,
@ -51,11 +54,12 @@ impl<'a> System<'a> for Sys {
let mut _local_emitter = local_bus.emitter();
// Attacks
for (entity, uid, pos, ori, _, stat) in (
for (entity, uid, pos, ori, scale_maybe, _, stat) in (
&entities,
&uids,
&positions,
&orientations,
scales.maybe(),
&controllers,
&stats,
)
@ -92,11 +96,12 @@ impl<'a> System<'a> for Sys {
if deal_damage {
if let Some(Attack { .. }) = &character_states.get(entity).map(|c| c.action) {
// Go through all other entities
for (b, uid_b, pos_b, ori_b, character_b, stat_b) in (
for (b, uid_b, pos_b, ori_b, scale_b_maybe, character_b, stat_b) in (
&entities,
&uids,
&positions,
&orientations,
scales.maybe(),
&character_states,
&stats,
)
@ -107,12 +112,18 @@ impl<'a> System<'a> for Sys {
let pos_b2: Vec2<f32> = Vec2::from(pos_b.0);
let ori2 = Vec2::from(ori.0);
// 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);
// TODO: don't do this here
let rad_b = 0.5 * scale_b;
// Check if it is a hit
if entity != b
&& !stat_b.is_dead
&& pos.0.distance_squared(pos_b.0) < ATTACK_RANGE.powi(2)
// TODO: Use size instead of 1.0
&& ori2.angle_between(pos_b2 - pos2) < (2.0 / pos2.distance(pos_b2)).atan()
// Spherical wedge shaped attack field
&& pos.0.distance_squared(pos_b.0) < (rad_b + scale * ATTACK_RANGE).powi(2)
&& ori2.angle_between(pos_b2 - pos2) < ATTACK_ANGLE.to_radians() / 2.0 + (rad_b / pos2.distance(pos_b2)).atan()
{
// Weapon gives base damage
let mut dmg = if let Some(ItemKind::Tool { power, .. }) =
@ -125,8 +136,8 @@ impl<'a> System<'a> for Sys {
// Block
if character_b.action.is_block()
&& ori_b.0.angle_between(pos.0 - pos_b.0).to_degrees()
< BLOCK_ANGLE / 2.0
&& ori_b.0.angle_between(pos.0 - pos_b.0)
< BLOCK_ANGLE.to_radians() / 2.0
{
dmg = (dmg as f32 * (1.0 - BLOCK_EFFICIENCY)) as i32
}

View File

@ -173,10 +173,10 @@ impl<'a> System<'a> for Sys {
if Vec2::<f32>::from(wall_dir).magnitude_squared() > 0.001 {
Vec2::from(wall_dir).normalized()
} else {
Vec2::from(vel.0)
Vec2::from(inputs.move_dir)
}
} else {
Vec2::from(vel.0)
Vec2::from(inputs.move_dir)
};
if ori_dir.magnitude_squared() > 0.0001

View File

@ -102,6 +102,7 @@ impl<'a> System<'a> for Sys {
let scale = scale.map(|s| s.0).unwrap_or(1.0);
// Basic collision with terrain
// TODO: rename this, not just the player entity
let player_rad = 0.3 * scale; // half-width of the player's AABB
let player_height = 1.5 * scale;