From cf8faa207dc3ecab993bbd159618cd9cacb6ed75 Mon Sep 17 00:00:00 2001 From: FateJH Date: Fri, 13 Dec 2019 23:42:02 -0500 Subject: [PATCH] test jammering of avatars --- .../psforever/objects/GlobalDefinitions.scala | 46 +++--- .../objects/equipment/JammingUnit.scala | 4 +- .../src/main/scala/WorldSessionActor.scala | 139 +++++++++++++----- 3 files changed, 124 insertions(+), 65 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index e00ecab5..0a69c556 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -2688,12 +2688,12 @@ object GlobalDefinitions { jammer_cartridge_projectile.Lifespan = 15f jammer_cartridge_projectile.AdditionalEffect = true jammer_cartridge_projectile.JammerProjectile = true - jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> (1 seconds) - jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> (5 seconds) - jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> (30 seconds) - jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> (30 seconds) - jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> (30 seconds) - jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> (10 seconds) + jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> 1000 + jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> 5000 + jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> 30000 + jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> 30000 + jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> 30000 + jammer_cartridge_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> 10000 ProjectileDefinition.CalculateDerivedFields(jammer_cartridge_projectile) jammer_cartridge_projectile_b.Name = "jammer_cartridge_projectile_b" @@ -2707,12 +2707,12 @@ object GlobalDefinitions { jammer_cartridge_projectile_b.Lifespan = 2f jammer_cartridge_projectile_b.AdditionalEffect = true jammer_cartridge_projectile_b.JammerProjectile = true - jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> (1 seconds) - jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> (5 seconds) - jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> (30 seconds) - jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> (30 seconds) - jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> (30 seconds) - jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> (10 seconds) + jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> 1000 + jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> 5000 + jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> 30000 + jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> 30000 + jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> 30000 + jammer_cartridge_projectile_b.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> 10000 ProjectileDefinition.CalculateDerivedFields(jammer_cartridge_projectile_b) jammer_grenade_projectile.Name = "jammer_grenade_projectile" @@ -2725,12 +2725,12 @@ object GlobalDefinitions { jammer_grenade_projectile.Lifespan = 15f jammer_grenade_projectile.AdditionalEffect = true jammer_grenade_projectile.JammerProjectile = true - jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> (1 seconds) - jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> (5 seconds) - jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> (30 seconds) - jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> (30 seconds) - jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> (30 seconds) - jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> (10 seconds) + jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> 1000 + jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> 5000 + jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> 30000 + jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> 30000 + jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> 30000 + jammer_grenade_projectile.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.VehicleNotAMS) -> 10000 ProjectileDefinition.CalculateDerivedFields(jammer_grenade_projectile) jammer_grenade_projectile_enh.Name = "jammer_grenade_projectile_enh" @@ -2744,11 +2744,11 @@ object GlobalDefinitions { jammer_grenade_projectile_enh.Lifespan = 3f jammer_grenade_projectile_enh.AdditionalEffect = true jammer_grenade_projectile_enh.JammerProjectile = true - jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> (1 seconds) - jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> (5 seconds) - jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> (30 seconds) - jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> (30 seconds) - jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> (30 seconds) + jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) -> 1000 + jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.AMS) -> 5000 + jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.MotionSensor) -> 30000 + jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Deployable, EffectTarget.Validation.Spitfire) -> 30000 + jammer_grenade_projectile_enh.JammedEffectDuration += TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret) -> 30000 ProjectileDefinition.CalculateDerivedFields(jammer_grenade_projectile_enh) katana_projectile.Name = "katana_projectile" diff --git a/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala b/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala index c336ec15..1bd54684 100644 --- a/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala +++ b/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala @@ -7,9 +7,9 @@ import scala.collection.mutable import scala.concurrent.duration.Duration trait JammingUnit { - private val jammedEffectDuration : mutable.ListBuffer[(TargetValidation, Duration)] = new mutable.ListBuffer() + private val jammedEffectDuration : mutable.ListBuffer[(TargetValidation, Int)] = new mutable.ListBuffer() def HasJammedEffectDuration : Boolean = jammedEffectDuration.isEmpty - def JammedEffectDuration : mutable.ListBuffer[(TargetValidation, Duration)] = jammedEffectDuration + def JammedEffectDuration : mutable.ListBuffer[(TargetValidation, Int)] = jammedEffectDuration } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index a2865e5f..6033140a 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -151,8 +151,10 @@ class WorldSessionActor extends Actor with MDCContextAware { var timeDL : Long = 0 var timeSurge : Long = 0 + var skipStaminaRegenForTurns : Int = 0 lazy val unsignedIntMaxValue : Long = Int.MaxValue.toLong * 2L + 1L var serverTime : Long = 0 + var jammeredEquipment : Seq[PlanetSideGUID] = Nil var amsSpawnPoints : List[SpawnPoint] = Nil var clientKeepAlive : Cancellable = DefaultCancellable.obj @@ -163,6 +165,8 @@ class WorldSessionActor extends Actor with MDCContextAware { var cargoDismountTimer : Cancellable = DefaultCancellable.obj var antChargingTick : Cancellable = DefaultCancellable.obj var antDischargingTick : Cancellable = DefaultCancellable.obj + var jammeredSoundTimer : Cancellable = DefaultCancellable.obj + var jammeredStatusTimer : Cancellable = DefaultCancellable.obj /** @@ -1179,6 +1183,12 @@ class WorldSessionActor extends Actor with MDCContextAware { case _ => ; } + case ClearJammeredSound() => + CancelJammeredSound() + + case ClearJammeredStatus() => + CancelJammeredStatus() + case default => log.warn(s"Invalid packet class received: $default from $sender") } @@ -1325,8 +1335,24 @@ class WorldSessionActor extends Actor with MDCContextAware { val radius = cause.projectile.profile.DamageRadius FindJammerDuration(cause.projectile.profile, target) match { case Some(dur) if Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius => - //TODO jammer messaging here + //implants + DeactivateImplants() + //jammered sound sendResponse(PlanetsideAttributeMessage(player.GUID, 54, 1)) + continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 54, 1)) + import scala.concurrent.ExecutionContext.Implicits.global + jammeredSoundTimer = context.system.scheduler.scheduleOnce(30 seconds, self, ClearJammeredSound()) + //jammered status + skipStaminaRegenForTurns = 5 + sendResponse(PlanetsideAttributeMessage(player.GUID, 2, 0)) + jammeredEquipment = player.Holsters() + .map { _.Equipment } + .collect { + case Some(item) if item.Size != EquipmentSize.Melee => + sendResponse(GenericObjectActionMessage(item.GUID, 156)) + item.GUID + } + jammeredStatusTimer = context.system.scheduler.scheduleOnce(dur milliseconds, self, ClearJammeredStatus()) case _ => ; } } @@ -3897,6 +3923,7 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ PlayerStateMessageUpstream(avatar_guid, pos, vel, yaw, pitch, yaw_upper, seq_time, unk3, is_crouching, is_jumping, jump_thrust, is_cloaking, unk5, unk6) => val isMoving = WorldEntity.isMoving(vel) + val isMovingPlus = isMoving || is_jumping || jump_thrust //implants and stamina management start val implantsAreActive = avatar.Implants(0).Active || avatar.Implants(1).Active val staminaBefore = player.Stamina @@ -3928,14 +3955,23 @@ class WorldSessionActor extends Actor with MDCContextAware { } } } - CapacitorTick(jump_thrust) - //if the player lost all stamina this turn (had stamina at the start), do not renew 1 stamina - if(!isMoving && (if(player.Stamina > 0) player.Stamina < player.MaxStamina else !hadStaminaBefore)) { - player.Stamina = player.Stamina + 1 - true + if(skipStaminaRegenForTurns > 0) { + //do not renew stamina for a while + skipStaminaRegenForTurns -= 1 + player.Stamina > 0 + } + else if(player.Stamina == 0 && hadStaminaBefore) { + //if the player lost all stamina this turn (had stamina at the start), do not renew stamina for a while + skipStaminaRegenForTurns = 4 + player.Stamina > 0 + } + else if(isMovingPlus || player.Stamina == player.MaxStamina) { + //ineligible for stamina regen + player.Stamina > 0 } else { - player.Stamina > 0 + player.Stamina = player.Stamina + 1 + true } } else { @@ -3947,18 +3983,7 @@ class WorldSessionActor extends Actor with MDCContextAware { sendResponse(PlanetsideAttributeMessage(player.GUID, 2, player.Stamina)) } if(implantsAreActive && !hasStaminaAfter) { //implants deactivated at 0 stamina - if(avatar.Implants(0).Active) { - avatar.Implants(0).Active = false - continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 28, avatar.Implant(0).id * 2)) - sendResponse(AvatarImplantMessage(PlanetSideGUID(player.GUID.guid), ImplantAction.Activation, 0, 0)) - timeDL = 0 - } - if(avatar.Implants(1).Active) { - avatar.Implants(1).Active = false - continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 28, avatar.Implant(1).id * 2)) - sendResponse(AvatarImplantMessage(PlanetSideGUID(player.GUID.guid), ImplantAction.Activation, 1, 0)) - timeSurge = 0 - } + DeactivateImplants() } //implants and stamina management finish player.Position = pos @@ -3968,8 +3993,9 @@ class WorldSessionActor extends Actor with MDCContextAware { player.Crouching = is_crouching player.Jumping = is_jumping player.Cloaked = player.ExoSuit == ExoSuitType.Infiltration && is_cloaking + CapacitorTick(jump_thrust) - if(isMoving && usingMedicalTerminal.isDefined) { + if(isMovingPlus && usingMedicalTerminal.isDefined) { continent.GUID(usingMedicalTerminal) match { case Some(term : Terminal with ProximityUnit) => StopUsingProximityUnit(term) @@ -3987,7 +4013,7 @@ class WorldSessionActor extends Actor with MDCContextAware { accessedContainer = None } case Some(container) => //just in case - if(isMoving) { + if(isMovingPlus) { val guid = player.GUID // If the container is a corpse and gets removed just as this runs it can cause a client disconnect, so we'll check the container has a GUID first. if(container.HasGUID) { @@ -4554,6 +4580,7 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ AvatarJumpMessage(state) => //log.info("AvatarJump: " + msg) player.Stamina = player.Stamina - 10 + skipStaminaRegenForTurns = 5 sendResponse(PlanetsideAttributeMessage(player.GUID, 2, player.Stamina)) case msg @ ZipLineMessage(player_guid,origin_side,action,id,pos) => @@ -7951,9 +7978,14 @@ class WorldSessionActor extends Actor with MDCContextAware { * This is not a complete list but, for the purpose of enforcement, some pointers will be documented here. */ def PlayerActionsToCancel() : Unit = { + if(!jammeredSoundTimer.isCancelled) { + CancelJammeredSound() + } + jammeredStatusTimer.cancel progressBarUpdate.cancel progressBarValue = None lastTerminalOrderFulfillment = true + skipStaminaRegenForTurns = 0 accessedContainer match { case Some(obj : Vehicle) => if(obj.AccessingTrunk.contains(player.GUID)) { @@ -8612,10 +8644,7 @@ class WorldSessionActor extends Actor with MDCContextAware { } /** - * Find a projectile with the given globally unique identifier and mark it as a resolved shot. - * A `Resolved` shot has either encountered an obstacle or is being cleaned up for not finding an obstacle. - * The internal copy of the projectile is retained as merely `Resolved` - * while the observed projectile is promoted to the suggested resolution status. + * na * @param projectile the projectile object * @param resolution the resolution status to promote the projectile * @return a copy of the projectile @@ -8626,21 +8655,11 @@ class WorldSessionActor extends Actor with MDCContextAware { None } else { - ResolveProjectileEntry(projectile, resolution, target, pos) + projectile.Resolve() + Some(ResolvedProjectile(resolution, projectile, SourceEntry(target), target.DamageModel, pos)) } } - /** - * na - * @param projectile the projectile object - * @param resolution the resolution status to promote the projectile - * @return a copy of the projectile - */ - def ResolveProjectileEntry(projectile : Projectile, resolution : ProjectileResolution.Value, target : PlanetSideGameObject with FactionAffinity with Vitality, pos : Vector3) : Option[ResolvedProjectile] = { - projectile.Resolve() - Some(ResolvedProjectile(resolution, projectile, SourceEntry(target), target.DamageModel, pos)) - } - /** * Common activities/procedure when a player mounts a valid object. * @param tplayer the player @@ -10380,18 +10399,54 @@ class WorldSessionActor extends Actor with MDCContextAware { } } - def FindJammerDuration(jammer : JammingUnit, target : PlanetSideGameObject) : Option[Duration] = { + def FindJammerDuration(jammer : JammingUnit, target : PlanetSideGameObject) : Option[Int] = { jammer.JammedEffectDuration .collect { case (TargetValidation(_, test), duration) if test(target) => duration } .toList - .sortWith(_.toMillis > _.toMillis) + .sortWith(_ > _) .headOption } - def FindJammerDuration(jammer : JammingUnit, targets : Seq[PlanetSideGameObject]) : Seq[Option[Duration]] = { + def FindJammerDuration(jammer : JammingUnit, targets : Seq[PlanetSideGameObject]) : Seq[Option[Int]] = { targets.map { target => FindJammerDuration(jammer, target) } } + def DeactivateImplants() : Unit = { + DeactivateImplantDarkLight() + DeactivateImplantSurge() + } + + def DeactivateImplantDarkLight() : Unit = { + if(avatar.Implants(0).Active) { + avatar.Implants(0).Active = false + continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 28, avatar.Implant(0).id * 2)) + sendResponse(AvatarImplantMessage(PlanetSideGUID(player.GUID.guid), ImplantAction.Activation, 0, 0)) + timeDL = 0 + } + } + + def DeactivateImplantSurge() : Unit = { + if(avatar.Implants(1).Active) { + avatar.Implants(1).Active = false + continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 28, avatar.Implant(1).id * 2)) + sendResponse(AvatarImplantMessage(PlanetSideGUID(player.GUID.guid), ImplantAction.Activation, 1, 0)) + timeSurge = 0 + } + } + + def CancelJammeredSound() : Unit = { + jammeredSoundTimer.cancel + sendResponse(PlanetsideAttributeMessage(player.GUID, 54, 0)) + continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 54, 0)) + } + + def CancelJammeredStatus() : Unit = { + if(!jammeredSoundTimer.isCancelled) { + CancelJammeredSound() + } + jammeredEquipment.foreach { id => sendResponse(GenericObjectActionMessage(id, 152)) } + jammeredEquipment = Nil + } def failWithError(error : String) = { log.error(error) @@ -10558,4 +10613,8 @@ object WorldSessionActor { private final case class FinalizeDeployable(obj : PlanetSideGameObject with Deployable, tool : ConstructionItem, index : Int) private final case class LoadedRemoteProjectile(projectile_guid : PlanetSideGUID, projectile : Option[Projectile]) + + private final case class ClearJammeredSound() + + private final case class ClearJammeredStatus() }