From 50df2bace0e510697ffef78f86b25cf9f1ffce49 Mon Sep 17 00:00:00 2001 From: Mazo Date: Wed, 8 Jan 2020 13:31:02 +0000 Subject: [PATCH] Basic functionality for capitol force domes (#315) --- .../serverobject/structures/Building.scala | 55 ++++++++++++++++++- .../scala/services/local/LocalService.scala | 5 ++ .../services/local/LocalServiceMessage.scala | 1 + .../services/local/LocalServiceResponse.scala | 1 + .../src/main/scala/WorldSessionActor.scala | 13 +++++ 5 files changed, 74 insertions(+), 1 deletion(-) diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala index 7fa0ab898..e2a7f7941 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala @@ -15,6 +15,8 @@ import net.psforever.objects.zones.Zone import net.psforever.packet.game._ import net.psforever.types.{PlanetSideEmpire, Vector3} import scalax.collection.{Graph, GraphEdge} +import services.Service +import services.local.{LocalAction, LocalServiceMessage} class Building(private val name: String, private val building_guid : Int, @@ -28,6 +30,8 @@ class Building(private val name: String, */ private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL private var playersInSOI : List[Player] = List.empty + private val capitols = List("Thoth", "Voltan", "Neit", "Anguta", "Eisa", "Verica") + private var forceDomeActive : Boolean = false super.Zone_=(zone) GUID = PlanetSideGUID(building_guid) @@ -38,10 +42,31 @@ class Building(private val name: String, def MapId : Int = map_id + def IsCapitol : Boolean = capitols.contains(name) + def IsSubCapitol : Boolean = { + Neighbours match { + case Some(buildings: Set[Building]) => !buildings.filter(x => capitols.contains(x.name)).isEmpty + case None => false + } + } + def ForceDomeActive : Boolean = forceDomeActive + def ForceDomeActive_=(activated : Boolean) : Boolean = { + forceDomeActive = activated + forceDomeActive + } + def Faction : PlanetSideEmpire.Value = faction override def Faction_=(fac : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = { faction = fac + if(IsSubCapitol) { + Neighbours match { + case Some(buildings: Set[Building]) => buildings.filter(x => x.IsCapitol).head.UpdateForceDomeStatus() + case None => ; + } + } else if (IsCapitol) { + UpdateForceDomeStatus() + } TriggerZoneMapUpdate() Faction } @@ -95,6 +120,34 @@ class Building(private val name: String, if(Actor != ActorRef.noSender) Actor ! Building.TriggerZoneMapUpdate(Zone.Number) } + def UpdateForceDomeStatus() : Unit = { + if(IsCapitol) { + val originalStatus = ForceDomeActive + + if(Faction == PlanetSideEmpire.NEUTRAL) { + ForceDomeActive = false + } else { + val ownedSubCapitols = Neighbours(Faction) match { + case Some(buildings: Set[Building]) => buildings.size + case None => 0 + } + + if(ForceDomeActive && ownedSubCapitols <= 1) { + ForceDomeActive = false + } else if(!ForceDomeActive && ownedSubCapitols > 1) { + ForceDomeActive = true + } + } + + if(originalStatus != ForceDomeActive) { + if(Actor != ActorRef.noSender) { + Zone.LocalEvents ! LocalServiceMessage(Zone.Id, LocalAction.UpdateForceDomeStatus(Service.defaultPlayerGUID, GUID, ForceDomeActive)) + Actor ! Building.SendMapUpdate(all_clients = true) + } + } + } + } + // Get all lattice neighbours matching the specified faction def Neighbours(faction: PlanetSideEmpire.Value): Option[Set[Building]] = { this.Neighbours match { @@ -192,7 +245,7 @@ class Building(private val name: String, None, generatorState, spawnTubesNormal, - false, //force_dome_active + ForceDomeActive, latticeBenefit, 0, //cavern_benefit; !! Field > 0 will cause malformed packet. See class def. Nil, diff --git a/common/src/main/scala/services/local/LocalService.scala b/common/src/main/scala/services/local/LocalService.scala index 369e653b5..914bd5b59 100644 --- a/common/src/main/scala/services/local/LocalService.scala +++ b/common/src/main/scala/services/local/LocalService.scala @@ -146,6 +146,11 @@ class LocalService(zone : Zone) extends Actor { LocalEvents.publish( LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.TriggerSound(sound, pos, unk, volume)) ) + case LocalAction.UpdateForceDomeStatus(player_guid, building_guid, activated) => { + LocalEvents.publish( + LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.UpdateForceDomeStatus(building_guid, activated)) + ) + } case _ => ; } diff --git a/common/src/main/scala/services/local/LocalServiceMessage.scala b/common/src/main/scala/services/local/LocalServiceMessage.scala index 7c1a9a9b6..ed0887c57 100644 --- a/common/src/main/scala/services/local/LocalServiceMessage.scala +++ b/common/src/main/scala/services/local/LocalServiceMessage.scala @@ -39,4 +39,5 @@ object LocalAction { final case class TriggerEffectInfo(player_guid : PlanetSideGUID, effect : String, target : PlanetSideGUID, unk1 : Boolean, unk2 : Long) extends Action final case class TriggerEffectLocation(player_guid : PlanetSideGUID, effect : String, pos : Vector3, orient : Vector3) extends Action final case class TriggerSound(player_guid : PlanetSideGUID, sound : TriggeredSound.Value, pos : Vector3, unk : Int, volume : Float) extends Action + final case class UpdateForceDomeStatus(player_guid : PlanetSideGUID, building_guid : PlanetSideGUID, activated : Boolean) extends Action } diff --git a/common/src/main/scala/services/local/LocalServiceResponse.scala b/common/src/main/scala/services/local/LocalServiceResponse.scala index abc752aaa..7d856c917 100644 --- a/common/src/main/scala/services/local/LocalServiceResponse.scala +++ b/common/src/main/scala/services/local/LocalServiceResponse.scala @@ -35,4 +35,5 @@ object LocalResponse { final case class ToggleTeleportSystem(router : Vehicle, systemPlan : Option[(Utility.InternalTelepad, TelepadDeployable)]) extends Response final case class TriggerEffect(target: PlanetSideGUID, effect: String, effectInfo: Option[TriggeredEffect] = None, triggeredLocation: Option[TriggeredEffectLocation] = None) extends Response final case class TriggerSound(sound : TriggeredSound.Value, pos : Vector3, unk : Int, volume : Float) extends Response + final case class UpdateForceDomeStatus(building_guid : PlanetSideGUID, activated : Boolean) extends Response } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index d98639297..2eb3f95a4 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -1688,6 +1688,13 @@ class WorldSessionActor extends Actor case LocalResponse.TriggerSound(sound, pos, unk, volume) => sendResponse(TriggerSoundMessage(sound, pos, unk, volume)) + case LocalResponse.UpdateForceDomeStatus(building_guid, activated) => { + if(activated) { + sendResponse(GenericObjectActionMessage(building_guid, 11)) + } else { + sendResponse(GenericObjectActionMessage(building_guid, 12)) + } + } case _ => ; } } @@ -7594,6 +7601,12 @@ class WorldSessionActor extends Actor def configZone(zone : Zone) : Unit = { zone.Buildings.values.foreach(building => { sendResponse(SetEmpireMessage(building.GUID, building.Faction)) + + // Synchronise capitol force dome state + if(building.IsCapitol && building.ForceDomeActive) { + sendResponse(GenericObjectActionMessage(building.GUID, 13)) + } + building.Amenities.foreach(amenity => { val amenityId = amenity.GUID sendResponse(PlanetsideAttributeMessage(amenityId, 50, 0))