diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala
index fc9e1b2d..c4f9973b 100644
--- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala
+++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala
@@ -980,6 +980,8 @@ object GlobalDefinitions {
val respawn_tube = new SpawnTubeDefinition(732)
+ val respawn_tube_sanctuary = new SpawnTubeDefinition(732) //respawn_tube for sanctuary VT_building_* structures
+
val respawn_tube_tower = new SpawnTubeDefinition(733)
val teleportpad_terminal = new OrderTerminalDefinition(853)
@@ -1029,6 +1031,41 @@ object GlobalDefinitions {
val manned_turret = new TurretDefinition(480)
initMiscellaneous()
+ /*
+ Buildings
+ */
+ val building : ObjectDefinition = new ObjectDefinition(474) { Name = "building" } //borrows object id of entity mainbase1
+
+ val warpgate : ObjectDefinition with SpawnPointDefinition = new ObjectDefinition(993) with SpawnPointDefinition
+ warpgate.Name = "warpgate"
+ warpgate.UseRadius = 301.8713f
+ warpgate.Delay = 10
+ warpgate.VehicleAllowance = true
+ warpgate.SpecificPointFunc = SpawnPoint.Gate
+
+ val hst : ObjectDefinition with SpawnPointDefinition = new ObjectDefinition(402) with SpawnPointDefinition
+ hst.Name = "hst"
+ hst.UseRadius = 20.4810f
+ hst.Delay = 10
+ hst.VehicleAllowance = true
+ hst.NoWarp += dropship
+ hst.NoWarp += galaxy_gunship
+ hst.NoWarp += lodestar
+ //hst.NoWarp += aphelion_gunner
+ //hst.NoWarp += aphelion_flight
+ //hst.NoWarp += colossus_gunner
+ //hst.NoWarp += colossus_flight
+ //hst.NoWarp += peregrine_gunner
+ //hst.NoWarp += peregrine_flight
+ hst.SpecificPointFunc = SpawnPoint.Gate
+
+ val warpgate_cavern : ObjectDefinition with SpawnPointDefinition = new ObjectDefinition(994) with SpawnPointDefinition
+ warpgate_cavern.Name = "warpgate_cavern"
+ warpgate_cavern.UseRadius = 55.0522f
+ warpgate_cavern.Delay = 10
+ warpgate_cavern.VehicleAllowance = true
+ warpgate_cavern.SpecificPointFunc = SpawnPoint.Gate
+
/**
* Given a faction, provide the standard assault melee weapon.
* @param faction the faction
@@ -5352,6 +5389,7 @@ object GlobalDefinitions {
mosquito.Name = "mosquito"
mosquito.MaxHealth = 665
mosquito.MaxShields = 133 + 1
+ mosquito.CanFly = true
mosquito.Seats += 0 -> new SeatDefinition()
mosquito.Seats(0).Bailable = true
mosquito.Seats(0).ControlledWeapon = 1
@@ -5367,6 +5405,7 @@ object GlobalDefinitions {
lightgunship.Name = "lightgunship"
lightgunship.MaxHealth = 1000
lightgunship.MaxShields = 200 + 1
+ lightgunship.CanFly = true
lightgunship.Seats += 0 -> new SeatDefinition()
lightgunship.Seats(0).Bailable = true
lightgunship.Seats(0).ControlledWeapon = 1
@@ -5383,6 +5422,7 @@ object GlobalDefinitions {
wasp.Name = "wasp"
wasp.MaxHealth = 515
wasp.MaxShields = 103 + 1
+ wasp.CanFly = true
wasp.Seats += 0 -> new SeatDefinition()
wasp.Seats(0).Bailable = true
wasp.Seats(0).ControlledWeapon = 1
@@ -5398,6 +5438,7 @@ object GlobalDefinitions {
liberator.Name = "liberator"
liberator.MaxHealth = 2500
liberator.MaxShields = 500 + 1
+ liberator.CanFly = true
liberator.Seats += 0 -> new SeatDefinition()
liberator.Seats(0).ControlledWeapon = 3
liberator.Seats += 1 -> new SeatDefinition()
@@ -5421,6 +5462,7 @@ object GlobalDefinitions {
vulture.Name = "vulture"
vulture.MaxHealth = 2500
vulture.MaxShields = 500 + 1
+ vulture.CanFly = true
vulture.Seats += 0 -> new SeatDefinition()
vulture.Seats(0).ControlledWeapon = 3
vulture.Seats += 1 -> new SeatDefinition()
@@ -5444,6 +5486,7 @@ object GlobalDefinitions {
dropship.Name = "dropship"
dropship.MaxHealth = 5000
dropship.MaxShields = 1000 + 1
+ dropship.CanFly = true
dropship.Seats += 0 -> new SeatDefinition()
dropship.Seats += 1 -> new SeatDefinition()
dropship.Seats(1).Bailable = true
@@ -5499,6 +5542,7 @@ object GlobalDefinitions {
galaxy_gunship.Name = "galaxy_gunship"
galaxy_gunship.MaxHealth = 6000
galaxy_gunship.MaxShields = 1200 + 1
+ galaxy_gunship.CanFly = true
galaxy_gunship.Seats += 0 -> new SeatDefinition()
galaxy_gunship.Seats += 1 -> new SeatDefinition()
galaxy_gunship.Seats(1).ControlledWeapon = 6
@@ -5531,6 +5575,7 @@ object GlobalDefinitions {
lodestar.Name = "lodestar"
lodestar.MaxHealth = 5000
lodestar.MaxShields = 1000 + 1
+ lodestar.CanFly = true
lodestar.Seats += 0 -> new SeatDefinition()
lodestar.MountPoints += 1 -> 0
lodestar.MountPoints += 2 -> 1
@@ -5554,6 +5599,7 @@ object GlobalDefinitions {
phantasm.MaxHealth = 2500
phantasm.MaxShields = 500 + 1
phantasm.CanCloak = true
+ phantasm.CanFly = true
phantasm.Seats += 0 -> new SeatDefinition()
phantasm.Seats += 1 -> new SeatDefinition()
phantasm.Seats(1).Bailable = true
@@ -5731,6 +5777,10 @@ object GlobalDefinitions {
* Initialize `Miscellaneous` globals.
*/
private def initMiscellaneous() : Unit = {
+ ams_respawn_tube.Name = "ams_respawn_tube"
+ ams_respawn_tube.Delay = 5
+ ams_respawn_tube.SpecificPointFunc = SpawnPoint.AMS
+
matrix_terminala.Name = "matrix_terminala"
matrix_terminalb.Name = "matrix_terminalb"
@@ -5789,6 +5839,18 @@ object GlobalDefinitions {
bfr_terminal.Tab += 46769 -> OrderTerminalDefinition.VehiclePage(VehicleTerminalDefinition.bfrVehicles, VehicleTerminalDefinition.trunk)
bfr_terminal.Tab += 4 -> OrderTerminalDefinition.VehicleLoadoutPage()
+ respawn_tube.Name = "respawn_tube"
+ respawn_tube.Delay = 10
+ respawn_tube.SpecificPointFunc = SpawnPoint.Tube
+
+ respawn_tube_sanctuary.Name = "respawn_tube"
+ respawn_tube_sanctuary.Delay = 10
+ respawn_tube_sanctuary.SpecificPointFunc = SpawnPoint.Default
+
+ respawn_tube_tower.Name = "respawn_tube_tower"
+ respawn_tube_tower.Delay = 10
+ respawn_tube_tower.SpecificPointFunc = SpawnPoint.Tube
+
teleportpad_terminal.Name = "teleportpad_terminal"
teleportpad_terminal.Tab += 0 -> OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.routerTerminal)
diff --git a/common/src/main/scala/net/psforever/objects/SpawnPoint.scala b/common/src/main/scala/net/psforever/objects/SpawnPoint.scala
new file mode 100644
index 00000000..05eedd80
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/SpawnPoint.scala
@@ -0,0 +1,162 @@
+// Copyright (c) 2019 PSForever
+package net.psforever.objects
+
+import net.psforever.objects.definition.{ObjectDefinition, VehicleDefinition}
+import net.psforever.objects.serverobject.PlanetSideServerObject
+import net.psforever.packet.game.PlanetSideGUID
+import net.psforever.types.Vector3
+
+import scala.collection.mutable
+
+trait SpawnPoint {
+ psso : PlanetSideServerObject =>
+ /**
+ * An element of the contract of `PlanetSideServerObject`;
+ * but, this makes it visible to a `SpawnPoint` object without casting.
+ * @see `Identifiable.GUID`
+ */
+ def GUID : PlanetSideGUID
+ /**
+ * An element of the contract of `PlanetSideServerObject`;
+ * but, this makes it visible to a `SpawnPoint` object without casting.
+ * @see `WorldEntity.GUID`
+ * @see `SpecificPoint`
+ */
+ def Position : Vector3
+ /**
+ * An element of the contract of `PlanetSideServerObject`;
+ * but, this makes it visible to a `SpawnPoint` object without casting.
+ * @see `WorldEntity.GUID`
+ * @see `SpecificPoint`
+ */
+ def Orientation : Vector3
+ /**
+ * An element of an unspoken contract with `Amenity`.
+ * While not all `SpawnPoint` objects will be `Amenity` objects, a subclass of the `PlanetSideServerObject` class,
+ * they will all promote having an object owner, or "parent."
+ * This should generally be themselves.
+ * @see `Amenity.Owner`
+ */
+ def Owner : PlanetSideServerObject
+ /**
+ * An element of the contract of `PlanetSideServerObject`;
+ * but, this makes it visible to a `SpawnPoint` object without casting.
+ * @see `PlanetSideGameObject.Definition`
+ * @see `SpecificPoint`
+ */
+ def Definition : ObjectDefinition with SpawnPointDefinition
+
+ /**
+ * Determine a specific position and orientation in which to spawn the target.
+ * @return a `Tuple` of `Vector3` objects;
+ * the first represents the game world position of spawning;
+ * the second represents the game world direction of spawning
+ */
+ def SpecificPoint(target : PlanetSideGameObject) : (Vector3, Vector3) = {
+ psso.Definition match {
+ case d : SpawnPointDefinition =>
+ d.SpecificPoint(this, target)
+ case _ =>
+ SpawnPoint.Default(this, target)
+ }
+ }
+}
+
+object SpawnPoint {
+ def Default(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = (obj.Position, obj.Orientation)
+
+ def Tube(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = (
+ obj.Position + Vector3.z(1.5f),
+ obj.Orientation.xy + Vector3.z(obj.Orientation.z + 90 % 360)
+ )
+
+ def AMS(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = {
+ //position the player alongside either of the AMS's terminals, facing away from it
+ val ori = obj.Orientation
+ val side = if(System.currentTimeMillis() % 2 == 0) 1 else -1 //right | left
+ val x = ori.x
+ val xsin = 3 * side * math.abs(math.sin(math.toRadians(x))).toFloat + 0.5f //sin because 0-degrees is up
+ val z = ori.z
+ val zrot = (z + 90) % 360
+ val zrad = math.toRadians(zrot)
+ val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * (3 * side) //x=sin, y=cos because compass-0 is East, not North
+ (
+ obj.Position + shift + (if(x >= 330) { //ams leaning to the left
+ Vector3.z(xsin)
+ }
+ else { //ams leaning to the right
+ Vector3.z(-xsin)
+ }),
+ if(side == 1) {
+ Vector3.z(zrot)
+ }
+ else {
+ Vector3.z((z - 90) % 360)
+ }
+ )
+ }
+
+ def Gate(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = {
+ obj.Definition match {
+ case d : SpawnPointDefinition =>
+ val ori = target.Orientation
+ val zrad = math.toRadians(ori.z)
+ val radius = scala.math.random.toFloat * d.UseRadius/2 + 20f //20 is definitely outside of the gating energy field
+ val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * radius
+ val altitudeShift = target.Definition match {
+ case vdef : VehicleDefinition if GlobalDefinitions.isFlightVehicle(vdef) =>
+ Vector3.z(scala.math.random.toFloat * d.UseRadius/4 + 20f)
+ case _ =>
+ Vector3.Zero
+ }
+ (obj.Position + shift + altitudeShift, ori)
+ case _ =>
+ Default(obj, target)
+ }
+ }
+}
+
+trait SpawnPointDefinition {
+ private var radius : Float = 0f //m
+ private var delay : Long = 0 //s
+ private var noWarp : Option[mutable.Set[VehicleDefinition]] = None
+ private var spawningFunc : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = SpawnPoint.Default
+
+ def UseRadius : Float = radius
+
+ def UseRadius_=(rad : Float) : Float = {
+ radius = rad
+ UseRadius
+ }
+
+ def Delay : Long = delay
+
+ def Delay_=(toDelay : Long) : Long = {
+ delay = toDelay
+ Delay
+ }
+
+ def VehicleAllowance : Boolean = noWarp.isDefined
+
+ def VehicleAllowance_=(allow : Boolean) : Boolean = {
+ if(allow && noWarp.isEmpty) {
+ noWarp = Some(mutable.Set.empty[VehicleDefinition])
+ }
+ else if(!allow && noWarp.isDefined) {
+ noWarp = None
+ }
+ VehicleAllowance
+ }
+
+ def NoWarp : mutable.Set[VehicleDefinition] = {
+ noWarp.getOrElse(mutable.Set.empty[VehicleDefinition])
+ }
+
+ def SpecificPointFunc : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = spawningFunc
+
+ def SpecificPointFunc_=(func : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3)) : Unit = {
+ spawningFunc = func
+ }
+
+ def SpecificPoint(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = spawningFunc(obj, target)
+}
diff --git a/common/src/main/scala/net/psforever/objects/Vehicle.scala b/common/src/main/scala/net/psforever/objects/Vehicle.scala
index c552177b..0026124c 100644
--- a/common/src/main/scala/net/psforever/objects/Vehicle.scala
+++ b/common/src/main/scala/net/psforever/objects/Vehicle.scala
@@ -82,6 +82,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
private var trunkAccess : Option[PlanetSideGUID] = None
private var jammered : Boolean = false
private var cloaked : Boolean = false
+ private var flying : Boolean = false
private var capacitor : Int = 0
private var continent : String = "home2" //the zone id
@@ -207,6 +208,13 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
Cloaked
}
+ def Flying : Boolean = flying
+
+ def Flying_=(isFlying : Boolean) : Boolean = {
+ flying = isFlying
+ Flying
+ }
+
def Capacitor : Int = capacitor
def Capacitor_=(value: Int) : Int = {
diff --git a/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala b/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala
index ffc4237a..0d90fabb 100644
--- a/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala
@@ -36,6 +36,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
private var trunkSize : InventoryTile = InventoryTile.None
private var trunkOffset : Int = 0
private var canCloak : Boolean = false
+ private var canFly : Boolean = false
private var canBeOwned : Boolean = true
private var serverVehicleOverrideSpeeds : (Int, Int) = (0, 0)
private var deconTime : Option[FiniteDuration] = None
@@ -81,6 +82,13 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
CanCloak
}
+ def CanFly : Boolean = canFly
+
+ def CanFly_=(flying : Boolean) : Boolean = {
+ canFly = flying
+ CanFly
+ }
+
def Weapons : mutable.HashMap[Int, ToolDefinition] = weapons
def Deployment : Boolean = deployment
diff --git a/common/src/main/scala/net/psforever/objects/definition/converter/VariantVehicleConverter.scala b/common/src/main/scala/net/psforever/objects/definition/converter/VariantVehicleConverter.scala
index 12758a05..cfe9d68d 100644
--- a/common/src/main/scala/net/psforever/objects/definition/converter/VariantVehicleConverter.scala
+++ b/common/src/main/scala/net/psforever/objects/definition/converter/VariantVehicleConverter.scala
@@ -7,5 +7,13 @@ import net.psforever.packet.game.objectcreate.{VariantVehicleData, VehicleFormat
class VariantVehicleConverter extends VehicleConverter {
override protected def SpecificFormatModifier : VehicleFormat.Value = VehicleFormat.Variant
- override protected def SpecificFormatData(obj : Vehicle) = Some(VariantVehicleData(0))
+ override protected def SpecificFormatData(obj : Vehicle) = {
+ /*
+ landed is 0
+ flying is 7
+ */
+ Some(VariantVehicleData(
+ if(obj.Definition.CanFly && obj.Flying) 7 else 0
+ ))
+ }
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/hackable/Hackable.scala b/common/src/main/scala/net/psforever/objects/serverobject/hackable/Hackable.scala
index dc6fbd96..65c0e5ff 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/hackable/Hackable.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/hackable/Hackable.scala
@@ -3,40 +3,46 @@ package net.psforever.objects.serverobject.hackable
import net.psforever.objects.Player
import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.packet.game.{PlanetSideGUID, TriggeredSound}
-import net.psforever.types.Vector3
+import net.psforever.types.{PlanetSideEmpire, Vector3}
trait Hackable extends FactionAffinity {
- /** An entry that maintains a reference to the `Player`, and the player's GUID and location when the message was received. */
- private var hackedBy : Option[(Player, PlanetSideGUID, Vector3)] = None
- def HackedBy : Option[(Player, PlanetSideGUID, Vector3)] = hackedBy
- def HackedBy_=(agent : Player) : Option[(Player, PlanetSideGUID, Vector3)] = HackedBy_=(Some(agent))
+ import Hackable._
+ /** inportant information regarding the hack and how it was started */
+ private var hackedBy : Option[HackInfo] = None
+ def HackedBy : Option[HackInfo] = hackedBy
+ def HackedBy_=(agent : Player) : Option[HackInfo] = HackedBy_=(Some(agent))
+
/**
- * Set the hack state of this object by recording important information about the player that caused it.
+ * Set the hack state of this object by recording important information about the player who caused it.
* Set the hack state if there is no current hack state.
* Override the hack state with a new hack state if the new user has different faction affiliation.
* @param agent a `Player`, or no player
* @return the player hack entry
*/
- def HackedBy_=(agent : Option[Player]) : Option[(Player, PlanetSideGUID, Vector3)] = {
- hackedBy match {
- case None =>
- //set the hack state if there is no current hack state
- if(agent.isDefined) {
- hackedBy = Some(agent.get, agent.get.GUID, agent.get.Position)
- }
- case Some(_) =>
- //clear the hack state if no agent is provided or the agent's faction matches the object faction
- if(agent.isEmpty || agent.get.Faction == this.Faction) {
+ def HackedBy_=(agent : Option[Player]) : Option[HackInfo] = {
+ (hackedBy, agent) match {
+ case (None, Some(actor)) =>
+ hackedBy = Some(HackInfo(actor.Name, actor.GUID, actor.Faction, actor.Position, System.nanoTime, 0L))
+ case (Some(info), Some(actor)) =>
+ if(actor.Faction == this.Faction) {
+ //hack cleared
hackedBy = None
}
- //override the hack state with a new hack state if the new user has different faction affiliation
- else if(agent.get.Faction != hackedBy.get._1.Faction) {
- hackedBy = Some(agent.get, agent.get.GUID, agent.get.Position)
+ else if(actor.Faction != info.hackerFaction) {
+ //override the hack state with a new hack state if the new user has different faction affiliation
+ hackedBy = Some(HackInfo(actor.Name, actor.GUID, actor.Faction, actor.Position, System.nanoTime, 0L))
}
+ case (_, None) =>
+ hackedBy = None
}
HackedBy
}
+ def HackedBy_=(hackInfo : HackInfo) : Option[HackInfo] = {
+ hackedBy = Some(hackInfo)
+ HackedBy
+ }
+
/** The sound made when the object is hacked */
private var hackSound : TriggeredSound.Value = TriggeredSound.HackDoor
def HackSound : TriggeredSound.Value = hackSound
@@ -61,3 +67,15 @@ trait Hackable extends FactionAffinity {
arr
}
}
+
+object Hackable {
+ final case class HackInfo(hackerName : String,
+ hackerGUID : PlanetSideGUID,
+ hackerFaction : PlanetSideEmpire.Value,
+ hackerPos : Vector3,
+ hackStartTime : Long,
+ hackDuration : Long) {
+ def Duration(time : Long) : HackInfo =
+ HackInfo(hackerName, hackerGUID, hackerFaction, hackerPos, hackStartTime, time)
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala
index 311e274f..81069f1f 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala
@@ -2,13 +2,18 @@
package net.psforever.objects.serverobject.structures
import akka.actor.ActorContext
+import net.psforever.objects.GlobalDefinitions
import net.psforever.objects.definition.ObjectDefinition
import net.psforever.objects.serverobject.PlanetSideServerObject
+import net.psforever.objects.serverobject.hackable.Hackable
+import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
+import net.psforever.objects.serverobject.terminals.CaptureTerminal
+import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.zones.Zone
-import net.psforever.packet.game.PlanetSideGUID
+import net.psforever.packet.game._
import net.psforever.types.{PlanetSideEmpire, Vector3}
-class Building(private val building_guid : Int, private val map_id : Int, private val zone : Zone, private val buildingType : StructureType.Value) extends PlanetSideServerObject {
+class Building(private val building_guid : Int, private val map_id : Int, private val zone : Zone, private val buildingType : StructureType.Value, private val buildingDefinition : ObjectDefinition) extends PlanetSideServerObject {
/**
* The map_id is the identifier number used in BuildingInfoUpdateMessage. This is the index that the building appears in the MPO file starting from index 1
* The GUID is the identifier number used in SetEmpireMessage / Facility hacking / PlanetSideAttributeMessage.
@@ -36,30 +41,93 @@ class Building(private val building_guid : Int, private val map_id : Int, privat
def Zone : Zone = zone
+ def Info : (
+ Int,
+ Boolean, PlanetSideEmpire.Value, Long, PlanetSideEmpire.Value,
+ Long, Option[Additional1],
+ PlanetSideGeneratorState.Value, Boolean, Boolean,
+ Int, Int,
+ List[Additional2], Long, Boolean,
+ Int, Option[Additional3],
+ Boolean, Boolean
+ ) = {
+ //if we have a silo, get the NTU level
+ val ntuLevel : Int = amenities.find(_.Definition == GlobalDefinitions.resource_silo) match {
+ case Some(obj: ResourceSilo) =>
+ obj.CapacitorDisplay.toInt
+ case _ => //we have no silo; we have unlimited power
+ 10
+ }
+ //if we have a capture terminal, get the hack status & time from control console if it exists
+ val (hacking, hackingFaction, hackTime) : (Boolean, PlanetSideEmpire.Value, Long) = amenities.find(_.Definition == GlobalDefinitions.capture_terminal) match {
+ case Some(obj: CaptureTerminal with Hackable) =>
+ obj.HackedBy match {
+ case Some(Hackable.HackInfo(_, _, hfaction, _, start, length)) =>
+ (true, hfaction, math.max(0, start + length - System.nanoTime))
+ case _ =>
+ (false, PlanetSideEmpire.NEUTRAL, 0L)
+ }
+ case _ =>
+ (false, PlanetSideEmpire.NEUTRAL, 0L)
+ }
+ //TODO if we have a generator, get the current repair state
+ val (generatorState, bootGeneratorPain) = (PlanetSideGeneratorState.Normal, false)
+ //if we have spawn tubes, determine if any of them are active
+ val (spawnTubesNormal, boostSpawnPain) : (Boolean, Boolean) = {
+ val o = amenities.collect({ case _ : SpawnTube => true }) ///TODO obj.Health > 0
+ if(o.nonEmpty) {
+ (o.foldLeft(false)(_ || _), false) //TODO poll pain field strength
+ }
+ else {
+ (true, false)
+ }
+ }
+ //out
+ (
+ ntuLevel,
+ hacking,
+ hackingFaction,
+ hackTime,
+ if(ntuLevel > 0) Faction else PlanetSideEmpire.NEUTRAL,
+ 0, //!! Field != 0 will cause malformed packet. See class def.
+ None,
+ generatorState,
+ spawnTubesNormal,
+ false, //force_dome_active
+ 0, //lattice_benefit
+ 0, //cavern_benefit; !! Field > 0 will cause malformed packet. See class def.
+ Nil,
+ 0,
+ false,
+ 8, //!! Field != 8 will cause malformed packet. See class def.
+ None,
+ boostSpawnPain, //boost_spawn_pain
+ bootGeneratorPain //boost_generator_pain
+ )
+ }
+
def BuildingType : StructureType.Value = buildingType
override def Continent : String = zone.Id
override def Continent_=(zone : String) : String = Continent
- def Definition: ObjectDefinition = Building.BuildingDefinition
+ def Definition: ObjectDefinition = buildingDefinition
}
object Building {
- final val NoBuilding : Building = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Platform) {
+ final val NoBuilding : Building = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Platform, GlobalDefinitions.building) {
override def Faction_=(faction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
override def Amenities_=(obj : Amenity) : List[Amenity] = Nil
}
- final val BuildingDefinition : ObjectDefinition = new ObjectDefinition(0) { Name = "building" }
-
def apply(guid : Int, map_id : Int, zone : Zone, buildingType : StructureType.Value) : Building = {
- new Building(guid, map_id, zone, buildingType)
+ new Building(guid, map_id, zone, buildingType, GlobalDefinitions.building)
}
def Structure(buildingType : StructureType.Value, location : Vector3)(guid : Int, map_id : Int, zone : Zone, context : ActorContext) : Building = {
import akka.actor.Props
- val obj = new Building(guid, map_id, zone, buildingType)
+ val obj = new Building(guid, map_id, zone, buildingType, GlobalDefinitions.building)
obj.Position = location
obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$map_id-$buildingType-building")
obj
@@ -67,10 +135,18 @@ object Building {
def Structure(buildingType : StructureType.Value)(guid: Int, map_id : Int, zone : Zone, context : ActorContext) : Building = {
import akka.actor.Props
- val obj = new Building(guid, map_id, zone, buildingType)
+ val obj = new Building(guid, map_id, zone, buildingType, GlobalDefinitions.building)
obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$map_id-$buildingType-building")
obj
}
+ def Structure(buildingType : StructureType.Value, buildingDefinition : ObjectDefinition, location : Vector3)(guid: Int, id : Int, zone : Zone, context : ActorContext) : Building = {
+ import akka.actor.Props
+ val obj = new Building(guid, id, zone, buildingType, buildingDefinition)
+ obj.Position = location
+ obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$id-$buildingType-building")
+ obj
+ }
+
final case class SendMapUpdate(all_clients: Boolean)
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala
index 63ef77b0..90aa9ff1 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/BuildingControl.scala
@@ -1,26 +1,12 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.structures
-import java.util.concurrent.TimeUnit
-
-import akka.actor.{Actor, ActorRef, Props}
-import net.psforever.objects.GlobalDefinitions
+import akka.actor.{Actor, ActorRef}
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
-import net.psforever.objects.serverobject.hackable.Hackable
-import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
-import net.psforever.objects.serverobject.terminals.CaptureTerminal
-import net.psforever.packet.game.{BuildingInfoUpdateMessage, PlanetSideGeneratorState}
-import net.psforever.types.PlanetSideEmpire
+import net.psforever.packet.game.BuildingInfoUpdateMessage
import services.ServiceManager
import services.ServiceManager.Lookup
import services.galaxy.{GalaxyAction, GalaxyResponse, GalaxyServiceMessage, GalaxyServiceResponse}
-import services.local.support.HackCaptureActor
-
-import scala.util.Success
-import scala.concurrent.duration._
-import akka.pattern.ask
-
-import scala.concurrent.{Await, Future}
class BuildingControl(building : Building) extends Actor with FactionAffinityBehavior.Check {
def FactionObject : FactionAffinity = building
@@ -47,59 +33,32 @@ class BuildingControl(building : Building) extends Actor with FactionAffinityBeh
building.Amenities.foreach(_.Actor forward FactionAffinity.ConfirmFactionAffinity())
}
sender ! FactionAffinity.AssertFactionAffinity(building, faction)
+
case Building.SendMapUpdate(all_clients: Boolean) =>
- log.info(s"Sending BuildingInfoUpdateMessage update. Zone: ${building.Zone.Number} - Building: ${building.GUID} / MapId: ${building.MapId}")
- var ntuLevel = 0
- var is_hacked = false
- var hack_time_remaining_ms = 0L;
- var hacked_by_faction = PlanetSideEmpire.NEUTRAL
-
- // Get Ntu level from silo if it exists
- building.Amenities.filter(x => (x.Definition == GlobalDefinitions.resource_silo)).headOption.asInstanceOf[Option[ResourceSilo]] match {
- case Some(obj: ResourceSilo) =>
- ntuLevel = obj.CapacitorDisplay.toInt
- case _ => ;
- }
-
- // Get hack status & time from control console if it exists
- building.Amenities.filter(x => x.Definition == GlobalDefinitions.capture_terminal).headOption.asInstanceOf[Option[CaptureTerminal with Hackable]] match {
- case Some(obj: CaptureTerminal with Hackable) =>
- if(!obj.HackedBy.isEmpty) {
- is_hacked = true
- hacked_by_faction = obj.HackedBy.get._1.Faction
- }
-
- import scala.concurrent.ExecutionContext.Implicits.global
- val future = ask(localService, HackCaptureActor.GetHackTimeRemainingNanos(obj.GUID))(1 second)
-
- //todo: this is blocking. Not so bad when we're only retrieving one piece of data but as more functionality is added we'll need to change this to be async but wait for all replies before sending BIUM to clients
- val time = Await.result(future, 1 second).asInstanceOf[Long]
- hack_time_remaining_ms = TimeUnit.MILLISECONDS.convert(time, TimeUnit.NANOSECONDS)
- case _ => ;
- }
-
+ val zoneNumber = building.Zone.Number
+ val buildingNumber = building.MapId
+ log.info(s"sending BuildingInfoUpdateMessage update - zone=$zoneNumber, building=$buildingNumber")
+ val (
+ ntuLevel,
+ isHacked, empireHack, hackTimeRemaining, controllingEmpire,
+ unk1, unk1x,
+ generatorState, spawnTubesNormal, forceDomeActive,
+ latticeBenefit, cavernBenefit,
+ unk4, unk5, unk6,
+ unk7, unk7x,
+ boostSpawnPain, boostGeneratorPain
+ ) = building.Info
val msg = BuildingInfoUpdateMessage(
- continent_id = building.Zone.Number, //Zone
- building_map_id = building.MapId, //Facility
- ntu_level = ntuLevel,
- is_hacked,
- hacked_by_faction,
- hack_time_remaining_ms,
- empire_own = building.Faction,
- unk1 = 0, //!! Field != 0 will cause malformed packet. See class def.
- unk1x = None,
- generator_state = PlanetSideGeneratorState.Normal,
- spawn_tubes_normal = true,
- force_dome_active = false,
- lattice_benefit = 0,
- cavern_benefit = 0, //!! Field > 0 will cause malformed packet. See class def.
- unk4 = Nil,
- unk5 = 0,
- unk6 = false,
- unk7 = 8, //!! Field != 8 will cause malformed packet. See class def.
- unk7x = None,
- boost_spawn_pain = false,
- boost_generator_pain = false
+ zoneNumber,
+ buildingNumber,
+ ntuLevel,
+ isHacked, empireHack, hackTimeRemaining, controllingEmpire,
+ unk1, unk1x,
+ generatorState, spawnTubesNormal, forceDomeActive,
+ latticeBenefit, cavernBenefit,
+ unk4, unk5, unk6,
+ unk7, unk7x,
+ boostSpawnPain, boostGeneratorPain
)
if(all_clients) {
@@ -110,6 +69,6 @@ class BuildingControl(building : Building) extends Actor with FactionAffinityBeh
}
case default =>
- log.warn(s"BuildingControl: Unknown message ${default} received from ${sender().path}")
+ log.warn(s"BuildingControl: Unknown message $default received from ${sender().path}")
}
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/StructureType.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/StructureType.scala
index 7acc1840..59028b6a 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/structures/StructureType.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/StructureType.scala
@@ -9,12 +9,12 @@ object StructureType extends Enumeration {
type Type = Value
val
- Bridge,
+ Bridge, //technically, a "bridge section"
Building, //generic
- Bunker,
- Facility,
- Platform, //outdoor amenities like the spawn pads in sanctuary
- Tower,
- WarpGate
+ Bunker, //low accessible ground cover
+ Facility, //large base
+ Platform, //outdoor amenities disconnected froma proper base like the vehicle spawn pads in sanctuary
+ Tower, //also called field towers: watchtower, air tower, gun tower
+ WarpGate //transport point between zones
= Value
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/WarpGate.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/WarpGate.scala
index 14626993..eca8a29f 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/structures/WarpGate.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/WarpGate.scala
@@ -2,20 +2,96 @@
package net.psforever.objects.serverobject.structures
import akka.actor.ActorContext
+import net.psforever.objects.definition.ObjectDefinition
+import net.psforever.objects.serverobject.PlanetSideServerObject
+import net.psforever.objects.{GlobalDefinitions, SpawnPoint, SpawnPointDefinition}
import net.psforever.objects.zones.Zone
+import net.psforever.packet.game.{Additional1, Additional2, Additional3, PlanetSideGeneratorState}
+import net.psforever.types.{PlanetSideEmpire, Vector3}
-class WarpGate(building_guid : Int, map_id : Int, zone : Zone) extends Building(building_guid, map_id, zone, StructureType.WarpGate) {
+class WarpGate(building_guid : Int, map_id : Int, zone : Zone, buildingDefinition : ObjectDefinition with SpawnPointDefinition)
+ extends Building(building_guid, map_id, zone, StructureType.WarpGate, buildingDefinition)
+ with SpawnPoint {
+ private var active : Boolean = true
+ private var broadcast : Boolean = false
+
+ override def Info : (
+ Int,
+ Boolean, PlanetSideEmpire.Value, Long, PlanetSideEmpire.Value,
+ Long, Option[Additional1],
+ PlanetSideGeneratorState.Value, Boolean, Boolean,
+ Int, Int,
+ List[Additional2], Long, Boolean,
+ Int, Option[Additional3],
+ Boolean, Boolean
+ ) = {
+ (
+ 0,
+ false,
+ PlanetSideEmpire.NEUTRAL,
+ 0L,
+ Faction,
+ 0, //!! Field != 0 will cause malformed packet. See class def.
+ None,
+ PlanetSideGeneratorState.Normal,
+ true, //TODO?
+ false, //force_dome_active
+ 0, //lattice_benefit
+ 0, //cavern_benefit; !! Field > 0 will cause malformed packet. See class def.
+ Nil,
+ 0,
+ false,
+ 8, //!! Field != 8 will cause malformed packet. See class def.
+ None,
+ false, //boost_spawn_pain
+ false //boost_generator_pain
+ )
+ }
+
+ def Active : Boolean = active
+
+ def Active_=(state : Boolean) : Boolean = {
+ active = state
+ Active
+ }
+
+ def Broadcast : Boolean = Active && broadcast
+
+ def Broadcast_=(cast : Boolean) : Boolean = {
+ broadcast = cast
+ Broadcast
+ }
+
+ def Owner : PlanetSideServerObject = this
+
+ override def Definition : ObjectDefinition with SpawnPointDefinition = buildingDefinition
//TODO stuff later
}
object WarpGate {
- def apply(guid : Int, map_id : Int, zone : Zone) : WarpGate = {
- new WarpGate(guid, map_id, zone)
+ def apply(guid : Int, map_id : Int, zone : Zone, buildingDefinition : ObjectDefinition with SpawnPointDefinition) : WarpGate = {
+ new WarpGate(guid, map_id, zone, buildingDefinition)
}
def Structure(guid : Int, map_id : Int, zone : Zone, context : ActorContext) : WarpGate = {
import akka.actor.Props
- val obj = new WarpGate(guid, map_id, zone)
+ val obj = new WarpGate(guid, map_id, zone, GlobalDefinitions.warpgate)
+ obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$map_id-gate")
+ obj
+ }
+
+ def Structure(location : Vector3)(guid : Int, map_id : Int, zone : Zone, context : ActorContext) : WarpGate = {
+ import akka.actor.Props
+ val obj = new WarpGate(guid, map_id, zone, GlobalDefinitions.warpgate)
+ obj.Position = location
+ obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$map_id-gate")
+ obj
+ }
+
+ def Structure(location : Vector3, buildingDefinition : ObjectDefinition with SpawnPointDefinition)(guid : Int, map_id : Int, zone : Zone, context : ActorContext) : WarpGate = {
+ import akka.actor.Props
+ val obj = new WarpGate(guid, map_id, zone, buildingDefinition)
+ obj.Position = location
obj.Actor = context.actorOf(Props(classOf[BuildingControl], obj), s"$map_id-gate")
obj
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTube.scala b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTube.scala
index 91aff35d..494e37a7 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTube.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTube.scala
@@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.tube
-import net.psforever.objects.GlobalDefinitions
+import net.psforever.objects.{GlobalDefinitions, SpawnPoint}
import net.psforever.objects.serverobject.structures.Amenity
/**
@@ -9,7 +9,8 @@ import net.psforever.objects.serverobject.structures.Amenity
* that infantry will be arranged upon spawning into the game world.
* @param tDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
*/
-class SpawnTube(tDef : SpawnTubeDefinition) extends Amenity {
+class SpawnTube(tDef : SpawnTubeDefinition) extends Amenity
+ with SpawnPoint {
def Definition : SpawnTubeDefinition = tDef
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeDefinition.scala
index 1cb1279d..755f64a1 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeDefinition.scala
@@ -2,28 +2,16 @@
package net.psforever.objects.serverobject.tube
import akka.actor.ActorContext
+import net.psforever.objects.SpawnPointDefinition
import net.psforever.objects.definition.ObjectDefinition
import net.psforever.objects.definition.converter.SpawnTubeConverter
import net.psforever.objects.serverobject.structures.Amenity
/**
- * The definition for any `VehicleSpawnPad`.
- * Currently, all tubes identify as object id 49 - `ams_respawn_tube` - configured manually.
- * @see `GlobalDefinitions.ams_respawn_tube`
+ * The definition for any spawn point in the game world.
*/
-class SpawnTubeDefinition(object_id : Int) extends ObjectDefinition(object_id) {
- Name = if(object_id == 49) {
- "ams_respawn_tube"
- }
- else if(object_id == 732) {
- "respawn_tube"
- }
- else if(object_id == 733) {
- "respawn_tube_tower"
- }
- else {
- throw new IllegalArgumentException("terminal must be object id 49, 732, or 733")
- }
+class SpawnTubeDefinition(object_id : Int) extends ObjectDefinition(object_id)
+ with SpawnPointDefinition {
Packet = new SpawnTubeConverter
}
diff --git a/common/src/main/scala/net/psforever/objects/zones/InterstellarCluster.scala b/common/src/main/scala/net/psforever/objects/zones/InterstellarCluster.scala
index bb731466..a85c784a 100644
--- a/common/src/main/scala/net/psforever/objects/zones/InterstellarCluster.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/InterstellarCluster.scala
@@ -61,6 +61,15 @@ class InterstellarCluster(zones : List[Zone]) extends Actor {
sender ! Zone.Lattice.NoValidSpawnPoint(zone_number, None)
}
+ case msg @ Zone.Lattice.RequestSpecificSpawnPoint(zone_number, _, _) =>
+ recursiveFindWorldInCluster(zones.iterator, _.Number == zone_number) match {
+ case Some(zone) =>
+ zone.Actor forward msg
+
+ case None => //zone_number does not exist
+ sender ! Zone.Lattice.NoValidSpawnPoint(zone_number, None)
+ }
+
case _ =>
log.warn(s"InterstellarCluster received unknown message");
}
diff --git a/common/src/main/scala/net/psforever/objects/zones/Zone.scala b/common/src/main/scala/net/psforever/objects/zones/Zone.scala
index 6447cb78..b99c4376 100644
--- a/common/src/main/scala/net/psforever/objects/zones/Zone.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/Zone.scala
@@ -15,9 +15,8 @@ import net.psforever.objects.guid.source.LimitedNumberSource
import net.psforever.objects.inventory.Container
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
-import net.psforever.objects.serverobject.structures.{Amenity, Building}
+import net.psforever.objects.serverobject.structures.{Amenity, Building, WarpGate}
import net.psforever.objects.serverobject.terminals.ProximityUnit
-import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.serverobject.turret.FacilityTurret
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.Vector3
@@ -75,7 +74,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
private var buildings : PairMap[Int, Building] = PairMap.empty[Int, Building]
/** key - spawn zone id, value - buildings belonging to spawn zone */
- private var spawnGroups : Map[Building, List[SpawnTube]] = PairMap[Building, List[SpawnTube]]()
+ private var spawnGroups : Map[Building, List[SpawnPoint]] = PairMap[Building, List[SpawnPoint]]()
/** */
private var vehicleEvents : ActorRef = ActorRef.noSender
@@ -92,7 +91,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
*
* Execution of this operation should be fail-safe.
* The chances of failure should be mitigated or skipped.
- * An testing routine should be run after the fact on the results of the process.
+ * A testing routine should be run after the fact on the results of the process.
* @see `ZoneActor.ZoneSetupCheck`
* @param context a reference to an `ActorContext` necessary for `Props`
*/
@@ -188,7 +187,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
* @return synchronized reference to the globally unique identifier system
*/
def GUID(hub : NumberPoolHub) : Boolean = {
- if(actor == ActorRef.noSender && guid.Pools.map({case ((_, pool)) => pool.Count}).sum == 0) {
+ if(actor == ActorRef.noSender && guid.Pools.map({case (_, pool) => pool.Count}).sum == 0) {
import org.fusesource.jansi.Ansi.Color.RED
import org.fusesource.jansi.Ansi.ansi
println(ansi().fgBright(RED).a(s"""Caution: replacement of the number pool system for zone $Id; function is for testing purposes only""").reset())
@@ -312,8 +311,8 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
buildings.get(id)
}
- def BuildingByMapId(map_id : Int) : Building = {
- buildings.filter(x => x._2.MapId == map_id).head._2
+ def BuildingByMapId(map_id : Int) : Option[Building] = {
+ buildings.values.find(_.MapId == map_id)
}
private def BuildLocalObjects(implicit context : ActorContext, guid : NumberPoolHub) : Unit = {
@@ -324,7 +323,7 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
//guard against errors here, but don't worry about specifics; let ZoneActor.ZoneSetupCheck complain about problems
val other : ListBuffer[IdentifiableEntity] = new ListBuffer[IdentifiableEntity]()
//turret to weapon
- Map.TurretToWeapon.foreach({ case ((turret_guid, weapon_guid)) =>
+ Map.TurretToWeapon.foreach({ case (turret_guid, weapon_guid) =>
((GUID(turret_guid) match {
case Some(obj : FacilityTurret) =>
Some(obj)
@@ -385,27 +384,32 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
private def CreateSpawnGroups() : Unit = {
buildings.values
.filterNot { _.Position == Vector3.Zero }
- .map(building => { building -> building.Amenities.collect { case(obj : SpawnTube) => obj } })
- .filter( { case((_, spawns)) => spawns.nonEmpty })
+ .map(building => { building -> building.Amenities.collect { case obj : SpawnPoint => obj } })
+ .filter( { case(_, spawns) => spawns.nonEmpty })
+ .foreach { SpawnGroups }
+
+ buildings.values
+ .filterNot { _.Position == Vector3.Zero }
+ .collect { case building : WarpGate => building -> List(building.asInstanceOf[SpawnPoint]) }
.foreach { SpawnGroups }
}
- def SpawnGroups() : Map[Building, List[SpawnTube]] = spawnGroups
+ def SpawnGroups() : Map[Building, List[SpawnPoint]] = spawnGroups
- def SpawnGroups(building : Building) : List[SpawnTube] = SpawnGroups(building.MapId)
+ def SpawnGroups(building : Building) : List[SpawnPoint] = SpawnGroups(building.MapId)
- def SpawnGroups(buildingId : Int) : List[SpawnTube] = {
- spawnGroups.find({ case((building, _)) => building.MapId == buildingId }) match {
+ def SpawnGroups(buildingId : Int) : List[SpawnPoint] = {
+ spawnGroups.find({ case(building, _) => building.MapId == buildingId }) match {
case Some((_, list)) =>
list
case None =>
- List.empty[SpawnTube]
+ List.empty[SpawnPoint]
}
}
- def SpawnGroups(spawns : (Building, List[SpawnTube])) : Map[Building, List[SpawnTube]] = {
- val (building, tubes) = spawns
- val entry : Map[Building, List[SpawnTube]] = PairMap(building -> tubes)
+ def SpawnGroups(spawns : (Building, List[SpawnPoint])) : Map[Building, List[SpawnPoint]] = {
+ val (building, points) = spawns
+ val entry : Map[Building, List[SpawnPoint]] = PairMap(building -> points)
spawnGroups = spawnGroups ++ entry
entry
}
@@ -533,12 +537,14 @@ object Zone {
* @param spawn_group the category of spawn points the request wants searched
*/
final case class RequestSpawnPoint(zone_number : Int, player : Player, spawn_group : Int)
+
+ final case class RequestSpecificSpawnPoint(zone_number : Int, player : Player, target : PlanetSideGUID)
/**
* Message that returns a discovered spawn point to a request source.
* @param zone_id the zone's text identifier
- * @param spawn_tube the spawn point holding object
+ * @param spawn_point the spawn point holding object
*/
- final case class SpawnPoint(zone_id : String, spawn_tube : SpawnTube)
+ final case class SpawnPoint(zone_id : String, spawn_point : net.psforever.objects.SpawnPoint)
/**
* Message that informs a request source that a spawn point could not be discovered with the previous criteria.
* @param zone_number this zone's numeric identifier
diff --git a/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala b/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala
index 327eb6c2..a64183c2 100644
--- a/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala
@@ -4,11 +4,11 @@ package net.psforever.objects.zones
import java.util.concurrent.atomic.AtomicInteger
import akka.actor.Actor
-import net.psforever.objects.{GlobalDefinitions, PlanetSideGameObject, Tool}
-import net.psforever.objects.serverobject.structures.StructureType
+import net.psforever.objects.{GlobalDefinitions, PlanetSideGameObject, SpawnPoint, Tool}
+import net.psforever.objects.serverobject.structures.{StructureType, WarpGate}
import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.vehicles.UtilityType
-import net.psforever.types.{DriveState, Vector3}
+import net.psforever.types.{DriveState, PlanetSideEmpire, Vector3}
import org.log4s.Logger
/**
@@ -79,8 +79,8 @@ class ZoneActor(zone : Zone) extends Actor {
//ams
zone.Vehicles
.filter(veh =>
- veh.DeploymentState == DriveState.Deployed &&
veh.Definition == GlobalDefinitions.ams &&
+ veh.DeploymentState == DriveState.Deployed &&
veh.Faction == player.Faction
)
.sortBy(veh => Vector3.DistanceSquared(playerPosition, veh.Position.xy))
@@ -103,16 +103,23 @@ class ZoneActor(zone : Zone) extends Actor {
else if(spawn_group == 7) {
Set(StructureType.Facility, StructureType.Building)
}
+ else if(spawn_group == 12) {
+ Set(StructureType.WarpGate)
+ }
else {
Set.empty[StructureType.Value]
}
zone.SpawnGroups()
- .filter({ case ((building, _)) =>
- building.Faction == player.Faction &&
- buildingTypeSet.contains(building.BuildingType)
+ .filter({ case (building, _) =>
+ buildingTypeSet.contains(building.BuildingType) && (building match {
+ case wg : WarpGate =>
+ building.Faction == player.Faction || building.Faction == PlanetSideEmpire.NEUTRAL || wg.Broadcast
+ case _ =>
+ building.Faction == player.Faction
+ })
})
.toSeq
- .sortBy({ case ((building, _)) =>
+ .sortBy({ case (building, _) =>
Vector3.DistanceSquared(playerPosition, building.Position.xy)
})
.headOption match {
@@ -137,6 +144,53 @@ class ZoneActor(zone : Zone) extends Actor {
sender ! Zone.Lattice.NoValidSpawnPoint(zone_number, None)
}
+ case Zone.Lattice.RequestSpecificSpawnPoint(zone_number, player, target) =>
+ if(zone_number == zone.Number) {
+ //is our spawn point some other privileged vehicle?
+ zone.Vehicles.collectFirst({
+ case vehicle : SpawnPoint if vehicle.Faction == player.Faction && vehicle.GUID == target =>
+ Some(vehicle) //the vehicle itself is the spawn point
+ case vehicle if vehicle.Faction == player.Faction && vehicle.GUID == target =>
+ vehicle.Utilities.values.find {
+ util =>
+ util().isInstanceOf[SpawnPoint]
+ } match {
+ case None =>
+ None
+ case Some(util) =>
+ Some(util().asInstanceOf[SpawnTube]) //the vehicle's utility is the spawn point
+ }
+ }).orElse( {
+ //is our spawn point a building itself (like a warp gate)?
+ val friendlySpawnGroups = zone.SpawnGroups().filter {
+ case(building, _) =>
+ building match {
+ case wg : WarpGate =>
+ building.Faction == player.Faction || building.Faction == PlanetSideEmpire.NEUTRAL || wg.Broadcast
+ case _ =>
+ building.Faction == player.Faction
+ }
+ }
+ friendlySpawnGroups.collectFirst({
+ case (building, points) if building.MapId == target.guid && points.nonEmpty =>
+ scala.util.Random.shuffle(points).head
+ })
+ .orElse {
+ //is our spawn a conventional amenity?
+ friendlySpawnGroups.values.flatten.find { point => point.GUID == target}
+ }
+ }) match {
+ case Some(point : SpawnPoint) =>
+ sender ! Zone.Lattice.SpawnPoint(zone.Id, point)
+
+ case _ =>
+ sender ! Zone.Lattice.NoValidSpawnPoint(zone_number, Some(target.guid))
+ }
+ }
+ else { //wrong zone_number
+ sender ! Zone.Lattice.NoValidSpawnPoint(zone_number, None)
+ }
+
case msg =>
log.warn(s"Received unexpected message - $msg")
}
@@ -147,7 +201,7 @@ class ZoneActor(zone : Zone) extends Actor {
def guid(id : Int) = zone.GUID(id)
val slog = org.log4s.getLogger(s"zone/${zone.Id}/sanity")
val errors = new AtomicInteger(0)
- val validateObject : (Int, (PlanetSideGameObject)=>Boolean, String) => Boolean = ValidateObject(guid, slog, errors)
+ val validateObject : (Int, PlanetSideGameObject=>Boolean, String) => Boolean = ValidateObject(guid, slog, errors)
//check bases
map.ObjectToBuilding.values.toSet[Int].foreach(building_id =>
@@ -166,25 +220,25 @@ class ZoneActor(zone : Zone) extends Actor {
)
//check door to lock association
- map.DoorToLock.foreach({ case((door_guid, lock_guid)) =>
+ map.DoorToLock.foreach({ case(door_guid, lock_guid) =>
validateObject(door_guid, DoorCheck, "door")
validateObject(lock_guid, LockCheck, "IFF lock")
})
//check vehicle terminal to spawn pad association
- map.TerminalToSpawnPad.foreach({ case ((term_guid, pad_guid)) =>
+ map.TerminalToSpawnPad.foreach({ case (term_guid, pad_guid) =>
validateObject(term_guid, TerminalCheck, "vehicle terminal")
validateObject(pad_guid, VehicleSpawnPadCheck, "vehicle spawn pad")
})
//check implant terminal mech to implant terminal interface association
- map.TerminalToInterface.foreach({case ((mech_guid, interface_guid)) =>
+ map.TerminalToInterface.foreach({case (mech_guid, interface_guid) =>
validateObject(mech_guid, ImplantMechCheck, "implant terminal mech")
validateObject(interface_guid, TerminalCheck, "implant terminal interface")
})
//check manned turret to weapon association
- map.TurretToWeapon.foreach({ case ((turret_guid, weapon_guid)) =>
+ map.TurretToWeapon.foreach({ case (turret_guid, weapon_guid) =>
validateObject(turret_guid, FacilityTurretCheck, "facility turret mount")
if(validateObject(weapon_guid, WeaponCheck, "facility turret weapon")) {
if(guid(weapon_guid).get.asInstanceOf[Tool].AmmoSlots.count(!_.Box.HasGUID) > 0) {
@@ -213,8 +267,8 @@ object ZoneActor {
* @return `true` if the object was discovered and validates correctly;
* `false` if the object failed any tests
*/
- def ValidateObject(guid : (Int)=>Option[PlanetSideGameObject], elog : Logger, errorCounter : AtomicInteger)
- (object_guid : Int, test : (PlanetSideGameObject)=>Boolean, description : String) : Boolean = {
+ def ValidateObject(guid : Int=>Option[PlanetSideGameObject], elog : Logger, errorCounter : AtomicInteger)
+ (object_guid : Int, test : PlanetSideGameObject=>Boolean, description : String) : Boolean = {
try {
if(!test(guid(object_guid).get)) {
elog.error(s"expected id $object_guid to be a $description, but it was not")
diff --git a/common/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala b/common/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala
index bdb2c2c3..98764820 100644
--- a/common/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala
@@ -42,6 +42,7 @@ class ZoneVehicleActor(zone : Zone, vehicleList : ListBuffer[Vehicle]) extends A
}
else {
vehicleList += vehicle
+ vehicle.Continent = zone.Id
vehicle.Actor = context.actorOf(Props(classOf[VehicleControl], vehicle), s"${vehicle.Definition.Name}_${vehicle.GUID.guid}")
}
diff --git a/common/src/main/scala/net/psforever/packet/game/BindPlayerMessage.scala b/common/src/main/scala/net/psforever/packet/game/BindPlayerMessage.scala
index f6898576..383f3cf8 100644
--- a/common/src/main/scala/net/psforever/packet/game/BindPlayerMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/BindPlayerMessage.scala
@@ -54,10 +54,9 @@ object BindStatus extends Enumeration(1) {
* Find other bind descriptors.
* @param action the purpose of the packet
* @param bind_desc a text description of the respawn binding point
- * @param unk1 na;
- * usually set `true` if there is more data in the packet ...
+ * @param display_icon show the selection icon on the redeployment map
* @param logging true, to report on bind point change visible in the events window;
- * false, to render spawn change silent;
+ * false, to render spawn change silently;
* some first time notifications will always display regardless of this flag
* @param spawn_group the kind of spawn request that will be made;
* affects the type of icon displayed;
@@ -71,7 +70,7 @@ object BindStatus extends Enumeration(1) {
*/
final case class BindPlayerMessage(action : BindStatus.Value,
bind_desc : String,
- unk1 : Boolean,
+ display_icon : Boolean,
logging : Boolean,
spawn_group : SpawnGroup.Value,
zone_number : Long,
@@ -94,7 +93,7 @@ object BindPlayerMessage extends Marshallable[BindPlayerMessage] {
implicit val codec : Codec[BindPlayerMessage] = (
("action" | BindStatus.codec) ::
("bind_desc" | PacketHelpers.encodedString) ::
- ("unk1" | bool) ::
+ ("display_icon" | bool) ::
("logging" | bool) ::
("spawn_group" | spawnGroupCodec) ::
("zone_number" | uint32L) ::
diff --git a/common/src/main/scala/net/psforever/packet/game/CargoMountPointStatusMessage.scala b/common/src/main/scala/net/psforever/packet/game/CargoMountPointStatusMessage.scala
index fa250ead..1b813c4e 100644
--- a/common/src/main/scala/net/psforever/packet/game/CargoMountPointStatusMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/CargoMountPointStatusMessage.scala
@@ -7,14 +7,23 @@ import scodec.Codec
import scodec.codecs._
/**
- *
- * @param cargo_vehicle_guid Cargo vehicle GUID (galaxy / lodestar)
- * @param requesting_vehicle Seems to be vehicle that requested mounting (0 after mount)
- * @param mounted_vehicle Seems to be vehicle that requested mounting after mount (0 before mount)
- * @param dismounted_vehicle Seems to be vehicle that was mounted after disembarking (0 before embark or reset to 0 when MountVehicleCargoMsg received)
- * @param slot Mount point for cargo bay 1 = lodestar, 15 = galaxy
- * @param mount_status Mount status? 0 = None, 1 = Mount/Dismount in progress, 3 = Mounted
- * @param orientation 0 = normal, 1 = sideways (e.g. router in lodestar)
+ * na
+ * @see `CargoStatus`
+ * @see `MountVehicleCargoMsg`
+ * @param cargo_vehicle_guid always the carrier vehicle
+ * @param requesting_vehicle cargo vehicle that requested mounting during the mounting process;
+ * blank when the process is complete
+ * @param mounted_vehicle cargo vehicle that requested mounting after the mounting process is complete;
+ * blank before the process is complete
+ * @param dismounted_vehicle cargo vehicle that was mounted after disembarking;
+ * blank before disembark
+ * blank before mounting request, when packet `MountVehicleCargoMsg` is received
+ * @param slot cargo hold mount position;
+ * common values are 1 for the `lodestar` and 15 for the `dropship`
+ * @param mount_status cargo mount status
+ * @param orientation direction the cargo vehicle faces when stowed in the carrier cargo bay;
+ * 0 is "normal," front facing forward;
+ * 1 is "sideways," front facing the side of the carrier vehicle, e.g. `router`
*/
final case class CargoMountPointStatusMessage(cargo_vehicle_guid : PlanetSideGUID,
requesting_vehicle: PlanetSideGUID,
diff --git a/common/src/main/scala/net/psforever/packet/game/VehicleStateMessage.scala b/common/src/main/scala/net/psforever/packet/game/VehicleStateMessage.scala
index b0282d5d..bd6eac63 100644
--- a/common/src/main/scala/net/psforever/packet/game/VehicleStateMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/VehicleStateMessage.scala
@@ -14,13 +14,17 @@ import scodec.codecs._
* @param pos the xyz-coordinate location in the world
* @param ang the orientation of the vehicle
* @param vel optional movement data
- * @param unk2 na
+ * @param flying flight information, valid only for a vehicle that can fly when in flight;
+ * `Some(7)`, when in a flying state (vertical thrust unnecessary to unlock movement)
+ * `None`, when landed and for all vehicles that do not fly
* @param unk3 na
* @param unk4 na
- * @param wheel_direction for ground vehicles, whether the wheels are being turned;
+ * @param wheel_direction for ground vehicles, whether and how much the wheels are being turned;
* 15 for straight;
* 0 for hard right;
- * 30 for hard left
+ * 30 for hard left;
+ * values in between are possible;
+ * vehicles that hover also influence this field as expected
* @param unk5 na - Possibly a flag to indicate the vehicle is attached to something else e.g. is in a galaxy/lodestar cargo bay
* @param unk6 na
* @see `PlacementData`
@@ -30,7 +34,7 @@ final case class VehicleStateMessage(vehicle_guid : PlanetSideGUID,
pos : Vector3,
ang : Vector3,
vel : Option[Vector3],
- unk2 : Option[Int],
+ flying : Option[Int],
unk3 : Int,
unk4 : Int,
wheel_direction : Int,
@@ -61,7 +65,7 @@ object VehicleStateMessage extends Marshallable[VehicleStateMessage] {
("pos" | Vector3.codec_pos) ::
("ang" | codec_orient) ::
optional(bool, "vel" | Vector3.codec_vel) ::
- optional(bool, "unk2" | uintL(5)) ::
+ optional(bool, "flying" | uintL(5)) ::
("unk3" | uintL(7)) ::
("unk4" | uint4L) ::
("wheel_direction" | uintL(5)) ::
diff --git a/common/src/main/scala/net/psforever/packet/game/WarpgateRequest.scala b/common/src/main/scala/net/psforever/packet/game/WarpgateRequest.scala
index b3ec98f7..bc8a0b94 100644
--- a/common/src/main/scala/net/psforever/packet/game/WarpgateRequest.scala
+++ b/common/src/main/scala/net/psforever/packet/game/WarpgateRequest.scala
@@ -15,21 +15,18 @@ import scodec.codecs._
* The process of gate transportation should not start until the server responds to this packet.
*
* Exploration 1:
- * Does this packet apply to geowarp transport as well?
- *
- * Exploration 2:
- * Those last two fields that are usually blanked do something?
- * @param continent_guid the continent (zone)
- * @param building_guid the warp gate
- * @param dest_building_guid the destination warp gate
- * @param dest_continent_guid the destination continent (zone)
+ * Does this packet apply to geowarp transport as well?
+ * @param from_zone the continent (zone)
+ * @param from_gate_guid the warp gate
+ * @param to_gate_mapid the destination warp gate
+ * @param to_zone the destination continent (zone)
* @param unk1 na; always zero?
* @param unk2 na; always zero?
*/
-final case class WarpgateRequest(continent_guid : PlanetSideGUID,
- building_guid : PlanetSideGUID,
- dest_building_guid : PlanetSideGUID,
- dest_continent_guid : PlanetSideGUID,
+final case class WarpgateRequest(from_zone : PlanetSideGUID,
+ from_gate_guid : PlanetSideGUID,
+ to_gate_mapid : PlanetSideGUID,
+ to_zone : PlanetSideGUID,
unk1 : Int,
unk2 : Int)
extends PlanetSideGamePacket {
@@ -40,10 +37,10 @@ final case class WarpgateRequest(continent_guid : PlanetSideGUID,
object WarpgateRequest extends Marshallable[WarpgateRequest] {
implicit val codec : Codec[WarpgateRequest] = (
- ("continent_guid" | PlanetSideGUID.codec) ::
- ("building_guid" | PlanetSideGUID.codec) ::
- ("dest_building_guid" | PlanetSideGUID.codec) ::
- ("dest_continent_guid" | PlanetSideGUID.codec) ::
+ ("from_zone" | PlanetSideGUID.codec) ::
+ ("from_gate_guid" | PlanetSideGUID.codec) ::
+ ("to_gate_mapid" | PlanetSideGUID.codec) ::
+ ("to_zone" | PlanetSideGUID.codec) ::
("unk1" | uint8L) ::
("unk2" | uint8L)
).as[WarpgateRequest]
diff --git a/common/src/main/scala/net/psforever/types/SpawnGroup.scala b/common/src/main/scala/net/psforever/types/SpawnGroup.scala
index 806a209c..5510bfa4 100644
--- a/common/src/main/scala/net/psforever/types/SpawnGroup.scala
+++ b/common/src/main/scala/net/psforever/types/SpawnGroup.scala
@@ -17,6 +17,7 @@ package net.psforever.types
* The icons produced by the normal and the bound tower and facility groups are not detailed.
* The ones that are not designated as "bound" also do not display icons when manually set.
* The AMS spawn group icons have an overhead AMS glyph and are smaller in radius, identical otherwise.
+ * @see `BindPlayerMessage`
*/
object SpawnGroup extends Enumeration {
type Type = Value
diff --git a/common/src/main/scala/net/psforever/types/Vector3.scala b/common/src/main/scala/net/psforever/types/Vector3.scala
index 83c740eb..01fc5b8e 100644
--- a/common/src/main/scala/net/psforever/types/Vector3.scala
+++ b/common/src/main/scala/net/psforever/types/Vector3.scala
@@ -108,11 +108,13 @@ object Vector3 {
).as[Vector3]
/**
- * A common vector object that only concerns itself with rotation around the world-up axis.
- * @param yaw the angle of rotation
+ * A common vector object that only concerns itself
+ * with rotation around the world-up axis
+ * or the "world up" coordinate direction.
+ * @param value the third coordinate
* @return a `Vector3` object
*/
- def z(yaw : Float) : Vector3 = Vector3(0, 0, yaw)
+ def z(value : Float) : Vector3 = Vector3(0, 0, value)
/**
* Calculate the actual distance between two points.
diff --git a/common/src/main/scala/services/local/support/HackCapturerActor.scala b/common/src/main/scala/services/local/support/HackCaptureActor.scala
similarity index 88%
rename from common/src/main/scala/services/local/support/HackCapturerActor.scala
rename to common/src/main/scala/services/local/support/HackCaptureActor.scala
index bcedffa7..f0174a15 100644
--- a/common/src/main/scala/services/local/support/HackCapturerActor.scala
+++ b/common/src/main/scala/services/local/support/HackCaptureActor.scala
@@ -23,9 +23,15 @@ class HackCaptureActor extends Actor {
def receive : Receive = {
case HackCaptureActor.ObjectIsHacked(target, zone, unk1, unk2, duration, time) =>
log.trace(s"${target.GUID} is hacked.")
+ target.HackedBy match {
+ case Some(hackInfo) =>
+ target.HackedBy = hackInfo.Duration(duration.toNanos)
+ case None =>
+ log.error(s"Initial $target hack information is missing")
+ }
- hackedObjects.filter(x => x.target == target).headOption match {
- case Some(x) =>
+ hackedObjects.find(_.target == target) match {
+ case Some(_) =>
log.trace(s"${target.GUID} was already hacked - removing it from the hacked objects list before re-adding it.")
hackedObjects = hackedObjects.filterNot(x => x.target == target)
log.warn(s"len: ${hackedObjects.length}")
@@ -49,7 +55,7 @@ class HackCaptureActor extends Actor {
unhackObjects.foreach(entry => {
log.trace(s"Capture terminal hack timeout reached for terminal ${entry.target.GUID}")
- val hackedByFaction = entry.target.HackedBy.get._1.Faction
+ val hackedByFaction = entry.target.HackedBy.get.hackerFaction
entry.target.Actor ! CommonMessages.ClearHack()
context.parent ! HackCaptureActor.HackTimeoutReached(entry.target.GUID, entry.zone.Id, entry.unk1, entry.unk2, hackedByFaction) //call up to the main event system
@@ -58,7 +64,7 @@ class HackCaptureActor extends Actor {
// If there's hacked objects left in the list restart the timer with the shortest hack time left
RestartTimer()
- case HackCaptureActor.ClearHack(target, zone) =>
+ case HackCaptureActor.ClearHack(target, _) =>
hackedObjects = hackedObjects.filterNot(x => x.target == target)
target.Owner.Actor ! Building.SendMapUpdate(all_clients = true)
@@ -66,19 +72,19 @@ class HackCaptureActor extends Actor {
RestartTimer()
case HackCaptureActor.GetHackTimeRemainingNanos(capture_console_guid) =>
- hackedObjects.filter(x => x.target.GUID == capture_console_guid).headOption match {
+ hackedObjects.find(_.target.GUID == capture_console_guid) match {
case Some(obj: HackCaptureActor.HackEntry) =>
val time_left: Long = obj.duration.toNanos - (System.nanoTime - obj.hack_timestamp)
sender ! time_left
case _ =>
- log.warn(s"Couldn't find capture terminal guid ${capture_console_guid} in hackedObjects list")
+ log.warn(s"Couldn't find capture terminal guid $capture_console_guid in hackedObjects list")
sender ! 0L
}
case _ => ;
}
private def RestartTimer(): Unit = {
- if(hackedObjects.length != 0) {
+ if(hackedObjects.nonEmpty) {
val now = System.nanoTime()
def minTimeLeft(entry1: HackCaptureActor.HackEntry, entry2: HackCaptureActor.HackEntry): HackCaptureActor.HackEntry = {
val entry1TimeLeft = entry1.duration.toNanos - (now - entry1.hack_timestamp)
diff --git a/common/src/main/scala/services/vehicle/VehicleAction.scala b/common/src/main/scala/services/vehicle/VehicleAction.scala
index c47b332f..e26fb0fb 100644
--- a/common/src/main/scala/services/vehicle/VehicleAction.scala
+++ b/common/src/main/scala/services/vehicle/VehicleAction.scala
@@ -32,4 +32,9 @@ object VehicleAction {
final case class VehicleState(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Action
final case class SendResponse(player_guid: PlanetSideGUID, msg : PlanetSideGamePacket) extends Action
final case class UpdateAmsSpawnPoint(zone : Zone) extends Action
+
+ final case class TransferPassengerChannel(player_guid : PlanetSideGUID, temp_channel : String, new_channel : String, vehicle : Vehicle) extends Action
+ final case class TransferPassenger(player_guid : PlanetSideGUID, temp_channel : String, vehicle : Vehicle, vehicle_to_delete : PlanetSideGUID) extends Action
+
+ final case class KickCargo(player_guid : PlanetSideGUID, cargo : Vehicle, speed : Int) extends Action
}
diff --git a/common/src/main/scala/services/vehicle/VehicleResponse.scala b/common/src/main/scala/services/vehicle/VehicleResponse.scala
index 07ba5901..1442205e 100644
--- a/common/src/main/scala/services/vehicle/VehicleResponse.scala
+++ b/common/src/main/scala/services/vehicle/VehicleResponse.scala
@@ -36,4 +36,9 @@ object VehicleResponse {
final case class VehicleState(vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Response
final case class SendResponse(msg: PlanetSideGamePacket) extends Response
final case class UpdateAmsSpawnPoint(list : List[SpawnTube]) extends Response
+
+ final case class TransferPassengerChannel(old_channel : String, temp_channel : String, vehicle : Vehicle) extends Response
+ final case class TransferPassenger(temp_channel : String, vehicle : Vehicle, vehicle_to_delete : PlanetSideGUID) extends Response
+
+ final case class KickCargo(cargo : Vehicle, speed : Int) extends Response
}
diff --git a/common/src/main/scala/services/vehicle/VehicleService.scala b/common/src/main/scala/services/vehicle/VehicleService.scala
index db49954e..7098454f 100644
--- a/common/src/main/scala/services/vehicle/VehicleService.scala
+++ b/common/src/main/scala/services/vehicle/VehicleService.scala
@@ -130,6 +130,20 @@ class VehicleService extends Actor {
//unlike other messages, just return to sender, don't publish
case VehicleAction.UpdateAmsSpawnPoint(zone : Zone) =>
sender ! VehicleServiceResponse(s"/$forChannel/Vehicle", Service.defaultPlayerGUID, VehicleResponse.UpdateAmsSpawnPoint(AmsSpawnPoints(zone)))
+
+ case VehicleAction.TransferPassengerChannel(player_guid, old_channel, temp_channel, vehicle) =>
+ VehicleEvents.publish(
+ VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.TransferPassengerChannel(old_channel, temp_channel, vehicle))
+ )
+ case VehicleAction.TransferPassenger(player_guid, temp_channel, vehicle, vehicle_to_delete) =>
+ VehicleEvents.publish(
+ VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.TransferPassenger(temp_channel, vehicle, vehicle_to_delete))
+ )
+
+ case VehicleAction.KickCargo(player_guid, cargo, speed) =>
+ VehicleEvents.publish(
+ VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.KickCargo(cargo, speed))
+ )
case _ => ;
}
diff --git a/common/src/test/scala/objects/BuildingTest.scala b/common/src/test/scala/objects/BuildingTest.scala
index 70192fcb..1d6f0aaf 100644
--- a/common/src/test/scala/objects/BuildingTest.scala
+++ b/common/src/test/scala/objects/BuildingTest.scala
@@ -104,7 +104,7 @@ class BuildingTest extends Specification {
class WarpGateTest extends Specification {
"WarpGate" should {
"construct" in {
- val bldg = WarpGate(0, 10, Zone.Nowhere)
+ val bldg = WarpGate(0, 10, Zone.Nowhere, GlobalDefinitions.warpgate)
bldg.MapId mustEqual 10
bldg.Actor mustEqual ActorRef.noSender
bldg.Amenities mustEqual Nil
diff --git a/common/src/test/scala/objects/DoorTest.scala b/common/src/test/scala/objects/DoorTest.scala
index 20e1a4d6..2c504b90 100644
--- a/common/src/test/scala/objects/DoorTest.scala
+++ b/common/src/test/scala/objects/DoorTest.scala
@@ -101,7 +101,7 @@ object DoorControlTest {
def SetUpAgents(faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, Door) = {
val door = Door(GlobalDefinitions.door)
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
- door.Owner = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building)
+ door.Owner = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
door.Owner.Faction = faction
(Player(Avatar("test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), door)
}
diff --git a/common/src/test/scala/objects/FactionAffinityTest.scala b/common/src/test/scala/objects/FactionAffinityTest.scala
index 3ce72e08..b36ca40f 100644
--- a/common/src/test/scala/objects/FactionAffinityTest.scala
+++ b/common/src/test/scala/objects/FactionAffinityTest.scala
@@ -43,7 +43,7 @@ class FactionAffinityTest extends Specification {
"inherits affinity from owner 2" in {
val obj = new Door(GlobalDefinitions.door)
- val bldg = new Building(building_guid = 0, map_id = 1, Zone.Nowhere, StructureType.Building)
+ val bldg = new Building(building_guid = 0, map_id = 1, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
obj.Owner = bldg
obj.Faction mustEqual PlanetSideEmpire.NEUTRAL
diff --git a/common/src/test/scala/objects/IFFLockTest.scala b/common/src/test/scala/objects/IFFLockTest.scala
index 737d1e17..ab94362c 100644
--- a/common/src/test/scala/objects/IFFLockTest.scala
+++ b/common/src/test/scala/objects/IFFLockTest.scala
@@ -89,7 +89,7 @@ object IFFLockControlTest {
def SetUpAgents(faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, IFFLock) = {
val lock = IFFLock(GlobalDefinitions.lock_external)
lock.Actor = system.actorOf(Props(classOf[IFFLockControl], lock), "lock-control")
- lock.Owner = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building)
+ lock.Owner = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
lock.Owner.Faction = faction
(Player(Avatar("test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), lock)
}
diff --git a/common/src/test/scala/objects/ResourceSiloTest.scala b/common/src/test/scala/objects/ResourceSiloTest.scala
index 3ac197f2..ab200466 100644
--- a/common/src/test/scala/objects/ResourceSiloTest.scala
+++ b/common/src/test/scala/objects/ResourceSiloTest.scala
@@ -14,7 +14,7 @@ import net.psforever.packet.game.{PlanetSideGUID, UseItemMessage}
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, Vector3}
import org.specs2.mutable.Specification
import services.ServiceManager
-import services.avatar.{AvatarAction, AvatarService, AvatarServiceMessage}
+import services.avatar.{AvatarAction, AvatarServiceMessage}
import scala.concurrent.duration._
@@ -111,7 +111,7 @@ class ResourceSiloControlNtuWarningTest extends ActorTest {
obj.GUID = PlanetSideGUID(1)
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
obj.Actor ! "startup"
- obj.Owner = new Building(building_guid = 6, map_id = 0, Zone.Nowhere, StructureType.Building)
+ obj.Owner = new Building(building_guid = 6, map_id = 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
"Resource silo" should {
"announce high ntu" in {
@@ -144,7 +144,7 @@ class ResourceSiloControlUpdate1Test extends ActorTest {
obj.GUID = PlanetSideGUID(1)
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
obj.Actor ! "startup"
- val bldg = new Building(building_guid = 6, map_id = 0, Zone.Nowhere, StructureType.Building)
+ val bldg = new Building(building_guid = 6, map_id = 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
val probe2 = TestProbe()
bldg.Actor = system.actorOf(Props(classOf[ResourceSiloTest.ProbedBuildingControl], probe2), "test-bldg")
obj.Owner = bldg
@@ -211,7 +211,7 @@ class ResourceSiloControlUpdate2Test extends ActorTest {
obj.GUID = PlanetSideGUID(1)
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
obj.Actor ! "startup"
- val bldg = new Building(building_guid = 6, map_id = 0, Zone.Nowhere, StructureType.Building)
+ val bldg = new Building(building_guid = 6, map_id = 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
val probe2 = TestProbe()
bldg.Actor = system.actorOf(Props(classOf[ResourceSiloTest.ProbedBuildingControl], probe2), "test-bldg")
obj.Owner = bldg
@@ -270,7 +270,7 @@ class ResourceSiloControlNoUpdateTest extends ActorTest {
obj.GUID = PlanetSideGUID(1)
obj.Actor = system.actorOf(Props(classOf[ResourceSiloControl], obj), "test-silo")
obj.Actor ! "startup"
- val bldg = new Building(building_guid = 6, map_id = 6, Zone.Nowhere, StructureType.Building)
+ val bldg = new Building(building_guid = 6, map_id = 6, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
val probe2 = TestProbe()
bldg.Actor = system.actorOf(Props(classOf[ResourceSiloTest.ProbedBuildingControl], probe2), "test-bldg")
obj.Owner = bldg
diff --git a/common/src/test/scala/objects/SpawnTubeTest.scala b/common/src/test/scala/objects/SpawnTubeTest.scala
index 564f29dd..96b37921 100644
--- a/common/src/test/scala/objects/SpawnTubeTest.scala
+++ b/common/src/test/scala/objects/SpawnTubeTest.scala
@@ -9,34 +9,9 @@ import org.specs2.mutable.Specification
class SpawnTubeTest extends Specification {
"SpawnTubeDefinition" should {
- "define (ams_respawn_tube)" in {
+ "define" in {
val obj = new SpawnTubeDefinition(49)
obj.ObjectId mustEqual 49
- obj.Name mustEqual "ams_respawn_tube"
- }
-
- "define (respawn_tube)" in {
- val obj = new SpawnTubeDefinition(732)
- obj.ObjectId mustEqual 732
- obj.Name mustEqual "respawn_tube"
- }
-
- "define (respawn_tube_tower)" in {
- val obj = new SpawnTubeDefinition(733)
- obj.ObjectId mustEqual 733
- obj.Name mustEqual "respawn_tube_tower"
- }
-
- "define (invalid)" in {
- var id : Int = (math.random * Int.MaxValue).toInt
- if(id == 49 || id == 733) {
- id += 1
- }
- else if(id == 732) {
- id += 2
- }
-
- new SpawnTubeDefinition(id) must throwA[IllegalArgumentException]
}
}
diff --git a/common/src/test/scala/objects/VehicleSpawnPadTest.scala b/common/src/test/scala/objects/VehicleSpawnPadTest.scala
index 2511210c..8ca3daa1 100644
--- a/common/src/test/scala/objects/VehicleSpawnPadTest.scala
+++ b/common/src/test/scala/objects/VehicleSpawnPadTest.scala
@@ -339,7 +339,7 @@ object VehicleSpawnPadControlTest {
val pad = VehicleSpawnPad(GlobalDefinitions.mb_pad_creation)
pad.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], pad), s"test-pad-${System.nanoTime()}")
- pad.Owner = new Building(building_guid = 0, map_id = 0, zone, StructureType.Building)
+ pad.Owner = new Building(building_guid = 0, map_id = 0, zone, StructureType.Building, GlobalDefinitions.building)
pad.Owner.Faction = faction
val player = Player(Avatar("test", faction, CharacterGender.Male, 0, CharacterVoice.Mute))
player.GUID = PlanetSideGUID(10)
diff --git a/common/src/test/scala/objects/ZoneTest.scala b/common/src/test/scala/objects/ZoneTest.scala
index 53a29510..625b5909 100644
--- a/common/src/test/scala/objects/ZoneTest.scala
+++ b/common/src/test/scala/objects/ZoneTest.scala
@@ -243,14 +243,14 @@ class ZoneActorTest extends ActorTest {
val reply1 = receiveOne(Duration.create(200, "ms"))
assert(reply1.isInstanceOf[Zone.Lattice.SpawnPoint])
assert(reply1.asInstanceOf[Zone.Lattice.SpawnPoint].zone_id == "test")
- assert(reply1.asInstanceOf[Zone.Lattice.SpawnPoint].spawn_tube.Owner == bldg1)
+ assert(reply1.asInstanceOf[Zone.Lattice.SpawnPoint].spawn_point.Owner == bldg1)
player.Position = Vector3(3,3,3) //closer to bldg3
zone.Actor ! Zone.Lattice.RequestSpawnPoint(1, player, 7)
val reply3 = receiveOne(Duration.create(200, "ms"))
assert(reply3.isInstanceOf[Zone.Lattice.SpawnPoint])
assert(reply3.asInstanceOf[Zone.Lattice.SpawnPoint].zone_id == "test")
- assert(reply3.asInstanceOf[Zone.Lattice.SpawnPoint].spawn_tube.Owner == bldg3)
+ assert(reply3.asInstanceOf[Zone.Lattice.SpawnPoint].spawn_point.Owner == bldg3)
}
"will report if no spawn points have been found in a zone" in {
diff --git a/common/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala b/common/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
index a60b9063..522be435 100644
--- a/common/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
+++ b/common/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
@@ -161,7 +161,7 @@ object ImplantTerminalMechTest {
val terminal = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech)
terminal.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], terminal), "mech")
- terminal.Owner = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building)
+ terminal.Owner = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
terminal.Owner.Faction = faction
terminal.GUID = PlanetSideGUID(1)
(Player(Avatar("test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), terminal)
diff --git a/common/src/test/scala/objects/terminal/OrderTerminalTest.scala b/common/src/test/scala/objects/terminal/OrderTerminalTest.scala
index e67c4505..34b21670 100644
--- a/common/src/test/scala/objects/terminal/OrderTerminalTest.scala
+++ b/common/src/test/scala/objects/terminal/OrderTerminalTest.scala
@@ -13,7 +13,7 @@ class OrderTerminalTest extends Specification {
val avatar = Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)
val player = Player(avatar)
- val building = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building)
+ val building = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
building.Faction = PlanetSideEmpire.TR
val infantryTerminal = Terminal(GlobalDefinitions.order_terminal)
infantryTerminal.Owner = building
diff --git a/common/src/test/scala/objects/terminal/ProximityTest.scala b/common/src/test/scala/objects/terminal/ProximityTest.scala
index 60a1e5b5..cd796176 100644
--- a/common/src/test/scala/objects/terminal/ProximityTest.scala
+++ b/common/src/test/scala/objects/terminal/ProximityTest.scala
@@ -109,7 +109,7 @@ class ProximityTerminalControlStartTest extends ActorTest {
AddPool("dynamic", 1 to 10)
}
}
- new Building(building_guid = 0, map_id = 0, zone, StructureType.Facility) {
+ new Building(building_guid = 0, map_id = 0, zone, StructureType.Facility, GlobalDefinitions.building) {
Amenities = terminal
Faction = PlanetSideEmpire.VS
}
@@ -153,7 +153,7 @@ class ProximityTerminalControlTwoUsersTest extends ActorTest {
AddPool("dynamic", 1 to 10)
}
}
- new Building(building_guid = 0, map_id = 0, zone, StructureType.Facility) {
+ new Building(building_guid = 0, map_id = 0, zone, StructureType.Facility, GlobalDefinitions.building) {
Amenities = terminal
Faction = PlanetSideEmpire.VS
}
@@ -205,7 +205,7 @@ class ProximityTerminalControlStopTest extends ActorTest {
AddPool("dynamic", 1 to 10)
}
}
- new Building(building_guid = 0, map_id = 0, zone, StructureType.Facility) {
+ new Building(building_guid = 0, map_id = 0, zone, StructureType.Facility, GlobalDefinitions.building) {
Amenities = terminal
Faction = PlanetSideEmpire.VS
}
@@ -256,7 +256,7 @@ class ProximityTerminalControlNotStopTest extends ActorTest {
AddPool("dynamic", 1 to 10)
}
}
- new Building(building_guid = 0, map_id = 0, zone, StructureType.Facility) {
+ new Building(building_guid = 0, map_id = 0, zone, StructureType.Facility, GlobalDefinitions.building) {
Amenities = terminal
Faction = PlanetSideEmpire.VS
}
diff --git a/common/src/test/scala/objects/terminal/TerminalControlTest.scala b/common/src/test/scala/objects/terminal/TerminalControlTest.scala
index fbd767da..9f953b99 100644
--- a/common/src/test/scala/objects/terminal/TerminalControlTest.scala
+++ b/common/src/test/scala/objects/terminal/TerminalControlTest.scala
@@ -121,7 +121,7 @@ object TerminalControlTest {
def SetUpAgents(tdef : TerminalDefinition, faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, Terminal) = {
val terminal = Terminal(tdef)
terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-term")
- terminal.Owner = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building)
+ terminal.Owner = new Building(building_guid = 0, map_id = 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building)
terminal.Owner.Faction = faction
(Player(Avatar("test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), terminal)
}
diff --git a/common/src/test/scala/service/VehicleServiceTest.scala b/common/src/test/scala/service/VehicleServiceTest.scala
index aaa96a9f..5242c49c 100644
--- a/common/src/test/scala/service/VehicleServiceTest.scala
+++ b/common/src/test/scala/service/VehicleServiceTest.scala
@@ -253,6 +253,33 @@ class VehicleStateTest extends ActorTest {
}
}
+class TransferPassengerChannelTest extends ActorTest {
+ ServiceManager.boot(system)
+
+ "VehicleService" should {
+ "pass TransferPassengerChannel" in {
+ val service = system.actorOf(Props[VehicleService], "v-service")
+ val fury = Vehicle(GlobalDefinitions.fury)
+ service ! Service.Join("test")
+ service ! VehicleServiceMessage("test", VehicleAction.TransferPassengerChannel(PlanetSideGUID(10), "old_channel", "new_channel", fury))
+ expectMsg(VehicleServiceResponse("/test/Vehicle", PlanetSideGUID(10), VehicleResponse.TransferPassengerChannel("old_channel", "new_channel", fury)))
+ }
+ }
+}
+
+class TransferPassengerTest extends ActorTest {
+ ServiceManager.boot(system)
+ "VehicleService" should {
+ "pass TransferPassenger" in {
+ val fury = Vehicle(GlobalDefinitions.fury)
+ val service = system.actorOf(Props[VehicleService], "v-service")
+ service ! Service.Join("test")
+ service ! VehicleServiceMessage("test", VehicleAction.TransferPassenger(PlanetSideGUID(10), "temp_channel", fury, PlanetSideGUID(11)))
+ expectMsg(VehicleServiceResponse("/test/Vehicle", PlanetSideGUID(10), VehicleResponse.TransferPassenger("temp_channel", fury, PlanetSideGUID(11))))
+ }
+ }
+}
+
object VehicleServiceTest {
//decoy
}
diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala
index 2b701344..dee89edb 100644
--- a/pslogin/src/main/scala/WorldSessionActor.scala
+++ b/pslogin/src/main/scala/WorldSessionActor.scala
@@ -98,9 +98,23 @@ class WorldSessionActor extends Actor with MDCContextAware {
val projectiles : Array[Option[Projectile]] = Array.fill[Option[Projectile]](Projectile.RangeUID - Projectile.BaseUID)(None)
var drawDeloyableIcon : PlanetSideGameObject with Deployable => Unit = RedrawDeployableIcons
var recentTeleportAttempt : Long = 0
- var lastTerminalOrderFulfillment : Boolean = true
+ var lastTerminalOrderFulfillment : Boolean = true /**
+ * used during zone transfers to maintain reference to seated vehicle (which does not yet exist in the new zone)
+ * used during intrazone gate transfers, but not in a way distinct from prior zone transfer procedures
+ * should only be set during the transient period when moving between one spawn point and the next
+ * leaving set prior to a subsequent transfers may cause unstable vehicle associations, with memory leak potential
+ */
+ var interstellarFerry : Option[Vehicle] = None
+ /**
+ * used during zone transfers for cleanup to refer to the vehicle that instigated a transfer
+ * "top level" is the carrier in a carrier/ferried association or a projected carrier/(ferried carrier)/ferried association
+ * inherited from parent (carrier) to child (ferried) through the `TransferPassenger` message
+ * the old-zone unique identifier for the carrier
+ * no harm should come from leaving the field set to an old unique identifier value after the transfer period
+ */
+ var interstellarFerryTopLevelGUID : Option[PlanetSideGUID] = None
- var amsSpawnPoint : Option[SpawnTube] = None
+ var amsSpawnPoints : List[SpawnPoint] = Nil
var clientKeepAlive : Cancellable = DefaultCancellable.obj
var progressBarUpdate : Cancellable = DefaultCancellable.obj
var reviveTimer : Cancellable = DefaultCancellable.obj
@@ -159,6 +173,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
//player disconnected while waiting for a revive
//similar to handling ReleaseAvatarRequestMessage
player.Release
+ DisownVehicle()
player.VehicleSeated match {
case None =>
FriskCorpse(player) //TODO eliminate dead letters
@@ -410,11 +425,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
})
sendResponse(ChatMsg(ChatMessageType.CMT_OPEN, true, "", msg, None))
- case CheckCargoDismount(vehicle_guid, cargo_vehicle_guid, cargo_mountpoint, iteration) =>
- HandleCheckCargoDismount(vehicle_guid, cargo_vehicle_guid, cargo_mountpoint, iteration)
+ case CheckCargoDismount(cargo_guid, carrier_guid, mountPoint, iteration) =>
+ HandleCheckCargoDismounting(cargo_guid, carrier_guid, mountPoint, iteration)
- case CheckCargoMounting(vehicle_guid, cargo_vehicle_guid, cargo_mountpoint, iteration) =>
- HandleCheckCargoMounting(vehicle_guid, cargo_vehicle_guid, cargo_mountpoint, iteration)
+ case CheckCargoMounting(cargo_guid, carrier_guid, mountPoint, iteration) =>
+ HandleCheckCargoMounting(cargo_guid, carrier_guid, mountPoint, iteration)
case ListAccountCharacters =>
import net.psforever.objects.definition.converter.CharacterSelectConverter
@@ -453,7 +468,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
val popVS = poplist.count(_.faction == PlanetSideEmpire.VS)
// StopBundlingPackets() is called on ClientInitializationComplete
StartBundlingPackets()
- zone.Buildings.foreach({ case (id, building) => initBuilding(continentNumber, id, building) })
+ zone.Buildings.foreach({ case (id, building) => initBuilding(continentNumber, building.MapId, building) })
sendResponse(ZonePopulationUpdateMessage(continentNumber, 414, 138, popTR, 138, popNC, 138, popVS, 138, popBO))
sendResponse(ContinentalLockUpdateMessage(continentNumber, PlanetSideEmpire.NEUTRAL))
//CaptureFlagUpdateMessage()
@@ -479,47 +494,21 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.warn(s"$tplayer is already spawned on zone ${zone.Id}; a clerical error?")
case Zone.Lattice.SpawnPoint(zone_id, spawn_tube) =>
- var pos = spawn_tube.Position
- var ori = spawn_tube.Orientation
+ var (pos, ori) = spawn_tube.SpecificPoint(continent.GUID(player.VehicleSeated) match {
+ case Some(obj) =>
+ obj
+ case _ =>
+ player
+ })
spawn_tube.Owner match {
case building : Building =>
log.info(s"Zone.Lattice.SpawnPoint: spawn point on $zone_id in building ${building.MapId} selected")
- val respawn_z_offset = 1.5f // Offset the spawn tube slightly, so the player doesn't spawn in the floor. This value comes from startup.pak/game_objects.adb.lst -> mb_respawn_tube respawn_z_offset setting
- pos += Vector3(0, 0, respawn_z_offset)
- ori += Vector3(0, 0, 90f) // Since all spawn tubes seem to have a zero orientation, we need to offset by 90 degrees so the player faces north towards the door, not east.
case vehicle : Vehicle =>
-// vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(vehicle), continent))
-// vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, vehicle.Definition.DeconstructionTime))
- //TODO replace this bad math with good math or no math
- //position the player alongside either of the AMS's terminals, facing away from it
- val side = if(System.currentTimeMillis() % 2 == 0) 1 else -1
- //right | left
- val z = spawn_tube.Orientation.z
- val zrot = (z + 90) % 360
- val x = spawn_tube.Orientation.x
- val xsin = 3 * side * math.abs(math.sin(math.toRadians(x))).toFloat + 0.5f
- //sin because 0-degrees is up
- val zrad = math.toRadians(zrot)
- pos = pos + (Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * (3 * side)) //x=sin, y=cos because compass-0 is East, not North
- ori = if(side == 1) {
- Vector3(0, 0, zrot)
- }
- else {
- Vector3(0, 0, (z - 90) % 360)
- }
- pos = if(x >= 330) {
- //leaning to the left
- pos + Vector3(0, 0, xsin)
- }
- else {
- pos - Vector3(0, 0, xsin)
- }
log.info(s"Zone.Lattice.SpawnPoint: spawn point on $zone_id at ams ${vehicle.GUID.guid} selected")
case owner =>
log.warn(s"Zone.Lattice.SpawnPoint: spawn point on $zone_id at ${spawn_tube.Position} has unexpected owner $owner")
}
- LoadZonePhysicalSpawnPoint(zone_id, pos, ori, if(zone_id == continent.Id) 10
- else 0)
+ LoadZonePhysicalSpawnPoint(zone_id, pos, ori, CountSpawnDelay(zone_id, spawn_tube, continent.Id))
case Zone.Lattice.NoValidSpawnPoint(zone_number, None) =>
log.warn(s"Zone.Lattice.SpawnPoint: zone $zone_number could not be accessed as requested")
@@ -537,6 +526,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
RequestSanctuaryZoneSpawn(player, zone_number)
}
+ case msg @ Zone.Vehicle.CanNotSpawn(zone, vehicle, reason) =>
+ log.warn(s"$msg")
+
+ case msg @ Zone.Vehicle.CanNotDespawn(zone, vehicle, reason) =>
+ log.warn(s"$msg")
+
case Zone.Ground.ItemOnGround(item : BoomerTrigger, pos, orient) =>
//dropped the trigger, no longer own the boomer; make certain whole faction is aware of that
val playerGUID = player.GUID
@@ -772,26 +767,38 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(FriendsResponse(FriendAction.InitializeIgnoreList, 0, true, true, Nil))
avatarService ! Service.Join(avatar.name) //channel will be player.Name
localService ! Service.Join(avatar.name) //channel will be player.Name
- cluster ! InterstellarCluster.GetWorld("z4")
+ vehicleService ! Service.Join(avatar.name) //channel will be player.Name
+ cluster ! InterstellarCluster.GetWorld("home3")
case InterstellarCluster.GiveWorld(zoneId, zone) =>
log.info(s"Zone $zoneId will now load")
- avatarService ! Service.Leave(Some(continent.Id))
- localService ! Service.Leave(Some(continent.Id))
- vehicleService ! Service.Leave(Some(continent.Id))
+ val continentId = continent.Id
+ val factionOnContinentChannel = s"$continentId/${avatar.faction}"
+ avatarService ! Service.Leave(Some(continentId))
+ avatarService ! Service.Leave(Some(factionOnContinentChannel))
+ localService ! Service.Leave(Some(continentId))
+ localService ! Service.Leave(Some(factionOnContinentChannel))
+ vehicleService ! Service.Leave(Some(continentId))
player.Continent = zoneId
continent = zone
continent.Population ! Zone.Population.Join(avatar)
- taskResolver ! RegisterNewAvatar(player)
+ interstellarFerry match {
+ case Some(vehicle) if vehicle.PassengerInSeat(player).contains(0) =>
+ taskResolver ! RegisterDrivenVehicle(vehicle, player)
+ case _ =>
+ taskResolver ! RegisterNewAvatar(player)
+ }
case NewPlayerLoaded(tplayer) =>
+ //new zone
log.info(s"Player ${tplayer.Name} has been loaded")
player = tplayer
- //LoadMapMessage will cause the client to send back a BeginZoningMessage packet (see below)
+ //LoadMapMessage causes the client to send BeginZoningMessage, eventually leading to SetCurrentAvatar
sendResponse(LoadMapMessage(continent.Map.Name, continent.Id, 40100, 25, true, 3770441820L))
AvatarCreate() //important! the LoadMapMessage must be processed by the client before the avatar is created
case PlayerLoaded(tplayer) =>
+ //same zone
log.info(s"Player ${tplayer.Name} will respawn")
player = tplayer
AvatarCreate()
@@ -1255,12 +1262,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
case LocalResponse.HackObject(target_guid, unk1, unk2) =>
- if(tplayer_guid != guid && continent.GUID(target_guid).get.asInstanceOf[Hackable].HackedBy.get._1.Faction != player.Faction) {
+ if(tplayer_guid != guid && continent.GUID(target_guid).get.asInstanceOf[Hackable].HackedBy.get.hackerFaction != player.Faction) {
// If the player is not in the faction that hacked this object then send the packet that it's been hacked, so they can either unhack it or use the hacked object
// Don't send this to the faction that hacked the object, otherwise it will interfere with the new SetEmpireMessage QoL change that changes the object colour to their faction (but only visible to that faction)
sendResponse(HackMessage(0, target_guid, guid, 100, unk1, HackState.Hacked, unk2))
}
- if(continent.GUID(target_guid).get.asInstanceOf[Hackable].HackedBy.get._1.Faction == player.Faction) {
+ if(continent.GUID(target_guid).get.asInstanceOf[Hackable].HackedBy.get.hackerFaction == player.Faction) {
// Make the hacked object look like it belongs to the hacking empire, but only for that empire's players (so that infiltrators on stealth missions won't be given away to opposing factions)
sendResponse(SetEmpireMessage(target_guid, player.Faction))
}
@@ -1276,7 +1283,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
// todo: blocking call. Not good.
val hack_time_remaining_ms = TimeUnit.MILLISECONDS.convert(time, TimeUnit.NANOSECONDS)
val deciseconds_remaining = (hack_time_remaining_ms / 100)
- val hacking_faction = continent.GUID(target_guid).get.asInstanceOf[Hackable].HackedBy.get._1.Faction
+ val hacking_faction = continent.GUID(target_guid).get.asInstanceOf[Hackable].HackedBy.get.hackerFaction
// See PlanetSideAttributeMessage #20 documentation for an explanation of how the timer is calculated
val start_num = hacking_faction match {
case PlanetSideEmpire.TR => 65536L
@@ -1359,31 +1366,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
tplayer.VehicleOwned = Some(obj_guid)
obj.Owner = Some(tplayer.GUID)
}
- obj.WeaponControlledFromSeat(seat_num) match {
- case Some(weapon : Tool) =>
- //update mounted weapon belonging to seat
- weapon.AmmoSlots.foreach(slot => {
- //update the magazine(s) in the weapon, specifically
- val magazine = slot.Box
- sendResponse(InventoryStateMessage(magazine.GUID, weapon.GUID, magazine.Capacity))
- })
- case _ => ; //no weapons to update
- }
AccessContents(obj)
+ UpdateWeaponAtSeatPosition(obj, seat_num)
MountingAction(tplayer, obj, seat_num)
case Mountable.CanMount(obj : PlanetSideGameObject with WeaponTurret, seat_num) =>
- obj.WeaponControlledFromSeat(seat_num) match {
- case Some(weapon : Tool) =>
- //update mounted weapon belonging to seat
- weapon.AmmoSlots.foreach(slot => {
- //update the magazine(s) in the weapon, specifically
- val magazine = slot.Box
- sendResponse(InventoryStateMessage(magazine.GUID, weapon.GUID, magazine.Capacity.toLong))
- })
- case _ => ; //no weapons to update
- }
sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health))
+ UpdateWeaponAtSeatPosition(obj, seat_num)
MountingAction(tplayer, obj, seat_num)
case Mountable.CanMount(obj : Mountable, _) =>
@@ -2020,17 +2009,48 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(msg)
case VehicleResponse.UpdateAmsSpawnPoint(list) =>
- //dismiss old ams spawn point
- ClearCurrentAmsSpawnPoint()
- //draw new ams spawn point
- list
- .filter(tube => tube.Faction == player.Faction)
- .sortBy(tube => Vector3.DistanceSquared(tube.Position, player.Position))
- .headOption match {
- case Some(tube) =>
- sendResponse(BindPlayerMessage(BindStatus.Available, "@ams", true, false, SpawnGroup.AMS, continent.Number, 5, tube.Position))
- amsSpawnPoint = Some(tube)
- case None => ;
+ amsSpawnPoints = list.filter(tube => tube.Faction == player.Faction)
+ DrawCurrentAmsSpawnPoint()
+
+ case VehicleResponse.TransferPassengerChannel(old_channel, temp_channel, vehicle) =>
+ if(tplayer_guid != guid) {
+ interstellarFerry = Some(vehicle)
+ vehicleService ! Service.Leave(Some(old_channel)) //old vehicle-specific channel (was s"${vehicle.Actor}")
+ vehicleService ! Service.Join(temp_channel) //temporary vehicle-specific channel (driver name, plus extra)
+ }
+ case VehicleResponse.TransferPassenger(temp_channel, vehicle, vehicle_to_delete) =>
+ vehicle.PassengerInSeat(player) match {
+ case Some(_) =>
+ vehicleService ! Service.Leave(Some(temp_channel)) //temporary vehicle-specific channel (see above)
+ deadState = DeadState.Release
+ sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
+ interstellarFerry = Some(vehicle) //on the other continent and registered to that continent's GUID system
+ interstellarFerryTopLevelGUID = Some(vehicle_to_delete) //vehicle.GUID, or previously a higher level parent
+ LoadZonePhysicalSpawnPoint(vehicle.Continent, vehicle.Position, vehicle.Orientation, 1)
+ case None =>
+ interstellarFerry match {
+ case None =>
+ vehicleService ! Service.Leave(Some(temp_channel)) //no longer being transferred between zones
+ case Some(_) => ;
+ //wait patiently
+ }
+ }
+
+ case VehicleResponse.KickCargo(vehicle, speed) =>
+ if(player.VehicleSeated.nonEmpty && deadState == DeadState.Alive) {
+ if(speed > 0) {
+ val strafe = if(CargoOrientation(vehicle) == 1) 2 else 1
+ val reverseSpeed = if(strafe > 1) 0 else speed
+ //strafe or reverse, not both
+ controlled = Some(reverseSpeed)
+ sendResponse(ServerVehicleOverrideMsg(true, true, true, false, 0, strafe, reverseSpeed, Some(0)))
+ import scala.concurrent.ExecutionContext.Implicits.global
+ context.system.scheduler.scheduleOnce(4500 milliseconds, self, VehicleServiceResponse(toChannel, tplayer_guid, VehicleResponse.KickCargo(vehicle, 0)))
+ }
+ else {
+ controlled = None
+ sendResponse(ServerVehicleOverrideMsg(false, false, false, false, 0, 0, 0, None))
+ }
}
case _ => ;
@@ -2039,98 +2059,289 @@ class WorldSessionActor extends Actor with MDCContextAware {
/**
* na
- * @param vehicle_guid na
- * @param cargo_vehicle_guid na
- * @param cargo_mountpoint na
- * @param iteration na
+ * @param decorator custom text for these messages in the log
+ * @param target an optional the target object
+ * @param targetGUID the expected globally unique identifier of the target object
*/
- def HandleCheckCargoDismount(vehicle_guid : PlanetSideGUID, cargo_vehicle_guid : PlanetSideGUID, cargo_mountpoint : Int, iteration : Int) : Unit = {
- val vehicle = continent.GUID(vehicle_guid.guid).get.asInstanceOf[Vehicle]
- val cargo_vehicle = continent.GUID(cargo_vehicle_guid).get.asInstanceOf[Vehicle]
- val distance = Vector3.Distance(vehicle.Position, cargo_vehicle.Position)
- log.info(s"Dismount distance ${distance}")
- if(distance > 15 || iteration > 20) {
- // Vehicle has moved far enough away - close the cargo door
- log.info("Vehicle is far enough away or disembark timed out - closing cargo door and returning full control to driver")
- StartBundlingPackets()
- // Return control of vehicle to driver
- DriverVehicleControl(vehicle)
- val cargoStatusMessage = CargoMountPointStatusMessage(cargo_vehicle_guid, PlanetSideGUID(0), PlanetSideGUID(0), vehicle_guid, cargo_mountpoint, CargoStatus.Empty, 0)
- log.warn(cargoStatusMessage.toString)
- // Do NOT send this packet back to the client directly. If you do and then send it again to all clients in the zone (including the client again)
- // The client will get stuck in a state where the player cannot dismount as it thinks it is always trying to remount the cargo hold
- avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, cargoStatusMessage))
- StopBundlingPackets()
- cargoMountTimer.cancel()
- cargoDismountTimer.cancel()
- }
- else {
- // Not far enough away - rescheduling check
- import scala.concurrent.ExecutionContext.Implicits.global
- cargoDismountTimer = context.system.scheduler.scheduleOnce(250 milliseconds, self, CheckCargoDismount(vehicle_guid, cargo_vehicle.GUID, cargo_mountpoint, iteration = iteration + 1))
+ def LogCargoEventMissingVehicleError(decorator : String, target : Option[PlanetSideGameObject], targetGUID : PlanetSideGUID) : Unit = {
+ target match {
+ case Some(_ : Vehicle) => ;
+ case Some(_) => log.error(s"$decorator target $targetGUID no longer identifies as a vehicle")
+ case None => log.error(s"$decorator target $targetGUID has gone missing")
}
}
/**
* na
- * @param vehicle_guid na
- * @param cargo_vehicle_guid na
- * @param cargo_mountpoint na
- * @param iteration na
+ * @param cargoGUID na
+ * @param carrierGUID na
+ * @param mountPoint na
+ * @param iteration na
*/
- def HandleCheckCargoMounting(vehicle_guid : PlanetSideGUID, cargo_vehicle_guid : PlanetSideGUID, cargo_mountpoint : Int, iteration : Int) : Unit = {
- val vehicle = continent.GUID(vehicle_guid.guid).get.asInstanceOf[Vehicle]
- val cargo_vehicle = continent.GUID(cargo_vehicle_guid.guid).get.asInstanceOf[Vehicle]
- val distance = Vector3.Distance(vehicle.Position, cargo_vehicle.Position)
- log.warn(s"Mount distance ${distance}")
- if(distance <= 8) {
- // Vehicle is close enough that it should be within the cargo bay. Mount it.
- log.info("Mounting vehicle cargo")
- cargoMountTimer.cancel()
- cargoDismountTimer.cancel()
- val vehicle = continent.GUID(vehicle_guid).get.asInstanceOf[Vehicle]
- StartBundlingPackets()
- vehicleService ! VehicleServiceMessage(s"${vehicle.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargo_vehicle_guid, 0, cargo_vehicle.Health)))
- vehicleService ! VehicleServiceMessage(s"${vehicle.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargo_vehicle_guid, 68, cargo_vehicle.Shields)))
- val attachMessage = ObjectAttachMessage(cargo_vehicle_guid, vehicle_guid, cargo_mountpoint)
- log.warn(attachMessage.toString)
- sendResponse(attachMessage)
- // This is required for when DismountVehicleCargoMsg is sent as the cargo_vehicle_guid isn't sent as a parameter
- vehicle.MountedIn = cargo_vehicle_guid
- cargo_vehicle.CargoHold(cargo_mountpoint).get.Occupant = vehicle
- val orientation = if(vehicle.Definition == GlobalDefinitions.router) {
- // mount router "sideways" in a lodestar
- //todo: BFRs will likely also need this set
- 1
- }
- else {
- 0
- }
- val cargoStatusMessage = CargoMountPointStatusMessage(cargo_vehicle_guid, vehicle_guid, vehicle_guid, PlanetSideGUID(0), cargo_mountpoint, CargoStatus.Occupied, orientation)
- log.warn(cargoStatusMessage.toString)
- sendResponse(cargoStatusMessage)
- StopBundlingPackets()
- avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, attachMessage))
- avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, cargoStatusMessage))
+ def HandleCheckCargoDismounting(cargoGUID : PlanetSideGUID, carrierGUID : PlanetSideGUID, mountPoint : Int, iteration : Int) : Unit = {
+ (continent.GUID(cargoGUID), continent.GUID(carrierGUID)) match {
+ case ((Some(vehicle : Vehicle), Some(cargo_vehicle : Vehicle))) =>
+ HandleCheckCargoDismounting(cargoGUID, vehicle, carrierGUID, cargo_vehicle, mountPoint, iteration)
+ case (cargo, carrier) if iteration > 0 =>
+ log.error(s"HandleCheckCargoDismounting: participant vehicles changed in the middle of a mounting event")
+ LogCargoEventMissingVehicleError("HandleCheckCargoDismounting: cargo", cargo, cargoGUID)
+ LogCargoEventMissingVehicleError("HandleCheckCargoDismounting: carrier", carrier, carrierGUID)
+ case _ =>
}
- else if(distance > 25 || iteration >= 15) {
- // Vehicle is too far away. Abort mounting.
- log.info("Vehicle is too far away or didn't mount within allocated time. Aborting cargo mount.")
- val cargoStatusMessage = CargoMountPointStatusMessage(cargo_vehicle_guid, PlanetSideGUID(0), PlanetSideGUID(0), vehicle_guid, cargo_mountpoint, CargoStatus.Empty, 0)
- log.warn(cargoStatusMessage.toString)
- // Do NOT send this packet back to the client directly. If you do and then send it again to all clients in the zone (including the client again)
- // The client will get stuck in a state where the player cannot dismount as it thinks it is always trying to remount the cargo hold
- avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, cargoStatusMessage))
- cargoMountTimer.cancel()
- cargoDismountTimer.cancel()
+ }
+
+ /**
+ * na
+ * @param cargoGUID na
+ * @param cargo na
+ * @param carrierGUID na
+ * @param carrier na
+ * @param mountPoint na
+ * @param iteration na
+ */
+ def HandleCheckCargoDismounting(cargoGUID : PlanetSideGUID, cargo : Vehicle, carrierGUID : PlanetSideGUID, carrier : Vehicle, mountPoint : Int, iteration : Int) : Unit = {
+ carrier.CargoHold(mountPoint) match {
+ case Some(hold) if !hold.isOccupied =>
+ val distance = Vector3.DistanceSquared(cargo.Position, carrier.Position)
+ log.debug(s"HandleCheckCargoDismounting: mount distance between $cargoGUID and $carrierGUID - actual=$distance, target=225")
+ if(distance > 225) {
+ //cargo vehicle has moved far enough away; close the carrier's hold door
+ log.info(s"HandleCheckCargoDismounting: dismount of cargo vehicle from carrier complete at distance of $distance")
+ vehicleService ! VehicleServiceMessage(
+ continent.Id,
+ VehicleAction.SendResponse(
+ player.GUID,
+ CargoMountPointStatusMessage(carrierGUID, PlanetSideGUID(0), PlanetSideGUID(0), cargoGUID, mountPoint, CargoStatus.Empty, 0)
+ )
+ )
+ //sending packet to the cargo vehicle's client results in player locking himself in his vehicle
+ //player gets stuck as "always trying to remount the cargo hold"
+ //obviously, don't do this
+ }
+ else if(iteration > 40) {
+ //cargo vehicle has spent too long not getting far enough away; restore the cargo's mount in the carrier hold
+ cargo.MountedIn = carrierGUID
+ hold.Occupant = cargo
+ StartBundlingPackets()
+ CargoMountBehaviorForAll(carrier, cargo, mountPoint)
+ StopBundlingPackets()
+ }
+ else {
+ //cargo vehicle did not move far away enough yet and there is more time to wait; reschedule check
+ import scala.concurrent.ExecutionContext.Implicits.global
+ cargoDismountTimer = context.system.scheduler.scheduleOnce(250 milliseconds, self, CheckCargoDismount(cargoGUID, carrierGUID, mountPoint, iteration + 1))
+ }
+ case None =>
+ log.warn(s"HandleCheckCargoDismounting: carrier vehicle $carrier does not have a cargo hold #$mountPoint")
+ case _ =>
+ if(iteration == 0) {
+ log.warn(s"HandleCheckCargoDismounting: carrier vehicle $carrier will not discharge the cargo of hold #$mountPoint; this operation was initiated incorrectly")
+ }
+ else {
+ log.error(s"HandleCheckCargoDismounting: something has attached to the carrier vehicle $carrier cargo of hold #$mountPoint while a cargo dismount event was ongoing; stopped at iteration $iteration / 40")
+ }
+ }
+ }
+
+ /**
+ * na
+ * @param cargoGUID the vehicle being ferried as cargo
+ * @param carrierGUID the ferrying carrier vehicle
+ * @param mountPoint the cargo hold to which the cargo vehicle is stowed
+ * @param iteration number of times a proper mounting for this combination has been queried
+ */
+ def HandleCheckCargoMounting(cargoGUID : PlanetSideGUID, carrierGUID : PlanetSideGUID, mountPoint : Int, iteration : Int) : Unit = {
+ (continent.GUID(cargoGUID), continent.GUID(carrierGUID)) match {
+ case ((Some(cargo : Vehicle), Some(carrier : Vehicle))) =>
+ HandleCheckCargoMounting(cargoGUID, cargo, carrierGUID, carrier, mountPoint, iteration)
+ case (cargo, carrier) if iteration > 0 =>
+ log.error(s"HandleCheckCargoMounting: participant vehicles changed in the middle of a mounting event")
+ LogCargoEventMissingVehicleError("HandleCheckCargoMounting: cargo", cargo, cargoGUID)
+ LogCargoEventMissingVehicleError("HandleCheckCargoMounting: carrier", carrier, carrierGUID)
+ case _ => ;
+ }
+ }
+
+ /**
+ * na
+ * @param cargoGUID the vehicle being ferried as cargo
+ * @param cargo the vehicle being ferried as cargo
+ * @param carrierGUID the ferrying carrier vehicle
+ * @param carrier the ferrying carrier vehicle
+ * @param mountPoint the cargo hold to which the cargo vehicle is stowed
+ * @param iteration number of times a proper mounting for this combination has been queried
+ */
+ def HandleCheckCargoMounting(cargoGUID : PlanetSideGUID, cargo : Vehicle, carrierGUID : PlanetSideGUID, carrier : Vehicle, mountPoint : Int, iteration : Int) : Unit = {
+ val distance = Vector3.DistanceSquared(cargo.Position, carrier.Position)
+ carrier.CargoHold(mountPoint) match {
+ case Some(hold) if !hold.isOccupied =>
+ log.debug(s"HandleCheckCargoMounting: mount distance between $cargoGUID and $carrierGUID - actual=$distance, target=64")
+ if(distance <= 64) {
+ //cargo vehicle is close enough to assume to be physically within the carrier's hold; mount it
+ log.info(s"HandleCheckCargoMounting: mounting cargo vehicle in carrier at distance of $distance")
+ cargo.MountedIn = carrierGUID
+ hold.Occupant = cargo
+ vehicleService ! VehicleServiceMessage(s"${cargo.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargoGUID, 0, cargo.Health)))
+ vehicleService ! VehicleServiceMessage(s"${cargo.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargoGUID, 68, cargo.Shields)))
+ StartBundlingPackets()
+ val (attachMsg, mountPointMsg) = CargoMountBehaviorForAll(carrier, cargo, mountPoint)
+ StopBundlingPackets()
+ log.info(s"HandleCheckCargoMounting: $attachMsg")
+ log.info(s"HandleCheckCargoMounting: $mountPointMsg")
+ }
+ else if(distance > 625 || iteration >= 40) {
+ //vehicles moved too far away or took too long to get into proper position; abort mounting
+ log.info("HandleCheckCargoMounting: cargo vehicle is too far away or didn't mount within allocated time - aborting")
+ vehicleService ! VehicleServiceMessage(
+ continent.Id,
+ VehicleAction.SendResponse(
+ player.GUID,
+ CargoMountPointStatusMessage(carrierGUID, PlanetSideGUID(0), PlanetSideGUID(0), cargoGUID, mountPoint, CargoStatus.Empty, 0)
+ )
+ )
+ //sending packet to the cargo vehicle's client results in player locking himself in his vehicle
+ //player gets stuck as "always trying to remount the cargo hold"
+ //obviously, don't do this
+ }
+ else {
+ //cargo vehicle still not in position but there is more time to wait; reschedule check
+ import scala.concurrent.ExecutionContext.Implicits.global
+ cargoMountTimer = context.system.scheduler.scheduleOnce(250 milliseconds, self, CheckCargoMounting(cargoGUID, carrierGUID, mountPoint, iteration = iteration + 1))
+ }
+ case None => ;
+ log.warn(s"HandleCheckCargoMounting: carrier vehicle $carrier does not have a cargo hold #$mountPoint")
+ case _ =>
+ if(iteration == 0) {
+ log.warn(s"HandleCheckCargoMounting: carrier vehicle $carrier already possesses cargo in hold #$mountPoint; this operation was initiated incorrectly")
+ }
+ else {
+ log.error(s"HandleCheckCargoMounting: something has attached to the carrier vehicle $carrier cargo of hold #$mountPoint while a cargo dismount event was ongoing; stopped at iteration $iteration / 40")
+ }
+ }
+ }
+
+ /**
+ * Produce an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet
+ * that will set up a realized parent-child association between a ferrying vehicle and a ferried vehicle.
+ * @see `CargoMountPointStatusMessage`
+ * @see `CargoOrientation`
+ * @see `ObjectAttachMessage`
+ * @param carrier the ferrying vehicle
+ * @param cargo the ferried vehicle
+ * @param mountPoint the point on the ferryoing vehicle where the ferried vehicle is attached;
+ * also known as a "cargo hold"
+ * @return a tuple composed of an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet
+ */
+ def CargoMountMessages(carrier : Vehicle, cargo : Vehicle, mountPoint : Int) : (ObjectAttachMessage, CargoMountPointStatusMessage) = {
+ CargoMountMessages(carrier.GUID, cargo.GUID, mountPoint, CargoOrientation(cargo))
+ }
+
+ /**
+ * Produce an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet
+ * that will set up a realized parent-child association between a ferrying vehicle and a ferried vehicle.
+ * @see `CargoMountPointStatusMessage`
+ * @see `ObjectAttachMessage`
+ * @param carrier the ferrying vehicle
+ * @param cargo the ferried vehicle
+ * @param mountPoint the point on the ferryoing vehicle where the ferried vehicle is attached
+ * @return a tuple composed of an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet
+ */
+ def CargoMountMessages(carrierGUID : PlanetSideGUID, cargoGUID : PlanetSideGUID, mountPoint : Int, orientation : Int) : (ObjectAttachMessage, CargoMountPointStatusMessage) = {
+ (
+ ObjectAttachMessage(carrierGUID, cargoGUID, mountPoint),
+ CargoMountPointStatusMessage(carrierGUID, cargoGUID, cargoGUID, PlanetSideGUID(0), mountPoint, CargoStatus.Occupied, orientation)
+ )
+ }
+
+ /**
+ * The orientation of a cargo vehicle as it is being loaded into and contained by a carrier vehicle.
+ * The type of carrier is not an important consideration in determining the orientation, oddly enough.
+ * @param vehicle the cargo vehicle
+ * @return the orientation as an `Integer` value;
+ * `0` for almost all cases
+ */
+ def CargoOrientation(vehicle : Vehicle) : Int = {
+ if(vehicle.Definition == GlobalDefinitions.router) {
+ 1
}
else {
- // Not close enough, far away enough or timeout not exceeded. Reschedule check
- import scala.concurrent.ExecutionContext.Implicits.global
- cargoMountTimer = context.system.scheduler.scheduleOnce(1 second, self, CheckCargoMounting(vehicle_guid, cargo_vehicle_guid, cargo_mountpoint, iteration = iteration + 1))
+ 0
}
}
+ /**
+ * Dispatch an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet only to this client.
+ * @see `CargoMountPointStatusMessage`
+ * @see `ObjectAttachMessage`
+ * @param carrier the ferrying vehicle
+ * @param cargo the ferried vehicle
+ * @param mountPoint the point on the ferryoing vehicle where the ferried vehicle is attached
+ * @return a tuple composed of an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet
+ */
+ def CargoMountBehaviorForUs(carrier : Vehicle, cargo : Vehicle, mountPoint : Int) : (ObjectAttachMessage, CargoMountPointStatusMessage) = {
+ val msgs @ (attachMessage, mountPointStatusMessage) = CargoMountMessages(carrier, cargo, mountPoint)
+ CargoMountMessagesForUs(attachMessage, mountPointStatusMessage)
+ msgs
+ }
+
+ /**
+ * Dispatch an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet only to this client.
+ * @see `CargoMountPointStatusMessage`
+ * @see `ObjectAttachMessage`
+ * @param attachMessage an `ObjectAttachMessage` packet suitable for initializing cargo operations
+ * @param mountPointStatusMessage a `CargoMountPointStatusMessage` packet suitable for initializing cargo operations
+ */
+ def CargoMountMessagesForUs(attachMessage : ObjectAttachMessage, mountPointStatusMessage : CargoMountPointStatusMessage) : Unit = {
+ sendResponse(attachMessage)
+ sendResponse(mountPointStatusMessage)
+ }
+
+
+
+ /**
+ * Dispatch an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet to all other clients, not this one.
+ * @see `CargoMountPointStatusMessage`
+ * @see `ObjectAttachMessage`
+ * @param carrier the ferrying vehicle
+ * @param cargo the ferried vehicle
+ * @param mountPoint the point on the ferryoing vehicle where the ferried vehicle is attached
+ * @return a tuple composed of an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet
+ */
+ def CargoMountBehaviorForOthers(carrier : Vehicle, cargo : Vehicle, mountPoint : Int) : (ObjectAttachMessage, CargoMountPointStatusMessage) = {
+ val msgs @ (attachMessage, mountPointStatusMessage) = CargoMountMessages(carrier, cargo, mountPoint)
+ CargoMountMessagesForOthers(attachMessage, mountPointStatusMessage)
+ msgs
+ }
+
+ /**
+ * Dispatch an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet to all other clients, not this one.
+ * @see `CargoMountPointStatusMessage`
+ * @see `ObjectAttachMessage`
+ * @param attachMessage an `ObjectAttachMessage` packet suitable for initializing cargo operations
+ * @param mountPointStatusMessage a `CargoMountPointStatusMessage` packet suitable for initializing cargo operations
+ */
+ def CargoMountMessagesForOthers(attachMessage : ObjectAttachMessage, mountPointStatusMessage : CargoMountPointStatusMessage) : Unit = {
+ val pguid = player.GUID
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.SendResponse(pguid, attachMessage))
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.SendResponse(pguid, mountPointStatusMessage))
+ }
+
+ /**
+ * Dispatch an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet to everyone.
+ * @see `CargoMountPointStatusMessage`
+ * @see `ObjectAttachMessage`
+ * @param carrier the ferrying vehicle
+ * @param cargo the ferried vehicle
+ * @param mountPoint the point on the ferryoing vehicle where the ferried vehicle is attached
+ * @return a tuple composed of an `ObjectAttachMessage` packet and a `CargoMountPointStatusMessage` packet
+ */
+ def CargoMountBehaviorForAll(carrier : Vehicle, cargo : Vehicle, mountPoint : Int) : (ObjectAttachMessage, CargoMountPointStatusMessage) = {
+ val msgs @ (attachMessage, mountPointStatusMessage) = CargoMountMessages(carrier, cargo, mountPoint)
+ CargoMountMessagesForUs(attachMessage, mountPointStatusMessage)
+ CargoMountMessagesForOthers(attachMessage, mountPointStatusMessage)
+ msgs
+ }
+
/**
* na
* @param target na
@@ -2176,7 +2387,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
target.Definition match {
case GlobalDefinitions.ams =>
target.Actor ! Deployment.TryDeploymentChange(DriveState.Undeploying)
- ClearCurrentAmsSpawnPoint()
case GlobalDefinitions.router =>
target.Actor ! Deployment.TryDeploymentChange(DriveState.Undeploying)
BeforeUnloadVehicle(target)
@@ -2408,15 +2618,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(PlayerStateShiftMessage(ShiftState(1, tplayer.Position, tplayer.Orientation.z)))
//transfer vehicle ownership
player.VehicleOwned match {
- case Some(vehicle_guid) =>
- continent.GUID(vehicle_guid) match {
- case Some(vehicle : Vehicle) =>
- vehicle.Owner = player
- vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.Ownership(guid, vehicle_guid))
- case _ =>
- player.VehicleOwned = None
- }
- case None => ;
+ case Some(vehicle_guid) if player.VehicleSeated.contains(vehicle_guid) =>
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.Ownership(guid, vehicle_guid))
+ case _ => ;
}
if(spectator) {
sendResponse(ChatMsg(ChatMessageType.CMT_TOGGLESPECTATORMODE, false, "", "on", None))
@@ -2533,8 +2737,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
InitializeDeployableQuantities(avatar) //set deployables ui elements
AwardBattleExperiencePoints(avatar, 1000000L)
player = new Player(avatar)
- //player.Position = Vector3(3561.0f, 2854.0f, 90.859375f) //home3, HART C
- player.Position = Vector3(3940.3984f, 4343.625f, 266.45312f) //z6, Anguta
+ player.Position = Vector3(3561.0f, 2854.0f, 90.859375f) //home3, HART C
+// player.Position = Vector3(3940.3984f, 4343.625f, 266.45312f) //z6, Anguta
// player.Position = Vector3(3571.2266f, 3278.0938f, 119.0f) //ce test
player.Orientation = Vector3(0f, 0f, 90f)
//player.Position = Vector3(4262.211f ,4067.0625f ,262.35938f) //z6, Akna.tower
@@ -2571,11 +2775,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
// Start timer to check every second if the vehicle is close enough to mount, or far enough away to cancel the mounting
+ cargoMountTimer.cancel
cargoMountTimer = context.system.scheduler.scheduleOnce(1 second, self, CheckCargoMounting(vehicle_guid, cargo_vehicle_guid, mountPoint, iteration = 0))
case None =>
log.warn(s"MountVehicleCargoMsg: target carrier vehicle (${carrier.Definition.Name}) does not have a cargo hold")
}
- case(None, _) | (Some(_), None) =>
+ case (None, _) | (Some(_), None) =>
log.warn(s"MountVehicleCargoMsg: one or more of the target vehicles do not exist - $cargo_vehicle_guid or $vehicle_guid")
case _ => ;
}
@@ -2623,7 +2828,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
traveler.zone = continentId
val faction = player.Faction
val factionOnContinentChannel = s"$continentId/$faction"
- StartBundlingPackets()
avatarService ! Service.Join(continentId)
avatarService ! Service.Join(factionOnContinentChannel)
localService ! Service.Join(continentId)
@@ -2711,9 +2915,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
)
)
})
- //load active players in zone
- continent.LivePlayers
- .filterNot(tplayer => { tplayer.GUID == player.GUID || tplayer.VehicleSeated.nonEmpty })
+ //load active players in zone (excepting players who are seated or players who are us)
+ val live = continent.LivePlayers
+ live.filterNot(tplayer => { tplayer.GUID == player.GUID || tplayer.VehicleSeated.nonEmpty })
.foreach(char => {
val tdefintion = char.Definition
sendResponse(ObjectCreateMessage(tdefintion.ObjectId, char.GUID, char.Definition.Packet.ConstructorData(char).get))
@@ -2725,16 +2929,28 @@ class WorldSessionActor extends Actor with MDCContextAware {
continent.Corpses.foreach {
TurnPlayerIntoCorpse
}
- //load vehicles in zone
- val (wreckages, vehicles) = continent.Vehicles.partition(vehicle => { vehicle.Health == 0 && vehicle.Definition.DestroyedModel.nonEmpty })
+ //load vehicles in zone (put separate the one we may be using)
+ val (wreckages, (vehicles, usedVehicle)) = {
+ val (a, b) = continent.Vehicles.partition(vehicle => { vehicle.Health == 0 && vehicle.Definition.DestroyedModel.nonEmpty })
+ (a, (continent.GUID(player.VehicleSeated) match {
+ case Some(vehicle : Vehicle) if vehicle.PassengerInSeat(player).isDefined =>
+ b.partition { _.GUID != vehicle.GUID }
+ case None =>
+ (b, List.empty[Vehicle])
+ case _ =>
+ //throw error since VehicleSeated didn't point to a vehicle?
+ player.VehicleSeated = None
+ (b, List.empty[Vehicle])
+ }))
+ }
//active vehicles (and some wreckage)
vehicles.foreach(vehicle => {
- val vehicle_guid = vehicle.GUID
+ val vguid = vehicle.GUID
val vdefinition = vehicle.Definition
- sendResponse(ObjectCreateMessage(vdefinition.ObjectId, vehicle_guid, vdefinition.Packet.ConstructorData(vehicle).get))
+ sendResponse(ObjectCreateMessage(vdefinition.ObjectId, vguid, vdefinition.Packet.ConstructorData(vehicle).get))
//occupants other than driver
vehicle.Seats
- .filter({ case(index, seat) => seat.isOccupied && index > 0 })
+ .filter({ case(index, seat) => seat.isOccupied && live.contains(seat.Occupant.get) && index > 0 })
.foreach({ case(index, seat) =>
val tplayer = seat.Occupant.get
val tdefintion = tplayer.Definition
@@ -2742,13 +2958,43 @@ class WorldSessionActor extends Actor with MDCContextAware {
ObjectCreateMessage(
tdefintion.ObjectId,
tplayer.GUID,
- ObjectCreateMessageParent(vehicle_guid, index),
+ ObjectCreateMessageParent(vguid, index),
tdefintion.Packet.ConstructorData(tplayer).get
)
)
})
ReloadVehicleAccessPermissions(vehicle)
})
+ //our vehicle would have already been loaded; see NewPlayerLoaded/AvatarCreate
+ usedVehicle.headOption match {
+ case Some(vehicle) if vehicle.PassengerInSeat(player).contains(0) =>
+ //if driver of vehicle, summon any passengers and cargo vehicles left behind on previous continent
+ LoadZoneTransferPassengerMessages(
+ guid,
+ continentId,
+ TransportVehicleChannelName(vehicle),
+ vehicle,
+ interstellarFerryTopLevelGUID.orElse(player.VehicleSeated).getOrElse(PlanetSideGUID(0))
+ )
+ case Some(vehicle) =>
+ //if passenger, attempt to depict any other passengers already in this zone
+ val vguid = vehicle.GUID
+ vehicle.Seats
+ .filter({ case(index, seat) => seat.isOccupied && !seat.Occupant.contains(player) && live.contains(seat.Occupant.get) && index > 0 })
+ .foreach({ case(index, seat) =>
+ val tplayer = seat.Occupant.get
+ val tdefintion = tplayer.Definition
+ sendResponse(
+ ObjectCreateMessage(
+ tdefintion.ObjectId,
+ tplayer.GUID,
+ ObjectCreateMessageParent(vguid, index),
+ tdefintion.Packet.ConstructorData(tplayer).get
+ )
+ )
+ })
+ case _ => ; //no vehicle
+ }
//vehicle wreckages
wreckages.foreach(vehicle => {
sendResponse(
@@ -2759,20 +3005,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
)
)
})
- //Loop over vehicles again to add cargohold occupants after all vehicles have been created on the local client
- vehicles.filter(_.CargoHolds.nonEmpty).foreach(vehicle => {
- vehicle.CargoHolds.foreach({ case (cargo_num, cargo) => {
- cargo.Occupant match {
- case Some(cargo_vehicle) =>
- if(cargo_vehicle.HasGUID) {
- sendResponse(ObjectAttachMessage(cargo_vehicle.GUID, vehicle.GUID, cargo_num))
- //todo: attaching the vehicle seems to work, but setting the mount point status doesn't?
- sendResponse(CargoMountPointStatusMessage(cargo_vehicle.GUID, vehicle.GUID, vehicle.GUID, PlanetSideGUID(0), cargo_num, CargoStatus.Occupied, 0))
- }
- case None => ; // No vehicle in cargo
- }
+ //cargo occupants (including our own vehicle as cargo)
+ vehicles.collect { case vehicle if vehicle.CargoHolds.nonEmpty =>
+ vehicle.CargoHolds.collect({ case (index, hold) if hold.isOccupied => {
+ CargoMountBehaviorForAll(vehicle, hold.Occupant.get, index) //CargoMountBehaviorForUs can fail to attach the cargo vehicle on some clients
}})
- })
+ }
//special deploy states
val deployedVehicles = vehicles.filter(_.DeploymentState == DriveState.Deployed)
deployedVehicles.filter(_.Definition == GlobalDefinitions.ams).foreach(obj => {
@@ -2858,11 +3096,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
case _ => ;
}
})
- StopBundlingPackets()
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.UpdateAmsSpawnPoint(continent))
self ! SetCurrentAvatar(player)
case msg @ PlayerStateMessageUpstream(avatar_guid, pos, vel, yaw, pitch, yaw_upper, seq_time, unk3, is_crouching, is_jumping, unk4, is_cloaking, unk5, unk6) =>
- if(player.isAlive) {
+ if(deadState == DeadState.Alive) {
player.Position = pos
player.Velocity = vel
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)
@@ -2922,11 +3160,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
//log.warn(s"ChildObjectState: player $player not related to anything with a controllable agent")
}
- case msg @ VehicleStateMessage(vehicle_guid, unk1, pos, ang, vel, unk5, unk6, unk7, wheels, unk9, unkA) =>
- continent.GUID(vehicle_guid) match {
- case Some(obj : Vehicle) =>
- val seat = obj.Seat(0).get
- if(seat.Occupant.contains(player)) {
+ case msg @ VehicleStateMessage(vehicle_guid, unk1, pos, ang, vel, flight, unk6, unk7, wheels, unk9, unkA) =>
+ if(deadState == DeadState.Alive) {
+ GetVehicleAndSeat() match {
+ case (Some(obj), Some(0)) =>
+ val seat = obj.Seats(0)
//we're driving the vehicle
player.Position = pos //convenient
if(seat.ControlledWeapon.isEmpty) {
@@ -2935,11 +3173,17 @@ class WorldSessionActor extends Actor with MDCContextAware {
obj.Position = pos
obj.Orientation = ang
obj.Velocity = vel
- vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.VehicleState(player.GUID, vehicle_guid, unk1, pos, ang, vel, unk5, unk6, unk7, wheels, unk9, unkA))
- }
- //TODO placing a "not driving" warning here may trigger as we are disembarking the vehicle
- case _ =>
- log.warn(s"VehicleState: no vehicle $vehicle_guid found in zone")
+ if(obj.Definition.CanFly) {
+ obj.Flying = flight.nonEmpty //usually Some(7)
+ }
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.VehicleState(player.GUID, vehicle_guid, unk1, pos, ang, vel, flight, unk6, unk7, wheels, unk9, unkA))
+ case (None, _) =>
+ //log.error(s"VehicleState: no vehicle $vehicle_guid found in zone")
+ //TODO placing a "not driving" warning here may trigger as we are disembarking the vehicle
+ case (_, Some(index)) =>
+ log.error(s"VehicleState: player should not be dispatching this kind of packet from vehicle#$vehicle_guid when not the driver ($index)")
+ case _ => ;
+ }
}
//log.info(s"VehicleState: $msg")
@@ -2952,11 +3196,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
case msg @ ReleaseAvatarRequestMessage() =>
log.info(s"ReleaseAvatarRequest: ${player.GUID} on ${continent.Id} has released")
reviveTimer.cancel
- player.Release
- deadState = DeadState.Release
- sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
continent.Population ! Zone.Population.Release(avatar)
- vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.UpdateAmsSpawnPoint(continent))
+ GoToDeploymentMap()
player.VehicleSeated match {
case None =>
FriskCorpse(player)
@@ -3025,24 +3266,38 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
CSRZone.read(traveler, msg) match {
- case (true, zone, pos) =>
- if(player.isAlive) {
- player.Die //die to suspend client-driven position change updates (in theory)
- PlayerActionsToCancel()
- player.Position = pos
- avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, player.GUID))
- LoadZonePhysicalSpawnPoint(zone, pos, Vector3.Zero, 0)
+ case (true, zone, pos) if player.isAlive =>
+ deadState = DeadState.Release //cancel movement updates
+ PlayerActionsToCancel()
+ continent.GUID(player.VehicleSeated) match {
+ case Some(vehicle : Vehicle) =>
+ vehicle.Position = pos
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.UnloadVehicle(player.GUID, continent, vehicle, vehicle.GUID))
+ LoadZonePhysicalSpawnPoint(zone, pos, Vector3.Zero, 0)
+ case None =>
+ player.Position = pos
+ avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, player.GUID))
+ LoadZonePhysicalSpawnPoint(zone, pos, Vector3.Zero, 0)
+ case _ => //seated in something that is not a vehicle, in which case we can't move
+ deadState = DeadState.Alive
}
case (false, _, _) => ;
}
CSRWarp.read(traveler, msg) match {
- case (true, pos) =>
- if(player.isAlive) {
- PlayerActionsToCancel()
- sendResponse(PlayerStateShiftMessage(ShiftState(0, pos, player.Orientation.z, None)))
- player.Position = pos
+ case (true, pos) if player.isAlive =>
+ deadState = DeadState.Release //cancel movement updates
+ PlayerActionsToCancel()
+ continent.GUID(player.VehicleSeated) match {
+ case Some(vehicle : Vehicle) =>
+ LoadZonePhysicalSpawnPoint(continent.Id, pos, Vector3.z(vehicle.Orientation.z), 0)
+ case None =>
+ player.Position = pos
+ sendResponse(PlayerStateShiftMessage(ShiftState(0, pos, player.Orientation.z, None)))
+ deadState = DeadState.Alive //must be set here
+ case _ => //seated in something that is not a vehicle, in which case we can't move
+ deadState = DeadState.Alive
}
case (false, _) => ;
@@ -3084,7 +3339,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
else if(trimContents.equals("!ams")) {
makeReply = false
- if(player.isBackpack) { //player is on deployment screen (either dead or deconstructed)
+ if(deadState == DeadState.Release) { //player is on deployment screen (either dead or deconstructed)
cluster ! Zone.Lattice.RequestSpawnPoint(continent.Number, player, 2)
}
}
@@ -3700,7 +3955,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
case Some(captureTerminal : CaptureTerminal) =>
- val hackedByCurrentFaction = (captureTerminal.Faction != player.Faction && !captureTerminal.HackedBy.isEmpty && captureTerminal.HackedBy.head._1.Faction == player.Faction)
+ val hackedByCurrentFaction = (captureTerminal.Faction != player.Faction && !captureTerminal.HackedBy.isEmpty && captureTerminal.HackedBy.get.hackerFaction == player.Faction)
val ownedByPlayerFactionAndHackedByEnemyFaction = (captureTerminal.Faction == player.Faction && !captureTerminal.HackedBy.isEmpty)
if(!hackedByCurrentFaction || ownedByPlayerFactionAndHackedByEnemyFaction) {
player.Slot(player.DrawnSlot).Equipment match {
@@ -3839,10 +4094,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
//deconstruction
PlayerActionsToCancel()
CancelAllProximityUnits()
- player.Release
- deadState = DeadState.Release
- sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
continent.Population ! Zone.Population.Release(avatar)
+ GoToDeploymentMap()
case Some(obj : TelepadDeployable) =>
continent.GUID(obj.Router) match {
@@ -4153,7 +4406,19 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.info("AvatarFirstTimeEvent: " + msg)
case msg @ WarpgateRequest(continent_guid, building_guid, dest_building_guid, dest_continent_guid, unk1, unk2) =>
- log.info("WarpgateRequest: " + msg)
+ log.info(s"WarpgateRequest: $msg")
+ continent.Buildings.values.find(building => building.GUID == building_guid) match {
+ case Some(wg : WarpGate) if(wg.Active && (GetKnownVehicleAndSeat() match {
+ case (Some(vehicle), _) =>
+ wg.Definition.VehicleAllowance && !wg.Definition.NoWarp.contains(vehicle.Definition)
+ case _ =>
+ true
+ })) =>
+ cluster ! Zone.Lattice.RequestSpecificSpawnPoint(dest_continent_guid.guid, player, dest_building_guid)
+
+ case _ =>
+ RequestSanctuaryZoneSpawn(player, continent.Number)
+ }
case msg @ MountVehicleMsg(player_guid, mountable_guid, entry_point) =>
log.info("MountVehicleMsg: "+msg)
@@ -4176,23 +4441,31 @@ class WorldSessionActor extends Actor with MDCContextAware {
def dismountWarning(msg : String) : Unit = {
log.warn(s"$msg; some vehicle might not know that a player is no longer sitting in it")
}
- if(player.HasGUID && player.GUID == player_guid) {
+ if(player.GUID == player_guid) {
//normally disembarking from a seat
player.VehicleSeated match {
case Some(obj_guid) =>
- continent.GUID(obj_guid) match {
+ interstellarFerry.orElse(continent.GUID(obj_guid)) match {
case Some(obj : Mountable) =>
obj.PassengerInSeat(player) match {
+ case Some(0) if controlled.nonEmpty =>
+ log.warn(s"DismountVehicleMsg: can not dismount from vehicle as driver while server has asserted control; please wait ...")
case Some(seat_num : Int) =>
obj.Actor ! Mountable.TryDismount(player, seat_num)
-
+ if(interstellarFerry.isDefined) {
+ //short-circuit the temporary channel for transferring between zones, the player is no longer doing that
+ //see above in VehicleResponse.TransferPassenger case
+ interstellarFerry = None
+ }
// Deconstruct the vehicle if the driver has bailed out and the vehicle is capable of flight
//todo: implement auto landing procedure if the pilot bails but passengers are still present instead of deconstructing the vehicle
//todo: continue flight path until aircraft crashes if no passengers present (or no passenger seats), then deconstruct.
//todo: kick cargo passengers out. To be added after PR #216 is merged
- if(bailType == BailType.Bailed && seat_num == 0 && GlobalDefinitions.isFlightVehicle(obj.asInstanceOf[Vehicle].Definition)) {
- vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent))
- vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(obj, continent, Some(0 seconds))) // Immediately deconstruct vehicle
+ obj match {
+ case v : Vehicle if bailType == BailType.Bailed && seat_num == 0 && v.Flying =>
+ vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(obj), continent))
+ vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(obj, continent, Some(0 seconds))) // Immediately deconstruct vehicle
+ case _ => ;
}
case None =>
@@ -4634,12 +4907,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
}, List(RegisterVehicle(obj)))
}
- //TODO this may be useful for vehicle gating
def RegisterDrivenVehicle(obj : Vehicle, driver : Player) : TaskResolver.GiveTask = {
TaskResolver.GiveTask(
new Task() {
private val localVehicle = obj
private val localDriver = driver
+ private val localAnnounce = self
override def isComplete : Task.Resolution.Value = {
if(localVehicle.HasGUID && localDriver.HasGUID) {
@@ -4651,10 +4924,37 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
def Execute(resolver : ActorRef) : Unit = {
- //TODO some kind of callback ...
+ localDriver.VehicleSeated = localVehicle.GUID
+ localVehicle.Owner = localDriver.GUID
+ localAnnounce ! NewPlayerLoaded(localDriver) //alerts WSA
resolver ! scala.util.Success(this)
}
- }, List(RegisterAvatar(driver), RegisterVehicle(obj)))
+
+ override def onFailure(ex : Throwable) : Unit = {
+ localAnnounce ! PlayerFailedToLoad(localDriver) //alerts WSA
+ }
+ }, List(GUIDTask.RegisterAvatar(driver)(continent.GUID), GUIDTask.RegisterVehicle(obj)(continent.GUID)))
+ }
+
+ def UnregisterDrivenVehicle(obj : Vehicle, driver : Player) : TaskResolver.GiveTask = {
+ TaskResolver.GiveTask(
+ new Task() {
+ private val localVehicle = obj
+ private val localDriver = driver
+
+ override def isComplete : Task.Resolution.Value = {
+ if(!localVehicle.HasGUID && !localDriver.HasGUID) {
+ Task.Resolution.Success
+ }
+ else {
+ Task.Resolution.Incomplete
+ }
+ }
+
+ def Execute(resolver : ActorRef) : Unit = {
+ resolver ! scala.util.Success(this)
+ }
+ }, List(GUIDTask.UnregisterAvatar(driver)(continent.GUID), GUIDTask.UnregisterVehicle(obj)(continent.GUID)))
}
/**
@@ -4927,7 +5227,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
* The vehicle must exist in the game world on the current continent.
* This is similar but unrelated to the natural exchange of ownership when someone else sits in the vehicle's driver seat.
* This is the player side of vehicle ownership removal.
- * @see `DisownVehicle(Player, Vehicle)`
+ * @see `SpecialCaseVehicleDespawn(Player, Vehicle)`
* @param tplayer the player
*/
def DisownVehicle(tplayer : Player) : Option[Vehicle] = {
@@ -4936,7 +5236,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
tplayer.VehicleOwned = None
continent.GUID(vehicle_guid) match {
case Some(vehicle : Vehicle) =>
- DisownVehicle(tplayer, vehicle)
+ SpecialCaseVehicleDespawn(tplayer, vehicle)
case _ =>
None
}
@@ -4948,16 +5248,33 @@ class WorldSessionActor extends Actor with MDCContextAware {
/**
* Disassociate a vehicle from the player that owns it, if that player really was the previous owner.
* This is the vehicle side of vehicle ownership removal.
- * Additionally, start the vehicle deconstruction timer.
+ * Additionally, start the vehicle deconstruction timer if conditions are valid.
* @see `DisownVehicle(Player)`
* @param tplayer the player
* @param vehicle the discovered vehicle
*/
- private def DisownVehicle(tplayer : Player, vehicle : Vehicle) : Option[Vehicle] = {
- if(vehicle.Owner.contains(tplayer.GUID)) {
+ private def SpecialCaseVehicleDespawn(tplayer : Player, vehicle : Vehicle) : Option[Vehicle] = {
+ if(vehicle.Owner.contains(tplayer.GUID) || !vehicle.Seats(0).isOccupied) {
vehicle.Owner = None
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(vehicle), continent))
- vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, vehicle.Definition.DeconstructionTime)) //start vehicle decay
+ vehicle.CargoHolds.values
+ .collect { case hold if hold.isOccupied => SpecialCaseVehicleDespawn(player, hold.Occupant.get) }
+ continent.GUID(vehicle.MountedIn) match {
+ case Some(ferry : Vehicle) =>
+ HandleDismountVehicleCargo(
+ PlanetSideGUID(0),
+ vehicle.GUID,
+ vehicle,
+ ferry.GUID,
+ ferry,
+ true,
+ false,
+ false
+ )
+ vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, Some(0 seconds))) //instant vehicle decay
+ case _ =>
+ vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, vehicle.Definition.DeconstructionTime)) //normal vehicle decay
+ }
Some(vehicle)
}
else {
@@ -5867,15 +6184,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.error(s"DeployRequest: $obj can not transition to $state - $reason$mobileShift")
}
- def ClearCurrentAmsSpawnPoint() : Unit = {
- amsSpawnPoint match {
- case Some(tube) =>
- sendResponse(BindPlayerMessage(BindStatus.Unavailable, "@ams", true, false, SpawnGroup.AMS, continent.Number, 0, Vector3.Zero))
- amsSpawnPoint = None
- case None => ;
- }
- }
-
/**
* For a given continental structure, determine the method of generating server-join client configuration packets.
* @param continentNumber the zone id
@@ -5904,29 +6212,28 @@ class WorldSessionActor extends Actor with MDCContextAware {
* @param building the building object
*/
def initFacility(continentNumber : Int, buildingNumber : Int, building : Building) : Unit = {
+ val (
+ ntuLevel,
+ isHacked, empireHack, hackTimeRemaining, controllingEmpire,
+ unk1, unk1x,
+ generatorState, spawnTubesNormal, forceDomeActive,
+ latticeBenefit, cavernBenefit,
+ unk4, unk5, unk6,
+ unk7, unk7x,
+ boostSpawnPain, boostGeneratorPain
+ ) = building.Info
sendResponse(
BuildingInfoUpdateMessage(
continentNumber,
buildingNumber,
- ntu_level = 8,
- is_hacked = false,
- empire_hack = PlanetSideEmpire.NEUTRAL,
- hack_time_remaining = 0,
- building.Faction,
- unk1 = 0, //!! Field != 0 will cause malformed packet. See class def.
- unk1x = None,
- PlanetSideGeneratorState.Normal,
- spawn_tubes_normal = true,
- force_dome_active = false,
- lattice_benefit = 0,
- cavern_benefit = 0, //!! Field > 0 will cause malformed packet. See class def.
- unk4 = Nil,
- unk5 = 0,
- unk6 = false,
- unk7 = 8, //!! Field != 8 will cause malformed packet. See class def.
- unk7x = None,
- boost_spawn_pain = false,
- boost_generator_pain = false
+ ntuLevel,
+ isHacked, empireHack, hackTimeRemaining, controllingEmpire,
+ unk1, unk1x,
+ generatorState, spawnTubesNormal, forceDomeActive,
+ latticeBenefit, cavernBenefit,
+ unk4, unk5, unk6,
+ unk7, unk7x,
+ boostSpawnPain, boostGeneratorPain
)
)
sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0)))
@@ -5944,33 +6251,37 @@ class WorldSessionActor extends Actor with MDCContextAware {
* @param building the building object
*/
def initGate(continentNumber : Int, buildingNumber : Int, building : Building) : Unit = {
- sendResponse(
- BuildingInfoUpdateMessage(
- continentNumber,
- buildingNumber,
- ntu_level = 0,
- is_hacked = false,
- empire_hack = PlanetSideEmpire.NEUTRAL,
- hack_time_remaining = 0,
- building.Faction,
- unk1 = 0,
- unk1x = None,
- PlanetSideGeneratorState.Normal,
- spawn_tubes_normal = true,
- force_dome_active = false,
- lattice_benefit = 0,
- cavern_benefit = 0,
- unk4 = Nil,
- unk5 = 0,
- unk6 = false,
- unk7 = 8,
- unk7x = None,
- boost_spawn_pain = false,
- boost_generator_pain = false
- )
- )
- sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0)))
- sendResponse(BroadcastWarpgateUpdateMessage(continentNumber, buildingNumber, false, false, true))
+ building match {
+ case wg : WarpGate =>
+ sendResponse(
+ BuildingInfoUpdateMessage(
+ continentNumber,
+ buildingNumber,
+ ntu_level = 0,
+ is_hacked = false,
+ empire_hack = PlanetSideEmpire.NEUTRAL,
+ hack_time_remaining = 0,
+ building.Faction,
+ unk1 = 0,
+ unk1x = None,
+ PlanetSideGeneratorState.Normal,
+ spawn_tubes_normal = true,
+ force_dome_active = false,
+ lattice_benefit = 0,
+ cavern_benefit = 0,
+ unk4 = Nil,
+ unk5 = 0,
+ unk6 = false,
+ unk7 = 8,
+ unk7x = None,
+ boost_spawn_pain = false,
+ boost_generator_pain = false
+ )
+ )
+ sendResponse(DensityLevelUpdateMessage(continentNumber, buildingNumber, List(0,0, 0,0, 0,0, 0,0)))
+ sendResponse(BroadcastWarpgateUpdateMessage(continentNumber, buildingNumber, false, false, wg.Broadcast))
+ case _ => ;
+ }
}
/**
@@ -6107,7 +6418,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
*
* Things whose configuration should not be changed:
* - if the player is seated
- * - if anchored
+ * - if the player is anchored
+ * This is not a complete list but, for the purpose of enforcement, some pointers will be documented here.
*/
def PlayerActionsToCancel() : Unit = {
progressBarUpdate.cancel
@@ -6147,20 +6459,181 @@ class WorldSessionActor extends Actor with MDCContextAware {
/**
* A part of the process of spawning the player into the game world.
* The function should work regardless of whether the player is alive or dead - it will make them alive.
- * It adds the `WSA`-current `Player` to the current zone and sends out the expected packets.
+ * It adds the `WSA`-current `Player` to the current zone and sends out the expected packets.
+ *
+ * If that player is the driver of a vehicle, it will construct the vehicle.
+ * If that player is the occupant of a vehicle, it will place them inside that vehicle.
+ * These two previous statements operate through similar though distinct mechanisms and actually imply different conditions.
+ * The vehicle will not be created unless the player is a living driver;
+ * but, the second statement will always trigger so long as the player is in a vehicle.
+ * The first produces a version of the player more suitable to be "another player in the game," and not "the avatar."
+ * The second would write over the product of the first to produce "the avatar."
+ * The vehicle should only be constructed once as, if it created a second time, that distinction will become lost.
+ * @see `BeginZoningMessage`
+ * @see `CargoMountBehaviorForOthers`
+ * @see `AvatarCreateInVehicle`
+ * @see `GetKnownVehicleAndSeat`
+ * @see `LoadZoneTransferPassengerMessages`
+ * @see `Player.Spawn`
+ * @see `ReloadVehicleAccessPermissions`
+ * @see `TransportVehicleChannelName`
*/
def AvatarCreate() : Unit = {
- player.VehicleSeated = None //TODO temp, until vehicle gating; unseat player else constructor data is messed up
+ val health = player.Health
+ val armor = player.Armor
+ val stamina = player.Stamina
player.Spawn
- player.Health = 100
- player.Armor = 50
- val packet = player.Definition.Packet
- val dcdata = packet.DetailedConstructorData(player).get
- val player_guid = player.GUID
- sendResponse(ObjectCreateDetailedMessage(ObjectClass.avatar, player_guid, dcdata))
+ if(health != 0) {
+ player.Health = health
+ player.Armor = armor
+ player.Stamina = stamina
+ }
+ GetKnownVehicleAndSeat() match {
+ case (Some(vehicle : Vehicle), Some(seat : Int)) =>
+ //vehicle and driver/passenger
+ interstellarFerry = None
+ val vdef = vehicle.Definition
+ val data = vdef.Packet.ConstructorData(vehicle).get
+ val guid = vehicle.GUID
+ sendResponse(ObjectCreateMessage(vehicle.Definition.ObjectId, guid, data))
+ ReloadVehicleAccessPermissions(vehicle)
+ //if the vehicle is the cargo of another vehicle in this zone
+ val carrierInfo = continent.GUID(vehicle.MountedIn) match {
+ case Some(carrier : Vehicle) =>
+ (Some(carrier), carrier.CargoHolds.find({ case (index, hold) => hold.Occupant.contains(vehicle)}))
+ case _ =>
+ (None, None)
+ }
+ player.VehicleSeated = guid
+ if(seat == 0) {
+ //if driver
+ player.VehicleOwned = guid
+ vehicle.Owner = player.GUID
+ vehicle.CargoHolds.values
+ .collect { case hold if hold.isOccupied => hold.Occupant.get }
+ .foreach { _.MountedIn = guid }
+ continent.Transport ! Zone.Vehicle.Spawn(vehicle)
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.LoadVehicle(player.GUID, vehicle, vdef.ObjectId, guid, data))
+ carrierInfo match {
+ case (Some(carrier), Some((index, _))) =>
+ CargoMountBehaviorForOthers(carrier, vehicle, index)
+ case _ =>
+ vehicle.MountedIn = None
+ }
+ //call for passengers across the expanse
+ LoadZoneTransferPassengerMessages(
+ player.GUID,
+ continent.Id,
+ TransportVehicleChannelName(vehicle),
+ vehicle,
+ interstellarFerryTopLevelGUID.orElse(player.VehicleSeated).getOrElse(PlanetSideGUID(0))
+ )
+ interstellarFerryTopLevelGUID = None
+ }
+ else {
+ //if passenger;
+ //meant for same-zone warping; when player changes zones, redundant information will be sent
+ carrierInfo match {
+ case (Some(carrier), Some((index, _))) =>
+ CargoMountBehaviorForUs(carrier, vehicle, index)
+ case _ => ;
+ }
+ }
+ log.info(s"AvatarCreate (vehicle): $guid -> $data")
+ //player, passenger
+ AvatarCreateInVehicle(player, vehicle, seat)
+
+ case _ =>
+ player.VehicleSeated = None
+ val packet = player.Definition.Packet
+ val data = packet.DetailedConstructorData(player).get
+ val guid = player.GUID
+ sendResponse(ObjectCreateDetailedMessage(ObjectClass.avatar, guid, data))
+ avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.LoadPlayer(guid, ObjectClass.avatar, guid, packet.ConstructorData(player).get, None))
+ log.info(s"AvatarCreate: $guid -> $data")
+ }
continent.Population ! Zone.Population.Spawn(avatar, player)
- avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.LoadPlayer(player_guid, ObjectClass.avatar, player_guid, packet.ConstructorData(player).get, None))
- log.debug(s"ObjectCreateDetailedMessage: $dcdata")
+ //cautious redundancy
+ deadState = DeadState.Alive
+ }
+
+ /**
+ * If the player is seated in a vehicle, find that vehicle and get the seat index number at which the player is sat.
+ *
+ * For special purposes involved in zone transfers,
+ * where the vehicle may or may not exist in either of the zones (yet),
+ * the value of `interstellarFerry` is also polled.
+ * Making certain this field is blanked after the transfer is completed is important
+ * to avoid inspecting the wrong vehicle and failing simple vehicle checks where this function may be employed.
+ * @see `interstellarFerry`
+ * @return a tuple consisting of a vehicle reference and a seat index
+ * if and only if the vehicle is known to this client and the `WorldSessioNActor`-global `player` occupies it;
+ * `(None, None)`, otherwise (even if the vehicle can be determined)
+ */
+ def GetKnownVehicleAndSeat() : (Option[Vehicle], Option[Int]) =
+ interstellarFerry.orElse(continent.GUID(player.VehicleSeated)) match {
+ case Some(vehicle : Vehicle) =>
+ vehicle.PassengerInSeat(player) match {
+ case index @ Some(_) =>
+ (Some(vehicle), index)
+ case None =>
+ (None, None)
+ }
+ case _ =>
+ (None, None)
+ }
+
+ /**
+ * If the player is seated in a vehicle, find that vehicle and get the seat index number at which the player is sat.
+ * @return a tuple consisting of a vehicle reference and a seat index
+ * if and only if the vehicle is known to this client and the `WorldSessioNActor`-global `player` occupies it;
+ * `(None, None)`, otherwise (even if the vehicle can be determined)
+ */
+ def GetVehicleAndSeat() : (Option[Vehicle], Option[Int]) =
+ continent.GUID(player.VehicleSeated) match {
+ case Some(vehicle : Vehicle) =>
+ vehicle.PassengerInSeat(player) match {
+ case index @ Some(_) =>
+ (Some(vehicle), index)
+ case None =>
+ (None, None)
+ }
+ case _ =>
+ (None, None)
+ }
+
+ /**
+ * Create an avatar character as if that avatar's player is mounted in a vehicle object's seat.
+ *
+ * This is a very specific configuration of the player character that is not visited very often.
+ * The value of `player.VehicleSeated` should be set to accommodate `Packet.DetailedConstructorData` and,
+ * though not explicitly checked,
+ * should be the same as the globally unique identifier that is assigned to the `vehicle` parameter for the current zone.
+ * The priority of this function is consider "initial" so it introduces the avatar to the game world in this state
+ * and is permitted to introduce the avatar to the vehicle's internal settings in a similar way.
+ * @see `AccessContents`
+ * @see `UpdateWeaponAtSeatPosition`
+ * @param tplayer the player avatar seated in the vehicle's seat
+ * @param vehicle the vehicle the player is driving
+ * @param seat the seat index
+ */
+ def AvatarCreateInVehicle(tplayer : Player, vehicle : Vehicle, seat : Int) : Unit = {
+ val pdef = tplayer.Definition
+ val guid = player.GUID
+ val parent = ObjectCreateMessageParent(vehicle.GUID, seat)
+ val data = pdef.Packet.DetailedConstructorData(player).get
+ sendResponse(
+ ObjectCreateDetailedMessage(
+ pdef.ObjectId,
+ guid,
+ parent,
+ data
+ )
+ )
+ avatarService ! AvatarServiceMessage(vehicle.Continent, AvatarAction.LoadPlayer(guid, pdef.ObjectId, guid, pdef.Packet.ConstructorData(player).get, Some(parent)))
+ AccessContents(vehicle)
+ UpdateWeaponAtSeatPosition(vehicle, seat)
+ log.info(s"AvatarCreateInVehicle: $guid -> $data")
}
/**
@@ -6187,7 +6660,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
/**
- * Remove items from a deceased player that is not expected to be found on a corpse.
+ * Remove items from a deceased player that are not expected to be found on a corpse.
* Most all players have their melee slot knife (which can not be un-equipped normally) removed.
* MAX's have their primary weapon in the designated slot removed.
* @param obj the player to be turned into a corpse
@@ -6264,21 +6737,30 @@ class WorldSessionActor extends Actor with MDCContextAware {
/**
* Attempt to tranfer to the player's faction-specific sanctuary continent.
- * If the server thinks the player is already on his sanctuary continent,
+ * If the server thinks the player is already on his sanctuary continent, and dead,
* it will disconnect the player under the assumption that an error has occurred.
* Eventually, this functionality should support better error-handling before it jumps to the conclusion:
* "Disconnecting the client is the safest option."
* @see `Zones.SanctuaryZoneNumber`
* @param tplayer the player
- * @param currentZone the current cone number
+ * @param currentZone the current zone number
*/
def RequestSanctuaryZoneSpawn(tplayer : Player, currentZone : Int) : Unit = {
val sanctNumber = Zones.SanctuaryZoneNumber(tplayer.Faction)
if(currentZone == sanctNumber) {
- sendResponse(DisconnectMessage("Player failed to load on faction's sanctuary continent. Please relog."))
+ if(!player.isAlive) {
+ sendResponse(DisconnectMessage("Player failed to load on faction's sanctuary continent. Please relog."))
+ }
+ //we are already on sanctuary, alive; what more is there to do?
}
else {
- cluster ! Zone.Lattice.RequestSpawnPoint(sanctNumber, tplayer, 7)
+ continent.GUID(player.VehicleSeated) match {
+ case Some(_ : Vehicle) =>
+ cluster ! Zone.Lattice.RequestSpawnPoint(sanctNumber, tplayer, 12) //warp gates
+ case None =>
+ cluster ! Zone.Lattice.RequestSpawnPoint(sanctNumber, tplayer, 7) //player character spawns
+ case _ =>
+ }
}
}
@@ -6378,7 +6860,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
/**
- *
+ * na
*/
def ForgetAllProximityTerminals(term_guid : PlanetSideGUID) : Unit = {
if(usingMedicalTerminal.contains(term_guid)) {
@@ -6776,7 +7258,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
* They do not havwe to be redrawn to stay accurate.
* Upon leaving a zone, where the icons are erased, and returning back to the zone, where they are drawn again,
* the deployables that a player owned should be restored in terms of their map icon visibility.
- * TThis control can not be recovered, however, until they are updated with the player's globally unique identifier.
+ * This control can not be recovered, however, until they are updated with the player's globally unique identifier.
* Since the player does not need to redraw his own deployable icons each time he respawns,
* but will not possess a valid GUID for that zone until he spawns in it at least once,
* this function is swapped with another after the first spawn in any given zone.
@@ -7281,11 +7763,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
/**
- * Common behavior for a player who:
+ * The starting point of behavior for a player who:
* is dead and is respawning;
- * is deconstructing at a spawn tube and is respawning; or,
- * either of the previous conditions, but the final result involves changing what zone the player occupies.
- * This route is not taken when first spawning, unless special conditions need to be satisfied.
+ * is deconstructing at a spawn tube and is respawning;
+ * is using a warp gate; or,
+ * any or none of the previous conditions, but the final result involves changing what zone the player occupies.
+ * This route is not taken when first spawning in the game world, unless special conditions need to be satisfied.
+ * The visible result will be apparent by the respawn timer being displayed to the client over the deployment map.
*
* Two choices must be independently made to complete this part of the process.
* The first choice ivolves the state of the player who is spawning
@@ -7296,10 +7780,16 @@ class WorldSessionActor extends Actor with MDCContextAware {
* for obtaining a completely new globally unique identifier,
* though the new identifier belongs to the new zone rather than the previous (still current) one.
* The second choice is satisfied by respawning in the same zone while still in a state of still being alive.
- * In this singulkar case, the player retains his previous globally unique identifier.
- * In all other cases, as indicated, a new globally unique identifier is selected.
- * @see `AvatarDeadStateMessage`
- * `RespawnClone`
+ * In this singular case, the player retains his previous globally unique identifier.
+ * In all other cases, as indicated, a new globally unique identifier is selected.
+ *
+ * If the player is alive and mounted in a vehicle, a different can of worms is produced.
+ * The ramifications of these conditions are not fully satisfied until the player loads into the new zone.
+ * Even then, the conclusion becomes delayed while a slightly lagged mechanism hoists players between zones.
+ * @see `AvatarDeadStateMessage`
+ * @see `interstellarFerry`
+ * @see `LoadZoneAsPlayer`
+ * @see `LoadZoneInVehicle`
* @param zone_id the zone in which the player will be placed
* @param pos the game world coordinates where the player will be positioned
* @param ori the direction in which the player will be oriented
@@ -7307,27 +7797,60 @@ class WorldSessionActor extends Actor with MDCContextAware {
* does not factor in any time required for loading zone or game objects
*/
def LoadZonePhysicalSpawnPoint(zone_id : String, pos : Vector3, ori : Vector3, respawnTime : Long) : Unit = {
+ log.info(s"Load in zone $zone_id at position $pos")
respawnTimer.cancel
reviveTimer.cancel
- ClearCurrentAmsSpawnPoint()
val backpack = player.isBackpack
val respawnTimeMillis = respawnTime * 1000 //ms
deadState = DeadState.RespawnTime
sendResponse(AvatarDeadStateMessage(DeadState.RespawnTime, respawnTimeMillis, respawnTimeMillis, Vector3.Zero, player.Faction, true))
- val tplayer = if(backpack) {
- RespawnClone(player) //new player
+ val (target, msg) = if(backpack) { //if the player is dead, he is handled as dead infantry, even if he died in a vehicle
+ //new player is spawning
+ val newPlayer = RespawnClone(player)
+ newPlayer.Position = pos
+ newPlayer.Orientation = ori
+ LoadZoneAsPlayer(newPlayer, zone_id)
}
else {
- val player_guid = player.GUID
- sendResponse(ObjectDeleteMessage(player_guid, 4))
- avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, player_guid, 4))
- player //player is deconstructing self
- }
+ interstellarFerry.orElse(continent.GUID(player.VehicleSeated)) match {
+ case Some(vehicle : Vehicle) => //driver or passenger in vehicle using a warp gate
+ LoadZoneInVehicle(vehicle, pos, ori, zone_id)
- tplayer.Position = pos
- tplayer.Orientation = ori
- val (target, msg) : (ActorRef, Any) = if(zone_id == continent.Id) {
- if(backpack) {
+ case _ => //player is deconstructing self
+ val player_guid = player.GUID
+ sendResponse(ObjectDeleteMessage(player_guid, 4))
+ avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, player_guid, 4))
+ player.Position = pos
+ player.Orientation = ori
+ LoadZoneAsPlayer(player, zone_id)
+ }
+ }
+ import scala.concurrent.ExecutionContext.Implicits.global
+ respawnTimer = context.system.scheduler.scheduleOnce(respawnTime seconds, target, msg)
+ }
+
+ /**
+ * Deal with a target player as free-standing infantry in the course of a redeployment action to a target continent
+ * whether that action is the result of a deconstruction (reconstruction), a death (respawning),
+ * or other position shifting action handled directly by the server.
+ *
+ * The two important vectors are still whether the zone being transported to is the same or is different
+ * and whether the target player is alive or released (note: not just "dead" ...).
+ * @see `LoadZoneCommonTransferActivity`
+ * @see `GUIDTask.UnregisterAvatar`
+ * @see `GUIDTask.UnregisterLocker`
+ * @see `PlayerLoaded`
+ * @see `Player.isBackpack`
+ * @see `RegisterAvatar`
+ * @see `TaskBeforeZoneChange`
+ * @param tplayer the target player being moved around;
+ * not necessarily the same player as the `WorldSessionActor`-global `player`
+ * @param zone_id the zone in which the player will be placed
+ * @return a tuple composed of an ActorRef` destination and a message to send to that destination
+ */
+ def LoadZoneAsPlayer(tplayer : Player, zone_id : String) : (ActorRef, Any) = {
+ if(zone_id == continent.Id) {
+ if(player.isBackpack) { //important! test the actor-wide player ref, not the parameter
//respawning from unregistered player
(taskResolver, RegisterAvatar(tplayer))
}
@@ -7337,17 +7860,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
}
else {
+ LoadZoneCommonTransferActivity()
val original = player
- //release constraints from former zone; vehicle ownership, and deployable ownership, etc..
- DisownVehicle()
- RemoveBoomerTriggersFromInventory().foreach(obj => {
- taskResolver ! GUIDTask.UnregisterObjectTask(obj)(continent.GUID)
- })
- DisownDeployables()
- drawDeloyableIcon = RedrawDeployableIcons //important for when SetCurrentAvatar initializes the UI next zone
- continent.Population ! Zone.Population.Leave(avatar)
- //TODO check player orientation upon spawn not polluted
- if(backpack) {
+ if(tplayer.isBackpack) {
//unregister avatar locker + GiveWorld
player = tplayer
(taskResolver, TaskBeforeZoneChange(GUIDTask.UnregisterLocker(original.Locker)(continent.GUID), zone_id))
@@ -7357,8 +7872,241 @@ class WorldSessionActor extends Actor with MDCContextAware {
(taskResolver, TaskBeforeZoneChange(GUIDTask.UnregisterAvatar(original)(continent.GUID), zone_id))
}
}
- import scala.concurrent.ExecutionContext.Implicits.global
- respawnTimer = context.system.scheduler.scheduleOnce(respawnTime seconds, target, msg)
+ }
+
+ /**
+ * Deal with a target player as a vehicle occupant in the course of a redeployment action to a target continent
+ * whether that action is the result of a deconstruction (reconstruction)
+ * or other position shifting action handled directly by the server.
+ *
+ * The original target player must be alive and the only consideration is in what position the player is mounted in the vehicle.
+ * Any seated position that isn't the driver is a passenger.
+ * The most important role performed in this function is to declare a reference to the vehicle itsself
+ * since no other connection from the player to the vehicle is guaranteed to persist in a meaningful way during the transfer.
+ * @see `interstellarFerry`
+ * @see `LoadZoneInVehicleAsDriver`
+ * @see `LoadZoneInVehicleAsPassenger`
+ * @see `Vehicle.PassengerInSeat`
+ * @param vehicle the target vehicle being moved around;
+ * WILL necessarily be the same vehicles as is controlled by the `WorldSessionActor`-global `player`
+ * @param pos the game world coordinates where the vehicle will be positioned
+ * @param ori the direction in which the vehicle will be oriented
+ * @param zone_id the zone in which the vehicle and driver will be placed,
+ * or in which the vehicle has already been placed
+ * @return a tuple composed of an ActorRef` destination and a message to send to that destination
+ **/
+ def LoadZoneInVehicle(vehicle : Vehicle, pos : Vector3, ori : Vector3, zone_id : String) : (ActorRef, Any) = {
+ interstellarFerry = Some(vehicle)
+ if(vehicle.PassengerInSeat(player).contains(0)) {
+ vehicle.Position = pos
+ vehicle.Orientation = ori
+ LoadZoneInVehicleAsDriver(vehicle, zone_id)
+ }
+ else {
+ LoadZoneInVehicleAsPassenger(vehicle, zone_id)
+ }
+ }
+
+ /**
+ * Deal with a target player as a vehicle driver in the course of a redeployment action to a target continent
+ * whether that action is the result of a deconstruction (reconstruction)
+ * or other position shifting action handled directly by the server.
+ *
+ * During a vehicle transfer, whether to the same zone or to a different zone,
+ * the driver has the important task of ensuring the certain safety of his passengers during transport.
+ * The driver must modify the conditions of the vehicle's passengers common communication channel
+ * originally determined entirely by the vehicle's soon-to-be blanked internal `Actor` object.
+ * Any cargo vehicles under the control of the target vehicle must also be made aware of the current state of the process.
+ * In the case of a series of ferrying vehicles and cargo vehicles,
+ * the vehicle to be deleted might not be the one immediately mounted.
+ * A reference to the top-level ferrying vehicle's former globally unique identifier has been retained for this purpose.
+ * This vehicle can be deleted for everyone if no more work can be detected.
+ * @see `interstellarFerryTopLevelGUID`
+ * @see `LoadZoneCommonTransferActivity`
+ * @see `PlayerLoaded`
+ * @see `TaskBeforeZoneChange`
+ * @see `UnAccessContents`
+ * @see `UnregisterDrivenVehicle`
+ * @param vehicle the target vehicle being moved around;
+ * WILL necessarily be the same vehicles as is controlled by the `WorldSessionActor`-global `player`
+ * @param zone_id the zone in which the vehicle and driver will be placed,
+ * or in which the vehicle has already been placed
+ * @return a tuple composed of an ActorRef` destination and a message to send to that destination
+ **/
+ def LoadZoneInVehicleAsDriver(vehicle : Vehicle, zone_id : String) : (ActorRef, Any) = {
+ log.info(s"LoadZoneInVehicleAsDriver: ${player.Name} is driving a ${vehicle.Definition.Name}")
+ val pguid = player.GUID
+ val toChannel = TransportVehicleChannelName(vehicle)
+ //standard passengers
+ vehicleService ! VehicleServiceMessage(s"${vehicle.Actor}", VehicleAction.TransferPassengerChannel(pguid, s"${vehicle.Actor}", toChannel, vehicle))
+ //cargo
+ val occupiedCargoHolds = vehicle.CargoHolds.values.collect {
+ case hold if hold.isOccupied =>
+ hold.Occupant.get
+ }
+ occupiedCargoHolds.foreach{ cargo =>
+ cargo.Seat(0) match {
+ case Some(seat) if seat.isOccupied =>
+ vehicleService ! VehicleServiceMessage(s"${seat.Occupant.get.Name}", VehicleAction.TransferPassengerChannel(pguid, s"${cargo.Actor}", toChannel, cargo))
+ case _ =>
+ log.error("LoadZoneInVehicleAsDriver: abort; vehicle in cargo hold missing driver")
+ SpecialCaseVehicleDespawn(player, cargo)
+ }
+ }
+ //
+ if(zone_id == continent.Id) {
+ //transferring a vehicle between spawn points (warp gates) in the same zone
+ //LoadZoneTransferPassengerMessages(pguid, zone_id, toChannel, vehicle, PlanetSideGUID(0))
+ (self, PlayerLoaded(player))
+ }
+ else {
+ UnAccessContents(vehicle)
+ LoadZoneCommonTransferActivity()
+ player.VehicleSeated = vehicle.GUID
+ player.Continent = zone_id //forward-set the continent id to perform a test
+ interstellarFerryTopLevelGUID = (if(vehicle.Seats.values.count(_.isOccupied) == 1 && occupiedCargoHolds.size == 0) {
+ //do not delete if vehicle has passengers or cargo
+ val vehicleToDelete = interstellarFerryTopLevelGUID.orElse(player.VehicleSeated).getOrElse(PlanetSideGUID(0))
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.UnloadVehicle(pguid, continent, vehicle, vehicleToDelete))
+ None
+ }
+ else {
+ interstellarFerryTopLevelGUID.orElse(Some(vehicle.GUID))
+ })
+ //unregister vehicle and driver whole + GiveWorld
+ continent.Transport ! Zone.Vehicle.Despawn(vehicle)
+ (taskResolver, TaskBeforeZoneChange(UnregisterDrivenVehicle(vehicle, player), zone_id))
+ }
+ }
+
+ /**
+ * The channel name for summoning passengers to the vehicle
+ * after it has been loaded to a new location or to a new zone.
+ * This channel name should be unique to the vehicle for at least the duration of the transition.
+ * The vehicle-specific channel with which all passengers are coordinated back to the original vehicle.
+ * @param vehicle the vehicle being moved (or having been moved)
+ * @return the channel name
+ */
+ def TransportVehicleChannelName(vehicle : Vehicle) : String = {
+ s"transport-vehicle-channel-${interstellarFerryTopLevelGUID.getOrElse(vehicle.GUID).guid}"
+ }
+
+ /**
+ * Deal with a target player as a vehicle passenger in the course of a redeployment action to a target continent
+ * whether that action is the result of a deconstruction (reconstruction)
+ * or other position shifting action handled directly by the server.
+ *
+ * The way a vehicle is handled in reference to being a passenger
+ * is very similar to how an infantry player is handled in the same process.
+ * If this player is the last person who requires a zone change
+ * which is the concluding zone transfer of what might have been a long chain of vehicle and passengers
+ * then that player is responsible for deleting the vehicle for other players of the previous zone.
+ * In the case of a series of ferrying vehicles and cargo vehicles,
+ * the vehicle to be deleted might not be the one immediately mounted.
+ * A reference to the top-level ferrying vehicle's former globally unique identifier has been retained for this purpose.
+ * This vehicle can be deleted for everyone if no more work can be detected.
+ * @see `GUIDTask.UnregisterAvatar`
+ * @see `LoadZoneCommonTransferActivity`
+ * @see `NoVehicleOccupantsInZone`
+ * @see `PlayerLoaded`
+ * @see `TaskBeforeZoneChange`
+ * @see `UnAccessContents`
+ * @param vehicle the target vehicle being moved around
+ * @param zone_id the zone in which the vehicle and driver will be placed
+ * @return a tuple composed of an ActorRef` destination and a message to send to that destination
+ **/
+ def LoadZoneInVehicleAsPassenger(vehicle : Vehicle, zone_id : String) : (ActorRef, Any) = {
+ log.info(s"LoadZoneInVehicleAsPassenger: ${player.Name} is the passenger of a ${vehicle.Definition.Name}")
+ if(zone_id == continent.Id) {
+ //transferring a vehicle between spawn points (warp gates) in the same zone
+ (self, PlayerLoaded(player))
+ }
+ else {
+ LoadZoneCommonTransferActivity()
+ player.VehicleSeated = vehicle.GUID
+ player.Continent = zone_id //forward-set the continent id to perform a test
+ val continentId = continent.Id
+ if(NoVehicleOccupantsInZone(vehicle, continentId)) {
+ //do not dispatch delete action if any hierarchical occupant has not gotten this far through the summoning process
+ val vehicleToDelete = interstellarFerryTopLevelGUID.orElse(player.VehicleSeated).getOrElse(PlanetSideGUID(0))
+ vehicleService ! VehicleServiceMessage(continentId, VehicleAction.UnloadVehicle(player.GUID, continent, vehicle, vehicleToDelete))
+ }
+ interstellarFerryTopLevelGUID = None
+ //unregister avatar + GiveWorld
+ (taskResolver, TaskBeforeZoneChange(GUIDTask.UnregisterAvatar(player)(continent.GUID), zone_id))
+ }
+ }
+
+ /**
+ * A recursive test that explores all the seats of a target vehicle
+ * and all the seats of any discovered cargo vehicles
+ * and then the same criteria in those cargo vehicles
+ * to determine if any of their combined passenger roster remains in a given zone.
+ *
+ * While it should be possible to recursively explore up a parent-child relationship -
+ * testing the ferrying vehicle to which of the current tested vehicle in consider a cargo vehicle -
+ * the relationship expressed is one of globally unique refertences and not one of object references -
+ * that suggested super-ferrying vehicle may not exist in the zone unless special considerations are imposed.
+ * For the purpose of these special considerations,
+ * implemented by enforcing a strictly downwards order of vehicular zone transportation,
+ * where drivers move vehicles and call passengers and immediate cargo vehicle drivers,
+ * it becomes unnecessary to test any vehicle that might be ferrying the target vehicle.
+ * @see `ZoneAware`
+ * @param vehicle the target vehicle being moved around
+ * @param zone_id the zone in which the vehicle and its passengers should not be located
+ * @return `true`, if all passengers of the vehicle, and its cargo vehicles, etc., have reported being moved from the zone;
+ * `false`, otherwise
+ */
+ def NoVehicleOccupantsInZone(vehicle : Vehicle, zoneId : String) : Boolean = {
+ (vehicle.Seats.values
+ .collect { case seat if seat.isOccupied && seat.Occupant.get.Continent == zoneId => true }
+ .isEmpty) &&
+ {
+ vehicle.CargoHolds.values
+ .collect {
+ case hold if hold.isOccupied =>
+ hold.Occupant.get
+ }
+ .foldLeft(true)(_ && NoVehicleOccupantsInZone(_, zoneId))
+ }
+ }
+
+ /**
+ * Dispatch messages to all target players in immediate passenger and gunner seats
+ * and to the driver of all vehicles in cargo holds
+ * that their current ferrying vehicle is being transported from one zone to the next
+ * and that they should follow after it.
+ * The messages address the avatar of their recipient `WorldSessionActor` objects.
+ * @param player_guid the driver of the target vehicle
+ * @param toZoneId the zone where the target vehicle will be moved
+ * @param toChannel the vehicle-specific channel with which all passengers are coordinated to the vehicle
+ * @param vehicle the vehicle (object)
+ * @param vehicleToDelete the vehicle as it was identified in the zone that it is being moved from
+ */
+ def LoadZoneTransferPassengerMessages(player_guid : PlanetSideGUID, toZoneId : String, toChannel : String, vehicle : Vehicle, vehicleToDelete : PlanetSideGUID) : Unit = {
+ vehicleService ! VehicleServiceMessage(toChannel, VehicleAction.TransferPassenger(player_guid, toChannel, vehicle, vehicleToDelete))
+ vehicle.CargoHolds.values
+ .collect {
+ case hold if hold.isOccupied =>
+ val cargo = hold.Occupant.get
+ cargo.Continent = toZoneId
+ //point to the cargo vehicle to instigate cargo vehicle driver transportation
+ vehicleService ! VehicleServiceMessage(toChannel, VehicleAction.TransferPassenger(player_guid, toChannel, cargo, vehicleToDelete))
+ }
+ }
+
+ /**
+ * Common behavior when transferring between zones
+ * encompassing actions that disassociate the player with entities they left (will leave) in the previous zone.
+ * It also sets up actions for the new zone loading process.
+ */
+ def LoadZoneCommonTransferActivity() : Unit = {
+ RemoveBoomerTriggersFromInventory().foreach(obj => {
+ taskResolver ! GUIDTask.UnregisterObjectTask(obj)(continent.GUID)
+ })
+ DisownDeployables()
+ drawDeloyableIcon = RedrawDeployableIcons //important for when SetCurrentAvatar initializes the UI next zone
+ continent.Population ! Zone.Population.Leave(avatar)
}
/**
@@ -7606,7 +8354,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
/**
* na
- * @param player_guid the player that ...
+ * @param player_guid the target player
* @param cargoGUID the globally unique number for the vehicle being ferried
* @param cargo the vehicle being ferried
* @param carrierGUID the globally unique number for the vehicle doing the ferrying
@@ -7618,56 +8366,65 @@ class WorldSessionActor extends Actor with MDCContextAware {
def HandleDismountVehicleCargo(player_guid : PlanetSideGUID, cargoGUID : PlanetSideGUID, cargo : Vehicle, carrierGUID : PlanetSideGUID, carrier : Vehicle, bailed : Boolean, requestedByPassenger : Boolean, kicked : Boolean) : Unit = {
carrier.CargoHolds.find({case((_, hold)) => hold.Occupant.contains(cargo)}) match {
case Some((mountPoint, hold)) =>
- StartBundlingPackets()
- val cargoStatusMessage = CargoMountPointStatusMessage(cargoGUID, PlanetSideGUID(0), PlanetSideGUID(0), carrierGUID, mountPoint, CargoStatus.InProgress, 0)
- log.debug(cargoStatusMessage.toString)
- sendResponse(cargoStatusMessage) //dismount vehicle on UI and disable "shield" effect on lodestar
- val dismount_position = if(bailed || kicked) { //if we're bailing drop the vehicle below the cargo vehicle
- //TODO: ensure vehicles aren't dropped below the world
- cargo.Position - Vector3.z(1)
- }
- else if(cargo.Definition == GlobalDefinitions.dropship) { //the galaxy cargo bay is offset backwards from the center of the vehicle
- Vector3(cargo.Position.x, cargo.Position.y - 7f, cargo.Position.z + 2f)
- }
- else {
- cargo.Position + Vector3.z(2)
- }
- //TODO: BFRs will likely also need this set
- val sideways = cargo.Definition == GlobalDefinitions.router
- val rotation = if(sideways) {
- (cargo.Orientation.z - 90) % 360 //dismount router "sideways" in a lodestar
- }
- else {
- cargo.Orientation.z
- }
- val detachMessage = ObjectDetachMessage(carrierGUID, cargoGUID, dismount_position, carrier.Orientation.x, carrier.Orientation.y, rotation)
- log.debug(detachMessage.toString)
- sendResponse(detachMessage)
- vehicleService ! VehicleServiceMessage(s"${cargo.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargoGUID, 0, cargo.Health)))
- vehicleService ! VehicleServiceMessage(s"${cargo.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargoGUID, 68, cargo.Shields)))
cargo.MountedIn = None
hold.Occupant = None
- if(!bailed) {
- // Automatically drive the vehicle backwards out of the cargo bay
- if(!sideways) {
- ServerVehicleLockReverse()
- }
- else {
- ServerVehicleLockStrafeLeft()
- }
+ val rotation : Vector3 = if(CargoOrientation(cargo) == 1) { //TODO: BFRs will likely also need this set
+ //dismount router "sideways" in a lodestar
+ carrier.Orientation.xy + Vector3.z((carrier.Orientation.z - 90) % 360)
}
else {
- //todo: proper vehicle bailing. It works currently but when collision damage is implemented the vehicle will take damage if not in a bail state. Need to confirm how this is done with further research
+ carrier.Orientation
+ }
+ val cargoHoldPosition : Vector3 = if(carrier.Definition == GlobalDefinitions.dropship) {
+ //the galaxy cargo bay is offset backwards from the center of the vehicle
+ carrier.Position + Vector3.Rz(Vector3(0, 7, 0), math.toRadians(carrier.Orientation.z))
+ }
+ else {
+ //the lodestar's cargo hold is almost the center of the vehicle
+ carrier.Position
+ }
+ StartBundlingPackets()
+ vehicleService ! VehicleServiceMessage(s"${cargo.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargoGUID, 0, cargo.Health)))
+ vehicleService ! VehicleServiceMessage(s"${cargo.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargoGUID, 68, cargo.Shields)))
+ if(carrier.Flying) {
+ //the carrier vehicle is flying; eject the cargo vehicle
+ val ejectCargoMsg = CargoMountPointStatusMessage(carrierGUID, PlanetSideGUID(0), PlanetSideGUID(0), cargoGUID, mountPoint, CargoStatus.InProgress, 0)
+ val detachCargoMsg = ObjectDetachMessage(carrierGUID, cargoGUID, cargoHoldPosition - Vector3.z(1), rotation)
+ val resetCargoMsg = CargoMountPointStatusMessage(carrierGUID, PlanetSideGUID(0), PlanetSideGUID(0), cargoGUID, mountPoint, CargoStatus.Empty, 0)
+ sendResponse(ejectCargoMsg) //dismount vehicle on UI and disable "shield" effect on lodestar
+ sendResponse(detachCargoMsg)
+ avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player_guid, ejectCargoMsg))
+ avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player_guid, detachCargoMsg))
+ avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(PlanetSideGUID(0), resetCargoMsg)) //lazy
+ log.debug(ejectCargoMsg.toString)
+ log.debug(detachCargoMsg.toString)
+ }
+ else {
+ //the carrier vehicle is not flying; just open the door and let the cargo vehicle back out; force it out if necessary
+ val cargoStatusMessage = CargoMountPointStatusMessage(carrierGUID, PlanetSideGUID(0), cargoGUID, PlanetSideGUID(0), mountPoint, CargoStatus.InProgress, 0)
+ val cargoDetachMessage = ObjectDetachMessage(carrierGUID, cargoGUID, cargoHoldPosition + Vector3.z(1f), rotation)
+ sendResponse(cargoStatusMessage)
+ sendResponse(cargoDetachMessage)
+ avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player_guid, cargoStatusMessage))
+ avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player_guid, cargoDetachMessage))
+ if(kicked) {
+ cargo.Seat(0).get.Occupant match {
+ case Some(driver) =>
+ vehicleService ! VehicleServiceMessage(s"${driver.Name}", VehicleAction.KickCargo(player_guid, cargo, cargo.Definition.AutoPilotSpeed2))
+ case None =>
+ //driverless vehicle will get cleaned up
+ }
+ }
+ import scala.concurrent.duration._
+ import scala.concurrent.ExecutionContext.Implicits.global
+ //check every quarter second if the vehicle has moved far enough away to be considered dismounted
+ cargoDismountTimer.cancel
+ cargoDismountTimer = context.system.scheduler.scheduleOnce(250 milliseconds, self, CheckCargoDismount(cargoGUID, carrierGUID, mountPoint, iteration = 0))
}
- import scala.concurrent.duration._
- import scala.concurrent.ExecutionContext.Implicits.global
- // Start a timer to check every second if the vehicle has moved far enough away to be considered dismounted, and then close the cargo door
- cargoDismountTimer = context.system.scheduler.scheduleOnce(250 milliseconds, self, CheckCargoDismount(cargoGUID, carrierGUID, mountPoint, iteration = 0))
StopBundlingPackets()
- //sync to other clients
- avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, cargoStatusMessage))
- avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, detachMessage))
- case None => ;
+
+ case None =>
+ log.warn(s"HandleDismountVehicleCargo: can not locate cargo $cargo in any hold of the carrier vehicle $carrier")
}
}
@@ -7697,6 +8454,82 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
}
+ /**
+ * Make this client display the deployment map, and all its available destination spawn points.
+ * @see `AvatarDeadStateMessage`
+ * @see `DeadState.Release`
+ * @see `Player.Release`
+ */
+ def GoToDeploymentMap() : Unit = {
+ player.Release
+ deadState = DeadState.Release
+ sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
+ DrawCurrentAmsSpawnPoint()
+ }
+
+ /**
+ * From a seat, find the weapon controlled from it, and update the ammunition counts for that weapon's magazines.
+ * @param objWithSeat the object that owns seats (and weaponry)
+ * @param seatNum the seat
+ */
+ def UpdateWeaponAtSeatPosition(objWithSeat : MountedWeapons, seatNum : Int) : Unit = {
+ objWithSeat.WeaponControlledFromSeat(seatNum) match {
+ case Some(weapon : Tool) =>
+ //update mounted weapon belonging to seat
+ weapon.AmmoSlots.foreach(slot => {
+ //update the magazine(s) in the weapon, specifically
+ val magazine = slot.Box
+ sendResponse(InventoryStateMessage(magazine.GUID, weapon.GUID, magazine.Capacity.toLong))
+ })
+ case _ => ; //no weapons to update
+ }
+ }
+
+ /**
+ * Given an origin and a destination, determine how long the process of traveling should take in reconstruction time.
+ * For most destinations, the unit of receiving ("spawn point") determines the reconstruction time.
+ * In a special consideration, travel from any sanctuary or sanctuary-special zone should be as immediate as zone loading.
+ * @param toZoneId the zone where the target is headed
+ * @param toSpawnPoint the unit the target is using as a destination
+ * @param fromZoneId the zone where the target current is located
+ * @return how long in seconds the spawning process will take
+ */
+ def CountSpawnDelay(toZoneId : String, toSpawnPoint : SpawnPoint, fromZoneId : String) : Long = {
+ val sanctuaryZoneId = Zones.SanctuaryZoneId(player.Faction)
+ if(sanctuaryZoneId.equals(fromZoneId)) { //TODO includes traveing zones
+ 0L
+ }
+ else if(sanctuaryZoneId.equals(toZoneId)) {
+ 10L
+ }
+ else if(!player.isAlive) {
+ toSpawnPoint.Definition.Delay //TODO +cumulative death penalty
+ }
+ else {
+ toSpawnPoint.Definition.Delay
+ }
+ }
+
+ /**
+ * In the background, a list of advanced mobile spawn vehicles that are deployed in the zone is being updated constantly.
+ * Select, from this list, the AMS that is closest to the player's current or last position
+ * and draw its spawn selection icon onto the deployment map.
+ * @see `BindPlayerMessage`
+ * @see `DeadState.Release`
+ */
+ def DrawCurrentAmsSpawnPoint() : Unit = {
+ if(deadState == DeadState.Release) {
+ amsSpawnPoints
+ .sortBy(tube => Vector3.DistanceSquared(tube.Position, player.Position))
+ .headOption match {
+ case Some(tube) =>
+ sendResponse(BindPlayerMessage(BindStatus.Available, "@ams", true, false, SpawnGroup.AMS, continent.Number, 5, tube.Position))
+ case None =>
+ sendResponse(BindPlayerMessage(BindStatus.Unavailable, "@ams", false, false, SpawnGroup.AMS, continent.Number, 0, Vector3.Zero))
+ }
+ }
+ }
+
def failWithError(error : String) = {
log.error(error)
sendResponse(ConnectionClose())
diff --git a/pslogin/src/main/scala/Zones.scala b/pslogin/src/main/scala/Zones.scala
index 52c3b141..3b959866 100644
--- a/pslogin/src/main/scala/Zones.scala
+++ b/pslogin/src/main/scala/Zones.scala
@@ -1,7 +1,8 @@
// Copyright (c) 2017 PSForever
import akka.actor.ActorContext
-import net.psforever.objects.serverobject.pad.VehicleSpawnPad
-import net.psforever.objects.serverobject.pad.process._
+import net.psforever.objects.GlobalDefinitions
+import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
+import net.psforever.objects.serverobject.structures.WarpGate
import net.psforever.objects.zones.Zone
import net.psforever.types.PlanetSideEmpire
@@ -16,67 +17,74 @@ object Zones {
override def Init(implicit context : ActorContext) : Unit = {
super.Init(context)
- BuildingByMapId(5).Faction = PlanetSideEmpire.TR //Akkan
- BuildingByMapId(6).Faction = PlanetSideEmpire.TR //Baal
- BuildingByMapId(7).Faction = PlanetSideEmpire.TR //Dagon
- BuildingByMapId(8).Faction = PlanetSideEmpire.NC //Enkidu
- BuildingByMapId(9).Faction = PlanetSideEmpire.VS //Girru
- BuildingByMapId(10).Faction = PlanetSideEmpire.VS //Hanish
- BuildingByMapId(11).Faction = PlanetSideEmpire.VS //Irkalla
- BuildingByMapId(12).Faction = PlanetSideEmpire.VS //Kusag
- BuildingByMapId(13).Faction = PlanetSideEmpire.VS //Lahar
- BuildingByMapId(14).Faction = PlanetSideEmpire.NC //Marduk
- BuildingByMapId(15).Faction = PlanetSideEmpire.NC //Neti
- BuildingByMapId(16).Faction = PlanetSideEmpire.NC //Zaqar
- BuildingByMapId(17).Faction = PlanetSideEmpire.NC //S_Marduk_Tower
- BuildingByMapId(18).Faction = PlanetSideEmpire.NC //W_Neti_Tower
- BuildingByMapId(19).Faction = PlanetSideEmpire.NC //W_Zaqar_Tower
- BuildingByMapId(20).Faction = PlanetSideEmpire.NC //E_Zaqar_Tower
- BuildingByMapId(21).Faction = PlanetSideEmpire.NC //NE_Neti_Tower
- BuildingByMapId(22).Faction = PlanetSideEmpire.NC //SE_Ceryshen_Warpgate_Tower
- BuildingByMapId(23).Faction = PlanetSideEmpire.VS //S_Kusag_Tower
- BuildingByMapId(24).Faction = PlanetSideEmpire.VS //NW_Kusag_Tower
- BuildingByMapId(25).Faction = PlanetSideEmpire.VS //N_Ceryshen_Warpgate_Tower
- BuildingByMapId(26).Faction = PlanetSideEmpire.VS //SE_Irkalla_Tower
- BuildingByMapId(27).Faction = PlanetSideEmpire.VS //S_Irkalla_Tower
- BuildingByMapId(28).Faction = PlanetSideEmpire.TR //NE_Enkidu_Tower
- BuildingByMapId(29).Faction = PlanetSideEmpire.NC //SE_Akkan_Tower
- BuildingByMapId(30).Faction = PlanetSideEmpire.NC //SW_Enkidu_Tower
- BuildingByMapId(31).Faction = PlanetSideEmpire.TR //E_Searhus_Warpgate_Tower
- BuildingByMapId(32).Faction = PlanetSideEmpire.TR //N_Searhus_Warpgate_Tower
- BuildingByMapId(33).Faction = PlanetSideEmpire.VS //E_Girru_Tower
- BuildingByMapId(34).Faction = PlanetSideEmpire.VS //SE_Hanish_Tower
- BuildingByMapId(35).Faction = PlanetSideEmpire.TR //SW_Hanish_Tower
- BuildingByMapId(36).Faction = PlanetSideEmpire.VS //W_Girru_Tower
- BuildingByMapId(37).Faction = PlanetSideEmpire.TR //E_Dagon_Tower
- BuildingByMapId(38).Faction = PlanetSideEmpire.TR //NE_Baal_Tower
- BuildingByMapId(39).Faction = PlanetSideEmpire.TR //SE_Baal_Tower
- BuildingByMapId(40).Faction = PlanetSideEmpire.TR //S_Dagon_Tower
- BuildingByMapId(41).Faction = PlanetSideEmpire.NC //W_Ceryshen_Warpgate_Tower
- BuildingByMapId(42).Faction = PlanetSideEmpire.NEUTRAL //dagon bunker
- BuildingByMapId(43).Faction = PlanetSideEmpire.NEUTRAL //Akkan North Bunker
- BuildingByMapId(44).Faction = PlanetSideEmpire.NEUTRAL //Enkidu East Bunker
- BuildingByMapId(45).Faction = PlanetSideEmpire.NEUTRAL //Neti bunker
- BuildingByMapId(46).Faction = PlanetSideEmpire.NEUTRAL //Hanish West Bunker
- BuildingByMapId(47).Faction = PlanetSideEmpire.NEUTRAL //Irkalla East Bunker
- BuildingByMapId(48).Faction = PlanetSideEmpire.NEUTRAL //Zaqar bunker
- BuildingByMapId(49).Faction = PlanetSideEmpire.NEUTRAL //Kusag West Bunker
- BuildingByMapId(50).Faction = PlanetSideEmpire.NEUTRAL //marduk bunker
- BuildingByMapId(51).Faction = PlanetSideEmpire.TR //baal bunker
- BuildingByMapId(52).Faction = PlanetSideEmpire.NEUTRAL //girru bunker
- BuildingByMapId(53).Faction = PlanetSideEmpire.NEUTRAL //lahar bunker
- BuildingByMapId(54).Faction = PlanetSideEmpire.NEUTRAL //akkan bunker
- BuildingByMapId(55).Faction = PlanetSideEmpire.VS //Irkalla_Tower
- BuildingByMapId(56).Faction = PlanetSideEmpire.VS //Hanish_Tower
- BuildingByMapId(57).Faction = PlanetSideEmpire.VS //E_Ceryshen_Warpgate_Tower
- BuildingByMapId(58).Faction = PlanetSideEmpire.VS //Lahar_Tower
- BuildingByMapId(59).Faction = PlanetSideEmpire.VS //VSSanc_Warpgate_Tower
- BuildingByMapId(60).Faction = PlanetSideEmpire.TR //Akkan_Tower
- BuildingByMapId(61).Faction = PlanetSideEmpire.NC //TRSanc_Warpgate_Tower
- BuildingByMapId(62).Faction = PlanetSideEmpire.NC //Marduk_Tower
- BuildingByMapId(63).Faction = PlanetSideEmpire.TR //NW_Dagon_Tower
- BuildingByMapId(64).Faction = PlanetSideEmpire.NEUTRAL //E7 East Bunker (at north from bridge)
- BuildingByMapId(65).Faction = PlanetSideEmpire.VS //W_Hanish_Tower
+ Buildings.values.flatMap {
+ _.Amenities.collect {
+ case amenity if amenity.Definition == GlobalDefinitions.resource_silo =>
+ val silo = amenity.asInstanceOf[ResourceSilo]
+ silo.ChargeLevel = silo.MaximumCharge
+ }
+ }
+ BuildingByMapId(5).get.Faction = PlanetSideEmpire.TR //Akkan
+ BuildingByMapId(6).get.Faction = PlanetSideEmpire.TR //Baal
+ BuildingByMapId(7).get.Faction = PlanetSideEmpire.TR //Dagon
+ BuildingByMapId(8).get.Faction = PlanetSideEmpire.NC //Enkidu
+ BuildingByMapId(9).get.Faction = PlanetSideEmpire.VS //Girru
+ BuildingByMapId(10).get.Faction = PlanetSideEmpire.VS //Hanish
+ BuildingByMapId(11).get.Faction = PlanetSideEmpire.VS //Irkalla
+ BuildingByMapId(12).get.Faction = PlanetSideEmpire.VS //Kusag
+ BuildingByMapId(13).get.Faction = PlanetSideEmpire.VS //Lahar
+ BuildingByMapId(14).get.Faction = PlanetSideEmpire.NC //Marduk
+ BuildingByMapId(15).get.Faction = PlanetSideEmpire.NC //Neti
+ BuildingByMapId(16).get.Faction = PlanetSideEmpire.NC //Zaqar
+ BuildingByMapId(17).get.Faction = PlanetSideEmpire.NC //S_Marduk_Tower
+ BuildingByMapId(18).get.Faction = PlanetSideEmpire.NC //W_Neti_Tower
+ BuildingByMapId(19).get.Faction = PlanetSideEmpire.NC //W_Zaqar_Tower
+ BuildingByMapId(20).get.Faction = PlanetSideEmpire.NC //E_Zaqar_Tower
+ BuildingByMapId(21).get.Faction = PlanetSideEmpire.NC //NE_Neti_Tower
+ BuildingByMapId(22).get.Faction = PlanetSideEmpire.NC //SE_Ceryshen_Warpgate_Tower
+ BuildingByMapId(23).get.Faction = PlanetSideEmpire.VS //S_Kusag_Tower
+ BuildingByMapId(24).get.Faction = PlanetSideEmpire.VS //NW_Kusag_Tower
+ BuildingByMapId(25).get.Faction = PlanetSideEmpire.VS //N_Ceryshen_Warpgate_Tower
+ BuildingByMapId(26).get.Faction = PlanetSideEmpire.VS //SE_Irkalla_Tower
+ BuildingByMapId(27).get.Faction = PlanetSideEmpire.VS //S_Irkalla_Tower
+ BuildingByMapId(28).get.Faction = PlanetSideEmpire.TR //NE_Enkidu_Tower
+ BuildingByMapId(29).get.Faction = PlanetSideEmpire.NC //SE_Akkan_Tower
+ BuildingByMapId(30).get.Faction = PlanetSideEmpire.NC //SW_Enkidu_Tower
+ BuildingByMapId(31).get.Faction = PlanetSideEmpire.TR //E_Searhus_Warpgate_Tower
+ BuildingByMapId(32).get.Faction = PlanetSideEmpire.TR //N_Searhus_Warpgate_Tower
+ BuildingByMapId(33).get.Faction = PlanetSideEmpire.VS //E_Girru_Tower
+ BuildingByMapId(34).get.Faction = PlanetSideEmpire.VS //SE_Hanish_Tower
+ BuildingByMapId(35).get.Faction = PlanetSideEmpire.TR //SW_Hanish_Tower
+ BuildingByMapId(36).get.Faction = PlanetSideEmpire.VS //W_Girru_Tower
+ BuildingByMapId(37).get.Faction = PlanetSideEmpire.TR //E_Dagon_Tower
+ BuildingByMapId(38).get.Faction = PlanetSideEmpire.TR //NE_Baal_Tower
+ BuildingByMapId(39).get.Faction = PlanetSideEmpire.TR //SE_Baal_Tower
+ BuildingByMapId(40).get.Faction = PlanetSideEmpire.TR //S_Dagon_Tower
+ BuildingByMapId(41).get.Faction = PlanetSideEmpire.NC //W_Ceryshen_Warpgate_Tower
+ BuildingByMapId(42).get.Faction = PlanetSideEmpire.NEUTRAL //dagon bunker
+ BuildingByMapId(43).get.Faction = PlanetSideEmpire.NEUTRAL //Akkan North Bunker
+ BuildingByMapId(44).get.Faction = PlanetSideEmpire.NEUTRAL //Enkidu East Bunker
+ BuildingByMapId(45).get.Faction = PlanetSideEmpire.NEUTRAL //Neti bunker
+ BuildingByMapId(46).get.Faction = PlanetSideEmpire.NEUTRAL //Hanish West Bunker
+ BuildingByMapId(47).get.Faction = PlanetSideEmpire.NEUTRAL //Irkalla East Bunker
+ BuildingByMapId(48).get.Faction = PlanetSideEmpire.NEUTRAL //Zaqar bunker
+ BuildingByMapId(49).get.Faction = PlanetSideEmpire.NEUTRAL //Kusag West Bunker
+ BuildingByMapId(50).get.Faction = PlanetSideEmpire.NEUTRAL //marduk bunker
+ BuildingByMapId(51).get.Faction = PlanetSideEmpire.TR //baal bunker
+ BuildingByMapId(52).get.Faction = PlanetSideEmpire.NEUTRAL //girru bunker
+ BuildingByMapId(53).get.Faction = PlanetSideEmpire.NEUTRAL //lahar bunker
+ BuildingByMapId(54).get.Faction = PlanetSideEmpire.NEUTRAL //akkan bunker
+ BuildingByMapId(55).get.Faction = PlanetSideEmpire.VS //Irkalla_Tower
+ BuildingByMapId(56).get.Faction = PlanetSideEmpire.VS //Hanish_Tower
+ BuildingByMapId(57).get.Faction = PlanetSideEmpire.VS //E_Ceryshen_Warpgate_Tower
+ BuildingByMapId(58).get.Faction = PlanetSideEmpire.VS //Lahar_Tower
+ BuildingByMapId(59).get.Faction = PlanetSideEmpire.VS //VSSanc_Warpgate_Tower
+ BuildingByMapId(60).get.Faction = PlanetSideEmpire.TR //Akkan_Tower
+ BuildingByMapId(61).get.Faction = PlanetSideEmpire.NC //TRSanc_Warpgate_Tower
+ BuildingByMapId(62).get.Faction = PlanetSideEmpire.NC //Marduk_Tower
+ BuildingByMapId(63).get.Faction = PlanetSideEmpire.TR //NW_Dagon_Tower
+ BuildingByMapId(64).get.Faction = PlanetSideEmpire.NEUTRAL //E7 East Bunker (at north from bridge)
+ BuildingByMapId(65).get.Faction = PlanetSideEmpire.VS //W_Hanish_Tower
}
}
@@ -86,15 +94,21 @@ object Zones {
override def Init(implicit context : ActorContext) : Unit = {
super.Init(context)
+ GUID(2094) match {
+ case Some(silo : ResourceSilo) =>
+ silo.ChargeLevel = silo.MaximumCharge
+ case _ => ;
+ }
import net.psforever.types.PlanetSideEmpire
-// Building(2).get.Faction = PlanetSideEmpire.VS
-// Building(2).get.ModelId = 20
-// Building(38).get.ModelId = 0
-// Building(42).get.ModelId = 0
-// Building(48).get.Faction = PlanetSideEmpire.VS
-// Building(48).get.ModelId = 59
-// Building(49).get.Faction = PlanetSideEmpire.VS
-// Building(49).get.ModelId = 69
+ BuildingByMapId(2).get.Faction = PlanetSideEmpire.VS
+ BuildingByMapId(10).get.asInstanceOf[WarpGate].Broadcast = true
+ BuildingByMapId(11).get.asInstanceOf[WarpGate].Broadcast = true
+ BuildingByMapId(12).get.asInstanceOf[WarpGate].Broadcast = true
+ BuildingByMapId(13).get.asInstanceOf[WarpGate].Broadcast = true
+ BuildingByMapId(48).get.Faction = PlanetSideEmpire.VS
+ BuildingByMapId(49).get.Faction = PlanetSideEmpire.VS
+ BuildingByMapId(18657).get.asInstanceOf[WarpGate].Active = false
+ BuildingByMapId(18658).get.asInstanceOf[WarpGate].Active = false
}
}
@@ -130,11 +144,9 @@ object Zones {
import net.psforever.types.PlanetSideEmpire
Buildings.values.foreach { _.Faction = PlanetSideEmpire.VS }
-// Building(29).get.Faction = PlanetSideEmpire.NC //South Villa Gun Tower
-// GUID(293).get.asInstanceOf[VehicleSpawnPad].Railed = false //building 52
-// GUID(706).get.asInstanceOf[VehicleSpawnPad].Guide = List(AutoDriveControls.DistanceFromHere(50f)) //building 77
-// GUID(710).get.asInstanceOf[VehicleSpawnPad].Railed = false //building 79
-// GUID(712).get.asInstanceOf[VehicleSpawnPad].Railed = false //building 81
+ BuildingByMapId(60).get.Faction = PlanetSideEmpire.NC //South Villa Gun Tower
+ BuildingByMapId(1).get.asInstanceOf[WarpGate].Broadcast = true
+ BuildingByMapId(3).get.asInstanceOf[WarpGate].Broadcast = true
}
}
@@ -203,4 +215,32 @@ object Zones {
case PlanetSideEmpire.NEUTRAL => 0 //invalid, not black ops
}
}
+
+ /**
+ * Given a zone identification string, provide that zone's ordinal number.
+ * As zone identification naming is extremely formulaic,
+ * just being able to poll the zone's identifier by its first few letters will produce its ordinal position.
+ * @param id a zone id string
+ * @return a zone number
+ */
+ def NumberFromId(id : String) : Int = {
+ if(id.startsWith("z")) { //z2 -> 2
+ id.substring(1).toInt
+ }
+ else if(id.startsWith("home")) { //home2 -> 2 + 10 = 12
+ id.substring(4).toInt + 10
+ }
+ else if(id.startsWith("tz")) { //tzconc -> (14 + (3 * 1) + 2) -> 19
+ (List("tr", "nc", "vs").indexOf(id.substring(4)) * 3) + List("sh", "dr", "co").indexOf(id.substring(2, 4)) + 14
+ }
+ else if(id.startsWith("c")) { //c2 -> 2 + 21 = 23
+ id.substring(1).toInt + 21
+ }
+ else if(id.startsWith("i")) { //i2 -> 2 + 28 = 30
+ id.substring(1).toInt + 28
+ }
+ else {
+ 0
+ }
+ }
}
diff --git a/pslogin/src/main/scala/zonemaps/Map06.scala b/pslogin/src/main/scala/zonemaps/Map06.scala
index 4432401b..621c3d3d 100644
--- a/pslogin/src/main/scala/zonemaps/Map06.scala
+++ b/pslogin/src/main/scala/zonemaps/Map06.scala
@@ -7,7 +7,7 @@ import net.psforever.objects.serverobject.locks.IFFLock
import net.psforever.objects.serverobject.mblocker.Locker
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
-import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, StructureType}
+import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, StructureType, WarpGate}
import net.psforever.objects.serverobject.terminals.{CaptureTerminal, ProximityTerminal, Terminal}
import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.serverobject.turret.FacilityTurret
@@ -2280,5 +2280,41 @@ object Map06 {
LocalObject(1469, FacilityTurret.Constructor(manned_turret, Vector3(6343.497f, 4006.957f, 56.5199f)), owning_building_guid = 73)
TurretToWeapon(1469, 5098)
}
+
+ Building10()
+
+ def Building10() : Unit = { // Name: ??? Type: ??? GUID: 76, MapID: 10
+ LocalBuilding(76, 10, FoundationBuilder(WarpGate.Structure(Vector3(4970.0703f, 2082.1719f, 24.421875f)))) //searhus warp gate
+ }
+
+ Building11()
+
+ def Building11() : Unit = { // Name: ??? Type: ??? GUID: 75, MapID: 11
+ LocalBuilding(75, 11, FoundationBuilder(WarpGate.Structure(Vector3(2587.7969f, 2997.1562f, 195.34375f)))) //cyssor warp gate
+ }
+
+ Building12()
+
+ def Building12() : Unit = { // Name: ??? Type: ??? GUID: 74, MapID: 12
+ LocalBuilding(74, 12, FoundationBuilder(WarpGate.Structure(Vector3(2189.5703f, 5508.164f, 38.765625f)))) //solar warp gate
+ }
+
+ Building13()
+
+ def Building13() : Unit = { // Name: ??? Type: ??? GUID: 77, MapID: 13
+ LocalBuilding(77, 13, FoundationBuilder(WarpGate.Structure(Vector3(5028.1094f, 4499.7188f, 50.09375f)))) //vs sanctuary warp gate
+ }
+
+ Building18657()
+
+ def Building18657() : Unit = { // Name: ??? Type: ??? GUID: 33, MapID: 18657
+ LocalBuilding(33, 18657, FoundationBuilder(WarpGate.Structure(Vector3.Zero, hst))) //geowarp near Tarqaq
+ }
+
+ Building18658()
+
+ def Building18658() : Unit = { // Name: ??? Type: ??? GUID: 34, MapID: 18658
+ LocalBuilding(34, 18658, FoundationBuilder(WarpGate.Structure(Vector3.Zero, hst))) //geowarp near Igaluk
+ }
}
}
diff --git a/pslogin/src/main/scala/zonemaps/Map11.scala b/pslogin/src/main/scala/zonemaps/Map11.scala
index 3d017a98..c4a33f3e 100644
--- a/pslogin/src/main/scala/zonemaps/Map11.scala
+++ b/pslogin/src/main/scala/zonemaps/Map11.scala
@@ -817,12 +817,12 @@ object Map11 {
LocalObject(852, Terminal.Constructor(order_terminal), owning_building_guid = 41)
LocalObject(853, Terminal.Constructor(order_terminal), owning_building_guid = 41)
LocalObject(854, Terminal.Constructor(order_terminal), owning_building_guid = 41)
- LocalObject(774, SpawnTube.Constructor(Vector3(2162.234f, 5444.899f, 67.2449f), Vector3(0, 0, 181)), owning_building_guid = 41)
- LocalObject(775, SpawnTube.Constructor(Vector3(2162.317f, 5449.653f, 67.2449f), Vector3(0, 0, 1)), owning_building_guid = 41)
- LocalObject(776, SpawnTube.Constructor(Vector3(2168.941f, 5444.781f, 67.2449f), Vector3(0, 0, 181)), owning_building_guid = 41)
- LocalObject(777, SpawnTube.Constructor(Vector3(2169.023f, 5449.536f, 67.2449f), Vector3(0, 0, 1)), owning_building_guid = 41)
- LocalObject(778, SpawnTube.Constructor(Vector3(2175.648f, 5444.665f, 67.2449f), Vector3(0, 0, 181)), owning_building_guid = 41)
- LocalObject(779, SpawnTube.Constructor(Vector3(2175.731f, 5449.419f, 67.2449f), Vector3(0, 0, 1)), owning_building_guid = 41)
+ LocalObject(774, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2162.234f, 5444.899f, 67.2449f), Vector3(0, 0, 181)), owning_building_guid = 41)
+ LocalObject(775, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2162.317f, 5449.653f, 67.2449f), Vector3(0, 0, 1)), owning_building_guid = 41)
+ LocalObject(776, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2168.941f, 5444.781f, 67.2449f), Vector3(0, 0, 181)), owning_building_guid = 41)
+ LocalObject(777, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2169.023f, 5449.536f, 67.2449f), Vector3(0, 0, 1)), owning_building_guid = 41)
+ LocalObject(778, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2175.648f, 5444.665f, 67.2449f), Vector3(0, 0, 181)), owning_building_guid = 41)
+ LocalObject(779, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2175.731f, 5449.419f, 67.2449f), Vector3(0, 0, 1)), owning_building_guid = 41)
}
Building35()
@@ -849,12 +849,12 @@ object Map11 {
LocalObject(878, Terminal.Constructor(order_terminal), owning_building_guid = 42)
LocalObject(879, Terminal.Constructor(order_terminal), owning_building_guid = 42)
LocalObject(880, Terminal.Constructor(order_terminal), owning_building_guid = 42)
- LocalObject(780, SpawnTube.Constructor(Vector3(2355.215f, 5438.748f, 66.71281f), Vector3(0, 0, 316)), owning_building_guid = 42)
- LocalObject(781, SpawnTube.Constructor(Vector3(2358.517f, 5435.328f, 66.71281f), Vector3(0, 0, 136)), owning_building_guid = 42)
- LocalObject(782, SpawnTube.Constructor(Vector3(2360.04f, 5443.408f, 66.71281f), Vector3(0, 0, 316)), owning_building_guid = 42)
- LocalObject(783, SpawnTube.Constructor(Vector3(2363.344f, 5439.987f, 66.71281f), Vector3(0, 0, 136)), owning_building_guid = 42)
- LocalObject(784, SpawnTube.Constructor(Vector3(2364.866f, 5448.068f, 66.71281f), Vector3(0, 0, 316)), owning_building_guid = 42)
- LocalObject(785, SpawnTube.Constructor(Vector3(2368.168f, 5444.648f, 66.71281f), Vector3(0, 0, 136)), owning_building_guid = 42)
+ LocalObject(780, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2355.215f, 5438.748f, 66.71281f), Vector3(0, 0, 316)), owning_building_guid = 42)
+ LocalObject(781, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2358.517f, 5435.328f, 66.71281f), Vector3(0, 0, 136)), owning_building_guid = 42)
+ LocalObject(782, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2360.04f, 5443.408f, 66.71281f), Vector3(0, 0, 316)), owning_building_guid = 42)
+ LocalObject(783, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2363.344f, 5439.987f, 66.71281f), Vector3(0, 0, 136)), owning_building_guid = 42)
+ LocalObject(784, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2364.866f, 5448.068f, 66.71281f), Vector3(0, 0, 316)), owning_building_guid = 42)
+ LocalObject(785, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2368.168f, 5444.648f, 66.71281f), Vector3(0, 0, 136)), owning_building_guid = 42)
}
Building36()
@@ -881,12 +881,12 @@ object Map11 {
LocalObject(884, Terminal.Constructor(order_terminal), owning_building_guid = 43)
LocalObject(885, Terminal.Constructor(order_terminal), owning_building_guid = 43)
LocalObject(886, Terminal.Constructor(order_terminal), owning_building_guid = 43)
- LocalObject(786, SpawnTube.Constructor(Vector3(2394.346f, 5547.723f, 67.23998f), Vector3(0, 0, 269)), owning_building_guid = 43)
- LocalObject(787, SpawnTube.Constructor(Vector3(2394.463f, 5541.015f, 67.23998f), Vector3(0, 0, 269)), owning_building_guid = 43)
- LocalObject(788, SpawnTube.Constructor(Vector3(2394.58f, 5534.308f, 67.23998f), Vector3(0, 0, 269)), owning_building_guid = 43)
- LocalObject(789, SpawnTube.Constructor(Vector3(2399.1f, 5547.806f, 67.23998f), Vector3(0, 0, 89)), owning_building_guid = 43)
- LocalObject(790, SpawnTube.Constructor(Vector3(2399.218f, 5541.099f, 67.23998f), Vector3(0, 0, 89)), owning_building_guid = 43)
- LocalObject(791, SpawnTube.Constructor(Vector3(2399.334f, 5534.391f, 67.23998f), Vector3(0, 0, 89)), owning_building_guid = 43)
+ LocalObject(786, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2394.346f, 5547.723f, 67.23998f), Vector3(0, 0, 269)), owning_building_guid = 43)
+ LocalObject(787, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2394.463f, 5541.015f, 67.23998f), Vector3(0, 0, 269)), owning_building_guid = 43)
+ LocalObject(788, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2394.58f, 5534.308f, 67.23998f), Vector3(0, 0, 269)), owning_building_guid = 43)
+ LocalObject(789, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2399.1f, 5547.806f, 67.23998f), Vector3(0, 0, 89)), owning_building_guid = 43)
+ LocalObject(790, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2399.218f, 5541.099f, 67.23998f), Vector3(0, 0, 89)), owning_building_guid = 43)
+ LocalObject(791, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2399.334f, 5534.391f, 67.23998f), Vector3(0, 0, 89)), owning_building_guid = 43)
}
Building53()
@@ -913,12 +913,12 @@ object Map11 {
LocalObject(902, Terminal.Constructor(order_terminal), owning_building_guid = 44)
LocalObject(903, Terminal.Constructor(order_terminal), owning_building_guid = 44)
LocalObject(904, Terminal.Constructor(order_terminal), owning_building_guid = 44)
- LocalObject(792, SpawnTube.Constructor(Vector3(3990.234f, 5976.899f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 44)
- LocalObject(793, SpawnTube.Constructor(Vector3(3990.317f, 5981.653f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 44)
- LocalObject(794, SpawnTube.Constructor(Vector3(3996.941f, 5976.781f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 44)
- LocalObject(795, SpawnTube.Constructor(Vector3(3997.023f, 5981.536f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 44)
- LocalObject(796, SpawnTube.Constructor(Vector3(4003.648f, 5976.665f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 44)
- LocalObject(797, SpawnTube.Constructor(Vector3(4003.731f, 5981.419f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 44)
+ LocalObject(792, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3990.234f, 5976.899f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 44)
+ LocalObject(793, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3990.317f, 5981.653f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 44)
+ LocalObject(794, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3996.941f, 5976.781f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 44)
+ LocalObject(795, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3997.023f, 5981.536f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 44)
+ LocalObject(796, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4003.648f, 5976.665f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 44)
+ LocalObject(797, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4003.731f, 5981.419f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 44)
}
Building18()
@@ -945,12 +945,12 @@ object Map11 {
LocalObject(918, Terminal.Constructor(order_terminal), owning_building_guid = 45)
LocalObject(919, Terminal.Constructor(order_terminal), owning_building_guid = 45)
LocalObject(920, Terminal.Constructor(order_terminal), owning_building_guid = 45)
- LocalObject(798, SpawnTube.Constructor(Vector3(4142.234f, 5944.899f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 45)
- LocalObject(799, SpawnTube.Constructor(Vector3(4142.317f, 5949.653f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 45)
- LocalObject(800, SpawnTube.Constructor(Vector3(4148.941f, 5944.781f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 45)
- LocalObject(801, SpawnTube.Constructor(Vector3(4149.023f, 5949.536f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 45)
- LocalObject(802, SpawnTube.Constructor(Vector3(4155.648f, 5944.665f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 45)
- LocalObject(803, SpawnTube.Constructor(Vector3(4155.731f, 5949.419f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 45)
+ LocalObject(798, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4142.234f, 5944.899f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 45)
+ LocalObject(799, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4142.317f, 5949.653f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 45)
+ LocalObject(800, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4148.941f, 5944.781f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 45)
+ LocalObject(801, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4149.023f, 5949.536f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 45)
+ LocalObject(802, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4155.648f, 5944.665f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 45)
+ LocalObject(803, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4155.731f, 5949.419f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 45)
}
Building52()
@@ -977,12 +977,12 @@ object Map11 {
LocalObject(943, Terminal.Constructor(order_terminal), owning_building_guid = 46)
LocalObject(944, Terminal.Constructor(order_terminal), owning_building_guid = 46)
LocalObject(945, Terminal.Constructor(order_terminal), owning_building_guid = 46)
- LocalObject(804, SpawnTube.Constructor(Vector3(4296.234f, 5970.899f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 46)
- LocalObject(805, SpawnTube.Constructor(Vector3(4296.317f, 5975.653f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 46)
- LocalObject(806, SpawnTube.Constructor(Vector3(4302.941f, 5970.781f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 46)
- LocalObject(807, SpawnTube.Constructor(Vector3(4303.023f, 5975.536f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 46)
- LocalObject(808, SpawnTube.Constructor(Vector3(4309.648f, 5970.665f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 46)
- LocalObject(809, SpawnTube.Constructor(Vector3(4309.731f, 5975.419f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 46)
+ LocalObject(804, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4296.234f, 5970.899f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 46)
+ LocalObject(805, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4296.317f, 5975.653f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 46)
+ LocalObject(806, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4302.941f, 5970.781f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 46)
+ LocalObject(807, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4303.023f, 5975.536f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 46)
+ LocalObject(808, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4309.648f, 5970.665f, 45.90862f), Vector3(0, 0, 181)), owning_building_guid = 46)
+ LocalObject(809, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4309.731f, 5975.419f, 45.90862f), Vector3(0, 0, 1)), owning_building_guid = 46)
}
Building5()
@@ -1009,12 +1009,12 @@ object Map11 {
LocalObject(952, Terminal.Constructor(order_terminal), owning_building_guid = 47)
LocalObject(953, Terminal.Constructor(order_terminal), owning_building_guid = 47)
LocalObject(954, Terminal.Constructor(order_terminal), owning_building_guid = 47)
- LocalObject(810, SpawnTube.Constructor(Vector3(4696.047f, 3402.895f, 70.77006f), Vector3(0, 0, 227)), owning_building_guid = 47)
- LocalObject(811, SpawnTube.Constructor(Vector3(4699.524f, 3406.137f, 70.77006f), Vector3(0, 0, 47)), owning_building_guid = 47)
- LocalObject(812, SpawnTube.Constructor(Vector3(4700.622f, 3397.988f, 70.77006f), Vector3(0, 0, 227)), owning_building_guid = 47)
- LocalObject(813, SpawnTube.Constructor(Vector3(4704.099f, 3401.232f, 70.77006f), Vector3(0, 0, 47)), owning_building_guid = 47)
- LocalObject(814, SpawnTube.Constructor(Vector3(4705.197f, 3393.082f, 70.77006f), Vector3(0, 0, 227)), owning_building_guid = 47)
- LocalObject(815, SpawnTube.Constructor(Vector3(4708.674f, 3396.325f, 70.77006f), Vector3(0, 0, 47)), owning_building_guid = 47)
+ LocalObject(810, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4696.047f, 3402.895f, 70.77006f), Vector3(0, 0, 227)), owning_building_guid = 47)
+ LocalObject(811, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4699.524f, 3406.137f, 70.77006f), Vector3(0, 0, 47)), owning_building_guid = 47)
+ LocalObject(812, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4700.622f, 3397.988f, 70.77006f), Vector3(0, 0, 227)), owning_building_guid = 47)
+ LocalObject(813, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4704.099f, 3401.232f, 70.77006f), Vector3(0, 0, 47)), owning_building_guid = 47)
+ LocalObject(814, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4705.197f, 3393.082f, 70.77006f), Vector3(0, 0, 227)), owning_building_guid = 47)
+ LocalObject(815, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4708.674f, 3396.325f, 70.77006f), Vector3(0, 0, 47)), owning_building_guid = 47)
}
Building7()
@@ -1041,12 +1041,12 @@ object Map11 {
LocalObject(958, Terminal.Constructor(order_terminal), owning_building_guid = 48)
LocalObject(959, Terminal.Constructor(order_terminal), owning_building_guid = 48)
LocalObject(960, Terminal.Constructor(order_terminal), owning_building_guid = 48)
- LocalObject(816, SpawnTube.Constructor(Vector3(4724.571f, 3593.914f, 70.77006f), Vector3(0, 0, 315)), owning_building_guid = 48)
- LocalObject(817, SpawnTube.Constructor(Vector3(4727.933f, 3590.552f, 70.77006f), Vector3(0, 0, 135)), owning_building_guid = 48)
- LocalObject(818, SpawnTube.Constructor(Vector3(4729.314f, 3598.658f, 70.77006f), Vector3(0, 0, 315)), owning_building_guid = 48)
- LocalObject(819, SpawnTube.Constructor(Vector3(4732.677f, 3595.296f, 70.77006f), Vector3(0, 0, 135)), owning_building_guid = 48)
- LocalObject(820, SpawnTube.Constructor(Vector3(4734.058f, 3603.401f, 70.77006f), Vector3(0, 0, 315)), owning_building_guid = 48)
- LocalObject(821, SpawnTube.Constructor(Vector3(4737.42f, 3600.039f, 70.77006f), Vector3(0, 0, 135)), owning_building_guid = 48)
+ LocalObject(816, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4724.571f, 3593.914f, 70.77006f), Vector3(0, 0, 315)), owning_building_guid = 48)
+ LocalObject(817, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4727.933f, 3590.552f, 70.77006f), Vector3(0, 0, 135)), owning_building_guid = 48)
+ LocalObject(818, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4729.314f, 3598.658f, 70.77006f), Vector3(0, 0, 315)), owning_building_guid = 48)
+ LocalObject(819, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4732.677f, 3595.296f, 70.77006f), Vector3(0, 0, 135)), owning_building_guid = 48)
+ LocalObject(820, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4734.058f, 3603.401f, 70.77006f), Vector3(0, 0, 315)), owning_building_guid = 48)
+ LocalObject(821, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4737.42f, 3600.039f, 70.77006f), Vector3(0, 0, 135)), owning_building_guid = 48)
}
Building6()
@@ -1073,12 +1073,12 @@ object Map11 {
LocalObject(987, Terminal.Constructor(order_terminal), owning_building_guid = 49)
LocalObject(988, Terminal.Constructor(order_terminal), owning_building_guid = 49)
LocalObject(989, Terminal.Constructor(order_terminal), owning_building_guid = 49)
- LocalObject(822, SpawnTube.Constructor(Vector3(4919.932f, 3622.866f, 70.77006f), Vector3(0, 0, 226)), owning_building_guid = 49)
- LocalObject(823, SpawnTube.Constructor(Vector3(4923.352f, 3626.168f, 70.77006f), Vector3(0, 0, 46)), owning_building_guid = 49)
- LocalObject(824, SpawnTube.Constructor(Vector3(4924.592f, 3618.04f, 70.77006f), Vector3(0, 0, 226)), owning_building_guid = 49)
- LocalObject(825, SpawnTube.Constructor(Vector3(4928.013f, 3621.344f, 70.77006f), Vector3(0, 0, 46)), owning_building_guid = 49)
- LocalObject(826, SpawnTube.Constructor(Vector3(4929.252f, 3613.215f, 70.77006f), Vector3(0, 0, 226)), owning_building_guid = 49)
- LocalObject(827, SpawnTube.Constructor(Vector3(4932.672f, 3616.517f, 70.77006f), Vector3(0, 0, 46)), owning_building_guid = 49)
+ LocalObject(822, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4919.932f, 3622.866f, 70.77006f), Vector3(0, 0, 226)), owning_building_guid = 49)
+ LocalObject(823, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4923.352f, 3626.168f, 70.77006f), Vector3(0, 0, 46)), owning_building_guid = 49)
+ LocalObject(824, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4924.592f, 3618.04f, 70.77006f), Vector3(0, 0, 226)), owning_building_guid = 49)
+ LocalObject(825, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4928.013f, 3621.344f, 70.77006f), Vector3(0, 0, 46)), owning_building_guid = 49)
+ LocalObject(826, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4929.252f, 3613.215f, 70.77006f), Vector3(0, 0, 226)), owning_building_guid = 49)
+ LocalObject(827, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(4932.672f, 3616.517f, 70.77006f), Vector3(0, 0, 46)), owning_building_guid = 49)
}
Building34()
diff --git a/pslogin/src/main/scala/zonemaps/Map12.scala b/pslogin/src/main/scala/zonemaps/Map12.scala
index 26154ab9..996978aa 100644
--- a/pslogin/src/main/scala/zonemaps/Map12.scala
+++ b/pslogin/src/main/scala/zonemaps/Map12.scala
@@ -715,12 +715,12 @@ object Map12 {
LocalObject(817, Terminal.Constructor(order_terminal), owning_building_guid = 62)
LocalObject(818, Terminal.Constructor(order_terminal), owning_building_guid = 62)
LocalObject(819, Terminal.Constructor(order_terminal), owning_building_guid = 62)
- LocalObject(742, SpawnTube.Constructor(Vector3(2760.571f, 5245.914f, 38.03099f), Vector3(0, 0, 315)), owning_building_guid = 62)
- LocalObject(743, SpawnTube.Constructor(Vector3(2763.933f, 5242.552f, 38.03099f), Vector3(0, 0, 135)), owning_building_guid = 62)
- LocalObject(744, SpawnTube.Constructor(Vector3(2765.314f, 5250.658f, 38.03099f), Vector3(0, 0, 315)), owning_building_guid = 62)
- LocalObject(745, SpawnTube.Constructor(Vector3(2768.677f, 5247.296f, 38.03099f), Vector3(0, 0, 135)), owning_building_guid = 62)
- LocalObject(746, SpawnTube.Constructor(Vector3(2770.058f, 5255.401f, 38.03099f), Vector3(0, 0, 315)), owning_building_guid = 62)
- LocalObject(747, SpawnTube.Constructor(Vector3(2773.42f, 5252.039f, 38.03099f), Vector3(0, 0, 135)), owning_building_guid = 62)
+ LocalObject(742, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2760.571f, 5245.914f, 38.03099f), Vector3(0, 0, 315)), owning_building_guid = 62)
+ LocalObject(743, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2763.933f, 5242.552f, 38.03099f), Vector3(0, 0, 135)), owning_building_guid = 62)
+ LocalObject(744, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2765.314f, 5250.658f, 38.03099f), Vector3(0, 0, 315)), owning_building_guid = 62)
+ LocalObject(745, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2768.677f, 5247.296f, 38.03099f), Vector3(0, 0, 135)), owning_building_guid = 62)
+ LocalObject(746, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2770.058f, 5255.401f, 38.03099f), Vector3(0, 0, 315)), owning_building_guid = 62)
+ LocalObject(747, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2773.42f, 5252.039f, 38.03099f), Vector3(0, 0, 135)), owning_building_guid = 62)
}
Building43()
@@ -747,12 +747,12 @@ object Map12 {
LocalObject(833, Terminal.Constructor(order_terminal), owning_building_guid = 63)
LocalObject(834, Terminal.Constructor(order_terminal), owning_building_guid = 63)
LocalObject(835, Terminal.Constructor(order_terminal), owning_building_guid = 63)
- LocalObject(748, SpawnTube.Constructor(Vector3(2850.79f, 3037.98f, 36.95669f), Vector3(0, 0, 270)), owning_building_guid = 63)
- LocalObject(749, SpawnTube.Constructor(Vector3(2850.791f, 3031.272f, 36.95669f), Vector3(0, 0, 270)), owning_building_guid = 63)
- LocalObject(750, SpawnTube.Constructor(Vector3(2850.791f, 3044.688f, 36.95669f), Vector3(0, 0, 270)), owning_building_guid = 63)
- LocalObject(751, SpawnTube.Constructor(Vector3(2855.545f, 3031.272f, 36.95669f), Vector3(0, 0, 90)), owning_building_guid = 63)
- LocalObject(752, SpawnTube.Constructor(Vector3(2855.545f, 3037.981f, 36.95669f), Vector3(0, 0, 90)), owning_building_guid = 63)
- LocalObject(753, SpawnTube.Constructor(Vector3(2855.545f, 3044.688f, 36.95669f), Vector3(0, 0, 90)), owning_building_guid = 63)
+ LocalObject(748, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2850.79f, 3037.98f, 36.95669f), Vector3(0, 0, 270)), owning_building_guid = 63)
+ LocalObject(749, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2850.791f, 3031.272f, 36.95669f), Vector3(0, 0, 270)), owning_building_guid = 63)
+ LocalObject(750, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2850.791f, 3044.688f, 36.95669f), Vector3(0, 0, 270)), owning_building_guid = 63)
+ LocalObject(751, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2855.545f, 3031.272f, 36.95669f), Vector3(0, 0, 90)), owning_building_guid = 63)
+ LocalObject(752, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2855.545f, 3037.981f, 36.95669f), Vector3(0, 0, 90)), owning_building_guid = 63)
+ LocalObject(753, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2855.545f, 3044.688f, 36.95669f), Vector3(0, 0, 90)), owning_building_guid = 63)
}
Building13()
@@ -779,12 +779,12 @@ object Map12 {
LocalObject(845, Terminal.Constructor(order_terminal), owning_building_guid = 64)
LocalObject(846, Terminal.Constructor(order_terminal), owning_building_guid = 64)
LocalObject(847, Terminal.Constructor(order_terminal), owning_building_guid = 64)
- LocalObject(754, SpawnTube.Constructor(Vector3(2913.312f, 5104.791f, 38.03099f), Vector3(0, 0, 180)), owning_building_guid = 64)
- LocalObject(755, SpawnTube.Constructor(Vector3(2913.312f, 5109.545f, 38.03099f), Vector3(0, 0, 0)), owning_building_guid = 64)
- LocalObject(756, SpawnTube.Constructor(Vector3(2920.019f, 5109.545f, 38.03099f), Vector3(0, 0, 0)), owning_building_guid = 64)
- LocalObject(757, SpawnTube.Constructor(Vector3(2920.02f, 5104.79f, 38.03099f), Vector3(0, 0, 180)), owning_building_guid = 64)
- LocalObject(758, SpawnTube.Constructor(Vector3(2926.728f, 5104.791f, 38.03099f), Vector3(0, 0, 180)), owning_building_guid = 64)
- LocalObject(759, SpawnTube.Constructor(Vector3(2926.728f, 5109.545f, 38.03099f), Vector3(0, 0, 0)), owning_building_guid = 64)
+ LocalObject(754, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2913.312f, 5104.791f, 38.03099f), Vector3(0, 0, 180)), owning_building_guid = 64)
+ LocalObject(755, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2913.312f, 5109.545f, 38.03099f), Vector3(0, 0, 0)), owning_building_guid = 64)
+ LocalObject(756, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2920.019f, 5109.545f, 38.03099f), Vector3(0, 0, 0)), owning_building_guid = 64)
+ LocalObject(757, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2920.02f, 5104.79f, 38.03099f), Vector3(0, 0, 180)), owning_building_guid = 64)
+ LocalObject(758, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2926.728f, 5104.791f, 38.03099f), Vector3(0, 0, 180)), owning_building_guid = 64)
+ LocalObject(759, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2926.728f, 5109.545f, 38.03099f), Vector3(0, 0, 0)), owning_building_guid = 64)
}
Building15()
@@ -811,12 +811,12 @@ object Map12 {
LocalObject(877, Terminal.Constructor(order_terminal), owning_building_guid = 65)
LocalObject(880, Terminal.Constructor(order_terminal), owning_building_guid = 65)
LocalObject(881, Terminal.Constructor(order_terminal), owning_building_guid = 65)
- LocalObject(760, SpawnTube.Constructor(Vector3(3066.552f, 5250.067f, 38.03099f), Vector3(0, 0, 225)), owning_building_guid = 65)
- LocalObject(761, SpawnTube.Constructor(Vector3(3069.914f, 5253.429f, 38.03099f), Vector3(0, 0, 45)), owning_building_guid = 65)
- LocalObject(762, SpawnTube.Constructor(Vector3(3071.296f, 5245.323f, 38.03099f), Vector3(0, 0, 225)), owning_building_guid = 65)
- LocalObject(763, SpawnTube.Constructor(Vector3(3074.658f, 5248.686f, 38.03099f), Vector3(0, 0, 45)), owning_building_guid = 65)
- LocalObject(764, SpawnTube.Constructor(Vector3(3076.039f, 5240.58f, 38.03099f), Vector3(0, 0, 225)), owning_building_guid = 65)
- LocalObject(765, SpawnTube.Constructor(Vector3(3079.401f, 5243.942f, 38.03099f), Vector3(0, 0, 45)), owning_building_guid = 65)
+ LocalObject(760, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3066.552f, 5250.067f, 38.03099f), Vector3(0, 0, 225)), owning_building_guid = 65)
+ LocalObject(761, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3069.914f, 5253.429f, 38.03099f), Vector3(0, 0, 45)), owning_building_guid = 65)
+ LocalObject(762, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3071.296f, 5245.323f, 38.03099f), Vector3(0, 0, 225)), owning_building_guid = 65)
+ LocalObject(763, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3074.658f, 5248.686f, 38.03099f), Vector3(0, 0, 45)), owning_building_guid = 65)
+ LocalObject(764, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3076.039f, 5240.58f, 38.03099f), Vector3(0, 0, 225)), owning_building_guid = 65)
+ LocalObject(765, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3079.401f, 5243.942f, 38.03099f), Vector3(0, 0, 45)), owning_building_guid = 65)
}
Building42()
@@ -843,12 +843,12 @@ object Map12 {
LocalObject(893, Terminal.Constructor(order_terminal), owning_building_guid = 66)
LocalObject(894, Terminal.Constructor(order_terminal), owning_building_guid = 66)
LocalObject(895, Terminal.Constructor(order_terminal), owning_building_guid = 66)
- LocalObject(772, SpawnTube.Constructor(Vector3(3157.272f, 3044.455f, 36.9544f), Vector3(0, 0, 180)), owning_building_guid = 66)
- LocalObject(773, SpawnTube.Constructor(Vector3(3157.272f, 3049.209f, 36.9544f), Vector3(0, 0, 0)), owning_building_guid = 66)
- LocalObject(774, SpawnTube.Constructor(Vector3(3163.98f, 3049.21f, 36.9544f), Vector3(0, 0, 0)), owning_building_guid = 66)
- LocalObject(775, SpawnTube.Constructor(Vector3(3163.981f, 3044.455f, 36.9544f), Vector3(0, 0, 180)), owning_building_guid = 66)
- LocalObject(776, SpawnTube.Constructor(Vector3(3170.688f, 3044.455f, 36.9544f), Vector3(0, 0, 180)), owning_building_guid = 66)
- LocalObject(777, SpawnTube.Constructor(Vector3(3170.688f, 3049.209f, 36.9544f), Vector3(0, 0, 0)), owning_building_guid = 66)
+ LocalObject(772, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3157.272f, 3044.455f, 36.9544f), Vector3(0, 0, 180)), owning_building_guid = 66)
+ LocalObject(773, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3157.272f, 3049.209f, 36.9544f), Vector3(0, 0, 0)), owning_building_guid = 66)
+ LocalObject(774, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3163.98f, 3049.21f, 36.9544f), Vector3(0, 0, 0)), owning_building_guid = 66)
+ LocalObject(775, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3163.981f, 3044.455f, 36.9544f), Vector3(0, 0, 180)), owning_building_guid = 66)
+ LocalObject(776, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3170.688f, 3044.455f, 36.9544f), Vector3(0, 0, 180)), owning_building_guid = 66)
+ LocalObject(777, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3170.688f, 3049.209f, 36.9544f), Vector3(0, 0, 0)), owning_building_guid = 66)
}
Building41()
@@ -875,12 +875,12 @@ object Map12 {
LocalObject(887, Terminal.Constructor(order_terminal), owning_building_guid = 67)
LocalObject(888, Terminal.Constructor(order_terminal), owning_building_guid = 67)
LocalObject(889, Terminal.Constructor(order_terminal), owning_building_guid = 67)
- LocalObject(766, SpawnTube.Constructor(Vector3(3138.455f, 2875.312f, 36.95451f), Vector3(0, 0, 270)), owning_building_guid = 67)
- LocalObject(767, SpawnTube.Constructor(Vector3(3138.455f, 2882.019f, 36.95451f), Vector3(0, 0, 270)), owning_building_guid = 67)
- LocalObject(768, SpawnTube.Constructor(Vector3(3138.455f, 2888.728f, 36.95451f), Vector3(0, 0, 270)), owning_building_guid = 67)
- LocalObject(769, SpawnTube.Constructor(Vector3(3143.209f, 2875.312f, 36.95451f), Vector3(0, 0, 90)), owning_building_guid = 67)
- LocalObject(770, SpawnTube.Constructor(Vector3(3143.209f, 2888.728f, 36.95451f), Vector3(0, 0, 90)), owning_building_guid = 67)
- LocalObject(771, SpawnTube.Constructor(Vector3(3143.21f, 2882.02f, 36.95451f), Vector3(0, 0, 90)), owning_building_guid = 67)
+ LocalObject(766, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3138.455f, 2875.312f, 36.95451f), Vector3(0, 0, 270)), owning_building_guid = 67)
+ LocalObject(767, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3138.455f, 2882.019f, 36.95451f), Vector3(0, 0, 270)), owning_building_guid = 67)
+ LocalObject(768, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3138.455f, 2888.728f, 36.95451f), Vector3(0, 0, 270)), owning_building_guid = 67)
+ LocalObject(769, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3143.209f, 2875.312f, 36.95451f), Vector3(0, 0, 90)), owning_building_guid = 67)
+ LocalObject(770, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3143.209f, 2888.728f, 36.95451f), Vector3(0, 0, 90)), owning_building_guid = 67)
+ LocalObject(771, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3143.21f, 2882.02f, 36.95451f), Vector3(0, 0, 90)), owning_building_guid = 67)
}
Building25()
@@ -907,12 +907,12 @@ object Map12 {
LocalObject(917, Terminal.Constructor(order_terminal), owning_building_guid = 68)
LocalObject(918, Terminal.Constructor(order_terminal), owning_building_guid = 68)
LocalObject(919, Terminal.Constructor(order_terminal), owning_building_guid = 68)
- LocalObject(778, SpawnTube.Constructor(Vector3(5078.79f, 3907.98f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 68)
- LocalObject(779, SpawnTube.Constructor(Vector3(5078.791f, 3901.272f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 68)
- LocalObject(780, SpawnTube.Constructor(Vector3(5078.791f, 3914.688f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 68)
- LocalObject(781, SpawnTube.Constructor(Vector3(5083.545f, 3901.272f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 68)
- LocalObject(782, SpawnTube.Constructor(Vector3(5083.545f, 3907.981f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 68)
- LocalObject(783, SpawnTube.Constructor(Vector3(5083.545f, 3914.688f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 68)
+ LocalObject(778, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5078.79f, 3907.98f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 68)
+ LocalObject(779, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5078.791f, 3901.272f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 68)
+ LocalObject(780, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5078.791f, 3914.688f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 68)
+ LocalObject(781, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5083.545f, 3901.272f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 68)
+ LocalObject(782, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5083.545f, 3907.981f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 68)
+ LocalObject(783, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5083.545f, 3914.688f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 68)
}
Building23()
@@ -939,12 +939,12 @@ object Map12 {
LocalObject(933, Terminal.Constructor(order_terminal), owning_building_guid = 69)
LocalObject(934, Terminal.Constructor(order_terminal), owning_building_guid = 69)
LocalObject(935, Terminal.Constructor(order_terminal), owning_building_guid = 69)
- LocalObject(784, SpawnTube.Constructor(Vector3(5223.312f, 3784.791f, 37.96111f), Vector3(0, 0, 180)), owning_building_guid = 69)
- LocalObject(785, SpawnTube.Constructor(Vector3(5223.312f, 3789.545f, 37.96111f), Vector3(0, 0, 0)), owning_building_guid = 69)
- LocalObject(786, SpawnTube.Constructor(Vector3(5230.019f, 3789.545f, 37.96111f), Vector3(0, 0, 0)), owning_building_guid = 69)
- LocalObject(787, SpawnTube.Constructor(Vector3(5230.02f, 3784.79f, 37.96111f), Vector3(0, 0, 180)), owning_building_guid = 69)
- LocalObject(788, SpawnTube.Constructor(Vector3(5236.728f, 3784.791f, 37.96111f), Vector3(0, 0, 180)), owning_building_guid = 69)
- LocalObject(789, SpawnTube.Constructor(Vector3(5236.728f, 3789.545f, 37.96111f), Vector3(0, 0, 0)), owning_building_guid = 69)
+ LocalObject(784, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5223.312f, 3784.791f, 37.96111f), Vector3(0, 0, 180)), owning_building_guid = 69)
+ LocalObject(785, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5223.312f, 3789.545f, 37.96111f), Vector3(0, 0, 0)), owning_building_guid = 69)
+ LocalObject(786, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5230.019f, 3789.545f, 37.96111f), Vector3(0, 0, 0)), owning_building_guid = 69)
+ LocalObject(787, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5230.02f, 3784.79f, 37.96111f), Vector3(0, 0, 180)), owning_building_guid = 69)
+ LocalObject(788, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5236.728f, 3784.791f, 37.96111f), Vector3(0, 0, 180)), owning_building_guid = 69)
+ LocalObject(789, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5236.728f, 3789.545f, 37.96111f), Vector3(0, 0, 0)), owning_building_guid = 69)
}
Building24()
@@ -971,12 +971,12 @@ object Map12 {
LocalObject(949, Terminal.Constructor(order_terminal), owning_building_guid = 70)
LocalObject(950, Terminal.Constructor(order_terminal), owning_building_guid = 70)
LocalObject(951, Terminal.Constructor(order_terminal), owning_building_guid = 70)
- LocalObject(790, SpawnTube.Constructor(Vector3(5382.455f, 3899.312f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 70)
- LocalObject(791, SpawnTube.Constructor(Vector3(5382.455f, 3906.019f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 70)
- LocalObject(792, SpawnTube.Constructor(Vector3(5382.455f, 3912.728f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 70)
- LocalObject(793, SpawnTube.Constructor(Vector3(5387.209f, 3899.312f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 70)
- LocalObject(794, SpawnTube.Constructor(Vector3(5387.209f, 3912.728f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 70)
- LocalObject(795, SpawnTube.Constructor(Vector3(5387.21f, 3906.02f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 70)
+ LocalObject(790, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5382.455f, 3899.312f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 70)
+ LocalObject(791, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5382.455f, 3906.019f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 70)
+ LocalObject(792, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5382.455f, 3912.728f, 37.96111f), Vector3(0, 0, 270)), owning_building_guid = 70)
+ LocalObject(793, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5387.209f, 3899.312f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 70)
+ LocalObject(794, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5387.209f, 3912.728f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 70)
+ LocalObject(795, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5387.21f, 3906.02f, 37.96111f), Vector3(0, 0, 90)), owning_building_guid = 70)
}
Building8()
diff --git a/pslogin/src/main/scala/zonemaps/Map13.scala b/pslogin/src/main/scala/zonemaps/Map13.scala
index 552d1a01..b335ec4a 100644
--- a/pslogin/src/main/scala/zonemaps/Map13.scala
+++ b/pslogin/src/main/scala/zonemaps/Map13.scala
@@ -6,7 +6,7 @@ import net.psforever.objects.serverobject.implantmech.ImplantTerminalMech
import net.psforever.objects.serverobject.locks.IFFLock
import net.psforever.objects.serverobject.mblocker.Locker
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
-import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, StructureType}
+import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, StructureType, WarpGate}
import net.psforever.objects.serverobject.terminals.{CaptureTerminal, ProximityTerminal, Terminal}
import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.serverobject.turret.FacilityTurret
@@ -16,10 +16,9 @@ import net.psforever.types.Vector3
object Map13 {
// HOME3 (VANU SOVREIGNTY SANCTUARY)
val ZoneMap = new ZoneMap("map13") {
-
Building22()
- def Building22(): Unit = { // Name: Hart_Ishundar Type: orbital_building_vs GUID: 1, MapID: 22
+ def Building22() : Unit = { // Name: Hart_Ishundar Type: orbital_building_vs GUID: 1, MapID: 22
LocalBuilding(1, 22, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(2978f, 4834f, 56.08539f))))
LocalObject(360, Door.Constructor(Vector3(2898f, 4821.99f, 60.19139f)), owning_building_guid = 1)
LocalObject(361, Door.Constructor(Vector3(2898f, 4845.99f, 60.19139f)), owning_building_guid = 1)
@@ -125,7 +124,7 @@ object Map13 {
Building4()
- def Building4(): Unit = { // Name: Hart_Esamir Type: orbital_building_vs GUID: 2, MapID: 4
+ def Building4() : Unit = { // Name: Hart_Esamir Type: orbital_building_vs GUID: 2, MapID: 4
LocalBuilding(2, 4, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3688f, 2808f, 90.85312f))))
LocalObject(370, Door.Constructor(Vector3(3608f, 2795.99f, 94.95912f)), owning_building_guid = 2)
LocalObject(371, Door.Constructor(Vector3(3608f, 2819.99f, 94.95912f)), owning_building_guid = 2)
@@ -231,7 +230,7 @@ object Map13 {
Building40()
- def Building40(): Unit = { // Name: Hart_Hossin Type: orbital_building_vs GUID: 3, MapID: 40
+ def Building40() : Unit = { // Name: Hart_Hossin Type: orbital_building_vs GUID: 3, MapID: 40
LocalBuilding(3, 40, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5610f, 4238f, 103.2289f))))
LocalObject(382, Door.Constructor(Vector3(5530f, 4225.99f, 107.3349f)), owning_building_guid = 3)
LocalObject(383, Door.Constructor(Vector3(5530f, 4249.99f, 107.3349f)), owning_building_guid = 3)
@@ -337,7 +336,7 @@ object Map13 {
Building58()
- def Building58(): Unit = { // Name: S_Ishundar_WG_tower Type: tower_a GUID: 28, MapID: 58
+ def Building58() : Unit = { // Name: S_Ishundar_WG_tower Type: tower_a GUID: 28, MapID: 58
LocalBuilding(28, 58, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(2708f, 5084f, 56.14882f))))
LocalObject(1015, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 28)
LocalObject(312, Door.Constructor(Vector3(2720f, 5076f, 57.66982f)), owning_building_guid = 28)
@@ -371,7 +370,7 @@ object Map13 {
Building63()
- def Building63(): Unit = { // Name: Esamir_WG_tower Type: tower_a GUID: 29, MapID: 63
+ def Building63() : Unit = { // Name: Esamir_WG_tower Type: tower_a GUID: 29, MapID: 63
LocalBuilding(29, 63, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(3968f, 2600f, 90.86123f))))
LocalObject(1019, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 29)
LocalObject(330, Door.Constructor(Vector3(3980f, 2592f, 92.38223f)), owning_building_guid = 29)
@@ -405,7 +404,7 @@ object Map13 {
Building66()
- def Building66(): Unit = { // Name: SE_Hossin_WG_tower Type: tower_a GUID: 30, MapID: 66
+ def Building66() : Unit = { // Name: SE_Hossin_WG_tower Type: tower_a GUID: 30, MapID: 66
LocalBuilding(30, 66, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(6006f, 4414f, 97.87095f))))
LocalObject(1024, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 30)
LocalObject(354, Door.Constructor(Vector3(6018f, 4406f, 99.39195f)), owning_building_guid = 30)
@@ -439,7 +438,7 @@ object Map13 {
Building60()
- def Building60(): Unit = { // Name: NW_Esamir_WG_tower Type: tower_b GUID: 31, MapID: 60
+ def Building60() : Unit = { // Name: NW_Esamir_WG_tower Type: tower_b GUID: 31, MapID: 60
LocalBuilding(31, 60, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(3208f, 3524f, 92.25745f))))
LocalObject(1016, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 31)
LocalObject(316, Door.Constructor(Vector3(3220f, 3516f, 93.77745f)), owning_building_guid = 31)
@@ -473,7 +472,7 @@ object Map13 {
Building64()
- def Building64(): Unit = { // Name: W_Hossin_WG_tower Type: tower_b GUID: 32, MapID: 64
+ def Building64() : Unit = { // Name: W_Hossin_WG_tower Type: tower_b GUID: 32, MapID: 64
LocalBuilding(32, 64, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(3988f, 4380f, 87.9162f))))
LocalObject(1020, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 32)
LocalObject(334, Door.Constructor(Vector3(4000f, 4372f, 89.4362f)), owning_building_guid = 32)
@@ -507,7 +506,7 @@ object Map13 {
Building67()
- def Building67(): Unit = { // Name: NE_Esamir_WG_tower Type: tower_b GUID: 33, MapID: 67
+ def Building67() : Unit = { // Name: NE_Esamir_WG_tower Type: tower_b GUID: 33, MapID: 67
LocalBuilding(33, 67, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(5098f, 2978f, 97.9873f))))
LocalObject(1022, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 33)
LocalObject(344, Door.Constructor(Vector3(5110f, 2970f, 99.5073f)), owning_building_guid = 33)
@@ -541,7 +540,7 @@ object Map13 {
Building59()
- def Building59(): Unit = { // Name: SE_Ishundar_WG_tower Type: tower_c GUID: 34, MapID: 59
+ def Building59() : Unit = { // Name: SE_Ishundar_WG_tower Type: tower_c GUID: 34, MapID: 59
LocalBuilding(34, 59, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(3224f, 4594f, 56.08539f))))
LocalObject(1017, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 34)
LocalObject(322, Door.Constructor(Vector3(3236f, 4586f, 57.60639f)), owning_building_guid = 34)
@@ -579,7 +578,7 @@ object Map13 {
Building62()
- def Building62(): Unit = { // Name: N_Esamir_WG_tower Type: tower_c GUID: 35, MapID: 62
+ def Building62() : Unit = { // Name: N_Esamir_WG_tower Type: tower_c GUID: 35, MapID: 62
LocalBuilding(35, 62, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(3670f, 3180f, 89.51079f))))
LocalObject(1018, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 35)
LocalObject(326, Door.Constructor(Vector3(3682f, 3172f, 91.03179f)), owning_building_guid = 35)
@@ -617,7 +616,7 @@ object Map13 {
Building61()
- def Building61(): Unit = { // Name: Continent_Central_tower Type: tower_c GUID: 36, MapID: 61
+ def Building61() : Unit = { // Name: Continent_Central_tower Type: tower_c GUID: 36, MapID: 61
LocalBuilding(36, 61, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(4410f, 3728f, 83.92174f))))
LocalObject(1021, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 36)
LocalObject(340, Door.Constructor(Vector3(4422f, 3720f, 85.44274f)), owning_building_guid = 36)
@@ -655,7 +654,7 @@ object Map13 {
Building65()
- def Building65(): Unit = { // Name: SW_Hossin_WG_tower Type: tower_c GUID: 37, MapID: 65
+ def Building65() : Unit = { // Name: SW_Hossin_WG_tower Type: tower_c GUID: 37, MapID: 65
LocalBuilding(37, 65, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(5160f, 4266f, 93.25694f))))
LocalObject(1023, CaptureTerminal.Constructor(secondary_capture), owning_building_guid = 37)
LocalObject(350, Door.Constructor(Vector3(5172f, 4258f, 94.77794f)), owning_building_guid = 37)
@@ -693,7 +692,7 @@ object Map13 {
Building33()
- def Building33(): Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 38, MapID: 33
+ def Building33() : Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 38, MapID: 33
LocalBuilding(38, 33, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(2848f, 4948f, 56.08539f))))
LocalObject(234, Door.Constructor(Vector3(2801.93f, 4911.454f, 58.16139f)), owning_building_guid = 38)
LocalObject(235, Door.Constructor(Vector3(2806.54f, 4916.042f, 58.16139f)), owning_building_guid = 38)
@@ -715,17 +714,17 @@ object Map13 {
LocalObject(795, Terminal.Constructor(order_terminal), owning_building_guid = 38)
LocalObject(796, Terminal.Constructor(order_terminal), owning_building_guid = 38)
LocalObject(797, Terminal.Constructor(order_terminal), owning_building_guid = 38)
- LocalObject(720, SpawnTube.Constructor(Vector3(2802.552f, 4912.067f, 58.11739f), Vector3(0, 0, 225)), owning_building_guid = 38)
- LocalObject(721, SpawnTube.Constructor(Vector3(2805.914f, 4915.429f, 58.11739f), Vector3(0, 0, 45)), owning_building_guid = 38)
- LocalObject(722, SpawnTube.Constructor(Vector3(2807.296f, 4907.323f, 58.11739f), Vector3(0, 0, 225)), owning_building_guid = 38)
- LocalObject(723, SpawnTube.Constructor(Vector3(2810.658f, 4910.686f, 58.11739f), Vector3(0, 0, 45)), owning_building_guid = 38)
- LocalObject(724, SpawnTube.Constructor(Vector3(2812.039f, 4902.58f, 58.11739f), Vector3(0, 0, 225)), owning_building_guid = 38)
- LocalObject(725, SpawnTube.Constructor(Vector3(2815.401f, 4905.942f, 58.11739f), Vector3(0, 0, 45)), owning_building_guid = 38)
+ LocalObject(720, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2802.552f, 4912.067f, 58.11739f), Vector3(0, 0, 225)), owning_building_guid = 38)
+ LocalObject(721, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2805.914f, 4915.429f, 58.11739f), Vector3(0, 0, 45)), owning_building_guid = 38)
+ LocalObject(722, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2807.296f, 4907.323f, 58.11739f), Vector3(0, 0, 225)), owning_building_guid = 38)
+ LocalObject(723, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2810.658f, 4910.686f, 58.11739f), Vector3(0, 0, 45)), owning_building_guid = 38)
+ LocalObject(724, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2812.039f, 4902.58f, 58.11739f), Vector3(0, 0, 225)), owning_building_guid = 38)
+ LocalObject(725, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(2815.401f, 4905.942f, 58.11739f), Vector3(0, 0, 45)), owning_building_guid = 38)
}
Building35()
- def Building35(): Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 39, MapID: 35
+ def Building35() : Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 39, MapID: 35
LocalBuilding(39, 35, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3122f, 4690f, 56.08539f))))
LocalObject(240, Door.Constructor(Vector3(3075.97f, 4726.587f, 58.16139f)), owning_building_guid = 39)
LocalObject(241, Door.Constructor(Vector3(3080.558f, 4721.976f, 58.16139f)), owning_building_guid = 39)
@@ -747,17 +746,17 @@ object Map13 {
LocalObject(821, Terminal.Constructor(order_terminal), owning_building_guid = 39)
LocalObject(822, Terminal.Constructor(order_terminal), owning_building_guid = 39)
LocalObject(823, Terminal.Constructor(order_terminal), owning_building_guid = 39)
- LocalObject(726, SpawnTube.Constructor(Vector3(3076.58f, 4725.961f, 58.11739f), Vector3(0, 0, 315)), owning_building_guid = 39)
- LocalObject(727, SpawnTube.Constructor(Vector3(3079.942f, 4722.599f, 58.11739f), Vector3(0, 0, 135)), owning_building_guid = 39)
- LocalObject(728, SpawnTube.Constructor(Vector3(3081.323f, 4730.704f, 58.11739f), Vector3(0, 0, 315)), owning_building_guid = 39)
- LocalObject(729, SpawnTube.Constructor(Vector3(3084.686f, 4727.342f, 58.11739f), Vector3(0, 0, 135)), owning_building_guid = 39)
- LocalObject(730, SpawnTube.Constructor(Vector3(3086.067f, 4735.448f, 58.11739f), Vector3(0, 0, 315)), owning_building_guid = 39)
- LocalObject(731, SpawnTube.Constructor(Vector3(3089.429f, 4732.086f, 58.11739f), Vector3(0, 0, 135)), owning_building_guid = 39)
+ LocalObject(726, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3076.58f, 4725.961f, 58.11739f), Vector3(0, 0, 315)), owning_building_guid = 39)
+ LocalObject(727, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3079.942f, 4722.599f, 58.11739f), Vector3(0, 0, 135)), owning_building_guid = 39)
+ LocalObject(728, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3081.323f, 4730.704f, 58.11739f), Vector3(0, 0, 315)), owning_building_guid = 39)
+ LocalObject(729, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3084.686f, 4727.342f, 58.11739f), Vector3(0, 0, 135)), owning_building_guid = 39)
+ LocalObject(730, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3086.067f, 4735.448f, 58.11739f), Vector3(0, 0, 315)), owning_building_guid = 39)
+ LocalObject(731, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3089.429f, 4732.086f, 58.11739f), Vector3(0, 0, 135)), owning_building_guid = 39)
}
Building34()
- def Building34(): Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 40, MapID: 34
+ def Building34() : Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 40, MapID: 34
LocalBuilding(40, 34, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3144f, 4930f, 56.08539f))))
LocalObject(246, Door.Constructor(Vector3(3137.266f, 4871.582f, 58.16139f)), owning_building_guid = 40)
LocalObject(247, Door.Constructor(Vector3(3137.281f, 4878.085f, 58.16139f)), owning_building_guid = 40)
@@ -779,17 +778,17 @@ object Map13 {
LocalObject(827, Terminal.Constructor(order_terminal), owning_building_guid = 40)
LocalObject(828, Terminal.Constructor(order_terminal), owning_building_guid = 40)
LocalObject(829, Terminal.Constructor(order_terminal), owning_building_guid = 40)
- LocalObject(732, SpawnTube.Constructor(Vector3(3137.272f, 4872.455f, 58.11739f), Vector3(0, 0, 180)), owning_building_guid = 40)
- LocalObject(733, SpawnTube.Constructor(Vector3(3137.272f, 4877.209f, 58.11739f), Vector3(0, 0, 0)), owning_building_guid = 40)
- LocalObject(734, SpawnTube.Constructor(Vector3(3143.98f, 4877.21f, 58.11739f), Vector3(0, 0, 0)), owning_building_guid = 40)
- LocalObject(735, SpawnTube.Constructor(Vector3(3143.981f, 4872.455f, 58.11739f), Vector3(0, 0, 180)), owning_building_guid = 40)
- LocalObject(736, SpawnTube.Constructor(Vector3(3150.688f, 4872.455f, 58.11739f), Vector3(0, 0, 180)), owning_building_guid = 40)
- LocalObject(737, SpawnTube.Constructor(Vector3(3150.688f, 4877.209f, 58.11739f), Vector3(0, 0, 0)), owning_building_guid = 40)
+ LocalObject(732, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3137.272f, 4872.455f, 58.11739f), Vector3(0, 0, 180)), owning_building_guid = 40)
+ LocalObject(733, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3137.272f, 4877.209f, 58.11739f), Vector3(0, 0, 0)), owning_building_guid = 40)
+ LocalObject(734, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3143.98f, 4877.21f, 58.11739f), Vector3(0, 0, 0)), owning_building_guid = 40)
+ LocalObject(735, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3143.981f, 4872.455f, 58.11739f), Vector3(0, 0, 180)), owning_building_guid = 40)
+ LocalObject(736, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3150.688f, 4872.455f, 58.11739f), Vector3(0, 0, 180)), owning_building_guid = 40)
+ LocalObject(737, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3150.688f, 4877.209f, 58.11739f), Vector3(0, 0, 0)), owning_building_guid = 40)
}
Building7()
- def Building7(): Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 41, MapID: 7
+ def Building7() : Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 41, MapID: 7
LocalBuilding(41, 7, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3592f, 2966f, 90.8536f))))
LocalObject(252, Door.Constructor(Vector3(3584.247f, 2907.708f, 92.9296f)), owning_building_guid = 41)
LocalObject(253, Door.Constructor(Vector3(3584.376f, 2914.211f, 92.9296f)), owning_building_guid = 41)
@@ -811,17 +810,17 @@ object Map13 {
LocalObject(839, Terminal.Constructor(order_terminal), owning_building_guid = 41)
LocalObject(840, Terminal.Constructor(order_terminal), owning_building_guid = 41)
LocalObject(841, Terminal.Constructor(order_terminal), owning_building_guid = 41)
- LocalObject(738, SpawnTube.Constructor(Vector3(3584.269f, 2908.581f, 92.8856f), Vector3(0, 0, 181)), owning_building_guid = 41)
- LocalObject(739, SpawnTube.Constructor(Vector3(3584.352f, 2913.335f, 92.8856f), Vector3(0, 0, 1)), owning_building_guid = 41)
- LocalObject(740, SpawnTube.Constructor(Vector3(3590.977f, 2908.464f, 92.8856f), Vector3(0, 0, 181)), owning_building_guid = 41)
- LocalObject(741, SpawnTube.Constructor(Vector3(3591.059f, 2913.219f, 92.8856f), Vector3(0, 0, 1)), owning_building_guid = 41)
- LocalObject(742, SpawnTube.Constructor(Vector3(3597.683f, 2908.347f, 92.8856f), Vector3(0, 0, 181)), owning_building_guid = 41)
- LocalObject(743, SpawnTube.Constructor(Vector3(3597.766f, 2913.101f, 92.8856f), Vector3(0, 0, 1)), owning_building_guid = 41)
+ LocalObject(738, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3584.269f, 2908.581f, 92.8856f), Vector3(0, 0, 181)), owning_building_guid = 41)
+ LocalObject(739, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3584.352f, 2913.335f, 92.8856f), Vector3(0, 0, 1)), owning_building_guid = 41)
+ LocalObject(740, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3590.977f, 2908.464f, 92.8856f), Vector3(0, 0, 181)), owning_building_guid = 41)
+ LocalObject(741, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3591.059f, 2913.219f, 92.8856f), Vector3(0, 0, 1)), owning_building_guid = 41)
+ LocalObject(742, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3597.683f, 2908.347f, 92.8856f), Vector3(0, 0, 181)), owning_building_guid = 41)
+ LocalObject(743, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3597.766f, 2913.101f, 92.8856f), Vector3(0, 0, 1)), owning_building_guid = 41)
}
Building12()
- def Building12(): Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 42, MapID: 12
+ def Building12() : Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 42, MapID: 12
LocalBuilding(42, 12, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3690f, 2656f, 90.84919f))))
LocalObject(258, Door.Constructor(Vector3(3684.214f, 2708.023f, 92.92519f)), owning_building_guid = 42)
LocalObject(259, Door.Constructor(Vector3(3684.343f, 2714.527f, 92.92519f)), owning_building_guid = 42)
@@ -843,17 +842,17 @@ object Map13 {
LocalObject(855, Terminal.Constructor(order_terminal), owning_building_guid = 42)
LocalObject(859, Terminal.Constructor(order_terminal), owning_building_guid = 42)
LocalObject(860, Terminal.Constructor(order_terminal), owning_building_guid = 42)
- LocalObject(744, SpawnTube.Constructor(Vector3(3684.234f, 2708.899f, 92.88119f), Vector3(0, 0, 181)), owning_building_guid = 42)
- LocalObject(745, SpawnTube.Constructor(Vector3(3684.317f, 2713.653f, 92.88119f), Vector3(0, 0, 1)), owning_building_guid = 42)
- LocalObject(746, SpawnTube.Constructor(Vector3(3690.941f, 2708.781f, 92.88119f), Vector3(0, 0, 181)), owning_building_guid = 42)
- LocalObject(747, SpawnTube.Constructor(Vector3(3691.023f, 2713.536f, 92.88119f), Vector3(0, 0, 1)), owning_building_guid = 42)
- LocalObject(748, SpawnTube.Constructor(Vector3(3697.648f, 2708.665f, 92.88119f), Vector3(0, 0, 181)), owning_building_guid = 42)
- LocalObject(749, SpawnTube.Constructor(Vector3(3697.731f, 2713.419f, 92.88119f), Vector3(0, 0, 1)), owning_building_guid = 42)
+ LocalObject(744, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3684.234f, 2708.899f, 92.88119f), Vector3(0, 0, 181)), owning_building_guid = 42)
+ LocalObject(745, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3684.317f, 2713.653f, 92.88119f), Vector3(0, 0, 1)), owning_building_guid = 42)
+ LocalObject(746, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3690.941f, 2708.781f, 92.88119f), Vector3(0, 0, 181)), owning_building_guid = 42)
+ LocalObject(747, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3691.023f, 2713.536f, 92.88119f), Vector3(0, 0, 1)), owning_building_guid = 42)
+ LocalObject(748, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3697.648f, 2708.665f, 92.88119f), Vector3(0, 0, 181)), owning_building_guid = 42)
+ LocalObject(749, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3697.731f, 2713.419f, 92.88119f), Vector3(0, 0, 1)), owning_building_guid = 42)
}
Building13()
- def Building13(): Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 43, MapID: 13
+ def Building13() : Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 43, MapID: 13
LocalBuilding(43, 13, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3788f, 2968f, 90.8505f))))
LocalObject(264, Door.Constructor(Vector3(3780.247f, 2909.708f, 92.9265f)), owning_building_guid = 43)
LocalObject(265, Door.Constructor(Vector3(3780.376f, 2916.211f, 92.9265f)), owning_building_guid = 43)
@@ -875,17 +874,17 @@ object Map13 {
LocalObject(874, Terminal.Constructor(order_terminal), owning_building_guid = 43)
LocalObject(875, Terminal.Constructor(order_terminal), owning_building_guid = 43)
LocalObject(876, Terminal.Constructor(order_terminal), owning_building_guid = 43)
- LocalObject(750, SpawnTube.Constructor(Vector3(3780.269f, 2910.581f, 92.8825f), Vector3(0, 0, 181)), owning_building_guid = 43)
- LocalObject(751, SpawnTube.Constructor(Vector3(3780.352f, 2915.335f, 92.8825f), Vector3(0, 0, 1)), owning_building_guid = 43)
- LocalObject(752, SpawnTube.Constructor(Vector3(3786.977f, 2910.464f, 92.8825f), Vector3(0, 0, 181)), owning_building_guid = 43)
- LocalObject(753, SpawnTube.Constructor(Vector3(3787.059f, 2915.219f, 92.8825f), Vector3(0, 0, 1)), owning_building_guid = 43)
- LocalObject(754, SpawnTube.Constructor(Vector3(3793.683f, 2910.347f, 92.8825f), Vector3(0, 0, 181)), owning_building_guid = 43)
- LocalObject(755, SpawnTube.Constructor(Vector3(3793.766f, 2915.101f, 92.8825f), Vector3(0, 0, 1)), owning_building_guid = 43)
+ LocalObject(750, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3780.269f, 2910.581f, 92.8825f), Vector3(0, 0, 181)), owning_building_guid = 43)
+ LocalObject(751, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3780.352f, 2915.335f, 92.8825f), Vector3(0, 0, 1)), owning_building_guid = 43)
+ LocalObject(752, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3786.977f, 2910.464f, 92.8825f), Vector3(0, 0, 181)), owning_building_guid = 43)
+ LocalObject(753, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3787.059f, 2915.219f, 92.8825f), Vector3(0, 0, 1)), owning_building_guid = 43)
+ LocalObject(754, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3793.683f, 2910.347f, 92.8825f), Vector3(0, 0, 181)), owning_building_guid = 43)
+ LocalObject(755, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(3793.766f, 2915.101f, 92.8825f), Vector3(0, 0, 1)), owning_building_guid = 43)
}
Building50()
- def Building50(): Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 44, MapID: 50
+ def Building50() : Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 44, MapID: 50
LocalBuilding(44, 50, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5470f, 4094f, 103.2367f))))
LocalObject(276, Door.Constructor(Vector3(5501.976f, 4135.442f, 105.3127f)), owning_building_guid = 44)
LocalObject(277, Door.Constructor(Vector3(5506.587f, 4140.03f, 105.3127f)), owning_building_guid = 44)
@@ -907,17 +906,17 @@ object Map13 {
LocalObject(901, Terminal.Constructor(order_terminal), owning_building_guid = 44)
LocalObject(902, Terminal.Constructor(order_terminal), owning_building_guid = 44)
LocalObject(903, Terminal.Constructor(order_terminal), owning_building_guid = 44)
- LocalObject(762, SpawnTube.Constructor(Vector3(5502.599f, 4136.058f, 105.2687f), Vector3(0, 0, 225)), owning_building_guid = 44)
- LocalObject(763, SpawnTube.Constructor(Vector3(5505.961f, 4139.42f, 105.2687f), Vector3(0, 0, 45)), owning_building_guid = 44)
- LocalObject(764, SpawnTube.Constructor(Vector3(5507.342f, 4131.314f, 105.2687f), Vector3(0, 0, 225)), owning_building_guid = 44)
- LocalObject(765, SpawnTube.Constructor(Vector3(5510.704f, 4134.677f, 105.2687f), Vector3(0, 0, 45)), owning_building_guid = 44)
- LocalObject(766, SpawnTube.Constructor(Vector3(5512.086f, 4126.571f, 105.2687f), Vector3(0, 0, 225)), owning_building_guid = 44)
- LocalObject(767, SpawnTube.Constructor(Vector3(5515.448f, 4129.933f, 105.2687f), Vector3(0, 0, 45)), owning_building_guid = 44)
+ LocalObject(762, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5502.599f, 4136.058f, 105.2687f), Vector3(0, 0, 225)), owning_building_guid = 44)
+ LocalObject(763, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5505.961f, 4139.42f, 105.2687f), Vector3(0, 0, 45)), owning_building_guid = 44)
+ LocalObject(764, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5507.342f, 4131.314f, 105.2687f), Vector3(0, 0, 225)), owning_building_guid = 44)
+ LocalObject(765, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5510.704f, 4134.677f, 105.2687f), Vector3(0, 0, 45)), owning_building_guid = 44)
+ LocalObject(766, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5512.086f, 4126.571f, 105.2687f), Vector3(0, 0, 225)), owning_building_guid = 44)
+ LocalObject(767, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5515.448f, 4129.933f, 105.2687f), Vector3(0, 0, 45)), owning_building_guid = 44)
}
Building49()
- def Building49(): Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 45, MapID: 49
+ def Building49() : Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 45, MapID: 49
LocalBuilding(45, 49, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5494f, 4394f, 103.232f))))
LocalObject(270, Door.Constructor(Vector3(5487.266f, 4335.582f, 105.308f)), owning_building_guid = 45)
LocalObject(271, Door.Constructor(Vector3(5487.281f, 4342.085f, 105.308f)), owning_building_guid = 45)
@@ -939,17 +938,17 @@ object Map13 {
LocalObject(895, Terminal.Constructor(order_terminal), owning_building_guid = 45)
LocalObject(896, Terminal.Constructor(order_terminal), owning_building_guid = 45)
LocalObject(897, Terminal.Constructor(order_terminal), owning_building_guid = 45)
- LocalObject(756, SpawnTube.Constructor(Vector3(5487.272f, 4336.455f, 105.264f), Vector3(0, 0, 180)), owning_building_guid = 45)
- LocalObject(757, SpawnTube.Constructor(Vector3(5487.272f, 4341.209f, 105.264f), Vector3(0, 0, 0)), owning_building_guid = 45)
- LocalObject(758, SpawnTube.Constructor(Vector3(5493.98f, 4341.21f, 105.264f), Vector3(0, 0, 0)), owning_building_guid = 45)
- LocalObject(759, SpawnTube.Constructor(Vector3(5493.981f, 4336.455f, 105.264f), Vector3(0, 0, 180)), owning_building_guid = 45)
- LocalObject(760, SpawnTube.Constructor(Vector3(5500.688f, 4336.455f, 105.264f), Vector3(0, 0, 180)), owning_building_guid = 45)
- LocalObject(761, SpawnTube.Constructor(Vector3(5500.688f, 4341.209f, 105.264f), Vector3(0, 0, 0)), owning_building_guid = 45)
+ LocalObject(756, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5487.272f, 4336.455f, 105.264f), Vector3(0, 0, 180)), owning_building_guid = 45)
+ LocalObject(757, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5487.272f, 4341.209f, 105.264f), Vector3(0, 0, 0)), owning_building_guid = 45)
+ LocalObject(758, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5493.98f, 4341.21f, 105.264f), Vector3(0, 0, 0)), owning_building_guid = 45)
+ LocalObject(759, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5493.981f, 4336.455f, 105.264f), Vector3(0, 0, 180)), owning_building_guid = 45)
+ LocalObject(760, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5500.688f, 4336.455f, 105.264f), Vector3(0, 0, 180)), owning_building_guid = 45)
+ LocalObject(761, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5500.688f, 4341.209f, 105.264f), Vector3(0, 0, 0)), owning_building_guid = 45)
}
Building48()
- def Building48(): Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 46, MapID: 48
+ def Building48() : Unit = { // Name: VT_building_vs Type: VT_building_vs GUID: 46, MapID: 48
LocalBuilding(46, 48, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5796f, 4330f, 103.2358f))))
LocalObject(282, Door.Constructor(Vector3(5749.93f, 4293.454f, 105.3118f)), owning_building_guid = 46)
LocalObject(283, Door.Constructor(Vector3(5754.54f, 4298.042f, 105.3118f)), owning_building_guid = 46)
@@ -971,17 +970,17 @@ object Map13 {
LocalObject(927, Terminal.Constructor(order_terminal), owning_building_guid = 46)
LocalObject(928, Terminal.Constructor(order_terminal), owning_building_guid = 46)
LocalObject(929, Terminal.Constructor(order_terminal), owning_building_guid = 46)
- LocalObject(768, SpawnTube.Constructor(Vector3(5750.552f, 4294.067f, 105.2678f), Vector3(0, 0, 225)), owning_building_guid = 46)
- LocalObject(769, SpawnTube.Constructor(Vector3(5753.914f, 4297.429f, 105.2678f), Vector3(0, 0, 45)), owning_building_guid = 46)
- LocalObject(770, SpawnTube.Constructor(Vector3(5755.296f, 4289.323f, 105.2678f), Vector3(0, 0, 225)), owning_building_guid = 46)
- LocalObject(771, SpawnTube.Constructor(Vector3(5758.658f, 4292.686f, 105.2678f), Vector3(0, 0, 45)), owning_building_guid = 46)
- LocalObject(772, SpawnTube.Constructor(Vector3(5760.039f, 4284.58f, 105.2678f), Vector3(0, 0, 225)), owning_building_guid = 46)
- LocalObject(773, SpawnTube.Constructor(Vector3(5763.401f, 4287.942f, 105.2678f), Vector3(0, 0, 45)), owning_building_guid = 46)
+ LocalObject(768, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5750.552f, 4294.067f, 105.2678f), Vector3(0, 0, 225)), owning_building_guid = 46)
+ LocalObject(769, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5753.914f, 4297.429f, 105.2678f), Vector3(0, 0, 45)), owning_building_guid = 46)
+ LocalObject(770, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5755.296f, 4289.323f, 105.2678f), Vector3(0, 0, 225)), owning_building_guid = 46)
+ LocalObject(771, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5758.658f, 4292.686f, 105.2678f), Vector3(0, 0, 45)), owning_building_guid = 46)
+ LocalObject(772, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5760.039f, 4284.58f, 105.2678f), Vector3(0, 0, 225)), owning_building_guid = 46)
+ LocalObject(773, SpawnTube.Constructor(respawn_tube_sanctuary, Vector3(5763.401f, 4287.942f, 105.2678f), Vector3(0, 0, 45)), owning_building_guid = 46)
}
Building37()
- def Building37(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 47, MapID: 37
+ def Building37() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 47, MapID: 37
LocalBuilding(47, 37, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(2764f, 4842f, 56.08539f))))
LocalObject(300, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 47)
LocalObject(288, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(2767.589f, 4841.958f, 52.10039f), Vector3(0, 0, 181)), owning_building_guid = 47, terminal_guid = 300)
@@ -989,7 +988,7 @@ object Map13 {
Building24()
- def Building24(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 48, MapID: 24
+ def Building24() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 48, MapID: 24
LocalBuilding(48, 24, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(2928f, 5050f, 56.08539f))))
LocalObject(301, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 48)
LocalObject(289, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(2927.957f, 5046.411f, 52.10039f), Vector3(0, 0, -89)), owning_building_guid = 48, terminal_guid = 301)
@@ -997,7 +996,7 @@ object Map13 {
Building36()
- def Building36(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 49, MapID: 36
+ def Building36() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 49, MapID: 36
LocalBuilding(49, 36, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3018f, 4618f, 56.08539f))))
LocalObject(302, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 49)
LocalObject(290, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(3018.043f, 4621.589f, 52.10039f), Vector3(0, 0, 91)), owning_building_guid = 49, terminal_guid = 302)
@@ -1005,7 +1004,7 @@ object Map13 {
Building23()
- def Building23(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 50, MapID: 23
+ def Building23() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 50, MapID: 23
LocalBuilding(50, 23, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3212f, 4768f, 56.08539f))))
LocalObject(303, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 50)
LocalObject(291, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(3208.411f, 4768.042f, 52.10039f), Vector3(0, 0, 1)), owning_building_guid = 50, terminal_guid = 303)
@@ -1013,7 +1012,7 @@ object Map13 {
Building6()
- def Building6(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 51, MapID: 6
+ def Building6() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 51, MapID: 6
LocalBuilding(51, 6, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3506f, 2896f, 90.85538f))))
LocalObject(304, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 51)
LocalObject(292, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(3509.589f, 2895.957f, 86.87038f), Vector3(0, 0, 181)), owning_building_guid = 51, terminal_guid = 304)
@@ -1021,7 +1020,7 @@ object Map13 {
Building15()
- def Building15(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 52, MapID: 15
+ def Building15() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 52, MapID: 15
LocalBuilding(52, 15, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3572f, 2652f, 90.85646f))))
LocalObject(305, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 52)
LocalObject(293, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(3574.568f, 2654.508f, 86.87146f), Vector3(0, 0, 136)), owning_building_guid = 52, terminal_guid = 305)
@@ -1029,7 +1028,7 @@ object Map13 {
Building14()
- def Building14(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 53, MapID: 14
+ def Building14() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 53, MapID: 14
LocalBuilding(53, 14, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3808f, 2654f, 90.85372f))))
LocalObject(306, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 53)
LocalObject(294, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(3805.492f, 2656.568f, 86.86872f), Vector3(0, 0, 46)), owning_building_guid = 53, terminal_guid = 306)
@@ -1037,7 +1036,7 @@ object Map13 {
Building5()
- def Building5(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 54, MapID: 5
+ def Building5() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 54, MapID: 5
LocalBuilding(54, 5, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3876f, 2896f, 90.85098f))))
LocalObject(307, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 54)
LocalObject(295, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(3872.411f, 2896.043f, 86.86597f), Vector3(0, 0, 1)), owning_building_guid = 54, terminal_guid = 307)
@@ -1045,7 +1044,7 @@ object Map13 {
Building52()
- def Building52(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 55, MapID: 52
+ def Building52() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 55, MapID: 52
LocalBuilding(55, 52, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5394f, 4238f, 103.2297f))))
LocalObject(308, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 55)
LocalObject(296, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(5397.589f, 4237.958f, 99.24469f), Vector3(0, 0, 181)), owning_building_guid = 55, terminal_guid = 308)
@@ -1053,7 +1052,7 @@ object Map13 {
Building51()
- def Building51(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 56, MapID: 51
+ def Building51() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 56, MapID: 51
LocalBuilding(56, 51, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5600f, 4034f, 103.2345f))))
LocalObject(309, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 56)
LocalObject(297, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(5600.042f, 4037.589f, 99.24946f), Vector3(0, 0, 91)), owning_building_guid = 56, terminal_guid = 309)
@@ -1061,7 +1060,7 @@ object Map13 {
Building42()
- def Building42(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 57, MapID: 42
+ def Building42() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 57, MapID: 42
LocalBuilding(57, 42, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5622f, 4456f, 103.2351f))))
LocalObject(310, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 57)
LocalObject(298, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(5621.958f, 4452.411f, 99.25006f), Vector3(0, 0, -89)), owning_building_guid = 57, terminal_guid = 310)
@@ -1069,7 +1068,7 @@ object Map13 {
Building41()
- def Building41(): Unit = { // Name: vt_dropship Type: vt_dropship GUID: 58, MapID: 41
+ def Building41() : Unit = { // Name: vt_dropship Type: vt_dropship GUID: 58, MapID: 41
LocalBuilding(58, 41, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5834f, 4218f, 103.2365f))))
LocalObject(311, Terminal.Constructor(dropship_vehicle_terminal), owning_building_guid = 58)
LocalObject(299, VehicleSpawnPad.Constructor(dropship_pad_doors, Vector3(5830.411f, 4218.042f, 99.25149f), Vector3(0, 0, 1)), owning_building_guid = 58, terminal_guid = 311)
@@ -1077,79 +1076,79 @@ object Map13 {
Building30()
- def Building30(): Unit = { // Name: VS_NW_Tport_01 Type: vt_spawn GUID: 59, MapID: 30
+ def Building30() : Unit = { // Name: VS_NW_Tport_01 Type: vt_spawn GUID: 59, MapID: 30
LocalBuilding(59, 30, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(2900f, 4758f, 56.08539f))))
}
Building29()
- def Building29(): Unit = { // Name: VS_NW_Tport_02 Type: vt_spawn GUID: 60, MapID: 29
+ def Building29() : Unit = { // Name: VS_NW_Tport_02 Type: vt_spawn GUID: 60, MapID: 29
LocalBuilding(60, 29, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(2940f, 4932f, 56.08539f))))
}
Building32()
- def Building32(): Unit = { // Name: VS_NW_Tport_03 Type: vt_spawn GUID: 61, MapID: 32
+ def Building32() : Unit = { // Name: VS_NW_Tport_03 Type: vt_spawn GUID: 61, MapID: 32
LocalBuilding(61, 32, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3060f, 4908f, 56.08539f))))
}
Building31()
- def Building31(): Unit = { // Name: VS_NW_Tport_04 Type: vt_spawn GUID: 62, MapID: 31
+ def Building31() : Unit = { // Name: VS_NW_Tport_04 Type: vt_spawn GUID: 62, MapID: 31
LocalBuilding(62, 31, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3124f, 4776f, 56.08539f))))
}
Building19()
- def Building19(): Unit = { // Name: VS_S_Tport_03 Type: vt_spawn GUID: 63, MapID: 19
+ def Building19() : Unit = { // Name: VS_S_Tport_03 Type: vt_spawn GUID: 63, MapID: 19
LocalBuilding(63, 19, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3610f, 2732f, 90.85205f))))
}
Building18()
- def Building18(): Unit = { // Name: VS_S_Tport_01 Type: vt_spawn GUID: 64, MapID: 18
+ def Building18() : Unit = { // Name: VS_S_Tport_01 Type: vt_spawn GUID: 64, MapID: 18
LocalBuilding(64, 18, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3652f, 2908f, 90.8536f))))
}
Building21()
- def Building21(): Unit = { // Name: VS_S_Tport_02 Type: vt_spawn GUID: 65, MapID: 21
+ def Building21() : Unit = { // Name: VS_S_Tport_02 Type: vt_spawn GUID: 65, MapID: 21
LocalBuilding(65, 21, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3730f, 2908f, 90.8536f))))
}
Building20()
- def Building20(): Unit = { // Name: VS_S_Tport_04 Type: vt_spawn GUID: 66, MapID: 20
+ def Building20() : Unit = { // Name: VS_S_Tport_04 Type: vt_spawn GUID: 66, MapID: 20
LocalBuilding(66, 20, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3766f, 2732f, 90.84919f))))
}
Building45()
- def Building45(): Unit = { // Name: VS_NE_Tport_04 Type: vt_spawn GUID: 67, MapID: 45
+ def Building45() : Unit = { // Name: VS_NE_Tport_04 Type: vt_spawn GUID: 67, MapID: 45
LocalBuilding(67, 45, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5484f, 4208f, 103.2298f))))
}
Building44()
- def Building44(): Unit = { // Name: VS_NE_Tport_01 Type: vt_spawn GUID: 68, MapID: 44
+ def Building44() : Unit = { // Name: VS_NE_Tport_01 Type: vt_spawn GUID: 68, MapID: 44
LocalBuilding(68, 44, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5552f, 4344f, 103.2289f))))
}
Building46()
- def Building46(): Unit = { // Name: VS_NE_Tport_03 Type: vt_spawn GUID: 69, MapID: 46
+ def Building46() : Unit = { // Name: VS_NE_Tport_03 Type: vt_spawn GUID: 69, MapID: 46
LocalBuilding(69, 46, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5690f, 4164f, 103.2289f))))
}
Building47()
- def Building47(): Unit = { // Name: VS_NE_Tport_02 Type: vt_spawn GUID: 70, MapID: 47
+ def Building47() : Unit = { // Name: VS_NE_Tport_02 Type: vt_spawn GUID: 70, MapID: 47
LocalBuilding(70, 47, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5692f, 4312f, 103.2289f))))
}
Building26()
- def Building26(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 71, MapID: 26
+ def Building26() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 71, MapID: 26
LocalBuilding(71, 26, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(2768f, 4768f, 56.08539f))))
LocalObject(1057, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 71)
LocalObject(702, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(2767.853f, 4767.976f, 54.61439f), Vector3(0, 0, -89)), owning_building_guid = 71, terminal_guid = 1057)
@@ -1157,7 +1156,7 @@ object Map13 {
Building38()
- def Building38(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 72, MapID: 38
+ def Building38() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 72, MapID: 38
LocalBuilding(72, 38, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(2816f, 4700f, 56.08539f))))
LocalObject(1058, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 72)
LocalObject(703, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(2815.915f, 4699.877f, 54.61439f), Vector3(0, 0, 225)), owning_building_guid = 72, terminal_guid = 1058)
@@ -1165,7 +1164,7 @@ object Map13 {
Building28()
- def Building28(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 73, MapID: 28
+ def Building28() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 73, MapID: 28
LocalBuilding(73, 28, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(2946f, 4622f, 56.08539f))))
LocalObject(1059, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 73)
LocalObject(704, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(2946.024f, 4621.853f, 54.61439f), Vector3(0, 0, 181)), owning_building_guid = 73, terminal_guid = 1059)
@@ -1173,7 +1172,7 @@ object Map13 {
Building25()
- def Building25(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 74, MapID: 25
+ def Building25() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 74, MapID: 25
LocalBuilding(74, 25, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3000f, 5048f, 56.08539f))))
LocalObject(1060, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 74)
LocalObject(705, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(2999.976f, 5048.147f, 54.61439f), Vector3(0, 0, 1)), owning_building_guid = 74, terminal_guid = 1060)
@@ -1181,7 +1180,7 @@ object Map13 {
Building39()
- def Building39(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 75, MapID: 39
+ def Building39() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 75, MapID: 39
LocalBuilding(75, 39, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3094f, 5010f, 56.08539f))))
LocalObject(1061, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 75)
LocalObject(706, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(3094.085f, 5010.123f, 54.61439f), Vector3(0, 0, 45)), owning_building_guid = 75, terminal_guid = 1061)
@@ -1189,7 +1188,7 @@ object Map13 {
Building27()
- def Building27(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 76, MapID: 27
+ def Building27() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 76, MapID: 27
LocalBuilding(76, 27, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3212f, 4842f, 56.08539f))))
LocalObject(1062, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 76)
LocalObject(707, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(3212.147f, 4842.024f, 54.61439f), Vector3(0, 0, 91)), owning_building_guid = 76, terminal_guid = 1062)
@@ -1197,7 +1196,7 @@ object Map13 {
Building17()
- def Building17(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 77, MapID: 17
+ def Building17() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 77, MapID: 17
LocalBuilding(77, 17, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3506f, 2820f, 90.8536f))))
LocalObject(1063, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 77)
LocalObject(708, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(3505.853f, 2819.976f, 89.3826f), Vector3(0, 0, -89)), owning_building_guid = 77, terminal_guid = 1063)
@@ -1205,7 +1204,7 @@ object Map13 {
Building8()
- def Building8(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 78, MapID: 8
+ def Building8() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 78, MapID: 8
LocalBuilding(78, 8, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3658f, 3020f, 90.8536f))))
LocalObject(1064, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 78)
LocalObject(709, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(3657.976f, 3020.147f, 89.3826f), Vector3(0, 0, 1)), owning_building_guid = 78, terminal_guid = 1064)
@@ -1213,7 +1212,7 @@ object Map13 {
Building11()
- def Building11(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 79, MapID: 11
+ def Building11() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 79, MapID: 11
LocalBuilding(79, 11, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3660f, 2590f, 90.8536f))))
LocalObject(1065, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 79)
LocalObject(710, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(3660.024f, 2589.853f, 89.3826f), Vector3(0, 0, 181)), owning_building_guid = 79, terminal_guid = 1065)
@@ -1221,7 +1220,7 @@ object Map13 {
Building9()
- def Building9(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 80, MapID: 9
+ def Building9() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 80, MapID: 9
LocalBuilding(80, 9, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3722f, 3020f, 90.8536f))))
LocalObject(1066, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 80)
LocalObject(711, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(3721.976f, 3020.147f, 89.3826f), Vector3(0, 0, 1)), owning_building_guid = 80, terminal_guid = 1066)
@@ -1229,7 +1228,7 @@ object Map13 {
Building10()
- def Building10(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 81, MapID: 10
+ def Building10() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 81, MapID: 10
LocalBuilding(81, 10, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3724f, 2588f, 90.85265f))))
LocalObject(1067, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 81)
LocalObject(712, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(3724.024f, 2587.853f, 89.38165f), Vector3(0, 0, 181)), owning_building_guid = 81, terminal_guid = 1067)
@@ -1237,7 +1236,7 @@ object Map13 {
Building16()
- def Building16(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 82, MapID: 16
+ def Building16() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 82, MapID: 16
LocalBuilding(82, 16, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(3878f, 2824f, 90.8536f))))
LocalObject(1068, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 82)
LocalObject(713, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(3878.147f, 2824.024f, 89.3826f), Vector3(0, 0, 91)), owning_building_guid = 82, terminal_guid = 1068)
@@ -1245,7 +1244,7 @@ object Map13 {
Building55()
- def Building55(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 83, MapID: 55
+ def Building55() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 83, MapID: 55
LocalBuilding(83, 55, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5420f, 4174f, 103.2318f))))
LocalObject(1069, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 83)
LocalObject(714, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(5419.853f, 4173.976f, 101.7608f), Vector3(0, 0, -89)), owning_building_guid = 83, terminal_guid = 1069)
@@ -1253,7 +1252,7 @@ object Map13 {
Building43()
- def Building43(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 84, MapID: 43
+ def Building43() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 84, MapID: 43
LocalBuilding(84, 43, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5420f, 4298f, 103.2333f))))
LocalObject(1070, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 84)
LocalObject(715, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(5419.853f, 4297.976f, 101.7623f), Vector3(0, 0, -89)), owning_building_guid = 84, terminal_guid = 1070)
@@ -1261,7 +1260,7 @@ object Map13 {
Building54()
- def Building54(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 85, MapID: 54
+ def Building54() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 85, MapID: 54
LocalBuilding(85, 54, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5686f, 4420f, 103.2329f))))
LocalObject(1071, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 85)
LocalObject(716, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(5686.085f, 4420.123f, 101.7619f), Vector3(0, 0, 45)), owning_building_guid = 85, terminal_guid = 1071)
@@ -1269,7 +1268,7 @@ object Map13 {
Building57()
- def Building57(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 86, MapID: 57
+ def Building57() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 86, MapID: 57
LocalBuilding(86, 57, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5710f, 4046f, 103.2289f))))
LocalObject(1072, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 86)
LocalObject(717, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(5710.123f, 4045.915f, 101.7579f), Vector3(0, 0, 135)), owning_building_guid = 86, terminal_guid = 1072)
@@ -1277,7 +1276,7 @@ object Map13 {
Building53()
- def Building53(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 87, MapID: 53
+ def Building53() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 87, MapID: 53
LocalBuilding(87, 53, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5752f, 4088f, 103.2289f))))
LocalObject(1073, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 87)
LocalObject(718, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(5752.123f, 4087.915f, 101.7579f), Vector3(0, 0, 135)), owning_building_guid = 87, terminal_guid = 1073)
@@ -1285,10 +1284,22 @@ object Map13 {
Building56()
- def Building56(): Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 88, MapID: 56
+ def Building56() : Unit = { // Name: vt_vehicle Type: vt_vehicle GUID: 88, MapID: 56
LocalBuilding(88, 56, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(5794f, 4132f, 103.2289f))))
LocalObject(1074, Terminal.Constructor(ground_vehicle_terminal), owning_building_guid = 88)
LocalObject(719, VehicleSpawnPad.Constructor(mb_pad_creation, Vector3(5794.123f, 4131.915f, 101.7579f), Vector3(0, 0, 135)), owning_building_guid = 88, terminal_guid = 1074)
}
+
+ Building1()
+
+ def Building1() : Unit = { // Name: ??? Type: ??? GUID: 90, MapID: 1
+ LocalBuilding(90, 1, FoundationBuilder(WarpGate.Structure(Vector3(2514.6094f, 5311.7656f, 65.984375f))))
+ }
+
+ Building3()
+
+ def Building3() : Unit = { // Name: ??? Type: ??? GUID: 89, MapID: 3
+ LocalBuilding(89, 3, FoundationBuilder(WarpGate.Structure(Vector3(4175.6484f, 2402.8125f, 163.9375f))))
+ }
}
}