updated ntu -> power workflow by making event progress - the silo will report the ntu state to the generator and the generator will only report on the power state if it is not destroyed; if the generator is destroyed, that is where the messaging will end, until the generator comes back online; the events for these state change are somewhat arbitrary

This commit is contained in:
Jason_DiDonato@yahoo.com 2020-10-14 22:40:27 -04:00
parent 4a0805b698
commit e1c5cd90a7
10 changed files with 178 additions and 31 deletions

View file

@ -3646,6 +3646,12 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
if (isMovingPlus) {
CancelZoningProcessWithDescriptiveReason("cancel_motion")
}
if (!player.Crouching && is_crouching) {
continent.Buildings.values.find { b => Vector3.Distance(player.Position, b.Position) <= b.Definition.SOIRadius} match {
case Some(b) => ;
case _ => ;
}
}
player.Position = pos
player.Velocity = vel
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)
@ -6554,13 +6560,20 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
*/
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))
val guid = building.GUID
sendResponse(SetEmpireMessage(guid, building.Faction))
// power
building.Generator match {
case Some(obj) if obj.Condition != PlanetSideGeneratorState.Normal =>
sendResponse(PlanetsideAttributeMessage(guid, 48, 1))
sendResponse(PlanetsideAttributeMessage(guid, 38, 0))
case _ => ;
}
// Synchronise amenities
// capitol force dome state
if (building.IsCapitol && building.ForceDomeActive) {
sendResponse(GenericObjectActionMessage(guid, 13))
}
// amenities
building.Amenities.collect {
case obj if obj.Destroyed => configAmenityAsDestroyed(obj)
case obj => configAmenityAsWorking(obj)

View file

@ -9,8 +9,10 @@ import net.psforever.objects.{CommonNtuContainer, NtuContainer}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.generator.Generator
import net.psforever.objects.serverobject.structures.{Amenity, Building, StructureType, WarpGate}
import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.zones.Zone
import net.psforever.persistence
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import net.psforever.types.PlanetSideEmpire
import net.psforever.util.Database._
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
@ -43,7 +45,11 @@ object BuildingActor {
// Once they do, we won't need this anymore
final case class MapUpdate() extends Command
final case class AmenityStateChange(obj: Amenity) extends Command
final case class AmenityStateChange(obj: Amenity, data: Option[Any]) extends Command
object AmenityStateChange{
def apply(obj: Amenity): AmenityStateChange = AmenityStateChange(obj, None)
}
final case class Ntu(command: NtuCommand.Command) extends Command
@ -160,29 +166,50 @@ class BuildingActor(
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
Behaviors.same
case AmenityStateChange(obj: Generator) =>
case AmenityStateChange(obj: Generator, data) =>
//TODO when parameter object is finally immutable, perform analysis on it to determine specific actions
val msg = if(obj.Destroyed) BuildingActor.PowerOff() else BuildingActor.PowerOn()
building.Amenities.foreach { _.Actor ! msg }
data match {
case Some("overloaded") =>
powerLost()
val zone = building.Zone
val msg = AvatarAction.PlanetsideAttributeToAll(building.GUID, 46, 2)
building.PlayersInSOI.foreach { player =>
zone.AvatarEvents ! AvatarServiceMessage(player.Name, msg)
} //???
case Some("repaired") =>
powerRestored()
val zone = building.Zone
building.PlayersInSOI.foreach { player =>
val msg = AvatarAction.PlanetsideAttributeToAll(building.GUID, 46, 0)
zone.AvatarEvents ! AvatarServiceMessage(player.Name, msg)
} //reset ???
case _ => ;
}
//update the map
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
Behaviors.same
case AmenityStateChange(_) =>
case AmenityStateChange(_, _) =>
//TODO when parameter object is finally immutable, perform analysis on it to determine specific actions
//for now, just update the map
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
Behaviors.same
case PowerOff() =>
powerLost()
Behaviors.same
case PowerOn() =>
powerRestored()
Behaviors.same
case msg @ NtuDepleted() =>
log.trace(s"${building.Definition.Name} ${building.Name} ntu has been depleted")
building.Amenities.foreach { amenity =>
amenity.Actor ! msg
}
Behaviors.same
case msg @ SuppliedWithNtu() =>
log.trace(s"ntu supply has been restored to ${building.Definition.Name} ${building.Name}")
building.Amenities.foreach { amenity =>
amenity.Actor ! msg
}
@ -193,6 +220,36 @@ class BuildingActor(
}
}
def powerLost(): Unit = {
val zone = building.Zone
val zoneId = zone.id
val events = zone.AvatarEvents
val guid = building.GUID
val powerMsg = BuildingActor.PowerOff()
building.Amenities.foreach { amenity =>
amenity.Actor ! powerMsg
}
//amenities disabled; red warning lights
events ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(guid, 48, 1))
//disable spawn target on deployment map
events ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(guid, 38, 0))
}
def powerRestored(): Unit = {
val zone = building.Zone
val zoneId = zone.id
val events = zone.AvatarEvents
val guid = building.GUID
val powerMsg = BuildingActor.PowerOn()
building.Amenities.foreach { amenity =>
amenity.Actor ! powerMsg
}
//amenities enabled; normal lights
events ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(guid, 48, 0))
//enable spawn target on deployment map
events ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(guid, 38, 1))
}
def ntu(msg: NtuCommand.Command): Behavior[Command] = {
import NtuCommand._
msg match {

View file

@ -48,7 +48,7 @@ class GeneratorControl(gen: Generator)
gen.Health = 0
super.DestructionAwareness(gen, gen.LastShot.get)
gen.Condition = PlanetSideGeneratorState.Destroyed
GeneratorControl.UpdateOwner(gen)
GeneratorControl.UpdateOwner(gen, Some("destroyed"))
//kaboom
zone.AvatarEvents ! AvatarServiceMessage(
zone.id,
@ -74,13 +74,27 @@ class GeneratorControl(gen: Generator)
case GeneratorControl.UnderThreatAlarm() =>
if (!alarmCooldownPeriod) {
alarmCooldownPeriod = true
GeneratorControl.BroadcastGeneratorEvent(gen, event = 15)
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.UnderAttack)
context.system.scheduler.scheduleOnce(delay = 5 seconds, self, GeneratorControl.AlarmReset())
}
case GeneratorControl.AlarmReset() =>
alarmCooldownPeriod = false
case BuildingActor.NtuDepleted() =>
gen.Owner match {
case b: Building if !gen.Destroyed =>
b.Actor ! BuildingActor.PowerOff()
case _ => ;
}
case BuildingActor.SuppliedWithNtu() =>
gen.Owner match {
case b: Building if !gen.Destroyed =>
b.Actor ! BuildingActor.PowerOn()
case _ => ;
}
case _ => ;
}
@ -108,7 +122,8 @@ class GeneratorControl(gen: Generator)
target.Health = 1 //temporary
imminentExplosion = true
context.system.scheduler.scheduleOnce(10 seconds, self, GeneratorControl.GeneratorExplodes())
GeneratorControl.BroadcastGeneratorEvent(gen, 16)
GeneratorControl.UpdateOwner(gen, Some("overloaded"))
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.Overloaded)
}
}
@ -123,8 +138,8 @@ class GeneratorControl(gen: Generator)
override def Restoration(obj: Repairable.Target): Unit = {
super.Restoration(obj)
gen.Condition = PlanetSideGeneratorState.Normal
GeneratorControl.UpdateOwner(gen)
GeneratorControl.BroadcastGeneratorEvent(gen, 17)
GeneratorControl.UpdateOwner(gen, Some("repaired"))
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.Online)
}
}
@ -145,13 +160,23 @@ object GeneratorControl {
*/
private case class AlarmReset()
/**
* na
*/
object Event extends Enumeration {
val UnderAttack = Value(15)
val Critical = Value(0)
val Overloaded = Value(16)
val Online = Value(17)
}
/**
* na
* @param obj na
*/
private def UpdateOwner(obj: Generator): Unit = {
private def UpdateOwner(obj: Generator, data: Option[Any] = None): Unit = {
obj.Owner match {
case b: Building => b.Actor ! BuildingActor.AmenityStateChange(obj)
case b: Building => b.Actor ! BuildingActor.AmenityStateChange(obj, data)
case _ => ;
}
}
@ -161,11 +186,14 @@ object GeneratorControl {
* @param target the generator
* @param event the action code for the event
*/
private def BroadcastGeneratorEvent(target: Generator, event: Int): Unit = {
private def BroadcastGeneratorEvent(target: Generator, event: Event.Value): Unit = {
target.Owner match {
case b: Building =>
val events = target.Zone.AvatarEvents
val msg = AvatarAction.GenericObjectAction(Service.defaultPlayerGUID, target.Owner.GUID, event)
val msg = event match {
case Event.Critical => AvatarAction.PlanetsideAttributeToAll(b.GUID, 46, 1) //critical status warning
case _ => AvatarAction.GenericObjectAction(Service.defaultPlayerGUID, b.GUID, event.id)
}
b.PlayersInSOI.foreach { player =>
events ! AvatarServiceMessage(player.Name, msg)
}
@ -185,7 +213,7 @@ object GeneratorControl {
val max: Float = target.MaxHealth.toFloat
if (target.Condition != PlanetSideGeneratorState.Critical && health / max < 0.51f) { //becoming critical
target.Condition = PlanetSideGeneratorState.Critical
GeneratorControl.UpdateOwner(target)
GeneratorControl.UpdateOwner(target, Some("critical"))
}
//the generator is under attack
target.Actor ! UnderThreatAlarm()

View file

@ -107,7 +107,12 @@ class ImplantTerminalMechControl(mech: ImplantTerminalMech)
newHealth
}
override def tryAutoRepair() : Boolean = {
isPowered && super.tryAutoRepair()
}
def powerTurnOffCallback(): Unit = {
stopAutoRepair()
//kick all occupants
val guid = mech.GUID
val zone = mech.Zone
@ -126,5 +131,7 @@ class ImplantTerminalMechControl(mech: ImplantTerminalMech)
)
}
def powerTurnOnCallback(): Unit = { }
def powerTurnOnCallback(): Unit = {
tryAutoRepair()
}
}

View file

@ -129,10 +129,25 @@ trait AmenityAutoRepair
/**
* Attempt to start auto-repair operation
* only if no operation is currently being processed.
* @see `actuallyTryAutoRepair`
* @return `true`, if the auto-repair process started specifically due to this call;
* `false`, if it was already started, or did not start
*/
final def tryAutoRepair(): Boolean = {
def tryAutoRepair(): Boolean = {
actuallyTryAutoRepair()
}
/**
* Attempt to start auto-repair operation
* only if no operation is currently being processed.
* In case that an override to the normals operations of `tryAutoRepair` is necessary,
* but the superclass can not be invoked,
* this method is the backup of those operations to initiate auto-repair.
* @see `tryAutoRepair`
* @return `true`, if the auto-repair process started specifically due to this call;
* `false`, if it was already started, or did not start
*/
final def actuallyTryAutoRepair(): Boolean = {
val before = autoRepairTimer.isCancelled
autoRepairStartFunc()
!(before || autoRepairTimer.isCancelled)

View file

@ -114,6 +114,13 @@ class Building(
}
}
def Generator: Option[Generator] = {
Amenities.find(_.isInstanceOf[Generator]) match {
case Some(obj: Generator) => Some(obj)
case _ => None
}
}
def CaptureTerminal: Option[CaptureTerminal] = {
Amenities.find(_.isInstanceOf[CaptureTerminal]) match {
case Some(term) => Some(term.asInstanceOf[CaptureTerminal])
@ -187,8 +194,8 @@ class Building(
(false, PlanetSideEmpire.NEUTRAL, 0L)
}
//if we have no generator, assume the state is "Normal"
val (generatorState, boostGeneratorPain) = Amenities.find(x => x.isInstanceOf[Generator]) match {
case Some(obj: Generator) =>
val (generatorState, boostGeneratorPain) = Generator match {
case Some(obj) =>
(obj.Condition, false) // todo: poll pain field strength
case _ =>
(PlanetSideGeneratorState.Normal, false)

View file

@ -89,7 +89,12 @@ class TerminalControl(term: Terminal)
newHealth
}
override def tryAutoRepair() : Boolean = {
isPowered && super.tryAutoRepair()
}
def powerTurnOffCallback() : Unit = {
stopAutoRepair()
//clear hack state
if (term.HackedBy.nonEmpty) {
val zone = term.Zone
@ -97,7 +102,9 @@ class TerminalControl(term: Terminal)
}
}
def powerTurnOnCallback() : Unit = { }
def powerTurnOnCallback() : Unit = {
tryAutoRepair()
}
override def toString: String = term.Definition.Name
}

View file

@ -71,8 +71,13 @@ class SpawnTubeControl(tube: SpawnTube)
}
}
override def tryAutoRepair() : Boolean = {
isPowered && super.tryAutoRepair()
}
def powerTurnOffCallback(): Unit = {
tube.offline = false
stopAutoRepair()
tube.Owner match {
case b: Building => b.Actor ! BuildingActor.AmenityStateChange(tube)
case _ => ;
@ -81,6 +86,7 @@ class SpawnTubeControl(tube: SpawnTube)
def powerTurnOnCallback(): Unit = {
tube.offline = true
tryAutoRepair()
tube.Owner match {
case b: Building => b.Actor ! BuildingActor.AmenityStateChange(tube)
case _ => ;

View file

@ -58,11 +58,11 @@ class FacilityTurretControl(turret: FacilityTurret)
.orElse(dismountBehavior)
.orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser)
.orElse(autoRepairBehavior)
def poweredStateLogic: Receive =
commonBehavior
.orElse(mountBehavior)
.orElse(autoRepairBehavior)
.orElse {
case CommonMessages.Use(player, Some((item: Tool, upgradeValue: Int)))
if player.Faction == turret.Faction &&
@ -157,7 +157,12 @@ class FacilityTurretControl(turret: FacilityTurret)
events ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(tguid, 51, 0))
}
override def tryAutoRepair() : Boolean = {
isPowered && super.tryAutoRepair()
}
def powerTurnOffCallback(): Unit = {
stopAutoRepair()
//kick all occupants
val guid = turret.GUID
val zone = turret.Zone
@ -176,5 +181,7 @@ class FacilityTurretControl(turret: FacilityTurret)
)
}
def powerTurnOnCallback(): Unit = { }
def powerTurnOnCallback(): Unit = {
tryAutoRepair()
}
}

View file

@ -144,7 +144,7 @@ import scodec.codecs._
* `45 - NTU charge bar 0-10, 5 = 50% full. Seems to apply to both ANT and NTU Silo (possibly siphons?)`<br>
* `46 - Sends "Generator damage is at a critical level!" message`
* `47 - Sets base NTU level to CRITICAL. MUST use base MapId not base GUID`<br>
* `48 - Set to 1 to send base power loss message & turns on red warning lights throughout base. MUST use base MapId not base GUID`<br>
* `48 - Set to 1 to send base power loss message & turns on red warning lights throughout base. MUST use base MapId not base GUID`?<br>
* `49 - Vehicle texture effects state? (>0 turns on ANT panel glow or ntu silo panel glow + orbs) (bit?)`<br>
* `52 - Vehicle particle effects? (>0 turns on orbs going towards ANT. Doesn't affect silo) (bit?)`<br>
* `53 - LFS. Value is 1 to flag LFS`<br>