diff --git a/client/src/lib.rs b/client/src/lib.rs index aec0cb919c..f3e7a0a33f 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1050,7 +1050,7 @@ impl Client { self.group_leader = Some(leader); self.group_members = members.into_iter().collect(); // Currently add/remove messages treat client as an implicit member - // of the group whereas this message explicitly included them so to + // of the group whereas this message explicitly includes them so to // be consistent for now we will remove the client from the // received hashset if let Some(uid) = self.uid() { diff --git a/common/src/event.rs b/common/src/event.rs index 9a07615c68..943757a2a7 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -25,6 +25,7 @@ pub enum ServerEvent { pos: Vec3, power: f32, owner: Option, + friendly_damage: bool, }, Damage { uid: Uid, diff --git a/common/src/sys/projectile.rs b/common/src/sys/projectile.rs index ae6817cf35..20f96fc311 100644 --- a/common/src/sys/projectile.rs +++ b/common/src/sys/projectile.rs @@ -70,6 +70,7 @@ impl<'a> System<'a> for Sys { pos: pos.0, power, owner: projectile.owner, + friendly_damage: false, }) }, projectile::Effect::Vanish => server_emitter.emit(ServerEvent::Destroy { @@ -131,6 +132,7 @@ impl<'a> System<'a> for Sys { pos: pos.0, power, owner: projectile.owner, + friendly_damage: false, }) }, projectile::Effect::Vanish => server_emitter.emit(ServerEvent::Destroy { diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 3c5601f4e0..81a19a2a49 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -1006,6 +1006,7 @@ fn handle_explosion( pos: pos.0, power, owner: ecs.read_storage::().get(target).copied(), + friendly_damage: true, }) }, None => server.notify_client( diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 00b1810ad2..0a73123a28 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -7,12 +7,12 @@ use common::{ }, msg::{PlayerListUpdate, ServerMsg}, state::BlockChange, - sync::{Uid, WorldSyncExt}, + sync::{Uid, UidAllocator, WorldSyncExt}, sys::combat::BLOCK_ANGLE, terrain::{Block, TerrainGrid}, vol::{ReadVol, Vox}, }; -use specs::{join::Join, Entity as EcsEntity, WorldExt}; +use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt}; use tracing::error; use vek::Vec3; @@ -277,11 +277,25 @@ pub fn handle_respawn(server: &Server, entity: EcsEntity) { } } -pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Option) { +pub fn handle_explosion( + server: &Server, + pos: Vec3, + power: f32, + owner: Option, + friendly_damage: bool, +) { // Go through all other entities let hit_range = 3.0 * power; let ecs = &server.state.ecs(); - for (pos_b, ori_b, character_b, stats_b, loadout_b) in ( + + let owner_entity = owner.and_then(|uid| { + ecs.read_resource::() + .retrieve_entity_internal(uid.into()) + }); + let groups = ecs.read_storage::(); + + for (entity_b, pos_b, ori_b, character_b, stats_b, loadout_b) in ( + &ecs.entities(), &ecs.read_storage::(), &ecs.read_storage::(), ecs.read_storage::().maybe(), @@ -293,9 +307,13 @@ pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Opti 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 && distance_squared < hit_range.powi(2) + // Skip if they are in the same group and friendly_damage is turned off for the + // explosion + && (friendly_damage || !owner_entity + .and_then(|e| groups.get(e)) + .map_or(false, |group_a| Some(group_a) == groups.get(entity_b))) { // Weapon gives base damage let dmg = (1.0 - distance_squared / hit_range.powi(2)) * power * 130.0; diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index 55783d5196..412d9a536a 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -50,9 +50,12 @@ impl Server { for event in events { match event { - ServerEvent::Explosion { pos, power, owner } => { - handle_explosion(&self, pos, power, owner) - }, + ServerEvent::Explosion { + pos, + power, + owner, + friendly_damage, + } => handle_explosion(&self, pos, power, owner, friendly_damage), ServerEvent::Shoot { entity, dir, diff --git a/server/src/sys/object.rs b/server/src/sys/object.rs index be986f8e6e..ea3c2d3ad5 100644 --- a/server/src/sys/object.rs +++ b/server/src/sys/object.rs @@ -39,6 +39,7 @@ impl<'a> System<'a> for Sys { pos: pos.0, power: 4.0, owner: *owner, + friendly_damage: true, }); } },