mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-04-29 07:45:26 +00:00
Merge pull request #217 from Mazo/feature/CargoPassengers
Initital functionality for cargo passengers
This commit is contained in:
commit
8eb2d9cf80
24 changed files with 627 additions and 21 deletions
|
|
@ -2875,6 +2875,7 @@ object GlobalDefinitions {
|
||||||
dropship.Weapons += 12 -> cannon_dropship_20mm
|
dropship.Weapons += 12 -> cannon_dropship_20mm
|
||||||
dropship.Weapons += 13 -> cannon_dropship_20mm
|
dropship.Weapons += 13 -> cannon_dropship_20mm
|
||||||
dropship.Weapons += 14 -> dropship_rear_turret
|
dropship.Weapons += 14 -> dropship_rear_turret
|
||||||
|
dropship.Cargo += 15 -> new CargoDefinition()
|
||||||
dropship.MountPoints += 1 -> 0
|
dropship.MountPoints += 1 -> 0
|
||||||
dropship.MountPoints += 2 -> 11
|
dropship.MountPoints += 2 -> 11
|
||||||
dropship.MountPoints += 3 -> 1
|
dropship.MountPoints += 3 -> 1
|
||||||
|
|
@ -2887,6 +2888,7 @@ object GlobalDefinitions {
|
||||||
dropship.MountPoints += 10 -> 8
|
dropship.MountPoints += 10 -> 8
|
||||||
dropship.MountPoints += 11 -> 9
|
dropship.MountPoints += 11 -> 9
|
||||||
dropship.MountPoints += 12 -> 10
|
dropship.MountPoints += 12 -> 10
|
||||||
|
dropship.MountPoints += 13 -> 15
|
||||||
dropship.TrunkSize = InventoryTile.Tile1612
|
dropship.TrunkSize = InventoryTile.Tile1612
|
||||||
dropship.TrunkOffset = 30
|
dropship.TrunkOffset = 30
|
||||||
dropship.AutoPilotSpeeds = (0, 4)
|
dropship.AutoPilotSpeeds = (0, 4)
|
||||||
|
|
@ -2923,6 +2925,8 @@ object GlobalDefinitions {
|
||||||
lodestar.Name = "lodestar"
|
lodestar.Name = "lodestar"
|
||||||
lodestar.Seats += 0 -> new SeatDefinition()
|
lodestar.Seats += 0 -> new SeatDefinition()
|
||||||
lodestar.MountPoints += 1 -> 0
|
lodestar.MountPoints += 1 -> 0
|
||||||
|
lodestar.MountPoints += 2 -> 1
|
||||||
|
lodestar.Cargo += 1 -> new CargoDefinition()
|
||||||
lodestar.TrunkSize = InventoryTile.Tile1612
|
lodestar.TrunkSize = InventoryTile.Tile1612
|
||||||
lodestar.TrunkOffset = 30
|
lodestar.TrunkOffset = 30
|
||||||
lodestar.AutoPilotSpeeds = (0, 4)
|
lodestar.AutoPilotSpeeds = (0, 4)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import net.psforever.objects.serverobject.mount.Mountable
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
import net.psforever.objects.serverobject.deploy.Deployment
|
import net.psforever.objects.serverobject.deploy.Deployment
|
||||||
import net.psforever.objects.vehicles.{AccessPermissionGroup, Seat, Utility, VehicleLockState}
|
import net.psforever.objects.vehicles._
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
import net.psforever.types.PlanetSideEmpire
|
import net.psforever.types.PlanetSideEmpire
|
||||||
|
|
||||||
|
|
@ -83,10 +83,17 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
||||||
*/
|
*/
|
||||||
private val groupPermissions : Array[VehicleLockState.Value] = Array(VehicleLockState.Locked, VehicleLockState.Empire, VehicleLockState.Empire, VehicleLockState.Locked)
|
private val groupPermissions : Array[VehicleLockState.Value] = Array(VehicleLockState.Locked, VehicleLockState.Empire, VehicleLockState.Empire, VehicleLockState.Locked)
|
||||||
private var seats : Map[Int, Seat] = Map.empty
|
private var seats : Map[Int, Seat] = Map.empty
|
||||||
|
private var cargoHolds : Map[Int, Cargo] = Map.empty
|
||||||
private var weapons : Map[Int, EquipmentSlot] = Map.empty
|
private var weapons : Map[Int, EquipmentSlot] = Map.empty
|
||||||
private var utilities : Map[Int, Utility] = Map()
|
private var utilities : Map[Int, Utility] = Map()
|
||||||
private val trunk : GridInventory = GridInventory()
|
private val trunk : GridInventory = GridInventory()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records the GUID of the cargo vehicle (galaxy/lodestar) this vehicle is stored in for DismountVehicleCargoMsg use
|
||||||
|
* DismountVehicleCargoMsg only passes the player_guid and this vehicle's guid
|
||||||
|
*/
|
||||||
|
private var mountedIn : Option[PlanetSideGUID] = None
|
||||||
|
|
||||||
//init
|
//init
|
||||||
LoadDefinition()
|
LoadDefinition()
|
||||||
|
|
||||||
|
|
@ -107,6 +114,22 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
||||||
faction
|
faction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def MountedIn : Option[PlanetSideGUID] = {
|
||||||
|
this.mountedIn
|
||||||
|
}
|
||||||
|
|
||||||
|
def MountedIn_=(cargo_vehicle_guid : PlanetSideGUID) : Option[PlanetSideGUID] = MountedIn_=(Some(cargo_vehicle_guid))
|
||||||
|
|
||||||
|
def MountedIn_=(cargo_vehicle_guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||||
|
cargo_vehicle_guid match {
|
||||||
|
case Some(_) =>
|
||||||
|
this.mountedIn = cargo_vehicle_guid
|
||||||
|
case None =>
|
||||||
|
this.mountedIn = None
|
||||||
|
}
|
||||||
|
MountedIn
|
||||||
|
}
|
||||||
|
|
||||||
def Owner : Option[PlanetSideGUID] = {
|
def Owner : Option[PlanetSideGUID] = {
|
||||||
this.owner
|
this.owner
|
||||||
}
|
}
|
||||||
|
|
@ -273,6 +296,19 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
||||||
seats
|
seats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def CargoHold(cargoNumber : Int) : Option[Cargo] = {
|
||||||
|
if(cargoNumber >= 0) {
|
||||||
|
this.cargoHolds.get(cargoNumber)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def CargoHolds : Map[Int, Cargo] = {
|
||||||
|
cargoHolds
|
||||||
|
}
|
||||||
|
|
||||||
def SeatPermissionGroup(seatNumber : Int) : Option[AccessPermissionGroup.Value] = {
|
def SeatPermissionGroup(seatNumber : Int) : Option[AccessPermissionGroup.Value] = {
|
||||||
if(seatNumber == 0) {
|
if(seatNumber == 0) {
|
||||||
Some(AccessPermissionGroup.Driver)
|
Some(AccessPermissionGroup.Driver)
|
||||||
|
|
@ -289,6 +325,12 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
||||||
case None =>
|
case None =>
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
CargoHold(seatNumber) match {
|
||||||
|
case Some(_) =>
|
||||||
|
Some(AccessPermissionGroup.Passenger)
|
||||||
|
case None =>
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -558,6 +600,9 @@ object Vehicle {
|
||||||
}).toMap
|
}).toMap
|
||||||
//create seats
|
//create seats
|
||||||
vehicle.seats = vdef.Seats.map({ case(num, definition) => num -> Seat(definition)}).toMap
|
vehicle.seats = vdef.Seats.map({ case(num, definition) => num -> Seat(definition)}).toMap
|
||||||
|
// create cargo holds
|
||||||
|
vehicle.cargoHolds = vdef.Cargo.map({ case(num, definition) => num -> Cargo(definition)}).toMap
|
||||||
|
|
||||||
//create utilities
|
//create utilities
|
||||||
vehicle.utilities = vdef.Utilities.map({ case(num, util) => num -> Utility(util, vehicle) }).toMap
|
vehicle.utilities = vdef.Utilities.map({ case(num, util) => num -> Utility(util, vehicle) }).toMap
|
||||||
//trunk
|
//trunk
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.definition
|
||||||
|
|
||||||
|
import net.psforever.objects.vehicles.CargoVehicleRestriction
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The definition for a cargo hold.
|
||||||
|
*/
|
||||||
|
class CargoDefinition extends BasicDefinition {
|
||||||
|
/** a restriction on the type of exo-suit a person can wear */
|
||||||
|
private var vehicleRestriction : CargoVehicleRestriction.Value = CargoVehicleRestriction.Small
|
||||||
|
/** the user can escape while the vehicle is moving */
|
||||||
|
private var bailable : Boolean = true
|
||||||
|
Name = "cargo"
|
||||||
|
|
||||||
|
def CargoRestriction : CargoVehicleRestriction.Value = {
|
||||||
|
this.vehicleRestriction
|
||||||
|
}
|
||||||
|
|
||||||
|
def CargoRestriction_=(restriction : CargoVehicleRestriction.Value) : CargoVehicleRestriction.Value = {
|
||||||
|
this.vehicleRestriction = restriction
|
||||||
|
restriction
|
||||||
|
}
|
||||||
|
|
||||||
|
def Bailable : Boolean = {
|
||||||
|
this.bailable
|
||||||
|
}
|
||||||
|
|
||||||
|
def Bailable_=(canBail : Boolean) : Boolean = {
|
||||||
|
this.bailable = canBail
|
||||||
|
canBail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId) {
|
||||||
private var maxShields : Int = 0
|
private var maxShields : Int = 0
|
||||||
/* key - seat index, value - seat object */
|
/* key - seat index, value - seat object */
|
||||||
private val seats : mutable.HashMap[Int, SeatDefinition] = mutable.HashMap[Int, SeatDefinition]()
|
private val seats : mutable.HashMap[Int, SeatDefinition] = mutable.HashMap[Int, SeatDefinition]()
|
||||||
|
private val cargo : mutable.HashMap[Int, CargoDefinition] = mutable.HashMap[Int, CargoDefinition]()
|
||||||
/* key - entry point index, value - seat index */
|
/* key - entry point index, value - seat index */
|
||||||
private val mountPoints : mutable.HashMap[Int, Int] = mutable.HashMap()
|
private val mountPoints : mutable.HashMap[Int, Int] = mutable.HashMap()
|
||||||
/* key - seat index (where this weapon attaches during object construction), value - the weapon on an EquipmentSlot */
|
/* key - seat index (where this weapon attaches during object construction), value - the weapon on an EquipmentSlot */
|
||||||
|
|
@ -50,6 +51,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
def Seats : mutable.HashMap[Int, SeatDefinition] = seats
|
def Seats : mutable.HashMap[Int, SeatDefinition] = seats
|
||||||
|
def Cargo : mutable.HashMap[Int, CargoDefinition] = cargo
|
||||||
|
|
||||||
def MountPoints : mutable.HashMap[Int, Int] = mountPoints
|
def MountPoints : mutable.HashMap[Int, Int] = mountPoints
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.vehicles
|
||||||
|
|
||||||
|
import net.psforever.objects.{Player, Vehicle}
|
||||||
|
import net.psforever.objects.definition.{CargoDefinition}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server-side support for a slot that vehicles can occupy
|
||||||
|
* @param cargoDef the Definition that constructs this item and maintains some of its unchanging fields
|
||||||
|
*/
|
||||||
|
class Cargo(private val cargoDef : CargoDefinition) {
|
||||||
|
private var occupant : Option[Vehicle] = None
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the cargo hold occupied?
|
||||||
|
* @return The vehicle in the cargo hold, or `None` if it is left vacant
|
||||||
|
*/
|
||||||
|
def Occupant : Option[Vehicle] = {
|
||||||
|
this.occupant
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A vehicle is trying to board the cargo hold
|
||||||
|
* Cargo holds are exclusive positions that can only hold one vehicle at a time.
|
||||||
|
* @param vehicle the vehicle boarding the cargo hold, or `None` if the vehicle is leaving
|
||||||
|
* @return the vehicle sitting in this seat, or `None` if it is left vacant
|
||||||
|
*/
|
||||||
|
def Occupant_=(vehicle : Vehicle) : Option[Vehicle] = Occupant_=(Some(vehicle))
|
||||||
|
|
||||||
|
def Occupant_=(vehicle : Option[Vehicle]) : Option[Vehicle] = {
|
||||||
|
if(vehicle.isDefined) {
|
||||||
|
if(this.occupant.isEmpty) {
|
||||||
|
this.occupant = vehicle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.occupant = None
|
||||||
|
}
|
||||||
|
this.occupant
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this cargo hold occupied?
|
||||||
|
* @return `true`, if it is occupied; `false`, otherwise
|
||||||
|
*/
|
||||||
|
def isOccupied : Boolean = {
|
||||||
|
this.occupant.isDefined
|
||||||
|
}
|
||||||
|
|
||||||
|
def CargoRestriction : CargoVehicleRestriction.Value = {
|
||||||
|
cargoDef.CargoRestriction
|
||||||
|
}
|
||||||
|
|
||||||
|
def Bailable : Boolean = {
|
||||||
|
cargoDef.Bailable
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the string representation to provide additional information.
|
||||||
|
* @return the string output
|
||||||
|
*/
|
||||||
|
override def toString : String = {
|
||||||
|
Cargo.toString(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Cargo {
|
||||||
|
/**
|
||||||
|
* Overloaded constructor.
|
||||||
|
* @return a `Cargo` object
|
||||||
|
*/
|
||||||
|
def apply(cargoDef : CargoDefinition) : Cargo = {
|
||||||
|
new Cargo(cargoDef)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a fixed string representation.
|
||||||
|
* @return the string output
|
||||||
|
*/
|
||||||
|
def toString(obj : Cargo) : String = {
|
||||||
|
val cargoStr = if(obj.isOccupied) {
|
||||||
|
s", occupied by vehicle ${obj.Occupant.get.GUID}"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
s"cargo$cargoStr"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.vehicles
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An `Enumeration` of exo-suit-based seat access restrictions.<br>
|
||||||
|
* <br>
|
||||||
|
* The default value is `NoMax` as that is the most common seat.
|
||||||
|
* `NoReinforcedOrMax` is next most common.
|
||||||
|
* `MaxOnly` is a rare seat restriction found in pairs on Galaxies and on the large "Ground Transport" vehicles.
|
||||||
|
*/
|
||||||
|
object CargoVehicleRestriction extends Enumeration {
|
||||||
|
type Type = Value
|
||||||
|
|
||||||
|
val
|
||||||
|
Small,
|
||||||
|
Large
|
||||||
|
= Value
|
||||||
|
}
|
||||||
|
|
@ -395,9 +395,9 @@ object GamePacketOpcode extends Enumeration {
|
||||||
case 0x3f => game.ProjectileStateMessage.decode
|
case 0x3f => game.ProjectileStateMessage.decode
|
||||||
|
|
||||||
// OPCODES 0x40-4f
|
// OPCODES 0x40-4f
|
||||||
case 0x40 => noDecoder(MountVehicleCargoMsg)
|
case 0x40 => game.MountVehicleCargoMsg.decode
|
||||||
case 0x41 => noDecoder(DismountVehicleCargoMsg)
|
case 0x41 => game.DismountVehicleCargoMsg.decode
|
||||||
case 0x42 => noDecoder(CargoMountPointStatusMessage)
|
case 0x42 => game.CargoMountPointStatusMessage.decode
|
||||||
case 0x43 => game.BeginZoningMessage.decode
|
case 0x43 => game.BeginZoningMessage.decode
|
||||||
case 0x44 => game.ItemTransactionMessage.decode
|
case 0x44 => game.ItemTransactionMessage.decode
|
||||||
case 0x45 => game.ItemTransactionResultMessage.decode
|
case 0x45 => game.ItemTransactionResultMessage.decode
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.packet.game
|
||||||
|
|
||||||
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
|
||||||
|
import net.psforever.types.CargoStatus
|
||||||
|
import scodec.Codec
|
||||||
|
import scodec.codecs._
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param cargo_vehicle_guid Cargo vehicle GUID (galaxy / lodestar)
|
||||||
|
* @param requesting_vehicle Seems to be vehicle that requested mounting (0 after mount)
|
||||||
|
* @param mounted_vehicle Seems to be vehicle that requested mounting after mount (0 before mount)
|
||||||
|
* @param dismounted_vehicle Seems to be vehicle that was mounted after disembarking (0 before embark or reset to 0 when MountVehicleCargoMsg received)
|
||||||
|
* @param slot Mount point for cargo bay 1 = lodestar, 15 = galaxy
|
||||||
|
* @param mount_status Mount status? 0 = None, 1 = Mount/Dismount in progress, 3 = Mounted
|
||||||
|
* @param orientation 0 = normal, 1 = sideways (e.g. router in lodestar)
|
||||||
|
*/
|
||||||
|
final case class CargoMountPointStatusMessage(cargo_vehicle_guid : PlanetSideGUID,
|
||||||
|
requesting_vehicle: PlanetSideGUID,
|
||||||
|
mounted_vehicle: PlanetSideGUID,
|
||||||
|
dismounted_vehicle: PlanetSideGUID,
|
||||||
|
slot: Int,
|
||||||
|
mount_status: CargoStatus.Value,
|
||||||
|
orientation: Int)
|
||||||
|
extends PlanetSideGamePacket {
|
||||||
|
type Packet = CargoMountPointStatusMessage
|
||||||
|
|
||||||
|
def opcode = GamePacketOpcode.CargoMountPointStatusMessage
|
||||||
|
|
||||||
|
def encode = CargoMountPointStatusMessage.encode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
object CargoMountPointStatusMessage extends Marshallable[CargoMountPointStatusMessage] {
|
||||||
|
implicit val codec : Codec[CargoMountPointStatusMessage] = (
|
||||||
|
("cargo_vehicle_guid" | PlanetSideGUID.codec) ::
|
||||||
|
("requesting_vehicle" | PlanetSideGUID.codec) ::
|
||||||
|
("mounted_vehicle" | PlanetSideGUID.codec) ::
|
||||||
|
("dismounted_vehicle" | PlanetSideGUID.codec) ::
|
||||||
|
("slot" | uint8L) ::
|
||||||
|
("mount_status" | CargoStatus.codec) ::
|
||||||
|
("orientation" | uint2L)
|
||||||
|
).as[CargoMountPointStatusMessage]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.packet.game
|
||||||
|
|
||||||
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
|
||||||
|
import scodec.Codec
|
||||||
|
import scodec.codecs._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: For some reason this packet does not include the GUID of the vehicle that is being dismounted from. As a workaround vehicle.MountedIn in manually set/removed
|
||||||
|
* @param player_guid // GUID of the player that is rqeuesting dismount
|
||||||
|
* @param vehicle_guid GUID of the vehicle that is requesting dismount
|
||||||
|
* @param bailed If the vehicle bailed out of the cargo vehicle
|
||||||
|
* @param requestedByPassenger If a passenger of the vehicle in the cargo bay requests dismount this bit will be set
|
||||||
|
* @param kicked If the vehicle was kicked by the cargo vehicle pilot
|
||||||
|
*/
|
||||||
|
final case class DismountVehicleCargoMsg(player_guid : PlanetSideGUID, vehicle_guid: PlanetSideGUID, bailed: Boolean, requestedByPassenger: Boolean, kicked: Boolean)
|
||||||
|
extends PlanetSideGamePacket {
|
||||||
|
type Packet = DismountVehicleCargoMsg
|
||||||
|
|
||||||
|
def opcode = GamePacketOpcode.DismountVehicleCargoMsg
|
||||||
|
|
||||||
|
def encode = DismountVehicleCargoMsg.encode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
object DismountVehicleCargoMsg extends Marshallable[DismountVehicleCargoMsg] {
|
||||||
|
implicit val codec : Codec[DismountVehicleCargoMsg] = (
|
||||||
|
("player_guid" | PlanetSideGUID.codec) ::
|
||||||
|
("vehicle_guid" | PlanetSideGUID.codec) ::
|
||||||
|
("unk3" | bool) :: // bailed?
|
||||||
|
("unk4" | bool) ::
|
||||||
|
("unk5" | bool)
|
||||||
|
).as[DismountVehicleCargoMsg]
|
||||||
|
}
|
||||||
|
|
@ -10,11 +10,11 @@ import net.psforever.types.BailType
|
||||||
* Dispatched by the client when the player wishes to get out of a vehicle.
|
* Dispatched by the client when the player wishes to get out of a vehicle.
|
||||||
* @param player_guid the player
|
* @param player_guid the player
|
||||||
* @param bailType The dismount action e.g. normal dismount, kicked by owner, bailed
|
* @param bailType The dismount action e.g. normal dismount, kicked by owner, bailed
|
||||||
* @param unk2 na
|
* @param wasKickedByDriver Seems to be true if a passenger was manually kicked by the vehicle owner
|
||||||
*/
|
*/
|
||||||
final case class DismountVehicleMsg(player_guid : PlanetSideGUID,
|
final case class DismountVehicleMsg(player_guid : PlanetSideGUID,
|
||||||
bailType : BailType.Value,
|
bailType : BailType.Value,
|
||||||
wasKickedByDriver : Boolean) // Seems to be true if a passenger was manually kicked by the vehicle owner
|
wasKickedByDriver : Boolean)
|
||||||
extends PlanetSideGamePacket {
|
extends PlanetSideGamePacket {
|
||||||
type Packet = DismountVehicleMsg
|
type Packet = DismountVehicleMsg
|
||||||
def opcode = GamePacketOpcode.DismountVehicleMsg
|
def opcode = GamePacketOpcode.DismountVehicleMsg
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,10 @@ import shapeless.{::, HNil}
|
||||||
* (Write more some other time.)
|
* (Write more some other time.)
|
||||||
* @param object_guid the target object
|
* @param object_guid the target object
|
||||||
* @param code the action code
|
* @param code the action code
|
||||||
|
* 96, 97, 98, 99 - Makes the vehicle bounce slightly. Have seen this in packet captures after taking a vehicle through a warpgate
|
||||||
|
* 200, 201, 202, 203 - For aircraft - client shows "THe bailing mechanism failed! To fix the mechanism, land and repair the vehicle!"
|
||||||
|
* 224 - Sets vehicle or player to be black ops
|
||||||
|
* 228 - Reverts player from black ops
|
||||||
*/
|
*/
|
||||||
final case class GenericObjectActionMessage(object_guid : PlanetSideGUID,
|
final case class GenericObjectActionMessage(object_guid : PlanetSideGUID,
|
||||||
code : Int)
|
code : Int)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.packet.game
|
||||||
|
|
||||||
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
|
||||||
|
import scodec.Codec
|
||||||
|
import scodec.codecs._
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param player_guid The guid of the player sending the request to board another vehicle with a cargo vehicle
|
||||||
|
* @param vehicle_guid The guid of the vehicle for the requesting player
|
||||||
|
* @param target_vehicle The cargo vehicle guid e.g. Galaxy / Lodestar
|
||||||
|
* @param unk4
|
||||||
|
*/
|
||||||
|
final case class MountVehicleCargoMsg(player_guid : PlanetSideGUID, vehicle_guid: PlanetSideGUID, target_vehicle: PlanetSideGUID, unk4: Int)
|
||||||
|
extends PlanetSideGamePacket {
|
||||||
|
type Packet = MountVehicleCargoMsg
|
||||||
|
|
||||||
|
def opcode = GamePacketOpcode.MountVehicleCargoMsg
|
||||||
|
|
||||||
|
def encode = MountVehicleCargoMsg.encode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
object MountVehicleCargoMsg extends Marshallable[MountVehicleCargoMsg] {
|
||||||
|
implicit val codec : Codec[MountVehicleCargoMsg] = (
|
||||||
|
("unk1" | PlanetSideGUID.codec) ::
|
||||||
|
("unk2" | PlanetSideGUID.codec)::
|
||||||
|
("unk3" | PlanetSideGUID.codec) ::
|
||||||
|
("unk4" | uint8L)
|
||||||
|
).as[MountVehicleCargoMsg]
|
||||||
|
}
|
||||||
|
|
@ -137,6 +137,7 @@ import scodec.codecs._
|
||||||
* `22 - Toggles gunner and passenger mount points (1 = hides, 0 = reveals; this also locks their permissions)`<br>
|
* `22 - Toggles gunner and passenger mount points (1 = hides, 0 = reveals; this also locks their permissions)`<br>
|
||||||
* `54 - Vehicle EMP? Plays sound as if vehicle had been hit by EMP`<br>
|
* `54 - Vehicle EMP? Plays sound as if vehicle had been hit by EMP`<br>
|
||||||
* `68 - Vehicle shield health`<br>
|
* `68 - Vehicle shield health`<br>
|
||||||
|
* `79 - ???`<br>
|
||||||
* `80 - Damage vehicle (unknown value)`<br>
|
* `80 - Damage vehicle (unknown value)`<br>
|
||||||
* `81 - ???`<br>
|
* `81 - ???`<br>
|
||||||
* `113 - `Vehicle capacitor - e.g. Leviathan EMP charge`
|
* `113 - `Vehicle capacitor - e.g. Leviathan EMP charge`
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,19 @@ import scodec.codecs._
|
||||||
* @param lock_accelerator driver has no control over vehicle acceleration
|
* @param lock_accelerator driver has no control over vehicle acceleration
|
||||||
* @param lock_wheel driver has no control over vehicle turning
|
* @param lock_wheel driver has no control over vehicle turning
|
||||||
* @param reverse move in reverse
|
* @param reverse move in reverse
|
||||||
|
* 0 = forward
|
||||||
|
* 1 = reverse
|
||||||
* @param unk4 na;
|
* @param unk4 na;
|
||||||
* something to do with vehicle bailable speed
|
* something to do with vehicle bailable speed
|
||||||
* @param lock_vthrust pilot has no control over vertical thrust;
|
* @param lock_vthrust pilot has no control over vertical thrust;
|
||||||
* asserts a constant positive vertical thrust;
|
* asserts a constant positive vertical thrust;
|
||||||
* the only valid setting appears to be 1
|
* the only valid setting appears to be 1
|
||||||
* @param lock_strafe pilot has no control over strafing thrust;
|
* @param lock_strafe pilot has no control over strafing thrust;
|
||||||
* the only valid setting appears to be 1
|
* 0 = not locked
|
||||||
* @param forward_speed "something like speed"
|
* 1 = no strafing
|
||||||
|
* 2 = strafe left automatically
|
||||||
|
* 3 = strafe right automatically
|
||||||
|
* @param movement_speed "something like speed"
|
||||||
* @param unk8 na;
|
* @param unk8 na;
|
||||||
* set `lock_wheel` to `true` to expose this value
|
* set `lock_wheel` to `true` to expose this value
|
||||||
*/
|
*/
|
||||||
|
|
@ -50,7 +55,7 @@ final case class ServerVehicleOverrideMsg(lock_accelerator : Boolean,
|
||||||
unk4 : Boolean,
|
unk4 : Boolean,
|
||||||
lock_vthrust : Int,
|
lock_vthrust : Int,
|
||||||
lock_strafe : Int,
|
lock_strafe : Int,
|
||||||
forward_speed : Int,
|
movement_speed : Int,
|
||||||
unk8 : Option[Long]
|
unk8 : Option[Long]
|
||||||
) extends PlanetSideGamePacket {
|
) extends PlanetSideGamePacket {
|
||||||
type Packet = ServerVehicleOverrideMsg
|
type Packet = ServerVehicleOverrideMsg
|
||||||
|
|
@ -66,7 +71,7 @@ object ServerVehicleOverrideMsg extends Marshallable[ServerVehicleOverrideMsg] {
|
||||||
("unk4" | bool) ::
|
("unk4" | bool) ::
|
||||||
("lock_vthrust" | uint2L) ::
|
("lock_vthrust" | uint2L) ::
|
||||||
("lock_strafe" | uint2L) ::
|
("lock_strafe" | uint2L) ::
|
||||||
("forward_speed" | uintL(9)) ::
|
("movement_speed" | uintL(9)) ::
|
||||||
conditional(test, "unk8" | uint32L)
|
conditional(test, "unk8" | uint32L)
|
||||||
})
|
})
|
||||||
).as[ServerVehicleOverrideMsg]
|
).as[ServerVehicleOverrideMsg]
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import scodec.codecs._
|
||||||
* 15 for straight;
|
* 15 for straight;
|
||||||
* 0 for hard right;
|
* 0 for hard right;
|
||||||
* 30 for hard left
|
* 30 for hard left
|
||||||
* @param unk5 na
|
* @param unk5 na - Possibly a flag to indicate the vehicle is attached to something else e.g. is in a galaxy/lodestar cargo bay
|
||||||
* @param unk6 na
|
* @param unk6 na
|
||||||
* @see `PlacementData`
|
* @see `PlacementData`
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
15
common/src/main/scala/net/psforever/types/CargoStatus.scala
Normal file
15
common/src/main/scala/net/psforever/types/CargoStatus.scala
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.types
|
||||||
|
|
||||||
|
import net.psforever.packet.PacketHelpers
|
||||||
|
import scodec.codecs._
|
||||||
|
|
||||||
|
object CargoStatus extends Enumeration {
|
||||||
|
type Type = Value
|
||||||
|
|
||||||
|
val Empty = Value(0)
|
||||||
|
val InProgress = Value(1)
|
||||||
|
val Occupied = Value(3)
|
||||||
|
|
||||||
|
implicit val codec = PacketHelpers.createEnumerationCodec(this, uint4L)
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,8 @@ import net.psforever.objects.{PlanetSideGameObject, Player}
|
||||||
import net.psforever.objects.equipment.Equipment
|
import net.psforever.objects.equipment.Equipment
|
||||||
import net.psforever.objects.inventory.Container
|
import net.psforever.objects.inventory.Container
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game.{PlanetSideGUID, PlayerStateMessageUpstream}
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
|
import net.psforever.packet.game.{CargoMountPointStatusMessage, PlanetSideGUID, PlayerStateMessageUpstream}
|
||||||
import net.psforever.packet.game.objectcreate.{ConstructorData, ObjectCreateMessageParent}
|
import net.psforever.packet.game.objectcreate.{ConstructorData, ObjectCreateMessageParent}
|
||||||
import net.psforever.types.ExoSuitType
|
import net.psforever.types.ExoSuitType
|
||||||
|
|
||||||
|
|
@ -32,7 +33,10 @@ object AvatarAction {
|
||||||
final case class Reload(player_guid : PlanetSideGUID, weapon_guid : PlanetSideGUID) extends Action
|
final case class Reload(player_guid : PlanetSideGUID, weapon_guid : PlanetSideGUID) extends Action
|
||||||
final case class StowEquipment(player_guid : PlanetSideGUID, target_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Action
|
final case class StowEquipment(player_guid : PlanetSideGUID, target_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Action
|
||||||
final case class WeaponDryFire(player_guid : PlanetSideGUID, weapon_guid : PlanetSideGUID) extends Action
|
final case class WeaponDryFire(player_guid : PlanetSideGUID, weapon_guid : PlanetSideGUID) extends Action
|
||||||
// final case class PlayerStateShift(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
|
||||||
|
final case class SendResponse(player_guid: PlanetSideGUID, msg: PlanetSideGamePacket) extends Action
|
||||||
|
|
||||||
|
// final case class PlayerStateShift(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
||||||
// final case class DestroyDisplay(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
// final case class DestroyDisplay(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
||||||
// final case class HitHintReturn(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
// final case class HitHintReturn(killer : PlanetSideGUID, victim : PlanetSideGUID) extends Action
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package services.avatar
|
||||||
|
|
||||||
import net.psforever.objects.Player
|
import net.psforever.objects.Player
|
||||||
import net.psforever.objects.equipment.Equipment
|
import net.psforever.objects.equipment.Equipment
|
||||||
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID, PlayerStateMessageUpstream}
|
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID, PlayerStateMessageUpstream}
|
||||||
import net.psforever.packet.game.objectcreate.ConstructorData
|
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||||
import net.psforever.types.ExoSuitType
|
import net.psforever.types.ExoSuitType
|
||||||
|
|
@ -27,6 +28,8 @@ object AvatarResponse {
|
||||||
final case class Reload(weapon_guid : PlanetSideGUID) extends Response
|
final case class Reload(weapon_guid : PlanetSideGUID) extends Response
|
||||||
final case class StowEquipment(target_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Response
|
final case class StowEquipment(target_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Response
|
||||||
final case class WeaponDryFire(weapon_guid : PlanetSideGUID) extends Response
|
final case class WeaponDryFire(weapon_guid : PlanetSideGUID) extends Response
|
||||||
|
|
||||||
|
final case class SendResponse(msg: PlanetSideGamePacket) extends Response
|
||||||
// final case class PlayerStateShift(itemID : PlanetSideGUID) extends Response
|
// final case class PlayerStateShift(itemID : PlanetSideGUID) extends Response
|
||||||
// final case class DestroyDisplay(itemID : PlanetSideGUID) extends Response
|
// final case class DestroyDisplay(itemID : PlanetSideGUID) extends Response
|
||||||
// final case class HitHintReturn(itemID : PlanetSideGUID) extends Response
|
// final case class HitHintReturn(itemID : PlanetSideGUID) extends Response
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,10 @@ class AvatarService extends Actor {
|
||||||
AvatarEvents.publish(
|
AvatarEvents.publish(
|
||||||
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.WeaponDryFire(weapon_guid))
|
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.WeaponDryFire(weapon_guid))
|
||||||
)
|
)
|
||||||
|
case AvatarAction.SendResponse(player_guid, msg) =>
|
||||||
|
AvatarEvents.publish(
|
||||||
|
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.SendResponse(msg))
|
||||||
|
)
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,10 @@ package services.vehicle
|
||||||
import net.psforever.objects.{PlanetSideGameObject, Vehicle}
|
import net.psforever.objects.{PlanetSideGameObject, Vehicle}
|
||||||
import net.psforever.objects.equipment.Equipment
|
import net.psforever.objects.equipment.Equipment
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
import net.psforever.packet.game.objectcreate.ConstructorData
|
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||||
import net.psforever.types.{DriveState, Vector3, BailType}
|
import net.psforever.types.{BailType, DriveState, Vector3}
|
||||||
|
|
||||||
object VehicleAction {
|
object VehicleAction {
|
||||||
trait Action
|
trait Action
|
||||||
|
|
@ -25,6 +26,6 @@ object VehicleAction {
|
||||||
final case class UnloadVehicle(player_guid : PlanetSideGUID, continent : Zone, vehicle : Vehicle) extends Action
|
final case class UnloadVehicle(player_guid : PlanetSideGUID, continent : Zone, vehicle : Vehicle) extends Action
|
||||||
final case class UnstowEquipment(player_guid : PlanetSideGUID, item_guid : PlanetSideGUID) extends Action
|
final case class UnstowEquipment(player_guid : PlanetSideGUID, item_guid : PlanetSideGUID) extends Action
|
||||||
final case class VehicleState(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Action
|
final case class VehicleState(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Action
|
||||||
|
final case class SendResponse(player_guid: PlanetSideGUID, msg : PlanetSideGamePacket) extends Action
|
||||||
final case class UpdateAmsSpawnPoint(zone : Zone) extends Action
|
final case class UpdateAmsSpawnPoint(zone : Zone) extends Action
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ package services.vehicle
|
||||||
|
|
||||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||||
import net.psforever.objects.{PlanetSideGameObject, Vehicle}
|
import net.psforever.objects.{PlanetSideGameObject, Vehicle}
|
||||||
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.PlanetSideGUID
|
import net.psforever.packet.game.PlanetSideGUID
|
||||||
import net.psforever.packet.game.objectcreate.ConstructorData
|
import net.psforever.packet.game.objectcreate.ConstructorData
|
||||||
import net.psforever.types.{DriveState, Vector3, BailType}
|
import net.psforever.types.{BailType, DriveState, Vector3}
|
||||||
|
|
||||||
object VehicleResponse {
|
object VehicleResponse {
|
||||||
trait Response
|
trait Response
|
||||||
|
|
@ -29,6 +30,6 @@ object VehicleResponse {
|
||||||
final case class UnloadVehicle(vehicle_guid : PlanetSideGUID) extends Response
|
final case class UnloadVehicle(vehicle_guid : PlanetSideGUID) extends Response
|
||||||
final case class UnstowEquipment(item_guid : PlanetSideGUID) extends Response
|
final case class UnstowEquipment(item_guid : PlanetSideGUID) extends Response
|
||||||
final case class VehicleState(vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Response
|
final case class VehicleState(vehicle_guid : PlanetSideGUID, unk1 : Int, pos : Vector3, ang : Vector3, vel : Option[Vector3], unk2 : Option[Int], unk3 : Int, unk4 : Int, wheel_direction : Int, unk5 : Boolean, unk6 : Boolean) extends Response
|
||||||
|
final case class SendResponse(msg: PlanetSideGamePacket) extends Response
|
||||||
final case class UpdateAmsSpawnPoint(list : List[SpawnTube]) extends Response
|
final case class UpdateAmsSpawnPoint(list : List[SpawnTube]) extends Response
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,10 @@ class VehicleService extends Actor {
|
||||||
VehicleEvents.publish(
|
VehicleEvents.publish(
|
||||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.VehicleState(vehicle_guid, unk1, pos, ang, vel, unk2, unk3, unk4, wheel_direction, unk5, unk6))
|
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.VehicleState(vehicle_guid, unk1, pos, ang, vel, unk2, unk3, unk4, wheel_direction, unk5, unk6))
|
||||||
)
|
)
|
||||||
|
case VehicleAction.SendResponse(player_guid, msg) =>
|
||||||
|
VehicleEvents.publish(
|
||||||
|
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.SendResponse(msg))
|
||||||
|
)
|
||||||
|
|
||||||
//unlike other messages, just return to sender, don't publish
|
//unlike other messages, just return to sender, don't publish
|
||||||
case VehicleAction.UpdateAmsSpawnPoint(zone : Zone) =>
|
case VehicleAction.UpdateAmsSpawnPoint(zone : Zone) =>
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ import net.psforever.objects.serverobject.structures.{Building, StructureType, W
|
||||||
import net.psforever.objects.serverobject.terminals._
|
import net.psforever.objects.serverobject.terminals._
|
||||||
import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage
|
import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage
|
||||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||||
import net.psforever.objects.vehicles.{AccessPermissionGroup, Utility, VehicleLockState}
|
import net.psforever.objects.vehicles.{AccessPermissionGroup, Cargo, Utility, VehicleLockState}
|
||||||
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
||||||
import net.psforever.packet.game.objectcreate._
|
import net.psforever.packet.game.objectcreate._
|
||||||
import net.psforever.types._
|
import net.psforever.types._
|
||||||
|
|
@ -91,6 +91,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
var progressBarUpdate : Cancellable = DefaultCancellable.obj
|
var progressBarUpdate : Cancellable = DefaultCancellable.obj
|
||||||
var reviveTimer : Cancellable = DefaultCancellable.obj
|
var reviveTimer : Cancellable = DefaultCancellable.obj
|
||||||
var respawnTimer : Cancellable = DefaultCancellable.obj
|
var respawnTimer : Cancellable = DefaultCancellable.obj
|
||||||
|
var cargoMountTimer : Cancellable = DefaultCancellable.obj
|
||||||
|
var cargoDismountTimer : Cancellable = DefaultCancellable.obj
|
||||||
|
|
||||||
var antChargingTick : Cancellable = DefaultCancellable.obj
|
var antChargingTick : Cancellable = DefaultCancellable.obj
|
||||||
var antDischargingTick : Cancellable = DefaultCancellable.obj
|
var antDischargingTick : Cancellable = DefaultCancellable.obj
|
||||||
|
|
||||||
|
|
@ -250,9 +253,104 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case PokeClient() =>
|
case PokeClient() =>
|
||||||
sendResponse(KeepAliveMessage())
|
sendResponse(KeepAliveMessage())
|
||||||
|
|
||||||
|
case CheckCargoDismount(vehicle_guid, cargo_vehicle_guid, cargo_mountpoint, iteration) =>
|
||||||
|
val vehicle = continent.GUID(vehicle_guid.guid).get.asInstanceOf[Vehicle]
|
||||||
|
val cargo_vehicle = continent.GUID(cargo_vehicle_guid).get.asInstanceOf[Vehicle]
|
||||||
|
|
||||||
|
val distance = Vector3.Distance(vehicle.Position, cargo_vehicle.Position)
|
||||||
|
|
||||||
|
log.info(s"Dismount distance ${distance}")
|
||||||
|
if(distance > 15 || iteration > 20) {
|
||||||
|
// Vehicle has moved far enough away - close the cargo door
|
||||||
|
log.info("Vehicle is far enough away or disembark timed out - closing cargo door and returning full control to driver")
|
||||||
|
|
||||||
|
StartBundlingPackets()
|
||||||
|
|
||||||
|
// Return control of vehicle to driver
|
||||||
|
DriverVehicleControl(vehicle)
|
||||||
|
|
||||||
|
val cargoStatusMessage = CargoMountPointStatusMessage(cargo_vehicle_guid, PlanetSideGUID(0), PlanetSideGUID(0), vehicle_guid, cargo_mountpoint, CargoStatus.Empty, 0)
|
||||||
|
log.warn(cargoStatusMessage.toString)
|
||||||
|
// Do NOT send this packet back to the client directly. If you do and then send it again to all clients in the zone (including the client again)
|
||||||
|
// The client will get stuck in a state where the player cannot dismount as it thinks it is always trying to remount the cargo hold
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, cargoStatusMessage))
|
||||||
|
|
||||||
|
StopBundlingPackets()
|
||||||
|
|
||||||
|
cargoMountTimer.cancel()
|
||||||
|
cargoDismountTimer.cancel()
|
||||||
|
} else {
|
||||||
|
// Not far enough away - rescheduling check
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
cargoDismountTimer = context.system.scheduler.scheduleOnce(250 milliseconds, self, CheckCargoDismount(vehicle_guid, cargo_vehicle.GUID, cargo_mountpoint, iteration = iteration + 1))
|
||||||
|
}
|
||||||
|
case CheckCargoMounting(vehicle_guid, cargo_vehicle_guid, cargo_mountpoint, iteration) =>
|
||||||
|
val vehicle = continent.GUID(vehicle_guid.guid).get.asInstanceOf[Vehicle]
|
||||||
|
val cargo_vehicle = continent.GUID(cargo_vehicle_guid.guid).get.asInstanceOf[Vehicle]
|
||||||
|
|
||||||
|
val distance = Vector3.Distance(vehicle.Position, cargo_vehicle.Position)
|
||||||
|
log.warn(s"Mount distance ${distance}")
|
||||||
|
if(distance <= 8) {
|
||||||
|
// Vehicle is close enough that it should be within the cargo bay. Mount it.
|
||||||
|
log.info("Mounting vehicle cargo")
|
||||||
|
cargoMountTimer.cancel()
|
||||||
|
cargoDismountTimer.cancel()
|
||||||
|
|
||||||
|
val vehicle = continent.GUID(vehicle_guid).get.asInstanceOf[Vehicle]
|
||||||
|
|
||||||
|
StartBundlingPackets()
|
||||||
|
vehicleService ! VehicleServiceMessage(s"${vehicle.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargo_vehicle_guid, 0, cargo_vehicle.Health)))
|
||||||
|
vehicleService ! VehicleServiceMessage(s"${vehicle.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(cargo_vehicle_guid, 68, cargo_vehicle.Shields)))
|
||||||
|
|
||||||
|
val attachMessage = ObjectAttachMessage(cargo_vehicle_guid, vehicle_guid, cargo_mountpoint)
|
||||||
|
log.warn(attachMessage.toString)
|
||||||
|
sendResponse(attachMessage)
|
||||||
|
|
||||||
|
// This is required for when DismountVehicleCargoMsg is sent as the cargo_vehicle_guid isn't sent as a parameter
|
||||||
|
vehicle.MountedIn = cargo_vehicle_guid
|
||||||
|
cargo_vehicle.CargoHold(cargo_mountpoint).get.Occupant = vehicle
|
||||||
|
|
||||||
|
val orientation = if(vehicle.Definition == GlobalDefinitions.router) {
|
||||||
|
// mount router "sideways" in a lodestar
|
||||||
|
//todo: BFRs will likely also need this set
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
val cargoStatusMessage = CargoMountPointStatusMessage(cargo_vehicle_guid, vehicle_guid, vehicle_guid, PlanetSideGUID(0), cargo_mountpoint, CargoStatus.Occupied, orientation)
|
||||||
|
log.warn(cargoStatusMessage.toString)
|
||||||
|
sendResponse(cargoStatusMessage)
|
||||||
|
|
||||||
|
StopBundlingPackets()
|
||||||
|
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, attachMessage))
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, cargoStatusMessage))
|
||||||
|
} else if (distance > 25 || iteration >= 15) {
|
||||||
|
// Vehicle is too far away. Abort mounting.
|
||||||
|
log.info("Vehicle is too far away or didn't mount within allocated time. Aborting cargo mount.")
|
||||||
|
|
||||||
|
val cargoStatusMessage = CargoMountPointStatusMessage(cargo_vehicle_guid, PlanetSideGUID(0), PlanetSideGUID(0), vehicle_guid, cargo_mountpoint, CargoStatus.Empty, 0)
|
||||||
|
log.warn(cargoStatusMessage.toString)
|
||||||
|
// Do NOT send this packet back to the client directly. If you do and then send it again to all clients in the zone (including the client again)
|
||||||
|
// The client will get stuck in a state where the player cannot dismount as it thinks it is always trying to remount the cargo hold
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, cargoStatusMessage))
|
||||||
|
|
||||||
|
|
||||||
|
cargoMountTimer.cancel()
|
||||||
|
cargoDismountTimer.cancel()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Not close enough, far away enough or timeout not exceeded. Reschedule check
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
cargoMountTimer = context.system.scheduler.scheduleOnce(1 second, self, CheckCargoMounting(vehicle_guid, cargo_vehicle_guid, cargo_mountpoint, iteration = iteration + 1))
|
||||||
|
}
|
||||||
|
|
||||||
case AvatarServiceResponse(_, guid, reply) =>
|
case AvatarServiceResponse(_, guid, reply) =>
|
||||||
val tplayer_guid = if(player.HasGUID) { player.GUID} else { PlanetSideGUID(-1) }
|
val tplayer_guid = if(player.HasGUID) { player.GUID} else { PlanetSideGUID(-1) }
|
||||||
reply match {
|
reply match {
|
||||||
|
case AvatarResponse.SendResponse(msg) =>
|
||||||
|
sendResponse(msg)
|
||||||
case AvatarResponse.ArmorChanged(suit, subtype) =>
|
case AvatarResponse.ArmorChanged(suit, subtype) =>
|
||||||
if(tplayer_guid != guid) {
|
if(tplayer_guid != guid) {
|
||||||
sendResponse(ArmorChangedMessage(guid, suit, subtype))
|
sendResponse(ArmorChangedMessage(guid, suit, subtype))
|
||||||
|
|
@ -552,6 +650,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
player.Position = pos
|
player.Position = pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case VehicleResponse.SendResponse(msg) =>
|
||||||
|
sendResponse(msg)
|
||||||
|
|
||||||
case VehicleResponse.UpdateAmsSpawnPoint(list) =>
|
case VehicleResponse.UpdateAmsSpawnPoint(list) =>
|
||||||
if(player.isBackpack) {
|
if(player.isBackpack) {
|
||||||
|
|
@ -1725,6 +1825,97 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
clientKeepAlive.cancel
|
clientKeepAlive.cancel
|
||||||
clientKeepAlive = context.system.scheduler.schedule(0 seconds, 500 milliseconds, self, PokeClient())
|
clientKeepAlive = context.system.scheduler.schedule(0 seconds, 500 milliseconds, self, PokeClient())
|
||||||
|
|
||||||
|
case msg @ DismountVehicleCargoMsg(player_guid, vehicle_guid, bailed, requestedByPassenger, kicked) =>
|
||||||
|
log.info(msg.toString)
|
||||||
|
|
||||||
|
// Ignore dismount requests by passengers of the vehicle in the cargo bay for now
|
||||||
|
// todo: allow passengers of vehicle in cargo bay to bail, but not bail the cargo vehicle itself
|
||||||
|
if(!requestedByPassenger) {
|
||||||
|
StartBundlingPackets()
|
||||||
|
val vehicle = continent.GUID(vehicle_guid).get.asInstanceOf[Vehicle]
|
||||||
|
val cargo_vehicle = continent.GUID(vehicle.MountedIn.get).get.asInstanceOf[Vehicle]
|
||||||
|
// todo: change this to work with multiple cargo holds for potential custom vehicles in the future
|
||||||
|
val cargo_mountpoint = cargo_vehicle.Definition.Cargo.head._1
|
||||||
|
|
||||||
|
val cargoStatusMessage = CargoMountPointStatusMessage(cargo_vehicle.GUID, PlanetSideGUID(0), PlanetSideGUID(0), vehicle_guid, cargo_mountpoint, CargoStatus.InProgress, 0)
|
||||||
|
log.info(cargoStatusMessage.toString)
|
||||||
|
// Dismount vehicle on UI and disable "shield" effect on lodestar
|
||||||
|
sendResponse(cargoStatusMessage)
|
||||||
|
|
||||||
|
|
||||||
|
// Detach vehicle from cargo vehicle
|
||||||
|
val dismount_position = if (bailed || kicked) {
|
||||||
|
// If we're bailing drop the vehicle below the cargo vehicle
|
||||||
|
//todo: once the server has a concept of height from the floor we should probably ensure vehicles aren't dropped below the world
|
||||||
|
Vector3(cargo_vehicle.Position.x, cargo_vehicle.Position.y, cargo_vehicle.Position.z - 1f)
|
||||||
|
} else if (cargo_vehicle.Definition == GlobalDefinitions.dropship) {
|
||||||
|
// As the galaxy cargo bay is offset backwards from the center of the vehicle (unlike the lodestar) we need to set the position backwards slightly
|
||||||
|
Vector3(cargo_vehicle.Position.x, cargo_vehicle.Position.y - 7f, cargo_vehicle.Position.z + 2f)
|
||||||
|
} else {
|
||||||
|
Vector3(cargo_vehicle.Position.x, cargo_vehicle.Position.y, cargo_vehicle.Position.z + 2f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a flag if the vehicle should mount/dismount sideways
|
||||||
|
//todo: BFRs will likely also need this set
|
||||||
|
val sideways = vehicle.Definition == GlobalDefinitions.router
|
||||||
|
|
||||||
|
val rotation = if(sideways) {
|
||||||
|
// dismount router "sideways" in a lodestar
|
||||||
|
cargo_vehicle.Orientation.z - 90f
|
||||||
|
} else {
|
||||||
|
cargo_vehicle.Orientation.z
|
||||||
|
}
|
||||||
|
|
||||||
|
val detachMessage = ObjectDetachMessage(cargo_vehicle.GUID, vehicle_guid, dismount_position, cargo_vehicle.Orientation.x, cargo_vehicle.Orientation.y, rotation)
|
||||||
|
log.info(detachMessage.toString)
|
||||||
|
sendResponse(detachMessage)
|
||||||
|
|
||||||
|
// Update display to show current vehicle health & shields correctly
|
||||||
|
log.warn(s"vehicle health: ${vehicle.Health} shields: ${vehicle.Shields}")
|
||||||
|
vehicleService ! VehicleServiceMessage(s"${vehicle.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(vehicle_guid, 0, vehicle.Health)))
|
||||||
|
vehicleService ! VehicleServiceMessage(s"${vehicle.Actor}", VehicleAction.SendResponse(PlanetSideGUID(0), PlanetsideAttributeMessage(vehicle_guid, 68, vehicle.Shields)))
|
||||||
|
|
||||||
|
vehicle.MountedIn = None
|
||||||
|
cargo_vehicle.CargoHold(cargo_mountpoint).get.Occupant = None
|
||||||
|
|
||||||
|
if (!bailed) {
|
||||||
|
// Automatically drive the vehicle backwards out of the cargo bay
|
||||||
|
if (!sideways) {
|
||||||
|
ServerVehicleLockReverse()
|
||||||
|
} else {
|
||||||
|
ServerVehicleLockStrafeLeft()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//todo: proper vehicle bailing. It works currently but when collision damage is implemented the vehicle will take damage if not in a bail state. Need to confirm how this is done with further research
|
||||||
|
}
|
||||||
|
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
// Start a timer to check every second if the vehicle has moved far enough away to be considered dismounted, and then close the cargo door
|
||||||
|
cargoDismountTimer = context.system.scheduler.scheduleOnce(250 milliseconds, self, CheckCargoDismount(vehicle_guid, cargo_vehicle.GUID, cargo_mountpoint, iteration = 0))
|
||||||
|
|
||||||
|
StopBundlingPackets()
|
||||||
|
|
||||||
|
// Sync to other clients
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, cargoStatusMessage))
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, detachMessage))
|
||||||
|
}
|
||||||
|
case msg @ MountVehicleCargoMsg(player_guid, vehicle_guid, cargo_vehicle_guid, unk4) =>
|
||||||
|
log.info(msg.toString)
|
||||||
|
|
||||||
|
val cargo_vehicle = continent.GUID(cargo_vehicle_guid).get.asInstanceOf[Vehicle]
|
||||||
|
val cargo_mountpoint = cargo_vehicle.Definition.Cargo.head._1
|
||||||
|
|
||||||
|
// Begin the mount process - open the cargo door
|
||||||
|
val reply = CargoMountPointStatusMessage(cargo_vehicle_guid, PlanetSideGUID(0), vehicle_guid, PlanetSideGUID(0), cargo_mountpoint, CargoStatus.InProgress, 0)
|
||||||
|
log.warn(reply.toString)
|
||||||
|
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player.GUID, reply))
|
||||||
|
sendResponse(reply)
|
||||||
|
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
// Start timer to check every second if the vehicle is close enough to mount, or far enough away to cancel the mounting
|
||||||
|
cargoMountTimer = context.system.scheduler.scheduleOnce(1 second, self, CheckCargoMounting(vehicle_guid, cargo_vehicle_guid, cargo_mountpoint, iteration = 0))
|
||||||
case msg @ CharacterCreateRequestMessage(name, head, voice, gender, empire) =>
|
case msg @ CharacterCreateRequestMessage(name, head, voice, gender, empire) =>
|
||||||
log.info("Handling " + msg)
|
log.info("Handling " + msg)
|
||||||
sendResponse(ActionResultMessage.Pass)
|
sendResponse(ActionResultMessage.Pass)
|
||||||
|
|
@ -1810,6 +2001,24 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
})
|
})
|
||||||
ReloadVehicleAccessPermissions(vehicle)
|
ReloadVehicleAccessPermissions(vehicle)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Loop over vehicles again to add cargohold occupants after all vehicles have been created on the local client
|
||||||
|
continent.Vehicles.foreach(vehicle => {
|
||||||
|
vehicle.CargoHolds.foreach({ case (cargo_num, cargo) => {
|
||||||
|
cargo.Occupant match {
|
||||||
|
case Some(cargo_vehicle) =>
|
||||||
|
if(cargo_vehicle.HasGUID) {
|
||||||
|
StartBundlingPackets()
|
||||||
|
sendResponse(ObjectAttachMessage(cargo_vehicle.GUID, vehicle.GUID, cargo_num))
|
||||||
|
//todo: attaching the vehicle seems to work, but setting the mount point status doesn't?
|
||||||
|
sendResponse(CargoMountPointStatusMessage(cargo_vehicle.GUID, vehicle.GUID, vehicle.GUID, PlanetSideGUID(0), cargo_num, CargoStatus.Occupied, 0))
|
||||||
|
StopBundlingPackets()
|
||||||
|
}
|
||||||
|
case None => ; // No vehicle in cargo
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
})
|
||||||
|
|
||||||
//implant terminals
|
//implant terminals
|
||||||
continent.Map.TerminalToInterface.foreach({ case ((terminal_guid, interface_guid)) =>
|
continent.Map.TerminalToInterface.foreach({ case ((terminal_guid, interface_guid)) =>
|
||||||
val parent_guid = PlanetSideGUID(terminal_guid)
|
val parent_guid = PlanetSideGUID(terminal_guid)
|
||||||
|
|
@ -2994,6 +3203,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
// Deconstruct the vehicle if the driver has bailed out and the vehicle is capable of flight
|
// Deconstruct the vehicle if the driver has bailed out and the vehicle is capable of flight
|
||||||
//todo: implement auto landing procedure if the pilot bails but passengers are still present instead of deconstructing the vehicle
|
//todo: implement auto landing procedure if the pilot bails but passengers are still present instead of deconstructing the vehicle
|
||||||
//todo: continue flight path until aircraft crashes if no passengers present (or no passenger seats), then deconstruct.
|
//todo: continue flight path until aircraft crashes if no passengers present (or no passenger seats), then deconstruct.
|
||||||
|
//todo: kick cargo passengers out. To be added after PR #216 is merged
|
||||||
if(bailType == BailType.Bailed && seat_num == 0 && GlobalDefinitions.isFlightVehicle(obj.asInstanceOf[Vehicle].Definition)) {
|
if(bailType == BailType.Bailed && seat_num == 0 && GlobalDefinitions.isFlightVehicle(obj.asInstanceOf[Vehicle].Definition)) {
|
||||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(obj, continent, Some(0 seconds))) // Immediately deconstruct vehicle
|
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(obj, continent, Some(0 seconds))) // Immediately deconstruct vehicle
|
||||||
}
|
}
|
||||||
|
|
@ -3076,16 +3286,34 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.SeatPermissions(player.GUID, vehicle.GUID, attribute_type, attribute_value))
|
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.SeatPermissions(player.GUID, vehicle.GUID, attribute_type, attribute_value))
|
||||||
//kick players who should not be seated in the vehicle due to permission changes
|
//kick players who should not be seated in the vehicle due to permission changes
|
||||||
if(allow == VehicleLockState.Locked) { //TODO only important permission atm
|
if(allow == VehicleLockState.Locked) { //TODO only important permission atm
|
||||||
vehicle.Seats.foreach({ case (seat_num, seat) =>
|
vehicle.Definition.MountPoints.values.foreach(mountpoint_num => {
|
||||||
|
vehicle.Seat(mountpoint_num) match {
|
||||||
|
case Some(seat) =>
|
||||||
seat.Occupant match {
|
seat.Occupant match {
|
||||||
case Some(tplayer) =>
|
case Some(tplayer) =>
|
||||||
if(vehicle.SeatPermissionGroup(seat_num).contains(group) && tplayer != player) { //can not kick self
|
if(vehicle.SeatPermissionGroup(mountpoint_num).contains(group) && tplayer != player) { //can not kick self
|
||||||
seat.Occupant = None
|
seat.Occupant = None
|
||||||
tplayer.VehicleSeated = None
|
tplayer.VehicleSeated = None
|
||||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(tplayer.GUID, 4, false, object_guid))
|
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(tplayer.GUID, 4, false, object_guid))
|
||||||
}
|
}
|
||||||
case None => ;
|
case None => ; // No player seated
|
||||||
|
}
|
||||||
|
case None => ; // Not a seat mounting point
|
||||||
}
|
}
|
||||||
|
vehicle.CargoHold(mountpoint_num) match {
|
||||||
|
case Some(cargo) =>
|
||||||
|
cargo.Occupant match {
|
||||||
|
case Some(vehicle) =>
|
||||||
|
if(vehicle.SeatPermissionGroup(mountpoint_num).contains(group)) {
|
||||||
|
//todo: this probably doesn't work for passengers within the cargo vehicle
|
||||||
|
// Instruct client to start bail dismount procedure
|
||||||
|
self ! DismountVehicleCargoMsg(player.GUID, vehicle.GUID, true, false, false)
|
||||||
|
}
|
||||||
|
case None => ; // No vehicle in cargo
|
||||||
|
}
|
||||||
|
case None => ; // Not a cargo mounting point
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case None => ;
|
case None => ;
|
||||||
|
|
@ -3127,6 +3355,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
case default => log.error(s"Unhandled GamePacket $pkt")
|
case default => log.error(s"Unhandled GamePacket $pkt")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate over a group of `EquipmentSlot`s, some of which may be occupied with an item.
|
* Iterate over a group of `EquipmentSlot`s, some of which may be occupied with an item.
|
||||||
* Remove any encountered items and add them to an output `List`.
|
* Remove any encountered items and add them to an output `List`.
|
||||||
|
|
@ -4922,6 +5151,36 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
||||||
tplayer.Armor == tplayer.MaxArmor
|
tplayer.Armor == tplayer.MaxArmor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is applied to vehicles that are leaving a cargo vehicle's cargo hold to auto reverse them out
|
||||||
|
* Lock all applicable controls of the current vehicle
|
||||||
|
* Set the vehicle to move in reverse
|
||||||
|
*/
|
||||||
|
def ServerVehicleLockReverse() : Unit = {
|
||||||
|
controlled = Some(0)
|
||||||
|
sendResponse(ServerVehicleOverrideMsg(lock_accelerator = true, lock_wheel = true, reverse = true, unk4 = true, lock_vthrust = 0, lock_strafe = 1, movement_speed = 2, unk8 = Some(0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is applied to vehicles that are leaving a cargo vehicle's cargo hold to strafe right out of the cargo hold for vehicles that are mounted sideways e.g. router/BFR
|
||||||
|
* Lock all applicable controls of the current vehicle
|
||||||
|
* Set the vehicle to strafe right
|
||||||
|
*/
|
||||||
|
def ServerVehicleLockStrafeRight() : Unit = {
|
||||||
|
controlled = Some(0)
|
||||||
|
sendResponse(ServerVehicleOverrideMsg(lock_accelerator = true, lock_wheel = true, reverse = false, unk4 = true, lock_vthrust = 0, lock_strafe = 3, movement_speed = 0, unk8 = Some(0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is applied to vehicles that are leaving a cargo vehicle's cargo hold to strafe left out of the cargo hold for vehicles that are mounted sideways e.g. router/BFR
|
||||||
|
* Lock all applicable controls of the current vehicle
|
||||||
|
* Set the vehicle to strafe left
|
||||||
|
*/
|
||||||
|
def ServerVehicleLockStrafeLeft() : Unit = {
|
||||||
|
controlled = Some(0)
|
||||||
|
sendResponse(ServerVehicleOverrideMsg(lock_accelerator = true, lock_wheel = true, reverse = false, unk4 = true, lock_vthrust = 0, lock_strafe = 2, movement_speed = 0, unk8 = Some(0)))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock all applicable controls of the current vehicle.
|
* Lock all applicable controls of the current vehicle.
|
||||||
* This includes forward motion, turning, and, if applicable, strafing.
|
* This includes forward motion, turning, and, if applicable, strafing.
|
||||||
|
|
@ -5123,6 +5382,9 @@ object WorldSessionActor {
|
||||||
private final case class VehicleLoaded(vehicle : Vehicle)
|
private final case class VehicleLoaded(vehicle : Vehicle)
|
||||||
private final case class DelayedProximityUnitStop(unit : Terminal with ProximityUnit)
|
private final case class DelayedProximityUnitStop(unit : Terminal with ProximityUnit)
|
||||||
private final case class UnregisterCorpseOnVehicleDisembark(corpse : Player)
|
private final case class UnregisterCorpseOnVehicleDisembark(corpse : Player)
|
||||||
|
private final case class CheckCargoMounting(vehicle_guid : PlanetSideGUID, cargo_vehicle_guid: PlanetSideGUID, cargo_mountpoint: Int, iteration: Int)
|
||||||
|
private final case class CheckCargoDismount(vehicle_guid : PlanetSideGUID, cargo_vehicle_guid: PlanetSideGUID, cargo_mountpoint: Int, iteration: Int)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A message that indicates the user is using a remote electronics kit to hack some server object.
|
* A message that indicates the user is using a remote electronics kit to hack some server object.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue