diff --git a/common/src/main/scala/services/local/LocalService.scala b/common/src/main/scala/services/local/LocalService.scala index 1c5818ed3..21b137c86 100644 --- a/common/src/main/scala/services/local/LocalService.scala +++ b/common/src/main/scala/services/local/LocalService.scala @@ -7,6 +7,7 @@ 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 @@ -64,6 +65,10 @@ class LocalService(zone : Zone) extends Actor { LocalEvents.publish( LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.DeployableMapIcon(behavior, deployInfo)) ) + case LocalAction.Detonate(guid, obj) => + LocalEvents.publish( + LocalServiceResponse(s"/$forChannel/Local", Service.defaultPlayerGUID, LocalResponse.Detonate(guid, obj)) + ) case LocalAction.DoorOpens(player_guid, _, door) => doorCloser ! DoorCloseActor.DoorIsOpen(door, zone) LocalEvents.publish( @@ -282,8 +287,21 @@ class LocalService(zone : Zone) extends Actor { } //synchronized damage calculations - case Vitality.DamageOn(target : Deployable, func) => - val cause = func(target) + 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) case msg => diff --git a/common/src/main/scala/services/local/LocalServiceMessage.scala b/common/src/main/scala/services/local/LocalServiceMessage.scala index 3e81c479d..7c1a9a9b6 100644 --- a/common/src/main/scala/services/local/LocalServiceMessage.scala +++ b/common/src/main/scala/services/local/LocalServiceMessage.scala @@ -25,6 +25,7 @@ object LocalAction { final case class AlertDestroyDeployable(player_guid : PlanetSideGUID, obj : PlanetSideGameObject with Deployable) extends Action final case class DeployableMapIcon(player_guid : PlanetSideGUID, behavior : DeploymentAction.Value, deployInfo : DeployableInfo) extends Action + final case class Detonate(guid : PlanetSideGUID, obj : PlanetSideGameObject) extends Action final case class DoorOpens(player_guid : PlanetSideGUID, continent : Zone, door : Door) extends Action final case class DoorCloses(player_guid : PlanetSideGUID, door_guid : PlanetSideGUID) extends Action final case class HackClear(player_guid : PlanetSideGUID, target : PlanetSideServerObject, unk1 : Long, unk2 : Long = 8L) extends Action diff --git a/common/src/main/scala/services/local/LocalServiceResponse.scala b/common/src/main/scala/services/local/LocalServiceResponse.scala index cd31aa7a4..abc752aaa 100644 --- a/common/src/main/scala/services/local/LocalServiceResponse.scala +++ b/common/src/main/scala/services/local/LocalServiceResponse.scala @@ -19,6 +19,7 @@ object LocalResponse { final case class AlertDestroyDeployable(obj : PlanetSideGameObject with Deployable) extends Response final case class DeployableMapIcon(action : DeploymentAction.Value, deployInfo : DeployableInfo) extends Response + final case class Detonate(guid : PlanetSideGUID, obj : PlanetSideGameObject) extends Response final case class DoorOpens(door_guid : PlanetSideGUID) extends Response final case class DoorCloses(door_guid : PlanetSideGUID) extends Response final case class EliminateDeployable(obj : PlanetSideGameObject with Deployable, object_guid : PlanetSideGUID, pos : Vector3) extends Response diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 4459a930b..1fd112149 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -1116,6 +1116,16 @@ class WorldSessionActor extends Actor 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 : SimpleDeployable, _) => //boomers, mines if(target.Health <= 0) { @@ -1531,6 +1541,14 @@ class WorldSessionActor extends Actor sendResponse(DeployableObjectsInfoMessage(behavior, deployInfo)) } + case LocalResponse.Detonate(guid, obj : BoomerDeployable) => + sendResponse(TriggerEffectMessage(guid, "detonate_boomer")) + sendResponse(PlanetsideAttributeMessage(guid, 29, 1)) + sendResponse(ObjectDeleteMessage(guid, 0)) + + case LocalResponse.Detonate(guid, obj) => + log.warn(s"LocalAction.Detonate: ${obj.Definition.Name} not configured to explode correctly") + case LocalResponse.DoorOpens(door_guid) => if(tplayer_guid != guid) { sendResponse(GenericObjectStateMsg(door_guid, 16)) @@ -1556,7 +1574,7 @@ class WorldSessionActor extends Actor } case LocalResponse.EliminateDeployable(obj : ExplosiveDeployable, guid, pos) => - if(obj.Exploded || obj.Health == 0) { + if(obj.Exploded || obj.Jammed || obj.Health == 0) { DeconstructDeployable(obj, guid, pos) } else { @@ -4196,15 +4214,9 @@ class WorldSessionActor extends Actor continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.ChangeFireState_Start(playerGUID, item_guid)) continent.GUID(trigger.Companion) match { case Some(boomer : BoomerDeployable) => - val boomerGUID = boomer.GUID boomer.Exploded = true - sendResponse(TriggerEffectMessage(boomerGUID, "detonate_boomer")) - sendResponse(PlanetsideAttributeMessage(boomerGUID, 29, 1)) - sendResponse(ObjectDeleteMessage(boomerGUID, 0)) - continent.LocalEvents ! LocalServiceMessage(continent.Id, LocalAction.TriggerEffect(playerGUID, "detonate_boomer", boomerGUID)) - continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(boomerGUID, 29, 1)) - continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(playerGUID, boomerGUID)) - continent.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.AddTask(boomer, continent, Some(0 seconds))) + continent.LocalEvents ! LocalServiceMessage(continent.Id, LocalAction.Detonate(boomer.GUID, boomer)) + AnnounceDestroyDeployable(boomer, Some(500 milliseconds)) case Some(_) | None => ; } FindEquipmentToDelete(item_guid, trigger)