diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 0fe75fbf4c..efb5e01d33 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -132,6 +132,7 @@ impl Component for CharacterState { #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Attacking { pub base_damage: u32, + pub range: f32, pub max_angle: f32, pub applied: bool, pub hit_count: u32, diff --git a/common/src/states/basic_melee.rs b/common/src/states/basic_melee.rs index 01778be4f4..f05e638912 100644 --- a/common/src/states/basic_melee.rs +++ b/common/src/states/basic_melee.rs @@ -44,6 +44,7 @@ impl CharacterBehavior for Data { // Hit attempt data.updater.insert(data.entity, Attacking { base_damage: self.base_damage, + range: self.range, max_angle: self.max_angle.to_radians(), applied: false, hit_count: 0, diff --git a/common/src/states/dash_melee.rs b/common/src/states/dash_melee.rs index 22223a66fa..5d1d462a2c 100644 --- a/common/src/states/dash_melee.rs +++ b/common/src/states/dash_melee.rs @@ -1,5 +1,6 @@ use crate::{ comp::{Attacking, CharacterState, EnergySource, StateUpdate}, + states::utils::*, sys::character_behavior::*, util::safe_slerp, }; @@ -53,6 +54,7 @@ impl CharacterBehavior for Data { // Hit attempt data.updater.insert(data.entity, Attacking { base_damage: self.base_damage, + range: 3.5, max_angle: 180_f32.to_radians(), applied: false, hit_count: 0, @@ -67,6 +69,7 @@ impl CharacterBehavior for Data { }); } else if self.recover_duration != Duration::default() { // Recovery + handle_move(data, &mut update); update.character = CharacterState::DashMelee(Data { buildup_duration: self.buildup_duration, recover_duration: self diff --git a/common/src/states/timed_combo.rs b/common/src/states/timed_combo.rs index 0883f9c77a..ec50a25d2f 100644 --- a/common/src/states/timed_combo.rs +++ b/common/src/states/timed_combo.rs @@ -53,6 +53,7 @@ impl CharacterBehavior for Data { // Swing hits data.updater.insert(data.entity, Attacking { base_damage: self.base_damage * (self.stage as u32 + 1), + range: 3.5, max_angle: 75_f32.to_radians(), applied: false, hit_count: 0, diff --git a/common/src/states/triple_strike.rs b/common/src/states/triple_strike.rs index a2a864e4ce..f6b6ccebe6 100644 --- a/common/src/states/triple_strike.rs +++ b/common/src/states/triple_strike.rs @@ -92,6 +92,7 @@ impl CharacterBehavior for Data { // Try to deal damage in second half of stage data.updater.insert(data.entity, Attacking { base_damage: dmg, + range: 3.5, max_angle: 180_f32.to_radians(), applied: false, hit_count: 0, diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index e79c1c186a..c2f35c222a 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -82,9 +82,8 @@ fn swim_move(data: &JoinData, update: &mut StateUpdate) { handle_orientation(data, update, if data.physics.on_ground { 9.0 } else { 2.0 }); - // Force players to pulse jump button to swim up - if data.inputs.jump.is_pressed() && !data.inputs.jump.is_long_press(Duration::from_millis(600)) - { + // Swim + if data.inputs.jump.is_pressed() { update.vel.0.z = (update.vel.0.z + data.dt.0 * GRAVITY * 2.25).min(BASE_HUMANOID_WATER_SPEED); } diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index 18bb3eb9fd..d8a9f2f467 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -97,7 +97,7 @@ impl<'a> System<'a> for Sys { if entity != b && !stats_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_b + scale * attack.range).powi(2) && ori2.angle_between(pos_b2 - pos2) < attack.max_angle + (rad_b / pos2.distance(pos_b2)).atan() { // Weapon gives base damage diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 1c22232a9f..ab61740264 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -194,6 +194,7 @@ pub fn handle_respawn(server: &Server, entity: EcsEntity) { pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Option) { // Go through all other entities + let hit_range = 2.0 * power; let ecs = &server.state.ecs(); for (b, uid_b, pos_b, ori_b, character_b, stats_b) in ( &ecs.entities(), @@ -205,14 +206,15 @@ pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Opti ) .join() { + let distance_squared = pos.distance_squared(pos_b.0); // Check if it is a hit if !stats_b.is_dead // Spherical wedge shaped attack field // RADIUS - && pos.distance_squared(pos_b.0) < 10_f32.powi(2) + && distance_squared < hit_range.powi(2) { // Weapon gives base damage - let mut dmg = power as u32 * 2; + let mut dmg = ((1.0 - distance_squared / hit_range.powi(2)) * power * 5.0) as u32; if rand::random() { dmg += 1;