diff --git a/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala b/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala index fd243cdcd..b0b1ed6b2 100644 --- a/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala +++ b/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala @@ -3,10 +3,11 @@ package net.psforever.objects.zones import akka.actor.Actor import net.psforever.actors.zone.ZoneActor +import net.psforever.objects.definition.VehicleDefinition import net.psforever.objects.serverobject.deploy.{Deployment, Interference} import net.psforever.objects.vital.InGameHistory import net.psforever.objects.{Default, Vehicle} -import net.psforever.types.{DriveState, Vector3} +import net.psforever.types.{DriveState, PlanetSideEmpire, Vector3} import scala.annotation.tailrec import scala.collection.mutable @@ -14,27 +15,12 @@ import scala.collection.mutable /** * Synchronize management of the list of `Vehicles` maintained by some `Zone`. */ -//COMMENTS IMPORTED FROM FORMER VehicleContextActor: - /* - * Provide a context for a `Vehicle` `Actor` - the `VehicleControl`.
- *
- * A vehicle can be passed between different zones and, therefore, does not belong to the zone. - * A vehicle cna be given to different players and can persist and change though players have gone. - * Therefore, also does not belong to `WorldSessionActor`. - * A vehicle must anchored to something that exists outside of the `InterstellarCluster` and its agents.
- *
- * The only purpose of this `Actor` is to allow vehicles to borrow a context for the purpose of `Actor` creation. - * It is also be allowed to be responsible for cleaning up that context. - * (In reality, it can be cleaned up anywhere a `PoisonPill` can be sent.)
- *
- * This `Actor` is intended to sit on top of the event system that handles broadcast messaging. - */ class ZoneVehicleActor( zone: Zone, vehicleList: mutable.ListBuffer[Vehicle], turretToMount: mutable.HashMap[Int, Int] ) extends Actor { - //private[this] val log = org.log4s.getLogger + private var temporaryInterference: Seq[(Vector3, PlanetSideEmpire.Value, VehicleDefinition)] = Seq() def receive: Receive = { case Zone.Vehicle.Spawn(vehicle) => @@ -79,9 +65,23 @@ class ZoneVehicleActor( } case Zone.Vehicle.TryDeploymentChange(vehicle, toDeployState) - if toDeployState > DriveState.Undeploying && Interference.Test(zone, vehicle).nonEmpty => + if toDeployState == DriveState.Deploying && + (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) + ) + vehicle.Actor.tell(Deployment.TryDeploymentChange(toDeployState), sender()) + case Zone.Vehicle.TryDeploymentChange(vehicle, toDeployState) => vehicle.Actor.tell(Deployment.TryDeploymentChange(toDeployState), sender()) @@ -89,13 +89,20 @@ class ZoneVehicleActor( case Zone.Vehicle.CanNotDespawn(_, _, _) => () - case Zone.Vehicle.CanNotDeploy(_, _, _, _) => () + case Zone.Vehicle.CanNotDeploy(_, vehicle, _, _) => () + val pos = vehicle.Position + temporaryInterference = temporaryInterference.filterNot(_._1 == pos) + + case ZoneVehicleActor.ClearInterference(pos) => + temporaryInterference = temporaryInterference.filterNot(_._1 == pos) case _ => () } } object ZoneVehicleActor { + private case class ClearInterference(pos: Vector3) + @tailrec final def recursiveFindVehicle(iter: Iterator[Vehicle], target: Vehicle, index: Int = 0): Option[Int] = { if (!iter.hasNext) { None @@ -107,4 +114,22 @@ object ZoneVehicleActor { } } } + + private def temporaryInterferenceTest( + vehicle: Vehicle, + existingInterferences: Seq[(Vector3, PlanetSideEmpire.Value, VehicleDefinition)] + ): Boolean = { + 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 + } + } + } }