From 2b1d01c4bafb700658617720368dfe7e3b6467e2 Mon Sep 17 00:00:00 2001 From: ScrawnyRonnie Date: Mon, 28 Jul 2025 21:26:39 -0400 Subject: [PATCH 1/2] misc animations and turret range --- .../actors/session/csr/GeneralLogic.scala | 5 +++++ .../actors/session/normal/GeneralLogic.scala | 5 +++++ .../session/normal/VehicleHandlerLogic.scala | 2 +- .../spectator/VehicleHandlerLogic.scala | 2 +- .../session/support/ZoningOperations.scala | 12 ++++++++--- .../damage/DamageableEntity.scala | 12 +++++++---- .../turret/auto/AutomatedTurretBehavior.scala | 21 +++++++++++++------ .../game/GenericObjectActionMessage.scala | 1 + .../avatar/support/CorpseRemovalActor.scala | 2 +- 9 files changed, 46 insertions(+), 16 deletions(-) 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 68f59b43..d9c76b6e 100644 --- a/src/main/scala/net/psforever/actors/session/csr/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/csr/GeneralLogic.scala @@ -33,6 +33,7 @@ import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game.{ActionCancelMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestMessage, ChatMsg, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeadState, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, InvalidTerrainMessage, LootItemMessage, MoveItemMessage, ObjectDetectedMessage, ObjectHeldMessage, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, RequestDestroyMessage, TargetingImplantRequest, TerrainCondition, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage} import net.psforever.services.RemoverActor import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage} +import net.psforever.services.local.{LocalAction, LocalServiceMessage} import net.psforever.types.{CapacitorStateType, ChatMessageType, Cosmetic, ExoSuitType, PlanetSideEmpire, PlanetSideGUID, Vector3} import scala.util.Success @@ -181,7 +182,11 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex def handleEmote(pkt: EmoteMsg): Unit = { val EmoteMsg(avatarGuid, emote) = pkt + val pZone = player.Zone sendResponse(EmoteMsg(avatarGuid, emote)) + pZone.blockMap.sector(player).livePlayerList.collect { case t if t.GUID != player.GUID => + pZone.LocalEvents ! LocalServiceMessage(t.Name, LocalAction.SendResponse(EmoteMsg(avatarGuid, emote))) + } } def handleDropItem(pkt: DropItemMessage): Unit = { 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 fdfa1c9b..23e9d38e 100644 --- a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala @@ -40,6 +40,7 @@ import net.psforever.packet.PlanetSideGamePacket import net.psforever.packet.game.{ActionCancelMessage, ActionResultMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestAction, CharacterRequestMessage, ChatMsg, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeadState, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, InvalidTerrainMessage, LootItemMessage, MoveItemMessage, ObjectDetectedMessage, ObjectHeldMessage, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, RequestDestroyMessage, TargetingImplantRequest, TerrainCondition, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage} import net.psforever.services.account.{AccountPersistenceService, RetrieveAccountData} import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage} +import net.psforever.services.local.{LocalAction, LocalServiceMessage} import net.psforever.services.local.support.CaptureFlagManager import net.psforever.types.{CapacitorStateType, ChatMessageType, Cosmetic, ExoSuitType, ImplantType, PlanetSideEmpire, PlanetSideGUID, Vector3} import net.psforever.util.Config @@ -199,7 +200,11 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex def handleEmote(pkt: EmoteMsg): Unit = { val EmoteMsg(avatarGuid, emote) = pkt + val pZone = player.Zone sendResponse(EmoteMsg(avatarGuid, emote)) + pZone.blockMap.sector(player).livePlayerList.collect { case t if t.GUID != player.GUID => + pZone.LocalEvents ! LocalServiceMessage(t.Name, LocalAction.SendResponse(EmoteMsg(avatarGuid, emote))) + } } def handleDropItem(pkt: DropItemMessage): Unit = { 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 64a7a67a..f6102ded 100644 --- a/src/main/scala/net/psforever/actors/session/normal/VehicleHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/VehicleHandlerLogic.scala @@ -231,7 +231,7 @@ class VehicleHandlerLogic(val ops: SessionVehicleHandlers, implicit val context: sendResponse(ObjectCreateDetailedMessage(itemType, itemGuid, ObjectCreateMessageParent(vehicleGuid, slot), itemData)) case VehicleResponse.UnloadVehicle(_, vehicleGuid) => - sendResponse(ObjectDeleteMessage(vehicleGuid, unk1=0)) + sendResponse(ObjectDeleteMessage(vehicleGuid, unk1=1)) if (sessionLogic.zoning.spawn.prevSpawnPoint.map(_.Owner).exists { case ams: Vehicle => ams.GUID == vehicleGuid && diff --git a/src/main/scala/net/psforever/actors/session/spectator/VehicleHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/spectator/VehicleHandlerLogic.scala index ac930161..d68308a6 100644 --- a/src/main/scala/net/psforever/actors/session/spectator/VehicleHandlerLogic.scala +++ b/src/main/scala/net/psforever/actors/session/spectator/VehicleHandlerLogic.scala @@ -197,7 +197,7 @@ class VehicleHandlerLogic(val ops: SessionVehicleHandlers, implicit val context: sendResponse(PlanetsideAttributeMessage(vehicleGuid, seatGroup, permission)) case VehicleResponse.UnloadVehicle(_, vehicleGuid) => - sendResponse(ObjectDeleteMessage(vehicleGuid, unk1=0)) + sendResponse(ObjectDeleteMessage(vehicleGuid, unk1=1)) 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/ZoningOperations.scala b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala index fd7e3145..f46ba318 100644 --- a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala @@ -18,7 +18,8 @@ import net.psforever.objects.serverobject.turret.auto.AutomatedTurret import net.psforever.objects.sourcing.{PlayerSource, SourceEntry, VehicleSource} import net.psforever.objects.vital.{InGameHistory, IncarnationActivity, ReconstructionActivity, SpawningActivity} import net.psforever.objects.zones.blockmap.BlockMapEntity -import net.psforever.packet.game.{CampaignStatistic, ChangeFireStateMessage_Start, HackState7, MailMessage, ObjectDetectedMessage, SessionStatistic, TriggeredSound, WeatherMessage, CloudInfo, StormInfo} +import net.psforever.packet.game.GenericAction.FirstPersonViewWithEffect +import net.psforever.packet.game.{CampaignStatistic, ChangeFireStateMessage_Start, CloudInfo, GenericActionMessage, GenericObjectActionEnum, HackState7, MailMessage, ObjectDetectedMessage, SessionStatistic, StormInfo, TriggeredSound, WeatherMessage} import net.psforever.services.chat.DefaultChannel import scala.collection.mutable @@ -2972,10 +2973,10 @@ class ZoningOperations( case _ if player.HasGUID => // player is deconstructing self or instant action val player_guid = player.GUID - sendResponse(ObjectDeleteMessage(player_guid, 4)) + sendResponse(ObjectDeleteMessage(player_guid, unk1=1)) continent.AvatarEvents ! AvatarServiceMessage( continent.id, - AvatarAction.ObjectDelete(player_guid, player_guid, 4) + AvatarAction.ObjectDelete(player_guid, player_guid, unk=1) ) InGameHistory.SpawnReconstructionActivity(player, toZoneNumber, betterSpawnPoint) LoadZoneAsPlayerUsing(player, pos, ori, toSide, zoneId) @@ -3776,6 +3777,11 @@ class ZoningOperations( player.death_by = 1 } GoToDeploymentMap() + val pZone = player.Zone + sendResponse(GenericActionMessage(FirstPersonViewWithEffect)) + pZone.blockMap.sector(player).livePlayerList.collect { case t if t.GUID != player.GUID => + pZone.LocalEvents ! LocalServiceMessage(t.Name, LocalAction.SendGenericObjectActionMessage(t.GUID, player.GUID, GenericObjectActionEnum.PlayerDeconstructs)) + } } def stopDeconstructing(): Unit = { diff --git a/src/main/scala/net/psforever/objects/serverobject/damage/DamageableEntity.scala b/src/main/scala/net/psforever/objects/serverobject/damage/DamageableEntity.scala index b3d74ac1..e594de2d 100644 --- a/src/main/scala/net/psforever/objects/serverobject/damage/DamageableEntity.scala +++ b/src/main/scala/net/psforever/objects/serverobject/damage/DamageableEntity.scala @@ -2,6 +2,7 @@ package net.psforever.objects.serverobject.damage import net.psforever.objects.equipment.JammableUnit +import net.psforever.objects.serverobject.tube.SpawnTube import net.psforever.objects.vital.interaction.DamageResult import net.psforever.objects.vital.resolution.ResolutionCalculations import net.psforever.objects.zones.Zone @@ -199,9 +200,12 @@ object DamageableEntity { val tguid = target.GUID val attribution = attributionTo(cause, target.Zone) zone.AvatarEvents ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(tguid, 0, target.Health)) - zone.AvatarEvents ! AvatarServiceMessage( - zoneId, - AvatarAction.Destroy(tguid, attribution, Service.defaultPlayerGUID, target.Position) - ) + if (target.isInstanceOf[SpawnTube]) {}//do nothing to prevent issue #1057 + else { + zone.AvatarEvents ! AvatarServiceMessage( + zoneId, + AvatarAction.Destroy(tguid, attribution, Service.defaultPlayerGUID, target.Position) + ) + } } } diff --git a/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala b/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala index fad4c5c3..cd116dfd 100644 --- a/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala +++ b/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala @@ -205,7 +205,8 @@ trait AutomatedTurretBehavior { val now = System.currentTimeMillis() if ( currentTargetToken.isEmpty && - target.Faction != AutomatedTurretObject.Faction + target.Faction != AutomatedTurretObject.Faction && + now >= currentTargetLastShotTime ) { currentTargetLastShotTime = now currentTargetLocation = Some(target.Position) @@ -215,11 +216,19 @@ trait AutomatedTurretBehavior { true } else if ( currentTargetToken.contains(SourceUniqueness(target)) && - now - currentTargetLastShotTime < autoStats.map(_.cooldowns.missedShot).getOrElse(0L)) { - currentTargetLastShotTime = now - currentTargetLocation = Some(target.Position) - cancelSelfReportedAutoFire() - true + now - currentTargetLastShotTime < autoStats.map(_.cooldowns.missedShot).getOrElse(0L) + ) { + val escapeRange = autoStats.map(_.ranges.escape).getOrElse(400f) + val distSq = Vector3.DistanceSquared(target.Position, AutomatedTurretObject.Position) + val escapeSq = escapeRange * escapeRange + if (distSq <= escapeSq) { + currentTargetLastShotTime = now + currentTargetLocation = Some(target.Position) + cancelSelfReportedAutoFire() + true + } else { + false + } } else { false } diff --git a/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala b/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala index 916ee031..aa71a534 100644 --- a/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala +++ b/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala @@ -91,4 +91,5 @@ object GenericObjectActionEnum extends Enumeration { * Target: CaptureTerminal */ val FlagSpawned = Value(14) + val PlayerDeconstructs = Value(6) } diff --git a/src/main/scala/net/psforever/services/avatar/support/CorpseRemovalActor.scala b/src/main/scala/net/psforever/services/avatar/support/CorpseRemovalActor.scala index 062c7f15..974f0b68 100644 --- a/src/main/scala/net/psforever/services/avatar/support/CorpseRemovalActor.scala +++ b/src/main/scala/net/psforever/services/avatar/support/CorpseRemovalActor.scala @@ -25,7 +25,7 @@ class CorpseRemovalActor extends RemoverActor() { entry.zone.Population ! Zone.Corpse.Remove(entry.obj.asInstanceOf[Player]) context.parent ! AvatarServiceMessage( entry.zone.id, - AvatarAction.ObjectDelete(Service.defaultPlayerGUID, entry.obj.GUID) + AvatarAction.ObjectDelete(Service.defaultPlayerGUID, entry.obj.GUID, unk=1) ) } From aa31d6e3954074a10e0ecaf7fd704c746a96c868 Mon Sep 17 00:00:00 2001 From: ScrawnyRonnie Date: Wed, 30 Jul 2025 10:39:50 -0400 Subject: [PATCH 2/2] gm sees anims and crouch bfr --- .../actors/session/csr/GeneralLogic.scala | 3 +++ .../actors/session/normal/GeneralLogic.scala | 3 +++ .../session/support/ZoningOperations.scala | 3 +++ .../scala/net/psforever/objects/Vehicles.scala | 16 +++++++++++++++- .../packet/game/GenericObjectActionMessage.scala | 1 + 5 files changed, 25 insertions(+), 1 deletion(-) 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 d9c76b6e..2cd1782e 100644 --- a/src/main/scala/net/psforever/actors/session/csr/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/csr/GeneralLogic.scala @@ -187,6 +187,9 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex pZone.blockMap.sector(player).livePlayerList.collect { case t if t.GUID != player.GUID => pZone.LocalEvents ! LocalServiceMessage(t.Name, LocalAction.SendResponse(EmoteMsg(avatarGuid, emote))) } + pZone.AllPlayers.collect { case t if t.GUID != player.GUID && !t.allowInteraction => + pZone.LocalEvents ! LocalServiceMessage(t.Name, LocalAction.SendResponse(EmoteMsg(avatarGuid, emote))) + } } def handleDropItem(pkt: DropItemMessage): Unit = { 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 23e9d38e..99cf5103 100644 --- a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala +++ b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala @@ -205,6 +205,9 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex pZone.blockMap.sector(player).livePlayerList.collect { case t if t.GUID != player.GUID => pZone.LocalEvents ! LocalServiceMessage(t.Name, LocalAction.SendResponse(EmoteMsg(avatarGuid, emote))) } + pZone.AllPlayers.collect { case t if t.GUID != player.GUID && !t.allowInteraction => + pZone.LocalEvents ! LocalServiceMessage(t.Name, LocalAction.SendResponse(EmoteMsg(avatarGuid, emote))) + } } def handleDropItem(pkt: DropItemMessage): Unit = { 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 f46ba318..c2404d29 100644 --- a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala @@ -3782,6 +3782,9 @@ class ZoningOperations( pZone.blockMap.sector(player).livePlayerList.collect { case t if t.GUID != player.GUID => pZone.LocalEvents ! LocalServiceMessage(t.Name, LocalAction.SendGenericObjectActionMessage(t.GUID, player.GUID, GenericObjectActionEnum.PlayerDeconstructs)) } + pZone.AllPlayers.collect { case t if t.GUID != player.GUID && !t.allowInteraction => + pZone.LocalEvents ! LocalServiceMessage(t.Name, LocalAction.SendGenericObjectActionMessage(t.GUID, player.GUID, GenericObjectActionEnum.PlayerDeconstructs)) + } } def stopDeconstructing(): Unit = { diff --git a/src/main/scala/net/psforever/objects/Vehicles.scala b/src/main/scala/net/psforever/objects/Vehicles.scala index 259dc284..019f4d7f 100644 --- a/src/main/scala/net/psforever/objects/Vehicles.scala +++ b/src/main/scala/net/psforever/objects/Vehicles.scala @@ -10,7 +10,7 @@ import net.psforever.objects.serverobject.transfer.TransferContainer import net.psforever.objects.serverobject.structures.WarpGate import net.psforever.objects.vehicles._ import net.psforever.objects.zones.Zone -import net.psforever.packet.game.{ChatMsg, HackMessage, HackState, HackState1, HackState7, TriggeredSound} +import net.psforever.packet.game.{ChatMsg, FrameVehicleStateMessage, GenericObjectActionEnum, GenericObjectActionMessage, HackMessage, HackState, HackState1, HackState7, TriggeredSound, VehicleStateMessage} import net.psforever.types.{ChatMessageType, DriveState, PlanetSideEmpire, PlanetSideGUID, Vector3} import net.psforever.services.Service import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage} @@ -274,6 +274,20 @@ object Vehicles { VehicleAction.KickPassenger(player.GUID, 4, unk2 = false, tGuid) ) } + // In case BFR is occupied and may or may not be crouched + if (GlobalDefinitions.isBattleFrameVehicle(target.Definition) && target.Seat(0).isDefined) { + zone.LocalEvents ! LocalServiceMessage( + zoneid, + LocalAction.SendGenericObjectActionMessage(PlanetSideGUID(-1), target.GUID, GenericObjectActionEnum.BFRShieldsDown)) + zone.LocalEvents ! LocalServiceMessage( + zoneid, + LocalAction.SendResponse( + FrameVehicleStateMessage(target.GUID, 0, target.Position, target.Orientation, Some(Vector3(0f, 0f, 0f)), unk2=false, 0, 0, is_crouched=true, is_airborne=false, ascending_flight=false, 10, 0, 0))) + zone.LocalEvents ! LocalServiceMessage( + zoneid, + LocalAction.SendResponse( + VehicleStateMessage(target.GUID, 0, target.Position, target.Orientation, Some(Vector3(0f, 0f, 0f)), None, 0, 0, 15, is_decelerating=false, is_cloaked=false))) + } }) // If the vehicle can fly and is flying: deconstruct it; and well played to whomever managed to hack a plane in mid air if (target.Definition.CanFly && target.isFlying) { diff --git a/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala b/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala index aa71a534..8d4b7e4c 100644 --- a/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala +++ b/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala @@ -92,4 +92,5 @@ object GenericObjectActionEnum extends Enumeration { */ val FlagSpawned = Value(14) val PlayerDeconstructs = Value(6) + val BFRShieldsDown = Value(45) }