mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-03-04 12:40:20 +00:00
a little bit of vehicles everything; work on the endocder/decoder for vehicles and seated players and bitstream size; vehicle ownership is extremely passable right now; seat restrictionsfor getting into vehicles is now in place; tests repaired; adjustment to vehicle spawn pad (again) to hopefully increase tolerance and recovery
This commit is contained in:
parent
b2e0fd1276
commit
c664f96bd4
28 changed files with 777 additions and 553 deletions
|
|
@ -21,14 +21,42 @@ import scala.annotation.tailrec
|
|||
* Generally, all seating is declared first - the driver and passengers and and gunners.
|
||||
* Following that are the mounted weapons and other utilities.
|
||||
* Trunk space starts being indexed afterwards.
|
||||
* To keep it simple, infantry seating, mounted weapons, and utilities are stored separately.<br>
|
||||
* <br>
|
||||
* Vehicles maintain a `Map` of `Utility` objects in given index positions.
|
||||
* To keep it simple, infantry seating, mounted weapons, and utilities are stored separately herein.
|
||||
* The `Map` of `Utility` objects is given using the same inventory index positions.
|
||||
* Positive indices and zero are considered "represented" and must be assigned a globally unique identifier
|
||||
* and must be present in the containing vehicle's `ObjectCreateMessage` packet.
|
||||
* The index is the seat position, reflecting the position in the zero-index inventory.
|
||||
* Negative indices are expected to be excluded from this conversion.
|
||||
* The value of the negative index does not have a specific meaning.
|
||||
* The value of the negative index does not have a specific meaning.<br>
|
||||
* <br>
|
||||
* The importance of a vehicle's owner can not be overlooked.
|
||||
* The owner is someone who can control who can sit in the vehicle's seats
|
||||
* either through broad categorization or discriminating sleection ("kicking")
|
||||
* and who has access to and can allow access to the vehicle's trunk capacity.
|
||||
* The driver is the only player that can access a vehicle's saved loadouts through a repair/rearm silo
|
||||
* and can procure equipment from the said silo.
|
||||
* The owner of a vehicle and the driver of a vehicle as mostly interchangeable terms for this reason
|
||||
* and it can be summarized that the player who has access to the driver seat meets the qualifications for the "owner"
|
||||
* so long as that player is the last person to have sat in that seat.
|
||||
* All previous ownership information is replaced just as soon as someone else sits in the driver's seat.
|
||||
* Ownership is also transferred as players die and respawn (from and to the same client)
|
||||
* and when they leave a continent without taking the vehicle they currently own with them.
|
||||
* (They also lose ownership when they leave the game, of course.)<br>
|
||||
* <br>
|
||||
* All seats have vehicle-level properties on top of their own internal properties.
|
||||
* A seat has a glyph projected onto the ground when the vehicle is not moving
|
||||
* that is used to mark where the seat can be accessed, as well as broadcasting the current access condition of the seat.
|
||||
* As indicated previously, seats are composed into categories and the categories used to control access.
|
||||
* The "driver" group has already been mentioned and is usually composed of a single seat, the "first" one.
|
||||
* The driver seat is typically locked to the person who can sit in it - the owner - unless manually unlocked.
|
||||
* Any seat besides the "driver" that has a weapon controlled from the seat is called a "gunner" seats.
|
||||
* Any other seat besides the "driver" seat and "gunner" seats is called a "passenger" seat.
|
||||
* All of these seats are typically unlocked normally.
|
||||
* The "trunk" also counts as an access group even though it is not directly attached to a seat and starts as "locked."
|
||||
* The categories all have their own glyphs,
|
||||
* sharing a red cross glyph as a "can not access" state,
|
||||
* and may also use their lack of visibility to express state.
|
||||
* In terms of individual access, each seat can have its current occupant ejected, save for the driver's seat.
|
||||
* @see `Vehicle.EquipmentUtilities`
|
||||
* @param vehicleDef the vehicle's definition entry';
|
||||
* stores and unloads pertinent information about the `Vehicle`'s configuration;
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ import scala.util.{Success, Try}
|
|||
class AvatarConverter extends ObjectCreateConverter[Player]() {
|
||||
override def ConstructorData(obj : Player) : Try[PlayerData] = {
|
||||
import AvatarConverter._
|
||||
val MaxArmor = obj.MaxArmor
|
||||
if(obj.VehicleSeated.isEmpty) {
|
||||
Success(
|
||||
Success(
|
||||
if(obj.VehicleSeated.isEmpty) {
|
||||
PlayerData(
|
||||
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
|
||||
MakeAppearanceData(obj),
|
||||
|
|
@ -22,43 +21,38 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
|
|||
MakeInventoryData(obj),
|
||||
GetDrawnSlot(obj)
|
||||
)
|
||||
)
|
||||
}
|
||||
else {
|
||||
Success(
|
||||
}
|
||||
else {
|
||||
PlayerData(
|
||||
MakeAppearanceData(obj),
|
||||
MakeCharacterData(obj),
|
||||
MakeInventoryData(obj),
|
||||
GetDrawnSlot(obj)
|
||||
DrawnSlot.None
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = {
|
||||
import AvatarConverter._
|
||||
Success(
|
||||
DetailedPlayerData.apply(
|
||||
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
|
||||
MakeAppearanceData(obj),
|
||||
DetailedCharacterData(
|
||||
obj.BEP,
|
||||
obj.CEP,
|
||||
obj.MaxHealth,
|
||||
obj.Health,
|
||||
obj.Armor,
|
||||
obj.MaxStamina,
|
||||
obj.Stamina,
|
||||
obj.Certifications.toList.sortBy(_.id), //TODO is sorting necessary?
|
||||
MakeImplantEntries(obj),
|
||||
List.empty[String], //TODO fte list
|
||||
List.empty[String], //TODO tutorial list
|
||||
MakeCosmetics(obj.BEP)
|
||||
),
|
||||
InventoryData((MakeHolsters(obj, BuildDetailedEquipment) ++ MakeFifthSlot(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)),
|
||||
GetDrawnSlot(obj)
|
||||
)
|
||||
if(obj.VehicleSeated.isEmpty) {
|
||||
DetailedPlayerData.apply(
|
||||
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
|
||||
MakeAppearanceData(obj),
|
||||
MakeDetailedCharacterData(obj),
|
||||
MakeDetailedInventoryData(obj),
|
||||
GetDrawnSlot(obj)
|
||||
)
|
||||
}
|
||||
else {
|
||||
DetailedPlayerData.apply(
|
||||
MakeAppearanceData(obj),
|
||||
MakeDetailedCharacterData(obj),
|
||||
MakeDetailedInventoryData(obj),
|
||||
DrawnSlot.None
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -107,8 +101,29 @@ object AvatarConverter {
|
|||
)
|
||||
}
|
||||
|
||||
def MakeDetailedCharacterData(obj : Player) : (Option[Int])=>DetailedCharacterData = {
|
||||
DetailedCharacterData(
|
||||
obj.BEP,
|
||||
obj.CEP,
|
||||
obj.MaxHealth,
|
||||
obj.Health,
|
||||
obj.Armor,
|
||||
obj.MaxStamina,
|
||||
obj.Stamina,
|
||||
obj.Certifications.toList.sortBy(_.id), //TODO is sorting necessary?
|
||||
MakeImplantEntries(obj),
|
||||
List.empty[String], //TODO fte list
|
||||
List.empty[String], //TODO tutorial list
|
||||
MakeCosmetics(obj.BEP)
|
||||
)
|
||||
}
|
||||
|
||||
def MakeInventoryData(obj : Player) : InventoryData = {
|
||||
InventoryData(MakeHolsters(obj, BuildEquipment).sortBy(_.parentSlot)) //TODO is sorting necessary?
|
||||
InventoryData(MakeHolsters(obj, BuildEquipment).sortBy(_.parentSlot))
|
||||
}
|
||||
|
||||
def MakeDetailedInventoryData(obj : Player) : InventoryData = {
|
||||
InventoryData((MakeHolsters(obj, BuildDetailedEquipment) ++ MakeFifthSlot(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -13,16 +13,22 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
|
|||
Failure(new Exception("VehicleConverter should not be used to generate detailed VehicleData (nothing should)"))
|
||||
|
||||
override def ConstructorData(obj : Vehicle) : Try[VehicleData] = {
|
||||
val health = 255 * obj.Health / obj.MaxHealth //TODO not precise
|
||||
Success(
|
||||
VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
|
||||
obj.Faction,
|
||||
0,
|
||||
PlanetSideGUID(0) //if(obj.Owner.isDefined) { obj.Owner.get } else { PlanetSideGUID(0) } //TODO is this really Owner?
|
||||
),
|
||||
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
|
||||
obj.Faction,
|
||||
false, //bops
|
||||
health < 3, //destroyed
|
||||
0,
|
||||
255 * obj.Health / obj.MaxHealth, //TODO not precise
|
||||
obj.Jammered, //jammered
|
||||
false,
|
||||
obj.Owner match {
|
||||
case Some(owner) => owner
|
||||
case None => PlanetSideGUID(0)
|
||||
},
|
||||
false,
|
||||
health,
|
||||
false, false,
|
||||
obj.DeploymentState,
|
||||
false,
|
||||
|
|
@ -35,11 +41,9 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
|
|||
}
|
||||
|
||||
private def MakeSeats(obj : Vehicle) : List[InventoryItemData.InventoryItem] = {
|
||||
var offset : Long = VehicleData.InitialStreamLengthToSeatEntries(true, SpecificFormatModifier)
|
||||
obj.Seats
|
||||
.filter({ case(_, seat) => seat.isOccupied })
|
||||
.map({ case(index, seat) =>
|
||||
val player = seat.Occupant.get
|
||||
val offset : Long = VehicleData.InitialStreamLengthToSeatEntries(true, SpecificFormatModifier)
|
||||
obj.Seats(0).Occupant match { //TODO just the driver for now to avoid issues with seat permissions
|
||||
case Some(player) =>
|
||||
val mountedPlayer = VehicleData.PlayerData(
|
||||
AvatarConverter.MakeAppearanceData(player),
|
||||
AvatarConverter.MakeCharacterData(player),
|
||||
|
|
@ -47,11 +51,13 @@ class VehicleConverter extends ObjectCreateConverter[Vehicle]() {
|
|||
AvatarConverter.GetDrawnSlot(player),
|
||||
offset
|
||||
)
|
||||
val entry = InventoryItemData(ObjectClass.avatar, player.GUID, index, mountedPlayer)
|
||||
println(s"seat $index offset: $offset, size: ${entry.bitsize}")
|
||||
offset += entry.bitsize
|
||||
entry
|
||||
}).toList
|
||||
val entry = InventoryItemData(ObjectClass.avatar, player.GUID, 0, mountedPlayer)
|
||||
//println(s"seat 0 offset: $offset, size: ${entry.bitsize}, pad: ${mountedPlayer.basic_appearance.NamePadding}")
|
||||
//offset += entry.bitsize
|
||||
List(entry)
|
||||
case None =>
|
||||
Nil
|
||||
}
|
||||
}
|
||||
|
||||
private def MakeMountings(obj : Vehicle) : List[InventoryItemData.InventoryItem] = {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package net.psforever.objects.serverobject.pad.process
|
|||
import akka.actor.{ActorRef, Props}
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.duration._
|
||||
|
|
@ -46,7 +47,7 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC
|
|||
trace("driver to be made seated in vehicle")
|
||||
entry.sendTo ! VehicleSpawnPad.StartPlayerSeatedInVehicle(entry.vehicle, pad)
|
||||
entry.vehicle.Actor.tell(Mountable.TryMount(driver, 0), entry.sendTo) //entry.sendTo should handle replies to TryMount
|
||||
context.system.scheduler.scheduleOnce(1000 milliseconds, self, VehicleSpawnControlSeatDriver.AwaitDriverInSeat(entry))
|
||||
context.system.scheduler.scheduleOnce(1500 milliseconds, self, VehicleSpawnControlSeatDriver.AwaitDriverInSeat(entry))
|
||||
}
|
||||
else {
|
||||
trace("driver lost; vehicle stranded on pad")
|
||||
|
|
@ -55,11 +56,18 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC
|
|||
|
||||
case VehicleSpawnControlSeatDriver.AwaitDriverInSeat(entry) =>
|
||||
val driver = entry.driver
|
||||
if(entry.sendTo == ActorRef.noSender || driver.Continent != Continent.Id) {
|
||||
if(entry.sendTo == ActorRef.noSender || !driver.isAlive || driver.Continent != Continent.Id) {
|
||||
trace("driver lost, but operations can continue")
|
||||
vehicleOverride ! VehicleSpawnControl.Process.ServerVehicleOverride(entry)
|
||||
}
|
||||
else if(entry.vehicle.Health == 0 || entry.vehicle.Position == Vector3.Zero) {
|
||||
//skip ahead for cleanup
|
||||
vehicleOverride ! VehicleSpawnControl.Process.ServerVehicleOverride(entry)
|
||||
}
|
||||
else if(driver.isAlive && driver.VehicleSeated.isEmpty) {
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.DetachFromRails(entry.vehicle, pad, Continent.Id)
|
||||
}
|
||||
context.system.scheduler.scheduleOnce(100 milliseconds, self, VehicleSpawnControlSeatDriver.AwaitDriverInSeat(entry))
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package net.psforever.objects.serverobject.pad.process
|
|||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.duration._
|
||||
|
|
@ -26,27 +27,33 @@ class VehicleSpawnControlServerVehicleOverride(pad : VehicleSpawnPad) extends Ve
|
|||
def receive : Receive = {
|
||||
case VehicleSpawnControl.Process.ServerVehicleOverride(entry) =>
|
||||
val vehicle = entry.vehicle
|
||||
val pad_railed = pad.Railed
|
||||
if(pad_railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad, Continent.Id)
|
||||
}
|
||||
if(vehicle.Health == 0) {
|
||||
trace(s"vehicle was already destroyed; but, everything is fine")
|
||||
if(pad_railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
val vehicleFailState = vehicle.Health == 0 || vehicle.Position == Vector3.Zero
|
||||
val driverFailState = !entry.driver.isAlive || entry.driver.Continent != Continent.Id || (if(vehicle.HasGUID) { !entry.driver.VehicleSeated.contains(vehicle.GUID) } else { true })
|
||||
if(vehicleFailState || driverFailState) {
|
||||
if(vehicleFailState) {
|
||||
trace(s"vehicle was already destroyed")
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
}
|
||||
}
|
||||
else {
|
||||
trace(s"driver is not ready")
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad, Continent.Id)
|
||||
}
|
||||
}
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.RevealPlayer(entry.driver.GUID, Continent.Id)
|
||||
vehicleGuide ! VehicleSpawnControl.Process.FinalClearance(entry)
|
||||
}
|
||||
else if(entry.sendTo != ActorRef.noSender && entry.driver.isAlive && entry.driver.Continent == Continent.Id && entry.driver.VehicleSeated.contains(vehicle.GUID)) {
|
||||
trace(s"telling ${entry.driver.Name} that the server is assuming control of the ${vehicle.Definition.Name}")
|
||||
entry.sendTo ! VehicleSpawnPad.ServerVehicleOverrideStart(vehicle, pad)
|
||||
context.system.scheduler.scheduleOnce(3000 milliseconds, vehicleGuide, VehicleSpawnControl.Process.StartGuided(entry))
|
||||
}
|
||||
else {
|
||||
if(pad_railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad, Continent.Id)
|
||||
if(pad.Railed) {
|
||||
Continent.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad, Continent.Id)
|
||||
}
|
||||
if(entry.sendTo != ActorRef.noSender) {
|
||||
trace(s"telling ${entry.driver.Name} that the server is assuming control of the ${vehicle.Definition.Name}")
|
||||
entry.sendTo ! VehicleSpawnPad.ServerVehicleOverrideStart(vehicle, pad)
|
||||
context.system.scheduler.scheduleOnce(3000 milliseconds, vehicleGuide, VehicleSpawnControl.Process.StartGuided(entry))
|
||||
}
|
||||
vehicleGuide ! VehicleSpawnControl.Process.FinalClearance(entry)
|
||||
}
|
||||
|
||||
case msg @ (VehicleSpawnControl.ProcessControl.Reminder | VehicleSpawnControl.ProcessControl.GetNewOrder) =>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ package net.psforever.objects.vehicles
|
|||
|
||||
import akka.actor.Actor
|
||||
import net.psforever.objects.Vehicle
|
||||
import net.psforever.objects.serverobject.mount.MountableBehavior
|
||||
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
import net.psforever.objects.serverobject.deploy.DeploymentBehavior
|
||||
import net.psforever.types.ExoSuitType
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific `Vehicle`.<br>
|
||||
|
|
@ -32,9 +33,32 @@ class VehicleControl(vehicle : Vehicle) extends Actor
|
|||
|
||||
def Enabled : Receive = checkBehavior
|
||||
.orElse(deployBehavior)
|
||||
.orElse(mountBehavior)
|
||||
.orElse(dismountBehavior)
|
||||
.orElse {
|
||||
case Mountable.TryMount(user, seat_num) =>
|
||||
val exosuit = user.ExoSuit
|
||||
val restriction = vehicle.Seats(seat_num).ArmorRestriction
|
||||
val seatGroup = vehicle.SeatPermissionGroup(seat_num).getOrElse(AccessPermissionGroup.Passenger)
|
||||
val permission = vehicle.PermissionGroup(seatGroup.id).getOrElse(VehicleLockState.Empire)
|
||||
if(
|
||||
(if(seatGroup == AccessPermissionGroup.Driver) {
|
||||
vehicle.Owner.contains(user.GUID) || vehicle.Owner.isEmpty || permission != VehicleLockState.Locked
|
||||
}
|
||||
else {
|
||||
permission != VehicleLockState.Locked
|
||||
}) &&
|
||||
(exosuit match {
|
||||
case ExoSuitType.MAX => restriction == SeatArmorRestriction.MaxOnly
|
||||
case ExoSuitType.Reinforced => restriction != SeatArmorRestriction.NoReinforcedOrMax
|
||||
case _ => true
|
||||
})
|
||||
) {
|
||||
mountBehavior.apply(Mountable.TryMount(user, seat_num))
|
||||
}
|
||||
else {
|
||||
sender ! Mountable.MountMessages(user, Mountable.CanNotMount(vehicle, seat_num))
|
||||
}
|
||||
|
||||
case FactionAffinity.ConvertFactionAffinity(faction) =>
|
||||
val originalAffinity = vehicle.Faction
|
||||
if(originalAffinity != (vehicle.Faction = faction)) {
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ import scodec.codecs._
|
|||
* `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>
|
||||
* `21 - Declare a player the vehicle's owner, by globally unique identifier`<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>
|
||||
|
|
|
|||
|
|
@ -125,11 +125,17 @@ final case class CharacterAppearanceData(app : BasicCharacterData,
|
|||
//factor guard bool values into the base size, not its corresponding optional field
|
||||
val nameStringSize : Long = StreamBitSize.stringBitSize(app.name, 16) + name_padding
|
||||
val outfitStringSize : Long = StreamBitSize.stringBitSize(outfit_name, 16) +
|
||||
CharacterAppearanceData.outfitNamePadding //even if the outfit_name is blank, string always padded
|
||||
(if(outfit_name.nonEmpty) { CharacterAppearanceData.outfitNamePadding } else { 0L }) //even if the outfit_name is blank, string always padded
|
||||
val altModelSize = CharacterAppearanceData.altModelBit(this).getOrElse(0)
|
||||
335L + nameStringSize + outfitStringSize + altModelSize
|
||||
}
|
||||
|
||||
/**
|
||||
* External access to the value padding on the name field.
|
||||
* The padding will always be a number 0-7.
|
||||
* @return the pad length in bits
|
||||
*/
|
||||
def NamePadding : Int = name_padding
|
||||
|
||||
/**
|
||||
* When a player is released-dead or attached to a zipline, their basic infantry model is replaced with a different one.
|
||||
|
|
|
|||
|
|
@ -49,33 +49,62 @@ final case class DetailedPlayerData(pos : Option[PlacementData],
|
|||
|
||||
object DetailedPlayerData extends Marshallable[DetailedPlayerData] {
|
||||
/**
|
||||
* Overloaded constructor that ignores the coordinate information.
|
||||
* Overloaded constructor that ignores the coordinate information but includes the inventory.
|
||||
* It passes information between the three major divisions for the purposes of offset calculations.
|
||||
* This constructor should be used for players that are mounted.
|
||||
* @param basic_appearance a curried function for the common fields regarding the the character's appearance
|
||||
* @param character_data a curried function for the class-specific data that explains about the character
|
||||
* @param inventory the player's inventory
|
||||
* @param drawn_slot the holster that is initially drawn;
|
||||
* technically, always `DrawnSlot.None`, but the field is preserved to maintain similarity
|
||||
* @return a `DetailedPlayerData` object
|
||||
*/
|
||||
def apply(basic_appearance : (Int)=>CharacterAppearanceData, character_data : (Option[Int])=>DetailedCharacterData, inventory : InventoryData, drawn_slot : DrawnSlot.Value) : DetailedPlayerData = {
|
||||
val appearance = basic_appearance(5)
|
||||
DetailedPlayerData(None, appearance, character_data(appearance.altModelBit), Some(inventory), drawn_slot)(false)
|
||||
}
|
||||
/** */
|
||||
|
||||
/**
|
||||
* Overloaded constructor that ignores the coordinate information and the inventory.
|
||||
* It passes information between the three major divisions for the purposes of offset calculations.
|
||||
* This constructor should be used for players that are mounted.
|
||||
* @param basic_appearance a curried function for the common fields regarding the the character's appearance
|
||||
* @param character_data a curried function for the class-specific data that explains about the character
|
||||
* @param drawn_slot the holster that is initially drawn;
|
||||
* technically, always `DrawnSlot.None`, but the field is preserved to maintain similarity
|
||||
* @return a `DetailedPlayerData` object
|
||||
*/
|
||||
def apply(basic_appearance : (Int)=>CharacterAppearanceData, character_data : (Option[Int])=>DetailedCharacterData, drawn_slot : DrawnSlot.Value) : DetailedPlayerData = {
|
||||
val appearance = basic_appearance(5)
|
||||
DetailedPlayerData(None, appearance, character_data(appearance.altModelBit), None, drawn_slot)(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded constructor that includes the coordinate information.
|
||||
* Overloaded constructor that includes the coordinate information and the inventory.
|
||||
* It passes information between the three major divisions for the purposes of offset calculations.
|
||||
* This constructor should be used for players that are standing apart from other containers.
|
||||
* @param pos the optional position of the character in the world environment
|
||||
* @param basic_appearance a curried function for the common fields regarding the the character's appearance
|
||||
* @param character_data a curried function for the class-specific data that explains about the character
|
||||
* @param inventory the player's inventory
|
||||
* @param drawn_slot the holster that is initially drawn
|
||||
* @return a `DetailedPlayerData` object
|
||||
*/
|
||||
def apply(pos : PlacementData, basic_appearance : (Int)=>CharacterAppearanceData, character_data : (Option[Int])=>DetailedCharacterData, inventory : InventoryData, drawn_slot : DrawnSlot.Value) : DetailedPlayerData = {
|
||||
val appearance = basic_appearance(PlayerData.PaddingOffset(Some(pos)))
|
||||
DetailedPlayerData(Some(pos), appearance, character_data(appearance.altModelBit), Some(inventory), drawn_slot)(true)
|
||||
}
|
||||
/** */
|
||||
|
||||
/**
|
||||
* Overloaded constructor that includes the coordinate information but ignores the inventory.
|
||||
* It passes information between the three major divisions for the purposes of offset calculations.
|
||||
* This constructor should be used for players that are standing apart from other containers.
|
||||
* @param pos the optional position of the character in the world environment
|
||||
* @param basic_appearance a curried function for the common fields regarding the the character's appearance
|
||||
* @param character_data a curried function for the class-specific data that explains about the character
|
||||
* @param drawn_slot the holster that is initially drawn
|
||||
* @return a `DetailedPlayerData` object
|
||||
*/
|
||||
def apply(pos : PlacementData, basic_appearance : (Int)=>CharacterAppearanceData, character_data : (Option[Int])=>DetailedCharacterData, drawn_slot : DrawnSlot.Value) : DetailedPlayerData = {
|
||||
val appearance = basic_appearance(PlayerData.PaddingOffset(Some(pos)))
|
||||
DetailedPlayerData(Some(pos), appearance, character_data(appearance.altModelBit), None, drawn_slot)(true)
|
||||
|
|
|
|||
|
|
@ -53,13 +53,14 @@ final case class PlayerData(pos : Option[PlacementData],
|
|||
|
||||
object PlayerData extends Marshallable[PlayerData] {
|
||||
/**
|
||||
* Overloaded constructor that ignores the coordinate information.
|
||||
* Overloaded constructor that ignores the coordinate information but includes the inventory.
|
||||
* It passes information between the three major divisions for the purposes of offset calculations.
|
||||
* This constructor should be used for players that are mounted.
|
||||
* @param basic_appearance a curried function for the common fields regarding the the character's appearance
|
||||
* @param character_data a curried function for the class-specific data that explains about the character
|
||||
* @param inventory the player's inventory
|
||||
* @param drawn_slot the holster that is initially drawn
|
||||
* @param drawn_slot the holster that is initially drawn;
|
||||
* technically, always `DrawnSlot.None`, but the field is preserved to maintain similarity
|
||||
* @return a `PlayerData` object
|
||||
*/
|
||||
def apply(basic_appearance : (Int)=>CharacterAppearanceData, character_data : (Boolean,Boolean)=>CharacterData, inventory : InventoryData, drawn_slot : DrawnSlot.Type) : PlayerData = {
|
||||
|
|
@ -72,7 +73,8 @@ object PlayerData extends Marshallable[PlayerData] {
|
|||
* This constructor should be used for players that are mounted.
|
||||
* @param basic_appearance a curried function for the common fields regarding the the character's appearance
|
||||
* @param character_data a curried function for the class-specific data that explains about the character
|
||||
* @param drawn_slot the holster that is initially drawn
|
||||
* @param drawn_slot the holster that is initially drawn;
|
||||
* technically, always `DrawnSlot.None`, but the field is preserved to maintain similarity
|
||||
* @return a `PlayerData` object
|
||||
*/
|
||||
def apply(basic_appearance : (Int)=>CharacterAppearanceData, character_data : (Boolean,Boolean)=>CharacterData, drawn_slot : DrawnSlot.Type) : PlayerData = {
|
||||
|
|
@ -81,7 +83,7 @@ object PlayerData extends Marshallable[PlayerData] {
|
|||
}
|
||||
|
||||
/**
|
||||
* Overloaded constructor.
|
||||
* Overloaded constructor that includes the coordinate information and the inventory.
|
||||
* It passes information between the three major divisions for the purposes of offset calculations.
|
||||
* This constructor should be used for players that are standing apart from other containers.
|
||||
* @param pos the optional position of the character in the world environment
|
||||
|
|
@ -96,7 +98,7 @@ object PlayerData extends Marshallable[PlayerData] {
|
|||
PlayerData(Some(pos), appearance, character_data(appearance.backpack, false), Some(inventory), drawn_slot)(true)
|
||||
}
|
||||
/**
|
||||
* Overloaded constructor that ignores the inventory.
|
||||
* Overloaded constructor that includes the coordinate information but ignores the inventory.
|
||||
* It passes information between the three major divisions for the purposes of offset calculations.
|
||||
* This constructor should be used for players that are standing apart from other containers.
|
||||
* @param pos the optional position of the character in the world environment
|
||||
|
|
|
|||
|
|
@ -13,22 +13,23 @@ import net.psforever.types.{DriveState, PlanetSideEmpire}
|
|||
object Prefab {
|
||||
object Vehicle {
|
||||
def ams(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, driveState : DriveState.Value, matrix_guid : PlanetSideGUID, respawn_guid : PlanetSideGUID, term_a_guid : PlanetSideGUID, term_b_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, driveState, false, false, false, Some(UtilityVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, driveState, false, UtilityVehicleData(0),
|
||||
Some(InventoryData(List(
|
||||
InternalSlot(ObjectClass.matrix_terminalc, matrix_guid, 1, CommonTerminalData(faction)),
|
||||
InternalSlot(ObjectClass.ams_respawn_tube, respawn_guid, 2, CommonTerminalData(faction)),
|
||||
InternalSlot(ObjectClass.order_terminala, term_a_guid, 3, CommonTerminalData(faction)),
|
||||
InternalSlot(ObjectClass.order_terminalb, term_b_guid, 4, CommonTerminalData(faction))
|
||||
)))
|
||||
)(VehicleFormat.Utility)
|
||||
)
|
||||
}
|
||||
|
||||
def ant(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, driveState : DriveState.Value) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, driveState, false, false, false, Some(UtilityVehicleData(0)), None)(VehicleFormat.Utility)
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, driveState, false, UtilityVehicleData(0), None)
|
||||
}
|
||||
|
||||
def apc_nc(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID, weapon6_guid : PlanetSideGUID, ammo6_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.apc_weapon_systemc_nc, weapon1_guid, 11,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_20mm, ammo1_guid, 0, AmmoBoxData(8))
|
||||
|
|
@ -49,11 +50,12 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo6_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def apc_tr(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID, weapon6_guid : PlanetSideGUID, ammo6_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.apc_weapon_systemc_tr, weapon1_guid, 11,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_15mm, ammo1_guid, 0, AmmoBoxData(8))
|
||||
|
|
@ -74,11 +76,12 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo6_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def apc_vs(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID, weapon6_guid : PlanetSideGUID, ammo6_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.apc_weapon_systemc_vs, weapon1_guid, 11,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.flux_cannon_thresher_battery, ammo1_guid, 0, AmmoBoxData(8))
|
||||
|
|
@ -99,12 +102,13 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo6_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def aurora(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo11_guid : PlanetSideGUID, ammo12_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo21_guid : PlanetSideGUID, ammo22_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
Some(InventoryData(
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.aurora_weapon_systema, weapon1_guid, 5,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.fluxpod_ammo, ammo11_guid, 0, AmmoBoxData(0x8))
|
||||
) ::
|
||||
|
|
@ -112,11 +116,12 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.fluxpod_ammo, ammo21_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def battlewagon(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.battlewagon_weapon_systema, weapon1_guid, 5,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_15mm, ammo1_guid, 0, AmmoBoxData(0x8))
|
||||
|
|
@ -131,11 +136,12 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_15mm, ammo4_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def dropship(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.cannon_dropship_20mm, weapon1_guid, 12,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_20mm, ammo1_guid, 0, AmmoBoxData(8))
|
||||
|
|
@ -147,32 +153,35 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_20mm, ammo3_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def flail(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo_guid : PlanetSideGUID, terminal_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.Mobile, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.flail_weapon, weapon_guid, 1,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.ancient_ammo_vehicle, ammo_guid, 0, AmmoBoxData(8))
|
||||
) ::
|
||||
InventoryItemData(ObjectClass.targeting_laser_dispenser, terminal_guid, 2, CommonTerminalData(faction, 2)) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def fury(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.fury_weapon_systema, weapon_guid, 1,
|
||||
WeaponData(0x4, 0x8, ObjectClass.hellfire_ammo, ammo_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def galaxy_gunship(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.galaxy_gunship_cannon, weapon1_guid, 6,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.heavy_grenade_mortar, ammo1_guid, 0, AmmoBoxData(8))
|
||||
|
|
@ -190,11 +199,12 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_35mm, ammo5_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def liberator(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.liberator_weapon_system, weapon1_guid, 3,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_35mm, ammo1_guid, 0, AmmoBoxData(8))
|
||||
|
|
@ -206,31 +216,34 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_25mm, ammo4_guid, 0 ,AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def lightgunship(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.Mobile, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.lightgunship_weapon_system, weapon_guid, 1,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_20mm, ammo1_guid, 0, AmmoBoxData(8), ObjectClass.reaver_rocket, ammo2_guid,1, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def lightning(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.lightning_weapon_system, weapon_guid, 1,
|
||||
WeaponData(0x4, 0x8, 0, ObjectClass.bullet_75mm, ammo1_guid, 0, AmmoBoxData(0x0), ObjectClass.bullet_12mm, ammo2_guid, 1, AmmoBoxData(0x0))
|
||||
) :: Nil)
|
||||
)
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def lodestar(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, repair1_guid : PlanetSideGUID, repair2_guid : PlanetSideGUID, veh_rearm1_guid : PlanetSideGUID, veh_rearm2_guid : PlanetSideGUID, bfr_rearm1_guid : PlanetSideGUID, bfr_rearm2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false, VariantVehicleData(0),
|
||||
Some(InventoryData(List(
|
||||
InternalSlot(ObjectClass.lodestar_repair_terminal, repair1_guid, 2, CommonTerminalData(faction, 2)),
|
||||
InternalSlot(ObjectClass.lodestar_repair_terminal, repair2_guid, 3, CommonTerminalData(faction, 2)),
|
||||
|
|
@ -239,11 +252,12 @@ object Prefab {
|
|||
InternalSlot(ObjectClass.bfr_rearm_terminal, bfr_rearm1_guid, 6, CommonTerminalData(faction, 2)),
|
||||
InternalSlot(ObjectClass.bfr_rearm_terminal, bfr_rearm2_guid, 7, CommonTerminalData(faction, 2))
|
||||
)))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def magrider(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.particle_beam_magrider, weapon1_guid, 2,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.pulse_battery, ammo1_guid, 0, AmmoBoxData(8))
|
||||
|
|
@ -252,11 +266,12 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.heavy_rail_beam_battery, ammo2_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def mediumtransport(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID): VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.mediumtransport_weapon_systemA, weapon1_guid, 5,
|
||||
WeaponData(0x6, 0x8, ObjectClass.bullet_20mm, ammo1_guid, 0, AmmoBoxData(0x8))
|
||||
|
|
@ -265,25 +280,28 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, ObjectClass.bullet_20mm, ammo2_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def mosquito(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.rotarychaingun_mosquito, weapon_guid, 1,
|
||||
WeaponData(0x6, 0x8, ObjectClass.bullet_12mm, ammo_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def phantasm(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)), None)(VehicleFormat.Variant)
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)), None)(VehicleFormat.Variant)
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false, VariantVehicleData(0), None)
|
||||
}
|
||||
|
||||
def prowler(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.prowler_weapon_systemA, weapon1_guid, 3,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_105mm, ammo1_guid, 0, AmmoBoxData(8))
|
||||
|
|
@ -292,53 +310,59 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_15mm, ammo2_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def quadassault(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.quadassault_weapon_system, weapon_guid, 1,
|
||||
WeaponData(0x6, 0x8, ObjectClass.bullet_12mm, ammo_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def quadstealth(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, false, false, false, None, None)(VehicleFormat.Normal)
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, false, false, false, None, None)(VehicleFormat.Normal)
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false, None)
|
||||
}
|
||||
|
||||
def router(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, terminal_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.Mobile, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.teleportpad_terminal, terminal_guid, 1, CommonTerminalData(faction, 2)) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def skyguard(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.skyguard_weapon_system, weapon_guid, 2,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.skyguard_flak_cannon_ammo, ammo1_guid, 0, AmmoBoxData(8), ObjectClass.bullet_12mm, ammo2_guid, 1, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def switchblade(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, driveState : DriveState.Value, weapon_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.scythe, weapon_guid, 1,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.ancient_ammo_vehicle, ammo1_guid, 0, AmmoBoxData(0x8), ObjectClass.ancient_ammo_vehicle, ammo2_guid, 1, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def threemanheavybuggy(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.chaingun_p, weapon1_guid, 3,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo1_guid, 0, AmmoBoxData(0x8))
|
||||
|
|
@ -347,11 +371,12 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.heavy_grenade_mortar, ammo2_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def thunderer(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.thunderer_weapon_systema, weapon1_guid, 5,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.gauss_cannon_ammo, ammo1_guid, 0, AmmoBoxData(0x8))
|
||||
|
|
@ -360,51 +385,56 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.gauss_cannon_ammo, ammo2_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def two_man_assault_buggy(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.chaingun_p, weapon_guid, 2,
|
||||
WeaponData(0x6, 0x8, ObjectClass.bullet_12mm, ammo_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def twomanheavybuggy(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.advanced_missile_launcher_t, weapon_guid, 2,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.firebird_missile, ammo_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def twomanhoverbuggy(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.flux_cannon_thresher, weapon_guid, 2,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.flux_cannon_thresher_battery, ammo_guid, 0, AmmoBoxData(0x8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def vanguard(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false,
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.vanguard_weapon_system, weapon_guid, 2,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_150mm, ammo1_guid, 0, AmmoBoxData(8), ObjectClass.bullet_20mm, ammo2_guid, 1, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Normal)
|
||||
)
|
||||
}
|
||||
|
||||
def vulture(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 2), health, DriveState.State7, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.vulture_nose_weapon_system, weapon1_guid, 3,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_35mm, ammo1_guid, 0, AmmoBoxData(8))
|
||||
|
|
@ -416,17 +446,18 @@ object Prefab {
|
|||
WeaponData(0x6, 0x8, 0, ObjectClass.bullet_25mm, ammo3_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
|
||||
def wasp(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
|
||||
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
|
||||
//VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
|
||||
VehicleData(CommonFieldData(loc, faction, 0), health, DriveState.Mobile, false, VariantVehicleData(0),
|
||||
Some(InventoryData(
|
||||
InventoryItemData(ObjectClass.wasp_weapon_system, weapon_guid, 1,
|
||||
WeaponData(0x6, 0x8, 0, ObjectClass.wasp_gun_ammo, ammo1_guid, 0, AmmoBoxData(8), ObjectClass.wasp_rocket_ammo, ammo2_guid, 0, AmmoBoxData(8))
|
||||
) :: Nil
|
||||
))
|
||||
)(VehicleFormat.Variant)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import net.psforever.packet.game.PlanetSideGUID
|
|||
import net.psforever.packet.{Marshallable, PacketHelpers}
|
||||
import scodec.Attempt.{Failure, Successful}
|
||||
import scodec.{Attempt, Codec, Err}
|
||||
import shapeless.HNil
|
||||
import shapeless.HNil //note: do not import shapeless.:: here; it messes up List's :: function
|
||||
import scodec.codecs._
|
||||
import net.psforever.types.DriveState
|
||||
import net.psforever.types.{DriveState, PlanetSideEmpire}
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
|
|
@ -50,100 +50,103 @@ final case class VariantVehicleData(unk : Int) extends SpecificVehicleData {
|
|||
}
|
||||
|
||||
/**
|
||||
* A representation of a generic vehicle.<br>
|
||||
* <br>
|
||||
* Vehicles utilize their own packet to communicate position to the server, known as `VehicleStateMessage`.
|
||||
* This takes the place of `PlayerStateMessageUpstream` when the player avatar is in control;
|
||||
* and, it takes the place of `PlayerStateMessage` for other players when they are in control.
|
||||
* If the vehicle is sufficiently complicated, a `ChildObjectStateMessage` will be used.
|
||||
* This packet will control any turret(s) on the vehicle.
|
||||
* For very complicated vehicles, the packets `FrameVehicleStateMessage` and `VehicleSubStateMessage` will also be employed.
|
||||
* The tasks that these packets perform are different based on the vehicle that responds or generates them.
|
||||
* @param basic data common to objects
|
||||
* A representation of a generic vehicle.
|
||||
* @param pos where the vehicle is and how it is oriented in the game world
|
||||
* @param faction the faction that is aligned with this vehicle
|
||||
* @param bops this vehicle belongs to the Black Ops, regardless of the faction field;
|
||||
* activates the green camo and adjusts permissions
|
||||
* @param destroyed this vehicle has ben destroyed;
|
||||
* it's health should be less than 3/255, or 0%
|
||||
* @param unk1 na
|
||||
* @param health the amount of health the vehicle has, as a percentage of a filled bar (255)
|
||||
* @param jammered this vehicle is under the influence of a jammer grenade
|
||||
* @param unk2 na
|
||||
* @param owner_guid the vehicle's (official) owner;
|
||||
* verified as a living player in the game world on the same continent as the vehicle;
|
||||
* sitting in the driver's seat or a `PlanetSideAttributeMessage` of type 21 can influence
|
||||
* @param unk3 na
|
||||
* @param health the amount of health the vehicle has, as a percentage of a filled bar (255)
|
||||
* @param unk4 na
|
||||
* @param no_mount_points do not display entry points for the seats
|
||||
* @param driveState a representation for the current mobility state;
|
||||
* various vehicles also use this field to indicate "deployment," e.g., AMS
|
||||
* @param unk3 na
|
||||
* various vehicles also use this field to indicate "deployment," e.g., the advanced mobile spawn
|
||||
* @param unk5 na
|
||||
* @param cloak if a cloakable vehicle is cloaked
|
||||
* @param unk4 na
|
||||
* @param unk6 na
|
||||
* @param cloak if a vehicle (that can cloak) is cloaked
|
||||
* @param vehicle_format_data extra information necessary to implement special-type vehicles;
|
||||
* see `vehicle_type`
|
||||
* @param inventory the seats, mounted weapons, and utilities (such as terminals) that are currently included;
|
||||
* will also include trunk contents
|
||||
* will also include trunk contents;
|
||||
* the driver is the only valid seat entry (more will cause the access permissions to act up)
|
||||
* @param vehicle_type a modifier for parsing the vehicle data format differently;
|
||||
* see `vehicle_format_data`;
|
||||
* defaults to `Normal`
|
||||
*/
|
||||
final case class VehicleData(basic : CommonFieldData,
|
||||
final case class VehicleData(pos : PlacementData,
|
||||
faction : PlanetSideEmpire.Value,
|
||||
bops : Boolean,
|
||||
destroyed : Boolean,
|
||||
unk1 : Int,
|
||||
health : Int,
|
||||
jammered : Boolean,
|
||||
unk2 : Boolean,
|
||||
owner_guid : PlanetSideGUID,
|
||||
unk3 : Boolean,
|
||||
health : Int,
|
||||
unk4 : Boolean,
|
||||
no_mount_points : Boolean,
|
||||
driveState : DriveState.Value,
|
||||
unk3 : Boolean,
|
||||
unk5 : Boolean,
|
||||
unk6 : Boolean,
|
||||
cloak : Boolean,
|
||||
unk4 : Option[SpecificVehicleData],
|
||||
inventory : Option[InventoryData] = None
|
||||
)(val vehicle_type : VehicleFormat.Value = VehicleFormat.Normal) extends ConstructorData {
|
||||
vehicle_format_data : Option[SpecificVehicleData],
|
||||
inventory : Option[InventoryData] = None)
|
||||
(val vehicle_type : VehicleFormat.Value = VehicleFormat.Normal) extends ConstructorData {
|
||||
override def bitsize : Long = {
|
||||
val basicSize = basic.bitsize
|
||||
val extraBitsSize : Long = if(unk4.isDefined) { unk4.get.bitsize } else { 0L }
|
||||
//factor guard bool values into the base size, not its corresponding optional field
|
||||
val posSize : Long = pos.bitsize
|
||||
val extraBitsSize : Long = if(vehicle_format_data.isDefined) { vehicle_format_data.get.bitsize } else { 0L }
|
||||
val inventorySize = if(inventory.isDefined) { inventory.get.bitsize } else { 0L }
|
||||
24L + basicSize + extraBitsSize + inventorySize
|
||||
47L + posSize + extraBitsSize + inventorySize
|
||||
}
|
||||
}
|
||||
|
||||
object VehicleData extends Marshallable[VehicleData] {
|
||||
/**
|
||||
* Overloaded constructor for specifically handling `Normal` vehicle format.
|
||||
* @param basic data common to objects
|
||||
* @param unk1 na
|
||||
* @param basic a field that encompasses some data used by the vehicle, including `faction` and `owner`
|
||||
* @param health the amount of health the vehicle has, as a percentage of a filled bar (255)
|
||||
* @param unk2 na
|
||||
* @param driveState a representation for the current mobility state;
|
||||
* @param unk3 na
|
||||
* @param unk4 na
|
||||
* @param driveState a representation for the current mobility state
|
||||
* @param cloak if a vehicle (that can cloak) is cloaked
|
||||
* @param inventory the seats, mounted weapons, and utilities (such as terminals) that are currently included
|
||||
* @return a `VehicleData` object
|
||||
*/
|
||||
def apply(basic : CommonFieldData, unk1 : Int, health : Int, unk2 : Int, driveState : DriveState.Value, unk3 : Boolean, unk4 : Int, inventory : Option[InventoryData]) : VehicleData = {
|
||||
new VehicleData(basic, unk1, health, unk2>0, false, driveState, unk3, unk4>0, false, None, inventory)(VehicleFormat.Normal)
|
||||
def apply(basic : CommonFieldData, health : Int, driveState : DriveState.Value, cloak : Boolean, inventory : Option[InventoryData]) : VehicleData = {
|
||||
VehicleData(basic.pos, basic.faction, basic.bops, basic.destroyed, 0, basic.jammered, false, basic.player_guid,
|
||||
false, health, false, false, driveState, false, false, cloak, None, inventory)(VehicleFormat.Normal)
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded constructor for specifically handling `Utility` vehicle format.
|
||||
* @param basic data common to objects
|
||||
* @param unk1 na
|
||||
* @param basic a field that encompasses some data used by the vehicle, including `faction` and `owner`
|
||||
* @param health the amount of health the vehicle has, as a percentage of a filled bar (255)
|
||||
* @param unk2 na
|
||||
* @param driveState a representation for the current mobility state;
|
||||
* @param unk3 na
|
||||
* @param unk4 utility-specific field
|
||||
* @param unk5 na
|
||||
* @param driveState a representation for the current mobility state
|
||||
* @param cloak if a vehicle (that can cloak) is cloaked
|
||||
* @param inventory the seats, mounted weapons, and utilities (such as terminals) that are currently included
|
||||
* @return a `VehicleData` object
|
||||
*/
|
||||
def apply(basic : CommonFieldData, unk1 : Int, health : Int, unk2 : Int, driveState : DriveState.Value, unk3 : Boolean, unk4 : UtilityVehicleData, unk5 : Int, inventory : Option[InventoryData]) : VehicleData = {
|
||||
new VehicleData(basic, unk1, health, unk2>0, false, driveState, unk3, unk5>0, false, Some(unk4), inventory)(VehicleFormat.Utility)
|
||||
def apply(basic : CommonFieldData, health : Int, driveState : DriveState.Value, cloak : Boolean, format : UtilityVehicleData, inventory : Option[InventoryData]) : VehicleData = {
|
||||
VehicleData(basic.pos, basic.faction, basic.bops, basic.destroyed, 0, basic.jammered, false, basic.player_guid,
|
||||
false, health, false, false, driveState, false, false, cloak, Some(format), inventory)(VehicleFormat.Utility)
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded constructor for specifically handling `Variant` vehicle format.
|
||||
* @param basic data common to objects
|
||||
* @param unk1 na
|
||||
* @param basic a field that encompasses some data used by the vehicle, including `faction` and `owner`
|
||||
* @param health the amount of health the vehicle has, as a percentage of a filled bar (255)
|
||||
* @param unk2 na
|
||||
* @param driveState a representation for the current mobility state;
|
||||
* @param unk3 na
|
||||
* @param unk4 variant-specific field
|
||||
* @param unk5 na
|
||||
* @param driveState a representation for the current mobility state
|
||||
* @param cloak if a vehicle (that can cloak) is cloaked
|
||||
* @param inventory the seats, mounted weapons, and utilities (such as terminals) that are currently included
|
||||
* @return a `VehicleData` object
|
||||
*/
|
||||
def apply(basic : CommonFieldData, unk1 : Int, health : Int, unk2 : Int, driveState : DriveState.Value, unk3 : Boolean, unk4 : VariantVehicleData, unk5 : Int, inventory : Option[InventoryData]) : VehicleData = {
|
||||
new VehicleData(basic, unk1, health, unk2>0, false, driveState, unk3, unk5>0, false, Some(unk4), inventory)(VehicleFormat.Variant)
|
||||
def apply(basic : CommonFieldData, health : Int, driveState : DriveState.Value, cloak : Boolean, format : VariantVehicleData, inventory : Option[InventoryData]) : VehicleData = {
|
||||
VehicleData(basic.pos, basic.faction, basic.bops, basic.destroyed, 0, basic.jammered, false, basic.player_guid,
|
||||
false, health, false, false, driveState, false, false, cloak, Some(format), inventory)(VehicleFormat.Variant)
|
||||
}
|
||||
|
||||
import net.psforever.packet.game.objectcreate.{PlayerData => Player_Data}
|
||||
|
|
@ -237,41 +240,43 @@ object VehicleData extends Marshallable[VehicleData] {
|
|||
def codec(vehicle_type : VehicleFormat.Value) : Codec[VehicleData] = {
|
||||
import shapeless.::
|
||||
(
|
||||
("basic" | CommonFieldData.codec) >>:~ { com =>
|
||||
("unk1" | uint2L) ::
|
||||
("pos" | PlacementData.codec) >>:~ { pos =>
|
||||
("faction" | PlanetSideEmpire.codec) ::
|
||||
("bops" | bool) ::
|
||||
("destroyed" | bool) ::
|
||||
("unk1" | uint2L) :: //3 - na, 2 - common, 1 - na, 0 - common?
|
||||
("jammered" | bool) ::
|
||||
("unk2" | bool) ::
|
||||
("owner_guid" | PlanetSideGUID.codec) ::
|
||||
("unk3" | bool) ::
|
||||
("health" | uint8L) ::
|
||||
("unk2" | bool) :: //usually 0
|
||||
("unk4" | bool) :: //usually 0
|
||||
("no_mount_points" | bool) ::
|
||||
("driveState" | driveState8u) :: //used for deploy state
|
||||
("unk3" | bool) :: //unknown but generally false; can cause stream misalignment if set when unexpectedly
|
||||
("unk4" | bool) ::
|
||||
("unk5" | bool) :: //unknown but generally false; can cause stream misalignment if set when unexpectedly
|
||||
("unk6" | bool) ::
|
||||
("cloak" | bool) :: //cloak as wraith, phantasm
|
||||
conditional(vehicle_type != VehicleFormat.Normal, "unk5" | selectFormatReader(vehicle_type)) :: //padding?
|
||||
optional(bool, "inventory" | custom_inventory_codec(InitialStreamLengthToSeatEntries(com.pos.vel.isDefined, vehicle_type)))
|
||||
conditional(vehicle_type != VehicleFormat.Normal, "vehicle_format_data" | selectFormatReader(vehicle_type)) :: //padding?
|
||||
optional(bool, "inventory" | custom_inventory_codec(InitialStreamLengthToSeatEntries(pos.vel.isDefined, vehicle_type)))
|
||||
}
|
||||
).exmap[VehicleData] (
|
||||
{
|
||||
case basic :: u1 :: health :: u2 :: no_mount :: driveState :: u3 :: u4 :: u5 :: cloak :: inv :: HNil =>
|
||||
Attempt.successful(new VehicleData(basic, u1, health, u2, no_mount, driveState, u3, u4, u5, cloak, inv)(vehicle_type))
|
||||
case pos :: faction :: bops :: destroyed :: u1 :: jamd :: u2 :: owner :: u3 :: health :: u4 :: no_mount :: driveState :: u5 :: u6 :: cloak :: format :: inv :: HNil =>
|
||||
Attempt.successful(new VehicleData(pos, faction, bops, destroyed, u1, jamd, u2, owner, u3, health, u4, no_mount, driveState, u5, u6, cloak, format, inv)(vehicle_type))
|
||||
|
||||
case _ =>
|
||||
Attempt.failure(Err("invalid vehicle data format"))
|
||||
},
|
||||
{
|
||||
case obj @ VehicleData(basic, u1, health, u2, no_mount, driveState, u3, u4, cloak, Some(u5), inv) =>
|
||||
if(obj.vehicle_type == VehicleFormat.Normal) {
|
||||
Attempt.failure(Err("invalid vehicle data format; variable bits not expected; will ignore ..."))
|
||||
case obj @ VehicleData(pos, faction, bops, destroyed, u1, jamd, u2, owner, u3, health, u4, no_mount, driveState, u5, u6, cloak, format, inv) =>
|
||||
if(obj.vehicle_type == VehicleFormat.Normal && format.nonEmpty) {
|
||||
Attempt.failure(Err("invalid vehicle data format; variable bits not expected"))
|
||||
}
|
||||
else if(obj.vehicle_type != VehicleFormat.Normal && format.isEmpty) {
|
||||
Attempt.failure(Err(s"invalid vehicle data format; variable bits for ${obj.vehicle_type} expected"))
|
||||
}
|
||||
else {
|
||||
Attempt.successful(basic :: u1 :: health :: u2 :: no_mount :: driveState :: u3 :: u4 :: cloak :: Some(u5) :: inv :: HNil)
|
||||
}
|
||||
|
||||
case obj @ VehicleData(basic, u1, health, u2, no_mount, driveState, u3, u4, cloak, None, inv) =>
|
||||
if(obj.vehicle_type != VehicleFormat.Normal) {
|
||||
Attempt.failure(Err("invalid vehicle data format; variable bits expected"))
|
||||
}
|
||||
else {
|
||||
Attempt.successful(basic :: u1 :: health :: u2 :: no_mount :: driveState :: u3 :: u4 :: cloak :: None :: inv :: HNil)
|
||||
Attempt.successful(pos :: faction :: bops :: destroyed :: u1 :: jamd :: u2 :: owner :: u3 :: health :: u4 :: no_mount :: driveState :: u5 :: u6 :: cloak :: format :: inv :: HNil)
|
||||
}
|
||||
|
||||
case _ =>
|
||||
|
|
@ -284,7 +289,11 @@ object VehicleData extends Marshallable[VehicleData] {
|
|||
* Distance from the length field of a vehicle creation packet up until the start of the vehicle's inventory data.
|
||||
* The only field excluded belongs to the original opcode for the packet.
|
||||
* The parameters outline reasons why the length of the stream would be different
|
||||
* and are used to determine the exact difference value.
|
||||
* and are used to determine the exact difference value.<br>
|
||||
* Note:<br>
|
||||
* 198 includes the `ObjectCreateMessage` packet fields, without parent data,
|
||||
* the `VehicleData` fields,
|
||||
* and the first three fields of the `InternalSlot`.
|
||||
* @see `ObjectCreateMessage`
|
||||
* @param hasVelocity the presence of a velocity field - `vel` - in the `PlacementData` object for this vehicle
|
||||
* @param format the `Codec` subtype for this vehicle
|
||||
|
|
@ -333,7 +342,9 @@ object VehicleData extends Marshallable[VehicleData] {
|
|||
}
|
||||
|
||||
/**
|
||||
* A special method of handling mounted players within the same inventory space as normal `Equipment` can be encountered.
|
||||
* A special method of handling mounted players within the same inventory space as normal `Equipment` can be encountered
|
||||
* before restoring normal inventory operations.<br>
|
||||
* <br>
|
||||
* Due to variable-length fields within `PlayerData` extracted from the input,
|
||||
* the distance of the bit(stream) vector to the initial inventory entry is calculated
|
||||
* to produce the initial value for padding the `PlayerData` object's name field.
|
||||
|
|
@ -341,7 +352,11 @@ object VehicleData extends Marshallable[VehicleData] {
|
|||
* the remainder of the inventory must be handled as standard inventory
|
||||
* and finally both groups must be repackaged into a single standard `InventoryData` object.
|
||||
* Due to the unique value for the mounted players that must be updated for each entry processed,
|
||||
* the entries are temporarily formatted into a linked list before being put back into a normal `List`.
|
||||
* the entries are temporarily formatted into a linked list before being put back into a normal `List`.<br>
|
||||
* <br>
|
||||
* 6 June 2018:<br>
|
||||
* Due to curious behavior in the vehicle seat access controls,
|
||||
* please only encode and decode the driver seat even though all seats are currently reachable.
|
||||
* @param length the distance in bits to the first inventory entry
|
||||
* @return a `Codec` that translates `InventoryData`
|
||||
*/
|
||||
|
|
@ -512,7 +527,7 @@ object VehicleData extends Marshallable[VehicleData] {
|
|||
case x :: Nil =>
|
||||
Some(InventorySeat(Some(x), None))
|
||||
case _ :: _ =>
|
||||
var link = InventorySeat(Some(list.last), None)
|
||||
var link = InventorySeat(Some(list.last), None) //build the chain in reverse order, starting with the last entry
|
||||
list.reverse.drop(1).foreach(seat => {
|
||||
link = InventorySeat(Some(seat), Some(link))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -503,18 +503,12 @@ class DetailedCharacterDataTest extends Specification {
|
|||
Nil
|
||||
)
|
||||
val obj = DetailedPlayerData.apply(app, char, inv, DrawnSlot.Pistol1)
|
||||
//it shouldn't be Pistol1 if he's seated but it's fine for the test
|
||||
|
||||
val msg = ObjectCreateDetailedMessage(0x79, PlanetSideGUID(75), ObjectCreateMessageParent(PlanetSideGUID(43981), 0), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
val pkt_bitv = pkt.toBitVector
|
||||
val ori_bitv = string_seated.toBitVector
|
||||
// var test = pkt_bitv
|
||||
// while(test.nonEmpty) {
|
||||
// val (printHex, save) = test.splitAt(512)
|
||||
// test = save
|
||||
// println(printHex)
|
||||
// }
|
||||
pkt_bitv.take(16) mustEqual ori_bitv.take(16)
|
||||
pkt_bitv mustEqual ori_bitv
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ package game.objectcreatevehicle
|
|||
import net.psforever.packet._
|
||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types._
|
||||
import org.specs2.mutable._
|
||||
import scodec.bits._
|
||||
|
||||
|
|
|
|||
|
|
@ -25,23 +25,25 @@ class MountedVehiclesTest extends Specification {
|
|||
parent mustEqual None
|
||||
data match {
|
||||
case Some(vdata : VehicleData) =>
|
||||
vdata.basic.pos.coord mustEqual Vector3(4571.6875f, 5602.1875f, 93)
|
||||
vdata.basic.pos.orient mustEqual Vector3(11.25f, 2.8125f, 92.8125f)
|
||||
vdata.basic.pos.vel mustEqual Some(Vector3(31.71875f, 8.875f, -0.03125f))
|
||||
vdata.basic.faction mustEqual PlanetSideEmpire.TR
|
||||
vdata.basic.bops mustEqual false
|
||||
vdata.basic.destroyed mustEqual false
|
||||
vdata.basic.jammered mustEqual false
|
||||
vdata.basic.player_guid mustEqual PlanetSideGUID(1888)
|
||||
vdata.unk1 mustEqual 0
|
||||
vdata.pos.coord mustEqual Vector3(4571.6875f, 5602.1875f, 93)
|
||||
vdata.pos.orient mustEqual Vector3(11.25f, 2.8125f, 92.8125f)
|
||||
vdata.pos.vel mustEqual Some(Vector3(31.71875f, 8.875f, -0.03125f))
|
||||
vdata.faction mustEqual PlanetSideEmpire.TR
|
||||
vdata.bops mustEqual false
|
||||
vdata.destroyed mustEqual false
|
||||
vdata.jammered mustEqual false
|
||||
vdata.owner_guid mustEqual PlanetSideGUID(3776)
|
||||
vdata.health mustEqual 255
|
||||
vdata.unk2 mustEqual false
|
||||
vdata.no_mount_points mustEqual false
|
||||
vdata.driveState mustEqual DriveState.Mobile
|
||||
vdata.unk3 mustEqual false
|
||||
vdata.unk5 mustEqual false
|
||||
vdata.cloak mustEqual false
|
||||
vdata.unk4 mustEqual Some(VariantVehicleData(7))
|
||||
vdata.unk1 mustEqual 0
|
||||
vdata.unk2 mustEqual false
|
||||
vdata.unk3 mustEqual false
|
||||
vdata.unk4 mustEqual false
|
||||
vdata.unk5 mustEqual false
|
||||
vdata.unk6 mustEqual false
|
||||
vdata.vehicle_format_data mustEqual Some(VariantVehicleData(7))
|
||||
vdata.inventory match {
|
||||
case Some(InventoryData(list)) =>
|
||||
list.head.objectClass mustEqual ObjectClass.avatar
|
||||
|
|
@ -147,17 +149,18 @@ class MountedVehiclesTest extends Specification {
|
|||
)
|
||||
val player = VehicleData.PlayerData(app, char, inv, DrawnSlot.None, VehicleData.InitialStreamLengthToSeatEntries(true, VehicleFormat.Variant))
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(
|
||||
Vector3(4571.6875f, 5602.1875f, 93),
|
||||
Vector3(11.25f, 2.8125f, 92.8125f),
|
||||
Some(Vector3(31.71875f, 8.875f, -0.03125f))
|
||||
),
|
||||
PlanetSideEmpire.TR,
|
||||
false, false, 0, false,
|
||||
PlanetSideGUID(1888)
|
||||
PlacementData(
|
||||
Vector3(4571.6875f, 5602.1875f, 93),
|
||||
Vector3(11.25f, 2.8125f, 92.8125f),
|
||||
Some(Vector3(31.71875f, 8.875f, -0.03125f))
|
||||
),
|
||||
0, 255,
|
||||
PlanetSideEmpire.TR,
|
||||
false, false,
|
||||
0,
|
||||
false, false,
|
||||
PlanetSideGUID(3776),
|
||||
false,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
|
|
|
|||
|
|
@ -24,16 +24,12 @@ class NormalVehiclesTest extends Specification {
|
|||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val fury = data.get.asInstanceOf[VehicleData]
|
||||
fury.basic.pos.coord.x mustEqual 6531.961f
|
||||
fury.basic.pos.coord.y mustEqual 1872.1406f
|
||||
fury.basic.pos.coord.z mustEqual 24.734375f
|
||||
fury.basic.pos.orient.x mustEqual 0f
|
||||
fury.basic.pos.orient.y mustEqual 0f
|
||||
fury.basic.pos.orient.z mustEqual 357.1875f
|
||||
fury.basic.pos.vel.isDefined mustEqual false
|
||||
fury.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
fury.basic.unk mustEqual 2
|
||||
fury.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
fury.pos.coord mustEqual Vector3(6531.961f, 1872.1406f,24.734375f)
|
||||
fury.pos.orient mustEqual Vector3(0, 0, 357.1875f)
|
||||
fury.pos.vel mustEqual None
|
||||
fury.faction mustEqual PlanetSideEmpire.VS
|
||||
fury.unk1 mustEqual 2
|
||||
fury.owner_guid mustEqual PlanetSideGUID(0)
|
||||
fury.health mustEqual 255
|
||||
//
|
||||
fury.inventory.isDefined mustEqual true
|
||||
|
|
@ -69,16 +65,14 @@ class NormalVehiclesTest extends Specification {
|
|||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val lightning = data.get.asInstanceOf[VehicleData]
|
||||
lightning.basic.pos.coord.x mustEqual 3674.8438f
|
||||
lightning.basic.pos.coord.y mustEqual 2726.789f
|
||||
lightning.basic.pos.coord.z mustEqual 91.15625f
|
||||
lightning.basic.pos.orient.x mustEqual 0f
|
||||
lightning.basic.pos.orient.y mustEqual 0f
|
||||
lightning.basic.pos.orient.z mustEqual 90.0f
|
||||
lightning.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
lightning.basic.unk mustEqual 2
|
||||
lightning.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
lightning.pos.coord mustEqual Vector3(3674.8438f, 2726.789f, 91.15625f)
|
||||
lightning.pos.orient mustEqual Vector3(0, 0, 90)
|
||||
lightning.pos.vel mustEqual None
|
||||
lightning.faction mustEqual PlanetSideEmpire.VS
|
||||
lightning.unk1 mustEqual 2
|
||||
lightning.owner_guid mustEqual PlanetSideGUID(0)
|
||||
lightning.health mustEqual 255
|
||||
|
||||
lightning.inventory.isDefined mustEqual true
|
||||
lightning.inventory.get.contents.size mustEqual 1
|
||||
val mounting = lightning.inventory.get.contents.head
|
||||
|
|
@ -120,22 +114,23 @@ class NormalVehiclesTest extends Specification {
|
|||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val deliverer = data.get.asInstanceOf[VehicleData]
|
||||
deliverer.basic.pos.coord.x mustEqual 6531.961f
|
||||
deliverer.basic.pos.coord.y mustEqual 1872.1406f
|
||||
deliverer.basic.pos.coord.z mustEqual 24.734375f
|
||||
deliverer.basic.pos.orient.x mustEqual 0f
|
||||
deliverer.basic.pos.orient.y mustEqual 0f
|
||||
deliverer.basic.pos.orient.z mustEqual 357.1875f
|
||||
deliverer.basic.faction mustEqual PlanetSideEmpire.NC
|
||||
deliverer.basic.unk mustEqual 2
|
||||
deliverer.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
deliverer.unk1 mustEqual 0
|
||||
deliverer.pos.coord mustEqual Vector3(6531.961f, 1872.1406f, 24.734375f)
|
||||
deliverer.pos.orient mustEqual Vector3(0, 0, 357.1875f)
|
||||
deliverer.pos.vel mustEqual None
|
||||
deliverer.faction mustEqual PlanetSideEmpire.NC
|
||||
deliverer.owner_guid mustEqual PlanetSideGUID(0)
|
||||
deliverer.health mustEqual 255
|
||||
deliverer.unk2 mustEqual false
|
||||
deliverer.driveState mustEqual DriveState.State7
|
||||
deliverer.unk3 mustEqual true
|
||||
deliverer.unk4 mustEqual None
|
||||
deliverer.unk5 mustEqual false
|
||||
deliverer.jammered mustEqual false
|
||||
deliverer.destroyed mustEqual false
|
||||
deliverer.cloak mustEqual false
|
||||
deliverer.unk1 mustEqual 2
|
||||
deliverer.unk2 mustEqual false
|
||||
deliverer.unk3 mustEqual false
|
||||
deliverer.unk4 mustEqual false
|
||||
deliverer.unk5 mustEqual true
|
||||
deliverer.unk6 mustEqual false
|
||||
deliverer.vehicle_format_data mustEqual None
|
||||
deliverer.inventory.isDefined mustEqual true
|
||||
deliverer.inventory.get.contents.size mustEqual 2
|
||||
//0
|
||||
|
|
@ -179,11 +174,13 @@ class NormalVehiclesTest extends Specification {
|
|||
|
||||
"encode (fury)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.VS, 2
|
||||
),
|
||||
0,
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.VS,
|
||||
false, false,
|
||||
2,
|
||||
false, false,
|
||||
PlanetSideGUID(0),
|
||||
false,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
|
|
@ -203,11 +200,13 @@ class NormalVehiclesTest extends Specification {
|
|||
|
||||
"encode (lightning)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(3674.8438f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 2
|
||||
),
|
||||
0,
|
||||
PlacementData(3674.8438f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS,
|
||||
false, false,
|
||||
2,
|
||||
false, false,
|
||||
PlanetSideGUID(0),
|
||||
false,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
|
|
@ -227,11 +226,13 @@ class NormalVehiclesTest extends Specification {
|
|||
|
||||
"encode (medium transport)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.NC, 2
|
||||
),
|
||||
0,
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.NC,
|
||||
false, false,
|
||||
2,
|
||||
false, false,
|
||||
PlanetSideGUID(0),
|
||||
false,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.State7,
|
||||
|
|
|
|||
|
|
@ -11,120 +11,122 @@ import scodec.bits._
|
|||
class UtilityVehiclesTest extends Specification {
|
||||
val string_ant = hex"17 C2000000 9E0 7C01 6C2D7 65535 CA16 00 00 00 4400003FC000000"
|
||||
val string_ams = hex"17 B8010000 970 3D10 002D765535CA16000000 402285BB0037E4100749E1D03000000620D83A0A00000195798741C00000332E40D84800000"
|
||||
val string_ams_seated =
|
||||
hex"17ec060000970fe0f030898abda28127f007ff9c1f2f80c0001e18ff00001051e40786400000008c50004c0041006d0069006e006700790075006500540052007c00000304217c859e8080000000000000002503420022c02a002a002a002a0050004c0041002a002a002a002a00010027e300940000016c0400023c040002285a086c2f00c80000000000300210288740800000004046f17423018000002c4d6190400000001010704a86406000002bc770842000000004041c5f21d01800000e075821902000000623e84208000001950588c1800000332ea0f840000000"
|
||||
// val string_ams_seated =
|
||||
// hex"17ec060000970fe0f030898abda28127f007ff9c1f2f80c0001e18ff00001051e40786400000008c50004c0041006d0069006e006700790075006500540052007c00000304217c859e8080000000000000002503420022c02a002a002a002a0050004c0041002a002a002a002a00010027e300940000016c0400023c040002285a086c2f00c80000000000300210288740800000004046f17423018000002c4d6190400000001010704a86406000002bc770842000000004041c5f21d01800000e075821902000000623e84208000001950588c1800000332ea0f840000000"
|
||||
|
||||
"Utility vehicles" should {
|
||||
// "decode (ant)" in {
|
||||
// PacketCoding.DecodePacket(string_ant).require match {
|
||||
// case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
// len mustEqual 194L
|
||||
// cls mustEqual ObjectClass.ant
|
||||
// guid mustEqual PlanetSideGUID(380)
|
||||
// parent.isDefined mustEqual false
|
||||
// data.isDefined mustEqual true
|
||||
// data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
// val ant = data.get.asInstanceOf[VehicleData]
|
||||
// ant.basic.pos.coord.x mustEqual 3674.8438f
|
||||
// ant.basic.pos.coord.y mustEqual 2726.789f
|
||||
// ant.basic.pos.coord.z mustEqual 91.15625f
|
||||
// ant.basic.pos.orient.x mustEqual 0f
|
||||
// ant.basic.pos.orient.y mustEqual 0f
|
||||
// ant.basic.pos.orient.z mustEqual 90.0f
|
||||
// ant.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
// ant.basic.unk mustEqual 2
|
||||
// ant.basic.player_guid mustEqual PlanetSideGUID(0)
|
||||
// ant.health mustEqual 255
|
||||
// ant.driveState mustEqual DriveState.Mobile
|
||||
// case _ =>
|
||||
// ko
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// "decode (ams)" in {
|
||||
// PacketCoding.DecodePacket(string_ams).require match {
|
||||
// case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
// len mustEqual 440L
|
||||
// cls mustEqual ObjectClass.ams
|
||||
// guid mustEqual PlanetSideGUID(4157)
|
||||
// parent.isDefined mustEqual false
|
||||
// data.isDefined mustEqual true
|
||||
// data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
// val ams = data.get.asInstanceOf[VehicleData]
|
||||
// ams.basic.pos.coord.x mustEqual 3674.0f
|
||||
// ams.basic.pos.coord.y mustEqual 2726.789f
|
||||
// ams.basic.pos.coord.z mustEqual 91.15625f
|
||||
// ams.basic.pos.orient.x mustEqual 0f
|
||||
// ams.basic.pos.orient.y mustEqual 0f
|
||||
// ams.basic.pos.orient.z mustEqual 90.0f
|
||||
// ams.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
// ams.basic.unk mustEqual 0
|
||||
// ams.basic.player_guid mustEqual PlanetSideGUID(34082)
|
||||
// ams.unk1 mustEqual 2
|
||||
// ams.health mustEqual 236
|
||||
// ams.unk2 mustEqual false
|
||||
// ams.driveState mustEqual DriveState.Deployed
|
||||
//
|
||||
// ams.inventory.isDefined mustEqual true
|
||||
// val inv = ams.inventory.get.contents
|
||||
// inv.head.objectClass mustEqual ObjectClass.matrix_terminalc
|
||||
// inv.head.guid mustEqual PlanetSideGUID(3663)
|
||||
// inv.head.parentSlot mustEqual 1
|
||||
// inv.head.obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
// inv(1).objectClass mustEqual ObjectClass.ams_respawn_tube
|
||||
// inv(1).guid mustEqual PlanetSideGUID(3638)
|
||||
// inv(1).parentSlot mustEqual 2
|
||||
// inv(1).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
// inv(2).objectClass mustEqual ObjectClass.order_terminala
|
||||
// inv(2).guid mustEqual PlanetSideGUID(3827)
|
||||
// inv(2).parentSlot mustEqual 3
|
||||
// inv(2).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
// inv(3).objectClass mustEqual ObjectClass.order_terminalb
|
||||
// inv(3).guid mustEqual PlanetSideGUID(3556)
|
||||
// inv(3).parentSlot mustEqual 4
|
||||
// inv(3).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
// case _ =>
|
||||
// ko
|
||||
// }
|
||||
// }
|
||||
//
|
||||
"decode (ams, seated)" in {
|
||||
PacketCoding.DecodePacket(string_ams_seated).require match {
|
||||
"decode (ant)" in {
|
||||
PacketCoding.DecodePacket(string_ant).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 194L
|
||||
cls mustEqual ObjectClass.ant
|
||||
guid mustEqual PlanetSideGUID(380)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val ant = data.get.asInstanceOf[VehicleData]
|
||||
ant.pos.coord mustEqual Vector3(3674.8438f, 2726.789f, 91.15625f)
|
||||
ant.pos.orient mustEqual Vector3(0, 0, 90)
|
||||
ant.faction mustEqual PlanetSideEmpire.VS
|
||||
ant.owner_guid mustEqual PlanetSideGUID(0)
|
||||
ant.driveState mustEqual DriveState.Mobile
|
||||
ant.health mustEqual 255
|
||||
ant.jammered mustEqual false
|
||||
ant.destroyed mustEqual false
|
||||
ant.cloak mustEqual false
|
||||
ant.unk1 mustEqual 2
|
||||
ant.unk2 mustEqual false
|
||||
ant.unk3 mustEqual false
|
||||
ant.unk4 mustEqual false
|
||||
ant.unk5 mustEqual false
|
||||
ant.unk6 mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
//
|
||||
// "encode (ant)" in {
|
||||
// val obj = VehicleData(
|
||||
// CommonFieldData(
|
||||
// PlacementData(3674.8438f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
// PlanetSideEmpire.VS, 2
|
||||
// ),
|
||||
// 0,
|
||||
// 255,
|
||||
// false, false,
|
||||
// DriveState.Mobile,
|
||||
// false, false, false,
|
||||
// Some(UtilityVehicleData(0)),
|
||||
// None
|
||||
// )(VehicleFormat.Utility)
|
||||
// val msg = ObjectCreateMessage(ObjectClass.ant, PlanetSideGUID(380), obj)
|
||||
// val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
//
|
||||
// pkt mustEqual string_ant
|
||||
// }
|
||||
|
||||
"decode (ams)" in {
|
||||
PacketCoding.DecodePacket(string_ams).require match {
|
||||
case ObjectCreateMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 440L
|
||||
cls mustEqual ObjectClass.ams
|
||||
guid mustEqual PlanetSideGUID(4157)
|
||||
parent.isDefined mustEqual false
|
||||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val ams = data.get.asInstanceOf[VehicleData]
|
||||
ams.pos.coord mustEqual Vector3(3674, 2726.789f, 91.15625f)
|
||||
ams.pos.orient mustEqual Vector3(0, 0, 90)
|
||||
ams.pos.vel mustEqual None
|
||||
ams.faction mustEqual PlanetSideEmpire.VS
|
||||
ams.owner_guid mustEqual PlanetSideGUID(2885)
|
||||
ams.driveState mustEqual DriveState.Deployed
|
||||
ams.vehicle_format_data mustEqual Some(UtilityVehicleData(60))
|
||||
ams.health mustEqual 236
|
||||
ams.jammered mustEqual false
|
||||
ams.destroyed mustEqual false
|
||||
ams.cloak mustEqual true
|
||||
ams.unk1 mustEqual 0
|
||||
ams.unk2 mustEqual false
|
||||
ams.unk3 mustEqual false
|
||||
ams.unk4 mustEqual false
|
||||
ams.unk5 mustEqual false
|
||||
ams.unk6 mustEqual true
|
||||
|
||||
ams.inventory.isDefined mustEqual true
|
||||
val inv = ams.inventory.get.contents
|
||||
inv.head.objectClass mustEqual ObjectClass.matrix_terminalc
|
||||
inv.head.guid mustEqual PlanetSideGUID(3663)
|
||||
inv.head.parentSlot mustEqual 1
|
||||
inv.head.obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
inv(1).objectClass mustEqual ObjectClass.ams_respawn_tube
|
||||
inv(1).guid mustEqual PlanetSideGUID(3638)
|
||||
inv(1).parentSlot mustEqual 2
|
||||
inv(1).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
inv(2).objectClass mustEqual ObjectClass.order_terminala
|
||||
inv(2).guid mustEqual PlanetSideGUID(3827)
|
||||
inv(2).parentSlot mustEqual 3
|
||||
inv(2).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
inv(3).objectClass mustEqual ObjectClass.order_terminalb
|
||||
inv(3).guid mustEqual PlanetSideGUID(3556)
|
||||
inv(3).parentSlot mustEqual 4
|
||||
inv(3).obj.isInstanceOf[CommonTerminalData] mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (ant)" in {
|
||||
val obj = VehicleData(
|
||||
PlacementData(3674.8438f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS,
|
||||
false, false,
|
||||
2,
|
||||
false, false,
|
||||
PlanetSideGUID(0),
|
||||
false,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
false, false, false,
|
||||
Some(UtilityVehicleData(0)),
|
||||
None
|
||||
)(VehicleFormat.Utility)
|
||||
val msg = ObjectCreateMessage(ObjectClass.ant, PlanetSideGUID(380), obj)
|
||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_ant
|
||||
}
|
||||
|
||||
"encode (ams)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(3674.0f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS, 0,
|
||||
PlanetSideGUID(34082)
|
||||
),
|
||||
2,
|
||||
PlacementData(3674.0f, 2726.789f, 91.15625f, 0f, 0f, 90.0f),
|
||||
PlanetSideEmpire.VS,
|
||||
false, false,
|
||||
0,
|
||||
false, false,
|
||||
PlanetSideGUID(2885),
|
||||
false,
|
||||
236,
|
||||
false, false,
|
||||
DriveState.Deployed,
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ class VariantVehiclesTest extends Specification {
|
|||
data.isDefined mustEqual true
|
||||
data.get.isInstanceOf[VehicleData] mustEqual true
|
||||
val switchblade = data.get.asInstanceOf[VehicleData]
|
||||
switchblade.basic.pos.coord.x mustEqual 6531.961f
|
||||
switchblade.basic.pos.coord.y mustEqual 1872.1406f
|
||||
switchblade.basic.pos.coord.z mustEqual 24.734375f
|
||||
switchblade.basic.pos.orient.x mustEqual 0f
|
||||
switchblade.basic.pos.orient.y mustEqual 0f
|
||||
switchblade.basic.pos.orient.z mustEqual 357.1875f
|
||||
switchblade.basic.faction mustEqual PlanetSideEmpire.VS
|
||||
switchblade.basic.unk mustEqual 2
|
||||
switchblade.pos.coord.x mustEqual 6531.961f
|
||||
switchblade.pos.coord.y mustEqual 1872.1406f
|
||||
switchblade.pos.coord.z mustEqual 24.734375f
|
||||
switchblade.pos.orient.x mustEqual 0f
|
||||
switchblade.pos.orient.y mustEqual 0f
|
||||
switchblade.pos.orient.z mustEqual 357.1875f
|
||||
switchblade.faction mustEqual PlanetSideEmpire.VS
|
||||
switchblade.unk1 mustEqual 2
|
||||
switchblade.health mustEqual 255
|
||||
switchblade.driveState mustEqual DriveState.Mobile
|
||||
switchblade.inventory.isDefined mustEqual true
|
||||
|
|
@ -61,12 +61,13 @@ class VariantVehiclesTest extends Specification {
|
|||
|
||||
"encode (switchblade)" in {
|
||||
val obj = VehicleData(
|
||||
CommonFieldData(
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.VS,
|
||||
2
|
||||
),
|
||||
0,
|
||||
PlacementData(6531.961f, 1872.1406f, 24.734375f, 0f, 0f, 357.1875f),
|
||||
PlanetSideEmpire.VS,
|
||||
false, false,
|
||||
2,
|
||||
false, false,
|
||||
PlanetSideGUID(0),
|
||||
false,
|
||||
255,
|
||||
false, false,
|
||||
DriveState.Mobile,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class VehicleSpawnControl1Test extends ActorTest() {
|
|||
}
|
||||
|
||||
class VehicleSpawnControl2aTest extends ActorTest() {
|
||||
// This long runs for a long time.
|
||||
// This runs for a long time.
|
||||
"VehicleSpawnControl" should {
|
||||
"complete on a vehicle order (block a second one until the first is done and the spawn pad is cleared)" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
|
|
@ -102,18 +102,18 @@ class VehicleSpawnControl2aTest extends ActorTest() {
|
|||
|
||||
//if we move the vehicle more than 25m away from the pad, we should receive a ResetSpawnPad, and a second ConcealPlayer message
|
||||
//that means that the first order has cleared and the spawn pad is now working on the second order successfully
|
||||
vehicle.Position = Vector3(11,0,0)
|
||||
player.VehicleSeated = None //since shared between orders, is necessary
|
||||
vehicle.Position = Vector3(12,0,0)
|
||||
val probe3Msg5 = probe3.receiveOne(4 seconds)
|
||||
assert(probe3Msg5.isInstanceOf[VehicleSpawnPad.ResetSpawnPad])
|
||||
val probe3Msg6 = probe3.receiveOne(5 seconds)
|
||||
val probe3Msg6 = probe3.receiveOne(4 seconds)
|
||||
assert(probe3Msg6.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl2bTest extends ActorTest() {
|
||||
// This long runs for a long time.
|
||||
// This runs for a long time.
|
||||
"VehicleSpawnControl" should {
|
||||
"complete on a vehicle order (railless)" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
|
|
@ -144,7 +144,7 @@ class VehicleSpawnControl2bTest extends ActorTest() {
|
|||
assert(probe1Msg2.isInstanceOf[Mountable.MountMessages])
|
||||
val probe1Msg2Contents = probe1Msg2.asInstanceOf[Mountable.MountMessages]
|
||||
assert(probe1Msg2Contents.response.isInstanceOf[Mountable.CanMount])
|
||||
val probe1Msg3 = probe1.receiveOne(3 seconds)
|
||||
val probe1Msg3 = probe1.receiveOne(4 seconds)
|
||||
assert(probe1Msg3.isInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle])
|
||||
|
||||
val probe1Msg4 = probe1.receiveOne(1 seconds)
|
||||
|
|
@ -161,9 +161,9 @@ class VehicleSpawnControl2bTest extends ActorTest() {
|
|||
|
||||
//if we move the vehicle more than 10m away from the pad, we should receive a second ConcealPlayer message
|
||||
//that means that the first order has cleared and the spawn pad is now working on the second order successfully
|
||||
vehicle.Position = Vector3(11,0,0)
|
||||
player.VehicleSeated = None //since shared between orders, is necessary
|
||||
val probe3Msg6 = probe3.receiveOne(4 seconds)
|
||||
vehicle.Position = Vector3(12,0,0)
|
||||
val probe3Msg6 = probe3.receiveOne(10 seconds)
|
||||
assert(probe3Msg6.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
}
|
||||
}
|
||||
|
|
@ -263,9 +263,12 @@ class VehicleSpawnControl5Test extends ActorTest() {
|
|||
val probe3Msg4 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
|
||||
val probe1Msg = probe1.receiveOne(12 seconds)
|
||||
assert(probe1Msg.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
val probe1Msg1 = probe1.receiveOne(1 seconds)
|
||||
assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.RevealPlayer])
|
||||
|
||||
val probe1Msg2 = probe1.receiveOne(12 seconds)
|
||||
assert(probe1Msg2.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg2.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -292,59 +295,17 @@ class VehicleSpawnControl6Test extends ActorTest() {
|
|||
|
||||
val probe1Msg1 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
|
||||
player.Continent = "problem" //problem 1
|
||||
player.Continent = "problem" //problem
|
||||
probe1.receiveOne(200 milliseconds) //Mountable.MountMessage
|
||||
|
||||
val probe3Msg4 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
val probe3Msg5 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg5.isInstanceOf[VehicleSpawnPad.ResetSpawnPad])
|
||||
val probe1Msg2 = probe1.receiveOne(3 seconds)
|
||||
assert(probe1Msg2.isInstanceOf[VehicleSpawnPad.RevealPlayer])
|
||||
|
||||
val probe1Msg2 = probe1.receiveOne(12 seconds)
|
||||
assert(probe1Msg2.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg2.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSpawnControl7Test extends ActorTest() {
|
||||
"VehicleSpawnControl" should {
|
||||
"player dies after getting in driver seat; the vehicle blocks the pad" in {
|
||||
val (vehicle, player, pad, zone) = VehicleSpawnPadControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||
//we can recycle the vehicle and the player for each order
|
||||
val probe1 = new TestProbe(system, "first-order")
|
||||
val probe3 = new TestProbe(system, "zone-events")
|
||||
zone.VehicleEvents = probe3.ref
|
||||
|
||||
pad.Actor.tell(VehicleSpawnPad.VehicleOrder(player, vehicle), probe1.ref)
|
||||
|
||||
val probe3Msg1 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg1.isInstanceOf[VehicleSpawnPad.ConcealPlayer])
|
||||
|
||||
val probe3Msg2 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
|
||||
|
||||
val probe3Msg3 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg3.isInstanceOf[VehicleSpawnPad.AttachToRails])
|
||||
|
||||
val probe1Msg1 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg1.isInstanceOf[VehicleSpawnPad.StartPlayerSeatedInVehicle])
|
||||
val probe1Msg2 = probe1.receiveOne(200 milliseconds)
|
||||
assert(probe1Msg2.isInstanceOf[Mountable.MountMessages])
|
||||
val probe1Msg2Contents = probe1Msg2.asInstanceOf[Mountable.MountMessages]
|
||||
assert(probe1Msg2Contents.response.isInstanceOf[Mountable.CanMount])
|
||||
val probe1Msg3 = probe1.receiveOne(3 seconds)
|
||||
assert(probe1Msg3.isInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle])
|
||||
player.Die //problem
|
||||
|
||||
val probe3Msg4 = probe3.receiveOne(3 seconds)
|
||||
assert(probe3Msg4.isInstanceOf[VehicleSpawnPad.DetachFromRails])
|
||||
val probe3Msg5 = probe3.receiveOne(100 milliseconds)
|
||||
assert(probe3Msg5.isInstanceOf[VehicleSpawnPad.ResetSpawnPad])
|
||||
|
||||
val probe1Msg4 = probe1.receiveOne(12 seconds)
|
||||
assert(probe1Msg4.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg4.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
val probe1Msg3 = probe1.receiveOne(12 seconds)
|
||||
assert(probe1Msg3.isInstanceOf[VehicleSpawnPad.PeriodicReminder])
|
||||
assert(probe1Msg3.asInstanceOf[VehicleSpawnPad.PeriodicReminder].reason == VehicleSpawnPad.Reminders.Blocked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -383,7 +344,9 @@ object VehicleSpawnPadControlTest {
|
|||
player.GUID = PlanetSideGUID(10)
|
||||
player.Continent = zone.Id
|
||||
player.Spawn
|
||||
//note: pad and vehicle are both at Vector3(0,0,0) so they count as blocking
|
||||
//note: pad and vehicle are both at Vector3(1,0,0) so they count as blocking
|
||||
pad.Position = Vector3(1,0,0)
|
||||
vehicle.Position = Vector3(1,0,0)
|
||||
(vehicle, player, pad, zone)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue