mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-03-23 14:20:45 +00:00
force dome messages owner about change in state, triggering the NTU silo to give away repairs for free; activating the force dome kills or destroys all enemies within its radius
This commit is contained in:
parent
8fedd2e724
commit
6a960ed5ac
8 changed files with 262 additions and 98 deletions
|
|
@ -6,7 +6,9 @@ import akka.actor.typed.{ActorRef, Behavior}
|
|||
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
|
||||
import net.psforever.actors.commands.NtuCommand
|
||||
import net.psforever.actors.zone.{BuildingActor, BuildingControlDetails, ZoneActor}
|
||||
import net.psforever.objects.serverobject.dome.ForceDomePhysics
|
||||
import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl}
|
||||
import net.psforever.objects.serverobject.resourcesilo.ResourceSiloControl
|
||||
import net.psforever.objects.serverobject.structures.{Amenity, Building}
|
||||
import net.psforever.objects.serverobject.terminals.capture.{CaptureTerminal, CaptureTerminalAware, CaptureTerminalAwareBehavior}
|
||||
import net.psforever.objects.sourcing.PlayerSource
|
||||
|
|
@ -104,6 +106,10 @@ case object MajorFacilityLogic
|
|||
)
|
||||
}
|
||||
// No map update needed - will be sent by `HackCaptureActor` when required
|
||||
case dome: ForceDomePhysics =>
|
||||
// The force dome being expanded modifies the NTU drain rate
|
||||
val multiplier: Float = calculateNtuDrainMultiplierFrom(details.building, domeOpt = Some(dome))
|
||||
details.building.NtuSource.foreach(_.Actor ! ResourceSiloControl.DrainMultiplier(multiplier))
|
||||
case _ =>
|
||||
details.galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(details.building.infoUpdateMessage()))
|
||||
}
|
||||
|
|
@ -345,4 +351,32 @@ case object MajorFacilityLogic
|
|||
}
|
||||
Behaviors.same
|
||||
}
|
||||
|
||||
private def calculateNtuDrainMultiplierFrom(
|
||||
building: Building,
|
||||
domeOpt: Option[ForceDomePhysics] = None,
|
||||
mainTerminalOpt: Option[Any] = None
|
||||
): Float = {
|
||||
val domeParam = domeOpt.orElse {
|
||||
building.Amenities.find(_.isInstanceOf[ForceDomePhysics]) match {
|
||||
case Some(d: ForceDomePhysics) => Some(d)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
val mainTerminalParam = mainTerminalOpt.orElse(None) //todo main terminal and viruses
|
||||
getNtuDrainMultiplierFromAmenities(domeParam, mainTerminalParam)
|
||||
}
|
||||
|
||||
private def getNtuDrainMultiplierFromAmenities(
|
||||
dome: Option[ForceDomePhysics],
|
||||
mainTerminal: Option[Any]
|
||||
): Float = {
|
||||
// The force dome being expanded means all repairs are essentially for free
|
||||
dome
|
||||
.map { case d if d.Energized => 0f }
|
||||
.orElse {
|
||||
mainTerminal.flatMap { _ => Some(2f) } //todo main terminal and viruses
|
||||
}
|
||||
.getOrElse(1f)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,7 +187,8 @@ object ExplosiveDeployableControl {
|
|||
zone,
|
||||
target,
|
||||
Zone.explosionDamage(Some(cause)),
|
||||
ExplosiveDeployableControl.detectionForExplosiveSource(target)
|
||||
ExplosiveDeployableControl.detectionForExplosiveSource(target),
|
||||
Zone.findAllTargets
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -956,5 +956,20 @@ object GlobalDefinitionsMiscellaneous {
|
|||
|
||||
zipline.Name = "zipline"
|
||||
zipline.interference = InterferenceRange(deployables = 5.5f)
|
||||
|
||||
force_dome_amp_physics.Name = "force_dome_amp_physics"
|
||||
force_dome_amp_physics.UseRadius = 142.26f
|
||||
|
||||
force_dome_comm_physics.Name = "force_dome_comm_physics"
|
||||
force_dome_comm_physics.UseRadius = 121.8149f
|
||||
|
||||
force_dome_cryo_physics.Name = "force_dome_cryo_physics"
|
||||
force_dome_cryo_physics.UseRadius = 127.9241f //127.7963f
|
||||
|
||||
force_dome_dsp_physics.Name = "force_dome_dsp_physics"
|
||||
force_dome_dsp_physics.UseRadius = 175.8838f //175.7081f
|
||||
|
||||
force_dome_tech_physics.Name = "force_dome_tech_physics"
|
||||
force_dome_tech_physics.UseRadius = 150.1284f
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,18 @@
|
|||
package net.psforever.objects.serverobject.dome
|
||||
|
||||
import net.psforever.actors.zone.BuildingActor
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.PlanetSideGameObject
|
||||
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.objects.sourcing.SourceEntry
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.vital.etc.ForceDomeExposure
|
||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.vital.prop.DamageWithPosition
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.ChatMsg
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||
|
|
@ -29,6 +37,7 @@ object ForceDomeControl {
|
|||
dome.Energized = activationState
|
||||
val owner = dome.Owner
|
||||
val zone = owner.Zone
|
||||
owner.Actor ! BuildingActor.AmenityStateChange(dome)
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.id,
|
||||
LocalAction.UpdateForceDomeStatus(Service.defaultPlayerGUID, owner.GUID, activationState)
|
||||
|
|
@ -48,12 +57,12 @@ object ForceDomeControl {
|
|||
def CheckForceDomeStatus(building: Building, dome: ForceDomePhysics): Option[Boolean] = {
|
||||
if (building.IsCapitol) {
|
||||
Some(
|
||||
if (ForceDomeControl.InvalidBuildingCapitolForceDomeConditions(building)) {
|
||||
if (InvalidBuildingCapitolForceDomeConditions(building)) {
|
||||
false
|
||||
} else {
|
||||
building
|
||||
.Neighbours(building.Faction)
|
||||
.map(_.count(b => !ForceDomeControl.InvalidBuildingCapitolForceDomeConditions(b)))
|
||||
.map(_.count(b => !InvalidBuildingCapitolForceDomeConditions(b)))
|
||||
.exists(_ > 1)
|
||||
}
|
||||
)
|
||||
|
|
@ -105,24 +114,25 @@ object ForceDomeControl {
|
|||
.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
|
||||
}
|
||||
import scala.annotation.unused
|
||||
def TechPlantFacilityPerimeter(@unused 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
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +157,7 @@ object ForceDomeControl {
|
|||
|
||||
/**
|
||||
* na
|
||||
* @param building target building
|
||||
* @param building facility
|
||||
*/
|
||||
def NormalDomeStateMessage(building: Building): Unit = {
|
||||
val events = building.Zone.LocalEvents
|
||||
|
|
@ -159,6 +169,116 @@ object ForceDomeControl {
|
|||
events ! LocalServiceMessage(player.Name, message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 facility with `dome`
|
||||
*/
|
||||
def AlignForceDomeStatusAndUpdate(building: Building, dome: ForceDomePhysics): Unit = {
|
||||
CheckForceDomeStatus(building, dome).foreach {
|
||||
case true =>
|
||||
if (!dome.Energized) {
|
||||
ChangeDomeEnergizedState(dome, activationState = true)
|
||||
ForceDomeKills(dome)
|
||||
dome.Owner.Actor ! BuildingActor.MapUpdate()
|
||||
}
|
||||
case false =>
|
||||
if (dome.Energized) {
|
||||
ChangeDomeEnergizedState(dome, activationState = false)
|
||||
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 facility with `dome`
|
||||
*/
|
||||
private def AlignForceDomeStatus(building: Building, dome: ForceDomePhysics): Unit = {
|
||||
CheckForceDomeStatus(building, dome).foreach {
|
||||
case true =>
|
||||
if (!dome.Energized) {
|
||||
ChangeDomeEnergizedState(dome, activationState = true)
|
||||
ForceDomeKills(dome)
|
||||
}
|
||||
case false =>
|
||||
if (dome.Energized) {
|
||||
ChangeDomeEnergizedState(dome, activationState = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Being too close to the force dome can destroy targets if they do not match the faction alignment of the dome.
|
||||
* This is the usual fate of opponents upon it being expanded (energeized).
|
||||
* @see `Zone.serverSideDamage`
|
||||
* @param dome force dome
|
||||
* @return a list of affected entities
|
||||
*/
|
||||
def ForceDomeKills(dome: ForceDomePhysics): List[PlanetSideServerObject] = {
|
||||
Zone.serverSideDamage(
|
||||
dome.Zone,
|
||||
dome,
|
||||
contactWithForceDome,
|
||||
Zone.distanceCheck,
|
||||
forceDomeTargets(dome.Definition.UseRadius, dome.Faction)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param source a game object that represents the source of the explosion
|
||||
* @param target a game object that is affected by the explosion
|
||||
* @return a `DamageInteraction` object
|
||||
*/
|
||||
private def contactWithForceDome(
|
||||
source: PlanetSideGameObject with FactionAffinity with Vitality,
|
||||
target: PlanetSideGameObject with FactionAffinity with Vitality
|
||||
): DamageInteraction = {
|
||||
DamageInteraction(
|
||||
SourceEntry(target),
|
||||
ForceDomeExposure(SourceEntry(source)),
|
||||
target.Position
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @see `DamageWithPosition`
|
||||
* @see `Zone.blockMap.sector`
|
||||
* @param zone the zone in which the explosion should occur
|
||||
* @param source a game entity that is treated as the origin and is excluded from results
|
||||
* @param damagePropertiesBySource information about the effect/damage
|
||||
* @return a list of affected entities
|
||||
*/
|
||||
private def forceDomeTargets(
|
||||
radius: Float,
|
||||
targetFaction: PlanetSideEmpire.Value
|
||||
)
|
||||
(
|
||||
zone: Zone,
|
||||
source: PlanetSideGameObject with Vitality,
|
||||
damagePropertiesBySource: DamageWithPosition
|
||||
): List[PlanetSideServerObject with Vitality] = {
|
||||
val sector = zone.blockMap.sector(source.Position.xy, radius)
|
||||
val playerTargets = sector.livePlayerList.filterNot { _.VehicleSeated.nonEmpty }
|
||||
//vehicles
|
||||
val vehicleTargets = sector.vehicleList.filterNot { v => v.Destroyed || v.MountedIn.nonEmpty }
|
||||
//deployables
|
||||
val deployableTargets = sector.deployableList.filterNot { _.Destroyed }
|
||||
//altogether ...
|
||||
(playerTargets ++ vehicleTargets ++ deployableTargets).filterNot(_.Faction == targetFaction)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -172,17 +292,12 @@ class ForceDomeControl(dome: ForceDomePhysics)
|
|||
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)
|
||||
|
|
@ -209,7 +324,7 @@ class ForceDomeControl(dome: ForceDomePhysics)
|
|||
if customState.nonEmpty =>
|
||||
customState = None
|
||||
ForceDomeControl.NormalDomeStateMessage(domeOwnerAsABuilding)
|
||||
alignForceDomeStatusAndUpdate(domeOwnerAsABuilding)
|
||||
ForceDomeControl.AlignForceDomeStatusAndUpdate(domeOwnerAsABuilding, dome)
|
||||
}
|
||||
|
||||
def poweredStateLogic: Receive = {
|
||||
|
|
@ -217,7 +332,7 @@ class ForceDomeControl(dome: ForceDomePhysics)
|
|||
.orElse(captureTerminalAwareBehaviour)
|
||||
.orElse {
|
||||
case BuildingActor.AlertToFactionChange(_) =>
|
||||
blockedByCustomStateOr(alignForceDomeStatusAndUpdate, domeOwnerAsABuilding)
|
||||
blockedByCustomStateOr(ForceDomeControl.AlignForceDomeStatusAndUpdate)
|
||||
|
||||
case _ => ()
|
||||
}
|
||||
|
|
@ -231,83 +346,53 @@ class ForceDomeControl(dome: ForceDomePhysics)
|
|||
}
|
||||
|
||||
def powerTurnOffCallback() : Unit = {
|
||||
if (dome.Energized && customState.isEmpty) {
|
||||
ForceDomeControl.ChangeDomeEnergizedState(dome,activationState = false)
|
||||
}
|
||||
deenergizeUnlessSuppressedDueToCustomState()
|
||||
}
|
||||
|
||||
def powerTurnOnCallback() : Unit = {
|
||||
blockedByCustomStateOr(alignForceDomeStatus, domeOwnerAsABuilding)
|
||||
blockedByCustomStateOr(ForceDomeControl.AlignForceDomeStatus)
|
||||
}
|
||||
|
||||
override protected def captureTerminalIsResecured(terminal: CaptureTerminal): Unit = {
|
||||
super.captureTerminalIsResecured(terminal)
|
||||
blockedByCustomStateOr(alignForceDomeStatus, domeOwnerAsABuilding)
|
||||
blockedByCustomStateOr(ForceDomeControl.AlignForceDomeStatus)
|
||||
}
|
||||
|
||||
override protected def captureTerminalIsHacked(terminal: CaptureTerminal): Unit = {
|
||||
super.captureTerminalIsHacked(terminal)
|
||||
if (dome.Energized && customState.isEmpty) {
|
||||
ForceDomeControl.ChangeDomeEnergizedState(dome, activationState = false)
|
||||
}
|
||||
deenergizeUnlessSuppressedDueToCustomState()
|
||||
}
|
||||
|
||||
private def setupPerimeter(): Unit = {
|
||||
//todo tech plants have an indent
|
||||
if (perimeterSegments.isEmpty) {
|
||||
perimeterSegments = ForceDomeControl.GeneralFacilityPerimeter(dome)
|
||||
private def deenergizeUnlessSuppressedDueToCustomState(): Unit = {
|
||||
if (dome.Energized) {
|
||||
if (customState.isEmpty) {
|
||||
ForceDomeControl.ChangeDomeEnergizedState(dome, activationState = false)
|
||||
} else {
|
||||
ForceDomeControl.CustomDomeStateEnforcedMessage(domeOwnerAsABuilding, state = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param func function to run if not blocked
|
||||
* @return next behavior for an actor state
|
||||
*/
|
||||
private def blockedByCustomStateOr(func: (Building, ForceDomePhysics) => Unit): Unit = {
|
||||
blockedByCustomStateOr(func, domeOwnerAsABuilding, 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 = {
|
||||
private def blockedByCustomStateOr(func: (Building, ForceDomePhysics) => Unit, building: Building, dome: ForceDomePhysics): Unit = {
|
||||
customState match {
|
||||
case None =>
|
||||
func(building)
|
||||
func(building, dome)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ class GeneratorControl(gen: Generator)
|
|||
queuedExplosion = Default.Cancellable
|
||||
imminentExplosion = false
|
||||
//hate on everything nearby
|
||||
Zone.serverSideDamage(gen.Zone, gen, Zone.explosionDamage(gen.LastDamage), explosionFunc)
|
||||
Zone.serverSideDamage(gen.Zone, gen, Zone.explosionDamage(gen.LastDamage), explosionFunc, Zone.findAllTargets)
|
||||
|
||||
case GeneratorControl.Restored() =>
|
||||
gen.ClearHistory()
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ class VehicleSpawnControlRailJack(pad: VehicleSpawnPad) extends VehicleSpawnCont
|
|||
pad.Zone,
|
||||
pad,
|
||||
VehicleSpawnControlRailJack.prepareSpawnExplosion(pad, SourceEntry(driver), SourceEntry(vehicle)),
|
||||
pad.Definition.killBox(pad, vehicle.Definition.CanFly)
|
||||
pad.Definition.killBox(pad, vehicle.Definition.CanFly),
|
||||
Zone.findAllTargets
|
||||
)
|
||||
pad.Zone.VehicleEvents ! VehicleSpawnPad.AttachToRails(vehicle, pad)
|
||||
context.system.scheduler.scheduleOnce(10 milliseconds, seatDriver, order)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ import net.psforever.util.Config
|
|||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.duration._
|
||||
|
||||
object ResourceSiloControl {
|
||||
final case class DrainMultiplier(multiplier: Float)
|
||||
}
|
||||
|
||||
/**
|
||||
* An `Actor` that handles messages being dispatched to a specific `ResourceSilo` entity.
|
||||
*
|
||||
|
|
@ -30,7 +34,9 @@ class ResourceSiloControl(resourceSilo: ResourceSilo)
|
|||
def FactionObject: FactionAffinity = resourceSilo
|
||||
|
||||
private[this] val log = org.log4s.getLogger
|
||||
var panelAnimationFunc: (ActorRef, Float) => Unit = PanelAnimation
|
||||
private var panelAnimationFunc: (ActorRef, Float) => Unit = PanelAnimation
|
||||
/** the higher the multiplier, the greater the drain */
|
||||
private var drainMultiplier: Float = 1.0f
|
||||
|
||||
def receive: Receive = {
|
||||
case Service.Startup() =>
|
||||
|
|
@ -53,6 +59,9 @@ class ResourceSiloControl(resourceSilo: ResourceSilo)
|
|||
checkBehavior
|
||||
.orElse(storageBehavior)
|
||||
.orElse {
|
||||
case ResourceSiloControl.DrainMultiplier(multiplier) =>
|
||||
drainMultiplier = multiplier
|
||||
|
||||
case CommonMessages.Use(_, Some(vehicle: Vehicle))
|
||||
if GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition) =>
|
||||
val siloFaction = resourceSilo.Faction
|
||||
|
|
@ -171,7 +180,7 @@ class ResourceSiloControl(resourceSilo: ResourceSilo)
|
|||
*/
|
||||
def HandleNtuRequest(sender: ActorRef, min: Float, max: Float): Unit = {
|
||||
val originalAmount = resourceSilo.NtuCapacitor
|
||||
UpdateChargeLevel(-min)
|
||||
UpdateChargeLevel(-min * drainMultiplier)
|
||||
sender ! Ntu.Grant(resourceSilo, originalAmount - resourceSilo.NtuCapacitor)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ 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}
|
||||
|
|
@ -1639,13 +1638,6 @@ 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 {
|
||||
|
|
@ -1817,6 +1809,29 @@ object Zone {
|
|||
|
||||
/* explosions */
|
||||
|
||||
/**
|
||||
* Allocates `Damageable` targets within the vicinity of server-prepared damage dealing
|
||||
* and informs those entities that they have affected by the aforementioned damage.
|
||||
* Usually, this is considered an "explosion;" but, the application can be utilized for a variety of unbound damage.
|
||||
* @param zone the zone in which the damage should occur
|
||||
* @param source the entity that embodies the damage (information)
|
||||
* @param createInteraction how the interaction for this damage is to prepared
|
||||
* @return a list of affected entities;
|
||||
* only mostly complete due to the exclusion of objects whose damage resolution is different than usual
|
||||
*/
|
||||
def serverSideDamage(
|
||||
zone: Zone,
|
||||
source: PlanetSideGameObject with FactionAffinity with Vitality,
|
||||
createInteraction: (PlanetSideGameObject with FactionAffinity with Vitality, PlanetSideGameObject with FactionAffinity with Vitality) => DamageInteraction
|
||||
): List[PlanetSideServerObject] = {
|
||||
source.Definition.innateDamage match {
|
||||
case Some(damage) =>
|
||||
serverSideDamage(zone, source, damage, createInteraction, distanceCheck, findAllTargets)
|
||||
case None =>
|
||||
Nil
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates `Damageable` targets within the vicinity of server-prepared damage dealing
|
||||
* and informs those entities that they have affected by the aforementioned damage.
|
||||
|
|
@ -1824,8 +1839,10 @@ object Zone {
|
|||
* @param zone the zone in which the damage should occur
|
||||
* @param source the entity that embodies the damage (information)
|
||||
* @param createInteraction how the interaction for this damage is to prepared
|
||||
* @param testTargetsFromZone a custom test for determining whether the allocated targets are affected by the damage
|
||||
* @param acquireTargetsFromZone the main target-collecting algorithm
|
||||
* @param testTargetsFromZone a custom test for determining whether the allocated targets are affected by the damage;
|
||||
* filters targets from the existing selection
|
||||
* @param acquireTargetsFromZone the main target-collecting algorithm;
|
||||
* collects targets from sector information
|
||||
* @return a list of affected entities;
|
||||
* only mostly complete due to the exclusion of objects whose damage resolution is different than usual
|
||||
*/
|
||||
|
|
@ -1833,8 +1850,8 @@ object Zone {
|
|||
zone: Zone,
|
||||
source: PlanetSideGameObject with FactionAffinity with Vitality,
|
||||
createInteraction: (PlanetSideGameObject with FactionAffinity with Vitality, PlanetSideGameObject with FactionAffinity with Vitality) => DamageInteraction,
|
||||
testTargetsFromZone: (PlanetSideGameObject, PlanetSideGameObject, Float) => Boolean = distanceCheck,
|
||||
acquireTargetsFromZone: (Zone, PlanetSideGameObject with FactionAffinity with Vitality, DamageWithPosition) => List[PlanetSideServerObject with Vitality] = findAllTargets
|
||||
testTargetsFromZone: (PlanetSideGameObject, PlanetSideGameObject, Float) => Boolean,
|
||||
acquireTargetsFromZone: (Zone, PlanetSideGameObject with FactionAffinity with Vitality, DamageWithPosition) => List[PlanetSideServerObject with Vitality]
|
||||
): List[PlanetSideServerObject] = {
|
||||
source.Definition.innateDamage match {
|
||||
case Some(damage) =>
|
||||
|
|
@ -1859,8 +1876,10 @@ object Zone {
|
|||
* @param zone the zone in which the damage should occur
|
||||
* @param source the entity that embodies the damage (information)
|
||||
* @param createInteraction how the interaction for this damage is to prepared
|
||||
* @param testTargetsFromZone a custom test for determining whether the allocated targets are affected by the damage
|
||||
* @param acquireTargetsFromZone the main target-collecting algorithm
|
||||
* @param testTargetsFromZone a custom test for determining whether the allocated targets are affected by the damage;
|
||||
* filters targets from the existing selection
|
||||
* @param acquireTargetsFromZone the main target-collecting algorithm;
|
||||
* collects targets from sector information
|
||||
* @return a list of affected entities;
|
||||
* only mostly complete due to the exclusion of objects whose damage resolution is different than usual
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue