From 879be9386338ddb50bd2c7b31d174c33304bfbab Mon Sep 17 00:00:00 2001 From: FateJH Date: Fri, 27 Dec 2019 00:18:46 -0500 Subject: [PATCH] converted explosive-type and sensor-type deployables into complex deployables that have integrated control actors --- .../psforever/objects/BoomerDeployable.scala | 4 +- .../net/psforever/objects/Deployables.scala | 45 +++++++ .../objects/ExplosiveDeployable.scala | 99 +++++++++++++- .../psforever/objects/GlobalDefinitions.scala | 26 ++-- .../psforever/objects/SensorDeployable.scala | 126 +++++++++++++++++- .../objects/ShieldGeneratorDeployable.scala | 28 +--- .../psforever/objects/TurretDeployable.scala | 26 +--- .../resolution/ResolutionCalculations.scala | 8 +- .../scala/services/local/LocalService.scala | 14 -- .../src/main/scala/WorldSessionActor.scala | 67 +++------- 10 files changed, 300 insertions(+), 143 deletions(-) diff --git a/common/src/main/scala/net/psforever/objects/BoomerDeployable.scala b/common/src/main/scala/net/psforever/objects/BoomerDeployable.scala index 21d66ea2..39523d25 100644 --- a/common/src/main/scala/net/psforever/objects/BoomerDeployable.scala +++ b/common/src/main/scala/net/psforever/objects/BoomerDeployable.scala @@ -1,9 +1,7 @@ // Copyright (c) 2017 PSForever package net.psforever.objects -import net.psforever.objects.definition.SimpleDeployableDefinition - -class BoomerDeployable(cdef : SimpleDeployableDefinition) extends ExplosiveDeployable(cdef) { +class BoomerDeployable(cdef : ExplosiveDeployableDefinition) extends ExplosiveDeployable(cdef) { private var trigger : Option[BoomerTrigger] = None def Trigger : Option[BoomerTrigger] = trigger diff --git a/common/src/main/scala/net/psforever/objects/Deployables.scala b/common/src/main/scala/net/psforever/objects/Deployables.scala index de1c9ce0..3c0af9b0 100644 --- a/common/src/main/scala/net/psforever/objects/Deployables.scala +++ b/common/src/main/scala/net/psforever/objects/Deployables.scala @@ -2,6 +2,12 @@ package net.psforever.objects import net.psforever.objects.ce.{Deployable, DeployedItem} +import net.psforever.objects.serverobject.PlanetSideServerObject +import net.psforever.packet.game.{DeployableInfo, DeploymentAction, PlanetSideGUID} +import services.RemoverActor +import services.local.{LocalAction, LocalServiceMessage} + +import scala.concurrent.duration.FiniteDuration object Deployables { object Make { @@ -26,4 +32,43 @@ object Deployables { DeployedItem.router_telepad_deployable -> { () => new TelepadDeployable(GlobalDefinitions.router_telepad_deployable) } ).withDefaultValue( { ()=> new ExplosiveDeployable(GlobalDefinitions.boomer) } ) } + + /** + * Distribute information that a deployable has been destroyed. + * The deployable may not have yet been eliminated from the game world (client or server), + * but its health is zero and it has entered the conditions where it is nearly irrelevant.
+ *
+ * The typical use case of this function involves destruction via weapon fire, attributed to a particular player. + * Contrast this to simply destroying a deployable by being the deployable's owner and using the map icon controls. + * This function eventually invokes the same routine + * but mainly goes into effect when the deployable has been destroyed + * and may still leave a physical component in the game world to be cleaned up later. + * That is the task `EliminateDeployable` performs. + * Additionally, since the player who destroyed the deployable isn't necessarily the owner, + * and the real owner will still be aware of the existence of the deployable, + * that player must be informed of the loss of the deployable directly. + * @see `DeployableRemover` + * @see `Vitality.DamageResolution` + * @see `LocalResponse.EliminateDeployable` + * @see `DeconstructDeployable` + * @param target the deployable that is destroyed + * @param time length of time that the deployable is allowed to exist in the game world; + * `None` indicates the normal un-owned existence time (180 seconds) + */ + def AnnounceDestroyDeployable(target : PlanetSideServerObject with Deployable, time : Option[FiniteDuration]) : Unit = { + val zone = target.Zone + target.OwnerName match { + case Some(owner) => + target.OwnerName = None + zone.LocalEvents ! LocalServiceMessage(owner, LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target)) + case None => ; + } + zone.LocalEvents ! LocalServiceMessage(s"${target.Faction}", LocalAction.DeployableMapIcon( + PlanetSideGUID(0), + DeploymentAction.Dismiss, + DeployableInfo(target.GUID, Deployable.Icon(target.Definition.Item), target.Position, PlanetSideGUID(0))) + ) + zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(target), zone)) + zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.AddTask(target, zone, time)) + } } diff --git a/common/src/main/scala/net/psforever/objects/ExplosiveDeployable.scala b/common/src/main/scala/net/psforever/objects/ExplosiveDeployable.scala index b324c666..75482ecb 100644 --- a/common/src/main/scala/net/psforever/objects/ExplosiveDeployable.scala +++ b/common/src/main/scala/net/psforever/objects/ExplosiveDeployable.scala @@ -1,11 +1,22 @@ // Copyright (c) 2017 PSForever package net.psforever.objects -import net.psforever.objects.ce.SimpleDeployable -import net.psforever.objects.definition.SimpleDeployableDefinition +import akka.actor.{Actor, ActorContext, Props} +import net.psforever.objects.ballistics.ResolvedProjectile +import net.psforever.objects.ce._ +import net.psforever.objects.definition.{ComplexDeployableDefinition, SimpleDeployableDefinition} +import net.psforever.objects.definition.converter.SmallDeployableConverter import net.psforever.objects.equipment.JammableUnit +import net.psforever.objects.serverobject.PlanetSideServerObject +import net.psforever.objects.vital.{StandardResolutions, Vitality} +import net.psforever.packet.game.PlanetSideGUID +import net.psforever.types.Vector3 +import services.avatar.{AvatarAction, AvatarServiceMessage} +import services.local.{LocalAction, LocalServiceMessage} -class ExplosiveDeployable(cdef : SimpleDeployableDefinition) extends SimpleDeployable(cdef) +import scala.concurrent.duration._ + +class ExplosiveDeployable(cdef : ExplosiveDeployableDefinition) extends ComplexDeployable(cdef) with JammableUnit { private var exploded : Boolean = false @@ -15,4 +26,86 @@ class ExplosiveDeployable(cdef : SimpleDeployableDefinition) extends SimpleDeplo exploded = fuse Exploded } + + override def Definition : ExplosiveDeployableDefinition = cdef } + +class ExplosiveDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId) { + Name = "explosive_deployable" + DeployCategory = DeployableCategory.Mines + Model = StandardResolutions.SimpleDeployables + Packet = new SmallDeployableConverter + + private var detonateOnJamming : Boolean = true + + def DetonateOnJamming : Boolean = detonateOnJamming + + def DetonateOnJamming_=(detonate : Boolean) : Boolean = { + detonateOnJamming = detonate + DetonateOnJamming + } + + override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { + obj.Actor = context.actorOf(Props(classOf[ExplosiveDeployableControl], obj), s"${obj.Definition.Name}_${obj.GUID.guid}") + } + + override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { + SimpleDeployableDefinition.SimpleUninitialize(obj, context) + } +} + +object ExplosiveDeployableDefinition { + def apply(dtype : DeployedItem.Value) : ExplosiveDeployableDefinition = { + new ExplosiveDeployableDefinition(dtype.id) + } +} + +class ExplosiveDeployableControl(mine : ExplosiveDeployable) extends Actor { + def receive : Receive = { + case Vitality.Damage(damage_func) => + val originalHealth = mine.Health + if(originalHealth > 0) { + val cause = damage_func(mine) + ExplosiveDeployableControl.HandleDamageResolution(mine, cause, originalHealth - mine.Health) + } + + case _ => ; + } +} + +object ExplosiveDeployableControl { + def HandleDamageResolution(target : ExplosiveDeployable, cause : ResolvedProjectile, damage : Int) : Unit = { + val zone = target.Zone + 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) { + HandleDestructionAwareness(target, playerGUID, cause) + } + else if(!target.Jammed && cause.projectile.profile.JammerProjectile) { + if(target.Jammed = { + val radius = cause.projectile.profile.DamageRadius + Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius + }) { + if(target.Definition.DetonateOnJamming) { + target.Zone.LocalEvents ! LocalServiceMessage(target.Zone.Id, LocalAction.Detonate(target.GUID, target)) + } + HandleDestructionAwareness(target, playerGUID, cause) + } + } + } + + /** + * na + * @param target na + * @param attribution na + * @param lastShot na + */ + def HandleDestructionAwareness(target : ExplosiveDeployable, attribution : PlanetSideGUID, lastShot : ResolvedProjectile) : Unit = { + val zone = target.Zone + Deployables.AnnounceDestroyDeployable(target, Some(if(target.Jammed) 0 seconds else 500 milliseconds)) + zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.Destroy(target.GUID, attribution, attribution, target.Position)) + } +} + diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index 13066bd9..af18d1f7 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -870,11 +870,11 @@ object GlobalDefinitions { /* combat engineering deployables */ - val boomer = SimpleDeployableDefinition(DeployedItem.boomer) + val boomer = ExplosiveDeployableDefinition(DeployedItem.boomer) - val he_mine = SimpleDeployableDefinition(DeployedItem.he_mine) + val he_mine = ExplosiveDeployableDefinition(DeployedItem.he_mine) - val jammer_mine = SimpleDeployableDefinition(DeployedItem.jammer_mine) + val jammer_mine = ExplosiveDeployableDefinition(DeployedItem.jammer_mine) val spitfire_turret = TurretDeployableDefinition(DeployedItem.spitfire_turret) @@ -882,9 +882,9 @@ object GlobalDefinitions { val spitfire_aa = TurretDeployableDefinition(DeployedItem.spitfire_aa) - val motionalarmsensor = SimpleDeployableDefinition(DeployedItem.motionalarmsensor) + val motionalarmsensor = SensorDeployableDefinition(DeployedItem.motionalarmsensor) - val sensor_shield = SimpleDeployableDefinition(DeployedItem.sensor_shield) + val sensor_shield = SensorDeployableDefinition(DeployedItem.sensor_shield) val tank_traps = SimpleDeployableDefinition(DeployedItem.tank_traps) @@ -5901,24 +5901,20 @@ object GlobalDefinitions { boomer.MaxHealth = 100 boomer.DeployCategory = DeployableCategory.Boomers boomer.DeployTime = Duration.create(1000, "ms") - boomer.Model = StandardResolutions.SimpleDeployables he_mine.Name = "he_mine" he_mine.Descriptor = "Mines" he_mine.MaxHealth = 100 - he_mine.DeployCategory = DeployableCategory.Mines he_mine.DeployTime = Duration.create(1000, "ms") - he_mine.Model = StandardResolutions.SimpleDeployables jammer_mine.Name = "jammer_mine" jammer_mine.Descriptor = "JammerMines" jammer_mine.MaxHealth = 100 - jammer_mine.DeployCategory = DeployableCategory.Mines jammer_mine.DeployTime = Duration.create(1000, "ms") - jammer_mine.Model = StandardResolutions.SimpleDeployables + jammer_mine.DetonateOnJamming = false spitfire_turret.Name = "spitfire_turret" - spitfire_turret.Descriptor= "Spitfires" + spitfire_turret.Descriptor = "Spitfires" spitfire_turret.MaxHealth = 100 spitfire_turret.Weapons += 1 -> new mutable.HashMap() spitfire_turret.Weapons(1) += TurretUpgrade.None -> spitfire_weapon @@ -5928,7 +5924,7 @@ object GlobalDefinitions { spitfire_turret.Model = StandardResolutions.ComplexDeployables spitfire_cloaked.Name = "spitfire_cloaked" - spitfire_cloaked.Descriptor= "CloakingSpitfires" + spitfire_cloaked.Descriptor = "CloakingSpitfires" spitfire_cloaked.MaxHealth = 100 spitfire_cloaked.Weapons += 1 -> new mutable.HashMap() spitfire_cloaked.Weapons(1) += TurretUpgrade.None -> spitfire_weapon @@ -5938,7 +5934,7 @@ object GlobalDefinitions { spitfire_cloaked.Model = StandardResolutions.ComplexDeployables spitfire_aa.Name = "spitfire_aa" - spitfire_aa.Descriptor= "FlakSpitfires" + spitfire_aa.Descriptor = "FlakSpitfires" spitfire_aa.MaxHealth = 100 spitfire_aa.Weapons += 1 -> new mutable.HashMap() spitfire_aa.Weapons(1) += TurretUpgrade.None -> spitfire_aa_weapon @@ -5950,16 +5946,12 @@ object GlobalDefinitions { motionalarmsensor.Name = "motionalarmsensor" motionalarmsensor.Descriptor = "MotionSensors" motionalarmsensor.MaxHealth = 100 - motionalarmsensor.DeployCategory = DeployableCategory.Sensors motionalarmsensor.DeployTime = Duration.create(1000, "ms") - motionalarmsensor.Model = StandardResolutions.SimpleDeployables sensor_shield.Name = "sensor_shield" sensor_shield.Descriptor = "SensorShields" sensor_shield.MaxHealth = 100 - sensor_shield.DeployCategory = DeployableCategory.Sensors sensor_shield.DeployTime = Duration.create(5000, "ms") - sensor_shield.Model = StandardResolutions.SimpleDeployables tank_traps.Name = "tank_traps" tank_traps.Descriptor = "TankTraps" diff --git a/common/src/main/scala/net/psforever/objects/SensorDeployable.scala b/common/src/main/scala/net/psforever/objects/SensorDeployable.scala index 1c886cd9..71d3373a 100644 --- a/common/src/main/scala/net/psforever/objects/SensorDeployable.scala +++ b/common/src/main/scala/net/psforever/objects/SensorDeployable.scala @@ -1,11 +1,129 @@ // Copyright (c) 2017 PSForever package net.psforever.objects -import net.psforever.objects.ce.SimpleDeployable -import net.psforever.objects.definition.SimpleDeployableDefinition -import net.psforever.objects.equipment.JammableUnit +import akka.actor.{Actor, ActorContext, Props} +import net.psforever.objects.ballistics.ResolvedProjectile +import net.psforever.objects.ce._ +import net.psforever.objects.definition.converter.SmallDeployableConverter +import net.psforever.objects.definition.{ComplexDeployableDefinition, SimpleDeployableDefinition} +import net.psforever.objects.equipment.{JammableBehavior, JammableUnit} +import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.objects.serverobject.hackable.Hackable +import net.psforever.objects.vital.{StandardResolutions, Vitality} +import net.psforever.objects.zones.Zone +import net.psforever.packet.game.PlanetSideGUID +import services.Service +import services.avatar.{AvatarAction, AvatarServiceMessage} +import services.local.{LocalAction, LocalServiceMessage} +import services.vehicle.{VehicleAction, VehicleServiceMessage} -class SensorDeployable(cdef : SimpleDeployableDefinition) extends SimpleDeployable(cdef) +import scala.concurrent.duration._ + +class SensorDeployable(cdef : SensorDeployableDefinition) extends ComplexDeployable(cdef) with Hackable with JammableUnit + +class SensorDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId) { + Name = "sensor_deployable" + DeployCategory = DeployableCategory.Sensors + Model = StandardResolutions.SimpleDeployables + Packet = new SmallDeployableConverter + + override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { + obj.Actor = context.actorOf(Props(classOf[SensorDeployableControl], obj), s"${obj.Definition.Name}_${obj.GUID.guid}") + } + + override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = { + SimpleDeployableDefinition.SimpleUninitialize(obj, context) + } +} + +object SensorDeployableDefinition { + def apply(dtype : DeployedItem.Value) : SensorDeployableDefinition = { + new SensorDeployableDefinition(dtype.id) + } +} + +class SensorDeployableControl(sensor : SensorDeployable) extends Actor + with JammableBehavior { + + def JammableObject = sensor + + def receive : Receive = jammableBehavior.orElse { + case Vitality.Damage(damage_func) => + val originalHealth = sensor.Health + if(originalHealth > 0) { + val cause = damage_func(sensor) + SensorDeployableControl.HandleDamageResolution(sensor, cause, originalHealth - sensor.Health) + } + + case _ => ; + } + + override def StartJammeredSound(target : Any, dur : Int) : Unit = target match { + case obj : PlanetSideServerObject => + obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 1)) + super.StartJammeredSound(obj, dur) + case _ => ; + } + + override def StartJammeredStatus(target : Any, dur : Int) : Unit = target match { + case obj : PlanetSideServerObject => + sensor.Zone.LocalEvents ! LocalServiceMessage(sensor.Zone.Id, LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, false, 1000)) + super.StartJammeredStatus(obj, dur) + case _ => ; + } + + override def CancelJammeredSound(target : Any) : Unit = target match { + case obj : PlanetSideServerObject => + obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 0)) + super.CancelJammeredSound(obj) + case _ => ; + } + + override def CancelJammeredStatus(target : Any) : Unit = target match { + case obj : PlanetSideServerObject => + sensor.Zone.LocalEvents ! LocalServiceMessage(sensor.Zone.Id, LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, true, 1000)) + super.CancelJammeredStatus(obj) + case _ => ; + } +} + +object SensorDeployableControl { + def HandleDamageResolution(target : SensorDeployable, cause : ResolvedProjectile, damage : Int) : Unit = { + val zone = target.Zone + val targetGUID = target.GUID + 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) { + zone.Activity ! Zone.HotSpot.Activity(cause.target, cause.projectile.owner, cause.hit_pos) + } + if(cause.projectile.profile.JammerProjectile) { + target.Actor ! JammableUnit.Jammered(cause) + } + } + else { + HandleDestructionAwareness(target, playerGUID, cause) + } + zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.PlanetsideAttribute(targetGUID, 0, target.Health)) + } + + /** + * na + * @param target na + * @param attribution na + * @param lastShot na + */ + def HandleDestructionAwareness(target : SensorDeployable, attribution : PlanetSideGUID, lastShot : ResolvedProjectile) : Unit = { + target.Actor ! JammableUnit.ClearJammeredSound() + target.Actor ! JammableUnit.ClearJammeredStatus() + val zone = target.Zone + Deployables.AnnounceDestroyDeployable(target, Some(0 seconds)) + zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", target.GUID, false, 1000)) + zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.Destroy(target.GUID, attribution, attribution, target.Position)) + } +} diff --git a/common/src/main/scala/net/psforever/objects/ShieldGeneratorDeployable.scala b/common/src/main/scala/net/psforever/objects/ShieldGeneratorDeployable.scala index ffe8dcb1..d304bb93 100644 --- a/common/src/main/scala/net/psforever/objects/ShieldGeneratorDeployable.scala +++ b/common/src/main/scala/net/psforever/objects/ShieldGeneratorDeployable.scala @@ -11,14 +11,11 @@ import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.objects.serverobject.hackable.Hackable import net.psforever.objects.vital.Vitality import net.psforever.objects.zones.Zone -import net.psforever.packet.game.{DeployableInfo, DeploymentAction, PlanetSideGUID} +import net.psforever.packet.game.PlanetSideGUID import services.avatar.{AvatarAction, AvatarServiceMessage} -import services.local.{LocalAction, LocalServiceMessage} -import services.{RemoverActor, Service} +import services.Service import services.vehicle.{VehicleAction, VehicleServiceMessage} -import scala.concurrent.duration.FiniteDuration - class ShieldGeneratorDeployable(cdef : ShieldGeneratorDefinition) extends ComplexDeployable(cdef) with Hackable with JammableUnit @@ -103,7 +100,7 @@ object ShieldGeneratorControl { else { HandleDestructionAwareness(target, playerGUID, cause) } - zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, targetGUID, 0, target.Health)) + zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.PlanetsideAttribute(targetGUID, 0, target.Health)) } /** @@ -116,24 +113,7 @@ object ShieldGeneratorControl { target.Actor ! JammableUnit.ClearJammeredSound() target.Actor ! JammableUnit.ClearJammeredStatus() val zone = target.Zone - AnnounceDestroyDeployable(target, None) + Deployables.AnnounceDestroyDeployable(target, None) zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.Destroy(target.GUID, attribution, attribution, target.Position)) } - - def AnnounceDestroyDeployable(target : PlanetSideServerObject with Deployable, time : Option[FiniteDuration]) : Unit = { - val zone = target.Zone - target.OwnerName match { - case Some(owner) => - target.OwnerName = None - zone.LocalEvents ! LocalServiceMessage(owner, LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target)) - case None => ; - } - zone.LocalEvents ! LocalServiceMessage(s"${target.Faction}", LocalAction.DeployableMapIcon( - PlanetSideGUID(0), - DeploymentAction.Dismiss, - DeployableInfo(target.GUID, Deployable.Icon(target.Definition.Item), target.Position, PlanetSideGUID(0))) - ) - zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(target), zone)) - zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.AddTask(target, zone, time)) - } } diff --git a/common/src/main/scala/net/psforever/objects/TurretDeployable.scala b/common/src/main/scala/net/psforever/objects/TurretDeployable.scala index 23b57441..46d9601a 100644 --- a/common/src/main/scala/net/psforever/objects/TurretDeployable.scala +++ b/common/src/main/scala/net/psforever/objects/TurretDeployable.scala @@ -14,10 +14,9 @@ import net.psforever.objects.serverobject.mount.MountableBehavior import net.psforever.objects.serverobject.turret.{TurretDefinition, WeaponTurret} import net.psforever.objects.vital.{StandardResolutions, StandardVehicleDamage, StandardVehicleResistance, Vitality} import net.psforever.objects.zones.Zone -import net.psforever.packet.game.{DeployableInfo, DeploymentAction, PlanetSideGUID} -import services.{RemoverActor, Service} +import net.psforever.packet.game.PlanetSideGUID +import services.Service import services.avatar.{AvatarAction, AvatarServiceMessage} -import services.local.{LocalAction, LocalServiceMessage} import services.vehicle.{VehicleAction, VehicleServiceMessage} class TurretDeployable(tdef : TurretDeployableDefinition) extends ComplexDeployable(tdef) @@ -101,8 +100,6 @@ class TurretControl(turret : TurretDeployable) extends Actor } object TurretControl { - import scala.concurrent.duration._ - /** * na * @param target na @@ -178,24 +175,7 @@ object TurretControl { val wep = slot.Equipment.get zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, wep.GUID)) }) - AnnounceDestroyDeployable(target, None) + Deployables.AnnounceDestroyDeployable(target, None) zone.AvatarEvents ! AvatarServiceMessage(continentId, AvatarAction.Destroy(target.GUID, attribution, attribution, target.Position)) } - - def AnnounceDestroyDeployable(target : PlanetSideServerObject with Deployable, time : Option[FiniteDuration]) : Unit = { - val zone = target.Zone - target.OwnerName match { - case Some(owner) => - target.OwnerName = None - zone.LocalEvents ! LocalServiceMessage(owner, LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target)) - case None => ; - } - zone.LocalEvents ! LocalServiceMessage(s"${target.Faction}", LocalAction.DeployableMapIcon( - PlanetSideGUID(0), - DeploymentAction.Dismiss, - DeployableInfo(target.GUID, Deployable.Icon(target.Definition.Item), target.Position, PlanetSideGUID(0))) - ) - zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(target), zone)) - zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.AddTask(target, zone, time)) - } } diff --git a/common/src/main/scala/net/psforever/objects/vital/resolution/ResolutionCalculations.scala b/common/src/main/scala/net/psforever/objects/vital/resolution/ResolutionCalculations.scala index a85f6206..bd395792 100644 --- a/common/src/main/scala/net/psforever/objects/vital/resolution/ResolutionCalculations.scala +++ b/common/src/main/scala/net/psforever/objects/vital/resolution/ResolutionCalculations.scala @@ -3,7 +3,7 @@ package net.psforever.objects.vital.resolution import net.psforever.objects.{Player, TurretDeployable, Vehicle} import net.psforever.objects.ballistics.{PlayerSource, ResolvedProjectile} -import net.psforever.objects.ce.{ComplexDeployable, SimpleDeployable} +import net.psforever.objects.ce.{ComplexDeployable, Deployable} import net.psforever.objects.serverobject.turret.FacilityTurret import net.psforever.objects.vital.projectile.ProjectileCalculations @@ -192,9 +192,9 @@ object ResolutionCalculations { def SimpleApplication(damage : Int, data : ResolvedProjectile)(target : Any) : ResolvedProjectile = { target match { - case ce : SimpleDeployable if ce.Health > 0 && damage > 0 => - ce.Health -= damage - ce.History(data) + case obj : Deployable if obj.Health > 0 => + obj.Health -= damage + obj.History(data) case turret : FacilityTurret if turret.Health > 0 => turret.Health -= damage turret.History(data) diff --git a/common/src/main/scala/services/local/LocalService.scala b/common/src/main/scala/services/local/LocalService.scala index 21b137c8..369e653b 100644 --- a/common/src/main/scala/services/local/LocalService.scala +++ b/common/src/main/scala/services/local/LocalService.scala @@ -7,7 +7,6 @@ import net.psforever.objects.serverobject.structures.{Amenity, Building} import net.psforever.objects.serverobject.terminals.{CaptureTerminal, Terminal} import net.psforever.objects.zones.Zone import net.psforever.objects._ -import net.psforever.objects.equipment.JammableUnit import net.psforever.packet.game.{PlanetSideGUID, TriggeredEffect, TriggeredEffectLocation} import net.psforever.objects.vital.Vitality import net.psforever.types.Vector3 @@ -287,19 +286,6 @@ class LocalService(zone : Zone) extends Actor { } //synchronized damage calculations - case Vitality.DamageOn(target : Deployable with JammableUnit, damage_func) => - if(target.Health > 0) { - val cause = damage_func(target) - target.Jammed = if(cause.projectile.profile.JammerProjectile) { - val radius = cause.projectile.profile.DamageRadius - Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius - } - else { - false - } - sender ! Vitality.DamageResolution(target, cause) - } - case Vitality.DamageOn(target : Deployable, damage_func) => val cause = damage_func(target) sender ! Vitality.DamageResolution(target, cause) diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index e2dd5569..5f2a7ab6 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -915,10 +915,11 @@ class WorldSessionActor extends Actor continent.Deployables ! Zone.Deployable.Dismiss(obj) } - case WorldSessionActor.FinalizeDeployable(obj : ComplexDeployable, tool, index) => - //spitfires and deployable field turrets and the deployable_shield_generator + case WorldSessionActor.FinalizeDeployable(obj : SensorDeployable, tool, index) => + //motion alarm sensor and sensor disruptor StartBundlingPackets() DeployableBuildActivity(obj) + continent.LocalEvents ! LocalServiceMessage(continent.Id, LocalAction.TriggerEffectInfo(player.GUID, "on", obj.GUID, true, 1000)) CommonDestroyConstructionItem(tool, index) FindReplacementConstructionItem(tool, index) StopBundlingPackets() @@ -953,11 +954,10 @@ class WorldSessionActor extends Actor FindReplacementConstructionItem(tool, index) StopBundlingPackets() - case WorldSessionActor.FinalizeDeployable(obj : SensorDeployable, tool, index) => - //motion alarm sensor and sensor disruptor + case WorldSessionActor.FinalizeDeployable(obj : ComplexDeployable, tool, index) => + //spitfires and deployable field turrets and the deployable_shield_generator StartBundlingPackets() DeployableBuildActivity(obj) - continent.LocalEvents ! LocalServiceMessage(continent.Id, LocalAction.TriggerEffectInfo(player.GUID, "on", obj.GUID, true, 1000)) CommonDestroyConstructionItem(tool, index) FindReplacementConstructionItem(tool, index) StopBundlingPackets() @@ -1107,43 +1107,8 @@ class WorldSessionActor extends Actor AnnounceDestroyDeployable(target, None) } - case Vitality.DamageResolution(target : SensorDeployable, _) => - //sensors - val guid = target.GUID - val health = target.Health - continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(guid, 0, health)) - if(health <= 0) { - AnnounceDestroyDeployable(target, Some(0 seconds)) - } - - case Vitality.DamageResolution(target : BoomerDeployable, _) => - //boomer - if(target.Jammed) { - continent.LocalEvents ! LocalServiceMessage(continent.Id, LocalAction.Detonate(target.GUID, target)) - AnnounceDestroyDeployable(target, Some(500 milliseconds)) - } - else if(target.Health <= 0) { - AnnounceDestroyDeployable(target, Some(0 seconds)) - } - - case Vitality.DamageResolution(target : ExplosiveDeployable, _) if target.Definition eq he_mine => - //he_mine - if(target.Jammed) { - continent.LocalEvents ! LocalServiceMessage(continent.Id, LocalAction.Detonate(target.GUID, target)) - AnnounceDestroyDeployable(target, Some(500 milliseconds)) - } - else if(target.Health <= 0) { - AnnounceDestroyDeployable(target, Some(0 seconds)) - } - - case Vitality.DamageResolution(target : ExplosiveDeployable, _) if target.Definition eq jammer_mine => - //jammer_mine - if(target.Jammed || target.Health <= 0) { - AnnounceDestroyDeployable(target, Some(0 seconds)) - } - - case Vitality.DamageResolution(target : SimpleDeployable, _) => - //boomers, mines + case Vitality.DamageResolution(target : TelepadDeployable, _) => + //telepads if(target.Health <= 0) { //update if destroyed val guid = target.GUID @@ -1580,14 +1545,6 @@ class WorldSessionActor extends Actor DeconstructDeployable(obj, guid, pos, obj.Orientation, if(obj.MountPoints.isEmpty) 2 else 1) } - case LocalResponse.EliminateDeployable(obj : ComplexDeployable, guid, pos) => - if(obj.Health == 0) { - DeconstructDeployable(obj, guid, pos) - } - else { - DeconstructDeployable(obj, guid, pos, obj.Orientation, 1) - } - case LocalResponse.EliminateDeployable(obj : ExplosiveDeployable, guid, pos) => if(obj.Exploded || obj.Jammed || obj.Health == 0) { DeconstructDeployable(obj, guid, pos) @@ -1596,6 +1553,14 @@ class WorldSessionActor extends Actor DeconstructDeployable(obj, guid, pos, obj.Orientation, 2) } + case LocalResponse.EliminateDeployable(obj : ComplexDeployable, guid, pos) => + if(obj.Health == 0) { + DeconstructDeployable(obj, guid, pos) + } + else { + DeconstructDeployable(obj, guid, pos, obj.Orientation, 1) + } + case LocalResponse.EliminateDeployable(obj : TelepadDeployable, guid, pos) => //if active, deactivate if(obj.Active) { @@ -4234,7 +4199,7 @@ class WorldSessionActor extends Actor case Some(boomer : BoomerDeployable) => boomer.Exploded = true continent.LocalEvents ! LocalServiceMessage(continent.Id, LocalAction.Detonate(boomer.GUID, boomer)) - AnnounceDestroyDeployable(boomer, Some(500 milliseconds)) + Deployables.AnnounceDestroyDeployable(boomer, Some(500 milliseconds)) case Some(_) | None => ; } FindEquipmentToDelete(item_guid, trigger)