mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-12 15:04:39 +00:00
powered amenity control agent; terminals, proximity terminals, spawn tubes, implant mechs, facility turrets, and painfields demonstrate this behavior
This commit is contained in:
parent
35b07f897d
commit
ef0d18d214
11 changed files with 392 additions and 174 deletions
|
|
@ -7,6 +7,7 @@ import akka.{actor => classic}
|
||||||
import net.psforever.actors.commands.NtuCommand
|
import net.psforever.actors.commands.NtuCommand
|
||||||
import net.psforever.objects.{CommonNtuContainer, NtuContainer}
|
import net.psforever.objects.{CommonNtuContainer, NtuContainer}
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
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.structures.{Amenity, Building, StructureType, WarpGate}
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.persistence
|
import net.psforever.persistence
|
||||||
|
|
@ -49,6 +50,10 @@ object BuildingActor {
|
||||||
final case class SuppliedWithNtu() extends Command
|
final case class SuppliedWithNtu() extends Command
|
||||||
|
|
||||||
final case class NtuDepleted() extends Command
|
final case class NtuDepleted() extends Command
|
||||||
|
|
||||||
|
final case class PowerOn() extends Command
|
||||||
|
|
||||||
|
final case class PowerOff() extends Command
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuildingActor(
|
class BuildingActor(
|
||||||
|
|
@ -155,6 +160,14 @@ class BuildingActor(
|
||||||
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
|
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
|
case AmenityStateChange(obj: Generator) =>
|
||||||
|
//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 }
|
||||||
|
//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
|
//TODO when parameter object is finally immutable, perform analysis on it to determine specific actions
|
||||||
//for now, just update the map
|
//for now, just update the map
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ trait SpawnPoint {
|
||||||
*/
|
*/
|
||||||
def Definition: ObjectDefinition with SpawnPointDefinition
|
def Definition: ObjectDefinition with SpawnPointDefinition
|
||||||
|
|
||||||
def Offline: Boolean = psso.Destroyed
|
def isOffline: Boolean = psso.Destroyed
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine a specific position and orientation in which to spawn the target.
|
* Determine a specific position and orientation in which to spawn the target.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.serverobject.implantmech
|
package net.psforever.objects.serverobject.implantmech
|
||||||
|
|
||||||
import akka.actor.Actor
|
|
||||||
import net.psforever.objects.ballistics.ResolvedProjectile
|
import net.psforever.objects.ballistics.ResolvedProjectile
|
||||||
import net.psforever.objects.{GlobalDefinitions, Player, SimpleItem}
|
import net.psforever.objects.{GlobalDefinitions, Player, SimpleItem}
|
||||||
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
||||||
|
|
@ -11,14 +10,15 @@ import net.psforever.objects.serverobject.damage.Damageable.Target
|
||||||
import net.psforever.objects.serverobject.damage.{Damageable, DamageableEntity, DamageableMountable}
|
import net.psforever.objects.serverobject.damage.{Damageable, DamageableEntity, DamageableMountable}
|
||||||
import net.psforever.objects.serverobject.hackable.{GenericHackables, HackableBehavior}
|
import net.psforever.objects.serverobject.hackable.{GenericHackables, HackableBehavior}
|
||||||
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, RepairableEntity}
|
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, RepairableEntity}
|
||||||
import net.psforever.objects.serverobject.structures.Building
|
import net.psforever.objects.serverobject.structures.{Building, PoweredAmenityControl}
|
||||||
|
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `Actor` that handles messages being dispatched to a specific `ImplantTerminalMech`.
|
* An `Actor` that handles messages being dispatched to a specific `ImplantTerminalMech`.
|
||||||
* @param mech the "mech" object being governed
|
* @param mech the "mech" object being governed
|
||||||
*/
|
*/
|
||||||
class ImplantTerminalMechControl(mech: ImplantTerminalMech)
|
class ImplantTerminalMechControl(mech: ImplantTerminalMech)
|
||||||
extends Actor
|
extends PoweredAmenityControl
|
||||||
with FactionAffinityBehavior.Check
|
with FactionAffinityBehavior.Check
|
||||||
with MountableBehavior.Mount
|
with MountableBehavior.Mount
|
||||||
with MountableBehavior.Dismount
|
with MountableBehavior.Dismount
|
||||||
|
|
@ -33,14 +33,16 @@ class ImplantTerminalMechControl(mech: ImplantTerminalMech)
|
||||||
def RepairableObject = mech
|
def RepairableObject = mech
|
||||||
def AutoRepairObject = mech
|
def AutoRepairObject = mech
|
||||||
|
|
||||||
def receive: Receive =
|
def commonBehavior: Receive =
|
||||||
checkBehavior
|
checkBehavior
|
||||||
.orElse(mountBehavior)
|
|
||||||
.orElse(dismountBehavior)
|
.orElse(dismountBehavior)
|
||||||
.orElse(hackableBehavior)
|
|
||||||
.orElse(takesDamage)
|
.orElse(takesDamage)
|
||||||
.orElse(canBeRepairedByNanoDispenser)
|
.orElse(canBeRepairedByNanoDispenser)
|
||||||
.orElse(autoRepairBehavior)
|
.orElse(autoRepairBehavior)
|
||||||
|
|
||||||
|
def poweredStateLogic : Receive =
|
||||||
|
commonBehavior
|
||||||
|
.orElse(mountBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
case CommonMessages.Use(player, Some(item: SimpleItem))
|
case CommonMessages.Use(player, Some(item: SimpleItem))
|
||||||
if item.Definition == GlobalDefinitions.remote_electronics_kit =>
|
if item.Definition == GlobalDefinitions.remote_electronics_kit =>
|
||||||
|
|
@ -57,6 +59,12 @@ class ImplantTerminalMechControl(mech: ImplantTerminalMech)
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def unpoweredStateLogic: Receive =
|
||||||
|
commonBehavior
|
||||||
|
.orElse {
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
override protected def MountTest(
|
override protected def MountTest(
|
||||||
obj: PlanetSideServerObject with Mountable,
|
obj: PlanetSideServerObject with Mountable,
|
||||||
seatNumber: Int,
|
seatNumber: Int,
|
||||||
|
|
@ -98,4 +106,25 @@ class ImplantTerminalMechControl(mech: ImplantTerminalMech)
|
||||||
}
|
}
|
||||||
newHealth
|
newHealth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def powerTurnOffCallback(): Unit = {
|
||||||
|
//kick all occupants
|
||||||
|
val guid = mech.GUID
|
||||||
|
val zone = mech.Zone
|
||||||
|
val zoneId = zone.id
|
||||||
|
val events = zone.VehicleEvents
|
||||||
|
mech.Seats.values.foreach(seat =>
|
||||||
|
seat.Occupant match {
|
||||||
|
case Some(player) =>
|
||||||
|
seat.Occupant = None
|
||||||
|
player.VehicleSeated = None
|
||||||
|
if (player.HasGUID) {
|
||||||
|
events ! VehicleServiceMessage(zoneId, VehicleAction.KickPassenger(player.GUID, 4, false, guid))
|
||||||
|
}
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
def powerTurnOnCallback(): Unit = { }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package net.psforever.objects.serverobject.painbox
|
package net.psforever.objects.serverobject.painbox
|
||||||
|
|
||||||
import akka.actor.{Actor, Cancellable}
|
import akka.actor.Cancellable
|
||||||
|
import net.psforever.actors.zone.BuildingActor
|
||||||
import net.psforever.objects.serverobject.doors.Door
|
import net.psforever.objects.serverobject.doors.Door
|
||||||
import net.psforever.objects.serverobject.structures.Building
|
import net.psforever.objects.serverobject.structures.{Building, PoweredAmenityControl}
|
||||||
import net.psforever.objects.{Default, GlobalDefinitions}
|
import net.psforever.objects.{Default, GlobalDefinitions}
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||||
|
|
@ -10,7 +11,7 @@ import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
class PainboxControl(painbox: Painbox) extends Actor {
|
class PainboxControl(painbox: Painbox) extends PoweredAmenityControl {
|
||||||
private[this] val log = org.log4s.getLogger(s"Painbox")
|
private[this] val log = org.log4s.getLogger(s"Painbox")
|
||||||
var painboxTick: Cancellable = Default.Cancellable
|
var painboxTick: Cancellable = Default.Cancellable
|
||||||
var nearestDoor: Option[Door] = None
|
var nearestDoor: Option[Door] = None
|
||||||
|
|
@ -20,8 +21,7 @@ class PainboxControl(painbox: Painbox) extends Actor {
|
||||||
|
|
||||||
var disabled = false // Temporary to disable cavern non-radius fields
|
var disabled = false // Temporary to disable cavern non-radius fields
|
||||||
|
|
||||||
def receive: Receive = {
|
val initialStartup: Unit = {
|
||||||
case "startup" =>
|
|
||||||
if (painbox.Definition.HasNearestDoorDependency) {
|
if (painbox.Definition.HasNearestDoorDependency) {
|
||||||
(painbox.Owner match {
|
(painbox.Owner match {
|
||||||
case obj : Building =>
|
case obj : Building =>
|
||||||
|
|
@ -39,19 +39,20 @@ class PainboxControl(painbox: Painbox) extends Actor {
|
||||||
s"Painbox ${painbox.GUID} on ${painbox.Owner.Continent} - ${painbox.Position} can not find a door that it is dependent on"
|
s"Painbox ${painbox.GUID} on ${painbox.Owner.Continent} - ${painbox.Position} can not find a door that it is dependent on"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (painbox.Definition.Radius == 0f) {
|
if (painbox.Definition.Radius == 0f) {
|
||||||
if (painbox.Owner.Continent.matches("c[0-9]")) {
|
if (painbox.Owner.Continent.matches("c[0-9]")) {
|
||||||
// todo: handle non-radius painboxes in caverns properly
|
// todo: handle non-radius painboxes in caverns properly
|
||||||
log.warn(s"Skipping initialization of ${painbox.GUID} on ${painbox.Owner.Continent} - ${painbox.Position}")
|
log.warn(s"Skipping initialization of ${painbox.GUID} on ${painbox.Owner.Continent} - ${painbox.Position}")
|
||||||
disabled = true
|
disabled = true
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
painbox.Owner match {
|
painbox.Owner match {
|
||||||
case obj : Building =>
|
case obj : Building =>
|
||||||
val planarRange = 16.5f
|
val planarRange = 16.5f
|
||||||
val aboveRange = 5
|
val aboveRange = 5
|
||||||
val belowRange = 5
|
val belowRange = 5
|
||||||
|
|
||||||
// Find amenities within the specified range
|
// Find amenities within the specified range
|
||||||
val nearbyAmenities = obj.Amenities
|
val nearbyAmenities = obj.Amenities
|
||||||
.filter(amenity =>
|
.filter(amenity =>
|
||||||
|
|
@ -87,19 +88,28 @@ class PainboxControl(painbox: Painbox) extends Actor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
context.become(Stopped)
|
self ! BuildingActor.PowerOff()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case _ => ;
|
var commonBehavior: Receive = {
|
||||||
|
case "startup" =>
|
||||||
|
if (bBoxMidPoint == Vector3.Zero) {
|
||||||
|
initialStartup()
|
||||||
}
|
}
|
||||||
|
|
||||||
def Running: Receive = {
|
|
||||||
case Painbox.Stop() =>
|
case Painbox.Stop() =>
|
||||||
context.become(Stopped)
|
|
||||||
painboxTick.cancel()
|
painboxTick.cancel()
|
||||||
painboxTick = Default.Cancellable
|
painboxTick = Default.Cancellable
|
||||||
|
}
|
||||||
|
|
||||||
|
def poweredStateLogic: Receive =
|
||||||
|
commonBehavior
|
||||||
|
.orElse {
|
||||||
|
case Painbox.Start() if isPowered =>
|
||||||
|
painboxTick.cancel()
|
||||||
|
painboxTick = context.system.scheduler.scheduleWithFixedDelay(0 seconds, 1 second, self, Painbox.Tick())
|
||||||
|
|
||||||
case Painbox.Tick() =>
|
case Painbox.Tick() =>
|
||||||
//todo: Account for overlapping pain fields
|
//todo: Account for overlapping pain fields
|
||||||
|
|
@ -109,7 +119,7 @@ class PainboxControl(painbox: Painbox) extends Actor {
|
||||||
val owner = painbox.Owner.asInstanceOf[Building]
|
val owner = painbox.Owner.asInstanceOf[Building]
|
||||||
val faction = owner.Faction
|
val faction = owner.Faction
|
||||||
if (
|
if (
|
||||||
faction != PlanetSideEmpire.NEUTRAL && (nearestDoor match {
|
isPowered && faction != PlanetSideEmpire.NEUTRAL && (nearestDoor match {
|
||||||
case Some(door) => door.Open.nonEmpty;
|
case Some(door) => door.Open.nonEmpty;
|
||||||
case _ => true
|
case _ => true
|
||||||
})
|
})
|
||||||
|
|
@ -157,12 +167,21 @@ class PainboxControl(painbox: Painbox) extends Actor {
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
def Stopped: Receive = {
|
def unpoweredStateLogic: Receive =
|
||||||
case Painbox.Start() =>
|
commonBehavior
|
||||||
context.become(Running)
|
.orElse {
|
||||||
painboxTick.cancel()
|
case _ => ;
|
||||||
painboxTick = context.system.scheduler.scheduleWithFixedDelay(0 seconds, 1 second, self, Painbox.Tick())
|
}
|
||||||
|
|
||||||
|
def powerTurnOffCallback(): Unit = {
|
||||||
|
self ! Painbox.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
def powerTurnOnCallback(): Unit = {
|
||||||
|
painbox.Owner match {
|
||||||
|
case b: Building if b.PlayersInSOI.nonEmpty =>
|
||||||
|
self ! Painbox.Start()
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) 2020 PSForever
|
||||||
|
package net.psforever.objects.serverobject.structures
|
||||||
|
|
||||||
|
import akka.actor.Actor
|
||||||
|
import net.psforever.actors.zone.BuildingActor
|
||||||
|
|
||||||
|
trait PoweredAmenityControl extends Actor {
|
||||||
|
private var powered: Boolean = true
|
||||||
|
|
||||||
|
final def receive: Receive = powerOnCondition
|
||||||
|
|
||||||
|
final def powerOnCondition: Receive = {
|
||||||
|
case BuildingActor.PowerOff() =>
|
||||||
|
powered = false
|
||||||
|
context.become(powerOffCondition)
|
||||||
|
powerTurnOffCallback()
|
||||||
|
case msg =>
|
||||||
|
poweredStateLogic.apply(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
final def powerOffCondition: Receive = {
|
||||||
|
case BuildingActor.PowerOn() =>
|
||||||
|
powered = true
|
||||||
|
context.become(powerOnCondition)
|
||||||
|
powerTurnOnCallback()
|
||||||
|
case msg =>
|
||||||
|
unpoweredStateLogic.apply(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
def isPowered: Boolean = powered
|
||||||
|
|
||||||
|
def poweredStateLogic: Receive
|
||||||
|
|
||||||
|
def unpoweredStateLogic: Receive
|
||||||
|
|
||||||
|
def powerTurnOnCallback(): Unit
|
||||||
|
|
||||||
|
def powerTurnOffCallback(): Unit
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.serverobject.terminals
|
package net.psforever.objects.serverobject.terminals
|
||||||
|
|
||||||
import akka.actor.{Actor, ActorRef, Cancellable}
|
import akka.actor.{ActorRef, Cancellable}
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
import net.psforever.objects.serverobject.CommonMessages
|
import net.psforever.objects.serverobject.CommonMessages
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
||||||
import net.psforever.objects.serverobject.damage.DamageableAmenity
|
import net.psforever.objects.serverobject.damage.DamageableAmenity
|
||||||
import net.psforever.objects.serverobject.hackable.{GenericHackables, HackableBehavior}
|
import net.psforever.objects.serverobject.hackable.{GenericHackables, HackableBehavior}
|
||||||
import net.psforever.objects.serverobject.repair.RepairableAmenity
|
import net.psforever.objects.serverobject.repair.RepairableAmenity
|
||||||
import net.psforever.objects.serverobject.structures.Building
|
import net.psforever.objects.serverobject.structures.{Building, PoweredAmenityControl}
|
||||||
|
import net.psforever.services.Service
|
||||||
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
@ -20,7 +22,7 @@ import scala.concurrent.duration._
|
||||||
* @param term the proximity unit (terminal)
|
* @param term the proximity unit (terminal)
|
||||||
*/
|
*/
|
||||||
class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
||||||
extends Actor
|
extends PoweredAmenityControl
|
||||||
with FactionAffinityBehavior.Check
|
with FactionAffinityBehavior.Check
|
||||||
with HackableBehavior.GenericHackable
|
with HackableBehavior.GenericHackable
|
||||||
with DamageableAmenity
|
with DamageableAmenity
|
||||||
|
|
@ -35,11 +37,20 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
||||||
val callbacks: mutable.ListBuffer[ActorRef] = new mutable.ListBuffer[ActorRef]()
|
val callbacks: mutable.ListBuffer[ActorRef] = new mutable.ListBuffer[ActorRef]()
|
||||||
val log = org.log4s.getLogger
|
val log = org.log4s.getLogger
|
||||||
|
|
||||||
def receive: Receive =
|
val commonBehavior: Receive = checkBehavior
|
||||||
checkBehavior
|
|
||||||
.orElse(hackableBehavior)
|
|
||||||
.orElse(takesDamage)
|
.orElse(takesDamage)
|
||||||
.orElse(canBeRepairedByNanoDispenser)
|
.orElse(canBeRepairedByNanoDispenser)
|
||||||
|
.orElse {
|
||||||
|
case CommonMessages.Unuse(_, Some(target: PlanetSideGameObject)) =>
|
||||||
|
Unuse(target, term.Continent)
|
||||||
|
|
||||||
|
case CommonMessages.Unuse(_, _) =>
|
||||||
|
log.warn(s"unexpected format for CommonMessages.Unuse in this context")
|
||||||
|
}
|
||||||
|
|
||||||
|
def poweredStateLogic: Receive =
|
||||||
|
commonBehavior
|
||||||
|
.orElse(hackableBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
case CommonMessages.Use(player, Some(item: SimpleItem))
|
case CommonMessages.Use(player, Some(item: SimpleItem))
|
||||||
if item.Definition == GlobalDefinitions.remote_electronics_kit =>
|
if item.Definition == GlobalDefinitions.remote_electronics_kit =>
|
||||||
|
|
@ -66,12 +77,6 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
||||||
case CommonMessages.Use(_, _) =>
|
case CommonMessages.Use(_, _) =>
|
||||||
log.warn(s"unexpected format for CommonMessages.Use in this context")
|
log.warn(s"unexpected format for CommonMessages.Use in this context")
|
||||||
|
|
||||||
case CommonMessages.Unuse(_, Some(target: PlanetSideGameObject)) =>
|
|
||||||
Unuse(target, term.Continent)
|
|
||||||
|
|
||||||
case CommonMessages.Unuse(_, _) =>
|
|
||||||
log.warn(s"unexpected format for CommonMessages.Unuse in this context")
|
|
||||||
|
|
||||||
case ProximityTerminalControl.TerminalAction() =>
|
case ProximityTerminalControl.TerminalAction() =>
|
||||||
val proxDef = term.Definition.asInstanceOf[ProximityDefinition]
|
val proxDef = term.Definition.asInstanceOf[ProximityDefinition]
|
||||||
val validateFunc: PlanetSideGameObject => Boolean =
|
val validateFunc: PlanetSideGameObject => Boolean =
|
||||||
|
|
@ -99,6 +104,19 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def unpoweredStateLogic : Receive = commonBehavior
|
||||||
|
.orElse {
|
||||||
|
case CommonMessages.Use(_, _) =>
|
||||||
|
log.warn(s"unexpected format for CommonMessages.Use in this context")
|
||||||
|
|
||||||
|
case CommonMessages.Unuse(_, Some(target: PlanetSideGameObject)) =>
|
||||||
|
Unuse(target, term.Continent)
|
||||||
|
|
||||||
|
case CommonMessages.Unuse(_, _) =>
|
||||||
|
log.warn(s"unexpected format for CommonMessages.Unuse in this context")
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
def Use(target: PlanetSideGameObject, zone: String, callback: ActorRef): Unit = {
|
def Use(target: PlanetSideGameObject, zone: String, callback: ActorRef): Unit = {
|
||||||
val hadNoUsers = term.NumberUsers == 0
|
val hadNoUsers = term.NumberUsers == 0
|
||||||
if (term.AddUser(target)) {
|
if (term.AddUser(target)) {
|
||||||
|
|
@ -145,6 +163,22 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def powerTurnOffCallback() : Unit = {
|
||||||
|
//clear effect callbacks
|
||||||
|
terminalAction.cancel()
|
||||||
|
if (callbacks.nonEmpty) {
|
||||||
|
callbacks.clear()
|
||||||
|
TerminalObject.Zone.LocalEvents ! Terminal.StopProximityEffect(term)
|
||||||
|
}
|
||||||
|
//clear hack state
|
||||||
|
if (term.HackedBy.nonEmpty) {
|
||||||
|
val zone = term.Zone
|
||||||
|
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.ClearTemporaryHack(Service.defaultPlayerGUID, term))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def powerTurnOnCallback() : Unit = { }
|
||||||
|
|
||||||
override def toString: String = term.Definition.Name
|
override def toString: String = term.Definition.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.serverobject.terminals
|
package net.psforever.objects.serverobject.terminals
|
||||||
|
|
||||||
import akka.actor.{Actor, ActorRef}
|
import akka.actor.ActorRef
|
||||||
import net.psforever.objects.ballistics.ResolvedProjectile
|
import net.psforever.objects.ballistics.ResolvedProjectile
|
||||||
import net.psforever.objects.{GlobalDefinitions, SimpleItem}
|
import net.psforever.objects.{GlobalDefinitions, SimpleItem}
|
||||||
import net.psforever.objects.serverobject.CommonMessages
|
import net.psforever.objects.serverobject.CommonMessages
|
||||||
|
|
@ -10,14 +10,16 @@ import net.psforever.objects.serverobject.damage.Damageable.Target
|
||||||
import net.psforever.objects.serverobject.damage.{Damageable, DamageableAmenity}
|
import net.psforever.objects.serverobject.damage.{Damageable, DamageableAmenity}
|
||||||
import net.psforever.objects.serverobject.hackable.{GenericHackables, HackableBehavior}
|
import net.psforever.objects.serverobject.hackable.{GenericHackables, HackableBehavior}
|
||||||
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, RepairableAmenity}
|
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, RepairableAmenity}
|
||||||
import net.psforever.objects.serverobject.structures.Building
|
import net.psforever.objects.serverobject.structures.{Building, PoweredAmenityControl}
|
||||||
|
import net.psforever.services.Service
|
||||||
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `Actor` that handles messages being dispatched to a specific `Terminal`.
|
* An `Actor` that handles messages being dispatched to a specific `Terminal`.
|
||||||
* @param term the `Terminal` object being governed
|
* @param term the `Terminal` object being governed
|
||||||
*/
|
*/
|
||||||
class TerminalControl(term: Terminal)
|
class TerminalControl(term: Terminal)
|
||||||
extends Actor
|
extends PoweredAmenityControl
|
||||||
with FactionAffinityBehavior.Check
|
with FactionAffinityBehavior.Check
|
||||||
with HackableBehavior.GenericHackable
|
with HackableBehavior.GenericHackable
|
||||||
with DamageableAmenity
|
with DamageableAmenity
|
||||||
|
|
@ -29,12 +31,14 @@ class TerminalControl(term: Terminal)
|
||||||
def RepairableObject = term
|
def RepairableObject = term
|
||||||
def AutoRepairObject = term
|
def AutoRepairObject = term
|
||||||
|
|
||||||
def receive: Receive =
|
val commonBehavior: Receive = checkBehavior
|
||||||
checkBehavior
|
|
||||||
.orElse(hackableBehavior)
|
|
||||||
.orElse(takesDamage)
|
.orElse(takesDamage)
|
||||||
.orElse(canBeRepairedByNanoDispenser)
|
.orElse(canBeRepairedByNanoDispenser)
|
||||||
.orElse(autoRepairBehavior)
|
.orElse(autoRepairBehavior)
|
||||||
|
|
||||||
|
def poweredStateLogic : Receive =
|
||||||
|
commonBehavior
|
||||||
|
.orElse(hackableBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
case Terminal.Request(player, msg) =>
|
case Terminal.Request(player, msg) =>
|
||||||
TerminalControl.Dispatch(sender(), term, Terminal.TerminalMessage(player, msg, term.Request(player, msg)))
|
TerminalControl.Dispatch(sender(), term, Terminal.TerminalMessage(player, msg, term.Request(player, msg)))
|
||||||
|
|
@ -55,6 +59,14 @@ class TerminalControl(term: Terminal)
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def unpoweredStateLogic : Receive = commonBehavior
|
||||||
|
.orElse {
|
||||||
|
case Terminal.Request(player, msg) =>
|
||||||
|
sender() ! Terminal.TerminalMessage(player, msg, Terminal.NoDeal())
|
||||||
|
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
override protected def DamageAwareness(target : Target, cause : ResolvedProjectile, amount : Any) : Unit = {
|
override protected def DamageAwareness(target : Target, cause : ResolvedProjectile, amount : Any) : Unit = {
|
||||||
tryAutoRepair()
|
tryAutoRepair()
|
||||||
super.DamageAwareness(target, cause, amount)
|
super.DamageAwareness(target, cause, amount)
|
||||||
|
|
@ -62,6 +74,10 @@ class TerminalControl(term: Terminal)
|
||||||
|
|
||||||
override protected def DestructionAwareness(target: Damageable.Target, cause: ResolvedProjectile) : Unit = {
|
override protected def DestructionAwareness(target: Damageable.Target, cause: ResolvedProjectile) : Unit = {
|
||||||
tryAutoRepair()
|
tryAutoRepair()
|
||||||
|
if (term.HackedBy.nonEmpty) {
|
||||||
|
val zone = term.Zone
|
||||||
|
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.ClearTemporaryHack(Service.defaultPlayerGUID, term))
|
||||||
|
}
|
||||||
super.DestructionAwareness(target, cause)
|
super.DestructionAwareness(target, cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,6 +89,16 @@ class TerminalControl(term: Terminal)
|
||||||
newHealth
|
newHealth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def powerTurnOffCallback() : Unit = {
|
||||||
|
//clear hack state
|
||||||
|
if (term.HackedBy.nonEmpty) {
|
||||||
|
val zone = term.Zone
|
||||||
|
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.ClearTemporaryHack(Service.defaultPlayerGUID, term))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def powerTurnOnCallback() : Unit = { }
|
||||||
|
|
||||||
override def toString: String = term.Definition.Name
|
override def toString: String = term.Definition.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@ import net.psforever.objects.serverobject.structures.Amenity
|
||||||
* @param tDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
* @param tDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||||
*/
|
*/
|
||||||
class SpawnTube(tDef: SpawnTubeDefinition) extends Amenity with SpawnPoint {
|
class SpawnTube(tDef: SpawnTubeDefinition) extends Amenity with SpawnPoint {
|
||||||
|
var offline: Boolean = false
|
||||||
|
|
||||||
|
override def isOffline: Boolean = offline || super.isOffline
|
||||||
|
|
||||||
def Definition: SpawnTubeDefinition = tDef
|
def Definition: SpawnTubeDefinition = tDef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,20 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.serverobject.tube
|
package net.psforever.objects.serverobject.tube
|
||||||
|
|
||||||
import akka.actor.Actor
|
|
||||||
import net.psforever.actors.zone.BuildingActor
|
import net.psforever.actors.zone.BuildingActor
|
||||||
import net.psforever.objects.ballistics.ResolvedProjectile
|
import net.psforever.objects.ballistics.ResolvedProjectile
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
||||||
import net.psforever.objects.serverobject.damage.Damageable.Target
|
import net.psforever.objects.serverobject.damage.Damageable.Target
|
||||||
import net.psforever.objects.serverobject.damage.DamageableAmenity
|
import net.psforever.objects.serverobject.damage.DamageableAmenity
|
||||||
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, Repairable, RepairableAmenity}
|
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, Repairable, RepairableAmenity}
|
||||||
import net.psforever.objects.serverobject.structures.Building
|
import net.psforever.objects.serverobject.structures.{Building, PoweredAmenityControl}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `Actor` that handles messages being dispatched to a specific `SpawnTube`.
|
* An `Actor` that handles messages being dispatched to a specific `SpawnTube`.
|
||||||
* @param tube the `SpawnTube` object being governed
|
* @param tube the `SpawnTube` object being governed
|
||||||
*/
|
*/
|
||||||
class SpawnTubeControl(tube: SpawnTube)
|
class SpawnTubeControl(tube: SpawnTube)
|
||||||
extends Actor
|
extends PoweredAmenityControl
|
||||||
with FactionAffinityBehavior.Check
|
with FactionAffinityBehavior.Check
|
||||||
with DamageableAmenity
|
with DamageableAmenity
|
||||||
with RepairableAmenity
|
with RepairableAmenity
|
||||||
|
|
@ -25,11 +24,19 @@ class SpawnTubeControl(tube: SpawnTube)
|
||||||
def RepairableObject = tube
|
def RepairableObject = tube
|
||||||
def AutoRepairObject = tube
|
def AutoRepairObject = tube
|
||||||
|
|
||||||
def receive: Receive =
|
val commonBehavior: Receive = checkBehavior
|
||||||
checkBehavior
|
|
||||||
.orElse(takesDamage)
|
.orElse(takesDamage)
|
||||||
.orElse(canBeRepairedByNanoDispenser)
|
.orElse(canBeRepairedByNanoDispenser)
|
||||||
.orElse(autoRepairBehavior)
|
.orElse(autoRepairBehavior)
|
||||||
|
|
||||||
|
def poweredStateLogic: Receive =
|
||||||
|
commonBehavior
|
||||||
|
.orElse {
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
|
def unpoweredStateLogic: Receive =
|
||||||
|
commonBehavior
|
||||||
.orElse {
|
.orElse {
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
@ -64,5 +71,21 @@ class SpawnTubeControl(tube: SpawnTube)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def powerTurnOffCallback(): Unit = {
|
||||||
|
tube.offline = false
|
||||||
|
tube.Owner match {
|
||||||
|
case b: Building => b.Actor ! BuildingActor.AmenityStateChange(tube)
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def powerTurnOnCallback(): Unit = {
|
||||||
|
tube.offline = true
|
||||||
|
tube.Owner match {
|
||||||
|
case b: Building => b.Actor ! BuildingActor.AmenityStateChange(tube)
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override def toString: String = tube.Definition.Name
|
override def toString: String = tube.Definition.Name
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.serverobject.turret
|
package net.psforever.objects.serverobject.turret
|
||||||
|
|
||||||
import akka.actor.Actor
|
|
||||||
import net.psforever.objects.ballistics.ResolvedProjectile
|
import net.psforever.objects.ballistics.ResolvedProjectile
|
||||||
import net.psforever.objects.{Default, GlobalDefinitions, Player, Tool}
|
import net.psforever.objects.{Default, GlobalDefinitions, Player, Tool}
|
||||||
import net.psforever.objects.equipment.{Ammo, JammableMountedWeapons}
|
import net.psforever.objects.equipment.{Ammo, JammableMountedWeapons}
|
||||||
|
|
@ -11,8 +10,10 @@ import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
||||||
import net.psforever.objects.serverobject.damage.{Damageable, DamageableWeaponTurret}
|
import net.psforever.objects.serverobject.damage.{Damageable, DamageableWeaponTurret}
|
||||||
import net.psforever.objects.serverobject.hackable.GenericHackables
|
import net.psforever.objects.serverobject.hackable.GenericHackables
|
||||||
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, RepairableWeaponTurret}
|
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, RepairableWeaponTurret}
|
||||||
|
import net.psforever.objects.serverobject.structures.PoweredAmenityControl
|
||||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
|
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
@ -27,7 +28,7 @@ import scala.concurrent.duration._
|
||||||
* @param turret the `MannedTurret` object being governed
|
* @param turret the `MannedTurret` object being governed
|
||||||
*/
|
*/
|
||||||
class FacilityTurretControl(turret: FacilityTurret)
|
class FacilityTurretControl(turret: FacilityTurret)
|
||||||
extends Actor
|
extends PoweredAmenityControl
|
||||||
with FactionAffinityBehavior.Check
|
with FactionAffinityBehavior.Check
|
||||||
with MountableBehavior.TurretMount
|
with MountableBehavior.TurretMount
|
||||||
with MountableBehavior.Dismount
|
with MountableBehavior.Dismount
|
||||||
|
|
@ -51,14 +52,17 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
stopAutoRepair()
|
stopAutoRepair()
|
||||||
}
|
}
|
||||||
|
|
||||||
def receive: Receive =
|
def commonBehavior: Receive =
|
||||||
checkBehavior
|
checkBehavior
|
||||||
.orElse(jammableBehavior)
|
.orElse(jammableBehavior)
|
||||||
.orElse(mountBehavior)
|
|
||||||
.orElse(dismountBehavior)
|
.orElse(dismountBehavior)
|
||||||
.orElse(takesDamage)
|
.orElse(takesDamage)
|
||||||
.orElse(canBeRepairedByNanoDispenser)
|
.orElse(canBeRepairedByNanoDispenser)
|
||||||
.orElse(autoRepairBehavior)
|
.orElse(autoRepairBehavior)
|
||||||
|
|
||||||
|
def poweredStateLogic: Receive =
|
||||||
|
commonBehavior
|
||||||
|
.orElse(mountBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
case CommonMessages.Use(player, Some((item: Tool, upgradeValue: Int)))
|
case CommonMessages.Use(player, Some((item: Tool, upgradeValue: Int)))
|
||||||
if player.Faction == turret.Faction &&
|
if player.Faction == turret.Faction &&
|
||||||
|
|
@ -113,6 +117,12 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def unpoweredStateLogic: Receive =
|
||||||
|
commonBehavior
|
||||||
|
.orElse {
|
||||||
|
case _ => ;
|
||||||
|
}
|
||||||
|
|
||||||
override protected def DamageAwareness(target : Damageable.Target, cause : ResolvedProjectile, amount : Any) : Unit = {
|
override protected def DamageAwareness(target : Damageable.Target, cause : ResolvedProjectile, amount : Any) : Unit = {
|
||||||
tryAutoRepair()
|
tryAutoRepair()
|
||||||
super.DamageAwareness(target, cause, amount)
|
super.DamageAwareness(target, cause, amount)
|
||||||
|
|
@ -146,4 +156,25 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
events ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(tguid, 50, 0))
|
events ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(tguid, 50, 0))
|
||||||
events ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(tguid, 51, 0))
|
events ! AvatarServiceMessage(zoneId, AvatarAction.PlanetsideAttributeToAll(tguid, 51, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def powerTurnOffCallback(): Unit = {
|
||||||
|
//kick all occupants
|
||||||
|
val guid = turret.GUID
|
||||||
|
val zone = turret.Zone
|
||||||
|
val zoneId = zone.id
|
||||||
|
val events = zone.VehicleEvents
|
||||||
|
turret.Seats.values.foreach(seat =>
|
||||||
|
seat.Occupant match {
|
||||||
|
case Some(player) =>
|
||||||
|
seat.Occupant = None
|
||||||
|
player.VehicleSeated = None
|
||||||
|
if (player.HasGUID) {
|
||||||
|
events ! VehicleServiceMessage(zoneId, VehicleAction.KickPassenger(player.GUID, 4, false, guid))
|
||||||
|
}
|
||||||
|
case None => ;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
def powerTurnOnCallback(): Unit = { }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -354,7 +354,7 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
|
||||||
.filter {
|
.filter {
|
||||||
case (building, spawns) =>
|
case (building, spawns) =>
|
||||||
spawns.nonEmpty &&
|
spawns.nonEmpty &&
|
||||||
spawns.exists(_.Offline == false) &&
|
spawns.exists(_.isOffline == false) &&
|
||||||
structures.contains(building.BuildingType)
|
structures.contains(building.BuildingType)
|
||||||
}
|
}
|
||||||
.filter {
|
.filter {
|
||||||
|
|
@ -368,7 +368,7 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
|
||||||
}
|
}
|
||||||
.map {
|
.map {
|
||||||
case (building, spawns: List[SpawnPoint]) =>
|
case (building, spawns: List[SpawnPoint]) =>
|
||||||
(building, spawns.filter(!_.Offline))
|
(building, spawns.filter(!_.isOffline))
|
||||||
}
|
}
|
||||||
.concat(
|
.concat(
|
||||||
(if (ams) Vehicles else List())
|
(if (ams) Vehicles else List())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue