diff --git a/Cargo.toml b/Cargo.toml index 9abd786022..4c463c2db7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index c2bcbe1c2a..ef768e2a9d 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -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::::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::() < 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::::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()); } } } diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index 7ee73e4bfa..807ca96945 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -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 = 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 } diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs index dcec8bac24..f0f157b9ce 100644 --- a/common/src/sys/movement.rs +++ b/common/src/sys/movement.rs @@ -173,10 +173,10 @@ impl<'a> System<'a> for Sys { if Vec2::::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 diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index ad9e5170ec..67689495b4 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -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;