mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-16 00:44:43 +00:00
comments and tests; generator now passes state information to owner, owner composes messaging; can not set faction information if building does not have ntu
This commit is contained in:
parent
88684aa1a2
commit
54f6588439
7 changed files with 296 additions and 236 deletions
|
|
@ -3646,12 +3646,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
||||||
if (isMovingPlus) {
|
if (isMovingPlus) {
|
||||||
CancelZoningProcessWithDescriptiveReason("cancel_motion")
|
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.Position = pos
|
||||||
player.Velocity = vel
|
player.Velocity = vel
|
||||||
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)
|
player.Orientation = Vector3(player.Orientation.x, pitch, yaw)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +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.generator.{Generator, GeneratorControl}
|
||||||
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
|
||||||
|
|
@ -16,7 +16,7 @@ import net.psforever.types.PlanetSideEmpire
|
||||||
import net.psforever.util.Database._
|
import net.psforever.util.Database._
|
||||||
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
||||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
import net.psforever.services.{InterstellarClusterService, ServiceManager}
|
import net.psforever.services.{InterstellarClusterService, Service, ServiceManager}
|
||||||
|
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
import scala.util.{Failure, Success}
|
import scala.util.{Failure, Success}
|
||||||
|
|
@ -73,6 +73,7 @@ class BuildingActor(
|
||||||
private[this] val log = org.log4s.getLogger
|
private[this] val log = org.log4s.getLogger
|
||||||
var galaxyService: Option[classic.ActorRef] = None
|
var galaxyService: Option[classic.ActorRef] = None
|
||||||
var interstellarCluster: Option[ActorRef[InterstellarClusterService.Command]] = None
|
var interstellarCluster: Option[ActorRef[InterstellarClusterService.Command]] = None
|
||||||
|
var hasNtuSupply: Boolean = true
|
||||||
|
|
||||||
context.system.receptionist ! Receptionist.Find(
|
context.system.receptionist ! Receptionist.Find(
|
||||||
InterstellarClusterService.InterstellarClusterServiceKey,
|
InterstellarClusterService.InterstellarClusterServiceKey,
|
||||||
|
|
@ -124,28 +125,11 @@ class BuildingActor(
|
||||||
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
|
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case AmenityStateChange(_: Generator, data) =>
|
case AmenityStateChange(gen: Generator, data) =>
|
||||||
//TODO when parameter object is finally immutable, perform analysis on it to determine specific actions
|
if (generatorStateChange(gen, data)) {
|
||||||
data match {
|
//update the map
|
||||||
case Some("overloaded") =>
|
galaxyService ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
|
||||||
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("restored") =>
|
|
||||||
// Power restored. Reactor Online. Sensors Online. Weapons Online. All systems nominal.
|
|
||||||
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
|
Behaviors.same
|
||||||
|
|
||||||
case AmenityStateChange(_, _) =>
|
case AmenityStateChange(_, _) =>
|
||||||
|
|
@ -163,15 +147,17 @@ class BuildingActor(
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case msg @ NtuDepleted() =>
|
case msg @ NtuDepleted() =>
|
||||||
// Oops, someone let the base run out of power. Shut it all down.
|
// Someone let the base run out of nanites. No one gets anything.
|
||||||
building.Amenities.foreach { amenity =>
|
building.Amenities.foreach { amenity =>
|
||||||
amenity.Actor ! msg
|
amenity.Actor ! msg
|
||||||
}
|
}
|
||||||
setFactionTo(PlanetSideEmpire.NEUTRAL, galaxyService)
|
setFactionTo(PlanetSideEmpire.NEUTRAL, galaxyService)
|
||||||
|
hasNtuSupply = false
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
case msg @ SuppliedWithNtu() =>
|
case msg @ SuppliedWithNtu() =>
|
||||||
// Auto-repair, mainly. If the Generator works, power is restored too.
|
// Auto-repair restart, mainly. If the Generator works, power should be restored too.
|
||||||
|
hasNtuSupply = true
|
||||||
building.Amenities.foreach { amenity =>
|
building.Amenities.foreach { amenity =>
|
||||||
amenity.Actor ! msg
|
amenity.Actor ! msg
|
||||||
}
|
}
|
||||||
|
|
@ -182,49 +168,107 @@ class BuildingActor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def generatorStateChange(generator: Generator, event: Any): Boolean = {
|
||||||
|
event match {
|
||||||
|
case Some(GeneratorControl.Event.UnderAttack) =>
|
||||||
|
val events = zone.AvatarEvents
|
||||||
|
val guid = building.GUID
|
||||||
|
val msg = AvatarAction.GenericObjectAction(Service.defaultPlayerGUID, guid, 15)
|
||||||
|
building.PlayersInSOI.foreach { player =>
|
||||||
|
events ! AvatarServiceMessage(player.Name, msg)
|
||||||
|
}
|
||||||
|
false
|
||||||
|
case Some(GeneratorControl.Event.Critical) =>
|
||||||
|
val events = zone.AvatarEvents
|
||||||
|
val guid = building.GUID
|
||||||
|
val msg = AvatarAction.PlanetsideAttributeToAll(guid, 46, 1)
|
||||||
|
building.PlayersInSOI.foreach { player =>
|
||||||
|
events ! AvatarServiceMessage(player.Name, msg)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
case Some(GeneratorControl.Event.Destabilized) =>
|
||||||
|
val events = zone.AvatarEvents
|
||||||
|
val guid = building.GUID
|
||||||
|
val msg = AvatarAction.GenericObjectAction(Service.defaultPlayerGUID, guid, 16)
|
||||||
|
building.PlayersInSOI.foreach { player =>
|
||||||
|
events ! AvatarServiceMessage(player.Name, msg)
|
||||||
|
}
|
||||||
|
false
|
||||||
|
case Some(GeneratorControl.Event.Destroyed) =>
|
||||||
|
true
|
||||||
|
case Some(GeneratorControl.Event.Offline) =>
|
||||||
|
powerLost()
|
||||||
|
val zone = building.Zone
|
||||||
|
val msg = AvatarAction.PlanetsideAttributeToAll(building.GUID, 46, 2)
|
||||||
|
building.PlayersInSOI.foreach { player =>
|
||||||
|
zone.AvatarEvents ! AvatarServiceMessage(player.Name, msg)
|
||||||
|
} //???
|
||||||
|
false
|
||||||
|
case Some(GeneratorControl.Event.Normal) =>
|
||||||
|
true
|
||||||
|
case Some(GeneratorControl.Event.Online) =>
|
||||||
|
// Power restored. Reactor Online. Sensors Online. Weapons Online. All systems nominal.
|
||||||
|
powerRestored()
|
||||||
|
val events = zone.AvatarEvents
|
||||||
|
val guid = building.GUID
|
||||||
|
val msg1 = AvatarAction.PlanetsideAttributeToAll(guid, 46, 0)
|
||||||
|
val msg2 = AvatarAction.GenericObjectAction(Service.defaultPlayerGUID, guid, 17)
|
||||||
|
building.PlayersInSOI.foreach { player =>
|
||||||
|
val name = player.Name
|
||||||
|
events ! AvatarServiceMessage(name, msg1) //reset ???; might be global?
|
||||||
|
events ! AvatarServiceMessage(name, msg2) //This facility's generator is back on line
|
||||||
|
}
|
||||||
|
true
|
||||||
|
case _ =>
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def setFactionTo(faction: PlanetSideEmpire.Value, galaxy: classic.ActorRef): Unit = {
|
def setFactionTo(faction: PlanetSideEmpire.Value, galaxy: classic.ActorRef): Unit = {
|
||||||
import ctx._
|
if (hasNtuSupply) {
|
||||||
ctx
|
import ctx._
|
||||||
.run(
|
ctx
|
||||||
query[persistence.Building]
|
.run(
|
||||||
.filter(_.localId == lift(building.MapId))
|
query[persistence.Building]
|
||||||
.filter(_.zoneId == lift(zone.Number))
|
.filter(_.localId == lift(building.MapId))
|
||||||
)
|
.filter(_.zoneId == lift(zone.Number))
|
||||||
.onComplete {
|
)
|
||||||
case Success(res) =>
|
.onComplete {
|
||||||
res.headOption match {
|
case Success(res) =>
|
||||||
case Some(_) =>
|
res.headOption match {
|
||||||
ctx
|
case Some(_) =>
|
||||||
.run(
|
ctx
|
||||||
query[persistence.Building]
|
.run(
|
||||||
.filter(_.localId == lift(building.MapId))
|
query[persistence.Building]
|
||||||
.filter(_.zoneId == lift(zone.Number))
|
.filter(_.localId == lift(building.MapId))
|
||||||
.update(_.factionId -> lift(building.Faction.id))
|
.filter(_.zoneId == lift(zone.Number))
|
||||||
)
|
.update(_.factionId -> lift(building.Faction.id))
|
||||||
.onComplete {
|
)
|
||||||
case Success(_) =>
|
.onComplete {
|
||||||
case Failure(e) => log.error(e.getMessage)
|
case Success(_) =>
|
||||||
}
|
case Failure(e) => log.error(e.getMessage)
|
||||||
case _ =>
|
}
|
||||||
ctx
|
case _ =>
|
||||||
.run(
|
ctx
|
||||||
query[persistence.Building]
|
.run(
|
||||||
.insert(
|
query[persistence.Building]
|
||||||
_.localId -> lift(building.MapId),
|
.insert(
|
||||||
_.factionId -> lift(building.Faction.id),
|
_.localId -> lift(building.MapId),
|
||||||
_.zoneId -> lift(zone.Number)
|
_.factionId -> lift(building.Faction.id),
|
||||||
)
|
_.zoneId -> lift(zone.Number)
|
||||||
)
|
)
|
||||||
.onComplete {
|
)
|
||||||
case Success(_) =>
|
.onComplete {
|
||||||
case Failure(e) => log.error(e.getMessage)
|
case Success(_) =>
|
||||||
}
|
case Failure(e) => log.error(e.getMessage)
|
||||||
}
|
}
|
||||||
case Failure(e) => log.error(e.getMessage)
|
}
|
||||||
}
|
case Failure(e) => log.error(e.getMessage)
|
||||||
building.Faction = faction
|
}
|
||||||
galaxy ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
|
building.Faction = faction
|
||||||
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.SetEmpire(building.GUID, faction))
|
galaxy ! GalaxyServiceMessage(GalaxyAction.MapUpdate(building.infoUpdateMessage()))
|
||||||
|
zone.LocalEvents ! LocalServiceMessage(zone.id, LocalAction.SetEmpire(building.GUID, faction))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def powerLost(): Unit = {
|
def powerLost(): Unit = {
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,23 @@ class GeneratorControl(gen: Generator)
|
||||||
def DamageableObject = gen
|
def DamageableObject = gen
|
||||||
def RepairableObject = gen
|
def RepairableObject = gen
|
||||||
def AutoRepairObject = gen
|
def AutoRepairObject = gen
|
||||||
|
/** flagged to explode after some time */
|
||||||
var imminentExplosion: Boolean = false
|
var imminentExplosion: Boolean = false
|
||||||
|
/** explode when this timer completes */
|
||||||
var queuedExplosion: Cancellable = Default.Cancellable
|
var queuedExplosion: Cancellable = Default.Cancellable
|
||||||
var alarmCooldownPeriod: Boolean = false
|
/** when damaged, announce that damage was dealt on a schedule */
|
||||||
private[this] val log = org.log4s.getLogger
|
var alarmCooldown: Cancellable = Default.Cancellable
|
||||||
|
|
||||||
|
/*
|
||||||
|
behavior of the generator piggybacks from the logic used in `AmenityAutoRepair`
|
||||||
|
AAR splits its logic based on whether or not it has detected a source of nanite transfer units (NTU)
|
||||||
|
this amenity is the bridge between NTU and facility power so it leverages that logic
|
||||||
|
it is split between when detecting ntu and when starved for ntu
|
||||||
|
*/
|
||||||
|
|
||||||
def receive: Receive = withNtu
|
def receive: Receive = withNtu
|
||||||
|
|
||||||
|
/** behavior that is valid for both "with-ntu" and "without-ntu" */
|
||||||
val commonBehavior: Receive =
|
val commonBehavior: Receive =
|
||||||
checkBehavior
|
checkBehavior
|
||||||
.orElse(takesDamage)
|
.orElse(takesDamage)
|
||||||
|
|
@ -48,22 +58,29 @@ class GeneratorControl(gen: Generator)
|
||||||
.orElse(autoRepairBehavior)
|
.orElse(autoRepairBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
case GeneratorControl.UnderThreatAlarm() =>
|
case GeneratorControl.UnderThreatAlarm() =>
|
||||||
if (!alarmCooldownPeriod) {
|
//alert to damage and block other damage alerts for a time
|
||||||
alarmCooldownPeriod = true
|
if (alarmCooldown.isCancelled) {
|
||||||
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.UnderAttack)
|
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.UnderAttack))
|
||||||
queuedExplosion = context.system.scheduler.scheduleOnce(delay = 5 seconds, self, GeneratorControl.AlarmReset())
|
alarmCooldown.cancel()
|
||||||
|
alarmCooldown = context.system.scheduler.scheduleOnce(delay = 5 seconds, self, GeneratorControl.AlarmReset())
|
||||||
}
|
}
|
||||||
|
|
||||||
case GeneratorControl.AlarmReset() =>
|
case GeneratorControl.AlarmReset() =>
|
||||||
alarmCooldownPeriod = false
|
//clear the blocker for alerting to damage
|
||||||
|
alarmCooldown = Default.Cancellable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
when NTU is detected,
|
||||||
|
the generator can be properly destabilized and explode
|
||||||
|
the generator can be repaired to operational status and power the facility in which it is installed
|
||||||
|
*/
|
||||||
def withNtu: Receive =
|
def withNtu: Receive =
|
||||||
commonBehavior
|
commonBehavior
|
||||||
.orElse {
|
.orElse {
|
||||||
case GeneratorControl.Destabilized() =>
|
case GeneratorControl.Destabilized() =>
|
||||||
imminentExplosion = true
|
imminentExplosion = true
|
||||||
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.Overloaded)
|
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Destabilized))
|
||||||
queuedExplosion.cancel()
|
queuedExplosion.cancel()
|
||||||
queuedExplosion = context.system.scheduler.scheduleOnce(10 seconds, self, GeneratorControl.GeneratorExplodes())
|
queuedExplosion = context.system.scheduler.scheduleOnce(10 seconds, self, GeneratorControl.GeneratorExplodes())
|
||||||
|
|
||||||
|
|
@ -73,7 +90,7 @@ class GeneratorControl(gen: Generator)
|
||||||
gen.Health = 0
|
gen.Health = 0
|
||||||
super.DestructionAwareness(gen, gen.LastShot.get)
|
super.DestructionAwareness(gen, gen.LastShot.get)
|
||||||
gen.Condition = PlanetSideGeneratorState.Destroyed
|
gen.Condition = PlanetSideGeneratorState.Destroyed
|
||||||
GeneratorControl.UpdateOwner(gen, Some("destroyed"))
|
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Destroyed))
|
||||||
//kaboom
|
//kaboom
|
||||||
zone.AvatarEvents ! AvatarServiceMessage(
|
zone.AvatarEvents ! AvatarServiceMessage(
|
||||||
zone.id,
|
zone.id,
|
||||||
|
|
@ -99,39 +116,45 @@ class GeneratorControl(gen: Generator)
|
||||||
gen.ClearHistory()
|
gen.ClearHistory()
|
||||||
|
|
||||||
case GeneratorControl.Restored() =>
|
case GeneratorControl.Restored() =>
|
||||||
GeneratorControl.UpdateOwner(gen, Some("restored"))
|
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Online))
|
||||||
GeneratorControl.BroadcastGeneratorEvent(gen, GeneratorControl.Event.Online)
|
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
when ntu is not expected,
|
||||||
|
the generator can still be destroyed but will not explode
|
||||||
|
handles the possibility that ntu was lost during an ongoing destabilization and cancels the explosion
|
||||||
|
*/
|
||||||
def withoutNtu: Receive =
|
def withoutNtu: Receive =
|
||||||
commonBehavior
|
commonBehavior
|
||||||
.orElse {
|
.orElse {
|
||||||
case GeneratorControl.GeneratorExplodes() =>
|
case GeneratorControl.GeneratorExplodes() =>
|
||||||
queuedExplosion.cancel()
|
queuedExplosion.cancel()
|
||||||
queuedExplosion = Default.Cancellable
|
queuedExplosion = Default.Cancellable
|
||||||
imminentExplosion = false
|
imminentExplosion = false
|
||||||
|
|
||||||
case GeneratorControl.Destabilized() =>
|
case GeneratorControl.Destabilized() =>
|
||||||
//if the generator is destabilized but has no ntu, it will not explode
|
//if the generator is destabilized but has no ntu, it will not explode
|
||||||
gen.Health = 0
|
gen.Health = 0
|
||||||
super.DestructionAwareness(gen, gen.LastShot.get)
|
super.DestructionAwareness(gen, gen.LastShot.get)
|
||||||
queuedExplosion.cancel()
|
queuedExplosion.cancel()
|
||||||
queuedExplosion = Default.Cancellable
|
queuedExplosion = Default.Cancellable
|
||||||
imminentExplosion = false
|
imminentExplosion = false
|
||||||
gen.Condition = PlanetSideGeneratorState.Destroyed
|
gen.Condition = PlanetSideGeneratorState.Destroyed
|
||||||
GeneratorControl.UpdateOwner(gen, Some("destroyed"))
|
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Destroyed))
|
||||||
gen.ClearHistory()
|
gen.ClearHistory()
|
||||||
|
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def CanPerformRepairs(obj: Target, player: Player, item: Tool): Boolean = {
|
override protected def CanPerformRepairs(obj: Target, player: Player, item: Tool): Boolean = {
|
||||||
|
//if an explosion is queued, disallow repairs
|
||||||
!imminentExplosion && super.CanPerformRepairs(obj, player, item)
|
!imminentExplosion && super.CanPerformRepairs(obj, player, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def WillAffectTarget(target: Target, damage: Int, cause: ResolvedProjectile): Boolean = {
|
override protected def WillAffectTarget(target: Target, damage: Int, cause: ResolvedProjectile): Boolean = {
|
||||||
|
//if an explosion is queued, disallow further damage
|
||||||
!imminentExplosion && super.WillAffectTarget(target, damage, cause)
|
!imminentExplosion && super.WillAffectTarget(target, damage, cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,9 +170,10 @@ class GeneratorControl(gen: Generator)
|
||||||
|
|
||||||
override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
|
override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
|
||||||
tryAutoRepair()
|
tryAutoRepair()
|
||||||
|
//if the target is already destroyed, do not let it be destroyed again
|
||||||
if (!target.Destroyed) {
|
if (!target.Destroyed) {
|
||||||
target.Health = 1 //temporary
|
target.Health = 1 //temporary
|
||||||
GeneratorControl.UpdateOwner(gen, Some("overloaded"))
|
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Offline))
|
||||||
self ! GeneratorControl.Destabilized()
|
self ! GeneratorControl.Destabilized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -165,12 +189,14 @@ class GeneratorControl(gen: Generator)
|
||||||
override def Restoration(obj: Repairable.Target): Unit = {
|
override def Restoration(obj: Repairable.Target): Unit = {
|
||||||
super.Restoration(obj)
|
super.Restoration(obj)
|
||||||
gen.Condition = PlanetSideGeneratorState.Normal
|
gen.Condition = PlanetSideGeneratorState.Normal
|
||||||
|
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Normal))
|
||||||
self ! GeneratorControl.Restored()
|
self ! GeneratorControl.Restored()
|
||||||
}
|
}
|
||||||
|
|
||||||
override def withNtuSupplyCallback() : Unit = {
|
override def withNtuSupplyCallback() : Unit = {
|
||||||
context.become(withNtu)
|
context.become(withNtu)
|
||||||
super.withNtuSupplyCallback()
|
super.withNtuSupplyCallback()
|
||||||
|
//if not destroyed when a source of ntu is detected, restore facility power
|
||||||
if(!gen.Destroyed) {
|
if(!gen.Destroyed) {
|
||||||
self ! GeneratorControl.Restored()
|
self ! GeneratorControl.Restored()
|
||||||
}
|
}
|
||||||
|
|
@ -180,9 +206,11 @@ class GeneratorControl(gen: Generator)
|
||||||
//auto-repair must stop naturally
|
//auto-repair must stop naturally
|
||||||
context.become(withoutNtu)
|
context.become(withoutNtu)
|
||||||
super.noNtuSupplyCallback()
|
super.noNtuSupplyCallback()
|
||||||
|
//if not destroyed when cutoff from a source of ntu, stop facility power generation
|
||||||
if(!gen.Destroyed) {
|
if(!gen.Destroyed) {
|
||||||
GeneratorControl.UpdateOwner(gen, Some("overloaded"))
|
GeneratorControl.UpdateOwner(gen, Some(GeneratorControl.Event.Offline))
|
||||||
}
|
}
|
||||||
|
//can any explosion (see withoutNtu->GenweratorControl.Destabilized)
|
||||||
if(!queuedExplosion.isCancelled) {
|
if(!queuedExplosion.isCancelled) {
|
||||||
queuedExplosion.cancel()
|
queuedExplosion.cancel()
|
||||||
self ! GeneratorControl.Destabilized()
|
self ! GeneratorControl.Destabilized()
|
||||||
|
|
@ -191,7 +219,6 @@ class GeneratorControl(gen: Generator)
|
||||||
}
|
}
|
||||||
|
|
||||||
object GeneratorControl {
|
object GeneratorControl {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* na
|
* na
|
||||||
*/
|
*/
|
||||||
|
|
@ -221,41 +248,24 @@ object GeneratorControl {
|
||||||
* na
|
* na
|
||||||
*/
|
*/
|
||||||
object Event extends Enumeration {
|
object Event extends Enumeration {
|
||||||
val UnderAttack = Value(15)
|
val
|
||||||
val Critical = Value(0)
|
Critical, //PlanetSideGeneratorState.Critical
|
||||||
val Overloaded = Value(16)
|
UnderAttack,
|
||||||
val Online = Value(17)
|
Destabilized,
|
||||||
|
Destroyed, //PlanetSideGeneratorState.Destroyed
|
||||||
|
Offline,
|
||||||
|
Normal, //PlanetSideGeneratorState.Normal
|
||||||
|
Online
|
||||||
|
= Value
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* na
|
* Send a message back to the owner for which this `Amenity` entity is installed.
|
||||||
* @param obj na
|
* @param obj the entity doing the self-reporting
|
||||||
|
* @param data optional information that indicates the nature of the state change
|
||||||
*/
|
*/
|
||||||
private def UpdateOwner(obj: Generator, data: Option[Any] = None): Unit = {
|
private def UpdateOwner(obj: Generator, data: Option[Any] = None): Unit = {
|
||||||
obj.Owner match {
|
obj.Owner.Actor ! BuildingActor.AmenityStateChange(obj, data)
|
||||||
case b: Building => b.Actor ! BuildingActor.AmenityStateChange(obj, data)
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* na
|
|
||||||
* @param target the generator
|
|
||||||
* @param event the action code for the event
|
|
||||||
*/
|
|
||||||
private def BroadcastGeneratorEvent(target: Generator, event: Event.Value): Unit = {
|
|
||||||
target.Owner match {
|
|
||||||
case b: Building =>
|
|
||||||
val events = target.Zone.AvatarEvents
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
case _ => ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -270,7 +280,7 @@ object GeneratorControl {
|
||||||
val max: Float = target.MaxHealth.toFloat
|
val max: Float = target.MaxHealth.toFloat
|
||||||
if (target.Condition != PlanetSideGeneratorState.Critical && health / max < 0.51f) { //becoming critical
|
if (target.Condition != PlanetSideGeneratorState.Critical && health / max < 0.51f) { //becoming critical
|
||||||
target.Condition = PlanetSideGeneratorState.Critical
|
target.Condition = PlanetSideGeneratorState.Critical
|
||||||
GeneratorControl.UpdateOwner(target, Some("critical"))
|
GeneratorControl.UpdateOwner(target, Some(GeneratorControl.Event.Critical))
|
||||||
}
|
}
|
||||||
//the generator is under attack
|
//the generator is under attack
|
||||||
target.Actor ! UnderThreatAlarm()
|
target.Actor ! UnderThreatAlarm()
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package objects
|
||||||
import akka.actor.Props
|
import akka.actor.Props
|
||||||
import akka.testkit.TestProbe
|
import akka.testkit.TestProbe
|
||||||
import base.FreedContextActorTest
|
import base.FreedContextActorTest
|
||||||
|
import net.psforever.actors.zone.BuildingActor
|
||||||
import net.psforever.objects.avatar.Avatar
|
import net.psforever.objects.avatar.Avatar
|
||||||
import net.psforever.objects.ballistics.{Projectile, ProjectileResolution, ResolvedProjectile, SourceEntry}
|
import net.psforever.objects.ballistics.{Projectile, ProjectileResolution, ResolvedProjectile, SourceEntry}
|
||||||
import net.psforever.objects.guid.NumberPoolHub
|
import net.psforever.objects.guid.NumberPoolHub
|
||||||
|
|
@ -57,6 +58,7 @@ class AutoRepairFacilityIntegrationTest extends FreedContextActorTest {
|
||||||
silo.NtuCapacitor = 1000
|
silo.NtuCapacitor = 1000
|
||||||
silo.Actor = system.actorOf(Props(classOf[ResourceSiloControl], silo), "test-silo")
|
silo.Actor = system.actorOf(Props(classOf[ResourceSiloControl], silo), "test-silo")
|
||||||
silo.Actor ! "startup"
|
silo.Actor ! "startup"
|
||||||
|
building.Actor ! BuildingActor.PowerOn() //artificial
|
||||||
|
|
||||||
val wep_fmode = weapon.FireMode
|
val wep_fmode = weapon.FireMode
|
||||||
val wep_prof = wep_fmode.Add
|
val wep_prof = wep_fmode.Add
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,22 @@
|
||||||
package objects
|
package objects
|
||||||
|
|
||||||
import akka.actor.{ActorSystem, Props}
|
import akka.actor.{ActorSystem, Props}
|
||||||
|
import akka.testkit.TestProbe
|
||||||
import base.ActorTest
|
import base.ActorTest
|
||||||
import net.psforever.objects.avatar.Avatar
|
import net.psforever.objects.avatar.Avatar
|
||||||
|
import net.psforever.objects.guid.NumberPoolHub
|
||||||
|
import net.psforever.objects.guid.source.MaxNumberSource
|
||||||
|
import net.psforever.objects.serverobject.CommonMessages
|
||||||
import net.psforever.objects.{Default, GlobalDefinitions, Player}
|
import net.psforever.objects.{Default, GlobalDefinitions, Player}
|
||||||
import net.psforever.objects.serverobject.doors.{Door, DoorControl}
|
import net.psforever.objects.serverobject.doors.{Door, DoorControl}
|
||||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||||
import net.psforever.packet.game.UseItemMessage
|
import net.psforever.packet.game.UseItemMessage
|
||||||
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
import net.psforever.types._
|
import net.psforever.types._
|
||||||
import org.specs2.mutable.Specification
|
import org.specs2.mutable.Specification
|
||||||
|
|
||||||
import scala.concurrent.duration.Duration
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
class DoorTest extends Specification {
|
class DoorTest extends Specification {
|
||||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||||
|
|
@ -83,6 +88,8 @@ class DoorControl2Test extends ActorTest {
|
||||||
"DoorControl" should {
|
"DoorControl" should {
|
||||||
"open on use" in {
|
"open on use" in {
|
||||||
val (player, door) = DoorControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
val (player, door) = DoorControlTest.SetUpAgents(PlanetSideEmpire.TR)
|
||||||
|
val probe = new TestProbe(system)
|
||||||
|
door.Zone.LocalEvents = probe.ref
|
||||||
val msg = UseItemMessage(
|
val msg = UseItemMessage(
|
||||||
PlanetSideGUID(1),
|
PlanetSideGUID(1),
|
||||||
PlanetSideGUID(0),
|
PlanetSideGUID(0),
|
||||||
|
|
@ -98,13 +105,12 @@ class DoorControl2Test extends ActorTest {
|
||||||
) //faked
|
) //faked
|
||||||
assert(door.Open.isEmpty)
|
assert(door.Open.isEmpty)
|
||||||
|
|
||||||
door.Actor ! Door.Use(player, msg)
|
door.Actor ! CommonMessages.Use(player, Some(msg))
|
||||||
val reply = receiveOne(Duration.create(500, "ms"))
|
val reply = probe.receiveOne(1000 milliseconds)
|
||||||
assert(reply.isInstanceOf[Door.DoorMessage])
|
assert(reply match {
|
||||||
val reply2 = reply.asInstanceOf[Door.DoorMessage]
|
case LocalServiceMessage("test", LocalAction.DoorOpens(PlanetSideGUID(0), _, d)) => d eq door
|
||||||
assert(reply2.player == player)
|
case _ => false
|
||||||
assert(reply2.msg == msg)
|
})
|
||||||
assert(reply2.response == Door.OpenEvent())
|
|
||||||
assert(door.Open.isDefined)
|
assert(door.Open.isDefined)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,16 +132,24 @@ class DoorControl3Test extends ActorTest {
|
||||||
object DoorControlTest {
|
object DoorControlTest {
|
||||||
def SetUpAgents(faction: PlanetSideEmpire.Value)(implicit system: ActorSystem): (Player, Door) = {
|
def SetUpAgents(faction: PlanetSideEmpire.Value)(implicit system: ActorSystem): (Player, Door) = {
|
||||||
val door = Door(GlobalDefinitions.door)
|
val door = Door(GlobalDefinitions.door)
|
||||||
|
val guid = new NumberPoolHub(new MaxNumberSource(5))
|
||||||
|
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||||
|
override def SetupNumberPools() = {}
|
||||||
|
GUID(guid)
|
||||||
|
}
|
||||||
|
guid.register(door, 1)
|
||||||
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
|
door.Actor = system.actorOf(Props(classOf[DoorControl], door), "door")
|
||||||
door.Owner = new Building(
|
door.Owner = new Building(
|
||||||
"Building",
|
"Building",
|
||||||
building_guid = 0,
|
building_guid = 0,
|
||||||
map_id = 0,
|
map_id = 0,
|
||||||
Zone.Nowhere,
|
zone,
|
||||||
StructureType.Building,
|
StructureType.Building,
|
||||||
GlobalDefinitions.building
|
GlobalDefinitions.building
|
||||||
)
|
)
|
||||||
door.Owner.Faction = faction
|
door.Owner.Faction = faction
|
||||||
(Player(Avatar(0, "test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), door)
|
val player = Player(Avatar(0, "test", faction, CharacterGender.Male, 0, CharacterVoice.Mute))
|
||||||
|
guid.register(player, 2)
|
||||||
|
(player, door)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import net.psforever.objects.{GlobalDefinitions, Player, Tool}
|
||||||
import net.psforever.objects.guid.NumberPoolHub
|
import net.psforever.objects.guid.NumberPoolHub
|
||||||
import net.psforever.objects.guid.source.MaxNumberSource
|
import net.psforever.objects.guid.source.MaxNumberSource
|
||||||
import net.psforever.objects.serverobject.CommonMessages
|
import net.psforever.objects.serverobject.CommonMessages
|
||||||
import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl}
|
import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl, GeneratorDefinition}
|
||||||
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
import net.psforever.objects.serverobject.structures.{Building, StructureType}
|
||||||
import net.psforever.objects.vital.Vitality
|
import net.psforever.objects.vital.Vitality
|
||||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||||
|
|
@ -25,12 +25,12 @@ import scala.concurrent.duration._
|
||||||
class GeneratorTest extends Specification {
|
class GeneratorTest extends Specification {
|
||||||
"Generator" should {
|
"Generator" should {
|
||||||
"construct" in {
|
"construct" in {
|
||||||
Generator(GlobalDefinitions.generator)
|
Generator(GeneratorTest.generator_definition)
|
||||||
ok
|
ok
|
||||||
}
|
}
|
||||||
|
|
||||||
"start in 'Normal' condition" in {
|
"start in 'Normal' condition" in {
|
||||||
val obj = Generator(GlobalDefinitions.generator)
|
val obj = Generator(GeneratorTest.generator_definition)
|
||||||
obj.Condition mustEqual PlanetSideGeneratorState.Normal
|
obj.Condition mustEqual PlanetSideGeneratorState.Normal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ class GeneratorTest extends Specification {
|
||||||
class GeneratorControlConstructTest extends ActorTest {
|
class GeneratorControlConstructTest extends ActorTest {
|
||||||
"GeneratorControl" should {
|
"GeneratorControl" should {
|
||||||
"construct" in {
|
"construct" in {
|
||||||
val gen = Generator(GlobalDefinitions.generator)
|
val gen = Generator(GeneratorTest.generator_definition)
|
||||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "gen-control")
|
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "gen-control")
|
||||||
assert(gen.Actor != ActorRef.noSender)
|
assert(gen.Actor != ActorRef.noSender)
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +57,7 @@ class GeneratorControlDamageTest extends ActorTest {
|
||||||
val activityProbe = TestProbe()
|
val activityProbe = TestProbe()
|
||||||
zone.Activity = activityProbe.ref
|
zone.Activity = activityProbe.ref
|
||||||
|
|
||||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
val gen = Generator(GeneratorTest.generator_definition) //guid=2
|
||||||
gen.Position = Vector3(1, 0, 0)
|
gen.Position = Vector3(1, 0, 0)
|
||||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||||
|
|
||||||
|
|
@ -106,19 +106,18 @@ class GeneratorControlDamageTest extends ActorTest {
|
||||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||||
|
|
||||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||||
val msg_avatar = avatarProbe.receiveN(2, 500 milliseconds)
|
val msg_avatar = avatarProbe.receiveOne(500 milliseconds)
|
||||||
buildingProbe.expectNoMessage(200 milliseconds)
|
val msg_building = buildingProbe.receiveOne(500 milliseconds)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar.head match {
|
msg_avatar match {
|
||||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(1) match {
|
msg_building match {
|
||||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 15)) =>
|
case BuildingActor.AmenityStateChange(_, Some(GeneratorControl.Event.UnderAttack)) => true
|
||||||
true
|
case _ => false
|
||||||
case _ => false
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(gen.Health < gen.Definition.MaxHealth)
|
assert(gen.Health < gen.Definition.MaxHealth)
|
||||||
|
|
@ -139,7 +138,7 @@ class GeneratorControlCriticalTest extends ActorTest {
|
||||||
val activityProbe = TestProbe()
|
val activityProbe = TestProbe()
|
||||||
zone.Activity = activityProbe.ref
|
zone.Activity = activityProbe.ref
|
||||||
|
|
||||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
val gen = Generator(GeneratorTest.generator_definition) //guid=2
|
||||||
gen.Position = Vector3(1, 0, 0)
|
gen.Position = Vector3(1, 0, 0)
|
||||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||||
|
|
||||||
|
|
@ -190,25 +189,18 @@ class GeneratorControlCriticalTest extends ActorTest {
|
||||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||||
|
|
||||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||||
val msg_avatar = avatarProbe.receiveN(2, 500 milliseconds)
|
val msg_avatar = avatarProbe.receiveOne(500 milliseconds)
|
||||||
val msg_building = buildingProbe.receiveOne(500 milliseconds)
|
val msg_building = buildingProbe.receiveOne(500 milliseconds)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar.head match {
|
msg_avatar match {
|
||||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
|
||||||
msg_avatar(1) match {
|
|
||||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 15)) =>
|
|
||||||
true
|
|
||||||
case _ => false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
assert(
|
assert(
|
||||||
msg_building match {
|
msg_building match {
|
||||||
case BuildingActor.AmenityStateChange(o) => o eq gen
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Critical)) => o eq gen
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(gen.Health < halfHealth)
|
assert(gen.Health < halfHealth)
|
||||||
|
|
@ -229,7 +221,7 @@ class GeneratorControlDestroyedTest extends ActorTest {
|
||||||
val activityProbe = TestProbe()
|
val activityProbe = TestProbe()
|
||||||
zone.Activity = activityProbe.ref
|
zone.Activity = activityProbe.ref
|
||||||
|
|
||||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
val gen = Generator(GeneratorTest.generator_definition) //guid=2
|
||||||
gen.Position = Vector3(1, 0, 0)
|
gen.Position = Vector3(1, 0, 0)
|
||||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||||
|
|
||||||
|
|
@ -269,7 +261,6 @@ class GeneratorControlDestroyedTest extends ActorTest {
|
||||||
Vector3(1, 0, 0)
|
Vector3(1, 0, 0)
|
||||||
)
|
)
|
||||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||||
gen.Actor ! BuildingActor.NtuDepleted() //no auto-repair
|
|
||||||
expectNoMessage(200 milliseconds)
|
expectNoMessage(200 milliseconds)
|
||||||
//we're not testing that the math is correct
|
//we're not testing that the math is correct
|
||||||
|
|
||||||
|
|
@ -281,12 +272,16 @@ class GeneratorControlDestroyedTest extends ActorTest {
|
||||||
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
|
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
|
||||||
|
|
||||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||||
val msg_avatar1 = avatarProbe.receiveOne(500 milliseconds)
|
val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
|
||||||
buildingProbe.expectNoMessage(200 milliseconds)
|
|
||||||
assert(
|
assert(
|
||||||
msg_avatar1 match {
|
msg_building12.head match {
|
||||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
|
||||||
true
|
case _ => false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
msg_building12(1) match {
|
||||||
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -294,13 +289,13 @@ class GeneratorControlDestroyedTest extends ActorTest {
|
||||||
assert(!gen.Destroyed)
|
assert(!gen.Destroyed)
|
||||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||||
|
|
||||||
avatarProbe.expectNoMessage(9 seconds)
|
avatarProbe.expectNoMessage(9500 milliseconds)
|
||||||
val msg_avatar2 = avatarProbe.receiveN(3, 1000 milliseconds) //see DamageableEntity test file
|
val msg_avatar2 = avatarProbe.receiveN(3, 1000 milliseconds) //see DamageableEntity test file
|
||||||
val msg_building = buildingProbe.receiveOne(200 milliseconds)
|
val msg_building = buildingProbe.receiveOne(200 milliseconds)
|
||||||
assert(
|
assert(
|
||||||
msg_building match {
|
msg_building match {
|
||||||
case BuildingActor.AmenityStateChange(o) => o eq gen
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destroyed)) => o eq gen
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
|
|
@ -352,7 +347,7 @@ class GeneratorControlKillsTest extends ActorTest {
|
||||||
val activityProbe = TestProbe()
|
val activityProbe = TestProbe()
|
||||||
zone.Activity = activityProbe.ref
|
zone.Activity = activityProbe.ref
|
||||||
|
|
||||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
val gen = Generator(GeneratorTest.generator_definition) //guid=2
|
||||||
gen.Position = Vector3(1, 0, 0)
|
gen.Position = Vector3(1, 0, 0)
|
||||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||||
|
|
||||||
|
|
@ -400,7 +395,6 @@ class GeneratorControlKillsTest extends ActorTest {
|
||||||
Vector3(1, 0, 0)
|
Vector3(1, 0, 0)
|
||||||
)
|
)
|
||||||
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
val applyDamageTo = resolved.damage_model.Calculate(resolved)
|
||||||
gen.Actor ! BuildingActor.NtuDepleted() //no auto-repair
|
|
||||||
expectNoMessage(200 milliseconds)
|
expectNoMessage(200 milliseconds)
|
||||||
//we're not testing that the math is correct
|
//we're not testing that the math is correct
|
||||||
|
|
||||||
|
|
@ -412,21 +406,16 @@ class GeneratorControlKillsTest extends ActorTest {
|
||||||
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
|
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
|
||||||
|
|
||||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||||
val msg_avatar1 = avatarProbe.receiveN(2, 500 milliseconds)
|
val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
|
||||||
buildingProbe.expectNoMessage(200 milliseconds)
|
|
||||||
player1Probe.expectNoMessage(200 milliseconds)
|
|
||||||
player2Probe.expectNoMessage(200 milliseconds)
|
|
||||||
assert(
|
assert(
|
||||||
msg_avatar1.head match {
|
msg_building12.head match {
|
||||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
|
||||||
true
|
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar1(1) match {
|
msg_building12(1) match {
|
||||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
|
||||||
true
|
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -434,14 +423,13 @@ class GeneratorControlKillsTest extends ActorTest {
|
||||||
assert(!gen.Destroyed)
|
assert(!gen.Destroyed)
|
||||||
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
assert(gen.Condition == PlanetSideGeneratorState.Normal)
|
||||||
|
|
||||||
val msg_building = buildingProbe.receiveOne(10500 milliseconds)
|
avatarProbe.expectNoMessage(9500 milliseconds)
|
||||||
val msg_avatar2 = avatarProbe.receiveN(3, 200 milliseconds)
|
val msg_avatar2 = avatarProbe.receiveN(3, 1000 milliseconds) //see DamageableEntity test file
|
||||||
val msg_player1 = player1Probe.receiveOne(100 milliseconds)
|
val msg_building = buildingProbe.receiveOne(200 milliseconds)
|
||||||
player2Probe.expectNoMessage(200 milliseconds)
|
|
||||||
assert(
|
assert(
|
||||||
msg_building match {
|
msg_building match {
|
||||||
case BuildingActor.AmenityStateChange(o) => o eq gen
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destroyed)) => o eq gen
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
|
|
@ -459,22 +447,25 @@ class GeneratorControlKillsTest extends ActorTest {
|
||||||
assert(
|
assert(
|
||||||
msg_avatar2(2) match {
|
msg_avatar2(2) match {
|
||||||
case AvatarServiceMessage(
|
case AvatarServiceMessage(
|
||||||
"test",
|
"test",
|
||||||
AvatarAction.SendResponse(_, TriggerEffectMessage(PlanetSideGUID(2), "explosion_generator", None, None))
|
AvatarAction.SendResponse(_, TriggerEffectMessage(PlanetSideGUID(2), "explosion_generator", None, None))
|
||||||
) =>
|
) =>
|
||||||
true
|
true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
assert(gen.Health == 0)
|
||||||
|
assert(gen.Destroyed)
|
||||||
|
assert(gen.Condition == PlanetSideGeneratorState.Destroyed)
|
||||||
|
|
||||||
|
val msg_player1 = player1Probe.receiveOne(100 milliseconds)
|
||||||
|
player2Probe.expectNoMessage(200 milliseconds)
|
||||||
assert(
|
assert(
|
||||||
msg_player1 match {
|
msg_player1 match {
|
||||||
case _ @Player.Die() => true
|
case _ @Player.Die() => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert(gen.Health == 0)
|
|
||||||
assert(gen.Destroyed)
|
|
||||||
assert(gen.Condition == PlanetSideGeneratorState.Destroyed)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -487,7 +478,7 @@ class GeneratorControlNotDestroyTwice extends ActorTest {
|
||||||
GUID(guid)
|
GUID(guid)
|
||||||
}
|
}
|
||||||
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
val building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
|
||||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
val gen = Generator(GeneratorTest.generator_definition) //guid=2
|
||||||
val player1 =
|
val player1 =
|
||||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=3
|
||||||
player1.Spawn()
|
player1.Spawn()
|
||||||
|
|
@ -573,7 +564,7 @@ class GeneratorControlNotDamageIfExplodingTest extends ActorTest {
|
||||||
val activityProbe = TestProbe()
|
val activityProbe = TestProbe()
|
||||||
zone.Activity = activityProbe.ref
|
zone.Activity = activityProbe.ref
|
||||||
|
|
||||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
val gen = Generator(GeneratorTest.generator_definition) //guid=2
|
||||||
gen.Position = Vector3(1, 0, 0)
|
gen.Position = Vector3(1, 0, 0)
|
||||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||||
|
|
||||||
|
|
@ -625,13 +616,16 @@ class GeneratorControlNotDamageIfExplodingTest extends ActorTest {
|
||||||
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
|
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
|
||||||
|
|
||||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||||
val msg_avatar = avatarProbe.receiveOne(500 milliseconds)
|
val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
|
||||||
buildingProbe.expectNoMessage(200 milliseconds)
|
|
||||||
player1Probe.expectNoMessage(200 milliseconds)
|
|
||||||
assert(
|
assert(
|
||||||
msg_avatar match {
|
msg_building12.head match {
|
||||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
|
||||||
true
|
case _ => false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
msg_building12(1) match {
|
||||||
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -667,7 +661,7 @@ class GeneratorControlNotRepairIfExplodingTest extends ActorTest {
|
||||||
val activityProbe = TestProbe()
|
val activityProbe = TestProbe()
|
||||||
zone.Activity = activityProbe.ref
|
zone.Activity = activityProbe.ref
|
||||||
|
|
||||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
val gen = Generator(GeneratorTest.generator_definition) //guid=2
|
||||||
gen.Position = Vector3(1, 0, 0)
|
gen.Position = Vector3(1, 0, 0)
|
||||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||||
|
|
||||||
|
|
@ -723,13 +717,16 @@ class GeneratorControlNotRepairIfExplodingTest extends ActorTest {
|
||||||
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
|
assert(gen.Condition == PlanetSideGeneratorState.Normal) //skipped critical state because didn't transition ~50%
|
||||||
|
|
||||||
gen.Actor ! Vitality.Damage(applyDamageTo)
|
gen.Actor ! Vitality.Damage(applyDamageTo)
|
||||||
val msg_avatar1 = avatarProbe.receiveOne(500 milliseconds)
|
val msg_building12 = buildingProbe.receiveN(2,500 milliseconds)
|
||||||
buildingProbe.expectNoMessage(200 milliseconds)
|
|
||||||
player1Probe.expectNoMessage(200 milliseconds)
|
|
||||||
assert(
|
assert(
|
||||||
msg_avatar1 match {
|
msg_building12.head match {
|
||||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 16)) =>
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Offline)) => o eq gen
|
||||||
true
|
case _ => false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
msg_building12(1) match {
|
||||||
|
case BuildingActor.AmenityStateChange(o, Some(GeneratorControl.Event.Destabilized)) => o eq gen
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -765,7 +762,7 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
|
||||||
val activityProbe = TestProbe()
|
val activityProbe = TestProbe()
|
||||||
zone.Activity = activityProbe.ref
|
zone.Activity = activityProbe.ref
|
||||||
|
|
||||||
val gen = Generator(GlobalDefinitions.generator) //guid=2
|
val gen = Generator(GeneratorTest.generator_definition) //guid=2
|
||||||
gen.Position = Vector3(1, 0, 0)
|
gen.Position = Vector3(1, 0, 0)
|
||||||
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
|
||||||
|
|
||||||
|
|
@ -804,7 +801,7 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
|
||||||
assert(gen.Destroyed)
|
assert(gen.Destroyed)
|
||||||
|
|
||||||
gen.Actor ! CommonMessages.Use(player1, Some(tool)) //repair
|
gen.Actor ! CommonMessages.Use(player1, Some(tool)) //repair
|
||||||
val msg_avatar = avatarProbe.receiveN(4, 500 milliseconds) //expected
|
val msg_avatar = avatarProbe.receiveN(3, 500 milliseconds) //expected
|
||||||
val msg_building = buildingProbe.receiveOne(200 milliseconds)
|
val msg_building = buildingProbe.receiveOne(200 milliseconds)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar.head match {
|
msg_avatar.head match {
|
||||||
|
|
@ -825,13 +822,6 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_avatar(2) match {
|
msg_avatar(2) match {
|
||||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.GenericObjectAction(_, PlanetSideGUID(1), 17)) =>
|
|
||||||
true
|
|
||||||
case _ => false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
assert(
|
|
||||||
msg_avatar(3) match {
|
|
||||||
case AvatarServiceMessage(
|
case AvatarServiceMessage(
|
||||||
"TestCharacter1",
|
"TestCharacter1",
|
||||||
AvatarAction.SendResponse(_, RepairMessage(ValidPlanetSideGUID(2), _))
|
AvatarAction.SendResponse(_, RepairMessage(ValidPlanetSideGUID(2), _))
|
||||||
|
|
@ -842,7 +832,7 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
|
||||||
)
|
)
|
||||||
assert(
|
assert(
|
||||||
msg_building match {
|
msg_building match {
|
||||||
case BuildingActor.AmenityStateChange(o) => o eq gen
|
case BuildingActor.AmenityStateChange(o, _) => o eq gen
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -852,3 +842,15 @@ class GeneratorControlRepairPastRestorePoint extends ActorTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object GeneratorTest {
|
||||||
|
final val generator_definition = new GeneratorDefinition(352) {
|
||||||
|
MaxHealth = 4000
|
||||||
|
Damageable = true
|
||||||
|
DamageableByFriendlyFire = false
|
||||||
|
Repairable = true
|
||||||
|
RepairDistance = 13.5f
|
||||||
|
RepairIfDestroyed = true
|
||||||
|
//note: no auto-repair
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -289,12 +289,6 @@ class ResourceSiloControlUpdate1Test extends ActorTest {
|
||||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 47, 0)) => true
|
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 47, 0)) => true
|
||||||
case _ => false
|
case _ => false
|
||||||
})
|
})
|
||||||
|
|
||||||
val reply4 = zoneEvents.receiveOne(500 milliseconds)
|
|
||||||
assert(reply4 match {
|
|
||||||
case AvatarServiceMessage("nowhere", AvatarAction.PlanetsideAttribute(PlanetSideGUID(6), 48, 0)) => true
|
|
||||||
case _ => false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue