mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-02-20 07:03:35 +00:00
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:
parent
4a0805b698
commit
e1c5cd90a7
10 changed files with 178 additions and 31 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 _ => ;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue