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 d0a6e8e96..cedba0624 100644 --- a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala @@ -118,11 +118,9 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex } } ops.fallHeightTracker(pos.z) - if (isCrouching && !player.Crouching) { - //dev stuff goes here - sendResponse(ChatMsg(ChatMessageType.UNK_229, "@PadDeconstruct_secsA^23~")) - sendResponse(ChatMsg(ChatMessageType.UNK_227, "@InventoryPickupNoRoom")) - } +// if (isCrouching && !player.Crouching) { +// //dev stuff goes here +// } player.Position = pos player.Velocity = vel player.Orientation = Vector3(player.Orientation.x, pitch, yaw) @@ -165,7 +163,9 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex case None => () } //llu destruction check - sessionLogic.localResponse.loseFlagViolently(ops.specialItemSlotGuid, player) + if (player.Carrying.contains(SpecialCarry.CaptureFlag)) { + CaptureFlagManager.reasonToLoseFlagViolently(continent, sessionLogic.general.specialItemSlotGuid, player) + } // val eagleEye: Boolean = ops.canSeeReallyFar val isNotVisible: Boolean = sessionLogic.zoning.zoningStatus == Zoning.Status.Deconstructing || 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 fa65279c8..5890402e8 100644 --- a/src/main/scala/net/psforever/actors/session/normal/VehicleHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/VehicleHandlerLogic.scala @@ -13,6 +13,7 @@ import net.psforever.objects.serverobject.pad.VehicleSpawnPad 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.local.support.CaptureFlagManager import net.psforever.services.vehicle.{VehicleResponse, VehicleServiceResponse} import net.psforever.types.{BailType, ChatMessageType, PlanetSideGUID, Vector3} @@ -63,11 +64,12 @@ class VehicleHandlerLogic(val ops: SessionVehicleHandlers, implicit val context: player.Orientation = orient player.Velocity = vel sessionLogic.updateLocalBlockMap(pos) + //llu destruction check if (player.Carrying.contains(SpecialCarry.CaptureFlag)) { continent .GUID(player.VehicleSeated) .collect { case vehicle: Vehicle => - sessionLogic.localResponse.loseFlagViolently(sessionLogic.general.specialItemSlotGuid, vehicle) + CaptureFlagManager.reasonToLoseFlagViolently(continent, sessionLogic.general.specialItemSlotGuid, vehicle) } } 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 deea975f9..f263e6600 100644 --- a/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/GeneralOperations.scala @@ -220,8 +220,12 @@ class GeneralOperations( ) } } - continent.LocalEvents ! CaptureFlagManager.DropFlag(llu) - case Some((llu, Some(carrier: Player))) if carrier.GUID == player.GUID => + if (!CaptureFlagManager.reasonToLoseFlagViolently(continent, Some(guid), player)) { + continent.LocalEvents ! CaptureFlagManager.DropFlag(llu) + } + case Some((llu, Some(carrier: Player))) + if carrier.GUID == player.GUID && + !CaptureFlagManager.reasonToLoseFlagViolently(continent, Some(guid), player) => continent.LocalEvents ! CaptureFlagManager.DropFlag(llu) case Some((_, Some(carrier: Player))) => log.warn(s"${player.toString} tried to drop LLU, but it is currently held by ${carrier.toString}") diff --git a/src/main/scala/net/psforever/actors/session/support/SessionLocalHandlers.scala b/src/main/scala/net/psforever/actors/session/support/SessionLocalHandlers.scala index 299fb750e..7706b54ee 100644 --- a/src/main/scala/net/psforever/actors/session/support/SessionLocalHandlers.scala +++ b/src/main/scala/net/psforever/actors/session/support/SessionLocalHandlers.scala @@ -52,40 +52,4 @@ class SessionLocalHandlers( else 400f } - - /** - * na - * @param target evaluate this to determine if to continue with this loss - * @return whether or not we are sufficiently submerged in water - */ - def wadingInWater(target: PlanetSideGameObject with InteractsWithZone): Boolean = { - target - .interaction() - .collectFirst { - case env: InteractWithEnvironment => - env - .Interactions - .get(EnvironmentAttribute.Water) - .collectFirst { - case water: Watery => water.Depth > 0f - } - } - .flatten - .contains(true) - } - - /** - * na - * @param flagGuid flag that may exist - * @param target evaluate this to determine if to continue with this loss - */ - def loseFlagViolently(flagGuid: Option[PlanetSideGUID], target: PlanetSideGameObject with InteractsWithZone): Unit = { - continent - .GUID(flagGuid) - .collect { - case flag: CaptureFlag if wadingInWater(target) => - flag.Destroyed = true - continent.LocalEvents ! LocalServiceMessage("", LocalAction.LluLost(flag)) - } - } } diff --git a/src/main/scala/net/psforever/objects/serverobject/environment/interaction/InteractWithEnvironment.scala b/src/main/scala/net/psforever/objects/serverobject/environment/interaction/InteractWithEnvironment.scala index 7b9f2e337..9cd84dd75 100644 --- a/src/main/scala/net/psforever/objects/serverobject/environment/interaction/InteractWithEnvironment.scala +++ b/src/main/scala/net/psforever/objects/serverobject/environment/interaction/InteractWithEnvironment.scala @@ -225,15 +225,13 @@ final case class AwaitOngoingInteraction(zone: Zone) extends InteractionBehavior if (allow) { val env = InteractWithEnvironment.checkAllEnvironmentInteractions(obj, sector) val (in, out) = existing.partition(body => InteractWithEnvironment.checkSpecificEnvironmentInteraction(zone, body, obj).nonEmpty) - val existAttrs = existing.map(_.attribute) val inAttrs = env.map(_.attribute) - env - .diff(in) - .filterNot(e => existAttrs.contains(e.attribute)) - .foreach(body => interactions.flatMap(_.get(body.attribute)).foreach(_.doInteractingWith(obj, body, None))) out .filterNot(e => inAttrs.contains(e.attribute)) .foreach(body => interactions.flatMap(_.get(body.attribute)).foreach(_.stopInteractingWith(obj, body, None))) + env + .diff(in) + .foreach(body => interactions.flatMap(_.get(body.attribute)).foreach(_.doInteractingWith(obj, body, None))) if (env.isEmpty) { val n = OnStableEnvironment() val out = n.perform(obj, sector, Set(), allow) diff --git a/src/main/scala/net/psforever/objects/serverobject/environment/interaction/common/Watery.scala b/src/main/scala/net/psforever/objects/serverobject/environment/interaction/common/Watery.scala index f29d3d47b..e08cd8b27 100644 --- a/src/main/scala/net/psforever/objects/serverobject/environment/interaction/common/Watery.scala +++ b/src/main/scala/net/psforever/objects/serverobject/environment/interaction/common/Watery.scala @@ -1,9 +1,12 @@ // Copyright (c) 2024 PSForever package net.psforever.objects.serverobject.environment.interaction.common +import net.psforever.objects.PlanetSideGameObject import net.psforever.objects.serverobject.PlanetSideServerObject +import net.psforever.objects.serverobject.environment.interaction.InteractWithEnvironment import net.psforever.objects.serverobject.environment.interaction.common.Watery.OxygenStateTarget import net.psforever.objects.serverobject.environment.{EnvironmentAttribute, EnvironmentTrait, PieceOfEnvironment} +import net.psforever.objects.zones.InteractsWithZone import net.psforever.types.{OxygenState, PlanetSideGUID} trait Watery { @@ -36,6 +39,27 @@ object Watery { progress: Float ) + /** + * na + * @param target evaluate this to determine if to continue with this loss + * @return whether or not we are sufficiently submerged in water + */ + def wading(target: PlanetSideGameObject with InteractsWithZone): Boolean = { + target + .interaction() + .collectFirst { + case env: InteractWithEnvironment => + env + .Interactions + .get(EnvironmentAttribute.Water) + .collectFirst { + case water: Watery => water.Depth > 0f + } + } + .flatten + .contains(true) + } + /** * Calculate the effect of being exposed to a watery environment beyond an entity's critical region. * @param obj the target diff --git a/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala b/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala index 1ea4b86a4..1b4195651 100644 --- a/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala +++ b/src/main/scala/net/psforever/objects/zones/ZoneVehicleActor.scala @@ -88,7 +88,7 @@ class ZoneVehicleActor( case Zone.Vehicle.CanNotDeploy(_, vehicle, toState, _) if vehicle.Definition == GlobalDefinitions.ams && - toState == DriveState.Deployed => + (toState == DriveState.Deploying || toState == DriveState.Deployed) => val pos = vehicle.Position zone.VehicleEvents ! VehicleServiceMessage( vehicle.Seats.headOption.flatMap(_._2.occupant).map(_.Name).getOrElse("Driver"), diff --git a/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala b/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala index 8c3177afd..c168e4a46 100644 --- a/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala +++ b/src/main/scala/net/psforever/packet/game/objectcreate/CharacterData.scala @@ -18,7 +18,6 @@ import shapeless.{::, HNil} object ImplantEffects extends Enumeration { type Type = Value - val SurgeEffects: ImplantEffects.Value = Value(9) val PersonalShieldEffects: ImplantEffects.Value = Value(5) val DarklightEffects: ImplantEffects.Value = Value(3) 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 103d98e9e..3f0426eb3 100644 --- a/src/main/scala/net/psforever/services/local/support/CaptureFlagManager.scala +++ b/src/main/scala/net/psforever/services/local/support/CaptureFlagManager.scala @@ -3,12 +3,13 @@ package net.psforever.services.local.support import akka.actor.{Actor, ActorRef, Cancellable} import net.psforever.login.WorldSession -import net.psforever.objects.{Default, Player} +import net.psforever.objects.{Default, PlanetSideGameObject, Player} import net.psforever.objects.guid.{GUIDTask, TaskWorkflow} +import net.psforever.objects.serverobject.environment.interaction.common.Watery import net.psforever.objects.serverobject.llu.CaptureFlag -import net.psforever.objects.serverobject.structures.Building +import net.psforever.objects.serverobject.structures.{Building, WarpGate} import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal -import net.psforever.objects.zones.Zone +import net.psforever.objects.zones.{InteractsWithZone, Zone} import net.psforever.packet.game._ import net.psforever.services.{Service, ServiceManager} import net.psforever.services.ServiceManager.{Lookup, LookupResult} @@ -166,8 +167,6 @@ class CaptureFlagManager(zone: Zone) extends Actor { } private def DoMapUpdate(): Unit = { - val events = zone.LocalEvents - val zoneId = zone.id val flagInfo = flags.map { case entry @ CaptureFlagManager.CaptureFlagEntry(flag) => val owner = flag.Owner.asInstanceOf[Building] val pos = flag.Position @@ -269,6 +268,38 @@ object CaptureFlagManager { CTF_Warning_NoCarrier(buildingName, flag.Faction, flag.Target.Name, time) } } + + /** + * na + * @param flagGuid flag that may exist + * @param target evaluate this to determine if to continue with this loss + */ + def reasonToLoseFlagViolently( + zone: Zone, + flagGuid: Option[PlanetSideGUID], + target: PlanetSideGameObject with InteractsWithZone + ): Boolean = { + zone + .GUID(flagGuid) + .collect { + case flag: CaptureFlag + if Watery.wading(target) || { + val position = target.Position + zone + .blockMap + .sector(position, range = 10f) + .buildingList + .collectFirst { + case gate: WarpGate if Vector3.DistanceSquared(position, gate.Position) < math.pow(gate.Definition.SOIRadius, 2f) => gate + } + .nonEmpty + } => + flag.Destroyed = true + zone.LocalEvents ! LocalServiceMessage("", LocalAction.LluLost(flag)) + true + } + .getOrElse(false) + } } object CaptureFlagChatMessageStrings {