adding the ams utility: ams respawn tube

This commit is contained in:
FateJH 2018-02-24 21:03:20 -05:00
parent 02c4fb26c7
commit e1581c94e7
12 changed files with 226 additions and 59 deletions

View file

@ -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,8 @@ object GlobalDefinitions {
*/
val order_terminal = new OrderTerminalDefinition
val ams_respawn_tube = new SpawnTubeDefinition(49) { Name = "ams_respawn_tube" }
val order_terminala = new OrderTerminalABDefinition(613)
val order_terminalb = new OrderTerminalABDefinition(614)
@ -2347,6 +2350,7 @@ object GlobalDefinitions {
ams.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
ams.MountPoints += 1 -> 0
ams.MountPoints += 2 -> 0
ams.Utilities += 2 -> UtilityType.ams_respawn_tube
ams.Utilities += 3 -> UtilityType.order_terminala
ams.Utilities += 4 -> UtilityType.order_terminalb
ams.Deployment = true

View file

@ -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)) }
}

View file

@ -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
// }
}

View file

@ -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
}

View file

@ -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}")
}
}
}

View file

@ -5,6 +5,7 @@ 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.tube.{SpawnTube, SpawnTubeDefinition}
/**
* An `Enumeration` of the available vehicular utilities.<br>
@ -17,6 +18,7 @@ import net.psforever.objects.serverobject.terminals.{OrderTerminalABDefinition,
object UtilityType extends Enumeration {
type Type = Value
val
ams_respawn_tube,
order_terminala,
order_terminalb
= Value
@ -83,6 +85,8 @@ object Utility {
* @return the `Amenity` object
*/
private def BuildUtilityFunc(util : UtilityType.Value) : Amenity = util match {
case UtilityType.ams_respawn_tube =>
SpawnTube(GlobalDefinitions.ams_respawn_tube)
case UtilityType.order_terminala =>
Terminal(GlobalDefinitions.order_terminala)
case UtilityType.order_terminalb =>
@ -95,6 +99,8 @@ object Utility {
* @return the `Amenity` object
*/
private def SelectUtilitySetupFunc(util : UtilityType.Value) : UtilLogic = util match {
case UtilityType.ams_respawn_tube =>
SpawnTubeDefinition.Setup
case UtilityType.order_terminala =>
OrderTerminalABDefinition.Setup
case UtilityType.order_terminalb =>

View file

@ -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

View file

@ -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)

View file

@ -74,31 +74,34 @@ import scodec.codecs._
* `36 - CR. Value is the CR`<br>
* `43 - Info on avatar name : 0 = Nothing, 1 = "(LD)" message`<br>
* `53 - LFS. Value is 1 to flag LFS`<br>
* `54 - Player "Aura". Values are : 0 for nothing, 1 for plasma, 2 for ancient, 3 for plasma + ancient,<br>
* 4 for LLU?, 5 for plasma + LLU?, 6 for ancient + LLU?, 7 for plasma + ancient + LLU?, 8 for fire,<br>
* 9 for plasma + fire, 10 for ancient + fire, 11 for plasma + ancient + fire,<br>
* 12 for LLU? + fire, 13 for plasma + LLU? + fire, 14 for ancient + LLU? + fire,<br>
* 15 for plasma + ancient + LLU? + fire,`<br>
* `54 - Player "Aura". Values can be expressed in the first byte's lower nibble:`<br>
* - 0 is nothing<br>
* - 1 is plasma<br>
* - 2 is ancient<br>
* - 4 is LLU (?)<br>
* - 8 is fire<br>
* -- e.g., 13 = 8 + 4 + 1 = fire and LLU and plasma<br>
* `55 - "Someone is attempting to Heal you". Value is 1`<br>
* `56 - "Someone is attempting to Repair you". Value is 1`<br>
* `73 - "You are locked into the Core Beam. Charging your Module now.". Value is 1 to active`<br>
* `77 - Cavern Facility Captures. Value is the number of captures`<br>
* `78 - Cavern Kills. Value is the number of kills`<br>
* `106 - Custom Head`
* `106 - Custom Head`<br>
* Client to Server : <br>
* `106 - Custom Head`<br>
* <br>
* Vehicles:<br>
* 0 - Vehicle base health<br>
* 10 - Driver seat permissions (0 = Locked, 1 = Group, 3 = Empire)<br>
* 11 - Gunner seat(s) permissions (same)<br>
* 12 - Passenger seat(s) permissions (same) <br>
* 13 - Trunk permissions (same)<br>
* 21 - Asserts first time event eligibility / makes owner if no owner is assigned<br>
* 22 - Toggles gunner and passenger mount points (1 = hides, 0 = reveals; this also locks their permissions)<br>
* 68 - ???<br>
* 80 - Damage vehicle (unknown value)<br>
* 113 - ???
* `Vehicles:`<br>
* `0 - Vehicle base health`<br>
* `10 - Driver seat permissions (0 = Locked, 1 = Group, 3 = Empire)`<br>
* `11 - Gunner seat(s) permissions (same)`<br>
* `12 - Passenger seat(s) permissions (same)`<br>
* `13 - Trunk permissions (same)`<br>
* `21 - Asserts first time event eligibility / makes owner if no owner is assigned`<br>
* `22 - Toggles gunner and passenger mount points (1 = hides, 0 = reveals; this also locks their permissions)`<br>
* `68 - ???`<br>
* `80 - Damage vehicle (unknown value)`<br>
* `81 - ???`<br>
* `113 - ???`
* @param player_guid the player
* @param attribute_type na
* @param attribute_value na

View file

@ -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]
}

View file

@ -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