diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index 5f3fa14869..51e31a7f14 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -113,13 +113,17 @@ impl<'a> System<'a> for Sys { .join() { // Hack, replace with better system when groups are more sophisticated - // Override alignment if in a group - let alignment = group - .and_then(|g| group_manager.group_info(*g)) - .and_then(|info| uids.get(info.leader)) - .copied() - .map(Alignment::Owned) - .or(alignment.copied()); + // Override alignment if in a group unless entity is owned already + let alignment = if !matches!(alignment, Some(Alignment::Owned(_))) { + group + .and_then(|g| group_manager.group_info(*g)) + .and_then(|info| uids.get(info.leader)) + .copied() + .map(Alignment::Owned) + .or(alignment.copied()) + } else { + alignment.copied() + }; // Skip mounted entities if mount_state diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index c065a9621f..ffec0df1b4 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -1,12 +1,17 @@ use crate::{ - comp::{Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos, Scale, Sticky, Vel}, + comp::{ + Collider, Gravity, Group, Mass, Mounting, Ori, PhysicsState, Pos, Projectile, Scale, + Sticky, Vel, + }, event::{EventBus, ServerEvent}, state::DeltaTime, - sync::Uid, + sync::{Uid, UidAllocator}, terrain::{Block, BlockKind, TerrainGrid}, vol::ReadVol, }; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage}; +use specs::{ + saveload::MarkerAllocator, Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage, +}; use vek::*; pub const GRAVITY: f32 = 9.81 * 5.0; @@ -44,6 +49,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Uid>, ReadExpect<'a, TerrainGrid>, Read<'a, DeltaTime>, + Read<'a, UidAllocator>, Read<'a, EventBus>, ReadStorage<'a, Scale>, ReadStorage<'a, Sticky>, @@ -55,6 +61,8 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Vel>, WriteStorage<'a, Ori>, ReadStorage<'a, Mounting>, + ReadStorage<'a, Group>, + ReadStorage<'a, Projectile>, ); #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 @@ -66,6 +74,7 @@ impl<'a> System<'a> for Sys { uids, terrain, dt, + uid_allocator, event_bus, scales, stickies, @@ -77,6 +86,8 @@ impl<'a> System<'a> for Sys { mut velocities, mut orientations, mountings, + groups, + projectiles, ): Self::SystemData, ) { let mut event_emitter = event_bus.emitter(); @@ -432,7 +443,7 @@ impl<'a> System<'a> for Sys { } // Apply pushback - for (pos, scale, mass, vel, _, _, _, physics) in ( + for (pos, scale, mass, vel, _, _, _, physics, projectile) in ( &positions, scales.maybe(), masses.maybe(), @@ -441,9 +452,12 @@ impl<'a> System<'a> for Sys { !&mountings, stickies.maybe(), &mut physics_states, + // TODO: if we need to avoid collisions for other things consider moving whether it + // should interact into the collider component or into a separate component + projectiles.maybe(), ) .join() - .filter(|(_, _, _, _, _, _, sticky, physics)| { + .filter(|(_, _, _, _, _, _, sticky, physics, _)| { sticky.is_none() || (physics.on_wall.is_none() && !physics.on_ground) }) { @@ -452,16 +466,27 @@ impl<'a> System<'a> for Sys { let scale = scale.map(|s| s.0).unwrap_or(1.0); let mass = mass.map(|m| m.0).unwrap_or(scale); - for (other, pos_other, scale_other, mass_other, _, _) in ( + // Group to ignore collisions with + let ignore_group = projectile + .and_then(|p| p.owner) + .and_then(|uid| uid_allocator.retrieve_entity_internal(uid.into())) + .and_then(|e| groups.get(e)); + + for (other, pos_other, scale_other, mass_other, _, _, group) in ( &uids, &positions, scales.maybe(), masses.maybe(), &colliders, !&mountings, + groups.maybe(), ) .join() { + if ignore_group.is_some() && ignore_group == group { + continue; + } + let scale_other = scale_other.map(|s| s.0).unwrap_or(1.0); let mass_other = mass_other.map(|m| m.0).unwrap_or(scale_other); diff --git a/common/src/sys/projectile.rs b/common/src/sys/projectile.rs index ad2e4a1023..ae6817cf35 100644 --- a/common/src/sys/projectile.rs +++ b/common/src/sys/projectile.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ - projectile, Alignment, Damage, DamageSource, Energy, EnergySource, HealthChange, - HealthSource, Loadout, Ori, PhysicsState, Pos, Projectile, Vel, + projectile, Damage, DamageSource, Energy, EnergySource, HealthChange, HealthSource, + Loadout, Ori, PhysicsState, Pos, Projectile, Vel, }, event::{EventBus, LocalEvent, ServerEvent}, state::DeltaTime, @@ -28,7 +28,6 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Ori>, WriteStorage<'a, Projectile>, WriteStorage<'a, Energy>, - ReadStorage<'a, Alignment>, ReadStorage<'a, Loadout>, ); @@ -46,7 +45,6 @@ impl<'a> System<'a> for Sys { mut orientations, mut projectiles, mut energies, - alignments, loadouts, ): Self::SystemData, ) { @@ -92,23 +90,13 @@ impl<'a> System<'a> for Sys { healthchange: healthchange as f32, source: DamageSource::Projectile, }; - if let Some(entity) = - uid_allocator.retrieve_entity_internal(other.into()) - { - if let Some(loadout) = loadouts.get(entity) { - damage.modify_damage(false, loadout); - } + + let other_entity = uid_allocator.retrieve_entity_internal(other.into()); + if let Some(loadout) = other_entity.and_then(|e| loadouts.get(e)) { + damage.modify_damage(false, loadout); } - // Hacky: remove this when groups get implemented - let passive = uid_allocator - .retrieve_entity_internal(other.into()) - .and_then(|other| { - alignments - .get(other) - .map(|a| Alignment::Owned(owner_uid).passive_towards(*a)) - }) - .unwrap_or(false); - if other != projectile.owner.unwrap() && !passive { + + if other != owner_uid { server_emitter.emit(ServerEvent::Damage { uid: other, change: HealthChange {