From 2e901ae90475bd70bdb872ba7c7af248a86c1527 Mon Sep 17 00:00:00 2001 From: Fate-JH Date: Thu, 22 Aug 2024 00:00:25 -0400 Subject: [PATCH] announce ams decay to players who have just spawned on an ams, when they spawn on that ams, and for the last round of spawnees when the vehicle finally deconstructs; due to use of the word 'bound' this may be an incorrect application, but matrixing doesn't work anyway --- .../session/normal/VehicleHandlerLogic.scala | 15 ++++- .../support/SessionVehicleHandlers.scala | 19 +++++- .../session/support/ZoningOperations.scala | 26 +++++--- .../net/psforever/objects/Vehicles.scala | 60 ++++++++++--------- .../global/GlobalDefinitionsVehicle.scala | 2 +- .../services/vehicle/VehicleService.scala | 4 ++ .../vehicle/VehicleServiceMessage.scala | 1 + .../vehicle/VehicleServiceResponse.scala | 2 + 8 files changed, 91 insertions(+), 38 deletions(-) diff --git a/src/main/scala/net/psforever/actors/session/normal/VehicleHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/normal/VehicleHandlerLogic.scala index 208173854..7084427ea 100644 --- a/src/main/scala/net/psforever/actors/session/normal/VehicleHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/VehicleHandlerLogic.scala @@ -14,7 +14,7 @@ import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent import net.psforever.packet.game.{ChangeAmmoMessage, ChangeFireStateMessage_Start, ChangeFireStateMessage_Stop, ChatMsg, ChildObjectStateMessage, DeadState, DeployRequestMessage, DismountVehicleMsg, FrameVehicleStateMessage, GenericObjectActionMessage, HitHint, InventoryStateMessage, ObjectAttachMessage, ObjectCreateDetailedMessage, ObjectCreateMessage, ObjectDeleteMessage, ObjectDetachMessage, PlanetsideAttributeMessage, ReloadMessage, ServerVehicleOverrideMsg, VehicleStateMessage, WeaponDryFireMessage} import net.psforever.services.Service import net.psforever.services.vehicle.{VehicleResponse, VehicleServiceResponse} -import net.psforever.types.{BailType, ChatMessageType, PlanetSideGUID, Vector3} +import net.psforever.types.{BailType, ChatMessageType, DriveState, PlanetSideGUID, Vector3} object VehicleHandlerLogic { def apply(ops: SessionVehicleHandlers): VehicleHandlerLogic = { @@ -207,6 +207,9 @@ class VehicleHandlerLogic(val ops: SessionVehicleHandlers, implicit val context: avatarActor ! AvatarActor.SetVehicle(Some(vehicleGuid)) sendResponse(PlanetsideAttributeMessage(resolvedPlayerGuid, attribute_type=21, vehicleGuid)) + case VehicleResponse.LoseOwnership(_, vehicleGuid) => + ops.announceAmsDecay(vehicleGuid,msg = "@ams_decaystarted") + case VehicleResponse.PlanetsideAttribute(vehicleGuid, attributeType, attributeValue) if isNotSameTarget => sendResponse(PlanetsideAttributeMessage(vehicleGuid, attributeType, attributeValue)) @@ -225,6 +228,16 @@ class VehicleHandlerLogic(val ops: SessionVehicleHandlers, implicit val context: case VehicleResponse.UnloadVehicle(_, vehicleGuid) => sendResponse(ObjectDeleteMessage(vehicleGuid, unk1=0)) + if (sessionLogic.zoning.spawn.prevSpawnPoint.map(_.Owner).exists { + case ams: Vehicle => + ams.GUID == vehicleGuid && + ams.OwnerGuid.isEmpty + case _ => + false + }) { + sessionLogic.zoning.spawn.prevSpawnPoint = None + sendResponse(ChatMsg(ChatMessageType.UNK_229, "@ams_decayed")) + } case VehicleResponse.UnstowEquipment(itemGuid) if isNotSameTarget => //TODO prefer ObjectDetachMessage, but how to force ammo pools to update properly? diff --git a/src/main/scala/net/psforever/actors/session/support/SessionVehicleHandlers.scala b/src/main/scala/net/psforever/actors/session/support/SessionVehicleHandlers.scala index 5389b6bb9..b493b1ff2 100644 --- a/src/main/scala/net/psforever/actors/session/support/SessionVehicleHandlers.scala +++ b/src/main/scala/net/psforever/actors/session/support/SessionVehicleHandlers.scala @@ -3,8 +3,10 @@ package net.psforever.actors.session.support import akka.actor.{ActorContext, ActorRef, typed} import net.psforever.actors.session.AvatarActor +import net.psforever.objects.Vehicle +import net.psforever.packet.game.ChatMsg import net.psforever.services.vehicle.VehicleResponse -import net.psforever.types.PlanetSideGUID +import net.psforever.types.{ChatMessageType, DriveState, PlanetSideGUID} trait VehicleHandlerFunctions extends CommonSessionInterfacingFunctionality { def ops: SessionVehicleHandlers @@ -17,4 +19,17 @@ class SessionVehicleHandlers( val avatarActor: typed.ActorRef[AvatarActor.Command], val galaxyService: ActorRef, implicit val context: ActorContext - ) extends CommonSessionInterfacingFunctionality + ) extends CommonSessionInterfacingFunctionality { + def announceAmsDecay(vehicleGuid: PlanetSideGUID, msg: String): Unit = { + if (sessionLogic.zoning.spawn.prevSpawnPoint.map(_.Owner).exists { + case ams: Vehicle => + ams.GUID == vehicleGuid && + ams.DeploymentState == DriveState.Deployed && + ams.OwnerGuid.isEmpty + case _ => + false + }) { + sendResponse(ChatMsg(ChatMessageType.UNK_229, msg)) + } + } +} diff --git a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala index ebeb512fc..4af23102d 100644 --- a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala @@ -1792,6 +1792,7 @@ class ZoningOperations( private[session] var setupAvatarFunc: () => Unit = AvatarCreate private[session] var setCurrentAvatarFunc: Player => Unit = SetCurrentAvatarNormally private[session] var nextSpawnPoint: Option[SpawnPoint] = None + private[session] var prevSpawnPoint: Option[SpawnPoint] = None private[session] var interimUngunnedVehicle: Option[PlanetSideGUID] = None private[session] var interimUngunnedVehicleSeat: Option[Int] = None /** Upstream message counter
@@ -2811,6 +2812,7 @@ class ZoningOperations( ) ) nextSpawnPoint = physSpawnPoint + prevSpawnPoint = physSpawnPoint shiftPosition = Some(pos) shiftOrientation = Some(ori) val toZoneNumber = if (continent.id.equals(zoneId)) { @@ -2819,10 +2821,14 @@ class ZoningOperations( Zones.zones.find { _.id.equals(zoneId) }.orElse(Some(Zone.Nowhere)).get.Number } val toSide = physSpawnPoint.map(_.Owner) match { - case Some(_: WarpGate) => Sidedness.OutsideOf - case Some(_: Building) => Sidedness.InsideOf - case Some(v: Vehicle) => v.WhichSide //though usually OutsideOf - case _ => Sidedness.StrictlyBetweenSides //todo needs better determination + case Some(_: WarpGate) => + Sidedness.OutsideOf + case Some(_: Building) => + Sidedness.InsideOf + case Some(v: Vehicle) => + v.WhichSide //though usually OutsideOf + case _ => + Sidedness.StrictlyBetweenSides //todo needs better determination } val toSpawnPoint = physSpawnPoint.collect { case o: PlanetSideGameObject with FactionAffinity => SourceEntry(o) } respawnTimer = context.system.scheduler.scheduleOnce(respawnTime) { @@ -3124,11 +3130,17 @@ class ZoningOperations( Config.app.game.savedMsg.short.fixed, Config.app.game.savedMsg.short.variable ) - val effortBy = nextSpawnPoint + val effortBy = prevSpawnPoint .collect { case sp: SpawnTube => (sp, continent.GUID(sp.Owner.GUID)) } .collect { - case (_, Some(v: Vehicle)) => continent.GUID(v.OwnerGuid) - case (sp, Some(_: Building)) => Some(sp) + case (_, Some(v: Vehicle)) => + sessionLogic.vehicleResponseOperations.announceAmsDecay( + v.GUID, + msg = "The AMS you were bound to has lost its' owner. It will auto-deconstruct soon." + ) + continent.GUID(v.OwnerGuid) + case (sp, Some(_: Building)) => + Some(sp) } .collect { case Some(thing: PlanetSideGameObject with FactionAffinity) => Some(SourceEntry(thing)) } .flatten diff --git a/src/main/scala/net/psforever/objects/Vehicles.scala b/src/main/scala/net/psforever/objects/Vehicles.scala index 462323e64..6a66afe33 100644 --- a/src/main/scala/net/psforever/objects/Vehicles.scala +++ b/src/main/scala/net/psforever/objects/Vehicles.scala @@ -46,7 +46,7 @@ object Vehicles { vehicle.Zone.id, VehicleAction.Ownership(tplayer.GUID, vehicle.GUID) ) - Vehicles.ReloadAccessPermissions(vehicle, tplayer.Name) + Vehicles.ReloadAccessPermissions(vehicle, tplayer.Faction.toString) Some(vehicle) case None => None @@ -61,31 +61,37 @@ object Vehicles { * @return the vehicle, if it had a previous owner; * `None`, otherwise */ - def Disown(guid: PlanetSideGUID, vehicle: Vehicle): Option[Vehicle] = - vehicle.Zone.GUID(vehicle.OwnerGuid) match { - case Some(player: Player) => - if (player.avatar.vehicle.contains(guid)) { - player.avatar.vehicle = None -// vehicle.Zone.VehicleEvents ! VehicleServiceMessage( -// player.Name, -// VehicleAction.Ownership(player.GUID, PlanetSideGUID(0)) -// ) - } - vehicle.AssignOwnership(None) - val empire = VehicleLockState.Empire.id - //val factionChannel = s"${vehicle.Faction}" - (0 to 2).foreach(group => { - vehicle.PermissionGroup(group, empire) - /*vehicle.Zone.VehicleEvents ! VehicleServiceMessage( - factionChannel, - VehicleAction.SeatPermissions(Service.defaultPlayerGUID, guid, group, empire) - )*/ - }) - ReloadAccessPermissions(vehicle, player.Name) - Some(vehicle) - case _ => - None - } + def Disown(guid: PlanetSideGUID, vehicle: Vehicle): Option[Vehicle] = { + val zone = vehicle.Zone + val ownerGuid = vehicle.OwnerGuid + val ownerName = vehicle.OwnerName + vehicle.AssignOwnership(None) + val result = zone + .GUID(ownerGuid) + .collect { + case player: Player => player.avatar + } + .orElse { + zone + .Players + .collectFirst { + case avatar if ownerName.contains(avatar.name) => avatar + } + } + .collect { + case avatar if avatar.vehicle.contains(guid) => + avatar.vehicle = None + vehicle + } + val empire = VehicleLockState.Empire.id + (0 to 2).foreach(group => vehicle.PermissionGroup(group, empire)) + ReloadAccessPermissions(vehicle, vehicle.Faction.toString) + zone.VehicleEvents ! VehicleServiceMessage( + zone.id, + VehicleAction.LoseOwnership(ownerGuid.getOrElse(Service.defaultPlayerGUID), guid) + ) + result + } /** * Disassociate a player from a vehicle that he owns. @@ -140,7 +146,7 @@ object Vehicles { VehicleAction.SeatPermissions(pguid, vguid, group, empire) )*/ }) - ReloadAccessPermissions(vehicle, player.Name) + ReloadAccessPermissions(vehicle, vehicle.Faction.toString) Some(vehicle) } else { None diff --git a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsVehicle.scala b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsVehicle.scala index c3dd0c9dd..4e4eabc40 100644 --- a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsVehicle.scala +++ b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsVehicle.scala @@ -971,7 +971,7 @@ object GlobalDefinitionsVehicle { ams.DeployTime = 2000 ams.UndeployTime = 2000 ams.interference = InterferenceRange(main = 125f, sharedGroupId = 3, shared = 30f) - ams.DeconstructionTime = Some(20 minutes) + ams.DeconstructionTime = Some(15 minutes) ams.AutoPilotSpeeds = (18, 6) ams.Packet = utilityConverter ams.DestroyedModel = Some(DestroyedVehicle.Ams) diff --git a/src/main/scala/net/psforever/services/vehicle/VehicleService.scala b/src/main/scala/net/psforever/services/vehicle/VehicleService.scala index 35b377981..72168faa0 100644 --- a/src/main/scala/net/psforever/services/vehicle/VehicleService.scala +++ b/src/main/scala/net/psforever/services/vehicle/VehicleService.scala @@ -184,6 +184,10 @@ class VehicleService(zone: Zone) extends Actor { VehicleResponse.MountVehicle(vehicle_guid, seat) ) ) + case VehicleAction.LoseOwnership(owner_guid, vehicle_guid) => + VehicleEvents.publish( + VehicleServiceResponse(s"/$forChannel/Vehicle", Service.defaultPlayerGUID, VehicleResponse.LoseOwnership(owner_guid, vehicle_guid)) + ) case VehicleAction.Ownership(player_guid, vehicle_guid) => VehicleEvents.publish( VehicleServiceResponse(s"/$forChannel/Vehicle", player_guid, VehicleResponse.Ownership(vehicle_guid)) diff --git a/src/main/scala/net/psforever/services/vehicle/VehicleServiceMessage.scala b/src/main/scala/net/psforever/services/vehicle/VehicleServiceMessage.scala index 979d179f9..07bb29769 100644 --- a/src/main/scala/net/psforever/services/vehicle/VehicleServiceMessage.scala +++ b/src/main/scala/net/psforever/services/vehicle/VehicleServiceMessage.scala @@ -93,6 +93,7 @@ object VehicleAction { ) extends Action final case class MountVehicle(player_guid: PlanetSideGUID, object_guid: PlanetSideGUID, seat: Int) extends Action final case class ObjectDelete(guid: PlanetSideGUID) extends Action + final case class LoseOwnership(owner_guid: PlanetSideGUID, vehicle_guid: PlanetSideGUID) extends Action final case class Ownership(player_guid: PlanetSideGUID, vehicle_guid: PlanetSideGUID) extends Action final case class PlanetsideAttribute( player_guid: PlanetSideGUID, diff --git a/src/main/scala/net/psforever/services/vehicle/VehicleServiceResponse.scala b/src/main/scala/net/psforever/services/vehicle/VehicleServiceResponse.scala index e64c6536e..22e2ed94f 100644 --- a/src/main/scala/net/psforever/services/vehicle/VehicleServiceResponse.scala +++ b/src/main/scala/net/psforever/services/vehicle/VehicleServiceResponse.scala @@ -74,6 +74,8 @@ object VehicleResponse { final case class MountVehicle(object_guid: PlanetSideGUID, seat: Int) extends Response final case class ObjectDelete(guid: PlanetSideGUID) extends Response final case class Ownership(vehicle_guid: PlanetSideGUID) extends Response + final case class LoseOwnership(owner_guid: PlanetSideGUID, vehicle_guid: PlanetSideGUID) + extends Response final case class PlanetsideAttribute(vehicle_guid: PlanetSideGUID, attribute_type: Int, attribute_value: Long) extends Response final case class Reload(weapon_guid: PlanetSideGUID) extends Response