mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-07-16 08:55:18 +00:00
radiator is turned off due to potential for server crashes; cerebus -> cerberus; turret kills name owner only when they are in the same zone; fewer chances for turrets to fire when they should not
This commit is contained in:
parent
a699c6c223
commit
e5cde75e72
14 changed files with 110 additions and 81 deletions
|
|
@ -76,6 +76,7 @@ add_property pulsar equiptime 600
|
||||||
add_property pulsar holstertime 600
|
add_property pulsar holstertime 600
|
||||||
add_property punisher equiptime 600
|
add_property punisher equiptime 600
|
||||||
add_property punisher holstertime 600
|
add_property punisher holstertime 600
|
||||||
|
add_property radiator allowed false
|
||||||
add_property r_shotgun equiptime 750
|
add_property r_shotgun equiptime 750
|
||||||
add_property r_shotgun holstertime 750
|
add_property r_shotgun holstertime 750
|
||||||
add_property remote_electronics_kit equiptime 500
|
add_property remote_electronics_kit equiptime 500
|
||||||
|
|
|
||||||
|
|
@ -545,9 +545,9 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
turret.Actor ! AutomatedTurretBehavior.ConfirmShot(target)
|
turret.Actor ! AutomatedTurretBehavior.ConfirmShot(target)
|
||||||
Some(target)
|
Some(target)
|
||||||
|
|
||||||
case turret: AutomatedTurret =>
|
case turret: AutomatedTurret with OwnableByPlayer =>
|
||||||
turret.Actor ! AutomatedTurretBehavior.ConfirmShot(target)
|
turret.Actor ! AutomatedTurretBehavior.ConfirmShot(target)
|
||||||
HandleAIDamage(target, CompileAutomatedTurretDamageData(turret, turret.TurretOwner, projectileTypeId))
|
HandleAIDamage(target, CompileAutomatedTurretDamageData(turret, projectileTypeId))
|
||||||
Some(target)
|
Some(target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -558,9 +558,9 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
case target: PlanetSideServerObject with FactionAffinity with Vitality =>
|
case target: PlanetSideServerObject with FactionAffinity with Vitality =>
|
||||||
sessionLogic.validObject(attackerGuid, decorator = "AIDamage/Attacker")
|
sessionLogic.validObject(attackerGuid, decorator = "AIDamage/Attacker")
|
||||||
.collect {
|
.collect {
|
||||||
case turret: AutomatedTurret if turret.Target.nonEmpty =>
|
case turret: AutomatedTurret with OwnableByPlayer if turret.Target.nonEmpty =>
|
||||||
//the turret must be shooting at something (else) first
|
//the turret must be shooting at something (else) first
|
||||||
HandleAIDamage(target, CompileAutomatedTurretDamageData(turret, turret.TurretOwner, projectileTypeId))
|
HandleAIDamage(target, CompileAutomatedTurretDamageData(turret, projectileTypeId))
|
||||||
}
|
}
|
||||||
Some(target)
|
Some(target)
|
||||||
}
|
}
|
||||||
|
|
@ -1268,14 +1268,17 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
}
|
}
|
||||||
|
|
||||||
private def CompileAutomatedTurretDamageData(
|
private def CompileAutomatedTurretDamageData(
|
||||||
turret: AutomatedTurret,
|
turret: AutomatedTurret with OwnableByPlayer,
|
||||||
owner: SourceEntry,
|
|
||||||
projectileTypeId: Long
|
projectileTypeId: Long
|
||||||
): Option[(AutomatedTurret, Tool, SourceEntry, ProjectileDefinition)] = {
|
): Option[(AutomatedTurret, Tool, SourceEntry, ProjectileDefinition)] = {
|
||||||
turret.Weapons
|
turret.Weapons
|
||||||
.values
|
.values
|
||||||
.flatMap { _.Equipment }
|
.flatMap { _.Equipment }
|
||||||
.collect { case weapon: Tool => (turret, weapon, owner, weapon.Projectile) }
|
.collect {
|
||||||
|
case weapon: Tool =>
|
||||||
|
val source = Deployables.AssignBlameTo(continent, turret.OwnerName, SourceEntry(turret))
|
||||||
|
(turret, weapon, source, weapon.Projectile)
|
||||||
|
}
|
||||||
.find { case (_, _, _, p) => p.ObjectId == projectileTypeId }
|
.find { case (_, _, _, p) => p.ObjectId == projectileTypeId }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import net.psforever.objects.avatar.{Avatar, Certification}
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import net.psforever.objects.ce.{Deployable, DeployedItem}
|
import net.psforever.objects.ce.{Deployable, DeployedItem}
|
||||||
|
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.types.PlanetSideGUID
|
import net.psforever.types.PlanetSideGUID
|
||||||
|
|
@ -261,4 +262,48 @@ object Deployables {
|
||||||
}
|
}
|
||||||
(sample intersect testDiff equals testDiff) && (sampleIntersect intersect testIntersect equals testIntersect)
|
(sample intersect testDiff equals testDiff) && (sampleIntersect intersect testIntersect equals testIntersect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a player with a given name in this zone.
|
||||||
|
* The assumption is the player is the owner of a given deployable entity.
|
||||||
|
* If the player can not be found, the deployable entity can stand in as it's own owner.
|
||||||
|
* @param zone continent in which the player should be found;
|
||||||
|
* should be the same zone as the deployable, but not required
|
||||||
|
* @param nameOpt optional player's name
|
||||||
|
* @param deployableSource deployable entity
|
||||||
|
* @return discovered player as a reference
|
||||||
|
*/
|
||||||
|
def AssignBlameTo(zone: Zone, nameOpt: Option[String], deployableSource: SourceEntry): SourceEntry = {
|
||||||
|
zone
|
||||||
|
.Players
|
||||||
|
.find(a => nameOpt.contains(a.name))
|
||||||
|
.collect { a =>
|
||||||
|
val name = a.name
|
||||||
|
Deployables.AssignBlameToFrom(name, zone.LivePlayers)
|
||||||
|
.orElse(Deployables.AssignBlameToFrom(name, zone.Corpses))
|
||||||
|
.getOrElse {
|
||||||
|
val player = PlayerSource(name, deployableSource.Faction, deployableSource.Position) //might report minor inconsistencies, e.g., exo-suit type
|
||||||
|
player.copy(unique = player.unique.copy(charId = a.id), progress = a.scorecard.CurrentLife)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.getOrElse(deployableSource)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a player with a given name from this list of possible players.
|
||||||
|
* If the player is seated, attach a shallow copy of the mounting information.
|
||||||
|
* @param name player name
|
||||||
|
* @param blameList possible players in which to find the player name
|
||||||
|
* @return discovered player as a reference, or `None` if not found
|
||||||
|
*/
|
||||||
|
private def AssignBlameToFrom(name: String, blameList: List[Player]): Option[SourceEntry] = {
|
||||||
|
blameList
|
||||||
|
.find(_.Name.equals(name))
|
||||||
|
.map { player =>
|
||||||
|
PlayerSource
|
||||||
|
.mountableAndSeat(player)
|
||||||
|
.map { case (mount, seat) => PlayerSource.inSeat(player, mount, seat) }
|
||||||
|
.getOrElse { PlayerSource(player) }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import akka.actor.{ActorContext, ActorRef, Props}
|
||||||
import net.psforever.objects.ce.{Deployable, DeployedItem}
|
import net.psforever.objects.ce.{Deployable, DeployedItem}
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
import net.psforever.objects.sourcing.{DeployableSource, PlayerSource, SourceEntry}
|
import net.psforever.objects.sourcing.{DeployableSource, SourceEntry}
|
||||||
import net.psforever.objects.vital.Vitality
|
import net.psforever.objects.vital.Vitality
|
||||||
import net.psforever.objects.vital.etc.TrippedMineReason
|
import net.psforever.objects.vital.etc.TrippedMineReason
|
||||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||||
|
|
@ -98,40 +98,8 @@ object MineDeployableControl {
|
||||||
private case class Triggered()
|
private case class Triggered()
|
||||||
|
|
||||||
def trippedMineReason(mine: ExplosiveDeployable): TrippedMineReason = {
|
def trippedMineReason(mine: ExplosiveDeployable): TrippedMineReason = {
|
||||||
lazy val deployableSource = DeployableSource(mine)
|
val deployableSource = DeployableSource(mine)
|
||||||
val zone = mine.Zone
|
val blame = Deployables.AssignBlameTo(mine.Zone, mine.OwnerName, deployableSource)
|
||||||
val ownerName = mine.OwnerName
|
|
||||||
val blame = zone
|
|
||||||
.Players
|
|
||||||
.find(a => ownerName.contains(a.name))
|
|
||||||
.collect { a =>
|
|
||||||
val name = a.name
|
|
||||||
assignBlameToFrom(name, zone.LivePlayers)
|
|
||||||
.orElse(assignBlameToFrom(name, zone.Corpses))
|
|
||||||
.getOrElse {
|
|
||||||
val player = PlayerSource(name, mine.Faction, mine.Position) //might report minor inconsistencies, e.g., exo-suit type
|
|
||||||
player.copy(unique = player.unique.copy(charId = a.id), progress = a.scorecard.CurrentLife)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.getOrElse(deployableSource)
|
|
||||||
TrippedMineReason(deployableSource, blame)
|
TrippedMineReason(deployableSource, blame)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a player with a given name from this list of possible players.
|
|
||||||
* If the player is seated, attach a shallow copy of the mounting information.
|
|
||||||
* @param name player name
|
|
||||||
* @param blameList possible players in which to find the player name
|
|
||||||
* @return discovered player as a reference, or `None` if not found
|
|
||||||
*/
|
|
||||||
private def assignBlameToFrom(name: String, blameList: List[Player]): Option[SourceEntry] = {
|
|
||||||
blameList
|
|
||||||
.find(_.Name.equals(name))
|
|
||||||
.map { player =>
|
|
||||||
PlayerSource
|
|
||||||
.mountableAndSeat(player)
|
|
||||||
.map { case (mount, seat) => PlayerSource.inSeat(player, mount, seat) }
|
|
||||||
.getOrElse { PlayerSource(player) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,9 @@ import scala.collection.mutable
|
||||||
* As deployables are added and removed, and tracked certifications are added and removed,
|
* As deployables are added and removed, and tracked certifications are added and removed,
|
||||||
* these structures are updated to reflect proper count.
|
* these structures are updated to reflect proper count.
|
||||||
* For example, the greatest number of spitfire turrets that can be placed is 15 (individual count)
|
* For example, the greatest number of spitfire turrets that can be placed is 15 (individual count)
|
||||||
* and the greatest number of shadow turrets and cerebus turrets that can be placed is 5 each (individual counts)
|
* and the greatest number of shadow turrets and cerberus turrets that can be placed is 5 each (individual counts)
|
||||||
* but the maximum number of small turrets that can be placed overall is only 15 (categorical count).
|
* but the maximum number of small turrets that can be placed overall is only 15 (categorical count).
|
||||||
* Spitfire turrets, shadow turrets, and cerebus turrets are all included in the category of small turrets.
|
* Spitfire turrets, shadow turrets, and cerberus turrets are all included in the category of small turrets.
|
||||||
*/
|
*/
|
||||||
class DeployableToolbox {
|
class DeployableToolbox {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ object Deployable {
|
||||||
DeployedItem.jammer_mine.id -> DeployableIcon.DisruptorMine,
|
DeployedItem.jammer_mine.id -> DeployableIcon.DisruptorMine,
|
||||||
DeployedItem.spitfire_turret.id -> DeployableIcon.SpitfireTurret,
|
DeployedItem.spitfire_turret.id -> DeployableIcon.SpitfireTurret,
|
||||||
DeployedItem.spitfire_cloaked.id -> DeployableIcon.ShadowTurret,
|
DeployedItem.spitfire_cloaked.id -> DeployableIcon.ShadowTurret,
|
||||||
DeployedItem.spitfire_aa.id -> DeployableIcon.CerebusTurret,
|
DeployedItem.spitfire_aa.id -> DeployableIcon.cerberusTurret,
|
||||||
DeployedItem.motionalarmsensor.id -> DeployableIcon.MotionAlarmSensor,
|
DeployedItem.motionalarmsensor.id -> DeployableIcon.MotionAlarmSensor,
|
||||||
DeployedItem.sensor_shield.id -> DeployableIcon.SensorDisruptor,
|
DeployedItem.sensor_shield.id -> DeployableIcon.SensorDisruptor,
|
||||||
DeployedItem.tank_traps.id -> DeployableIcon.TRAP,
|
DeployedItem.tank_traps.id -> DeployableIcon.TRAP,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ object DeployedItem extends Enumeration {
|
||||||
final val jammer_mine = Value(420) //disruptor mine
|
final val jammer_mine = Value(420) //disruptor mine
|
||||||
final val motionalarmsensor = Value(575)
|
final val motionalarmsensor = Value(575)
|
||||||
final val sensor_shield = Value(752) //sensor disruptor
|
final val sensor_shield = Value(752) //sensor disruptor
|
||||||
final val spitfire_aa = Value(819) //cerebus turret
|
final val spitfire_aa = Value(819) //cerberus turret
|
||||||
final val spitfire_cloaked = Value(825) //shadow turret
|
final val spitfire_cloaked = Value(825) //shadow turret
|
||||||
final val spitfire_turret = Value(826)
|
final val spitfire_turret = Value(826)
|
||||||
final val tank_traps = Value(849) //trap
|
final val tank_traps = Value(849) //trap
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ class UniqueNumberOps(
|
||||||
private val poolActors: Map[String, ActorRef]
|
private val poolActors: Map[String, ActorRef]
|
||||||
) {
|
) {
|
||||||
/** The timeout used by all number pool `ask` messaging */
|
/** The timeout used by all number pool `ask` messaging */
|
||||||
private implicit val timeout = UniqueNumberOps.timeout
|
private implicit val timeout: Timeout = UniqueNumberOps.timeout
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entry point for the entity GUID registration process.
|
* The entry point for the entity GUID registration process.
|
||||||
|
|
@ -149,25 +149,26 @@ class UniqueNumberOps(
|
||||||
val localPool = pool
|
val localPool = pool
|
||||||
|
|
||||||
val result = ask(pool, NumberPoolActor.GetAnyNumber())(timeout)
|
val result = ask(pool, NumberPoolActor.GetAnyNumber())(timeout)
|
||||||
result.onComplete {
|
result
|
||||||
case Success(NumberPoolActor.GiveNumber(number)) =>
|
.recover {
|
||||||
UniqueNumberOps.processRegisterResult(
|
case ex: AskTimeoutException =>
|
||||||
localPromise,
|
localPromise.failure(new RegisteringException(msg = s"did not register entity $localTarget in time", ex))
|
||||||
localTarget,
|
}
|
||||||
localUns,
|
.onComplete {
|
||||||
localPoolName,
|
case Success(NumberPoolActor.GiveNumber(number)) =>
|
||||||
localPool,
|
UniqueNumberOps.processRegisterResult(
|
||||||
number
|
localPromise,
|
||||||
)
|
localTarget,
|
||||||
case Success(NumberPoolActor.NoNumber(ex)) =>
|
localUns,
|
||||||
registrationProcessRetry(localPromise, ex, localTarget, localUns, localPools, localPoolName)
|
localPoolName,
|
||||||
case msg =>
|
localPool,
|
||||||
UniqueNumberOps.log.warn(s"unexpected message during $localTarget's registration process - $msg")
|
number
|
||||||
}
|
)
|
||||||
result.recover {
|
case Success(NumberPoolActor.NoNumber(ex)) =>
|
||||||
case ex: AskTimeoutException =>
|
registrationProcessRetry(localPromise, ex, localTarget, localUns, localPools, localPoolName)
|
||||||
localPromise.failure(new RegisteringException(msg = s"did not register entity $localTarget in time", ex))
|
case msg =>
|
||||||
}
|
UniqueNumberOps.log.warn(s"unexpected message during $localTarget's registration process - $msg")
|
||||||
|
}
|
||||||
|
|
||||||
case None =>
|
case None =>
|
||||||
//do not log
|
//do not log
|
||||||
|
|
@ -197,7 +198,7 @@ class UniqueNumberOps(
|
||||||
if (poolName.equals("generic")) {
|
if (poolName.equals("generic")) {
|
||||||
promise.failure(new RegisteringException(msg = s"did not register entity $obj", exception))
|
promise.failure(new RegisteringException(msg = s"did not register entity $obj", exception))
|
||||||
} else {
|
} else {
|
||||||
org.log4s.getLogger("UniqueNumberOps").warn(s"${exception.getLocalizedMessage()} - $poolName")
|
UniqueNumberOps.log.warn(s"${exception.getLocalizedMessage()} - $poolName")
|
||||||
promise.completeWith(registrationProcess(obj, guid, pools, poolName = "generic"))
|
promise.completeWith(registrationProcess(obj, guid, pools, poolName = "generic"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -302,7 +303,7 @@ class UniqueNumberOps(
|
||||||
|
|
||||||
object UniqueNumberOps {
|
object UniqueNumberOps {
|
||||||
private val log = org.log4s.getLogger
|
private val log = org.log4s.getLogger
|
||||||
private implicit val timeout = Timeout(2.seconds)
|
private implicit val timeout: Timeout = Timeout(4.seconds)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Final step of the object registration process.
|
* Final step of the object registration process.
|
||||||
|
|
@ -431,7 +432,7 @@ class UniqueNumberSetup(
|
||||||
) extends Actor {
|
) extends Actor {
|
||||||
init()
|
init()
|
||||||
|
|
||||||
final def receive: Receive = { case _ => ; }
|
final def receive: Receive = { case _ => () }
|
||||||
|
|
||||||
def init(): UniqueNumberOps = {
|
def init(): UniqueNumberOps = {
|
||||||
new UniqueNumberOps(hub, poolActorConversionFunc(context, hub))
|
new UniqueNumberOps(hub, poolActorConversionFunc(context, hub))
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
override protected def tryMount(obj: PlanetSideServerObject with Mountable, seatNumber: Int, player: Player): Boolean = {
|
override protected def tryMount(obj: PlanetSideServerObject with Mountable, seatNumber: Int, player: Player): Boolean = {
|
||||||
val originalAutoState = AutomaticOperation
|
val originalAutoState = AutomaticOperation
|
||||||
AutomaticOperation = false //turn off
|
AutomaticOperation = false //turn off
|
||||||
if (JammableObject.Jammed) {
|
if (AutomaticOperationPossible && JammableObject.Jammed) {
|
||||||
val zone = TurretObject.Zone
|
val zone = TurretObject.Zone
|
||||||
AutomatedTurretBehavior.stopTracking(zone, zone.id, TurretObject.GUID) //can not recover lost jamming aggro
|
AutomatedTurretBehavior.stopTracking(zone, zone.id, TurretObject.GUID) //can not recover lost jamming aggro
|
||||||
}
|
}
|
||||||
|
|
@ -220,6 +220,15 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
!TurretObject.isUpgrading
|
!TurretObject.isUpgrading
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def AutomaticOperationPossible: Boolean = {
|
||||||
|
super.AutomaticOperationPossible &&
|
||||||
|
(turret.Owner match {
|
||||||
|
case b: Building if b.CaptureTerminal.isEmpty => false
|
||||||
|
case b: Building => !b.CaptureTerminal.exists(_.Definition == GlobalDefinitions.secondary_capture)
|
||||||
|
case _ => false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private def primaryWeaponFireModeOnly(): Unit = {
|
private def primaryWeaponFireModeOnly(): Unit = {
|
||||||
if (testToResetToDefaultFireMode) {
|
if (testToResetToDefaultFireMode) {
|
||||||
val zone = TurretObject.Zone
|
val zone = TurretObject.Zone
|
||||||
|
|
@ -295,7 +304,7 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
|
|
||||||
override def TryJammerEffectActivate(target: Any, cause: DamageResult): Unit = {
|
override def TryJammerEffectActivate(target: Any, cause: DamageResult): Unit = {
|
||||||
super.TryJammerEffectActivate(target, cause)
|
super.TryJammerEffectActivate(target, cause)
|
||||||
if (JammableObject.Jammed) {
|
if (AutomaticOperationPossible && AutomaticOperation && JammableObject.Jammed) {
|
||||||
AutomaticOperation = false
|
AutomaticOperation = false
|
||||||
if (!MountableObject.Seats.values.exists(_.isOccupied) && AutomatedTurretObject.Definition.AutoFire.exists(_.retaliatoryDelay > 0)) {
|
if (!MountableObject.Seats.values.exists(_.isOccupied) && AutomatedTurretObject.Definition.AutoFire.exists(_.retaliatoryDelay > 0)) {
|
||||||
//look in direction of cause of jamming
|
//look in direction of cause of jamming
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ trait AutomatedTurretBehavior {
|
||||||
Actor.emptyBehavior
|
Actor.emptyBehavior
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def AutomaticOperationPossible: Boolean = autoStats.isDefined
|
||||||
|
|
||||||
def AutomaticOperation: Boolean = automaticOperation
|
def AutomaticOperation: Boolean = automaticOperation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -111,7 +113,7 @@ trait AutomatedTurretBehavior {
|
||||||
* @return `true`, if it would be possible for automated behavior to become operational;
|
* @return `true`, if it would be possible for automated behavior to become operational;
|
||||||
* `false`, otherwise
|
* `false`, otherwise
|
||||||
*/
|
*/
|
||||||
protected def AutomaticOperationFunctionalityChecks: Boolean = { autoStats.isDefined }
|
protected def AutomaticOperationFunctionalityChecks: Boolean = AutomaticOperationPossible
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last time weapons fire from the turret was confirmed by this control agency.
|
* The last time weapons fire from the turret was confirmed by this control agency.
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ object DeploymentAction extends Enumeration {
|
||||||
object DeployableIcon extends Enumeration {
|
object DeployableIcon extends Enumeration {
|
||||||
type Type = Value
|
type Type = Value
|
||||||
|
|
||||||
val Boomer, HEMine, MotionAlarmSensor, SpitfireTurret, RouterTelepad, DisruptorMine, ShadowTurret, CerebusTurret,
|
val Boomer, HEMine, MotionAlarmSensor, SpitfireTurret, RouterTelepad, DisruptorMine, ShadowTurret, cerberusTurret,
|
||||||
TRAP, AegisShieldGenerator, FieldTurret, SensorDisruptor = Value
|
TRAP, AegisShieldGenerator, FieldTurret, SensorDisruptor = Value
|
||||||
|
|
||||||
implicit val codec: Codec[DeployableIcon.Value] = PacketHelpers.createEnumerationCodec(this, uint4L)
|
implicit val codec: Codec[DeployableIcon.Value] = PacketHelpers.createEnumerationCodec(this, uint4L)
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import scodec.codecs._
|
||||||
* `86 - max spitfire turrets`<br>
|
* `86 - max spitfire turrets`<br>
|
||||||
* `87 - max motion sensors`<br>
|
* `87 - max motion sensors`<br>
|
||||||
* `88 - max shadow turrets`<br>
|
* `88 - max shadow turrets`<br>
|
||||||
* `89 - max cerebus turrets`<br>
|
* `89 - max cerberus turrets`<br>
|
||||||
* `90 - max Aegis shield generators`<br>
|
* `90 - max Aegis shield generators`<br>
|
||||||
* `91 - max TRAPs`<br>
|
* `91 - max TRAPs`<br>
|
||||||
* `92 - max OMFTs`<br>
|
* `92 - max OMFTs`<br>
|
||||||
|
|
@ -43,7 +43,7 @@ import scodec.codecs._
|
||||||
* `97 - spitfire turrets`<br>
|
* `97 - spitfire turrets`<br>
|
||||||
* `98 - motion sensors`<br>
|
* `98 - motion sensors`<br>
|
||||||
* `99 - shadow turrets`<br>
|
* `99 - shadow turrets`<br>
|
||||||
* `100 - cerebus turrets`<br>
|
* `100 - cerberus turrets`<br>
|
||||||
* `101 - Aegis shield generators`<br>
|
* `101 - Aegis shield generators`<br>
|
||||||
* `102 - TRAPSs`<br>
|
* `102 - TRAPSs`<br>
|
||||||
* `103 - OMFTs`<br>
|
* `103 - OMFTs`<br>
|
||||||
|
|
|
||||||
|
|
@ -138,14 +138,14 @@ class TurretDeployableTest extends Specification {
|
||||||
DeployedItem.portable_manned_turret_nc.id,
|
DeployedItem.portable_manned_turret_nc.id,
|
||||||
DeployedItem.portable_manned_turret_vs.id
|
DeployedItem.portable_manned_turret_vs.id
|
||||||
).foreach(id => {
|
).foreach(id => {
|
||||||
try { new TurretDeployableDefinition(id) }
|
try { new TurretDeployableDefinition(id) { } }
|
||||||
catch { case _: Exception => ko }
|
catch { case _: Exception => ko }
|
||||||
})
|
})
|
||||||
ok
|
ok
|
||||||
}
|
}
|
||||||
|
|
||||||
"define (invalid object)" in {
|
"define (invalid object)" in {
|
||||||
new TurretDeployableDefinition(5) must throwA[NoSuchElementException] //wrong object id altogether
|
new TurretDeployableDefinition(objectId = 5) { } must throwA[NoSuchElementException] //wrong object id altogether
|
||||||
}
|
}
|
||||||
|
|
||||||
"construct" in {
|
"construct" in {
|
||||||
|
|
@ -212,7 +212,7 @@ class DeployableMake extends Specification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"construct a cerebus turret" in {
|
"construct a cerberus turret" in {
|
||||||
val func = Deployables.Make(DeployedItem.spitfire_aa)
|
val func = Deployables.Make(DeployedItem.spitfire_aa)
|
||||||
func() match {
|
func() match {
|
||||||
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.spitfire_aa => ok
|
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.spitfire_aa => ok
|
||||||
|
|
|
||||||
|
|
@ -819,13 +819,13 @@ class DeployableToolboxTest extends Specification {
|
||||||
val obj = new DeployableToolbox
|
val obj = new DeployableToolbox
|
||||||
obj.Initialize(Set(CombatEngineering))
|
obj.Initialize(Set(CombatEngineering))
|
||||||
|
|
||||||
val cerebus = new TurretDeployable(GlobalDefinitions.spitfire_aa) //cerebus turret
|
val cerberus = new TurretDeployable(GlobalDefinitions.spitfire_aa) //cerberus turret
|
||||||
obj.Valid(cerebus) mustEqual false
|
obj.Valid(cerberus) mustEqual false
|
||||||
obj.CountDeployable(DeployedItem.spitfire_aa).productIterator.toList mustEqual List(0, 0)
|
obj.CountDeployable(DeployedItem.spitfire_aa).productIterator.toList mustEqual List(0, 0)
|
||||||
|
|
||||||
obj.UpdateMaxCounts(Set(CombatEngineering, AdvancedEngineering))
|
obj.UpdateMaxCounts(Set(CombatEngineering, AdvancedEngineering))
|
||||||
|
|
||||||
obj.Valid(cerebus) mustEqual true
|
obj.Valid(cerberus) mustEqual true
|
||||||
obj.CountDeployable(DeployedItem.spitfire_aa).productIterator.toList mustEqual List(0, 5)
|
obj.CountDeployable(DeployedItem.spitfire_aa).productIterator.toList mustEqual List(0, 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue