From 354376882ae2db423fc201589f5e014527e64c38 Mon Sep 17 00:00:00 2001 From: ScrawnyRonnie Date: Fri, 5 Dec 2025 17:00:32 -0500 Subject: [PATCH 1/3] llu handling, report accurate capture data --- .../session/normal/MountHandlerLogic.scala | 8 +++ .../session/support/GeneralOperations.scala | 5 +- .../support/SessionAvatarHandlers.scala | 8 +-- .../session/support/ZoningOperations.scala | 71 +++++++++++-------- .../MajorFacilityHackParticipation.scala | 3 + .../vehicles/control/VehicleControl.scala | 10 +++ .../local/support/CaptureFlagManager.scala | 4 +- 7 files changed, 74 insertions(+), 35 deletions(-) diff --git a/src/main/scala/net/psforever/actors/session/normal/MountHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/normal/MountHandlerLogic.scala index 9c03dc326..f7230008f 100644 --- a/src/main/scala/net/psforever/actors/session/normal/MountHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/MountHandlerLogic.scala @@ -4,6 +4,7 @@ package net.psforever.actors.session.normal import akka.actor.ActorContext import net.psforever.actors.session.support.{MountHandlerFunctions, SessionData, SessionMountHandlers} import net.psforever.actors.zone.ZoneActor +import net.psforever.objects.avatar.SpecialCarry import net.psforever.objects.{GlobalDefinitions, PlanetSideGameObject, Player, Vehicle, Vehicles} import net.psforever.objects.definition.{BasicDefinition, ObjectDefinition} import net.psforever.objects.serverobject.affinity.FactionAffinity @@ -296,6 +297,13 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act ChatMsg(ChatMessageType.CMT_OPEN, wideContents=false, recipient="", "You are not the driver of this vehicle.", note=None) ) } + if (obj.Zone.blockMap.sector(obj).buildingList.exists { + case wg: WarpGate => + Vector3.DistanceSquared(obj.Position, wg.Position) < math.pow(wg.Definition.SOIRadius, 2) + case _ => false + } && tplayer.Carrying.contains(SpecialCarry.CaptureFlag)) { + sendResponse(ChatMsg(ChatMessageType.UNK_224, "@VehicleMount_CaptureFlagWithVehicleInWarpgate")) + } case Mountable.CanNotMount(obj: Mountable, seatNumber) => log.warn(s"MountVehicleMsg: ${tplayer.Name} attempted to mount $obj's seat $seatNumber, but was not allowed") diff --git a/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala b/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala index 9f5ce393f..539e50935 100644 --- a/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala @@ -1441,9 +1441,12 @@ class GeneralOperations( } def handleUseCaptureFlag(obj: CaptureFlag): Unit = { + if (player.ZoningRequest != Zoning.Method.None) { + sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use") + } // LLU can normally only be picked up the faction that owns it specialItemSlotGuid match { - case None if obj.Faction == player.Faction => + case None if obj.Faction == player.Faction && player.ZoningRequest == Zoning.Method.None => specialItemSlotGuid = Some(obj.GUID) player.Carrying = SpecialCarry.CaptureFlag continent.LocalEvents ! CaptureFlagManager.PickupFlag(obj, player) diff --git a/src/main/scala/net/psforever/actors/session/support/SessionAvatarHandlers.scala b/src/main/scala/net/psforever/actors/session/support/SessionAvatarHandlers.scala index 682ef2ed6..7c7002e51 100644 --- a/src/main/scala/net/psforever/actors/session/support/SessionAvatarHandlers.scala +++ b/src/main/scala/net/psforever/actors/session/support/SessionAvatarHandlers.scala @@ -97,7 +97,7 @@ class SessionAvatarHandlers( } else { cappedModifiedExp } - exp.ToDatabase.reportFacilityCapture(charId, buildingId, zoneNumber, finalExp, expType="cep") + exp.ToDatabase.reportFacilityCapture(charId, zoneNumber, buildingId, finalExp, expType="cep") avatarActor ! AvatarActor.AwardCep(finalExp) Some(finalExp) @@ -116,9 +116,9 @@ class SessionAvatarHandlers( } val modifiedExp = (cep * individualContribution).toLong val finalBep = math.min(modifiedExp, 2250L) // 2250 max bep for capture - exp.ToDatabase.reportFacilityCapture(charId, buildingId, zoneNumber, finalBep, expType="bep") - avatarActor ! AvatarActor.AwardFacilityCaptureBep(modifiedExp) - Some(modifiedExp) + exp.ToDatabase.reportFacilityCapture(charId, zoneNumber, buildingId, finalBep, expType="bep") + avatarActor ! AvatarActor.AwardFacilityCaptureBep(finalBep) + Some(finalBep) } } 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 7cd3e1282..6a467e262 100644 --- a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala @@ -8,7 +8,7 @@ import akka.pattern.ask import akka.util.Timeout import net.psforever.actors.session.support.SpawnOperations.ActivityQueuedTask import net.psforever.login.WorldSession -import net.psforever.objects.avatar.{BattleRank, DeployableToolbox} +import net.psforever.objects.avatar.{BattleRank, DeployableToolbox, SpecialCarry} import net.psforever.objects.avatar.scoring.{CampaignStatistics, ScoreCard, SessionStatistics} import net.psforever.objects.definition.converter.OCM import net.psforever.objects.entity.WorldEntity @@ -781,41 +781,56 @@ class ZoningOperations( } def handleRecall(): Unit = { - player.ZoningRequest = Zoning.Method.Recall - zoningType = Zoning.Method.Recall - zoningChatMessageType = ChatMessageType.CMT_RECALL - zoningStatus = Zoning.Status.Request - beginZoningCountdown(() => { - cluster ! ICS.GetRandomSpawnPoint( - Zones.sanctuaryZoneNumber(player.Faction), - player.Faction, - Seq(SpawnGroup.Sanctuary), - context.self - ) - }) + if (player.Carrying.contains(SpecialCarry.CaptureFlag)) { + CancelZoningProcessWithDescriptiveReason("cancel") + } + else { + player.ZoningRequest = Zoning.Method.Recall + zoningType = Zoning.Method.Recall + zoningChatMessageType = ChatMessageType.CMT_RECALL + zoningStatus = Zoning.Status.Request + beginZoningCountdown(() => { + cluster ! ICS.GetRandomSpawnPoint( + Zones.sanctuaryZoneNumber(player.Faction), + player.Faction, + Seq(SpawnGroup.Sanctuary), + context.self + ) + }) + } } def handleInstantAction(): Unit = { - player.ZoningRequest = Zoning.Method.InstantAction - zoningType = Zoning.Method.InstantAction - zoningChatMessageType = ChatMessageType.CMT_INSTANTACTION - zoningStatus = Zoning.Status.Request - cluster ! ICS.GetInstantActionSpawnPoint(player.Faction, context.self) + if (player.Carrying.contains(SpecialCarry.CaptureFlag)) { + CancelZoningProcessWithDescriptiveReason("cancel") + } + else { + player.ZoningRequest = Zoning.Method.InstantAction + zoningType = Zoning.Method.InstantAction + zoningChatMessageType = ChatMessageType.CMT_INSTANTACTION + zoningStatus = Zoning.Status.Request + cluster ! ICS.GetInstantActionSpawnPoint(player.Faction, context.self) + } } def handleQuit(): Unit = { - //priority is given to quit over other zoning methods - if (session.zoningType == Zoning.Method.InstantAction || session.zoningType == Zoning.Method.Recall) { + if (player.Carrying.contains(SpecialCarry.CaptureFlag)) { CancelZoningProcessWithDescriptiveReason("cancel") } - player.ZoningRequest = Zoning.Method.Quit - zoningType = Zoning.Method.Quit - zoningChatMessageType = ChatMessageType.CMT_QUIT - zoningStatus = Zoning.Status.Request - beginZoningCountdown(() => { - log.info(s"Good-bye, ${player.Name}") - sessionLogic.immediateDisconnect() - }) + else { + //priority is given to quit over other zoning methods + if (session.zoningType == Zoning.Method.InstantAction || session.zoningType == Zoning.Method.Recall) { + CancelZoningProcessWithDescriptiveReason("cancel") + } + player.ZoningRequest = Zoning.Method.Quit + zoningType = Zoning.Method.Quit + zoningChatMessageType = ChatMessageType.CMT_QUIT + zoningStatus = Zoning.Status.Request + beginZoningCountdown(() => { + log.info(s"Good-bye, ${player.Name}") + sessionLogic.immediateDisconnect() + }) + } } def handleSetZone(zoneId: String, position: Vector3): Unit = { diff --git a/src/main/scala/net/psforever/objects/serverobject/structures/participation/MajorFacilityHackParticipation.scala b/src/main/scala/net/psforever/objects/serverobject/structures/participation/MajorFacilityHackParticipation.scala index 57129894a..29fd9a7c3 100644 --- a/src/main/scala/net/psforever/objects/serverobject/structures/participation/MajorFacilityHackParticipation.scala +++ b/src/main/scala/net/psforever/objects/serverobject/structures/participation/MajorFacilityHackParticipation.scala @@ -24,6 +24,7 @@ import scala.concurrent.Future final case class MajorFacilityHackParticipation(building: Building) extends FacilityHackParticipation { private implicit val timeout: Timeout = 10.seconds + private val log = org.log4s.getLogger private var hotSpotLayersOverTime: Seq[List[HotSpotInfo]] = Seq[List[HotSpotInfo]]() @@ -174,6 +175,8 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci val playersInSoi = building.PlayersInSOI.filter { _.Faction == victorFaction } + log.info(s"Facility Capture Event - Was Resecure: $isResecured, Victor: $victorFaction, Opposing: $failSafeOpposingFaction, " + + s"Victor Size: $contributionVictorSize, Opposing Size: $contributionOpposingSize, Experience: $baseExperienceFromFacilityCapture") if (baseExperienceFromFacilityCapture > 0) { //2) population modifier //The value of the first should grow as population grows. diff --git a/src/main/scala/net/psforever/objects/vehicles/control/VehicleControl.scala b/src/main/scala/net/psforever/objects/vehicles/control/VehicleControl.scala index d1d2a355e..64246df94 100644 --- a/src/main/scala/net/psforever/objects/vehicles/control/VehicleControl.scala +++ b/src/main/scala/net/psforever/objects/vehicles/control/VehicleControl.scala @@ -4,6 +4,7 @@ package net.psforever.objects.vehicles.control import akka.actor.Cancellable import net.psforever.actors.zone.ZoneActor import net.psforever.objects._ +import net.psforever.objects.avatar.SpecialCarry import net.psforever.objects.definition.{VehicleDefinition, WithShields} import net.psforever.objects.definition.converter.OCM import net.psforever.objects.entity.WorldEntity @@ -21,6 +22,7 @@ import net.psforever.objects.serverobject.environment.interaction.{InteractWithE import net.psforever.objects.serverobject.hackable.GenericHackables import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior, RadiationInMountableInteraction} import net.psforever.objects.serverobject.repair.RepairableVehicle +import net.psforever.objects.serverobject.structures.WarpGate import net.psforever.objects.serverobject.terminals.Terminal import net.psforever.objects.serverobject.turret.auto.AffectedByAutomaticTurretFire import net.psforever.objects.sourcing.{PlayerSource, SourceEntry, VehicleSource} @@ -122,6 +124,14 @@ class VehicleControl(vehicle: Vehicle) if vehicle.DeploymentState == DriveState.AutoPilot => sender() ! Mountable.MountMessages(user, Mountable.CanNotMount(vehicle, mountPoint)) + case Mountable.TryMount(user, mountPoint) + if vehicle.Zone.blockMap.sector(vehicle).buildingList.exists { + case wg: WarpGate => + Vector3.DistanceSquared(vehicle.Position, wg.Position) < math.pow(wg.Definition.SOIRadius, 2) + case _ => false + } && user.Carrying.contains(SpecialCarry.CaptureFlag) => + sender() ! Mountable.MountMessages(user, Mountable.CanNotMount(vehicle, mountPoint)) + case msg @ Mountable.TryMount(player, mount_point) => mountBehavior.apply(msg) mountCleanup(mount_point, player) diff --git a/src/main/scala/net/psforever/services/local/support/CaptureFlagManager.scala b/src/main/scala/net/psforever/services/local/support/CaptureFlagManager.scala index e6450a7a8..0760ac269 100644 --- a/src/main/scala/net/psforever/services/local/support/CaptureFlagManager.scala +++ b/src/main/scala/net/psforever/services/local/support/CaptureFlagManager.scala @@ -284,8 +284,8 @@ object CaptureFlagManager { .GUID(flagGuid) .collect { case flag: CaptureFlag - if LoseFlagViolentlyToEnvironment(target, Set(EnvironmentAttribute.Water, EnvironmentAttribute.Lava, EnvironmentAttribute.Death)) || - LoseFlagViolentlyToWarpGateEnvelope(zone, target) => + if LoseFlagViolentlyToEnvironment(target, Set(EnvironmentAttribute.Water, EnvironmentAttribute.Lava, EnvironmentAttribute.Death)) /*|| + LoseFlagViolentlyToWarpGateEnvelope(zone, target)*/ => flag.Destroyed = true zone.LocalEvents ! LocalServiceMessage("", LocalAction.LluLost(flag)) true From c4d164e3fba6558426cd7414cb84d73e02af6267 Mon Sep 17 00:00:00 2001 From: ScrawnyRonnie Date: Sat, 6 Dec 2025 16:46:34 -0500 Subject: [PATCH 2/3] wall turrets ignore walking max --- .../net/psforever/actors/session/normal/GeneralLogic.scala | 4 ++++ .../actors/session/support/ZoningOperations.scala | 1 + src/main/scala/net/psforever/objects/Player.scala | 1 + .../net/psforever/objects/equipment/EffectTarget.scala | 7 ++++--- .../net/psforever/packet/game/GenericActionMessage.scala | 2 ++ 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala index 2041d88d6..449980c49 100644 --- a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala @@ -586,6 +586,10 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex if (avatar.lookingForSquad && (sessionLogic.squad.squadUI.isEmpty || sessionLogic.squad.squadUI(player.CharId).index == 0)) { avatarActor ! AvatarActor.SetLookingForSquad(false) } + case GenericAction.MaxEnableAutoRun => + player.maxAutoRunEnabled = true + case GenericAction.MaxDisableAutoRun => + player.maxAutoRunEnabled = false case _ => log.warn(s"GenericActionMessage: ${player.Name} can't handle $action") } 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 6a467e262..11f039ee9 100644 --- a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala @@ -2221,6 +2221,7 @@ class ZoningOperations( if (zoningStatus == Zoning.Status.Deconstructing) { stopDeconstructing() } + player.maxAutoRunEnabled = false //reset flag in case max ran through a direct gate sessionLogic.avatarResponse.lastSeenStreamMessage.clear() upstreamMessageCount = 0 setAvatar = false diff --git a/src/main/scala/net/psforever/objects/Player.scala b/src/main/scala/net/psforever/objects/Player.scala index 1099c5bdf..e84a88baf 100644 --- a/src/main/scala/net/psforever/objects/Player.scala +++ b/src/main/scala/net/psforever/objects/Player.scala @@ -89,6 +89,7 @@ class Player(var avatar: Avatar) var outfit_id: Long = 0 var outfit_window_open: Boolean = false var outfit_list_open: Boolean = false + var maxAutoRunEnabled: Boolean = false /** From PlanetsideAttributeMessage */ var PlanetsideAttribute: Array[Long] = Array.ofDim(120) diff --git a/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala b/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala index 689fcf652..53aecdb94 100644 --- a/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala +++ b/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala @@ -282,8 +282,8 @@ object EffectTarget { def FacilityTurretValidateMaxTarget(target: PlanetSideGameObject): Boolean = target match { case p: Player - if p.ExoSuit == ExoSuitType.MAX && p.VehicleSeated.isEmpty => - val now = System.currentTimeMillis() + if p.ExoSuit == ExoSuitType.MAX && p.VehicleSeated.isEmpty && p.maxAutoRunEnabled => + /* val now = System.currentTimeMillis() val pos = p.Position val faction = p.Faction val sector = p.Zone.blockMap.sector(p.Position, range = 51f) @@ -293,7 +293,8 @@ object EffectTarget { if (radarCloakedAms(sector, pos) || radarCloakedAegis(sector, pos)) false else if (radarCloakedSensor(sector, pos, faction)) entityTookDamage(p, now) || usedEquipment else if (radarEnhancedInterlink(sector, pos, faction)) true - else p.isMoving(test = 15.5d) + else p.isMoving(test = 15.5d) */ + true case _ => false } diff --git a/src/main/scala/net/psforever/packet/game/GenericActionMessage.scala b/src/main/scala/net/psforever/packet/game/GenericActionMessage.scala index 39111f51a..1a50426ce 100644 --- a/src/main/scala/net/psforever/packet/game/GenericActionMessage.scala +++ b/src/main/scala/net/psforever/packet/game/GenericActionMessage.scala @@ -21,6 +21,8 @@ object GenericAction extends IntEnum[GenericAction] { final case object NewCharacterBasicTrainingPrompt extends GenericAction(value = 14) final case object MaxAnchorsExtend_RCV extends GenericAction(value = 15) final case object MaxAnchorsRelease_RCV extends GenericAction(value = 16) + final case object MaxEnableAutoRun extends GenericAction(value = 17) + final case object MaxDisableAutoRun extends GenericAction(value = 18) final case object MaxSpecialEffect_RCV extends GenericAction(value = 20) final case object StopMaxSpecialEffect_RCV extends GenericAction(value = 21) final case object CavernFacilityCapture extends GenericAction(value = 22) From fa9dc8e8f0413ab515edf59896037718148ac5aa Mon Sep 17 00:00:00 2001 From: ScrawnyRonnie Date: Sat, 6 Dec 2025 16:47:46 -0500 Subject: [PATCH 3/3] same for csr --- .../scala/net/psforever/actors/session/csr/GeneralLogic.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/scala/net/psforever/actors/session/csr/GeneralLogic.scala b/src/main/scala/net/psforever/actors/session/csr/GeneralLogic.scala index a920f4fed..f2b59f251 100644 --- a/src/main/scala/net/psforever/actors/session/csr/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/csr/GeneralLogic.scala @@ -524,6 +524,10 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex if (avatar.lookingForSquad) { avatarActor ! AvatarActor.SetLookingForSquad(false) } + case GenericAction.MaxEnableAutoRun => + player.maxAutoRunEnabled = true + case GenericAction.MaxDisableAutoRun => + player.maxAutoRunEnabled = false case _ => log.warn(s"GenericActionMessage: ${player.Name} can't handle $action") }