diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala
index 3d1bbc0f..14c8fbfe 100644
--- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala
+++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala
@@ -12,6 +12,7 @@ import net.psforever.objects.serverobject.locks.IFFLockDefinition
import net.psforever.objects.serverobject.mblocker.LockerDefinition
import net.psforever.objects.serverobject.pad.VehicleSpawnPadDefinition
import net.psforever.objects.serverobject.terminals._
+import net.psforever.objects.serverobject.tube.SpawnTubeDefinition
import net.psforever.objects.vehicles.{SeatArmorRestriction, UtilityType}
import net.psforever.types.PlanetSideEmpire
@@ -486,6 +487,10 @@ object GlobalDefinitions {
*/
val order_terminal = new OrderTerminalDefinition
+ val ams_respawn_tube = new SpawnTubeDefinition(49) { Name = "ams_respawn_tube" }
+
+ val matrix_terminalc = new MatrixTerminalDefinition(519)
+
val order_terminala = new OrderTerminalABDefinition(613)
val order_terminalb = new OrderTerminalABDefinition(614)
@@ -2347,6 +2352,8 @@ object GlobalDefinitions {
ams.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
ams.MountPoints += 1 -> 0
ams.MountPoints += 2 -> 0
+ ams.Utilities += 1 -> UtilityType.matrix_terminalc
+ ams.Utilities += 2 -> UtilityType.ams_respawn_tube
ams.Utilities += 3 -> UtilityType.order_terminala
ams.Utilities += 4 -> UtilityType.order_terminalb
ams.Deployment = true
diff --git a/common/src/main/scala/net/psforever/objects/definition/converter/SpawnTubeConverter.scala b/common/src/main/scala/net/psforever/objects/definition/converter/SpawnTubeConverter.scala
new file mode 100644
index 00000000..56671f98
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/definition/converter/SpawnTubeConverter.scala
@@ -0,0 +1,11 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.definition.converter
+
+import net.psforever.objects.serverobject.tube.SpawnTube
+import net.psforever.packet.game.objectcreate.CommonTerminalData
+
+import scala.util.{Success, Try}
+
+class SpawnTubeConverter extends ObjectCreateConverter[SpawnTube]() {
+ override def ConstructorData(obj : SpawnTube) : Try[CommonTerminalData] = { Success(CommonTerminalData(obj.Faction)) }
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/MatrixTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/MatrixTerminalDefinition.scala
new file mode 100644
index 00000000..047e786d
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/MatrixTerminalDefinition.scala
@@ -0,0 +1,42 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.terminals
+
+import akka.actor.ActorContext
+import net.psforever.objects.Player
+import net.psforever.objects.serverobject.structures.Amenity
+import net.psforever.packet.game.ItemTransactionMessage
+
+/**
+ * The definition for any `Terminal` that is of a type "matrix_terminal".
+ */
+class MatrixTerminalDefinition(object_id : Int) extends TerminalDefinition(object_id) {
+ Name = if(object_id == 517) {
+ "matrix_terminala"
+ }
+ else if(object_id == 518) {
+ "matrix_terminalb"
+ }
+ else if(object_id == 519) {
+ "matrix_terminalc"
+ }
+ else {
+ throw new IllegalArgumentException("terminal must be object id 517-519")
+ }
+
+ override def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = Terminal.NoDeal()
+}
+
+object MatrixTerminalDefinition {
+ /**
+ * Assemble some logic for a provided object.
+ * @param obj an `Amenity` object;
+ * anticipating a `Terminal` object using this same definition
+ * @param context hook to the local `Actor` system
+ */
+ def Setup(obj : Amenity, context : ActorContext) : Unit = {
+ import akka.actor.{ActorRef, Props}
+ if(obj.Actor == ActorRef.noSender) {
+ obj.Actor = context.actorOf(Props(classOf[TerminalControl], obj), s"${obj.Definition.Name}_${obj.GUID.guid}")
+ }
+ }
+}
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
new file mode 100644
index 00000000..9d9baac9
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTube.scala
@@ -0,0 +1,34 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.tube
+
+import net.psforever.objects.definition.ObjectDefinition
+import net.psforever.objects.serverobject.structures.Amenity
+
+class SpawnTube(tubeDef : ObjectDefinition) extends Amenity {
+ def Definition : ObjectDefinition = tubeDef
+}
+
+object SpawnTube {
+ def apply(tubeDef : ObjectDefinition) : SpawnTube = {
+ new SpawnTube(tubeDef)
+ }
+
+// import akka.actor.ActorContext
+// import net.psforever.types.Vector3
+// /**
+// * Instantiate an configure a `SpawnTube` object
+// * @param pos the position (used to determine spawn point)
+// * @param orient the orientation (used to indicate spawn direction)
+// * @param id the unique id that will be assigned to this entity
+// * @param context a context to allow the object to properly set up `ActorSystem` functionality
+// * @return the `SpawnTube` object
+// */
+// def Constructor(pos : Vector3, orient : Vector3)(id : Int, context : ActorContext) : SpawnTube = {
+// import net.psforever.objects.GlobalDefinitions
+//
+// val obj = SpawnTube(GlobalDefinitions.ams_respawn_tube)
+// obj.Position = pos
+// obj.Orientation = orient
+// obj
+// }
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeControl.scala
new file mode 100644
index 00000000..5b47ffe4
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeControl.scala
@@ -0,0 +1,17 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.tube
+
+import akka.actor.Actor
+import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
+
+/**
+ * An `Actor` that handles messages being dispatched to a specific `SpawnTube`.
+ * @param tube the `SpawnTube` object being governed
+ */
+class SpawnTubeControl(tube : SpawnTube) extends Actor with FactionAffinityBehavior.Check {
+ def FactionObject : FactionAffinity = tube
+
+ def receive : Receive = checkBehavior.orElse { case _ =>; }
+
+ override def toString : String = tube.Definition.Name
+}
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
new file mode 100644
index 00000000..774449c0
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/tube/SpawnTubeDefinition.scala
@@ -0,0 +1,26 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.tube
+
+import akka.actor.ActorContext
+import net.psforever.objects.definition.ObjectDefinition
+import net.psforever.objects.definition.converter.SpawnTubeConverter
+import net.psforever.objects.serverobject.structures.Amenity
+
+class SpawnTubeDefinition(object_id : Int) extends ObjectDefinition(object_id) {
+ Packet = new SpawnTubeConverter
+}
+
+object SpawnTubeDefinition {
+ /**
+ * Assemble some logic for a provided object.
+ * @param obj an `Amenity` object;
+ * anticipating a `Terminal` object using this same definition
+ * @param context hook to the local `Actor` system
+ */
+ def Setup(obj : Amenity, context : ActorContext) : Unit = {
+ import akka.actor.{ActorRef, Props}
+ if(obj.Actor == ActorRef.noSender) {
+ obj.Actor = context.actorOf(Props(classOf[SpawnTubeControl], obj), s"${obj.Definition.Name}_${obj.GUID.guid}")
+ }
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala b/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala
index 5259c325..dc7dfe27 100644
--- a/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala
+++ b/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala
@@ -4,7 +4,8 @@ package net.psforever.objects.vehicles
import akka.actor.ActorContext
import net.psforever.objects.{GlobalDefinitions, Vehicle}
import net.psforever.objects.serverobject.structures.Amenity
-import net.psforever.objects.serverobject.terminals.{OrderTerminalABDefinition, Terminal}
+import net.psforever.objects.serverobject.terminals.{MatrixTerminalDefinition, OrderTerminalABDefinition, Terminal, TerminalDefinition}
+import net.psforever.objects.serverobject.tube.{SpawnTube, SpawnTubeDefinition}
/**
* An `Enumeration` of the available vehicular utilities.
@@ -17,6 +18,8 @@ import net.psforever.objects.serverobject.terminals.{OrderTerminalABDefinition,
object UtilityType extends Enumeration {
type Type = Value
val
+ ams_respawn_tube,
+ matrix_terminalc,
order_terminala,
order_terminalb
= Value
@@ -83,10 +86,32 @@ object Utility {
* @return the `Amenity` object
*/
private def BuildUtilityFunc(util : UtilityType.Value) : Amenity = util match {
+ case UtilityType.ams_respawn_tube =>
+ new SpawnTubeUtility(GlobalDefinitions.ams_respawn_tube)
+ case UtilityType.matrix_terminalc =>
+ new TerminalUtility(GlobalDefinitions.matrix_terminalc)
case UtilityType.order_terminala =>
- Terminal(GlobalDefinitions.order_terminala)
+ new TerminalUtility(GlobalDefinitions.order_terminala)
case UtilityType.order_terminalb =>
- Terminal(GlobalDefinitions.order_terminalb)
+ new TerminalUtility(GlobalDefinitions.order_terminalb)
+ }
+
+ /**
+ * Override for `SpawnTube` objects so that they inherit the spatial characteristics of their `Owner`.
+ * @param tubeDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
+ */
+ private class SpawnTubeUtility(tubeDef : SpawnTubeDefinition) extends SpawnTube(tubeDef) {
+ override def Position = Owner.Position
+ override def Orientation = Owner.Orientation
+ }
+
+ /**
+ * Override for `Terminal` objects so that they inherit the spatial characteristics of their `Owner`.
+ * @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
+ */
+ private class TerminalUtility(tdef : TerminalDefinition) extends Terminal(tdef) {
+ override def Position = Owner.Position
+ override def Orientation = Owner.Orientation
}
/**
@@ -95,6 +120,10 @@ object Utility {
* @return the `Amenity` object
*/
private def SelectUtilitySetupFunc(util : UtilityType.Value) : UtilLogic = util match {
+ case UtilityType.ams_respawn_tube =>
+ SpawnTubeDefinition.Setup
+ case UtilityType.matrix_terminalc =>
+ MatrixTerminalDefinition.Setup
case UtilityType.order_terminala =>
OrderTerminalABDefinition.Setup
case UtilityType.order_terminalb =>
diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala
index 431aca9f..21ae82f6 100644
--- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala
+++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala
@@ -332,7 +332,7 @@ object GamePacketOpcode extends Enumeration {
case 0x09 => game.HitMessage.decode
case 0x0a => game.HitHint.decode
case 0x0b => noDecoder(DamageMessage)
- case 0x0c => noDecoder(DestroyMessage)
+ case 0x0c => game.DestroyMessage.decode
case 0x0d => game.ReloadMessage.decode
case 0x0e => game.MountVehicleMsg.decode
case 0x0f => game.DismountVehicleMsg.decode
@@ -406,7 +406,7 @@ object GamePacketOpcode extends Enumeration {
// 0x48
case 0x48 => game.TimeOfDayMessage.decode
case 0x49 => noDecoder(UnknownMessage73)
- case 0x4a => noDecoder(SpawnRequestMessage)
+ case 0x4a => game.SpawnRequestMessage.decode
case 0x4b => game.DeployRequestMessage.decode
case 0x4c => noDecoder(UnknownMessage76)
case 0x4d => game.RepairMessage.decode
diff --git a/common/src/main/scala/net/psforever/packet/game/AvatarDeadStateMessage.scala b/common/src/main/scala/net/psforever/packet/game/AvatarDeadStateMessage.scala
index 57b3b685..4b7ad326 100644
--- a/common/src/main/scala/net/psforever/packet/game/AvatarDeadStateMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/AvatarDeadStateMessage.scala
@@ -1,23 +1,36 @@
// Copyright (c) 2017 PSForever
package net.psforever.packet.game
-import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
+import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
import net.psforever.types.Vector3
import scodec.Codec
import scodec.codecs._
+object DeadState extends Enumeration {
+ type Type = Value
+
+ val
+ Nothing,
+ Dead,
+ Release,
+ RespawnTime
+ = Value
+
+ implicit val codec = PacketHelpers.createEnumerationCodec(this, uintL(3))
+}
+
/**
* na
- * @param unk1 0 = nothing, 1 = waiting for a rez, 2 = auto map to select spawn, 3 = respawn time
- * @param unk2 na
- * @param unk3 spawn penality
- * @param pos last victim's position
+ * @param state avatar's relationship with the world
+ * @param timer_max total length of respawn countdown, in milliseconds
+ * @param timer initial length of the respawn timer, in milliseconds
+ * @param pos last position
* @param unk4 na
* @param unk5 na
*/
-final case class AvatarDeadStateMessage(unk1 : Int,
- unk2 : Long,
- unk3 : Long,
+final case class AvatarDeadStateMessage(state : DeadState.Value,
+ timer_max : Long,
+ timer : Long,
pos : Vector3,
unk4 : Long,
unk5 : Boolean)
@@ -29,9 +42,9 @@ final case class AvatarDeadStateMessage(unk1 : Int,
object AvatarDeadStateMessage extends Marshallable[AvatarDeadStateMessage] {
implicit val codec : Codec[AvatarDeadStateMessage] = (
- ("unk1" | uintL(3)) ::
- ("unk2" | uint32L) ::
- ("unk3" | uint32L) ::
+ ("state" | DeadState.codec) ::
+ ("timer_max" | uint32L) ::
+ ("timer" | uint32L) ::
("pos" | Vector3.codec_pos) ::
("unk4" | uint32L) ::
("unk5" | bool)
diff --git a/common/src/main/scala/net/psforever/packet/game/DestroyMessage.scala b/common/src/main/scala/net/psforever/packet/game/DestroyMessage.scala
new file mode 100644
index 00000000..fdf6021b
--- /dev/null
+++ b/common/src/main/scala/net/psforever/packet/game/DestroyMessage.scala
@@ -0,0 +1,26 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.packet.game
+
+import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
+import net.psforever.types.Vector3
+import scodec.Codec
+import scodec.codecs._
+
+final case class DestroyMessage(unk1 : PlanetSideGUID,
+ unk2 : PlanetSideGUID,
+ unk3 : PlanetSideGUID,
+ pos : Vector3)
+ extends PlanetSideGamePacket {
+ type Packet = DestroyMessage
+ def opcode = GamePacketOpcode.DestroyMessage
+ def encode = DestroyMessage.encode(this)
+}
+
+object DestroyMessage extends Marshallable[DestroyMessage] {
+ implicit val codec : Codec[DestroyMessage] = (
+ ("unk1" | PlanetSideGUID.codec) ::
+ ("unk2" | PlanetSideGUID.codec) ::
+ ("unk3" | PlanetSideGUID.codec) ::
+ ("pos" | Vector3.codec_pos)
+ ).as[DestroyMessage]
+}
diff --git a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
index 036bd5ff..5d0dc875 100644
--- a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
@@ -6,6 +6,37 @@ import scodec.Codec
import scodec.codecs._
/**
+ * na
+ * Global:
+ * `50 - Common Initialization?`
+ * `51 - Common Initialization?`
+ * `67 - ???`
+ *
+ * Global (GUID=0)
+ * `82 - ???`
+ * `83 - max boomers`
+ * `84 - max he mines`
+ * `85 - max disruptor mines`
+ * `86 - max spitfire turrets`
+ * `87 - max motion sensors`
+ * `88 - max shadow turrets`
+ * `89 - max cerebus turrets`
+ * `90 - max Aegis shield generators`
+ * `91 - max TRAPs`
+ * `92 - max OMFTs`
+ * `93 - max sensor disruptors`
+ * `94 - boomers`
+ * `95 - he mines`
+ * `96 - disruptor mines`
+ * `97 - spitfire turrets`
+ * `98 - motion sensors`
+ * `99 - shadow turrets`
+ * `100 - cerebus turrets`
+ * `101 - Aegis shield generators`
+ * `102 - TRAPSs`
+ * `103 - OMFTs`
+ * `104 - sensor disruptors`
+ *
* Players/General:
* Server to client :
* `0 - health`
@@ -74,31 +105,33 @@ import scodec.codecs._
* `36 - CR. Value is the CR`
* `43 - Info on avatar name : 0 = Nothing, 1 = "(LD)" message`
* `53 - LFS. Value is 1 to flag LFS`
- * `54 - Player "Aura". Values are : 0 for nothing, 1 for plasma, 2 for ancient, 3 for plasma + ancient,
- * 4 for LLU?, 5 for plasma + LLU?, 6 for ancient + LLU?, 7 for plasma + ancient + LLU?, 8 for fire,
- * 9 for plasma + fire, 10 for ancient + fire, 11 for plasma + ancient + fire,
- * 12 for LLU? + fire, 13 for plasma + LLU? + fire, 14 for ancient + LLU? + fire,
- * 15 for plasma + ancient + LLU? + fire,`
+ * `54 - Player "Aura". Values can be expressed in the first byte's lower nibble:`
+ * - 0 is nothing
+ * - 1 is plasma
+ * - 2 is ancient
+ * - 4 is LLU (?)
+ * - 8 is fire
+ * -- e.g., 13 = 8 + 4 + 1 = fire and LLU and plasma
* `55 - "Someone is attempting to Heal you". Value is 1`
* `56 - "Someone is attempting to Repair you". Value is 1`
* `73 - "You are locked into the Core Beam. Charging your Module now.". Value is 1 to active`
* `77 - Cavern Facility Captures. Value is the number of captures`
* `78 - Cavern Kills. Value is the number of kills`
- * `106 - Custom Head`
+ * `106 - Custom Head`
* Client to Server :
* `106 - Custom Head`
*
- * Vehicles:
- * 0 - Vehicle base health
- * 10 - Driver seat permissions (0 = Locked, 1 = Group, 3 = Empire)
- * 11 - Gunner seat(s) permissions (same)
- * 12 - Passenger seat(s) permissions (same)
- * 13 - Trunk permissions (same)
- * 21 - Asserts first time event eligibility / makes owner if no owner is assigned
- * 22 - Toggles gunner and passenger mount points (1 = hides, 0 = reveals; this also locks their permissions)
- * 68 - ???
- * 80 - Damage vehicle (unknown value)
- * 113 - ???
+ * `Vehicles:`
+ * `10 - Driver seat permissions (0 = Locked, 1 = Group, 3 = Empire)`
+ * `11 - Gunner seat(s) permissions (same)`
+ * `12 - Passenger seat(s) permissions (same)`
+ * `13 - Trunk permissions (same)`
+ * `21 - Asserts first time event eligibility / makes owner if no owner is assigned`
+ * `22 - Toggles gunner and passenger mount points (1 = hides, 0 = reveals; this also locks their permissions)`
+ * `68 - ???`
+ * `80 - Damage vehicle (unknown value)`
+ * `81 - ???`
+ * `113 - ???`
* @param player_guid the player
* @param attribute_type na
* @param attribute_value na
diff --git a/common/src/main/scala/net/psforever/packet/game/SpawnRequestMessage.scala b/common/src/main/scala/net/psforever/packet/game/SpawnRequestMessage.scala
new file mode 100644
index 00000000..cbb35a95
--- /dev/null
+++ b/common/src/main/scala/net/psforever/packet/game/SpawnRequestMessage.scala
@@ -0,0 +1,28 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.packet.game
+
+import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
+import scodec.Codec
+import scodec.codecs._
+
+
+final case class SpawnRequestMessage(unk1 : Int,
+ unk2 : Long,
+ unk3 : Int,
+ unk4 : Int,
+ unk5 : Int)
+ extends PlanetSideGamePacket {
+ type Packet = SpawnRequestMessage
+ def opcode = GamePacketOpcode.SpawnRequestMessage
+ def encode = SpawnRequestMessage.encode(this)
+}
+
+object SpawnRequestMessage extends Marshallable[SpawnRequestMessage] {
+ implicit val codec : Codec[SpawnRequestMessage] = (
+ ("unk1" | uint16L) ::
+ ("unk2" | uint32L) ::
+ ("unk3" | uint16L) ::
+ ("unk4" | uint16L) ::
+ ("unk5" | uintL(10))
+ ).as[SpawnRequestMessage]
+}
diff --git a/common/src/test/scala/game/AvatarDeadStateMessageTest.scala b/common/src/test/scala/game/AvatarDeadStateMessageTest.scala
index 69e31d24..ef874727 100644
--- a/common/src/test/scala/game/AvatarDeadStateMessageTest.scala
+++ b/common/src/test/scala/game/AvatarDeadStateMessageTest.scala
@@ -13,7 +13,7 @@ class AvatarDeadStateMessageTest extends Specification {
"decode" in {
PacketCoding.DecodePacket(string).require match {
case AvatarDeadStateMessage(unk1,unk2,unk3,pos,unk4,unk5) =>
- unk1 mustEqual 1
+ unk1 mustEqual DeadState.Dead
unk2 mustEqual 300000
unk3 mustEqual 300000
pos mustEqual Vector3(6552.617f,4602.375f,60.90625f)
@@ -25,7 +25,7 @@ class AvatarDeadStateMessageTest extends Specification {
}
"encode" in {
- val msg = AvatarDeadStateMessage(1, 300000, 300000, Vector3(6552.617f,4602.375f,60.90625f), 2, true)
+ val msg = AvatarDeadStateMessage(DeadState.Dead, 300000, 300000, Vector3(6552.617f,4602.375f,60.90625f), 2, true)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual string
diff --git a/common/src/test/scala/game/DestroyMessageTest.scala b/common/src/test/scala/game/DestroyMessageTest.scala
new file mode 100644
index 00000000..ac5314ae
--- /dev/null
+++ b/common/src/test/scala/game/DestroyMessageTest.scala
@@ -0,0 +1,33 @@
+// Copyright (c) 2017 PSForever
+package game
+
+import org.specs2.mutable._
+import net.psforever.packet._
+import net.psforever.packet.game._
+import net.psforever.types.Vector3
+import scodec.bits._
+
+class DestroyMessageTest extends Specification {
+ val string = hex"0C 74 09 74 09 00 00 06 35 3C FF D7 26 08"
+
+ "DestroyMessage" should {
+ "decode" in {
+ PacketCoding.DecodePacket(string).require match {
+ case DestroyMessage(unk1, unk2, unk3, pos) =>
+ unk1 mustEqual PlanetSideGUID(2420)
+ unk2 mustEqual PlanetSideGUID(2420)
+ unk3 mustEqual PlanetSideGUID(0)
+ pos mustEqual Vector3(1642.0469f, 4091.6172f, 32.59375f)
+ case _ =>
+ ko
+ }
+ }
+
+ "encode" in {
+ val msg = DestroyMessage(PlanetSideGUID(2420), PlanetSideGUID(2420), PlanetSideGUID(0), Vector3(1642.0469f, 4091.6172f, 32.59375f))
+ val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
+
+ pkt mustEqual string
+ }
+ }
+}
diff --git a/common/src/test/scala/game/SpawnRequestMessageTest.scala b/common/src/test/scala/game/SpawnRequestMessageTest.scala
new file mode 100644
index 00000000..adab70f2
--- /dev/null
+++ b/common/src/test/scala/game/SpawnRequestMessageTest.scala
@@ -0,0 +1,31 @@
+// Copyright (c) 2017 PSForever
+package game
+
+import org.specs2.mutable._
+import net.psforever.packet._
+import net.psforever.packet.game._
+import scodec.bits._
+
+class SpawnRequestMessageTest extends Specification {
+ val string = hex"4a000007000000000000000200"
+
+ "decode" in {
+ PacketCoding.DecodePacket(string).require match {
+ case SpawnRequestMessage(unk1,unk2,unk3,unk4,unk5) =>
+ unk1 mustEqual 0
+ unk2 mustEqual 7
+ unk3 mustEqual 0
+ unk4 mustEqual 0
+ unk5 mustEqual 2
+ case _ =>
+ ko
+ }
+ }
+
+ "encode" in {
+ val msg = SpawnRequestMessage(0, 7, 0, 0, 2)
+ val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
+
+ pkt mustEqual string
+ }
+}
diff --git a/common/src/test/scala/objects/ConverterTest.scala b/common/src/test/scala/objects/ConverterTest.scala
index 723c248f..57d8fc86 100644
--- a/common/src/test/scala/objects/ConverterTest.scala
+++ b/common/src/test/scala/objects/ConverterTest.scala
@@ -1,7 +1,6 @@
// Copyright (c) 2017 PSForever
package objects
-import net.psforever.objects.GlobalDefinitions.remote_electronics_kit
import net.psforever.objects.definition.converter.{ACEConverter, CharacterSelectConverter, REKConverter}
import net.psforever.objects._
import net.psforever.objects.definition._
@@ -9,6 +8,7 @@ import net.psforever.objects.equipment.CItem.{DeployedItem, Unit}
import net.psforever.objects.equipment._
import net.psforever.objects.inventory.InventoryTile
import net.psforever.objects.serverobject.terminals.Terminal
+import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.packet.game.objectcreate._
import net.psforever.types.{CharacterGender, PlanetSideEmpire, Vector3}
@@ -184,13 +184,13 @@ class ConverterTest extends Specification {
"convert to packet (BR < 24)" in {
obj.BEP = 0
obj.Definition.Packet.DetailedConstructorData(obj) match {
- case Success(pkt) =>
+ case Success(_) =>
ok
case _ =>
ko
}
obj.Definition.Packet.ConstructorData(obj) match {
- case Success(pkt) =>
+ case Success(_) =>
ok
case _ =>
ko
@@ -200,13 +200,13 @@ class ConverterTest extends Specification {
"convert to packet (BR >= 24)" in {
obj.BEP = 10000000
obj.Definition.Packet.DetailedConstructorData(obj) match {
- case Success(pkt) =>
+ case Success(_) =>
ok
case _ =>
ko
}
obj.Definition.Packet.ConstructorData(obj) match {
- case Success(pkt) =>
+ case Success(_) =>
ok
case _ =>
ko
@@ -216,7 +216,7 @@ class ConverterTest extends Specification {
"convert to simple packet (BR < 24)" in {
obj.BEP = 0
converter.DetailedConstructorData(obj) match {
- case Success(pkt) =>
+ case Success(_) =>
ok
case _ =>
ko
@@ -228,7 +228,7 @@ class ConverterTest extends Specification {
"convert to simple packet (BR >= 24)" in {
obj.BEP = 10000000
converter.DetailedConstructorData(obj) match {
- case Success(pkt) =>
+ case Success(_) =>
ok
case _ =>
ko
@@ -290,7 +290,27 @@ class ConverterTest extends Specification {
obj.Definition.Packet.ConstructorData(obj) match {
case Success(pkt) =>
- pkt mustEqual CommonTerminalData(PlanetSideEmpire.NEUTRAL, 0)
+ pkt mustEqual CommonTerminalData(PlanetSideEmpire.NEUTRAL)
+ case _ =>
+ ko
+ }
+ }
+ }
+
+ "Spawn Tube" should {
+ "convert to packet" in {
+ val obj = SpawnTube(GlobalDefinitions.ams_respawn_tube)
+
+ obj.Definition.Packet.DetailedConstructorData(obj) match {
+ case Failure(err) =>
+ err.isInstanceOf[NoSuchMethodException] mustEqual true
+ case _ =>
+ ko
+ }
+
+ obj.Definition.Packet.ConstructorData(obj) match {
+ case Success(pkt) =>
+ pkt mustEqual CommonTerminalData(PlanetSideEmpire.NEUTRAL)
case _ =>
ko
}
@@ -338,8 +358,10 @@ class ConverterTest extends Specification {
val
ams = Vehicle(GlobalDefinitions.ams)
ams.GUID = PlanetSideGUID(413)
- ams.Utilities(3)().GUID = PlanetSideGUID(414)
- ams.Utilities(4)().GUID = PlanetSideGUID(415)
+ ams.Utilities(1)().GUID = PlanetSideGUID(414)
+ ams.Utilities(2)().GUID = PlanetSideGUID(415)
+ ams.Utilities(3)().GUID = PlanetSideGUID(416)
+ ams.Utilities(4)().GUID = PlanetSideGUID(417)
ams.Definition.Packet.ConstructorData(ams).isSuccess mustEqual true
ok //TODO write more of this test
diff --git a/common/src/test/scala/objects/UtilityTest.scala b/common/src/test/scala/objects/UtilityTest.scala
index ef78af4b..97b46d75 100644
--- a/common/src/test/scala/objects/UtilityTest.scala
+++ b/common/src/test/scala/objects/UtilityTest.scala
@@ -27,6 +27,49 @@ class UtilityTest extends Specification {
obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 614
obj().asInstanceOf[Terminal].Actor == ActorRef.noSender
}
+
+ "create a matrix_terminalc object" in {
+ val obj = Utility(UtilityType.matrix_terminalc, UtilityTest.vehicle)
+ obj.UtilType mustEqual UtilityType.matrix_terminalc
+ obj().isInstanceOf[Terminal] mustEqual true
+ obj().asInstanceOf[Terminal].Definition.ObjectId mustEqual 519
+ obj().asInstanceOf[Terminal].Actor == ActorRef.noSender
+ }
+
+ "create an ams_respawn_tube object" in {
+ import net.psforever.objects.serverobject.tube.SpawnTube
+ val obj = Utility(UtilityType.ams_respawn_tube, UtilityTest.vehicle)
+ obj.UtilType mustEqual UtilityType.ams_respawn_tube
+ obj().isInstanceOf[SpawnTube] mustEqual true
+ obj().asInstanceOf[SpawnTube].Definition.ObjectId mustEqual 49
+ obj().asInstanceOf[SpawnTube].Actor == ActorRef.noSender
+ }
+
+ "be located with their owner (terminal)" in {
+ val veh = Vehicle(GlobalDefinitions.quadstealth)
+ val obj = Utility(UtilityType.order_terminala, veh)
+ obj().Position mustEqual veh.Position
+ obj().Orientation mustEqual veh.Orientation
+
+ import net.psforever.types.Vector3
+ veh.Position = Vector3(1, 2, 3)
+ veh.Orientation = Vector3(4, 5, 6)
+ obj().Position mustEqual veh.Position
+ obj().Orientation mustEqual veh.Orientation
+ }
+
+ "be located with their owner (spawn tube)" in {
+ val veh = Vehicle(GlobalDefinitions.quadstealth)
+ val obj = Utility(UtilityType.ams_respawn_tube, veh)
+ obj().Position mustEqual veh.Position
+ obj().Orientation mustEqual veh.Orientation
+
+ import net.psforever.types.Vector3
+ veh.Position = Vector3(1, 2, 3)
+ veh.Orientation = Vector3(4, 5, 6)
+ obj().Position mustEqual veh.Position
+ obj().Orientation mustEqual veh.Orientation
+ }
}
}
@@ -58,6 +101,34 @@ class Utility2Test extends ActorTest() {
}
}
+class Utility3Test extends ActorTest() {
+ "Utility" should {
+ "wire a matrix_terminalc Actor" in {
+ val obj = Utility(UtilityType.matrix_terminalc, UtilityTest.vehicle)
+ obj().GUID = PlanetSideGUID(1)
+ assert(obj().Actor == ActorRef.noSender)
+
+ system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
+ receiveOne(Duration.create(100, "ms")) //consume and discard
+ assert(obj().Actor != ActorRef.noSender)
+ }
+ }
+}
+
+class Utility4Test extends ActorTest() {
+ "Utility" should {
+ "wire an ams_respawn_tube Actor" in {
+ val obj = Utility(UtilityType.ams_respawn_tube, UtilityTest.vehicle)
+ obj().GUID = PlanetSideGUID(1)
+ assert(obj().Actor == ActorRef.noSender)
+
+ system.actorOf(Props(classOf[UtilityTest.SetupControl], obj), "test") ! ""
+ receiveOne(Duration.create(100, "ms")) //consume and discard
+ assert(obj().Actor != ActorRef.noSender)
+ }
+ }
+}
+
object UtilityTest {
val vehicle = Vehicle(GlobalDefinitions.quadstealth)
diff --git a/common/src/test/scala/objects/terminal/MatrixTerminalTest.scala b/common/src/test/scala/objects/terminal/MatrixTerminalTest.scala
new file mode 100644
index 00000000..a574c79e
--- /dev/null
+++ b/common/src/test/scala/objects/terminal/MatrixTerminalTest.scala
@@ -0,0 +1,63 @@
+// Copyright (c) 2017 PSForever
+package objects.terminal
+
+import akka.actor.ActorRef
+import net.psforever.objects.serverobject.terminals.{MatrixTerminalDefinition, Terminal}
+import net.psforever.objects.{GlobalDefinitions, Player, Vehicle}
+import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
+import net.psforever.types._
+import org.specs2.mutable.Specification
+
+class MatrixTerminalTest extends Specification {
+ "MatrixTerminal" should {
+ "define (a)" in {
+ val a = new MatrixTerminalDefinition(517)
+ a.ObjectId mustEqual 517
+ a.Name mustEqual "matrix_terminala"
+ }
+
+ "define (b)" in {
+ val b = new MatrixTerminalDefinition(518)
+ b.ObjectId mustEqual 518
+ b.Name mustEqual "matrix_terminalb"
+ }
+
+ "define (b)" in {
+ val b = new MatrixTerminalDefinition(519)
+ b.ObjectId mustEqual 519
+ b.Name mustEqual "matrix_terminalc"
+ }
+
+ "define (invalid)" in {
+ var id : Int = (math.random * Int.MaxValue).toInt
+ if(id == 517) {
+ id += 3
+ }
+ else if(id == 518) {
+ id += 2
+ }
+ else if(id == 519) {
+ id += 1
+ }
+
+ new MatrixTerminalDefinition(id) must throwA[IllegalArgumentException]
+ }
+ }
+
+ "Matrix_Terminal" should {
+ val terminal = Terminal(GlobalDefinitions.matrix_terminalc)
+ terminal.Owner = Vehicle(GlobalDefinitions.quadstealth)
+ terminal.Owner.Faction = PlanetSideEmpire.TR
+
+ "construct" in {
+ terminal.Actor mustEqual ActorRef.noSender
+ }
+
+ "player can not buy (anything)" in {
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "lite_armor", 0, PlanetSideGUID(0))
+
+ terminal.Request(player, msg) mustEqual Terminal.NoDeal()
+ }
+ }
+}
diff --git a/pslogin/src/main/scala/Maps.scala b/pslogin/src/main/scala/Maps.scala
index 71c81084..d8c854c8 100644
--- a/pslogin/src/main/scala/Maps.scala
+++ b/pslogin/src/main/scala/Maps.scala
@@ -22,7 +22,18 @@ object Maps {
val map5 = new ZoneMap("map05")
- val map6 = new ZoneMap("map06")
+ val map6 = new ZoneMap("map06") {
+ //TODO TEST ceryshen
+ LocalObject(ServerObjectBuilder(3353, Terminal.Constructor(ground_vehicle_terminal)))
+ LocalObject(ServerObjectBuilder(500,
+ VehicleSpawnPad.Constructor(Vector3(3962.0f, 4334.0f, 268.0f), Vector3(0f, 0f, 180.0f))
+ )) //TODO guid not correct
+
+ LocalBuilding(2, FoundationBuilder(Building.Structure))
+ ObjectToBuilding(3353, 2)
+ ObjectToBuilding(500, 2)
+ TerminalToSpawnPad(3353, 500)
+ }
val map7 = new ZoneMap("map07")
diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala
index eade334d..a7c9d8f3 100644
--- a/pslogin/src/main/scala/WorldSessionActor.scala
+++ b/pslogin/src/main/scala/WorldSessionActor.scala
@@ -23,8 +23,9 @@ 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.terminals.Terminal
-import net.psforever.objects.vehicles.{AccessPermissionGroup, VehicleLockState}
+import net.psforever.objects.serverobject.terminals.{MatrixTerminalDefinition, Terminal}
+import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage
+import net.psforever.objects.vehicles.{AccessPermissionGroup, Utility, VehicleLockState}
import net.psforever.objects.zones.{InterstellarCluster, Zone}
import net.psforever.packet.game.objectcreate._
import net.psforever.types._
@@ -402,16 +403,17 @@ class WorldSessionActor extends Actor with MDCContextAware {
val vehicle_guid = obj.GUID
if(state == DriveState.Deploying) {
log.info(s"DeployRequest: $obj transitioning to deploy state")
- sendResponse(DeployRequestMessage(player.GUID, vehicle_guid, state, 0, false, obj.Position))
- vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.DeployRequest(player.GUID, vehicle_guid, state, 0, false, obj.Position))
+ obj.Velocity = Some(Vector3.Zero) //no velocity
+ sendResponse(DeployRequestMessage(player.GUID, vehicle_guid, state, 0, false, Vector3.Zero))
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.DeployRequest(player.GUID, vehicle_guid, state, 0, false, Vector3.Zero))
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
context.system.scheduler.scheduleOnce(obj.DeployTime milliseconds, obj.Actor, Deployment.TryDeploy(DriveState.Deployed))
}
else if(state == DriveState.Deployed) {
log.info(s"DeployRequest: $obj has been Deployed")
- sendResponse(DeployRequestMessage(player.GUID, vehicle_guid, state, 0, false, obj.Position))
- vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.DeployRequest(player.GUID, vehicle_guid, state, 0, false, obj.Position))
+ sendResponse(DeployRequestMessage(player.GUID, vehicle_guid, state, 0, false, Vector3.Zero))
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.DeployRequest(player.GUID, vehicle_guid, state, 0, false, Vector3.Zero))
DeploymentActivities(obj)
//...
}
@@ -902,8 +904,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
continent.Transport ! Zone.SpawnVehicle(vehicle)
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.LoadVehicle(player_guid, vehicle, objedtId, vehicle_guid, vdata))
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 1L)) //mount points off?
- //sendResponse(PlanetsideAttributeMessage(vehicle_guid, 21, player_guid.guid))) //fte and ownership?
- //sendResponse(ObjectAttachMessage(vehicle_guid, player_guid, 0)))
+ sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 1L)) //mount points off?
+ sendResponse(PlanetsideAttributeMessage(vehicle_guid, 21, player_guid.guid)) //fte and ownership?
+ //sendResponse(ObjectAttachMessage(vehicle_guid, player_guid, 0))
vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid) //cancel queue timeout delay
vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(vehicle, continent, 21L) //temporary drive away from pad delay
vehicle.Actor ! Mountable.TryMount(player, 0)
@@ -980,13 +983,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
PlanetSideGUID(6), //Ceryshen
PlanetSideGUID(2), //Anguta
8, //80% NTU
- true, //Base hacked
- PlanetSideEmpire.NC, //Base hacked by NC
- 600000, //10 minutes remaining for hack
+ false, //Base hacked
+ PlanetSideEmpire.NEUTRAL, //Base hacked by NC
+ 0, //10 minutes remaining for hack
PlanetSideEmpire.VS, //Base owned by VS
0, //!! Field != 0 will cause malformed packet. See class def.
None,
- PlanetSideGeneratorState.Critical, //Generator critical
+ PlanetSideGeneratorState.Normal, //Generator critical
true, //Respawn tubes destroyed
true, //Force dome active
16, //Tech plant lattice benefit
@@ -1022,6 +1025,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(SetCurrentAvatarMessage(guid,0,0))
sendResponse(CreateShortcutMessage(guid, 1, 0, true, Shortcut.MEDKIT))
sendResponse(ChatMsg(ChatMessageType.CMT_EXPANSIONS, true, "", "1 on", None)) //CC on
+ sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(0), 82, 0))
+
+ (1 to 73).foreach( i => {
+ sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(i), 67, 0))
+ })
case Zone.ItemFromGround(tplayer, item) =>
val obj_guid = item.GUID
@@ -1234,13 +1242,18 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.info("Reticulating splines ...")
//map-specific initializations
//TODO continent.ClientConfiguration()
+ sendResponse(PlanetsideAttributeMessage(PlanetSideGUID(0), 112, 1))
+
sendResponse(SetEmpireMessage(PlanetSideGUID(2), PlanetSideEmpire.VS)) //HART building C
sendResponse(SetEmpireMessage(PlanetSideGUID(29), PlanetSideEmpire.NC)) //South Villa Gun Tower
sendResponse(TimeOfDayMessage(1191182336))
sendResponse(ReplicationStreamMessage(5, Some(6), Vector(SquadListing()))) //clear squad list
- //render Equipment that was dropped into zone before the player arrived
+ sendResponse(ZonePopulationUpdateMessage(PlanetSideGUID(6), 414, 138, 0, 138, 0, 138, 0, 138, 0))
+ (1 to 255).foreach(i => { sendResponse(SetEmpireMessage(PlanetSideGUID(i), PlanetSideEmpire.VS)) })
+
+ //render Equipment that was dropped into zone before the player arrived
continent.EquipmentOnGround.foreach(item => {
val definition = item.Definition
sendResponse(
@@ -1387,14 +1400,31 @@ class WorldSessionActor extends Actor with MDCContextAware {
case msg @ ProjectileStateMessage(projectile_guid, shot_pos, shot_vector, unk1, unk2, unk3, unk4, time_alive) =>
//log.info("ProjectileState: " + msg)
+ case msg @ ReleaseAvatarRequestMessage() =>
+ log.info(s"ReleaseAvatarRequest: ${player.GUID} on ${continent.Id} has released")
+ sendResponse(PlanetsideAttributeMessage(player.GUID, 6, 1))
+ sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, 2, true))
+
+ case msg @ SpawnRequestMessage(u1, u2, u3, u4, u5) =>
+ log.info(s"SpawnRequestMessage: $msg")
+
case msg @ ChatMsg(messagetype, has_wide_contents, recipient, contents, note_contents) =>
// TODO: Prevents log spam, but should be handled correctly
if (messagetype != ChatMessageType.CMT_TOGGLE_GM) {
log.info("Chat: " + msg)
}
+ if(messagetype == ChatMessageType.CMT_SUICIDE) {
+ val player_guid = player.GUID
+ val pos = player.Position
+ sendResponse(PlanetsideAttributeMessage(player_guid, 0, 0))
+ sendResponse(PlanetsideAttributeMessage(player_guid, 2, 0))
+ sendResponse(DestroyMessage(player_guid, player_guid, PlanetSideGUID(0), pos))
+ sendResponse(AvatarDeadStateMessage(DeadState.Dead, 300000, 300000, pos, 2, true))
+ }
+
if (messagetype == ChatMessageType.CMT_VOICE) {
- sendResponse(ChatMsg(ChatMessageType.CMT_VOICE, false, "IlllIIIlllIlIllIlllIllI", contents, None))
+ sendResponse(ChatMsg(ChatMessageType.CMT_VOICE, false, player.Name, contents, None))
}
// TODO: handle this appropriately
@@ -1944,6 +1974,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
}
+ case Some(obj : Terminal) =>
+ if(obj.Definition.isInstanceOf[MatrixTerminalDefinition]) {
+ //TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
+ sendResponse(BindPlayerMessage(1, "@ams", true, true, 0, 0, 0, obj.Position))
+ }
+ else {
+ sendResponse(UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
+ }
+
case Some(obj : PlanetSideGameObject) =>
if(itemType != 121) {
sendResponse(UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
@@ -2986,8 +3025,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
def DeploymentActivities(obj : Deployment.DeploymentObject) : Unit = {
obj match {
case vehicle : Vehicle =>
- //TODO we should not have to do this imho
- ReloadVehicleAccessPermissions(vehicle)
+ ReloadVehicleAccessPermissions(vehicle) //TODO we should not have to do this imho
+ sendResponse(PlanetsideAttributeMessage(obj.GUID, 81, 1))
case _ => ;
}
}
diff --git a/pslogin/src/main/scala/Zones.scala b/pslogin/src/main/scala/Zones.scala
index f856f487..60de7f9c 100644
--- a/pslogin/src/main/scala/Zones.scala
+++ b/pslogin/src/main/scala/Zones.scala
@@ -13,7 +13,14 @@ object Zones {
val z5 = new Zone("z5", Maps.map5, 5)
- val z6 = new Zone("z6", Maps.map6, 6)
+ val z6 = new Zone("z6", Maps.map6, 6) {
+ override def Init(implicit context : ActorContext) : Unit = {
+ super.Init(context)
+
+ import net.psforever.types.PlanetSideEmpire
+ Building(2).get.Faction = PlanetSideEmpire.VS
+ }
+ }
val z7 = new Zone("z7", Maps.map7, 7)