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 9199f097..cbc58a62 100644
--- a/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala
+++ b/common/src/main/scala/net/psforever/objects/equipment/JammingUnit.scala
@@ -2,6 +2,7 @@
package net.psforever.objects.equipment
import net.psforever.objects.PlanetSideGameObject
+import net.psforever.objects.ballistics.ResolvedProjectile
import net.psforever.objects.serverobject.terminals.TargetValidation
import scala.collection.mutable
@@ -19,6 +20,12 @@ trait JammableUnit {
object JammableUnit {
final case class Jammer()
+
+ final case class Jammered(cause : ResolvedProjectile)
+
+ final case class ClearJammeredSound()
+
+ final case class ClearJammeredStatus()
}
trait JammingUnit {
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala
index 906e49b5..2d79b22e 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala
@@ -1,10 +1,24 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.turret
-import akka.actor.Actor
+import akka.actor.{Actor, Cancellable}
+import net.psforever.objects.{DefaultCancellable, Tool}
+import net.psforever.objects.ballistics.ResolvedProjectile
+import net.psforever.objects.equipment.{JammableUnit, JammingUnit}
+import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
+import net.psforever.objects.vehicles.MountedWeapons
import net.psforever.objects.vital.Vitality
+import net.psforever.objects.zones.Zone
+import net.psforever.packet.game.PlanetSideGUID
+import net.psforever.types.Vector3
+import services.Service
+import services.avatar.{AvatarAction, AvatarServiceMessage}
+import services.vehicle.{VehicleAction, VehicleServiceMessage}
+import services.vehicle.support.TurretUpgrader
+
+import scala.concurrent.duration._
/**
* An `Actor` that handles messages being dispatched to a specific `MannedTurret`.
@@ -17,6 +31,9 @@ import net.psforever.objects.vital.Vitality
class FacilityTurretControl(turret : FacilityTurret) extends Actor
with FactionAffinityBehavior.Check
with MountableBehavior.Dismount {
+ var jammeredSoundTimer : Cancellable = DefaultCancellable.obj
+ var jammeredStatusTimer : Cancellable = DefaultCancellable.obj
+
def MountableObject = turret //do not add type!
def FactionObject : FactionAffinity = turret
@@ -45,12 +62,149 @@ class FacilityTurretControl(turret : FacilityTurret) extends Actor
val cause = damage_func(turret)
val health = turret.Health
val damageToHealth = originalHealth - health
- val name = turret.Actor.toString
- val slashPoint = name.lastIndexOf("/")
- org.log4s.getLogger("DamageResolution").info(s"${name.substring(slashPoint+1, name.length-1)}: BEFORE=$originalHealth, AFTER=$health, CHANGE=$damageToHealth")
- sender ! Vitality.DamageResolution(turret, cause)
+ FacilityTurretControl.HandleDamageResolution(turret, cause, damageToHealth)
+ if(damageToHealth > 0) {
+ val name = turret.Actor.toString
+ val slashPoint = name.lastIndexOf("/")
+ org.log4s.getLogger("DamageResolution").info(s"${name.substring(slashPoint + 1, name.length - 1)}: BEFORE=$originalHealth, AFTER=$health, CHANGE=$damageToHealth")
+ }
}
+ case JammableUnit.Jammered(cause) =>
+ TryJammerWithProjectile(turret, cause)
+
+ case JammableUnit.ClearJammeredSound() =>
+ CancelJammeredSound(turret)
+
+ case JammableUnit.ClearJammeredStatus() =>
+ StopJammeredStatus(turret)
+
case _ => ;
}
+
+ def TryJammerWithProjectile(target : FacilityTurret, cause : ResolvedProjectile) : Unit = {
+ val radius = cause.projectile.profile.DamageRadius
+ JammingUnit.FindJammerDuration(cause.projectile.profile, target) match {
+ case Some(dur) if Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius =>
+ //jammered sound
+ target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 54, 1))
+ import scala.concurrent.ExecutionContext.Implicits.global
+ jammeredSoundTimer = context.system.scheduler.scheduleOnce(30 seconds, self, JammableUnit.ClearJammeredSound())
+ //jammered status
+ StartJammeredStatus(target, dur)
+ case _ => ;
+ }
+ }
+
+ def StartJammeredStatus(target : PlanetSideServerObject with MountedWeapons, dur : Int) : Unit = {
+ jammeredStatusTimer.cancel
+ FacilityTurretControl.JammeredStatus(target, 1)
+ import scala.concurrent.ExecutionContext.Implicits.global
+ jammeredStatusTimer = context.system.scheduler.scheduleOnce(dur milliseconds, self, JammableUnit.ClearJammeredStatus())
+ }
+
+ def StopJammeredStatus(target : PlanetSideServerObject with MountedWeapons) : Boolean = {
+ FacilityTurretControl.JammeredStatus(target, 0)
+ jammeredStatusTimer.cancel
+ }
+
+ def CancelJammeredSound(target : PlanetSideServerObject) : Unit = {
+ jammeredSoundTimer.cancel
+ target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 54, 0))
+ }
+}
+
+object FacilityTurretControl {
+ def HandleDamageResolution(target : FacilityTurret, cause : ResolvedProjectile, damage : Int) : Unit = {
+ val zone = target.Zone
+ val targetGUID = target.GUID
+ val playerGUID = target.Zone.LivePlayers.find { p => cause.projectile.owner.Name.equals(p.Name) } match {
+ case Some(player) => player.GUID
+ case _ => targetGUID
+ }
+ val continentId = zone.Id
+ if(target.Health > 1) {
+ //alert occupants to damage source
+ if(damage > 0) {
+ zone.Activity ! Zone.HotSpot.Activity(cause.target, cause.projectile.owner, cause.hit_pos)
+ //alert occupants to damage source
+ HandleDamageAwareness(target, playerGUID, cause)
+ }
+ if(cause.projectile.profile.JammerProjectile) {
+ target.Actor ! JammableUnit.Jammered(cause)
+ }
+ }
+ else {
+ //alert to vehicle death (hence, occupants' deaths)
+ HandleDestructionAwareness(target, playerGUID, cause)
+ }
+ zone.VehicleEvents ! VehicleServiceMessage(continentId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, targetGUID, 0, target.Health))
+ }
+
+ /**
+ * na
+ * @param target na
+ * @param attribution na
+ * @param lastShot na
+ */
+ def HandleDamageAwareness(target : FacilityTurret, attribution : PlanetSideGUID, lastShot : ResolvedProjectile) : Unit = {
+ val zone = target.Zone
+ val zoneId = zone.Id
+ //alert occupants to damage source
+ target.Seats.values.filter(seat => {
+ seat.isOccupied && seat.Occupant.get.isAlive
+ }).foreach(seat => {
+ val tplayer = seat.Occupant.get
+ zone.AvatarEvents ! AvatarServiceMessage(zoneId, AvatarAction.HitHint(attribution, tplayer.GUID))
+ })
+ }
+
+ /**
+ * na
+ * @param target na
+ * @param attribution na
+ * @param lastShot na
+ */
+ def HandleDestructionAwareness(target : FacilityTurret, attribution : PlanetSideGUID, lastShot : ResolvedProjectile) : Unit = {
+ target.Actor ! JammableUnit.ClearJammeredSound()
+ target.Actor ! JammableUnit.ClearJammeredStatus()
+ val zone = target.Zone
+ val zoneId = zone.Id
+ target.Seats.values.filter(seat => {
+ seat.isOccupied && seat.Occupant.get.isAlive
+ }).foreach(seat => {
+ val tplayer = seat.Occupant.get
+ val tplayerGUID = tplayer.GUID
+ zone.AvatarEvents ! AvatarServiceMessage(tplayer.Name, AvatarAction.KilledWhileInVehicle(tplayerGUID))
+ zone.AvatarEvents ! AvatarServiceMessage(zoneId, AvatarAction.ObjectDelete(tplayerGUID, tplayerGUID)) //dead player still sees self
+ })
+ //turret wreckage has no weapons
+ // target.Weapons.values
+ // .filter {
+ // _.Equipment.nonEmpty
+ // }
+ // .foreach(slot => {
+ // val wep = slot.Equipment.get
+ // zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, wep.GUID))
+ // })
+ // zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.Destroy(targetGUID, playerGUID, playerGUID, player.Position))
+ target.Health = 1 //TODO turret "death" at 0, as is proper
+ zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 0, target.Health)) //TODO not necessary
+ if(target.Upgrade != TurretUpgrade.None) {
+ zone.VehicleEvents ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.ClearSpecific(List(target), zone))
+ zone.VehicleEvents ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.AddTask(target, zone, TurretUpgrade.None))
+ }
+ }
+
+ def JammeredStatus(target : PlanetSideServerObject with MountedWeapons, statusCode : Int) : Unit = {
+ val zone = target.Zone
+ val zoneId = zone.Id
+ zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 27, statusCode))
+ target.Weapons.values
+ .map { _.Equipment }
+ .collect {
+ case Some(item : Tool) =>
+ zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, item.GUID, 27, statusCode))
+ }
+ }
}
diff --git a/common/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala b/common/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala
index 765ff003..cb091b58 100644
--- a/common/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala
+++ b/common/src/main/scala/net/psforever/objects/vehicles/VehicleControl.scala
@@ -4,7 +4,8 @@ package net.psforever.objects.vehicles
import akka.actor.{Actor, ActorRef, Cancellable}
import net.psforever.objects.{DefaultCancellable, GlobalDefinitions, Tool, Vehicle}
import net.psforever.objects.ballistics.{ResolvedProjectile, VehicleSource}
-import net.psforever.objects.equipment.JammingUnit
+import net.psforever.objects.equipment.{JammableUnit, JammingUnit}
+import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.serverobject.deploy.{Deployment, DeploymentBehavior}
@@ -90,7 +91,7 @@ class VehicleControl(vehicle : Vehicle) extends Actor
val shields = vehicle.Shields
val damageToHealth = originalHealth - health
val damageToShields = originalShields - shields
- VehicleControl.HandleVehicleDamageResolution(vehicle, cause, damageToHealth + damageToShields)
+ VehicleControl.HandleDamageResolution(vehicle, cause, damageToHealth + damageToShields)
if(damageToHealth > 0 || damageToShields > 0) {
val name = vehicle.Actor.toString
val slashPoint = name.lastIndexOf("/")
@@ -115,13 +116,13 @@ class VehicleControl(vehicle : Vehicle) extends Actor
}
sender ! FactionAffinity.AssertFactionAffinity(vehicle, faction)
- case VehicleControl.Jammered(cause) =>
- TryJammerVehicleWithProjectile(vehicle, cause)
+ case JammableUnit.Jammered(cause) =>
+ TryJammerWithProjectile(vehicle, cause)
- case VehicleControl.ClearJammeredSound() =>
+ case JammableUnit.ClearJammeredSound() =>
CancelJammeredSound(vehicle)
- case VehicleControl.ClearJammeredStatus() =>
+ case JammableUnit.ClearJammeredStatus() =>
StopJammeredStatus(vehicle)
case Vehicle.PrepareForDeletion =>
@@ -133,10 +134,10 @@ class VehicleControl(vehicle : Vehicle) extends Actor
def Disabled : Receive = checkBehavior
.orElse(dismountBehavior)
.orElse {
- case VehicleControl.ClearJammeredSound() =>
+ case JammableUnit.ClearJammeredSound() =>
CancelJammeredSound(vehicle)
- case VehicleControl.ClearJammeredStatus() =>
+ case JammableUnit.ClearJammeredStatus() =>
StopJammeredStatus(vehicle)
case Vehicle.Reactivate =>
@@ -145,49 +146,40 @@ class VehicleControl(vehicle : Vehicle) extends Actor
case _ => ;
}
- def TryJammerVehicleWithProjectile(target : Vehicle, cause : ResolvedProjectile) : Unit = {
+ def TryJammerWithProjectile(target : Vehicle, cause : ResolvedProjectile) : Unit = {
val radius = cause.projectile.profile.DamageRadius
JammingUnit.FindJammerDuration(cause.projectile.profile, target) match {
case Some(dur) if Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius =>
//jammered sound
+ jammeredSoundTimer.cancel
target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 54, 1))
import scala.concurrent.ExecutionContext.Implicits.global
- jammeredSoundTimer = context.system.scheduler.scheduleOnce(30 seconds, self, VehicleControl.ClearJammeredSound())
+ jammeredSoundTimer = context.system.scheduler.scheduleOnce(30 seconds, self, JammableUnit.ClearJammeredSound())
//jammered status
StartJammeredStatus(target, dur)
case _ => ;
}
}
- def StartJammeredStatus(target : Vehicle, dur : Int) : Boolean = {
- if(jammeredStatusTimer.isCancelled) {
- VehicleControl.JammeredStatus(target, 1)
- import scala.concurrent.ExecutionContext.Implicits.global
- jammeredStatusTimer = context.system.scheduler.scheduleOnce(dur milliseconds, self, VehicleControl.ClearJammeredStatus())
- true
- }
- else {
- false
- }
+ def StartJammeredStatus(target : PlanetSideServerObject with MountedWeapons, dur : Int) : Unit = {
+ jammeredStatusTimer.cancel
+ VehicleControl.JammeredStatus(target, 1)
+ import scala.concurrent.ExecutionContext.Implicits.global
+ jammeredStatusTimer = context.system.scheduler.scheduleOnce(dur milliseconds, self, JammableUnit.ClearJammeredStatus())
}
- def StopJammeredStatus(target : Vehicle) : Boolean = {
+ def StopJammeredStatus(target : PlanetSideServerObject with MountedWeapons) : Boolean = {
VehicleControl.JammeredStatus(target, 0)
jammeredStatusTimer.cancel
}
- def CancelJammeredSound(target : Vehicle) : Unit = {
+ def CancelJammeredSound(target : PlanetSideServerObject) : Unit = {
jammeredSoundTimer.cancel
target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 54, 0))
}
}
object VehicleControl {
- private final case class Jammered(cause : ResolvedProjectile)
-
- private final case class ClearJammeredSound()
-
- private final case class ClearJammeredStatus()
import net.psforever.objects.vital.{DamageFromProjectile, VehicleShieldCharge, VitalsActivity}
import scala.concurrent.duration._
@@ -211,29 +203,30 @@ object VehicleControl {
* na
* @param target na
*/
- def HandleVehicleDamageResolution(target : Vehicle, cause : ResolvedProjectile, damage : Int) : Unit = {
+ def HandleDamageResolution(target : Vehicle, cause : ResolvedProjectile, damage : Int) : Unit = {
+ val zone = target.Zone
val targetGUID = target.GUID
- val playerGUID = target.Zone.LivePlayers.find { p => cause.projectile.owner.Name.equals(p.Name) } match {
+ val playerGUID = zone.LivePlayers.find { p => cause.projectile.owner.Name.equals(p.Name) } match {
case Some(player) => player.GUID
case _ => PlanetSideGUID(0)
}
if(target.Health > 0) {
//activity on map
if(damage > 0) {
- target.Zone.Activity ! Zone.HotSpot.Activity(cause.target, cause.projectile.owner, cause.hit_pos)
+ zone.Activity ! Zone.HotSpot.Activity(cause.target, cause.projectile.owner, cause.hit_pos)
//alert occupants to damage source
- HandleVehicleDamageAwareness(target, playerGUID, cause)
+ HandleDamageAwareness(target, playerGUID, cause)
}
if(cause.projectile.profile.JammerProjectile) {
- target.Actor ! VehicleControl.Jammered(cause)
+ target.Actor ! JammableUnit.Jammered(cause)
}
}
else {
//alert to vehicle death (hence, occupants' deaths)
- HandleVehicleDestructionAwareness(target, playerGUID, cause)
+ HandleDestructionAwareness(target, playerGUID, cause)
}
- target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, targetGUID, 0, target.Health))
- target.Zone.VehicleEvents ! VehicleServiceMessage(s"${target.Actor}", VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, targetGUID, 68, target.Shields))
+ zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, targetGUID, 0, target.Health))
+ zone.VehicleEvents ! VehicleServiceMessage(s"${target.Actor}", VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, targetGUID, 68, target.Shields))
}
/**
@@ -242,13 +235,14 @@ object VehicleControl {
* @param attribution na
* @param lastShot na
*/
- def HandleVehicleDamageAwareness(target : Vehicle, attribution : PlanetSideGUID, lastShot : ResolvedProjectile) : Unit = {
+ def HandleDamageAwareness(target : Vehicle, attribution : PlanetSideGUID, lastShot : ResolvedProjectile) : Unit = {
+ val zone = target.Zone
//alert occupants to damage source
target.Seats.values.filter(seat => {
seat.isOccupied && seat.Occupant.get.isAlive
}).foreach(seat => {
val tplayer = seat.Occupant.get
- target.Zone.AvatarEvents ! AvatarServiceMessage(tplayer.Name, AvatarAction.HitHint(attribution, tplayer.GUID))
+ zone.AvatarEvents ! AvatarServiceMessage(tplayer.Name, AvatarAction.HitHint(attribution, tplayer.GUID))
})
//alert cargo occupants to damage source
target.CargoHolds.values.foreach(hold => {
@@ -257,7 +251,7 @@ object VehicleControl {
cargo.Health = 0
cargo.Shields = 0
cargo.History(lastShot)
- HandleVehicleDamageAwareness(cargo, attribution, lastShot)
+ HandleDamageAwareness(cargo, attribution, lastShot)
case None => ;
}
})
@@ -269,16 +263,19 @@ object VehicleControl {
* @param attribution na
* @param lastShot na
*/
- def HandleVehicleDestructionAwareness(target : Vehicle, attribution : PlanetSideGUID, lastShot : ResolvedProjectile) : Unit = {
- val continentId = target.Zone.Id
+ def HandleDestructionAwareness(target : Vehicle, attribution : PlanetSideGUID, lastShot : ResolvedProjectile) : Unit = {
+ target.Actor ! JammableUnit.ClearJammeredSound()
+ target.Actor ! JammableUnit.ClearJammeredStatus()
+ val zone = target.Zone
+ val continentId = zone.Id
//alert to vehicle death (hence, occupants' deaths)
target.Seats.values.filter(seat => {
seat.isOccupied && seat.Occupant.get.isAlive
}).foreach(seat => {
val tplayer = seat.Occupant.get
val tplayerGUID = tplayer.GUID
- target.Zone.AvatarEvents ! AvatarServiceMessage(tplayer.Name, AvatarAction.KilledWhileInVehicle(tplayerGUID))
- target.Zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(tplayerGUID, tplayerGUID)) //dead player still sees self
+ zone.AvatarEvents ! AvatarServiceMessage(tplayer.Name, AvatarAction.KilledWhileInVehicle(tplayerGUID))
+ zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(tplayerGUID, tplayerGUID)) //dead player still sees self
})
//vehicle wreckage has no weapons
target.Weapons.values
@@ -287,7 +284,7 @@ object VehicleControl {
}
.foreach(slot => {
val wep = slot.Equipment.get
- target.Zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, wep.GUID))
+ zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, wep.GUID))
})
target.CargoHolds.values.foreach(hold => {
hold.Occupant match {
@@ -296,7 +293,7 @@ object VehicleControl {
cargo.Shields = 0
cargo.Position += Vector3.z(1)
cargo.History(lastShot) //necessary to kill cargo vehicle occupants //TODO: collision damage
- HandleVehicleDestructionAwareness(cargo, attribution, lastShot) //might cause redundant packets
+ HandleDestructionAwareness(cargo, attribution, lastShot) //might cause redundant packets
case None => ;
}
})
@@ -305,22 +302,24 @@ object VehicleControl {
target.Actor ! Deployment.TryDeploymentChange(DriveState.Undeploying)
case GlobalDefinitions.router =>
target.Actor ! Deployment.TryDeploymentChange(DriveState.Undeploying)
- VehicleService.BeforeUnloadVehicle(target, target.Zone)
- target.Zone.LocalEvents ! LocalServiceMessage(target.Zone.Id, LocalAction.ToggleTeleportSystem(PlanetSideGUID(0), target, None))
+ VehicleService.BeforeUnloadVehicle(target, zone)
+ zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.ToggleTeleportSystem(PlanetSideGUID(0), target, None))
case _ => ;
}
- target.Zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.Destroy(target.GUID, attribution, attribution, target.Position))
- target.Zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(target), target.Zone))
- target.Zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.AddTask(target, target.Zone, Some(1 minute)))
+ zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.Destroy(target.GUID, attribution, attribution, target.Position))
+ zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(target), zone))
+ zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.AddTask(target, zone, Some(1 minute)))
}
- def JammeredStatus(target : Vehicle, statusCode : Int) : Unit = {
- target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 27, statusCode))
+ def JammeredStatus(target : PlanetSideServerObject with MountedWeapons, statusCode : Int) : Unit = {
+ val zone = target.Zone
+ val zoneId = zone.Id
+ zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 27, statusCode))
target.Weapons.values
.map { _.Equipment }
.collect {
case Some(item : Tool) =>
- target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, item.GUID, 27, statusCode))
+ zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, item.GUID, 27, statusCode))
}
}
}
diff --git a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
index 014df10d..b09ffb41 100644
--- a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
@@ -118,7 +118,7 @@ import scodec.codecs._
* `27 - PA_JAMMED - plays jammed buzzing sound`
* `28 - PA_IMPLANT_ACTIVE - Plays implant sounds. Valid values seem to be up to 20.`
* `29 - PA_VAPORIZED - Visible ?! That's not the cloaked effect, Maybe for spectator mode ?. Value is 0 to visible, 1 to invisible.`
- * `31 - Looking for Squad info (marquee and ui):
+ * `31 - Looking for Squad info (marquee and ui):`
* ` - 0 is LFS`
* ` - 1 is LFSM (Looking for Squad Members)`
* ` - n is the supplemental squad identifier number; same as "LFS;" for the leader, sets "LFSM" after the first manual flagging`
diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala
index c551b170..6db3e6d7 100644
--- a/pslogin/src/main/scala/WorldSessionActor.scala
+++ b/pslogin/src/main/scala/WorldSessionActor.scala
@@ -1143,9 +1143,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
AnnounceDestroyDeployable(target, None)
}
- case Vitality.DamageResolution(target : FacilityTurret, _) =>
- HandleFacilityTurretDamageResolution(target)
-
case Vitality.DamageResolution(target : PlanetSideGameObject, _) =>
log.warn(s"Vital target ${target.Definition.Name} damage resolution not supported using this method")
@@ -1335,16 +1332,18 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(PlanetsideAttributeMessage(player.GUID, 54, 1))
continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 54, 1))
import scala.concurrent.ExecutionContext.Implicits.global
+ jammeredSoundTimer.cancel
jammeredSoundTimer = context.system.scheduler.scheduleOnce(30 seconds, self, ClearJammeredSound())
//jammered status
skipStaminaRegenForTurns = 5
- jammeredEquipment = player.Holsters()
+ jammeredEquipment = (jammeredEquipment ++ player.Holsters()
.map { _.Equipment }
.collect {
case Some(item) if item.Size != EquipmentSize.Melee =>
- sendResponse(PlanetsideAttributeMessage(item.GUID, 24, 1))
+ sendResponse(PlanetsideAttributeMessage(item.GUID, 27, 1))
item.GUID
- }
+ }).distinct
+ jammeredStatusTimer.cancel
jammeredStatusTimer = context.system.scheduler.scheduleOnce(dur milliseconds, self, ClearJammeredStatus())
case _ => ;
}
@@ -2995,48 +2994,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
continent.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.PlanetsideAttribute(guid, 0, health))
}
- def HandleFacilityTurretDamageResolution(target : FacilityTurret) : Unit = {
- val targetGUID = target.GUID
- val playerGUID = player.GUID
- val continentId = continent.Id
- val players = target.Seats.values.filter(seat => {
- seat.isOccupied && seat.Occupant.get.isAlive
- })
- if(target.Health > 1) { //TODO turret "death" at 0, as is proper
- //alert occupants to damage source
- players.foreach(seat => {
- val tplayer = seat.Occupant.get
- continent.AvatarEvents ! AvatarServiceMessage(tplayer.Name, AvatarAction.HitHint(playerGUID, tplayer.GUID))
- })
- }
- else {
- //alert to vehicle death (hence, occupants' deaths)
- players.foreach(seat => {
- val tplayer = seat.Occupant.get
- val tplayerGUID = tplayer.GUID
- continent.AvatarEvents ! AvatarServiceMessage(tplayer.Name, AvatarAction.KilledWhileInVehicle(tplayerGUID))
- continent.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(tplayerGUID, tplayerGUID)) //dead player still sees self
- })
- //turret wreckage has no weapons
-// target.Weapons.values
-// .filter {
-// _.Equipment.nonEmpty
-// }
-// .foreach(slot => {
-// val wep = slot.Equipment.get
-// continent.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, wep.GUID))
-// })
-// continent.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.Destroy(targetGUID, playerGUID, playerGUID, player.Position))
- target.Health = 1
- continent.VehicleEvents ! VehicleServiceMessage(continentId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, targetGUID, 0, target.MaxHealth)) //TODO not necessary
- if(target.Upgrade != TurretUpgrade.None) {
- continent.VehicleEvents ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.ClearSpecific(List(target), continent))
- continent.VehicleEvents ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.AddTask(target, continent, TurretUpgrade.None))
- }
- }
- continent.VehicleEvents ! VehicleServiceMessage(continentId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, targetGUID, 0, target.Health))
- }
-
/**
* na
* @param tplayer na
@@ -4691,7 +4648,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
case msg @ UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType) =>
- log.info("UseItem: " + msg)
+ //log.info("UseItem: " + msg)
// TODO: Not all fields in the response are identical to source in real packet logs (but seems to be ok)
// TODO: Not all incoming UseItemMessage's respond with another UseItemMessage (i.e. doors only send out GenericObjectStateMsg)
continent.GUID(object_guid) match {
@@ -7844,10 +7801,8 @@ 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
+ CancelJammeredSound()
+ CancelJammeredStatus()
progressBarUpdate.cancel
progressBarValue = None
lastTerminalOrderFulfillment = true
@@ -8571,14 +8526,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
//damage is synchronized on the target player's `WSA` (results distributed from there)
continent.AvatarEvents ! AvatarServiceMessage(obj.Name, AvatarAction.Damage(player.GUID, obj, func))
case obj : Vehicle =>
- //damage is synchronized on the vehicle actor (results returned to and distributed from this `WSA`)
+ //damage is synchronized on the vehicle actor
+ obj.Actor ! Vitality.Damage(func)
+ case obj : FacilityTurret =>
+ //damage is synchronized on the turret actor
obj.Actor ! Vitality.Damage(func)
case obj : Deployable =>
//damage is synchronized on `LSA` (results returned to and distributed from this `WSA`)
continent.LocalEvents ! Vitality.DamageOn(obj, func)
- case obj : FacilityTurret =>
- //damage is synchronized on the turret actor (results returned to and distributed from this `WSA`)
- obj.Actor ! Vitality.Damage(func)
case _ => ;
}
}
@@ -10294,10 +10249,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
def CancelJammeredStatus() : Unit = {
- if(!jammeredSoundTimer.isCancelled) {
- CancelJammeredSound()
- }
- jammeredEquipment.foreach { id => sendResponse(PlanetsideAttributeMessage(id, 24, 0)) }
+ jammeredStatusTimer.cancel
+ jammeredEquipment.foreach { id => sendResponse(PlanetsideAttributeMessage(id, 27, 0)) }
jammeredEquipment = Nil
}