diff --git a/src/main/scala/net/psforever/objects/serverobject/deploy/Interference.scala b/src/main/scala/net/psforever/objects/serverobject/deploy/Interference.scala index d10f7df8a..16ba67795 100644 --- a/src/main/scala/net/psforever/objects/serverobject/deploy/Interference.scala +++ b/src/main/scala/net/psforever/objects/serverobject/deploy/Interference.scala @@ -2,11 +2,13 @@ package net.psforever.objects.serverobject.deploy import net.psforever.objects.PlanetSideGameObject -import net.psforever.objects.definition.ObjectDefinition +import net.psforever.objects.definition.{DeployableDefinition, ObjectDefinition} import net.psforever.objects.serverobject.affinity.FactionAffinity import net.psforever.objects.zones.Zone import net.psforever.types.{DriveState, Vector3} +import scala.annotation.unused + /** * Block the deployment of certain entities within a certain distance. * Deployable vehicles and combat engineer entities both have a deployment condition that can be influenced by these ranges. @@ -65,30 +67,62 @@ object Interference { zone: Zone, obj: PlanetSideGameObject with FactionAffinity ): (List[PlanetSideGameObject with FactionAffinity], PlanetSideGameObject => Boolean) = { - val position = obj.Position - val faction = obj.Faction val objectDefinition = obj.Definition - val sharedGroupId = objectDefinition.interference.sharedGroupId - val sector = zone.blockMap.sector(position, Interference.MaxRange) - ( - (sector.deployableList ++ sector.vehicleList.filter(_.DeploymentState == DriveState.Deployed)).filter(_.Faction == faction), - interferenceTest(position, sharedGroupId != 0, sharedGroupId, objectDefinition) - ) + if (objectDefinition.interference eq Interference.AllowAll) { + (List(), interferenceTestNoResults) //no targets can block, and test will never pass + } else { + val position = obj.Position + val faction = obj.Faction + val sharedGroupId = objectDefinition.interference.sharedGroupId + val sector = zone.blockMap.sector(position, Interference.MaxRange) + val targets = (sector.deployableList ++ sector.vehicleList.filter(_.DeploymentState >= DriveState.Deploying)) + .collect { case target: PlanetSideGameObject with FactionAffinity + if target.Faction != faction && + (target.Definition.asInstanceOf[ObjectDefinition].interference ne Interference.AllowAll) => + target + } + if (sharedGroupId != 0) { + (targets, interferenceTestWithSharedGroup(position, objectDefinition, sharedGroupId)) + } else { + (targets, interferenceTestNoSharedGroup(position, objectDefinition)) + } + } } - private def interferenceTest( - position: Vector3, - inAGroup: Boolean, - sharedGroupId: Int, - objectDefinition: ObjectDefinition - ): PlanetSideGameObject => Boolean = { p => + private def interferenceTestNoResults(@unused p: PlanetSideGameObject): Boolean = false + + private def interferenceTestNoSharedGroup( + position: Vector3, + objectDefinition: ObjectDefinition + ): PlanetSideGameObject => Boolean = { p => val pDefinition = p.Definition - val otherInterference = pDefinition.interference - (otherInterference ne Interference.AllowAll) && { - lazy val distanceSq = Vector3.DistanceSquared(position, p.Position) - (pDefinition == objectDefinition && distanceSq < otherInterference.main * otherInterference.main) || - (inAGroup && sharedGroupId == otherInterference.sharedGroupId && distanceSq < otherInterference.shared * otherInterference.shared) || - distanceSq < otherInterference.deployables * otherInterference.deployables + val objectInterference = objectDefinition.interference + lazy val distanceSq = Vector3.DistanceSquared(position, p.Position) + if (pDefinition == objectDefinition) { + distanceSq < objectInterference.main * objectInterference.main + } else if (pDefinition.isInstanceOf[DeployableDefinition]) { + distanceSq < objectInterference.deployables * objectInterference.deployables + } else { + false + } + } + + private def interferenceTestWithSharedGroup( + position: Vector3, + objectDefinition: ObjectDefinition, + sharedGroupId: Int + ): PlanetSideGameObject => Boolean = { p => + val pDefinition = p.Definition + val objectInterference = objectDefinition.interference + lazy val distanceSq = Vector3.DistanceSquared(position, p.Position) + if (pDefinition == objectDefinition) { + distanceSq < objectInterference.main * objectInterference.main + } else if (sharedGroupId == pDefinition.interference.sharedGroupId) { + distanceSq < objectInterference.shared * objectInterference.shared + } else if (pDefinition.isInstanceOf[DeployableDefinition]) { + distanceSq < objectInterference.deployables * objectInterference.deployables + } else { + false } } } diff --git a/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala b/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala index b0b1ed6b2..42a7b732b 100644 --- a/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala +++ b/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala @@ -66,20 +66,12 @@ class ZoneVehicleActor( case Zone.Vehicle.TryDeploymentChange(vehicle, toDeployState) if toDeployState == DriveState.Deploying && - (ZoneVehicleActor.temporaryInterferenceTest(vehicle,temporaryInterference) || Interference.Test(zone, vehicle).nonEmpty) => + (ZoneVehicleActor.temporaryInterferenceTest(vehicle, temporaryInterference) || Interference.Test(zone, vehicle).nonEmpty) => sender() ! Zone.Vehicle.CanNotDeploy(zone, vehicle, toDeployState, "blocked by a nearby entity") case Zone.Vehicle.TryDeploymentChange(vehicle, toDeployState) if toDeployState == DriveState.Deploying => - import scala.concurrent.duration._ - import scala.concurrent.ExecutionContext.Implicits.global - val position = vehicle.Position - temporaryInterference = temporaryInterference :+ (position, vehicle.Faction, vehicle.Definition) - context.system.scheduler.scheduleOnce( - vehicle.Definition.DeployTime.milliseconds, - self, - ZoneVehicleActor.ClearInterference(position) - ) + tryAddToInterferenceField(vehicle.Position, vehicle.Faction, vehicle.Definition) vehicle.Actor.tell(Deployment.TryDeploymentChange(toDeployState), sender()) case Zone.Vehicle.TryDeploymentChange(vehicle, toDeployState) => @@ -98,6 +90,25 @@ class ZoneVehicleActor( case _ => () } + + private def tryAddToInterferenceField( + position: Vector3, + faction: PlanetSideEmpire.Value, + definition: VehicleDefinition + ): Boolean = { + import scala.concurrent.duration._ + import scala.concurrent.ExecutionContext.Implicits.global + val causesInterference = definition.interference ne Interference.AllowAll + if (causesInterference) { + temporaryInterference = temporaryInterference :+ (position, faction, definition) + context.system.scheduler.scheduleOnce( + definition.DeployTime.milliseconds, + self, + ZoneVehicleActor.ClearInterference(position) + ) + } + causesInterference + } } object ZoneVehicleActor { @@ -122,14 +133,15 @@ object ZoneVehicleActor { val vPosition = vehicle.Position val vFaction = vehicle.Faction val vDefinition = vehicle.Definition - existingInterferences - .collect { case (p, faction, d) if faction == vFaction => (p, d) } - .exists { case (position, definition) => - val interference = definition.interference - (interference ne Interference.AllowAll) && { - lazy val distanceSq = Vector3.DistanceSquared(position, vPosition) - definition == vDefinition && distanceSq < interference.main * interference.main + (vDefinition.interference eq Interference.AllowAll) || + existingInterferences + .collect { case (p, faction, d) if faction == vFaction => (p, d) } + .exists { case (position, definition) => + val interference = definition.interference + (interference ne Interference.AllowAll) && { + lazy val distanceSq = Vector3.DistanceSquared(position, vPosition) + definition == vDefinition && distanceSq < interference.main * interference.main + } } - } } }