diff --git a/server/src/main/resources/overrides/game_objects0.adb.lst b/server/src/main/resources/overrides/game_objects0.adb.lst
index be23a5ae4..5e08278e5 100644
--- a/server/src/main/resources/overrides/game_objects0.adb.lst
+++ b/server/src/main/resources/overrides/game_objects0.adb.lst
@@ -76,6 +76,7 @@ add_property pulsar equiptime 600
add_property pulsar holstertime 600
add_property punisher equiptime 600
add_property punisher holstertime 600
+add_property radiator allowed false
add_property r_shotgun equiptime 750
add_property r_shotgun holstertime 750
add_property remote_electronics_kit equiptime 500
diff --git a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala
index 0a26acee8..1eb457f9d 100644
--- a/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala
+++ b/src/main/scala/net/psforever/actors/session/normal/GeneralLogic.scala
@@ -41,7 +41,7 @@ import net.psforever.objects.zones.blockmap.BlockMapEntity
import net.psforever.objects.zones.{Zone, ZoneProjectile, Zoning}
import net.psforever.packet.PlanetSideGamePacket
import net.psforever.packet.game.objectcreate.ObjectClass
-import net.psforever.packet.game.{ActionCancelMessage, ActionResultMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BindStatus, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestAction, CharacterRequestMessage, ChatMsg, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeadState, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, ImplantAction, InvalidTerrainMessage, ItemTransactionMessage, LootItemMessage, MoveItemMessage, ObjectDeleteMessage, ObjectDetectedMessage, ObjectHeldMessage, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, PlayerStateShiftMessage, RequestDestroyMessage, ShiftState, Shortcut, TargetInfo, TargetingImplantRequest, TargetingInfoMessage, TerrainCondition, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage}
+import net.psforever.packet.game.{ActionCancelMessage, ActionResultMessage, AvatarFirstTimeEventMessage, AvatarImplantMessage, AvatarJumpMessage, BattleplanMessage, BindPlayerMessage, BindStatus, BugReportMessage, ChangeFireModeMessage, ChangeShortcutBankMessage, CharacterCreateRequestMessage, CharacterRequestAction, CharacterRequestMessage, ChatMsg, CollisionIs, ConnectToWorldRequestMessage, CreateShortcutMessage, DeadState, DeployObjectMessage, DisplayedAwardMessage, DropItemMessage, EmoteMsg, FacilityBenefitShieldChargeRequestMessage, FriendsRequest, GenericAction, GenericActionMessage, GenericCollisionMsg, GenericObjectActionAtPositionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HitHint, ImplantAction, InvalidTerrainMessage, ItemTransactionMessage, LootItemMessage, MoveItemMessage, ObjectDeleteMessage, ObjectDetectedMessage, ObjectHeldMessage, PickupItemMessage, PlanetsideAttributeMessage, PlayerStateMessageUpstream, PlayerStateShiftMessage, RequestDestroyMessage, ShiftState, TargetInfo, TargetingImplantRequest, TargetingInfoMessage, TerrainCondition, TradeMessage, UnuseItemMessage, UseItemMessage, VoiceHostInfo, VoiceHostRequest, ZipLineMessage}
import net.psforever.services.RemoverActor
import net.psforever.services.account.{AccountPersistenceService, RetrieveAccountData}
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
@@ -1025,13 +1025,18 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
private def handleUseResourceSilo(resourceSilo: ResourceSilo, equipment: Option[Equipment]): Unit = {
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
- (continent.GUID(player.VehicleSeated), equipment) match {
+ val vehicleOpt = continent.GUID(player.avatar.vehicle)
+ (vehicleOpt, equipment) match {
case (Some(vehicle: Vehicle), Some(item))
if GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition) &&
GlobalDefinitions.isBattleFrameNTUSiphon(item.Definition) =>
- resourceSilo.Actor ! CommonMessages.Use(player, equipment)
- case _ =>
- resourceSilo.Actor ! CommonMessages.Use(player)
+ resourceSilo.Actor ! CommonMessages.Use(player, Some(vehicle))
+ case (Some(vehicle: Vehicle), _)
+ if vehicle.Definition == GlobalDefinitions.ant &&
+ vehicle.DeploymentState == DriveState.Deployed &&
+ Vector3.DistanceSquared(resourceSilo.Position.xy, vehicle.Position.xy) < math.pow(resourceSilo.Definition.UseRadius, 2) =>
+ resourceSilo.Actor ! CommonMessages.Use(player, Some(vehicle))
+ case _ => ()
}
}
diff --git a/src/main/scala/net/psforever/actors/session/normal/LocalHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/normal/LocalHandlerLogic.scala
index 8ddb6896b..009d0bbd7 100644
--- a/src/main/scala/net/psforever/actors/session/normal/LocalHandlerLogic.scala
+++ b/src/main/scala/net/psforever/actors/session/normal/LocalHandlerLogic.scala
@@ -4,6 +4,7 @@ package net.psforever.actors.session.normal
import akka.actor.ActorContext
import net.psforever.actors.session.support.{LocalHandlerFunctions, SessionData, SessionLocalHandlers}
import net.psforever.objects.ce.Deployable
+import net.psforever.objects.serverobject.doors.Door
import net.psforever.objects.vehicles.MountableWeapons
import net.psforever.objects.{BoomerDeployable, ExplosiveDeployable, TelepadDeployable, Tool, TurretDeployable}
import net.psforever.packet.game.{ChatMsg, DeployableObjectsInfoMessage, GenericActionMessage, GenericObjectActionMessage, GenericObjectStateMsg, HackMessage, HackState, InventoryStateMessage, ObjectAttachMessage, ObjectCreateMessage, ObjectDeleteMessage, ObjectDetachMessage, OrbitalShuttleTimeMsg, PadAndShuttlePair, PlanetsideAttributeMessage, ProximityTerminalUseMessage, SetEmpireMessage, TriggerEffectMessage, TriggerSoundMessage, TriggeredSound, VehicleStateMessage}
@@ -66,7 +67,18 @@ class LocalHandlerLogic(val ops: SessionLocalHandlers, implicit val context: Act
log.warn(s"LocalResponse.Detonate: ${obj.Definition.Name} not configured to explode correctly")
case LocalResponse.DoorOpens(doorGuid) if isNotSameTarget =>
- sendResponse(GenericObjectStateMsg(doorGuid, state=16))
+ val pos = player.Position.xy
+ val range = ops.doorLoadRange()
+ val foundDoor = continent
+ .blockMap
+ .sector(pos, range)
+ .amenityList
+ .collect { case door: Door => door }
+ .find(_.GUID == doorGuid)
+ val doorExistsInRange: Boolean = foundDoor.nonEmpty
+ if (doorExistsInRange) {
+ sendResponse(GenericObjectStateMsg(doorGuid, state=16))
+ }
case LocalResponse.DoorCloses(doorGuid) => //door closes for everyone
sendResponse(GenericObjectStateMsg(doorGuid, state=17))
@@ -95,16 +107,14 @@ class LocalHandlerLogic(val ops: SessionLocalHandlers, implicit val context: Act
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, _, _) if obj.Active && obj.Destroyed =>
//if active, deactivate
obj.Active = false
- sendResponse(GenericObjectActionMessage(dguid, code=29))
- sendResponse(GenericObjectActionMessage(dguid, code=30))
+ ops.deactivateTelpadDeployableMessages(dguid)
//standard deployable elimination behavior
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, pos, _) if obj.Active =>
//if active, deactivate
obj.Active = false
- sendResponse(GenericObjectActionMessage(dguid, code=29))
- sendResponse(GenericObjectActionMessage(dguid, code=30))
+ ops.deactivateTelpadDeployableMessages(dguid)
//standard deployable elimination behavior
obj.Destroyed = true
DeconstructDeployable(obj, dguid, pos, obj.Orientation, deletionType=2)
diff --git a/src/main/scala/net/psforever/actors/session/normal/WeaponAndProjectileLogic.scala b/src/main/scala/net/psforever/actors/session/normal/WeaponAndProjectileLogic.scala
index 05608922b..cc5e710b7 100644
--- a/src/main/scala/net/psforever/actors/session/normal/WeaponAndProjectileLogic.scala
+++ b/src/main/scala/net/psforever/actors/session/normal/WeaponAndProjectileLogic.scala
@@ -545,9 +545,9 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
turret.Actor ! AutomatedTurretBehavior.ConfirmShot(target)
Some(target)
- case turret: AutomatedTurret =>
+ case turret: AutomatedTurret with OwnableByPlayer =>
turret.Actor ! AutomatedTurretBehavior.ConfirmShot(target)
- HandleAIDamage(target, CompileAutomatedTurretDamageData(turret, turret.TurretOwner, projectileTypeId))
+ HandleAIDamage(target, CompileAutomatedTurretDamageData(turret, projectileTypeId))
Some(target)
}
}
@@ -558,9 +558,9 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
case target: PlanetSideServerObject with FactionAffinity with Vitality =>
sessionLogic.validObject(attackerGuid, decorator = "AIDamage/Attacker")
.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
- HandleAIDamage(target, CompileAutomatedTurretDamageData(turret, turret.TurretOwner, projectileTypeId))
+ HandleAIDamage(target, CompileAutomatedTurretDamageData(turret, projectileTypeId))
}
Some(target)
}
@@ -1268,14 +1268,17 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
}
private def CompileAutomatedTurretDamageData(
- turret: AutomatedTurret,
- owner: SourceEntry,
+ turret: AutomatedTurret with OwnableByPlayer,
projectileTypeId: Long
): Option[(AutomatedTurret, Tool, SourceEntry, ProjectileDefinition)] = {
turret.Weapons
.values
.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 }
}
diff --git a/src/main/scala/net/psforever/actors/session/spectator/LocalHandlerLogic.scala b/src/main/scala/net/psforever/actors/session/spectator/LocalHandlerLogic.scala
index 21d85d7a1..c0810ab64 100644
--- a/src/main/scala/net/psforever/actors/session/spectator/LocalHandlerLogic.scala
+++ b/src/main/scala/net/psforever/actors/session/spectator/LocalHandlerLogic.scala
@@ -96,16 +96,14 @@ class LocalHandlerLogic(val ops: SessionLocalHandlers, implicit val context: Act
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, _, _) if obj.Active && obj.Destroyed =>
//if active, deactivate
obj.Active = false
- sendResponse(GenericObjectActionMessage(dguid, code=29))
- sendResponse(GenericObjectActionMessage(dguid, code=30))
+ ops.deactivateTelpadDeployableMessages(dguid)
//standard deployable elimination behavior
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, pos, _) if obj.Active =>
//if active, deactivate
obj.Active = false
- sendResponse(GenericObjectActionMessage(dguid, code=29))
- sendResponse(GenericObjectActionMessage(dguid, code=30))
+ ops.deactivateTelpadDeployableMessages(dguid)
//standard deployable elimination behavior
obj.Destroyed = true
DeconstructDeployable(obj, dguid, pos, obj.Orientation, deletionType=2)
diff --git a/src/main/scala/net/psforever/actors/session/support/SessionLocalHandlers.scala b/src/main/scala/net/psforever/actors/session/support/SessionLocalHandlers.scala
index 456e3a237..7fc6a893b 100644
--- a/src/main/scala/net/psforever/actors/session/support/SessionLocalHandlers.scala
+++ b/src/main/scala/net/psforever/actors/session/support/SessionLocalHandlers.scala
@@ -5,6 +5,8 @@ import akka.actor.ActorContext
import net.psforever.objects.{Players, TurretDeployable}
import net.psforever.objects.ce.Deployable
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
+import net.psforever.objects.serverobject.interior.Sidedness
+import net.psforever.packet.game.GenericObjectActionMessage
import net.psforever.services.local.LocalResponse
import net.psforever.types.PlanetSideGUID
@@ -22,7 +24,10 @@ class SessionLocalHandlers(
val sessionLogic: SessionData,
implicit val context: ActorContext
) extends CommonSessionInterfacingFunctionality {
-
+ def deactivateTelpadDeployableMessages(guid: PlanetSideGUID): Unit = {
+ sendResponse(GenericObjectActionMessage(guid, code = 29))
+ sendResponse(GenericObjectActionMessage(guid, code = 30))
+ }
def handleTurretDeployableIsDismissed(obj: TurretDeployable): Unit = {
Players.buildCooldownReset(continent, player.Name, obj)
@@ -33,4 +38,13 @@ class SessionLocalHandlers(
Players.buildCooldownReset(continent, player.Name, obj)
TaskWorkflow.execute(GUIDTask.unregisterObject(continent.GUID, obj))
}
+
+ def doorLoadRange(): Float = {
+ if (Sidedness.equals(player.WhichSide, Sidedness.InsideOf))
+ 100f
+ else if (sessionLogic.general.canSeeReallyFar)
+ 800f
+ else
+ 400f
+ }
}
diff --git a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala
index 5981f3850..6648cf3ba 100644
--- a/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala
+++ b/src/main/scala/net/psforever/actors/session/support/ZoningOperations.scala
@@ -2227,15 +2227,28 @@ class ZoningOperations(
sessionLogic.actionsToCancel()
continent.GUID(player.VehicleSeated) match {
case Some(vehicle: Vehicle) if vehicle.MountedIn.isEmpty =>
- vehicle.PassengerInSeat(player) match {
- case Some(0) =>
- deadState = DeadState.Release // cancel movement updates
- vehicle.Position = position
- LoadZonePhysicalSpawnPoint(continent.id, position, Vector3.z(vehicle.Orientation.z), 0 seconds, None)
- case _ => // not seated as the driver, in which case we can't move
+ vehicle
+ .PassengerInSeat(player)
+ .collect {
+ case 0 => //driver of the vehicle carries the vehicle and its passengers
+ deadState = DeadState.Release //cancel movement updates
+ vehicle.Position = position
+ doorsThatShouldBeClosedOrBeOpenedByRange(
+ player.Position,
+ sessionLogic.localResponse.doorLoadRange(),
+ position,
+ openRange = 100f
+ )
+ LoadZonePhysicalSpawnPoint(continent.id, position, Vector3.z(vehicle.Orientation.z), 0 seconds, None)
}
case None =>
deadState = DeadState.Release // cancel movement updates
+ doorsThatShouldBeClosedOrBeOpenedByRange(
+ player.Position,
+ sessionLogic.localResponse.doorLoadRange(),
+ position,
+ openRange = 100f
+ )
player.Position = position
sendResponse(PlayerStateShiftMessage(ShiftState(0, position, player.Orientation.z, None)))
deadState = DeadState.Alive // must be set here
@@ -3105,6 +3118,7 @@ class ZoningOperations(
}
})
}
+ doorsThatShouldBeOpenInRange(pos, range = 100f)
setAvatar = true
player.allowInteraction = true
upstreamMessageCount = 0
@@ -3622,6 +3636,32 @@ class ZoningOperations(
}
}
+ def doorsThatShouldBeClosedOrBeOpenedByRange(
+ closedPosition: Vector3,
+ closedRange: Float,
+ openPosition: Vector3,
+ openRange: Float
+ ): Unit = {
+ continent
+ .blockMap
+ .sector(closedPosition, closedRange)
+ .amenityList
+ .collect { case door: Door if door.isOpen =>
+ sendResponse(GenericObjectStateMsg(door.GUID, state=17))
+ }
+ doorsThatShouldBeOpenInRange(openPosition, openRange)
+ }
+
+ def doorsThatShouldBeOpenInRange(position: Vector3, range: Float): Unit = {
+ continent
+ .blockMap
+ .sector(position.xy, range)
+ .amenityList
+ .collect { case door: Door if door.isOpen =>
+ sendResponse(GenericObjectStateMsg(door.GUID, state=16))
+ }
+ }
+
override protected[session] def stop(): Unit = {
zoningTimer.cancel()
spawn.respawnTimer.cancel()
diff --git a/src/main/scala/net/psforever/objects/Deployables.scala b/src/main/scala/net/psforever/objects/Deployables.scala
index 826b38761..c75057197 100644
--- a/src/main/scala/net/psforever/objects/Deployables.scala
+++ b/src/main/scala/net/psforever/objects/Deployables.scala
@@ -6,6 +6,7 @@ import net.psforever.objects.avatar.{Avatar, Certification}
import scala.concurrent.duration._
import net.psforever.objects.ce.{Deployable, DeployedItem}
+import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
import net.psforever.objects.zones.Zone
import net.psforever.packet.game._
import net.psforever.types.PlanetSideGUID
@@ -261,4 +262,48 @@ object Deployables {
}
(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) }
+ }
+ }
}
diff --git a/src/main/scala/net/psforever/objects/MineDeployableControl.scala b/src/main/scala/net/psforever/objects/MineDeployableControl.scala
index 3b393378a..0a1e46461 100644
--- a/src/main/scala/net/psforever/objects/MineDeployableControl.scala
+++ b/src/main/scala/net/psforever/objects/MineDeployableControl.scala
@@ -5,7 +5,7 @@ import akka.actor.{ActorContext, ActorRef, Props}
import net.psforever.objects.ce.{Deployable, DeployedItem}
import net.psforever.objects.serverobject.PlanetSideServerObject
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.etc.TrippedMineReason
import net.psforever.objects.vital.interaction.DamageInteraction
@@ -98,40 +98,8 @@ object MineDeployableControl {
private case class Triggered()
def trippedMineReason(mine: ExplosiveDeployable): TrippedMineReason = {
- lazy val deployableSource = DeployableSource(mine)
- val zone = mine.Zone
- 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)
+ val deployableSource = DeployableSource(mine)
+ val blame = Deployables.AssignBlameTo(mine.Zone, mine.OwnerName, deployableSource)
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) }
- }
- }
}
diff --git a/src/main/scala/net/psforever/objects/avatar/DeployableToolbox.scala b/src/main/scala/net/psforever/objects/avatar/DeployableToolbox.scala
index 2a6f4d23b..29c310101 100644
--- a/src/main/scala/net/psforever/objects/avatar/DeployableToolbox.scala
+++ b/src/main/scala/net/psforever/objects/avatar/DeployableToolbox.scala
@@ -22,9 +22,9 @@ import scala.collection.mutable
* As deployables are added and removed, and tracked certifications are added and removed,
* these structures are updated to reflect proper 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).
- * 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 {
diff --git a/src/main/scala/net/psforever/objects/ce/Deployable.scala b/src/main/scala/net/psforever/objects/ce/Deployable.scala
index a77989c20..ed2114172 100644
--- a/src/main/scala/net/psforever/objects/ce/Deployable.scala
+++ b/src/main/scala/net/psforever/objects/ce/Deployable.scala
@@ -114,7 +114,7 @@ object Deployable {
DeployedItem.jammer_mine.id -> DeployableIcon.DisruptorMine,
DeployedItem.spitfire_turret.id -> DeployableIcon.SpitfireTurret,
DeployedItem.spitfire_cloaked.id -> DeployableIcon.ShadowTurret,
- DeployedItem.spitfire_aa.id -> DeployableIcon.CerebusTurret,
+ DeployedItem.spitfire_aa.id -> DeployableIcon.cerberusTurret,
DeployedItem.motionalarmsensor.id -> DeployableIcon.MotionAlarmSensor,
DeployedItem.sensor_shield.id -> DeployableIcon.SensorDisruptor,
DeployedItem.tank_traps.id -> DeployableIcon.TRAP,
diff --git a/src/main/scala/net/psforever/objects/ce/DeployedItem.scala b/src/main/scala/net/psforever/objects/ce/DeployedItem.scala
index ff6d5e1e3..c144c2be9 100644
--- a/src/main/scala/net/psforever/objects/ce/DeployedItem.scala
+++ b/src/main/scala/net/psforever/objects/ce/DeployedItem.scala
@@ -10,7 +10,7 @@ object DeployedItem extends Enumeration {
final val jammer_mine = Value(420) //disruptor mine
final val motionalarmsensor = Value(575)
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_turret = Value(826)
final val tank_traps = Value(849) //trap
diff --git a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsImplant.scala b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsImplant.scala
index a64080e17..347c99b90 100644
--- a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsImplant.scala
+++ b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsImplant.scala
@@ -18,6 +18,7 @@ object GlobalDefinitionsImplant {
targeting.Name = "targeting"
targeting.InitializationDuration = 60
+ targeting.Passive = true
audio_amplifier.Name = "audio_amplifier"
audio_amplifier.InitializationDuration = 60
@@ -41,9 +42,11 @@ object GlobalDefinitionsImplant {
range_magnifier.Name = "range_magnifier"
range_magnifier.InitializationDuration = 60
+ range_magnifier.Passive = true
second_wind.Name = "second_wind"
second_wind.InitializationDuration = 180
+ second_wind.Passive = true
silent_run.Name = "silent_run"
silent_run.InitializationDuration = 90
diff --git a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsMiscellaneous.scala b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsMiscellaneous.scala
index 12868e001..41b224adc 100644
--- a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsMiscellaneous.scala
+++ b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsMiscellaneous.scala
@@ -698,6 +698,7 @@ object GlobalDefinitionsMiscellaneous {
spawn_tube_door_coffin.Damageable = true
resource_silo.Name = "resource_silo"
+ resource_silo.UseRadius = 22 //20
resource_silo.Damageable = false
resource_silo.Repairable = false
resource_silo.MaxNtuCapacitor = 1000
diff --git a/src/main/scala/net/psforever/objects/guid/UniqueNumberOps.scala b/src/main/scala/net/psforever/objects/guid/UniqueNumberOps.scala
index 279255dc7..e1a8a8210 100644
--- a/src/main/scala/net/psforever/objects/guid/UniqueNumberOps.scala
+++ b/src/main/scala/net/psforever/objects/guid/UniqueNumberOps.scala
@@ -50,7 +50,7 @@ class UniqueNumberOps(
private val poolActors: Map[String, ActorRef]
) {
/** 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.
@@ -149,25 +149,26 @@ class UniqueNumberOps(
val localPool = pool
val result = ask(pool, NumberPoolActor.GetAnyNumber())(timeout)
- result.onComplete {
- case Success(NumberPoolActor.GiveNumber(number)) =>
- UniqueNumberOps.processRegisterResult(
- localPromise,
- localTarget,
- localUns,
- localPoolName,
- localPool,
- number
- )
- case Success(NumberPoolActor.NoNumber(ex)) =>
- registrationProcessRetry(localPromise, ex, localTarget, localUns, localPools, localPoolName)
- case msg =>
- UniqueNumberOps.log.warn(s"unexpected message during $localTarget's registration process - $msg")
- }
- result.recover {
- case ex: AskTimeoutException =>
- localPromise.failure(new RegisteringException(msg = s"did not register entity $localTarget in time", ex))
- }
+ result
+ .recover {
+ case ex: AskTimeoutException =>
+ localPromise.failure(new RegisteringException(msg = s"did not register entity $localTarget in time", ex))
+ }
+ .onComplete {
+ case Success(NumberPoolActor.GiveNumber(number)) =>
+ UniqueNumberOps.processRegisterResult(
+ localPromise,
+ localTarget,
+ localUns,
+ localPoolName,
+ localPool,
+ number
+ )
+ case Success(NumberPoolActor.NoNumber(ex)) =>
+ registrationProcessRetry(localPromise, ex, localTarget, localUns, localPools, localPoolName)
+ case msg =>
+ UniqueNumberOps.log.warn(s"unexpected message during $localTarget's registration process - $msg")
+ }
case None =>
//do not log
@@ -197,7 +198,7 @@ class UniqueNumberOps(
if (poolName.equals("generic")) {
promise.failure(new RegisteringException(msg = s"did not register entity $obj", exception))
} 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"))
}
}
@@ -302,7 +303,7 @@ class UniqueNumberOps(
object UniqueNumberOps {
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.
@@ -431,7 +432,7 @@ class UniqueNumberSetup(
) extends Actor {
init()
- final def receive: Receive = { case _ => ; }
+ final def receive: Receive = { case _ => () }
def init(): UniqueNumberOps = {
new UniqueNumberOps(hub, poolActorConversionFunc(context, hub))
diff --git a/src/main/scala/net/psforever/objects/serverobject/CommonMessages.scala b/src/main/scala/net/psforever/objects/serverobject/CommonMessages.scala
index 7f19cf8d2..ef1d4679b 100644
--- a/src/main/scala/net/psforever/objects/serverobject/CommonMessages.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/CommonMessages.scala
@@ -10,7 +10,8 @@ object CommonMessages {
final case class Unuse(player: Player, data: Option[Any] = None)
final case class Hack(player: Player, obj: PlanetSideServerObject with Hackable, data: Option[Any] = None)
final case class ClearHack()
-
+ final case class EntityHackState(obj: PlanetSideGameObject with Hackable, hackState: Boolean)
+
/**
* The message that progresses some form of user-driven activity with a certain eventual outcome
* and potential feedback per cycle.
diff --git a/src/main/scala/net/psforever/objects/serverobject/deploy/Interference.scala b/src/main/scala/net/psforever/objects/serverobject/deploy/Interference.scala
index 16ba67795..8b0cae70e 100644
--- a/src/main/scala/net/psforever/objects/serverobject/deploy/Interference.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/deploy/Interference.scala
@@ -77,7 +77,7 @@ object Interference {
val sector = zone.blockMap.sector(position, Interference.MaxRange)
val targets = (sector.deployableList ++ sector.vehicleList.filter(_.DeploymentState >= DriveState.Deploying))
.collect { case target: PlanetSideGameObject with FactionAffinity
- if target.Faction != faction &&
+ if target.Faction == faction &&
(target.Definition.asInstanceOf[ObjectDefinition].interference ne Interference.AllowAll) =>
target
}
diff --git a/src/main/scala/net/psforever/objects/serverobject/hackable/GenericHackables.scala b/src/main/scala/net/psforever/objects/serverobject/hackable/GenericHackables.scala
index ed83e5ce0..a88b1907e 100644
--- a/src/main/scala/net/psforever/objects/serverobject/hackable/GenericHackables.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/hackable/GenericHackables.scala
@@ -31,12 +31,12 @@ object GenericHackables {
turretUpgradeTime
}
/**
- * na
- *
- * @param player the player doing the hacking
- * @param obj the object being hacked
- * @return the percentage amount of progress per tick
- */
+ * na
+ *
+ * @param player the player doing the hacking
+ * @param obj the object being hacked
+ * @return the percentage amount of progress per tick
+ */
def GetHackSpeed(player: Player, obj: PlanetSideServerObject): Float = {
val playerHackLevel = player.avatar.hackingSkillLevel()
val timeToHack = obj match {
@@ -60,23 +60,23 @@ object GenericHackables {
}
/**
- * Evaluate the progress of the user applying a tool to modify some server object.
- * This action is using the remote electronics kit to convert an enemy unit into an allied unit, primarily.
- * The act of transforming allied units of one kind into allied units of another kind (facility turret upgrades)
- * is also governed by this action per tick of progress.
- * @see `HackMessage`
- * @see `HackState`
- * @param progressType 1 - remote electronics kit hack (various ...);
- * 2 - nano dispenser (upgrade canister) turret upgrade
- * @param tplayer the player performing the action
- * @param target the object being affected
- * @param tool_guid the tool being used to affest the object
- * @param progress the current progress value
- * @return `true`, if the next cycle of progress should occur;
- * `false`, otherwise
- */
+ * Evaluate the progress of the user applying a tool to modify some server object.
+ * This action is using the remote electronics kit to convert an enemy unit into an allied unit, primarily.
+ * The act of transforming allied units of one kind into allied units of another kind (facility turret upgrades)
+ * is also governed by this action per tick of progress.
+ * @see `HackMessage`
+ * @see `HackState`
+ * @param progressType 1 - remote electronics kit hack (various ...);
+ * 2 - nano dispenser (upgrade canister) turret upgrade
+ * @param tplayer the player performing the action
+ * @param target the object being affected
+ * @param tool_guid the tool being used to affest the object
+ * @param progress the current progress value
+ * @return `true`, if the next cycle of progress should occur;
+ * `false`, otherwise
+ */
def HackingTickAction(progressType: Int, tplayer: Player, target: PlanetSideServerObject, tool_guid: PlanetSideGUID)(
- progress: Float
+ progress: Float
): Boolean = {
//hack state for progress bar visibility
val vis = if (progress <= 0L) {
@@ -108,37 +108,40 @@ object GenericHackables {
}
/**
- * The process of hacking an object is completed.
- * Pass the message onto the hackable object and onto the local events system.
- * @param target the `Hackable` object that has been hacked
- * @param user the player that is performing this hacking task
- * @param unk na;
- * used by `HackMessage` as `unk5`
- * @see `HackMessage`
- */
+ * The process of hacking an object is completed.
+ * Pass the message onto the hackable object and onto the local events system.
+ * @param target the `Hackable` object that has been hacked
+ * @param user the player that is performing this hacking task
+ * @param unk na;
+ * used by `HackMessage` as `unk5`
+ * @see `HackMessage`
+ */
//TODO add params here depending on which params in HackMessage are important
def FinishHacking(target: PlanetSideServerObject with Hackable, user: Player, unk: Long)(): Unit = {
import akka.pattern.ask
import scala.concurrent.duration._
- log.info(s"${user.Name} hacked a ${target.Definition.Name}")
// Wait for the target actor to set the HackedBy property, otherwise LocalAction.HackTemporarily will not complete properly
import scala.concurrent.ExecutionContext.Implicits.global
val tplayer = user
- ask(target.Actor, CommonMessages.Hack(tplayer, target))(1 second).mapTo[Boolean].onComplete {
- case Success(_) =>
- val zone = target.Zone
- val zoneId = zone.id
- val pguid = tplayer.GUID
- zone.LocalEvents ! LocalServiceMessage(
- zoneId,
- LocalAction.TriggerSound(pguid, target.HackSound, tplayer.Position, 30, 0.49803925f)
- )
- zone.LocalEvents ! LocalServiceMessage(
- zoneId,
- LocalAction
- .HackTemporarily(pguid, zone, target, unk, target.HackEffectDuration(user.avatar.hackingSkillLevel()))
- )
- case Failure(_) => log.warn(s"Hack message failed on target guid: ${target.GUID}")
- }
+ ask(target.Actor, CommonMessages.Hack(tplayer, target))(timeout = 2 second)
+ .mapTo[CommonMessages.EntityHackState]
+ .onComplete {
+ case Success(_) =>
+ val zone = target.Zone
+ val zoneId = zone.id
+ val pguid = tplayer.GUID
+ log.info(s"${user.Name} hacked a ${target.Definition.Name}")
+ zone.LocalEvents ! LocalServiceMessage(
+ zoneId,
+ LocalAction.TriggerSound(pguid, target.HackSound, tplayer.Position, 30, 0.49803925f)
+ )
+ zone.LocalEvents ! LocalServiceMessage(
+ zoneId,
+ LocalAction
+ .HackTemporarily(pguid, zone, target, unk, target.HackEffectDuration(user.avatar.hackingSkillLevel()))
+ )
+ case Failure(_) =>
+ log.warn(s"Hack message failed on target: ${target.Definition.Name}@${target.GUID.guid}")
+ }
}
}
diff --git a/src/main/scala/net/psforever/objects/serverobject/hackable/HackableBehavior.scala b/src/main/scala/net/psforever/objects/serverobject/hackable/HackableBehavior.scala
index 39fd599cc..d3d1243e1 100644
--- a/src/main/scala/net/psforever/objects/serverobject/hackable/HackableBehavior.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/hackable/HackableBehavior.scala
@@ -1,29 +1,44 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.hackable
-import akka.actor.Actor
+import akka.actor.{Actor, ActorRef}
+import net.psforever.objects.{PlanetSideGameObject, Player}
import net.psforever.objects.serverobject.CommonMessages
+import scala.annotation.unused
+
object HackableBehavior {
/**
- * The logic governing generic `Hackable` objects that use the `Hack` and `ClearHack` message.
- * This is a mix-in trait for combining with existing `Receive` logic.
- * @see `Hackable`
- */
+ * The logic governing generic `Hackable` objects that use the `Hack` and `ClearHack` message.
+ * This is a mix-in trait for combining with existing `Receive` logic.
+ * @see `Hackable`
+ */
trait GenericHackable {
this: Actor =>
- def HackableObject: Hackable
-
- val hackableBehavior: Receive = {
- case CommonMessages.Hack(player, _, _) =>
- val obj = HackableObject
- obj.HackedBy = player
- sender() ! true
+ def HackableObject: PlanetSideGameObject with Hackable
+ val clearHackBehavior: Receive = {
case CommonMessages.ClearHack() =>
- val obj = HackableObject
- obj.HackedBy = None
+ performClearHack(None, sender())
+ }
+
+ val hackableBehavior: Receive = clearHackBehavior
+ .orElse {
+ case CommonMessages.Hack(player, _, _) =>
+ performHack(player, None, sender())
+ }
+
+ def performHack(player: Player, @unused data: Option[Any], replyTo: ActorRef): Unit = {
+ val obj = HackableObject
+ obj.HackedBy = player
+ replyTo ! CommonMessages.EntityHackState(obj, hackState = true)
+ }
+
+ def performClearHack(@unused data: Option[Any], replyTo: ActorRef): Unit = {
+ val obj = HackableObject
+ obj.HackedBy = None
+ replyTo ! CommonMessages.EntityHackState(obj, hackState = false)
}
}
}
diff --git a/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala b/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala
index 0f8eceb58..a892e21b0 100644
--- a/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/resourcesilo/ResourceSiloControl.scala
@@ -1,7 +1,7 @@
// Copyright (c) 2019 PSForever
package net.psforever.objects.serverobject.resourcesilo
-import akka.actor.{Actor, ActorRef}
+import akka.actor.{Actor, ActorRef, Cancellable}
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.actors.zone.BuildingActor
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
@@ -53,37 +53,31 @@ class ResourceSiloControl(resourceSilo: ResourceSilo)
checkBehavior
.orElse(storageBehavior)
.orElse {
- case CommonMessages.Use(player, _) =>
+ case CommonMessages.Use(_, Some(vehicle: Vehicle))
+ if GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition) =>
val siloFaction = resourceSilo.Faction
- val playerFaction = player.Faction
- resourceSilo.Zone.Vehicles.find(v => v.PassengerInSeat(player).contains(0)) match {
- case Some(vehicle) =>
- (if (GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition)) {
- //bfr's discharge into friendly silos and charge from enemy and neutral silos
- if (siloFaction == playerFaction) {
- Some(TransferBehavior.Discharging(Ntu.Nanites))
- } else if (resourceSilo.MaxNtuCapacitor * 0.4f < resourceSilo.NtuCapacitor) {
- //the bfr never drains below 40%
- Some(TransferBehavior.Charging(Ntu.Nanites))
- } else {
- None
- }
- } else if(siloFaction == PlanetSideEmpire.NEUTRAL || siloFaction == playerFaction) {
- //ants discharge into neutral and friendly silos
- Some(TransferBehavior.Discharging(Ntu.Nanites))
- } else {
- None
- }) match {
- case Some(msg) =>
- context.system.scheduler.scheduleOnce(
- delay = 1000 milliseconds,
- vehicle.Actor,
- msg
- )
- case None => ;
- }
- case _ => ;
+ val vehicleFaction = vehicle.Faction
+ val msgOpt = if (siloFaction == vehicleFaction) {
+ Some(TransferBehavior.Discharging(Ntu.Nanites))
+ } else if (resourceSilo.MaxNtuCapacitor * 0.4f < resourceSilo.NtuCapacitor) {
+ //the bfr never drains below 40%
+ Some(TransferBehavior.Charging(Ntu.Nanites))
+ } else {
+ None
}
+ msgOpt.collect { SendNtuMessage(vehicle.Actor, _) }
+
+ case CommonMessages.Use(_, Some(vehicle: Vehicle))
+ if vehicle.Definition == GlobalDefinitions.ant =>
+ val siloFaction = resourceSilo.Faction
+ val vehicleFaction = vehicle.Faction
+ val msgOpt = if (siloFaction == PlanetSideEmpire.NEUTRAL || siloFaction == vehicleFaction) {
+ //ants discharge into neutral and friendly silos
+ Some(TransferBehavior.Discharging(Ntu.Nanites))
+ } else {
+ None
+ }
+ msgOpt.collect { SendNtuMessage(vehicle.Actor, _) }
case ResourceSilo.LowNtuWarning(enabled: Boolean) =>
LowNtuWarning(enabled)
@@ -91,9 +85,13 @@ class ResourceSiloControl(resourceSilo: ResourceSilo)
case ResourceSilo.UpdateChargeLevel(amount: Float) =>
UpdateChargeLevel(amount)
- case _ => ;
+ case _ => ()
}
+ def SendNtuMessage(replyTo: ActorRef, msg: Any): Cancellable = {
+ context.system.scheduler.scheduleOnce(delay = 1000 milliseconds, replyTo, msg)
+ }
+
def LowNtuWarning(enabled: Boolean): Unit = {
resourceSilo.LowNtuWarningOn = enabled
log.trace(s"LowNtuWarning: Silo ${resourceSilo.GUID} low ntu warning set to $enabled")
@@ -147,6 +145,7 @@ class ResourceSiloControl(resourceSilo: ResourceSilo)
* The silo will agree to offers until its nanite capacitor is completely full.
*/
def HandleNtuOffer(sender: ActorRef, src: NtuContainer): Unit = {
+ //todo if I want to test conditions towards continuing ntu transfers, do those here
sender ! (if (resourceSilo.NtuCapacitor < resourceSilo.MaxNtuCapacitor) {
Ntu.Request(0, resourceSilo.MaxNtuCapacitor - resourceSilo.NtuCapacitor)
} else {
diff --git a/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala b/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala
index 02191e393..adea8ef27 100644
--- a/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala
@@ -5,6 +5,7 @@ import akka.actor.{ActorRef, Cancellable}
import net.psforever.objects.sourcing.AmenitySource
import org.log4s.Logger
+import scala.annotation.unused
import scala.collection.mutable
import scala.concurrent.duration._
//
@@ -121,6 +122,7 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
}
def unpoweredStateLogic : Receive = commonBehavior
+ .orElse(clearHackBehavior)
.orElse {
case CommonMessages.Use(_, _) =>
log.warn(s"unexpected format for CommonMessages.Use in this context")
@@ -145,7 +147,7 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
isPowered && super.tryAutoRepair()
}
- def Use(target: PlanetSideGameObject, zone: String, callback: ActorRef): Unit = {
+ def Use(target: PlanetSideGameObject, @unused zone: String, callback: ActorRef): Unit = {
val hadNoUsers = term.NumberUsers == 0
if (term.AddUser(target)) {
log.trace(s"ProximityTerminal.Use: unit ${term.Definition.Name}@${term.GUID.guid} will act on $target")
@@ -169,7 +171,7 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
}
}
- def Unuse(target: PlanetSideGameObject, zone: String): Unit = {
+ def Unuse(target: PlanetSideGameObject, @unused zone: String): Unit = {
val whereTarget = term.Targets.indexWhere(_ eq target)
val previousUsers = term.NumberUsers
val hadUsers = previousUsers > 0
@@ -223,7 +225,7 @@ object ProximityTerminalControl {
* @param target the object being affected by the unit
*/
def selectAndTryProximityUnitBehavior(
- callback: ActorRef,
+ @unused callback: ActorRef,
terminal: Terminal with ProximityUnit,
target: PlanetSideGameObject
): Boolean = {
diff --git a/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalControl.scala b/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalControl.scala
index a020e8426..46f596aa8 100644
--- a/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalControl.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalControl.scala
@@ -19,24 +19,24 @@ import net.psforever.services.local.{LocalAction, LocalServiceMessage}
* @param term the `Terminal` object being governed
*/
class TerminalControl(term: Terminal)
- extends PoweredAmenityControl
+ extends PoweredAmenityControl
with FactionAffinityBehavior.Check
with HackableBehavior.GenericHackable
with DamageableAmenity
with RepairableAmenity
with AmenityAutoRepair {
- def FactionObject = term
- def HackableObject = term
- def DamageableObject = term
- def RepairableObject = term
- def AutoRepairObject = term
+ def FactionObject: Terminal = term
+ def HackableObject: Terminal = term
+ def DamageableObject: Terminal = term
+ def RepairableObject: Terminal = term
+ def AutoRepairObject: Terminal = term
val commonBehavior: Receive = checkBehavior
.orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser)
.orElse(autoRepairBehavior)
- def poweredStateLogic : Receive =
+ def poweredStateLogic: Receive =
commonBehavior
.orElse(hackableBehavior)
.orElse {
@@ -53,18 +53,19 @@ class TerminalControl(term: Terminal)
GenericHackables.FinishHacking(term, player, 3212836864L),
GenericHackables.HackingTickAction(progressType = 1, player, term, item.GUID)
)
- case _ => ;
+ case _ => ()
}
- case _ => ;
+ case _ => ()
}
def unpoweredStateLogic : Receive = commonBehavior
+ .orElse(clearHackBehavior)
.orElse {
case Terminal.Request(player, msg) =>
sender() ! Terminal.TerminalMessage(player, msg, Terminal.NoDeal())
- case _ => ;
+ case _ => ()
}
override protected def DamageAwareness(target: Target, cause: DamageResult, amount: Any) : Unit = {
diff --git a/src/main/scala/net/psforever/objects/serverobject/terminals/capture/CaptureTerminals.scala b/src/main/scala/net/psforever/objects/serverobject/terminals/capture/CaptureTerminals.scala
index 0ed0f7161..7144d4803 100644
--- a/src/main/scala/net/psforever/objects/serverobject/terminals/capture/CaptureTerminals.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/terminals/capture/CaptureTerminals.scala
@@ -1,6 +1,5 @@
package net.psforever.objects.serverobject.terminals.capture
-import akka.util.Timeout
import net.psforever.objects.Player
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.sourcing.PlayerSource
@@ -10,17 +9,16 @@ import scala.util.{Failure, Success}
object CaptureTerminals {import scala.concurrent.duration._
private val log = org.log4s.getLogger("CaptureTerminals")
- private implicit val timeout: Timeout = 1.second
/**
- * The process of hacking an object is completed.
- * Pass the message onto the hackable object and onto the local events system.
- * @param target the `Hackable` object that has been hacked
- * @param hackingPlayer The player that hacked the control console
- * @param unk na;
- * used by `HackMessage` as `unk5`
- * @see `HackMessage`
- */
+ * The process of hacking an object is completed.
+ * Pass the message onto the hackable object and onto the local events system.
+ * @param target the `Hackable` object that has been hacked
+ * @param hackingPlayer The player that hacked the control console
+ * @param unk na;
+ * used by `HackMessage` as `unk5`
+ * @see `HackMessage`
+ */
//TODO add params here depending on which params in HackMessage are important
def FinishHackingCaptureConsole(target: CaptureTerminal, hackingPlayer: Player, unk: Long)(): Unit = {
import akka.pattern.ask
@@ -28,31 +26,33 @@ object CaptureTerminals {import scala.concurrent.duration._
log.info(s"${hackingPlayer.toString} hacked a ${target.Definition.Name}")
// Wait for the target actor to set the HackedBy property
import scala.concurrent.ExecutionContext.Implicits.global
- ask(target.Actor, CommonMessages.Hack(hackingPlayer, target)).mapTo[Boolean].onComplete {
- case Success(_) =>
- val zone = target.Zone
- val zoneid = zone.id
- val events = zone.LocalEvents
- val isResecured = hackingPlayer.Faction == target.Faction
- events ! LocalServiceMessage(
- zoneid,
- LocalAction.TriggerSound(hackingPlayer.GUID, target.HackSound, hackingPlayer.Position, 30, 0.49803925f)
- )
- if (isResecured) {
- // Resecure the CC
+ ask(target.Actor, CommonMessages.Hack(hackingPlayer, target))(timeout = 2 second)
+ .mapTo[CommonMessages.EntityHackState]
+ .onComplete {
+ case Success(_) =>
+ val zone = target.Zone
+ val zoneid = zone.id
+ val events = zone.LocalEvents
+ val isResecured = hackingPlayer.Faction == target.Faction
events ! LocalServiceMessage(
zoneid,
- LocalAction.ResecureCaptureTerminal(target, PlayerSource(hackingPlayer))
+ LocalAction.TriggerSound(hackingPlayer.GUID, target.HackSound, hackingPlayer.Position, 30, 0.49803925f)
)
- } else {
- // Start the CC hack timer
- events ! LocalServiceMessage(
- zoneid,
- LocalAction.StartCaptureTerminalHack(target)
- )
- }
- case Failure(_) =>
- log.warn(s"Hack message failed on target guid: ${target.GUID}")
- }
+ if (isResecured) {
+ // Resecure the CC
+ events ! LocalServiceMessage(
+ zoneid,
+ LocalAction.ResecureCaptureTerminal(target, PlayerSource(hackingPlayer))
+ )
+ } else {
+ // Start the CC hack timer
+ events ! LocalServiceMessage(
+ zoneid,
+ LocalAction.StartCaptureTerminalHack(target)
+ )
+ }
+ case Failure(_) =>
+ log.warn(s"Hack message failed on target guid: ${target.GUID}")
+ }
}
}
diff --git a/src/main/scala/net/psforever/objects/serverobject/terminals/implant/ImplantTerminalMechControl.scala b/src/main/scala/net/psforever/objects/serverobject/terminals/implant/ImplantTerminalMechControl.scala
index 839c82d8a..f4f53b662 100644
--- a/src/main/scala/net/psforever/objects/serverobject/terminals/implant/ImplantTerminalMechControl.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/terminals/implant/ImplantTerminalMechControl.scala
@@ -125,7 +125,7 @@ class ImplantTerminalMechControl(mech: ImplantTerminalMech)
seat.unmount(player)
player.VehicleSeated = None
if (player.HasGUID) {
- events ! VehicleServiceMessage(zoneId, VehicleAction.KickPassenger(player.GUID, 4, false, guid))
+ events ! VehicleServiceMessage(zoneId, VehicleAction.KickPassenger(player.GUID, 4, unk2 = false, guid))
}
case None => ;
}
diff --git a/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala b/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala
index e0dec604c..09e0973f1 100644
--- a/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala
@@ -104,9 +104,14 @@ class FacilityTurretControl(turret: FacilityTurret)
}
override protected def tryMount(obj: PlanetSideServerObject with Mountable, seatNumber: Int, player: Player): Boolean = {
+ val originalAutoState = AutomaticOperation
AutomaticOperation = false //turn off
+ if (AutomaticOperationPossible && JammableObject.Jammed) {
+ val zone = TurretObject.Zone
+ AutomatedTurretBehavior.stopTracking(zone, zone.id, TurretObject.GUID) //can not recover lost jamming aggro
+ }
if (!super.tryMount(obj, seatNumber, player)) {
- AutomaticOperation = true //revert?
+ AutomaticOperation = originalAutoState //revert
false
} else {
true
@@ -215,6 +220,15 @@ class FacilityTurretControl(turret: FacilityTurret)
!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 = {
if (testToResetToDefaultFireMode) {
val zone = TurretObject.Zone
@@ -289,16 +303,15 @@ class FacilityTurretControl(turret: FacilityTurret)
}
override def TryJammerEffectActivate(target: Any, cause: DamageResult): Unit = {
- val startsUnjammed = !JammableObject.Jammed
super.TryJammerEffectActivate(target, cause)
- if (JammableObject.Jammed && AutomatedTurretObject.Definition.AutoFire.exists(_.retaliatoryDelay > 0)) {
- if (startsUnjammed) {
- AutomaticOperation = false
- }
- //look in direction of cause of jamming
- val zone = JammableObject.Zone
- AutomatedTurretBehavior.getAttackVectorFromCause(zone, cause).foreach { attacker =>
- AutomatedTurretBehavior.startTracking(zone, zone.id, JammableObject.GUID, List(attacker.GUID))
+ if (AutomaticOperationPossible && AutomaticOperation && JammableObject.Jammed) {
+ AutomaticOperation = false
+ if (!MountableObject.Seats.values.exists(_.isOccupied) && AutomatedTurretObject.Definition.AutoFire.exists(_.retaliatoryDelay > 0)) {
+ //look in direction of cause of jamming
+ val zone = JammableObject.Zone
+ AutomatedTurretBehavior.getAttackVectorFromCause(zone, cause).foreach { attacker =>
+ AutomatedTurretBehavior.startTracking(zone, zone.id, JammableObject.GUID, List(attacker.GUID))
+ }
}
}
}
diff --git a/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala b/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala
index 1c2f64354..fad4c5c34 100644
--- a/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala
+++ b/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala
@@ -80,6 +80,8 @@ trait AutomatedTurretBehavior {
Actor.emptyBehavior
}
+ def AutomaticOperationPossible: Boolean = autoStats.isDefined
+
def AutomaticOperation: Boolean = automaticOperation
/**
@@ -111,7 +113,7 @@ trait AutomatedTurretBehavior {
* @return `true`, if it would be possible for automated behavior to become operational;
* `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.
diff --git a/src/main/scala/net/psforever/objects/zones/Zone.scala b/src/main/scala/net/psforever/objects/zones/Zone.scala
index c8ef2e808..07c9ed581 100644
--- a/src/main/scala/net/psforever/objects/zones/Zone.scala
+++ b/src/main/scala/net/psforever/objects/zones/Zone.scala
@@ -288,7 +288,7 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
* @return synchronized reference to the globally unique identifier system
*/
def GUID(hub: NumberPoolHub): Boolean = {
- if (actor == null && guid.Pools.values.foldLeft(0)(_ + _.Count) == 0) {
+ if (actor == Default.typed.Actor && guid.Pools.values.foldLeft(0)(_ + _.Count) == 0) {
import org.fusesource.jansi.Ansi.Color.RED
import org.fusesource.jansi.Ansi.ansi
println(
diff --git a/src/main/scala/net/psforever/packet/game/DeployableObjectsInfoMessage.scala b/src/main/scala/net/psforever/packet/game/DeployableObjectsInfoMessage.scala
index 4c03ec112..916c8b0a3 100644
--- a/src/main/scala/net/psforever/packet/game/DeployableObjectsInfoMessage.scala
+++ b/src/main/scala/net/psforever/packet/game/DeployableObjectsInfoMessage.scala
@@ -26,7 +26,7 @@ object DeploymentAction extends Enumeration {
object DeployableIcon extends Enumeration {
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
implicit val codec: Codec[DeployableIcon.Value] = PacketHelpers.createEnumerationCodec(this, uint4L)
diff --git a/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala b/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
index d62590404..a6fb90707 100644
--- a/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
+++ b/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
@@ -32,7 +32,7 @@ import scodec.codecs._
* `86 - max spitfire turrets`
* `87 - max motion sensors`
* `88 - max shadow turrets`
- * `89 - max cerebus turrets`
+ * `89 - max cerberus turrets`
* `90 - max Aegis shield generators`
* `91 - max TRAPs`
* `92 - max OMFTs`
@@ -43,7 +43,7 @@ import scodec.codecs._
* `97 - spitfire turrets`
* `98 - motion sensors`
* `99 - shadow turrets`
- * `100 - cerebus turrets`
+ * `100 - cerberus turrets`
* `101 - Aegis shield generators`
* `102 - TRAPSs`
* `103 - OMFTs`
diff --git a/src/test/scala/base/ActorTest.scala b/src/test/scala/base/ActorTest.scala
index 2cbbaca0b..6249c31ff 100644
--- a/src/test/scala/base/ActorTest.scala
+++ b/src/test/scala/base/ActorTest.scala
@@ -4,6 +4,7 @@ package base
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.testkit.{ImplicitSender, TestKit}
import com.typesafe.config.ConfigFactory
+import net.psforever.objects.Default
import org.scalatest.BeforeAndAfterAll
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
@@ -19,6 +20,7 @@ abstract class ActorTest(sys: ActorSystem = ActorSystem("system", ConfigFactory.
with AnyWordSpecLike
with Matchers
with BeforeAndAfterAll {
+ Default(sys)
override def afterAll(): Unit = {
TestKit.shutdownActorSystem(system)
}
diff --git a/src/test/scala/objects/DamageableTest.scala b/src/test/scala/objects/DamageableTest.scala
index 457dd4bb4..bd2381fb9 100644
--- a/src/test/scala/objects/DamageableTest.scala
+++ b/src/test/scala/objects/DamageableTest.scala
@@ -775,7 +775,7 @@ class DamageableWeaponTurretDamageTest extends ActorTest {
zone.AvatarEvents = avatarProbe.ref
zone.VehicleEvents = vehicleProbe.ref
val turret = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) //2
- turret.Actor = system.actorOf(Props(classOf[TurretDeployableControl], turret), "turret-control")
+ turret.Actor = system.actorOf(Props(classOf[FieldTurretControl], turret), "turret-control")
turret.Zone = zone
turret.Position = Vector3(1, 0, 0)
turret.LogActivity(SpawningActivity(SourceEntry(turret), zone.Number, None)) //seed a spawn event
@@ -873,7 +873,7 @@ class DamageableWeaponTurretJammerTest extends ActorTest {
zone.VehicleEvents = vehicleProbe.ref
val turret = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) //2, 5, 6
- turret.Actor = system.actorOf(Props(classOf[TurretDeployableControl], turret), "turret-control")
+ turret.Actor = system.actorOf(Props(classOf[FieldTurretControl], turret), "turret-control")
turret.Zone = zone
turret.Position = Vector3(1, 0, 0)
val turretWeapon: Tool = turret.Weapons.values.head.Equipment.get.asInstanceOf[Tool]
diff --git a/src/test/scala/objects/DefaultTest.scala b/src/test/scala/objects/DefaultTest.scala
index 329efc410..cbf5ca7a5 100644
--- a/src/test/scala/objects/DefaultTest.scala
+++ b/src/test/scala/objects/DefaultTest.scala
@@ -25,18 +25,17 @@ class DefaultActorStartedTest extends ActorTest {
"Default.Actor" should {
"send messages to deadLetters" in {
//after being started
- Default(system)
val probe = new TestProbe(system)
system.eventStream.subscribe(probe.ref, classOf[DeadLetter])
Default.Actor ! "hello world"
- val msg1 = probe.receiveOne(250 milliseconds)
+ val msg1 = probe.receiveOne(5000 milliseconds)
assert(msg1.isInstanceOf[DeadLetter])
assert(msg1.asInstanceOf[DeadLetter].message equals "hello world")
//if it was stopped
system.stop(Default.Actor)
Default.Actor ! "hello world"
- val msg2 = probe.receiveOne(250 milliseconds)
+ val msg2 = probe.receiveOne(5000 milliseconds)
assert(msg2.isInstanceOf[DeadLetter])
assert(msg2.asInstanceOf[DeadLetter].message equals "hello world")
}
diff --git a/src/test/scala/objects/DeployableTest.scala b/src/test/scala/objects/DeployableTest.scala
index 26dac7579..1708ff74a 100644
--- a/src/test/scala/objects/DeployableTest.scala
+++ b/src/test/scala/objects/DeployableTest.scala
@@ -138,14 +138,14 @@ class TurretDeployableTest extends Specification {
DeployedItem.portable_manned_turret_nc.id,
DeployedItem.portable_manned_turret_vs.id
).foreach(id => {
- try { new TurretDeployableDefinition(id) }
+ try { new TurretDeployableDefinition(id) { } }
catch { case _: Exception => ko }
})
ok
}
"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 {
@@ -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)
func() match {
case obj: TurretDeployable if obj.Definition == GlobalDefinitions.spitfire_aa => ok
@@ -584,7 +584,7 @@ class TurretControlConstructTest extends ActorTest {
"TurretControl" should {
"construct" in {
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
- system.actorOf(Props(classOf[TurretDeployableControl], obj), s"${obj.Definition.Name}_test")
+ system.actorOf(Props(classOf[SmallTurretControl], obj), s"${obj.Definition.Name}_test")
}
}
}
@@ -629,7 +629,7 @@ class TurretControlMountTest extends ActorTest {
override def SetupNumberPools() = {}
this.actor = new TestProbe(system).ref.toTyped[ZoneActor.Command]
}
- obj.Actor = system.actorOf(Props(classOf[TurretDeployableControl], obj), s"${obj.Definition.Name}_test")
+ obj.Actor = system.actorOf(Props(classOf[FieldTurretControl], obj), s"${obj.Definition.Name}_test")
assert(obj.Seats(0).occupant.isEmpty)
val player1 = Player(Avatar(0, "test1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute))
@@ -649,7 +649,7 @@ class TurretControlBlockMountTest extends ActorTest {
"block mounting by others if already mounted by someone" in {
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
obj.Faction = PlanetSideEmpire.TR
- obj.Actor = system.actorOf(Props(classOf[TurretDeployableControl], obj), s"${obj.Definition.Name}_test")
+ obj.Actor = system.actorOf(Props(classOf[FieldTurretControl], obj), s"${obj.Definition.Name}_test")
obj.Zone = new Zone("test", new ZoneMap("test"), 0) {
override def SetupNumberPools() = {}
this.actor = new TestProbe(system).ref.toTyped[ZoneActor.Command]
@@ -681,7 +681,7 @@ class TurretControlBlockBetrayalMountTest extends ActorTest {
"block mounting by players of another faction" in {
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
obj.Faction = PlanetSideEmpire.TR
- obj.Actor = system.actorOf(Props(classOf[TurretDeployableControl], obj), s"${obj.Definition.Name}_test")
+ obj.Actor = system.actorOf(Props(classOf[FieldTurretControl], obj), s"${obj.Definition.Name}_test")
assert(obj.Seats(0).occupant.isEmpty)
val player = Player(Avatar(0, "test", PlanetSideEmpire.VS, CharacterSex.Male, 0, CharacterVoice.Mute))
@@ -705,7 +705,7 @@ class TurretControlDismountTest extends ActorTest {
override def SetupNumberPools() = {}
this.actor = new TestProbe(system).ref.toTyped[ZoneActor.Command]
}
- obj.Actor = system.actorOf(Props(classOf[TurretDeployableControl], obj), s"${obj.Definition.Name}_test")
+ obj.Actor = system.actorOf(Props(classOf[FieldTurretControl], obj), s"${obj.Definition.Name}_test")
assert(obj.Seats(0).occupant.isEmpty)
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute))
@@ -746,7 +746,7 @@ class TurretControlBetrayalMountTest extends ActorTest {
}
}
obj.Faction = PlanetSideEmpire.TR
- obj.Actor = system.actorOf(Props(classOf[TurretDeployableControl], obj), s"${obj.Definition.Name}_test")
+ obj.Actor = system.actorOf(Props(classOf[FieldTurretControl], obj), s"${obj.Definition.Name}_test")
val probe = new TestProbe(system)
assert(obj.Seats(0).occupant.isEmpty)
diff --git a/src/test/scala/objects/DeployableToolboxTest.scala b/src/test/scala/objects/DeployableToolboxTest.scala
index e608812ad..a524e909d 100644
--- a/src/test/scala/objects/DeployableToolboxTest.scala
+++ b/src/test/scala/objects/DeployableToolboxTest.scala
@@ -819,13 +819,13 @@ class DeployableToolboxTest extends Specification {
val obj = new DeployableToolbox
obj.Initialize(Set(CombatEngineering))
- val cerebus = new TurretDeployable(GlobalDefinitions.spitfire_aa) //cerebus turret
- obj.Valid(cerebus) mustEqual false
+ val cerberus = new TurretDeployable(GlobalDefinitions.spitfire_aa) //cerberus turret
+ obj.Valid(cerberus) mustEqual false
obj.CountDeployable(DeployedItem.spitfire_aa).productIterator.toList mustEqual List(0, 0)
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)
}
diff --git a/src/test/scala/objects/PlayerControlTest.scala b/src/test/scala/objects/PlayerControlTest.scala
index d10e7a85b..aad7d21ca 100644
--- a/src/test/scala/objects/PlayerControlTest.scala
+++ b/src/test/scala/objects/PlayerControlTest.scala
@@ -774,124 +774,124 @@ class PlayerControlDeathStandingTest extends ActorTest {
// }
//}
-class PlayerControlInteractWithWaterTest extends ActorTest {
- val player1: Player =
- Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)) //guid=1
- val avatarProbe: TestProbe = TestProbe()
- val guid = new NumberPoolHub(new MaxNumberSource(15))
- val pool: Pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
- val zone: Zone = new Zone(
- id = "test",
- new ZoneMap(name = "test-map") {
- environment = List(pool)
- },
- zoneNumber = 0
- ) {
- override def SetupNumberPools(): Unit = {}
- GUID(guid)
- override def LivePlayers: List[Player] = List(player1)
- override def AvatarEvents: ClassicActorRef = avatarProbe.ref
- }
- zone.blockMap.addTo(player1)
- zone.blockMap.addTo(pool)
+//class PlayerControlInteractWithWaterTest extends ActorTest {
+// val player1: Player =
+// Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)) //guid=1
+// val avatarProbe: TestProbe = TestProbe()
+// val guid = new NumberPoolHub(new MaxNumberSource(15))
+// val pool: Pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
+// val zone: Zone = new Zone(
+// id = "test",
+// new ZoneMap(name = "test-map") {
+// environment = List(pool)
+// },
+// zoneNumber = 0
+// ) {
+// override def SetupNumberPools(): Unit = {}
+// GUID(guid)
+// override def LivePlayers: List[Player] = List(player1)
+// override def AvatarEvents: ClassicActorRef = avatarProbe.ref
+// }
+// zone.blockMap.addTo(player1)
+// zone.blockMap.addTo(pool)
+//
+// player1.Zone = zone
+// player1.Spawn()
+// guid.register(player1.avatar.locker, 5)
+// val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
+// player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
+//
+// guid.register(player1, 1)
+//
+// "PlayerControl" should {
+// "cause drowning when player steps too deep in water" in {
+// assert(player1.Health == 100)
+// player1.Position = Vector3(5,5,-3) //right in the pool
+// player1.zoneInteractions() //trigger
+//
+// val msg_drown = avatarProbe.receiveOne(250 milliseconds)
+// assert(
+// msg_drown match {
+// case AvatarServiceMessage(
+// "TestCharacter1",
+// AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), _, OxygenState.Suffocation, 100f), _)
+// ) => true
+// case _ => false
+// }
+// )
+// //player will die in 60s
+// //detailing these death messages is not necessary
+// assert(player1.Health == 100)
+// probe.receiveOne(65 seconds) //wait until our implants deinitialize
+// assert(player1.Health == 0) //ded
+// }
+// }
+//}
- player1.Zone = zone
- player1.Spawn()
- guid.register(player1.avatar.locker, 5)
- val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
- player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
-
- guid.register(player1, 1)
-
- "PlayerControl" should {
- "cause drowning when player steps too deep in water" in {
- assert(player1.Health == 100)
- player1.Position = Vector3(5,5,-3) //right in the pool
- player1.zoneInteractions() //trigger
-
- val msg_drown = avatarProbe.receiveOne(250 milliseconds)
- assert(
- msg_drown match {
- case AvatarServiceMessage(
- "TestCharacter1",
- AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), _, OxygenState.Suffocation, 100f), _)
- ) => true
- case _ => false
- }
- )
- //player will die in 60s
- //detailing these death messages is not necessary
- assert(player1.Health == 100)
- probe.receiveOne(65 seconds) //wait until our implants deinitialize
- assert(player1.Health == 0) //ded
- }
- }
-}
-
-class PlayerControlStopInteractWithWaterTest extends ActorTest {
- val player1: Player =
- Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)) //guid=1
- val avatarProbe: TestProbe = TestProbe()
- val guid = new NumberPoolHub(new MaxNumberSource(15))
- val pool: Pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
- val zone: Zone = new Zone(
- id = "test",
- new ZoneMap(name = "test-map") {
- environment = List(pool)
- },
- zoneNumber = 0
- ) {
- override def SetupNumberPools(): Unit = {}
- GUID(guid)
- override def LivePlayers: List[Player] = List(player1)
- override def AvatarEvents: ClassicActorRef = avatarProbe.ref
- }
- zone.blockMap.addTo(player1)
- zone.blockMap.addTo(pool)
-
- player1.Zone = zone
- player1.Spawn()
- guid.register(player1.avatar.locker, 5)
- val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
- player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
-
- guid.register(player1, 1)
-
- "PlayerControl" should {
- "stop drowning if player steps out of deep water" in {
- assert(player1.Health == 100)
- player1.Position = Vector3(5,5,-3) //right in the pool
- player1.zoneInteractions() //trigger
-
- val msg_drown = avatarProbe.receiveOne(250 milliseconds)
- assert(
- msg_drown match {
- case AvatarServiceMessage(
- "TestCharacter1",
- AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), _, OxygenState.Suffocation, 100f), _)
- ) => true
- case _ => false
- }
- )
- //player would normally die in 60s
- player1.Position = Vector3.Zero //pool's closed
- player1.zoneInteractions() //trigger
- val msg_recover = avatarProbe.receiveOne(250 milliseconds)
- assert(
- msg_recover match {
- case AvatarServiceMessage(
- "TestCharacter1",
- AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), _, OxygenState.Recovery, _), _)
- ) => true
- case _ => false
- }
- )
- assert(player1.Health == 100) //still alive?
- probe.expectNoMessage(65 seconds)
- assert(player1.Health == 100) //yep, still alive
- }
- }
-}
+//class PlayerControlStopInteractWithWaterTest extends ActorTest {
+// val player1: Player =
+// Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)) //guid=1
+// val avatarProbe: TestProbe = TestProbe()
+// val guid = new NumberPoolHub(new MaxNumberSource(15))
+// val pool: Pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
+// val zone: Zone = new Zone(
+// id = "test",
+// new ZoneMap(name = "test-map") {
+// environment = List(pool)
+// },
+// zoneNumber = 0
+// ) {
+// override def SetupNumberPools(): Unit = {}
+// GUID(guid)
+// override def LivePlayers: List[Player] = List(player1)
+// override def AvatarEvents: ClassicActorRef = avatarProbe.ref
+// }
+// zone.blockMap.addTo(player1)
+// zone.blockMap.addTo(pool)
+//
+// player1.Zone = zone
+// player1.Spawn()
+// guid.register(player1.avatar.locker, 5)
+// val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
+// player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
+//
+// guid.register(player1, 1)
+//
+// "PlayerControl" should {
+// "stop drowning if player steps out of deep water" in {
+// assert(player1.Health == 100)
+// player1.Position = Vector3(5,5,-3) //right in the pool
+// player1.zoneInteractions() //trigger
+//
+// val msg_drown = avatarProbe.receiveOne(250 milliseconds)
+// assert(
+// msg_drown match {
+// case AvatarServiceMessage(
+// "TestCharacter1",
+// AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), _, OxygenState.Suffocation, 100f), _)
+// ) => true
+// case _ => false
+// }
+// )
+// //player would normally die in 60s
+// player1.Position = Vector3.Zero //pool's closed
+// player1.zoneInteractions() //trigger
+// val msg_recover = avatarProbe.receiveOne(250 milliseconds)
+// assert(
+// msg_recover match {
+// case AvatarServiceMessage(
+// "TestCharacter1",
+// AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), _, OxygenState.Recovery, _), _)
+// ) => true
+// case _ => false
+// }
+// )
+// assert(player1.Health == 100) //still alive?
+// probe.expectNoMessage(65 seconds)
+// assert(player1.Health == 100) //yep, still alive
+// }
+// }
+//}
class PlayerControlInteractWithLavaTest extends ActorTest {
val player1: Player =
diff --git a/src/test/scala/objects/ZoneTest.scala b/src/test/scala/objects/ZoneTest.scala
index 6c4f4dfe6..74cd60ddc 100644
--- a/src/test/scala/objects/ZoneTest.scala
+++ b/src/test/scala/objects/ZoneTest.scala
@@ -486,9 +486,13 @@ class ZonePopulationTest extends ActorTest {
class ZoneGroundDropItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new MaxNumberSource(20))
+ val zone = new Zone(
+ "test",
+ new ZoneMap("test-map"), 0) {
+ override def SetupNumberPools() = {}
+ GUID(hub)
+ }
hub.register(item, 10)
- val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
- zone.GUID(hub)
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
expectNoMessage(200 milliseconds)
@@ -511,9 +515,13 @@ class ZoneGroundDropItemTest extends ActorTest {
class ZoneGroundCanNotDropItem1Test extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new MaxNumberSource(20))
+ val zone = new Zone(
+ "test",
+ new ZoneMap("test-map"), 0) {
+ override def SetupNumberPools() = {}
+ GUID(hub)
+ }
//hub.register(item, 10) //!important
- val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
- zone.GUID(hub)
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
expectNoMessage(200 milliseconds)
@@ -536,9 +544,13 @@ class ZoneGroundCanNotDropItem1Test extends ActorTest {
class ZoneGroundCanNotDropItem2Test extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new MaxNumberSource(20))
- hub.register(item, 10) //!important
- val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
- //zone.GUID(hub) //!important
+ val zone = new Zone(
+ "test",
+ new ZoneMap("test-map"), 0) {
+ override def SetupNumberPools() = {}
+ //GUID(hub) !important
+ }
+ hub.register(item, 10)
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
expectNoMessage(200 milliseconds)
@@ -561,9 +573,13 @@ class ZoneGroundCanNotDropItem2Test extends ActorTest {
class ZoneGroundCanNotDropItem3Test extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new MaxNumberSource(20))
- hub.register(item, 10) //!important
- val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
- zone.GUID(hub) //!important
+ val zone = new Zone(
+ "test",
+ new ZoneMap("test-map"), 0) {
+ override def SetupNumberPools() = {}
+ GUID(hub)
+ }
+ hub.register(item, 10)
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
expectNoMessage(200 milliseconds)
@@ -594,9 +610,13 @@ class ZoneGroundCanNotDropItem3Test extends ActorTest {
class ZoneGroundPickupItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new MaxNumberSource(20))
+ val zone = new Zone(
+ "test",
+ new ZoneMap("test-map"), 0) {
+ override def SetupNumberPools() = {}
+ GUID(hub)
+ }
hub.register(item, 10)
- val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
- zone.GUID(hub)
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
expectNoMessage(200 milliseconds)
@@ -622,9 +642,13 @@ class ZoneGroundPickupItemTest extends ActorTest {
class ZoneGroundCanNotPickupItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new MaxNumberSource(20))
+ val zone = new Zone(
+ "test",
+ new ZoneMap("test-map"), 0) {
+ override def SetupNumberPools() = {}
+ GUID(hub)
+ }
hub.register(item, 10)
- val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
- zone.GUID(hub) //still registered to this zone
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
expectNoMessage(200 milliseconds)
@@ -646,9 +670,13 @@ class ZoneGroundCanNotPickupItemTest extends ActorTest {
class ZoneGroundRemoveItemTest extends ActorTest {
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
val hub = new NumberPoolHub(new MaxNumberSource(20))
+ val zone = new Zone(
+ "test",
+ new ZoneMap("test-map"), 0) {
+ override def SetupNumberPools() = {}
+ GUID(hub)
+ }
hub.register(item, 10)
- val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
- zone.GUID(hub) //still registered to this zone
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
expectNoMessage(200 milliseconds)
diff --git a/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala b/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
index 1f9712356..abe84021b 100644
--- a/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
+++ b/src/test/scala/objects/terminal/ImplantTerminalMechTest.scala
@@ -161,31 +161,37 @@ object ImplantTerminalMechTest {
import akka.actor.typed.scaladsl.adapter._
val guid = new NumberPoolHub(new MaxNumberSource(10))
- val map = new ZoneMap("test")
- val zone = new Zone("test", map, 0) {
- override def SetupNumberPools() = {}
- GUID(guid)
- this.actor = new TestProbe(system).ref.toTyped[ZoneActor.Command]
- }
+ val terminal = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech) //guid=1
+ val interface = Terminal(GlobalDefinitions.implant_terminal_interface) //guid=2
val building = new Building(
"Building",
building_guid = 0,
map_id = 0,
- zone,
+ Zone.Nowhere,
StructureType.Building,
GlobalDefinitions.building
) //guid=3
+ val zone = new Zone(
+ "test",
+ new ZoneMap("test") {
+ },
+ 0) {
+ override def SetupNumberPools() = {}
+ GUID(guid)
+ this.actor = new TestProbe(system).ref.toTyped[ZoneActor.Command]
+ }
+ //zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
+ zone.map.linkTerminalToInterface(1, 2)
+ building.Zone = zone
building.Faction = faction
-
- val interface = Terminal(GlobalDefinitions.implant_terminal_interface) //guid=2
- interface.Owner = building
- val terminal = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech) //guid=1
- terminal.Owner = building
+ interface.Zone = zone
+ building.Amenities = interface
+ terminal.Zone = zone
+ building.Amenities = terminal
guid.register(terminal, 1)
guid.register(interface, 2)
guid.register(building, 3)
- map.linkTerminalToInterface(1, 2)
terminal.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], terminal), "terminal-control")
(Player(Avatar(0, "test", faction, CharacterSex.Male, 0, CharacterVoice.Mute)), terminal)