mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
Cargo Bail (#258)
* deconstructing a vehicle that has cargo will eject the cargo before despawning the vehicle * cargo that dismounts without a driver is scheduled for deconstruction; any player that disconnects while in a vehicle that is flying has the vehicle scheduled for immediate deconstruction instead of the standard deconstruction time * modified routine for disowning vehicles outside of the conventional 'driver is owner' system * standardized player-driven ownership fields; adjusted how vehicles transfer and announce ownership on zone join events (SetCurrentAvatar) * stop /zone and /warp if in a cargo vehicle (even if driver) * fix for landed-dismount cargo logic not starting distance checking loop * concatenated Owner and OwnerName assignment to a singular object method, and the vehicle use of assignment to a singular WSA function
This commit is contained in:
parent
fca14e6b1b
commit
a467a79c71
|
|
@ -0,0 +1,65 @@
|
|||
// Copyright (c) 2019 PSForever
|
||||
package net.psforever.objects
|
||||
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
|
||||
trait OwnableByPlayer {
|
||||
private var owner : Option[PlanetSideGUID] = None
|
||||
private var ownerName : Option[String] = None
|
||||
|
||||
def Owner : Option[PlanetSideGUID] = owner
|
||||
|
||||
def Owner_=(owner : PlanetSideGUID) : Option[PlanetSideGUID] = Owner_=(Some(owner))
|
||||
|
||||
def Owner_=(owner : Player) : Option[PlanetSideGUID] = Owner_=(Some(owner.GUID))
|
||||
|
||||
def Owner_=(owner : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
owner match {
|
||||
case Some(_) =>
|
||||
this.owner = owner
|
||||
case None =>
|
||||
this.owner = None
|
||||
}
|
||||
Owner
|
||||
}
|
||||
|
||||
def OwnerName : Option[String] = ownerName
|
||||
|
||||
def OwnerName_=(owner : String) : Option[String] = OwnerName_=(Some(owner))
|
||||
|
||||
def OwnerName_=(owner : Player) : Option[String] = OwnerName_=(Some(owner.Name))
|
||||
|
||||
def OwnerName_=(owner : Option[String]) : Option[String] = {
|
||||
owner match {
|
||||
case Some(_) =>
|
||||
ownerName = owner
|
||||
case None =>
|
||||
ownerName = None
|
||||
}
|
||||
OwnerName
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param player na
|
||||
* @return na
|
||||
*/
|
||||
def AssignOwnership(player : Player) : OwnableByPlayer = AssignOwnership(Some(player))
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param playerOpt na
|
||||
* @return na
|
||||
*/
|
||||
def AssignOwnership(playerOpt : Option[Player]) : OwnableByPlayer = {
|
||||
playerOpt match {
|
||||
case Some(player) =>
|
||||
Owner = player
|
||||
OwnerName = player
|
||||
case None =>
|
||||
Owner = None
|
||||
OwnerName = None
|
||||
}
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
@ -72,10 +72,10 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
|||
with MountedWeapons
|
||||
with Deployment
|
||||
with Vitality
|
||||
with OwnableByPlayer
|
||||
with StandardResistanceProfile
|
||||
with Container {
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.TR
|
||||
private var owner : Option[PlanetSideGUID] = None
|
||||
private var health : Int = 1
|
||||
private var shields : Int = 0
|
||||
private var decal : Int = 0
|
||||
|
|
@ -139,26 +139,6 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
|||
MountedIn
|
||||
}
|
||||
|
||||
def Owner : Option[PlanetSideGUID] = {
|
||||
this.owner
|
||||
}
|
||||
|
||||
def Owner_=(owner : PlanetSideGUID) : Option[PlanetSideGUID] = Owner_=(Some(owner))
|
||||
|
||||
def Owner_=(owner : Player) : Option[PlanetSideGUID] = Owner_=(Some(owner.GUID))
|
||||
|
||||
def Owner_=(owner : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
owner match {
|
||||
case Some(_) =>
|
||||
if(Definition.CanBeOwned) {
|
||||
this.owner = owner
|
||||
}
|
||||
case None =>
|
||||
this.owner = None
|
||||
}
|
||||
Owner
|
||||
}
|
||||
|
||||
def Health : Int = {
|
||||
health
|
||||
}
|
||||
|
|
@ -499,7 +479,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
|
|||
if(trunkAccess.isEmpty || trunkAccess.contains(player.GUID)) {
|
||||
groupPermissions(3) match {
|
||||
case VehicleLockState.Locked => //only the owner
|
||||
owner.isEmpty || (owner.isDefined && player.GUID == owner.get)
|
||||
Owner.isEmpty || (Owner.isDefined && player.GUID == Owner.get)
|
||||
case VehicleLockState.Group => //anyone in the owner's squad or platoon
|
||||
faction == player.Faction //TODO this is not correct
|
||||
case VehicleLockState.Empire => //anyone of the owner's faction
|
||||
|
|
|
|||
|
|
@ -9,12 +9,11 @@ import net.psforever.packet.game.{DeployableIcon, PlanetSideGUID}
|
|||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
trait Deployable extends FactionAffinity
|
||||
with Vitality {
|
||||
with Vitality
|
||||
with OwnableByPlayer {
|
||||
this : PlanetSideGameObject =>
|
||||
private var health : Int = 1
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
private var owner : Option[PlanetSideGUID] = None
|
||||
private var ownerName : Option[String] = None
|
||||
|
||||
def Health : Int = health
|
||||
|
||||
|
|
@ -32,38 +31,6 @@ trait Deployable extends FactionAffinity
|
|||
Faction
|
||||
}
|
||||
|
||||
def Owner : Option[PlanetSideGUID] = owner
|
||||
|
||||
def Owner_=(owner : PlanetSideGUID) : Option[PlanetSideGUID] = Owner_=(Some(owner))
|
||||
|
||||
def Owner_=(owner : Player) : Option[PlanetSideGUID] = Owner_=(Some(owner.GUID))
|
||||
|
||||
def Owner_=(owner : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
owner match {
|
||||
case Some(_) =>
|
||||
this.owner = owner
|
||||
case None =>
|
||||
this.owner = None
|
||||
}
|
||||
Owner
|
||||
}
|
||||
|
||||
def OwnerName : Option[String] = ownerName
|
||||
|
||||
def OwnerName_=(owner : String) : Option[String] = OwnerName_=(Some(owner))
|
||||
|
||||
def OwnerName_=(owner : Player) : Option[String] = OwnerName_=(Some(owner.Name))
|
||||
|
||||
def OwnerName_=(owner : Option[String]) : Option[String] = {
|
||||
owner match {
|
||||
case Some(_) =>
|
||||
ownerName = owner
|
||||
case None =>
|
||||
ownerName = None
|
||||
}
|
||||
OwnerName
|
||||
}
|
||||
|
||||
def DamageModel : DamageResistanceModel = Definition.asInstanceOf[DamageResistanceModel]
|
||||
|
||||
def Definition : ObjectDefinition with BaseDeployableDefinition
|
||||
|
|
|
|||
|
|
@ -155,11 +155,11 @@ import scodec.codecs._
|
|||
* `81 - ???`<br>
|
||||
* `113 - Vehicle capacitor - e.g. Leviathan EMP charge`
|
||||
*
|
||||
* @param player_guid the player
|
||||
* @param attribute_type na
|
||||
* @param attribute_value na
|
||||
* @param guid the object
|
||||
* @param attribute_type the field
|
||||
* @param attribute_value the value
|
||||
*/
|
||||
final case class PlanetsideAttributeMessage(player_guid : PlanetSideGUID,
|
||||
final case class PlanetsideAttributeMessage(guid : PlanetSideGUID,
|
||||
attribute_type : Int,
|
||||
attribute_value : Long)
|
||||
extends PlanetSideGamePacket {
|
||||
|
|
@ -169,12 +169,16 @@ final case class PlanetsideAttributeMessage(player_guid : PlanetSideGUID,
|
|||
}
|
||||
|
||||
object PlanetsideAttributeMessage extends Marshallable[PlanetsideAttributeMessage] {
|
||||
def apply(player_guid : PlanetSideGUID, attribute_type : Int, attribute_value : Int) : PlanetsideAttributeMessage = {
|
||||
PlanetsideAttributeMessage(player_guid, attribute_type, attribute_value.toLong)
|
||||
def apply(guid : PlanetSideGUID, attribute_type : Int, attribute_value : Int) : PlanetsideAttributeMessage = {
|
||||
PlanetsideAttributeMessage(guid, attribute_type, attribute_value.toLong)
|
||||
}
|
||||
|
||||
def apply(guid : PlanetSideGUID, attribute_type : Int, attribute_value : PlanetSideGUID) : PlanetsideAttributeMessage = {
|
||||
PlanetsideAttributeMessage(guid, attribute_type, attribute_value.guid)
|
||||
}
|
||||
|
||||
implicit val codec : Codec[PlanetsideAttributeMessage] = (
|
||||
("player_guid" | PlanetSideGUID.codec) ::
|
||||
("guid" | PlanetSideGUID.codec) ::
|
||||
("attribute_type" | uint8L) ::
|
||||
("attribute_value" | uint32L)
|
||||
).as[PlanetsideAttributeMessage]
|
||||
|
|
|
|||
|
|
@ -36,5 +36,6 @@ object VehicleAction {
|
|||
final case class TransferPassengerChannel(player_guid : PlanetSideGUID, temp_channel : String, new_channel : String, vehicle : Vehicle) extends Action
|
||||
final case class TransferPassenger(player_guid : PlanetSideGUID, temp_channel : String, vehicle : Vehicle, vehicle_to_delete : PlanetSideGUID) extends Action
|
||||
|
||||
final case class KickCargo(player_guid : PlanetSideGUID, cargo : Vehicle, speed : Int) extends Action
|
||||
final case class ForceDismountVehicleCargo(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, bailed : Boolean, requestedByPassenger : Boolean, kicked : Boolean) extends Action
|
||||
final case class KickCargo(player_guid : PlanetSideGUID, cargo : Vehicle, speed : Int, delay : Long) extends Action
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,5 +40,6 @@ object VehicleResponse {
|
|||
final case class TransferPassengerChannel(old_channel : String, temp_channel : String, vehicle : Vehicle) extends Response
|
||||
final case class TransferPassenger(temp_channel : String, vehicle : Vehicle, vehicle_to_delete : PlanetSideGUID) extends Response
|
||||
|
||||
final case class KickCargo(cargo : Vehicle, speed : Int) extends Response
|
||||
final case class ForceDismountVehicleCargo(vehicle_guid : PlanetSideGUID, bailed : Boolean, requestedByPassenger : Boolean, kicked : Boolean) extends Response
|
||||
final case class KickCargo(cargo : Vehicle, speed : Int, delay : Long) extends Response
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,9 +140,13 @@ class VehicleService extends Actor {
|
|||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.TransferPassenger(temp_channel, vehicle, vehicle_to_delete))
|
||||
)
|
||||
|
||||
case VehicleAction.KickCargo(player_guid, cargo, speed) =>
|
||||
case VehicleAction.ForceDismountVehicleCargo(player_guid, vehicle_guid, bailed, requestedByPassenger, kicked) =>
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.KickCargo(cargo, speed))
|
||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.ForceDismountVehicleCargo(vehicle_guid, bailed, requestedByPassenger, kicked))
|
||||
)
|
||||
case VehicleAction.KickCargo(player_guid, cargo, speed, delay) =>
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.KickCargo(cargo, speed, delay))
|
||||
)
|
||||
case _ => ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package services.vehicle.support
|
|||
import net.psforever.objects.Vehicle
|
||||
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.PlanetSideGUID
|
||||
import net.psforever.types.DriveState
|
||||
import services.{RemoverActor, Service}
|
||||
import services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
|
@ -26,6 +27,21 @@ class VehicleRemover extends RemoverActor {
|
|||
val vehicleGUID = vehicle.GUID
|
||||
val zoneId = entry.zone.Id
|
||||
vehicle.Actor ! Vehicle.PrepareForDeletion
|
||||
//escape being someone else's cargo
|
||||
(vehicle.MountedIn match {
|
||||
case Some(carrierGUID) =>
|
||||
entry.zone.Vehicles.find(v => v.GUID == carrierGUID)
|
||||
case None =>
|
||||
None
|
||||
}) match {
|
||||
case Some(carrier : Vehicle) =>
|
||||
val driverName = carrier.Seats(0).Occupant match {
|
||||
case Some(driver) => driver.Name
|
||||
case _ => zoneId
|
||||
}
|
||||
context.parent ! VehicleServiceMessage(s"$driverName", VehicleAction.ForceDismountVehicleCargo(PlanetSideGUID(0), vehicleGUID, true, false, false))
|
||||
case _ => ;
|
||||
}
|
||||
//kick out all passengers
|
||||
vehicle.Seats.values.foreach(seat => {
|
||||
seat.Occupant match {
|
||||
|
|
@ -37,6 +53,12 @@ class VehicleRemover extends RemoverActor {
|
|||
}
|
||||
case None => ;
|
||||
}
|
||||
//abandon all cargo
|
||||
vehicle.CargoHolds.values
|
||||
.collect { case hold if hold.isOccupied =>
|
||||
val cargo = hold.Occupant.get
|
||||
context.parent ! VehicleServiceMessage(zoneId, VehicleAction.ForceDismountVehicleCargo(PlanetSideGUID(0), cargo.GUID, true, false, false))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ import services.local.support.{HackCaptureActor, RouterTelepadActivation}
|
|||
import services.support.SupportActor
|
||||
|
||||
class WorldSessionActor extends Actor with MDCContextAware {
|
||||
|
||||
import WorldSessionActor._
|
||||
|
||||
private[this] val log = org.log4s.getLogger
|
||||
|
|
@ -132,7 +131,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
*/
|
||||
implicit def boolToInt(b : Boolean) : Int = if(b) 1 else 0
|
||||
|
||||
override def postStop() = {
|
||||
override def postStop() : Unit = {
|
||||
//TODO normally, player avatar persists a minute or so after disconnect; we are subject to the SessionReaper
|
||||
clientKeepAlive.cancel
|
||||
reviveTimer.cancel
|
||||
|
|
@ -160,21 +159,22 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
if(player.isAlive) {
|
||||
//actually being alive or manually deconstructing
|
||||
player.Position = Vector3.Zero
|
||||
if(player.VehicleSeated.nonEmpty) {
|
||||
//quickly and briefly kill player to avoid disembark animation
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player_guid, 0, 0))
|
||||
DismountVehicleOnLogOut()
|
||||
DisownVehicle()
|
||||
//if seated, dismount
|
||||
player.VehicleSeated match {
|
||||
case Some(_) =>
|
||||
//quickly and briefly kill player to avoid disembark animation?
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player_guid, 0, 0))
|
||||
DismountVehicleOnLogOut()
|
||||
case _ => ;
|
||||
}
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, player_guid))
|
||||
taskResolver ! GUIDTask.UnregisterAvatar(player)(continent.GUID)
|
||||
//TODO normally, the actual player avatar persists a minute or so after the user disconnects
|
||||
}
|
||||
else if(continent.LivePlayers.contains(player) && !continent.Corpses.contains(player)) {
|
||||
//player disconnected while waiting for a revive
|
||||
//player disconnected while waiting for a revive, maybe
|
||||
//similar to handling ReleaseAvatarRequestMessage
|
||||
player.Release
|
||||
DisownVehicle()
|
||||
player.VehicleSeated match {
|
||||
case None =>
|
||||
FriskCorpse(player) //TODO eliminate dead letters
|
||||
|
|
@ -191,7 +191,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
taskResolver ! GUIDTask.UnregisterAvatar(player)(continent.GUID)
|
||||
}
|
||||
|
||||
case Some(vehicle_guid) =>
|
||||
case Some(_) =>
|
||||
val player_guid = player.GUID
|
||||
player.Position = Vector3.Zero //save character before doing this
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player_guid, player_guid))
|
||||
|
|
@ -199,7 +199,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
DismountVehicleOnLogOut()
|
||||
}
|
||||
}
|
||||
DisownVehicle()
|
||||
//disassociate and start the deconstruction timer for any currently owned vehicle
|
||||
SpecialCaseDisownVehicle()
|
||||
continent.Population ! Zone.Population.Leave(avatar)
|
||||
}
|
||||
}
|
||||
|
|
@ -221,6 +222,29 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a vehicle is owned by a character, disassociate the vehicle, then schedule it for deconstruction.
|
||||
* @see `DisownVehicle()`
|
||||
* @return the vehicle previously owned, if any
|
||||
*/
|
||||
def SpecialCaseDisownVehicle() : Option[Vehicle] = {
|
||||
DisownVehicle() match {
|
||||
case out @ Some(vehicle) =>
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(vehicle), continent))
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent,
|
||||
if(vehicle.Flying) {
|
||||
Some(0 seconds) //immediate deconstruction
|
||||
}
|
||||
else {
|
||||
vehicle.Definition.DeconstructionTime //normal deconstruction
|
||||
}
|
||||
))
|
||||
out
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
def receive = Initializing
|
||||
|
||||
def Initializing : Receive = {
|
||||
|
|
@ -373,7 +397,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectHeld(player.GUID, player.LastDrawnSlot))
|
||||
}
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 22, 1L)) //mount points off
|
||||
sendResponse(PlanetsideAttributeMessage(vehicle_guid, 21, player.GUID.guid)) //ownership
|
||||
sendResponse(PlanetsideAttributeMessage(player.GUID, 21, vehicle_guid)) //ownership
|
||||
|
||||
case VehicleSpawnPad.PlayerSeatedInVehicle(vehicle, pad) =>
|
||||
val vehicle_guid = vehicle.GUID
|
||||
|
|
@ -540,8 +564,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Some(obj : BoomerDeployable) =>
|
||||
val guid = obj.GUID
|
||||
val factionOnContinentChannel = s"${continent.Id}/${player.Faction}"
|
||||
obj.Owner = None
|
||||
obj.OwnerName = None
|
||||
obj.AssignOwnership(None)
|
||||
avatar.Deployables.Remove(obj)
|
||||
UpdateDeployableUIElements(avatar.Deployables.UpdateUIElement(obj.Definition.Item))
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, continent))
|
||||
|
|
@ -580,8 +603,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val playerGUID = player.GUID
|
||||
val faction = player.Faction
|
||||
val factionOnContinentChannel = s"${continent.Id}/${faction}"
|
||||
obj.Owner = playerGUID
|
||||
obj.OwnerName = player.Name
|
||||
obj.AssignOwnership(player)
|
||||
obj.Faction = faction
|
||||
avatar.Deployables.Add(obj)
|
||||
UpdateDeployableUIElements(avatar.Deployables.UpdateUIElement(obj.Definition.Item))
|
||||
|
|
@ -635,8 +657,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
TryDropConstructionTool(tool, index, obj.Position)
|
||||
sendResponse(ObjectDeployedMessage.Failure(obj.Definition.Name))
|
||||
obj.Position = Vector3.Zero
|
||||
obj.Owner = None
|
||||
obj.OwnerName = None
|
||||
obj.AssignOwnership(None)
|
||||
continent.Deployables ! Zone.Deployable.Dismiss(obj)
|
||||
}
|
||||
|
||||
|
|
@ -780,6 +801,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
localService ! Service.Leave(Some(continentId))
|
||||
localService ! Service.Leave(Some(factionOnContinentChannel))
|
||||
vehicleService ! Service.Leave(Some(continentId))
|
||||
vehicleService ! Service.Leave(Some(factionOnContinentChannel))
|
||||
player.Continent = zoneId
|
||||
continent = zone
|
||||
continent.Population ! Zone.Population.Join(avatar)
|
||||
|
|
@ -1348,8 +1370,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
case None => ;
|
||||
}
|
||||
tplayer.VehicleOwned = Some(obj_guid)
|
||||
obj.Owner = Some(tplayer.GUID)
|
||||
OwnVehicle(obj, tplayer)
|
||||
}
|
||||
AccessContents(obj)
|
||||
UpdateWeaponAtSeatPosition(obj, seat_num)
|
||||
|
|
@ -1764,11 +1785,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
avatar.Certifications += cert
|
||||
StartBundlingPackets()
|
||||
AddToDeployableQuantities(cert, player.Certifications)
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 24, cert.id.toLong))
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 24, cert.id))
|
||||
tplayer.Certifications.intersect(Certification.Dependencies.Like(cert)).foreach(entry => {
|
||||
log.info(s"$cert replaces the learned certification $entry that cost ${Certification.Cost.Of(entry)} points")
|
||||
avatar.Certifications -= entry
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 25, entry.id.toLong))
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 25, entry.id))
|
||||
})
|
||||
StopBundlingPackets()
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, true))
|
||||
|
|
@ -1787,12 +1808,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
avatar.Certifications -= cert
|
||||
StartBundlingPackets()
|
||||
RemoveFromDeployablesQuantities(cert, player.Certifications)
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 25, cert.id.toLong))
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 25, cert.id))
|
||||
tplayer.Certifications.intersect(Certification.Dependencies.FromAll(cert)).foreach(entry => {
|
||||
log.info(s"$name is also forgetting the ${Certification.Cost.Of(entry)}-point $entry certification which depends on $cert")
|
||||
avatar.Certifications -= entry
|
||||
RemoveFromDeployablesQuantities(entry, player.Certifications)
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 25, entry.id.toLong))
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 25, entry.id))
|
||||
})
|
||||
StopBundlingPackets()
|
||||
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Sell, true))
|
||||
|
|
@ -2023,7 +2044,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
case VehicleResponse.Ownership(vehicle_guid) =>
|
||||
sendResponse(PlanetsideAttributeMessage(guid, 21, vehicle_guid.guid))
|
||||
sendResponse(PlanetsideAttributeMessage(tplayer_guid, 21, vehicle_guid))
|
||||
|
||||
case VehicleResponse.PlanetsideAttribute(vehicle_guid, attribute_type, attribute_value) =>
|
||||
if(tplayer_guid != guid) {
|
||||
|
|
@ -2098,7 +2119,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
}
|
||||
|
||||
case VehicleResponse.KickCargo(vehicle, speed) =>
|
||||
case VehicleResponse.ForceDismountVehicleCargo(vehicle_guid, bailed, requestedByPassenger, kicked) =>
|
||||
DismountVehicleCargo(tplayer_guid, vehicle_guid, bailed, requestedByPassenger, kicked)
|
||||
case VehicleResponse.KickCargo(vehicle, speed, delay) =>
|
||||
if(player.VehicleSeated.nonEmpty && deadState == DeadState.Alive) {
|
||||
if(speed > 0) {
|
||||
val strafe = if(CargoOrientation(vehicle) == 1) 2 else 1
|
||||
|
|
@ -2107,7 +2130,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
controlled = Some(reverseSpeed)
|
||||
sendResponse(ServerVehicleOverrideMsg(true, true, true, false, 0, strafe, reverseSpeed, Some(0)))
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
context.system.scheduler.scheduleOnce(4500 milliseconds, self, VehicleServiceResponse(toChannel, tplayer_guid, VehicleResponse.KickCargo(vehicle, 0)))
|
||||
context.system.scheduler.scheduleOnce(delay milliseconds, self, VehicleServiceResponse(toChannel, tplayer_guid, VehicleResponse.KickCargo(vehicle, 0, delay)))
|
||||
}
|
||||
else {
|
||||
controlled = None
|
||||
|
|
@ -2678,12 +2701,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(SetCurrentAvatarMessage(guid, 0, 0))
|
||||
sendResponse(ChatMsg(ChatMessageType.CMT_EXPANSIONS, true, "", "1 on", None)) //CC on //TODO once per respawn?
|
||||
sendResponse(PlayerStateShiftMessage(ShiftState(1, tplayer.Position, tplayer.Orientation.z)))
|
||||
//transfer vehicle ownership
|
||||
player.VehicleOwned match {
|
||||
case Some(vehicle_guid) if player.VehicleSeated.contains(vehicle_guid) =>
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.Ownership(guid, vehicle_guid))
|
||||
case _ => ;
|
||||
}
|
||||
if(spectator) {
|
||||
sendResponse(ChatMsg(ChatMessageType.CMT_TOGGLESPECTATORMODE, false, "", "on", None))
|
||||
}
|
||||
|
|
@ -2734,6 +2751,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
})
|
||||
StopBundlingPackets()
|
||||
drawDeloyableIcon = DontRedrawIcons
|
||||
//assert or transfer vehicle ownership
|
||||
continent.GUID(player.VehicleOwned) match {
|
||||
case Some(vehicle : Vehicle) if vehicle.OwnerName.contains(tplayer.Name) =>
|
||||
vehicle.Owner = guid
|
||||
vehicleService ! VehicleServiceMessage(s"${continent.Id}/${tplayer.Faction}", VehicleAction.Ownership(guid, vehicle.GUID))
|
||||
case _ =>
|
||||
player.VehicleOwned = None
|
||||
}
|
||||
//if driver of a vehicle, summon any passengers and cargo vehicles left behind on previous continent
|
||||
GetVehicleAndSeat() match {
|
||||
case (Some(vehicle), Some(0)) =>
|
||||
|
|
@ -2863,16 +2888,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case msg @ DismountVehicleCargoMsg(player_guid, vehicle_guid, bailed, requestedByPassenger, kicked) =>
|
||||
log.info(msg.toString)
|
||||
if(!requestedByPassenger) {
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(cargo : Vehicle) =>
|
||||
continent.GUID(cargo.MountedIn) match {
|
||||
case Some(ferry : Vehicle) =>
|
||||
HandleDismountVehicleCargo(player_guid, vehicle_guid, cargo, ferry.GUID, ferry, bailed, requestedByPassenger, kicked)
|
||||
case _ =>
|
||||
log.warn(s"DismountVehicleCargoMsg: target ${cargo.Definition.Name} does not know what treats it as cargo")
|
||||
}
|
||||
case _ => ;
|
||||
}
|
||||
DismountVehicleCargo(player_guid, vehicle_guid, bailed, requestedByPassenger, kicked)
|
||||
}
|
||||
|
||||
case msg @ CharacterCreateRequestMessage(name, head, voice, gender, empire) =>
|
||||
|
|
@ -2908,6 +2924,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
localService ! Service.Join(continentId)
|
||||
localService ! Service.Join(factionOnContinentChannel)
|
||||
vehicleService ! Service.Join(continentId)
|
||||
vehicleService ! Service.Join(factionOnContinentChannel)
|
||||
galaxyService ! Service.Join("galaxy")
|
||||
configZone(continent)
|
||||
sendResponse(TimeOfDayMessage(1191182336))
|
||||
|
|
@ -3342,7 +3359,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
deadState = DeadState.Release //cancel movement updates
|
||||
PlayerActionsToCancel()
|
||||
continent.GUID(player.VehicleSeated) match {
|
||||
case Some(vehicle : Vehicle) =>
|
||||
case Some(vehicle : Vehicle) if vehicle.MountedIn.isEmpty =>
|
||||
vehicle.PassengerInSeat(player) match {
|
||||
case Some(0) =>
|
||||
vehicle.Position = pos
|
||||
|
|
@ -3354,7 +3371,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
player.Position = pos
|
||||
//avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, player.GUID))
|
||||
LoadZonePhysicalSpawnPoint(zone, pos, Vector3.Zero, 0)
|
||||
case _ => //seated in something that is not a vehicle, or we're dead, in which case we can't move
|
||||
case _ => //seated in something that is not a vehicle or the vehicle is cargo, in which case we can't move
|
||||
deadState = DeadState.Alive
|
||||
}
|
||||
|
||||
|
|
@ -3366,7 +3383,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
deadState = DeadState.Release //cancel movement updates
|
||||
PlayerActionsToCancel()
|
||||
continent.GUID(player.VehicleSeated) match {
|
||||
case Some(vehicle : Vehicle) if player.isAlive =>
|
||||
case Some(vehicle : Vehicle) if vehicle.MountedIn.isEmpty =>
|
||||
vehicle.PassengerInSeat(player) match {
|
||||
case Some(0) =>
|
||||
vehicle.Position = pos
|
||||
|
|
@ -3378,7 +3395,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
player.Position = pos
|
||||
sendResponse(PlayerStateShiftMessage(ShiftState(0, pos, player.Orientation.z, None)))
|
||||
deadState = DeadState.Alive //must be set here
|
||||
case _ => //seated in something that is not a vehicle, or we're dead, in which case we can't move
|
||||
case _ => //seated in something that is not a vehicle or the vehicle is cargo, in which case we can't move
|
||||
deadState = DeadState.Alive
|
||||
}
|
||||
|
||||
|
|
@ -4276,8 +4293,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
dObj.Position = pos
|
||||
dObj.Orientation = orient
|
||||
dObj.Faction = player.Faction
|
||||
dObj.Owner = player.GUID
|
||||
dObj.OwnerName = player.Name
|
||||
dObj.AssignOwnership(player)
|
||||
val tasking : TaskResolver.GiveTask = dObj match {
|
||||
case turret : TurretDeployable =>
|
||||
GUIDTask.RegisterDeployableTurret(turret)(continent.GUID)
|
||||
|
|
@ -4617,7 +4633,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case msg @ DeployRequestMessage(player_guid, vehicle_guid, deploy_state, unk2, unk3, pos) =>
|
||||
log.info(s"DeployRequest: $msg")
|
||||
if(player.VehicleOwned == Some(vehicle_guid) && player.VehicleOwned == player.VehicleSeated) {
|
||||
if(player.VehicleOwned.contains(vehicle_guid) && player.VehicleOwned == player.VehicleSeated) {
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(obj : Vehicle) =>
|
||||
obj.Actor ! Deployment.TryDeploymentChange(deploy_state)
|
||||
|
|
@ -5038,7 +5054,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
def Execute(resolver : ActorRef) : Unit = {
|
||||
localDriver.VehicleSeated = localVehicle.GUID
|
||||
localVehicle.Owner = localDriver.GUID
|
||||
OwnVehicle(localVehicle, localDriver)
|
||||
localAnnounce ! NewPlayerLoaded(localDriver) //alerts WSA
|
||||
resolver ! scala.util.Success(this)
|
||||
}
|
||||
|
|
@ -5322,12 +5338,39 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* @param vehicle the `Vehicle`
|
||||
*/
|
||||
def ReloadVehicleAccessPermissions(vehicle : Vehicle) : Unit = {
|
||||
val vehicle_guid = vehicle.GUID
|
||||
(0 to 3).foreach(group => {
|
||||
sendResponse(
|
||||
PlanetsideAttributeMessage(vehicle_guid, group + 10, vehicle.PermissionGroup(group).get.id)
|
||||
)
|
||||
})
|
||||
if(vehicle.Faction == player.Faction) {
|
||||
val vehicle_guid = vehicle.GUID
|
||||
(0 to 3).foreach(group => {
|
||||
sendResponse(
|
||||
PlanetsideAttributeMessage(vehicle_guid, group + 10, vehicle.PermissionGroup(group).get.id)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param vehicle na
|
||||
* @param tplayer na
|
||||
* @return na
|
||||
*/
|
||||
def OwnVehicle(vehicle : Vehicle, tplayer : Player) : Option[Vehicle] = OwnVehicle(vehicle, Some(tplayer))
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param vehicle na
|
||||
* @param playerOpt na
|
||||
* @return na
|
||||
*/
|
||||
def OwnVehicle(vehicle : Vehicle, playerOpt : Option[Player]) : Option[Vehicle] = {
|
||||
playerOpt match {
|
||||
case Some(tplayer) =>
|
||||
tplayer.VehicleOwned = vehicle.GUID
|
||||
vehicle.AssignOwnership(playerOpt)
|
||||
Some(vehicle)
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -5340,7 +5383,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* The vehicle must exist in the game world on the current continent.
|
||||
* This is similar but unrelated to the natural exchange of ownership when someone else sits in the vehicle's driver seat.
|
||||
* This is the player side of vehicle ownership removal.
|
||||
* @see `SpecialCaseVehicleDespawn(Player, Vehicle)`
|
||||
* @param tplayer the player
|
||||
*/
|
||||
def DisownVehicle(tplayer : Player) : Option[Vehicle] = {
|
||||
|
|
@ -5349,7 +5391,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
tplayer.VehicleOwned = None
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(vehicle : Vehicle) =>
|
||||
SpecialCaseVehicleDespawn(tplayer, vehicle)
|
||||
DisownVehicle(tplayer, vehicle)
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
|
|
@ -5359,35 +5401,25 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
|
||||
/**
|
||||
* Disassociate a vehicle from the player that owns it, if that player really was the previous owner.
|
||||
* Disassociate a player from a vehicle that he owns without associating a different player as the owner.
|
||||
* Set the vehicle's driver seat permissions and passenger and gunner seat permissions to "allow empire,"
|
||||
* then reload them for all clients.
|
||||
* This is the vehicle side of vehicle ownership removal.
|
||||
* Additionally, start the vehicle deconstruction timer if conditions are valid.
|
||||
* @see `DisownVehicle(Player)`
|
||||
* @param tplayer the player
|
||||
* @param vehicle the discovered vehicle
|
||||
*/
|
||||
private def SpecialCaseVehicleDespawn(tplayer : Player, vehicle : Vehicle) : Option[Vehicle] = {
|
||||
if(vehicle.Owner.contains(tplayer.GUID)) {
|
||||
vehicle.Owner = None
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(vehicle), continent))
|
||||
vehicle.CargoHolds.values
|
||||
.collect { case hold if hold.isOccupied => SpecialCaseVehicleDespawn(player, hold.Occupant.get) }
|
||||
continent.GUID(vehicle.MountedIn) match {
|
||||
case Some(ferry : Vehicle) =>
|
||||
HandleDismountVehicleCargo(
|
||||
PlanetSideGUID(0),
|
||||
vehicle.GUID,
|
||||
vehicle,
|
||||
ferry.GUID,
|
||||
ferry,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
)
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, Some(0 seconds))) //instant vehicle decay
|
||||
case _ =>
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(vehicle, continent, vehicle.Definition.DeconstructionTime)) //normal vehicle decay
|
||||
}
|
||||
private def DisownVehicle(tplayer : Player, vehicle : Vehicle) : Option[Vehicle] = {
|
||||
val pguid = tplayer.GUID
|
||||
if(vehicle.Owner.contains(pguid)) {
|
||||
vehicle.AssignOwnership(None)
|
||||
val factionOnContinent = s"${continent.Id}/${vehicle.Faction}"
|
||||
vehicleService ! VehicleServiceMessage(factionOnContinent, VehicleAction.Ownership(pguid, PlanetSideGUID(0)))
|
||||
val vguid = vehicle.GUID
|
||||
val empire = VehicleLockState.Empire.id
|
||||
(0 to 2).foreach(group => {
|
||||
vehicle.PermissionGroup(group, empire)
|
||||
vehicleService ! VehicleServiceMessage(factionOnContinent, VehicleAction.SeatPermissions(pguid, vguid, group, empire))
|
||||
})
|
||||
ReloadVehicleAccessPermissions(vehicle)
|
||||
Some(vehicle)
|
||||
}
|
||||
else {
|
||||
|
|
@ -6629,8 +6661,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
player.VehicleSeated = guid
|
||||
if(seat == 0) {
|
||||
//if driver
|
||||
player.VehicleOwned = guid
|
||||
vehicle.Owner = player.GUID
|
||||
OwnVehicle(vehicle, player)
|
||||
vehicle.CargoHolds.values
|
||||
.collect { case hold if hold.isOccupied => hold.Occupant.get }
|
||||
.foreach { _.MountedIn = guid }
|
||||
|
|
@ -7521,13 +7552,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
removed match {
|
||||
case Some(telepad : TelepadDeployable) =>
|
||||
telepad.Owner = None
|
||||
telepad.OwnerName = None
|
||||
telepad.AssignOwnership(None)
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(telepad), continent))
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(telepad, continent, Some(0 seconds))) //normal decay
|
||||
case Some(old) =>
|
||||
old.Owner = None
|
||||
old.OwnerName = None
|
||||
old.AssignOwnership(None)
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(old), continent))
|
||||
localService ! LocalServiceMessage.Deployables(RemoverActor.AddTask(old, continent, Some(0 seconds)))
|
||||
if(msg) { //max test
|
||||
|
|
@ -7959,7 +7988,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
* @param tplayer the target player being moved around;
|
||||
* not necessarily the same player as the `WorldSessionActor`-global `player`
|
||||
* @param zone_id the zone in which the player will be placed
|
||||
* @return a tuple composed of an ActorRef` destination and a message to send to that destination
|
||||
* @return a tuple composed of an `ActorRef` destination and a message to send to that destination
|
||||
*/
|
||||
def LoadZoneAsPlayer(tplayer : Player, zone_id : String) : (ActorRef, Any) = {
|
||||
if(zone_id == continent.Id) {
|
||||
|
|
@ -8058,12 +8087,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
hold.Occupant.get
|
||||
}
|
||||
occupiedCargoHolds.foreach{ cargo =>
|
||||
cargo.Seat(0) match {
|
||||
case Some(seat) if seat.isOccupied =>
|
||||
vehicleService ! VehicleServiceMessage(s"${seat.Occupant.get.Name}", VehicleAction.TransferPassengerChannel(pguid, s"${cargo.Actor}", toChannel, cargo))
|
||||
cargo.Seats(0).Occupant match {
|
||||
case Some(occupant) =>
|
||||
vehicleService ! VehicleServiceMessage(s"${occupant.Name}", VehicleAction.TransferPassengerChannel(pguid, s"${cargo.Actor}", toChannel, cargo))
|
||||
case _ =>
|
||||
log.error("LoadZoneInVehicleAsDriver: abort; vehicle in cargo hold missing driver")
|
||||
SpecialCaseVehicleDespawn(player, cargo)
|
||||
HandleDismountVehicleCargo(player.GUID, cargo.GUID, cargo, vehicle.GUID, vehicle, false, false, true)
|
||||
}
|
||||
}
|
||||
//
|
||||
|
|
@ -8486,6 +8515,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Some((mountPoint, hold)) =>
|
||||
cargo.MountedIn = None
|
||||
hold.Occupant = None
|
||||
val driverOpt = cargo.Seats(0).Occupant
|
||||
val rotation : Vector3 = if(CargoOrientation(cargo) == 1) { //TODO: BFRs will likely also need this set
|
||||
//dismount router "sideways" in a lodestar
|
||||
carrier.Orientation.xy + Vector3.z((carrier.Orientation.z - 90) % 360)
|
||||
|
|
@ -8511,11 +8541,16 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
val resetCargoMsg = CargoMountPointStatusMessage(carrierGUID, PlanetSideGUID(0), PlanetSideGUID(0), cargoGUID, mountPoint, CargoStatus.Empty, 0)
|
||||
sendResponse(ejectCargoMsg) //dismount vehicle on UI and disable "shield" effect on lodestar
|
||||
sendResponse(detachCargoMsg)
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player_guid, ejectCargoMsg))
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player_guid, detachCargoMsg))
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(PlanetSideGUID(0), resetCargoMsg)) //lazy
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.SendResponse(player_guid, ejectCargoMsg))
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.SendResponse(player_guid, detachCargoMsg))
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.SendResponse(PlanetSideGUID(0), resetCargoMsg)) //lazy
|
||||
log.debug(ejectCargoMsg.toString)
|
||||
log.debug(detachCargoMsg.toString)
|
||||
if(driverOpt.isEmpty) {
|
||||
//TODO cargo should drop like a rock like normal; until then, deconstruct it
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(cargo), continent))
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(cargo, continent, Some(0 seconds)))
|
||||
}
|
||||
}
|
||||
else {
|
||||
//the carrier vehicle is not flying; just open the door and let the cargo vehicle back out; force it out if necessary
|
||||
|
|
@ -8525,19 +8560,23 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
sendResponse(cargoDetachMessage)
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player_guid, cargoStatusMessage))
|
||||
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.SendResponse(player_guid, cargoDetachMessage))
|
||||
if(kicked) {
|
||||
cargo.Seat(0).get.Occupant match {
|
||||
case Some(driver) =>
|
||||
vehicleService ! VehicleServiceMessage(s"${driver.Name}", VehicleAction.KickCargo(player_guid, cargo, cargo.Definition.AutoPilotSpeed2))
|
||||
case None =>
|
||||
//driverless vehicle will get cleaned up
|
||||
}
|
||||
driverOpt match {
|
||||
case Some(driver) =>
|
||||
if(kicked) {
|
||||
vehicleService ! VehicleServiceMessage(s"${driver.Name}", VehicleAction.KickCargo(player_guid, cargo, cargo.Definition.AutoPilotSpeed2, 4500))
|
||||
}
|
||||
import scala.concurrent.duration._
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
//check every quarter second if the vehicle has moved far enough away to be considered dismounted
|
||||
cargoDismountTimer.cancel
|
||||
cargoDismountTimer = context.system.scheduler.scheduleOnce(250 milliseconds, self, CheckCargoDismount(cargoGUID, carrierGUID, mountPoint, iteration = 0))
|
||||
case None =>
|
||||
val resetCargoMsg = CargoMountPointStatusMessage(carrierGUID, PlanetSideGUID(0), PlanetSideGUID(0), cargoGUID, mountPoint, CargoStatus.Empty, 0)
|
||||
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.SendResponse(PlanetSideGUID(0), resetCargoMsg)) //lazy
|
||||
//TODO cargo should back out like normal; until then, deconstruct it
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(cargo), continent))
|
||||
vehicleService ! VehicleServiceMessage.Decon(RemoverActor.AddTask(cargo, continent, Some(0 seconds)))
|
||||
}
|
||||
import scala.concurrent.duration._
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
//check every quarter second if the vehicle has moved far enough away to be considered dismounted
|
||||
cargoDismountTimer.cancel
|
||||
cargoDismountTimer = context.system.scheduler.scheduleOnce(250 milliseconds, self, CheckCargoDismount(cargoGUID, carrierGUID, mountPoint, iteration = 0))
|
||||
}
|
||||
StopBundlingPackets()
|
||||
|
||||
|
|
@ -8546,6 +8585,28 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param player_guid na
|
||||
* @param vehicle_guid na
|
||||
* @param bailed na
|
||||
* @param requestedByPassenger na
|
||||
* @param kicked na
|
||||
*/
|
||||
def DismountVehicleCargo(player_guid : PlanetSideGUID, vehicle_guid : PlanetSideGUID, bailed : Boolean, requestedByPassenger : Boolean, kicked : Boolean) : Unit = {
|
||||
continent.GUID(vehicle_guid) match {
|
||||
case Some(cargo : Vehicle) =>
|
||||
continent.GUID(cargo.MountedIn) match {
|
||||
case Some(ferry : Vehicle) =>
|
||||
HandleDismountVehicleCargo(player_guid, vehicle_guid, cargo, ferry.GUID, ferry, bailed, requestedByPassenger, kicked)
|
||||
case _ =>
|
||||
log.warn(s"DismountVehicleCargo: target ${cargo.Definition.Name}@$vehicle_guid does not know what treats it as cargo")
|
||||
}
|
||||
case _ =>
|
||||
log.warn(s"DismountVehicleCargo: target $vehicle_guid either is not a vehicle in ${continent.Id} or does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
def GetPlayerHackSpeed(obj: PlanetSideServerObject with Hackable): Float = {
|
||||
val playerHackLevel = GetPlayerHackLevel()
|
||||
val timeToHack = obj.HackDuration(playerHackLevel)
|
||||
|
|
|
|||
Loading…
Reference in a new issue