mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-03-23 14:20:45 +00:00
force dome is now an amenity owned by its encompassing capitol facility and has its own control agency that is aware of the faction affinity, hack state, etc. conditions that would cause it to close over or open up
This commit is contained in:
parent
1d57cca1d3
commit
8fedd2e724
8 changed files with 354 additions and 124 deletions
|
|
@ -1060,7 +1060,7 @@ class ZoningOperations(
|
|||
case _ => ()
|
||||
}
|
||||
// capitol force dome state
|
||||
if (building.IsCapitol && building.ForceDomeActive) {
|
||||
if (building.IsCapitol && building.ForceDome.exists(_.Energized)) {
|
||||
sendResponse(GenericObjectActionMessage(guid, 13))
|
||||
}
|
||||
// amenities
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import net.psforever.objects.zones.blockmap.{BlockMapEntity, SectorGroup}
|
|||
import net.psforever.objects.{ConstructionItem, PlanetSideGameObject, Player, Vehicle}
|
||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, PlanetSideGeneratorState, Vector3}
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import net.psforever.actors.zone.building.MajorFacilityLogic
|
||||
import net.psforever.objects.avatar.scoring.Kill
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminalAwareBehavior
|
||||
|
|
@ -110,7 +109,6 @@ class ZoneActor(
|
|||
//warp gates are controlled by game logic and are better off not restored via the database
|
||||
case Some(b) =>
|
||||
if ((b.Faction = PlanetSideEmpire(building.factionId)) != PlanetSideEmpire.NEUTRAL) {
|
||||
b.ForceDomeActive = MajorFacilityLogic.checkForceDomeStatus(b).getOrElse(false)
|
||||
b.Neighbours.getOrElse(Nil).foreach(_.Actor ! BuildingActor.AlertToFactionChange(b))
|
||||
b.CaptureTerminal.collect { terminal =>
|
||||
val msg = CaptureTerminalAwareBehavior.TerminalStatusChanged(terminal, isResecured = true)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import net.psforever.services.{InterstellarClusterService, Service}
|
|||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, PlanetSideGeneratorState}
|
||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
|
||||
|
||||
/**
|
||||
* A package class that conveys the important information for handling facility updates.
|
||||
|
|
@ -56,99 +56,6 @@ case object MajorFacilityLogic
|
|||
MajorFacilityWrapper(building, context, details.galaxyService, details.interstellarCluster)
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the conditions of the building
|
||||
* and determine if its capitol force dome state should be updated
|
||||
* to reflect the actual conditions of the base or its surrounding bases.
|
||||
* If this building is considered a subcapitol facility to the zone's actual capitol facility,
|
||||
* and has the capitol force dome has a dependency upon it,
|
||||
* pass a message onto that facility that it should check its own state alignment.
|
||||
* @param mapUpdateOnChange if `true`, dispatch a `MapUpdate` message for this building
|
||||
*/
|
||||
private def alignForceDomeStatus(details: BuildingWrapper, mapUpdateOnChange: Boolean = true): Behavior[Command] = {
|
||||
val building = details.building
|
||||
checkForceDomeStatus(building) match {
|
||||
case Some(updatedStatus) if updatedStatus != building.ForceDomeActive =>
|
||||
updateForceDomeStatus(details, updatedStatus, mapUpdateOnChange)
|
||||
case _ => ;
|
||||
}
|
||||
Behaviors.same
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a message to update the state of the clients with the server state of the capitol force dome.
|
||||
* @param updatedStatus the new capitol force dome status
|
||||
* @param mapUpdateOnChange if `true`, dispatch a `MapUpdate` message for this building
|
||||
*/
|
||||
private def updateForceDomeStatus(
|
||||
details: BuildingWrapper,
|
||||
updatedStatus: Boolean,
|
||||
mapUpdateOnChange: Boolean
|
||||
): Unit = {
|
||||
val building = details.building
|
||||
val zone = building.Zone
|
||||
building.ForceDomeActive = updatedStatus
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.UpdateForceDomeStatus(Service.defaultPlayerGUID, building.GUID, updatedStatus)
|
||||
)
|
||||
if (mapUpdateOnChange) {
|
||||
details.context.self ! BuildingActor.MapUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The natural conditions of a facility that is not eligible for its capitol force dome to be expanded.
|
||||
* The only test not employed is whether or not the target building is a capitol.
|
||||
* Ommission of this condition makes this test capable of evaluating subcapitol eligibility
|
||||
* for capitol force dome expansion.
|
||||
* @param building the target building
|
||||
* @return `true`, if the conditions for capitol force dome are not met;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
private def invalidBuildingCapitolForceDomeConditions(building: Building): Boolean = {
|
||||
building.Faction == PlanetSideEmpire.NEUTRAL ||
|
||||
building.NtuLevel == 0 ||
|
||||
(building.Generator match {
|
||||
case Some(o) => o.Condition == PlanetSideGeneratorState.Destroyed
|
||||
case _ => false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* If this building is a capitol major facility,
|
||||
* use the faction affinity, the generator status, and the resource silo's capacitance level
|
||||
* to determine if the capitol force dome should be active.
|
||||
* @param building the building being evaluated
|
||||
* @return the condition of the capitol force dome;
|
||||
* `None`, if the facility is not a capitol building;
|
||||
* `Some(true|false)` to indicate the state of the force dome
|
||||
*/
|
||||
def checkForceDomeStatus(building: Building): Option[Boolean] = {
|
||||
if (building.IsCapitol) {
|
||||
val originalStatus = building.ForceDomeActive
|
||||
val faction = building.Faction
|
||||
val updatedStatus = if (invalidBuildingCapitolForceDomeConditions(building)) {
|
||||
false
|
||||
} else {
|
||||
val ownedSubCapitols = building.Neighbours(faction) match {
|
||||
case Some(buildings: Set[Building]) => buildings.count { b => !invalidBuildingCapitolForceDomeConditions(b) }
|
||||
case None => 0
|
||||
}
|
||||
if (originalStatus && ownedSubCapitols <= 1) {
|
||||
false
|
||||
} else if (!originalStatus && ownedSubCapitols > 1) {
|
||||
true
|
||||
} else {
|
||||
originalStatus
|
||||
}
|
||||
}
|
||||
Some(updatedStatus)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The power structure of major facilities has to be statused on the continental map
|
||||
* via the state of its nanite-to-energy generator, and
|
||||
|
|
@ -267,7 +174,7 @@ case object MajorFacilityLogic
|
|||
}
|
||||
|
||||
/**
|
||||
* The generator is an extrememly important amenity of a major facility
|
||||
* The generator is an extremely important amenity of a major facility
|
||||
* that is given its own status indicators that are apparent from the continental map
|
||||
* and warning messages that are displayed to everyone who might have an interest in the that particular generator.
|
||||
* @param details package class that conveys the important information
|
||||
|
|
@ -314,7 +221,6 @@ case object MajorFacilityLogic
|
|||
true
|
||||
case Some(GeneratorControl.Event.Offline) =>
|
||||
powerLost(details)
|
||||
alignForceDomeStatus(details, mapUpdateOnChange = false)
|
||||
val zone = building.Zone
|
||||
val msg = AvatarAction.PlanetsideAttributeToAll(building.GUID, 46, 2)
|
||||
building.PlayersInSOI.foreach { player =>
|
||||
|
|
@ -326,7 +232,6 @@ case object MajorFacilityLogic
|
|||
case Some(GeneratorControl.Event.Online) =>
|
||||
// Power restored. Reactor Online. Sensors Online. Weapons Online. All systems nominal.
|
||||
powerRestored(details)
|
||||
alignForceDomeStatus(details, mapUpdateOnChange = false)
|
||||
val events = zone.AvatarEvents
|
||||
val guid = building.GUID
|
||||
val msg1 = AvatarAction.PlanetsideAttributeToAll(guid, 46, 0)
|
||||
|
|
@ -348,16 +253,17 @@ case object MajorFacilityLogic
|
|||
): Behavior[Command] = {
|
||||
if (details.asInstanceOf[MajorFacilityWrapper].hasNtuSupply) {
|
||||
BuildingActor.setFactionTo(details, faction, log)
|
||||
alignForceDomeStatus(details, mapUpdateOnChange = false)
|
||||
val building = details.building
|
||||
building.Neighbours.getOrElse(Nil).foreach { _.Actor ! BuildingActor.AlertToFactionChange(building) }
|
||||
val alertMsg = BuildingActor.AlertToFactionChange(building)
|
||||
building.Neighbours.getOrElse(Nil).foreach { _.Actor ! alertMsg }
|
||||
building.Amenities.foreach { _.Actor ! alertMsg }
|
||||
}
|
||||
Behaviors.same
|
||||
}
|
||||
|
||||
def alertToFactionChange(details: BuildingWrapper, building: Building): Behavior[Command] = {
|
||||
alignForceDomeStatus(details)
|
||||
val bldg = details.building
|
||||
bldg.Amenities.foreach { _.Actor ! BuildingActor.AlertToFactionChange(building) } //todo map update?
|
||||
//the presence of the flag means that we are involved in an ongoing llu hack
|
||||
(bldg.GetFlag, bldg.CaptureTerminal) match {
|
||||
case (Some(flag), Some(terminal)) if (flag.Target eq building) && flag.Faction != building.Faction =>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,313 @@
|
|||
// Copyright (c) 2025 PSForever
|
||||
package net.psforever.objects.serverobject.dome
|
||||
|
||||
import net.psforever.actors.zone.BuildingActor
|
||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
import net.psforever.objects.serverobject.structures.{Amenity, Building, PoweredAmenityControl}
|
||||
import net.psforever.objects.serverobject.terminals.capture.{CaptureTerminal, CaptureTerminalAware, CaptureTerminalAwareBehavior}
|
||||
import net.psforever.objects.serverobject.turret.FacilityTurret
|
||||
import net.psforever.packet.game.ChatMsg
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||
import net.psforever.types.{ChatMessageType, PlanetSideEmpire, PlanetSideGeneratorState, Vector3}
|
||||
|
||||
object ForceDomeControl {
|
||||
trait Command
|
||||
|
||||
final case object CustomExpand extends Command
|
||||
|
||||
final case object CustomCollapse extends Command
|
||||
|
||||
final case object NormalBehavior extends Command
|
||||
|
||||
/**
|
||||
* Dispatch a message to update the state of the clients with the server state of the capitol force dome.
|
||||
* @param dome force dome
|
||||
* @param activationState new force dome status
|
||||
*/
|
||||
def ChangeDomeEnergizedState(dome: ForceDomePhysics, activationState: Boolean): Unit = {
|
||||
dome.Energized = activationState
|
||||
val owner = dome.Owner
|
||||
val zone = owner.Zone
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.UpdateForceDomeStatus(Service.defaultPlayerGUID, owner.GUID, activationState)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* If this building is a capitol major facility,
|
||||
* use the faction affinity, the generator status, and the resource silo's capacitance level
|
||||
* to determine if the capitol force dome should be active.
|
||||
* @param building building being evaluated
|
||||
* @param dome force dome
|
||||
* @return the condition of the capitol force dome;
|
||||
* `None`, if the facility is not a capitol building;
|
||||
* `Some(true|false)` to indicate the state of the force dome
|
||||
*/
|
||||
def CheckForceDomeStatus(building: Building, dome: ForceDomePhysics): Option[Boolean] = {
|
||||
if (building.IsCapitol) {
|
||||
Some(
|
||||
if (ForceDomeControl.InvalidBuildingCapitolForceDomeConditions(building)) {
|
||||
false
|
||||
} else {
|
||||
building
|
||||
.Neighbours(building.Faction)
|
||||
.map(_.count(b => !ForceDomeControl.InvalidBuildingCapitolForceDomeConditions(b)))
|
||||
.exists(_ > 1)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The natural conditions of a facility that is not eligible for its capitol force dome to be expanded.
|
||||
* The only test not employed is whether or not the target building is a capitol.
|
||||
* Omission of this condition makes this test capable of evaluating subcapitol eligibility
|
||||
* for capitol force dome expansion.
|
||||
* @param building target building
|
||||
* @return `true`, if the conditions for capitol force dome are not met;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def InvalidBuildingCapitolForceDomeConditions(building: Building): Boolean = {
|
||||
building.Faction == PlanetSideEmpire.NEUTRAL ||
|
||||
building.NtuLevel == 0 ||
|
||||
building.Generator.exists(_.Condition == PlanetSideGeneratorState.Destroyed)
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param dome force dome
|
||||
* @return na
|
||||
*/
|
||||
def GeneralFacilityPerimeter(dome: ForceDomePhysics): List[(Vector3, Vector3)] = {
|
||||
val generatorTowerCenter = dome.Position.xy
|
||||
val turretPoints = dome.Owner.Amenities.filter(_.isInstanceOf[FacilityTurret]).map(_.Position.xy)
|
||||
val pointsOfForceDomePerimeter = turretPoints.map { p =>
|
||||
val segmentFromTowerToTurret = p - generatorTowerCenter
|
||||
Vector3.Unit(segmentFromTowerToTurret) * (Vector3.Magnitude(segmentFromTowerToTurret) + 20) //todo get correct distance offset
|
||||
}
|
||||
pointsOfForceDomePerimeter
|
||||
.flatMap { point =>
|
||||
pointsOfForceDomePerimeter
|
||||
.sortBy(p => Vector3.DistanceSquared(p, point))
|
||||
.slice(1, 3)
|
||||
.map { otherPoint =>
|
||||
if (point.y > otherPoint.y || point.x < otherPoint.x) {
|
||||
(point, otherPoint)
|
||||
} else {
|
||||
(otherPoint, point)
|
||||
}
|
||||
}
|
||||
}
|
||||
.distinct
|
||||
}
|
||||
|
||||
def TechPlantFacilityPerimeter(dome: ForceDomePhysics): List[(Vector3, Vector3)] = {
|
||||
val generatorTowerCenter = dome.Position.xy
|
||||
val turretPoints = dome.Owner.Amenities.filter(_.isInstanceOf[FacilityTurret]).map(_.Position.xy)
|
||||
val organizedByClosestToGarage = dome
|
||||
.Owner
|
||||
.Amenities
|
||||
.find(_.Definition.Name.equals("gr_door_garage_ext"))
|
||||
.map { garage =>
|
||||
val doorPosition = garage.Position.xy
|
||||
turretPoints.sortBy(point => Vector3.DistanceSquared(doorPosition, point))
|
||||
}
|
||||
.getOrElse(List[Vector3]())
|
||||
|
||||
//val turretPoints = dome.Owner.Amenities.filter(_.isInstanceOf[FacilityTurret]).map(_.Position.xy)
|
||||
val pointsOfForceDomePerimeter = turretPoints.map { p =>
|
||||
val segmentFromTowerToTurret = p - generatorTowerCenter
|
||||
Vector3.Unit(segmentFromTowerToTurret) * (Vector3.Magnitude(segmentFromTowerToTurret) + 20) //todo get correct distance offset
|
||||
}
|
||||
Nil
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param building target building
|
||||
* @param state na
|
||||
*/
|
||||
def CustomDomeStateEnforcedMessage(
|
||||
building: Building,
|
||||
state: Boolean
|
||||
): Unit = {
|
||||
val events = building.Zone.LocalEvents
|
||||
val message = LocalAction.SendResponse(ChatMsg(
|
||||
ChatMessageType.UNK_227,
|
||||
s"Capitol force dome state change was suppressed. ${building.Name} will remain ${if (state) "enveloped" else "exposed"}."
|
||||
))
|
||||
building.PlayersInSOI.foreach { player =>
|
||||
events ! LocalServiceMessage(player.Name, message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param building target building
|
||||
*/
|
||||
def NormalDomeStateMessage(building: Building): Unit = {
|
||||
val events = building.Zone.LocalEvents
|
||||
val message = LocalAction.SendResponse(ChatMsg(
|
||||
ChatMessageType.UNK_227,
|
||||
"Expected capitol force dome state change will resume."
|
||||
))
|
||||
building.PlayersInSOI.foreach { player =>
|
||||
events ! LocalServiceMessage(player.Name, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific capitol facility's force dome.
|
||||
* @param dome the `ForceDomePhysics` object being governed
|
||||
*/
|
||||
class ForceDomeControl(dome: ForceDomePhysics)
|
||||
extends PoweredAmenityControl
|
||||
with CaptureTerminalAwareBehavior
|
||||
with FactionAffinityBehavior.Check {
|
||||
def CaptureTerminalAwareObject: Amenity with CaptureTerminalAware = dome
|
||||
def FactionObject: FactionAffinity = dome
|
||||
|
||||
private var perimeterSegments: List[(Vector3, Vector3)] = Nil
|
||||
|
||||
private lazy val domeOwnerAsABuilding = dome.Owner.asInstanceOf[Building]
|
||||
|
||||
private var customState: Option[Boolean] = None
|
||||
|
||||
def commonBehavior: Receive = checkBehavior
|
||||
.orElse {
|
||||
case Service.Startup() =>
|
||||
setupPerimeter()
|
||||
|
||||
case ForceDomeControl.CustomExpand
|
||||
if !dome.Energized && (customState.isEmpty || customState.contains(false)) =>
|
||||
customState = Some(true)
|
||||
ForceDomeControl.CustomDomeStateEnforcedMessage(domeOwnerAsABuilding, state = true)
|
||||
ForceDomeControl.ChangeDomeEnergizedState(dome, activationState = true)
|
||||
|
||||
case ForceDomeControl.CustomExpand
|
||||
if customState.isEmpty =>
|
||||
customState = Some(true)
|
||||
ForceDomeControl.CustomDomeStateEnforcedMessage(domeOwnerAsABuilding, state = true)
|
||||
|
||||
case ForceDomeControl.CustomCollapse
|
||||
if dome.Energized && (customState.isEmpty || customState.contains(true)) =>
|
||||
customState = Some(false)
|
||||
ForceDomeControl.CustomDomeStateEnforcedMessage(domeOwnerAsABuilding, state = false)
|
||||
ForceDomeControl.ChangeDomeEnergizedState(dome, activationState = false)
|
||||
|
||||
case ForceDomeControl.CustomCollapse
|
||||
if customState.isEmpty =>
|
||||
customState = Some(false)
|
||||
ForceDomeControl.CustomDomeStateEnforcedMessage(domeOwnerAsABuilding, state = false)
|
||||
|
||||
case ForceDomeControl.NormalBehavior
|
||||
if customState.nonEmpty =>
|
||||
customState = None
|
||||
ForceDomeControl.NormalDomeStateMessage(domeOwnerAsABuilding)
|
||||
alignForceDomeStatusAndUpdate(domeOwnerAsABuilding)
|
||||
}
|
||||
|
||||
def poweredStateLogic: Receive = {
|
||||
commonBehavior
|
||||
.orElse(captureTerminalAwareBehaviour)
|
||||
.orElse {
|
||||
case BuildingActor.AlertToFactionChange(_) =>
|
||||
blockedByCustomStateOr(alignForceDomeStatusAndUpdate, domeOwnerAsABuilding)
|
||||
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
def unpoweredStateLogic: Receive = {
|
||||
commonBehavior
|
||||
.orElse {
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
||||
def powerTurnOffCallback() : Unit = {
|
||||
if (dome.Energized && customState.isEmpty) {
|
||||
ForceDomeControl.ChangeDomeEnergizedState(dome,activationState = false)
|
||||
}
|
||||
}
|
||||
|
||||
def powerTurnOnCallback() : Unit = {
|
||||
blockedByCustomStateOr(alignForceDomeStatus, domeOwnerAsABuilding)
|
||||
}
|
||||
|
||||
override protected def captureTerminalIsResecured(terminal: CaptureTerminal): Unit = {
|
||||
super.captureTerminalIsResecured(terminal)
|
||||
blockedByCustomStateOr(alignForceDomeStatus, domeOwnerAsABuilding)
|
||||
}
|
||||
|
||||
override protected def captureTerminalIsHacked(terminal: CaptureTerminal): Unit = {
|
||||
super.captureTerminalIsHacked(terminal)
|
||||
if (dome.Energized && customState.isEmpty) {
|
||||
ForceDomeControl.ChangeDomeEnergizedState(dome, activationState = false)
|
||||
}
|
||||
}
|
||||
|
||||
private def setupPerimeter(): Unit = {
|
||||
//todo tech plants have an indent
|
||||
if (perimeterSegments.isEmpty) {
|
||||
perimeterSegments = ForceDomeControl.GeneralFacilityPerimeter(dome)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param func function to run if not blocked
|
||||
* @param building facility to operate upon (parameter to `func`)
|
||||
* @return next behavior for an actor state
|
||||
*/
|
||||
private def blockedByCustomStateOr(func: Building => Unit, building: Building): Unit = {
|
||||
customState match {
|
||||
case None =>
|
||||
func(building)
|
||||
case Some(state) =>
|
||||
ForceDomeControl.CustomDomeStateEnforcedMessage(building, state)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the conditions of the building
|
||||
* and determine if its capitol force dome state should be updated
|
||||
* to reflect the actual conditions of the base or its surrounding bases.
|
||||
* If this building is considered a subcapitol facility to the zone's actual capitol facility,
|
||||
* and has the capitol force dome has a dependency upon it,
|
||||
* pass a message onto that facility that it should check its own state alignment.
|
||||
* @param building the building being evaluated
|
||||
*/
|
||||
private def alignForceDomeStatusAndUpdate(building: Building): Unit = {
|
||||
ForceDomeControl.CheckForceDomeStatus(building, dome).foreach {
|
||||
updatedStatus =>
|
||||
if (updatedStatus != dome.Energized) {
|
||||
ForceDomeControl.ChangeDomeEnergizedState(dome, updatedStatus)
|
||||
dome.Owner.Actor ! BuildingActor.MapUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the conditions of the building
|
||||
* and determine if its capitol force dome state should be updated
|
||||
* to reflect the actual conditions of the base or its surrounding bases.
|
||||
* If this building is considered a subcapitol facility to the zone's actual capitol facility,
|
||||
* and has the capitol force dome has a dependency upon it,
|
||||
* pass a message onto that facility that it should check its own state alignment.
|
||||
* @param building the building being evaluated
|
||||
*/
|
||||
private def alignForceDomeStatus(building: Building): Unit = {
|
||||
ForceDomeControl.CheckForceDomeStatus(building, dome).foreach {
|
||||
updatedStatus =>
|
||||
if (updatedStatus != dome.Energized) {
|
||||
ForceDomeControl.ChangeDomeEnergizedState(dome, updatedStatus)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,12 @@
|
|||
package net.psforever.objects.serverobject.dome
|
||||
|
||||
import net.psforever.objects.serverobject.structures.Amenity
|
||||
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminalAware
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
class ForceDomePhysics(private val cfddef: ForceDomeDefinition)
|
||||
extends Amenity {
|
||||
extends Amenity
|
||||
with CaptureTerminalAware {
|
||||
private var energized: Boolean = false
|
||||
|
||||
def Energized: Boolean = energized
|
||||
|
|
@ -23,18 +25,18 @@ object ForceDomePhysics {
|
|||
|
||||
/**
|
||||
* Instantiate and configure a `CapitolForceDome` object.
|
||||
* @param pos positon of the object in the zone's coordinate system
|
||||
* @param pos position of the object in the zone's coordinate system
|
||||
* @param fddef specific type of force dome
|
||||
* @param id the unique id that will be assigned to this entity
|
||||
* @param context a context to allow the object to properly set up `ActorSystem` functionality
|
||||
* @return the `CapitolForceDome` object
|
||||
*/
|
||||
def Constructor(pos: Vector3)(id: Int, context: ActorContext): ForceDomePhysics = {
|
||||
//import akka.actor.Props
|
||||
import net.psforever.objects.GlobalDefinitions
|
||||
def Constructor(pos: Vector3, fddef: ForceDomeDefinition)(id: Int, context: ActorContext): ForceDomePhysics = {
|
||||
import akka.actor.Props
|
||||
|
||||
val obj = new ForceDomePhysics(GlobalDefinitions.force_dome_generator)
|
||||
val obj = new ForceDomePhysics(fddef)
|
||||
obj.Position = pos
|
||||
//obj.Actor = context.actorOf(Props(classOf[null], obj), s"${GlobalDefinitions.door.Name}_$id")
|
||||
obj.Actor = context.actorOf(Props(classOf[ForceDomeControl], obj), name = s"${fddef.Name}_$id")
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import net.psforever.packet.game.{Additional3, BuildingInfoUpdateMessage, Densit
|
|||
import net.psforever.types._
|
||||
import scalax.collection.{Graph, GraphEdge}
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import net.psforever.objects.serverobject.dome.ForceDomePhysics
|
||||
import net.psforever.objects.serverobject.llu.{CaptureFlag, CaptureFlagSocket}
|
||||
import net.psforever.objects.serverobject.structures.participation.{MajorFacilityHackParticipation, NoParticipation, ParticipationLogic, TowerHackParticipation}
|
||||
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
||||
|
|
@ -32,7 +33,6 @@ class Building(
|
|||
|
||||
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
private var playersInSOI: List[Player] = List.empty
|
||||
private var forceDomeActive: Boolean = false
|
||||
private var participationFunc: ParticipationLogic = NoParticipation
|
||||
var virusId: Long = 8 // 8 default = no virus
|
||||
var virusInstalledBy: Option[Int] = None // faction id
|
||||
|
|
@ -59,11 +59,6 @@ class Building(
|
|||
case None => false
|
||||
}
|
||||
}
|
||||
def ForceDomeActive: Boolean = forceDomeActive
|
||||
def ForceDomeActive_=(activated: Boolean): Boolean = {
|
||||
forceDomeActive = activated
|
||||
forceDomeActive
|
||||
}
|
||||
|
||||
def Faction: PlanetSideEmpire.Value = faction
|
||||
|
||||
|
|
@ -108,6 +103,13 @@ class Building(
|
|||
}
|
||||
}
|
||||
|
||||
def ForceDome: Option[ForceDomePhysics] = {
|
||||
Amenities.find(_.isInstanceOf[ForceDomePhysics]) match {
|
||||
case Some(out: ForceDomePhysics) => Some(out)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
def NtuSource: Option[NtuContainer] = {
|
||||
Amenities.find(_.isInstanceOf[NtuContainer]) match {
|
||||
case Some(o: NtuContainer) => Some(o)
|
||||
|
|
@ -223,6 +225,7 @@ class Building(
|
|||
else {
|
||||
(virusId.toInt, Some(Additional3(inform_defenders=true, virusInstalledBy.getOrElse(3))))
|
||||
}
|
||||
val forceDomeActive = ForceDome.exists(_.Energized)
|
||||
|
||||
BuildingInfoUpdateMessage(
|
||||
Zone.Number,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import net.psforever.objects.geometry.d3.VolumetricGeometry
|
|||
import net.psforever.objects.guid.pool.NumberPool
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.serverobject.dome.{ForceDomeDefinition, ForceDomePhysics}
|
||||
import net.psforever.objects.serverobject.doors.Door
|
||||
import net.psforever.objects.serverobject.environment.EnvironmentAttribute
|
||||
import net.psforever.objects.serverobject.interior.{InteriorAware, Sidedness}
|
||||
|
|
@ -1638,6 +1639,13 @@ object Zone {
|
|||
case painbox: Painbox =>
|
||||
painbox.Actor ! Service.Startup()
|
||||
}
|
||||
//capitol facilities have force domes
|
||||
buildings.values
|
||||
.flatMap(_.Amenities.filter(_.Definition.isInstanceOf[ForceDomeDefinition]))
|
||||
.collect {
|
||||
case obj: ForceDomePhysics =>
|
||||
obj.Actor ! Service.Startup()
|
||||
}
|
||||
//the orbital_buildings in sanctuary zones have to establish their shuttle routes
|
||||
map.shuttleBays
|
||||
.map {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import io.circe.parser._
|
|||
import net.psforever.objects.{GlobalDefinitions, LocalLockerItem, LocalProjectile}
|
||||
import net.psforever.objects.definition.BasicDefinition
|
||||
import net.psforever.objects.guid.selector.{NumberSelector, RandomSelector, SpecificSelector}
|
||||
import net.psforever.objects.serverobject.dome.ForceDomePhysics
|
||||
import net.psforever.objects.serverobject.dome.{ForceDomeDefinition, ForceDomePhysics}
|
||||
import net.psforever.objects.serverobject.doors.{Door, DoorDefinition, SpawnTubeDoor}
|
||||
import net.psforever.objects.serverobject.generator.Generator
|
||||
import net.psforever.objects.serverobject.llu.{CaptureFlagSocket, CaptureFlagSocketDefinition}
|
||||
|
|
@ -385,7 +385,7 @@ object Zones {
|
|||
None,
|
||||
turretWeaponGuid
|
||||
)
|
||||
//force dome physics object are not owned
|
||||
//force dome physics objects have no owner
|
||||
//for our benefit, we can attach them as amenities to the zone's capitol facility
|
||||
zoneObjects
|
||||
.find { obj => forceDomeTypes.contains(obj.objectType) }
|
||||
|
|
@ -393,12 +393,12 @@ object Zones {
|
|||
structures
|
||||
.find { structure => Building.Capitols.contains(structure.objectName) }
|
||||
.foreach { capitol =>
|
||||
zoneMap
|
||||
.addLocalObject(
|
||||
forceDome.guid,
|
||||
ForceDomePhysics.Constructor(forceDome.position),
|
||||
owningBuildingGuid = capitol.guid
|
||||
)
|
||||
val definition = DefinitionUtil.fromString(forceDome.objectType).asInstanceOf[ForceDomeDefinition]
|
||||
zoneMap.addLocalObject(
|
||||
forceDome.guid,
|
||||
ForceDomePhysics.Constructor(forceDome.position, definition),
|
||||
owningBuildingGuid = capitol.guid
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue