diff --git a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index 1f678c4c..fda65d68 100644 --- a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -1063,9 +1063,13 @@ object GlobalDefinitions { val lock_external = new IFFLockDefinition - val door = new DoorDefinition + val door = new DoorDefinition(242) - val gr_door_mb_orb = new DoorDefinition + val door_spawn_mb = new DoorDefinition(257) + + val gr_door_mb_orb = new DoorDefinition(368) + + val spawn_tube_door = new DoorDefinition(813) val resource_silo = new ResourceSiloDefinition @@ -7729,10 +7733,18 @@ object GlobalDefinitions { door.Damageable = false door.Repairable = false + door_spawn_mb.Name = "door_spawn_mb" + door_spawn_mb.Damageable = true + door_spawn_mb.Repairable = false + gr_door_mb_orb.Name = "gr_door_mb_orb" gr_door_mb_orb.Damageable = false gr_door_mb_orb.Repairable = false + spawn_tube_door.Name = "spawn_tube_door" + spawn_tube_door.Damageable = true + spawn_tube_door.Repairable = false + resource_silo.Name = "resource_silo" resource_silo.Damageable = false resource_silo.Repairable = false diff --git a/src/main/scala/net/psforever/objects/serverobject/doors/Door.scala b/src/main/scala/net/psforever/objects/serverobject/doors/Door.scala index e6c34b84..ca55a3b6 100644 --- a/src/main/scala/net/psforever/objects/serverobject/doors/Door.scala +++ b/src/main/scala/net/psforever/objects/serverobject/doors/Door.scala @@ -26,6 +26,9 @@ class Door(private val ddef: DoorDefinition) extends Amenity { Open } + /** Doors do not have health, so only check if they are damageable. */ + override def CanDamage : Boolean = Definition.Damageable + def Definition: DoorDefinition = ddef } diff --git a/src/main/scala/net/psforever/objects/serverobject/doors/DoorControl.scala b/src/main/scala/net/psforever/objects/serverobject/doors/DoorControl.scala index a13c1b55..573db81f 100644 --- a/src/main/scala/net/psforever/objects/serverobject/doors/DoorControl.scala +++ b/src/main/scala/net/psforever/objects/serverobject/doors/DoorControl.scala @@ -20,7 +20,7 @@ class DoorControl(door: Door) var isLocked: Boolean = false var lockingMechanism: Door.LockingMechanismLogic = DoorControl.alwaysOpen - val commonBehavior: Receive = checkBehavior + def commonBehavior: Receive = checkBehavior .orElse { case Door.Lock => isLocked = true diff --git a/src/main/scala/net/psforever/objects/serverobject/doors/DoorDefinition.scala b/src/main/scala/net/psforever/objects/serverobject/doors/DoorDefinition.scala index 6864f3a1..bb074612 100644 --- a/src/main/scala/net/psforever/objects/serverobject/doors/DoorDefinition.scala +++ b/src/main/scala/net/psforever/objects/serverobject/doors/DoorDefinition.scala @@ -5,8 +5,8 @@ import net.psforever.objects.serverobject.structures.AmenityDefinition /** * The definition for any `Door`. - * Object Id 242 is a generic door. */ -class DoorDefinition extends AmenityDefinition(242) { +class DoorDefinition(objectId: Int) + extends AmenityDefinition(objectId) { Name = "door" } diff --git a/src/main/scala/net/psforever/objects/serverobject/doors/SpawnTubeDoor.scala b/src/main/scala/net/psforever/objects/serverobject/doors/SpawnTubeDoor.scala new file mode 100644 index 00000000..06c8bc59 --- /dev/null +++ b/src/main/scala/net/psforever/objects/serverobject/doors/SpawnTubeDoor.scala @@ -0,0 +1,23 @@ +// Copyright (c) 2021 PSForever +package net.psforever.objects.serverobject.doors + +import akka.actor.Props +import akka.actor.ActorContext +import net.psforever.types.Vector3 + +object SpawnTubeDoor { + /** + * Instantiate and configure a `Door` object that is to later be paired with a `SpawnTube` entity. + * @param pos the position of the door + * @param ddef the definition for this specific type of door + * @param id the unique id that will be assigned to this entity + * @param context a context to allow the object to properly set up `ActorSystem` functionality + * @return the `Door` object + */ + def Constructor(pos: Vector3, ddef: DoorDefinition)(id: Int, context: ActorContext): Door = { + val obj = Door(ddef) + obj.Position = pos + obj.Actor = context.actorOf(Props(classOf[SpawnTubeDoorControl], obj), s"${ddef.Name}_$id") + obj + } +} diff --git a/src/main/scala/net/psforever/objects/serverobject/doors/SpawnTubeDoorControl.scala b/src/main/scala/net/psforever/objects/serverobject/doors/SpawnTubeDoorControl.scala new file mode 100644 index 00000000..10a70123 --- /dev/null +++ b/src/main/scala/net/psforever/objects/serverobject/doors/SpawnTubeDoorControl.scala @@ -0,0 +1,26 @@ +// Copyright (c) 2021 PSForever +package net.psforever.objects.serverobject.doors + +import akka.actor.ActorRef +import net.psforever.objects.vital.Vitality + +class SpawnTubeDoorControl(door: Door) + extends DoorControl(door) { + lazy val spawnTube: ActorRef = { + import net.psforever.objects.serverobject.tube.SpawnTube + import net.psforever.types.Vector3 + + val dpos = door.Position + door.Owner.Amenities + .filter { _.isInstanceOf[SpawnTube] } + .minBy { tube => Vector3.DistanceSquared(dpos, tube.Position) } + .Actor + } + + //doors do not implement the Damageable mxin, so it should be fine just catching the message + override def commonBehavior: Receive = super.commonBehavior + .orElse { + case msg: Vitality.Damage => + spawnTube.forward(msg) + } +} diff --git a/src/main/scala/net/psforever/zones/Zones.scala b/src/main/scala/net/psforever/zones/Zones.scala index 530154b7..53a9ce57 100644 --- a/src/main/scala/net/psforever/zones/Zones.scala +++ b/src/main/scala/net/psforever/zones/Zones.scala @@ -1,17 +1,18 @@ package net.psforever.zones import java.io.FileNotFoundException + import net.psforever.objects.serverobject.terminals.{ProximityTerminal, ProximityTerminalDefinition, Terminal, TerminalDefinition} import net.psforever.objects.serverobject.mblocker.Locker - import java.util.concurrent.atomic.AtomicInteger + import akka.actor.ActorContext import io.circe._ import io.circe.parser._ import net.psforever.objects.{GlobalDefinitions, LocalLockerItem, LocalProjectile} import net.psforever.objects.ballistics.Projectile import net.psforever.objects.definition.BasicDefinition -import net.psforever.objects.serverobject.doors.Door +import net.psforever.objects.serverobject.doors.{Door, DoorDefinition, SpawnTubeDoor} import net.psforever.objects.serverobject.generator.Generator import net.psforever.objects.serverobject.llu.{CaptureFlagSocket, CaptureFlagSocketDefinition} import net.psforever.objects.serverobject.locks.IFFLock @@ -357,6 +358,16 @@ object Zones { owningBuildingGuid = ownerGuid ) + case doorType if doorType.equals("door_spawn_mb") || doorType.equals("spawn_tube_door") => + zoneMap.addLocalObject( + obj.guid, + SpawnTubeDoor.Constructor( + obj.position, + DefinitionUtil.fromString(doorType).asInstanceOf[DoorDefinition] + ), + owningBuildingGuid = ownerGuid + ) + case objectType if doorTypes.contains(objectType) => zoneMap .addLocalObject(obj.guid, Door.Constructor(obj.position), owningBuildingGuid = ownerGuid)