mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-04-27 14:55:22 +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
9 changed files with 284 additions and 179 deletions
|
|
@ -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…
Add table
Add a link
Reference in a new issue