mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
Bug Fixes 20240712 (#1212)
* correctly clear the hack state of terminals when unpowered; turrets will no longer act like they have AI control if jammed when mounted; restore passive implants * reload opened and closed doors upon zoning changes; rework ntu silo and ant interaction start; clear hack on proximity terminals; facility turrets stop indicating towards jamming cause when mounted * 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 * incorporating structural changes to hacking for future expansion * an attempt at fixing tests was made
This commit is contained in:
parent
5990f247c9
commit
d1dbbcb08f
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ import net.psforever.objects.zones.blockmap.BlockMapEntity
|
||||||
import net.psforever.objects.zones.{Zone, ZoneProjectile, Zoning}
|
import net.psforever.objects.zones.{Zone, ZoneProjectile, Zoning}
|
||||||
import net.psforever.packet.PlanetSideGamePacket
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.objectcreate.ObjectClass
|
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.RemoverActor
|
||||||
import net.psforever.services.account.{AccountPersistenceService, RetrieveAccountData}
|
import net.psforever.services.account.{AccountPersistenceService, RetrieveAccountData}
|
||||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
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 = {
|
private def handleUseResourceSilo(resourceSilo: ResourceSilo, equipment: Option[Equipment]): Unit = {
|
||||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_use")
|
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))
|
case (Some(vehicle: Vehicle), Some(item))
|
||||||
if GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition) &&
|
if GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition) &&
|
||||||
GlobalDefinitions.isBattleFrameNTUSiphon(item.Definition) =>
|
GlobalDefinitions.isBattleFrameNTUSiphon(item.Definition) =>
|
||||||
resourceSilo.Actor ! CommonMessages.Use(player, equipment)
|
resourceSilo.Actor ! CommonMessages.Use(player, Some(vehicle))
|
||||||
case _ =>
|
case (Some(vehicle: Vehicle), _)
|
||||||
resourceSilo.Actor ! CommonMessages.Use(player)
|
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 _ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package net.psforever.actors.session.normal
|
||||||
import akka.actor.ActorContext
|
import akka.actor.ActorContext
|
||||||
import net.psforever.actors.session.support.{LocalHandlerFunctions, SessionData, SessionLocalHandlers}
|
import net.psforever.actors.session.support.{LocalHandlerFunctions, SessionData, SessionLocalHandlers}
|
||||||
import net.psforever.objects.ce.Deployable
|
import net.psforever.objects.ce.Deployable
|
||||||
|
import net.psforever.objects.serverobject.doors.Door
|
||||||
import net.psforever.objects.vehicles.MountableWeapons
|
import net.psforever.objects.vehicles.MountableWeapons
|
||||||
import net.psforever.objects.{BoomerDeployable, ExplosiveDeployable, TelepadDeployable, Tool, TurretDeployable}
|
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}
|
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")
|
log.warn(s"LocalResponse.Detonate: ${obj.Definition.Name} not configured to explode correctly")
|
||||||
|
|
||||||
case LocalResponse.DoorOpens(doorGuid) if isNotSameTarget =>
|
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
|
case LocalResponse.DoorCloses(doorGuid) => //door closes for everyone
|
||||||
sendResponse(GenericObjectStateMsg(doorGuid, state=17))
|
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 =>
|
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, _, _) if obj.Active && obj.Destroyed =>
|
||||||
//if active, deactivate
|
//if active, deactivate
|
||||||
obj.Active = false
|
obj.Active = false
|
||||||
sendResponse(GenericObjectActionMessage(dguid, code=29))
|
ops.deactivateTelpadDeployableMessages(dguid)
|
||||||
sendResponse(GenericObjectActionMessage(dguid, code=30))
|
|
||||||
//standard deployable elimination behavior
|
//standard deployable elimination behavior
|
||||||
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||||
|
|
||||||
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, pos, _) if obj.Active =>
|
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, pos, _) if obj.Active =>
|
||||||
//if active, deactivate
|
//if active, deactivate
|
||||||
obj.Active = false
|
obj.Active = false
|
||||||
sendResponse(GenericObjectActionMessage(dguid, code=29))
|
ops.deactivateTelpadDeployableMessages(dguid)
|
||||||
sendResponse(GenericObjectActionMessage(dguid, code=30))
|
|
||||||
//standard deployable elimination behavior
|
//standard deployable elimination behavior
|
||||||
obj.Destroyed = true
|
obj.Destroyed = true
|
||||||
DeconstructDeployable(obj, dguid, pos, obj.Orientation, deletionType=2)
|
DeconstructDeployable(obj, dguid, pos, obj.Orientation, deletionType=2)
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,16 +96,14 @@ class LocalHandlerLogic(val ops: SessionLocalHandlers, implicit val context: Act
|
||||||
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, _, _) if obj.Active && obj.Destroyed =>
|
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, _, _) if obj.Active && obj.Destroyed =>
|
||||||
//if active, deactivate
|
//if active, deactivate
|
||||||
obj.Active = false
|
obj.Active = false
|
||||||
sendResponse(GenericObjectActionMessage(dguid, code=29))
|
ops.deactivateTelpadDeployableMessages(dguid)
|
||||||
sendResponse(GenericObjectActionMessage(dguid, code=30))
|
|
||||||
//standard deployable elimination behavior
|
//standard deployable elimination behavior
|
||||||
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
sendResponse(ObjectDeleteMessage(dguid, unk1=0))
|
||||||
|
|
||||||
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, pos, _) if obj.Active =>
|
case LocalResponse.EliminateDeployable(obj: TelepadDeployable, dguid, pos, _) if obj.Active =>
|
||||||
//if active, deactivate
|
//if active, deactivate
|
||||||
obj.Active = false
|
obj.Active = false
|
||||||
sendResponse(GenericObjectActionMessage(dguid, code=29))
|
ops.deactivateTelpadDeployableMessages(dguid)
|
||||||
sendResponse(GenericObjectActionMessage(dguid, code=30))
|
|
||||||
//standard deployable elimination behavior
|
//standard deployable elimination behavior
|
||||||
obj.Destroyed = true
|
obj.Destroyed = true
|
||||||
DeconstructDeployable(obj, dguid, pos, obj.Orientation, deletionType=2)
|
DeconstructDeployable(obj, dguid, pos, obj.Orientation, deletionType=2)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import akka.actor.ActorContext
|
||||||
import net.psforever.objects.{Players, TurretDeployable}
|
import net.psforever.objects.{Players, TurretDeployable}
|
||||||
import net.psforever.objects.ce.Deployable
|
import net.psforever.objects.ce.Deployable
|
||||||
import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
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.services.local.LocalResponse
|
||||||
import net.psforever.types.PlanetSideGUID
|
import net.psforever.types.PlanetSideGUID
|
||||||
|
|
||||||
|
|
@ -22,7 +24,10 @@ class SessionLocalHandlers(
|
||||||
val sessionLogic: SessionData,
|
val sessionLogic: SessionData,
|
||||||
implicit val context: ActorContext
|
implicit val context: ActorContext
|
||||||
) extends CommonSessionInterfacingFunctionality {
|
) extends CommonSessionInterfacingFunctionality {
|
||||||
|
def deactivateTelpadDeployableMessages(guid: PlanetSideGUID): Unit = {
|
||||||
|
sendResponse(GenericObjectActionMessage(guid, code = 29))
|
||||||
|
sendResponse(GenericObjectActionMessage(guid, code = 30))
|
||||||
|
}
|
||||||
|
|
||||||
def handleTurretDeployableIsDismissed(obj: TurretDeployable): Unit = {
|
def handleTurretDeployableIsDismissed(obj: TurretDeployable): Unit = {
|
||||||
Players.buildCooldownReset(continent, player.Name, obj)
|
Players.buildCooldownReset(continent, player.Name, obj)
|
||||||
|
|
@ -33,4 +38,13 @@ class SessionLocalHandlers(
|
||||||
Players.buildCooldownReset(continent, player.Name, obj)
|
Players.buildCooldownReset(continent, player.Name, obj)
|
||||||
TaskWorkflow.execute(GUIDTask.unregisterObject(continent.GUID, 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2227,15 +2227,28 @@ class ZoningOperations(
|
||||||
sessionLogic.actionsToCancel()
|
sessionLogic.actionsToCancel()
|
||||||
continent.GUID(player.VehicleSeated) match {
|
continent.GUID(player.VehicleSeated) match {
|
||||||
case Some(vehicle: Vehicle) if vehicle.MountedIn.isEmpty =>
|
case Some(vehicle: Vehicle) if vehicle.MountedIn.isEmpty =>
|
||||||
vehicle.PassengerInSeat(player) match {
|
vehicle
|
||||||
case Some(0) =>
|
.PassengerInSeat(player)
|
||||||
deadState = DeadState.Release // cancel movement updates
|
.collect {
|
||||||
vehicle.Position = position
|
case 0 => //driver of the vehicle carries the vehicle and its passengers
|
||||||
LoadZonePhysicalSpawnPoint(continent.id, position, Vector3.z(vehicle.Orientation.z), 0 seconds, None)
|
deadState = DeadState.Release //cancel movement updates
|
||||||
case _ => // not seated as the driver, in which case we can't move
|
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 =>
|
case None =>
|
||||||
deadState = DeadState.Release // cancel movement updates
|
deadState = DeadState.Release // cancel movement updates
|
||||||
|
doorsThatShouldBeClosedOrBeOpenedByRange(
|
||||||
|
player.Position,
|
||||||
|
sessionLogic.localResponse.doorLoadRange(),
|
||||||
|
position,
|
||||||
|
openRange = 100f
|
||||||
|
)
|
||||||
player.Position = position
|
player.Position = position
|
||||||
sendResponse(PlayerStateShiftMessage(ShiftState(0, position, player.Orientation.z, None)))
|
sendResponse(PlayerStateShiftMessage(ShiftState(0, position, player.Orientation.z, None)))
|
||||||
deadState = DeadState.Alive // must be set here
|
deadState = DeadState.Alive // must be set here
|
||||||
|
|
@ -3105,6 +3118,7 @@ class ZoningOperations(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
doorsThatShouldBeOpenInRange(pos, range = 100f)
|
||||||
setAvatar = true
|
setAvatar = true
|
||||||
player.allowInteraction = true
|
player.allowInteraction = true
|
||||||
upstreamMessageCount = 0
|
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 = {
|
override protected[session] def stop(): Unit = {
|
||||||
zoningTimer.cancel()
|
zoningTimer.cancel()
|
||||||
spawn.respawnTimer.cancel()
|
spawn.respawnTimer.cancel()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ object GlobalDefinitionsImplant {
|
||||||
|
|
||||||
targeting.Name = "targeting"
|
targeting.Name = "targeting"
|
||||||
targeting.InitializationDuration = 60
|
targeting.InitializationDuration = 60
|
||||||
|
targeting.Passive = true
|
||||||
|
|
||||||
audio_amplifier.Name = "audio_amplifier"
|
audio_amplifier.Name = "audio_amplifier"
|
||||||
audio_amplifier.InitializationDuration = 60
|
audio_amplifier.InitializationDuration = 60
|
||||||
|
|
@ -41,9 +42,11 @@ object GlobalDefinitionsImplant {
|
||||||
|
|
||||||
range_magnifier.Name = "range_magnifier"
|
range_magnifier.Name = "range_magnifier"
|
||||||
range_magnifier.InitializationDuration = 60
|
range_magnifier.InitializationDuration = 60
|
||||||
|
range_magnifier.Passive = true
|
||||||
|
|
||||||
second_wind.Name = "second_wind"
|
second_wind.Name = "second_wind"
|
||||||
second_wind.InitializationDuration = 180
|
second_wind.InitializationDuration = 180
|
||||||
|
second_wind.Passive = true
|
||||||
|
|
||||||
silent_run.Name = "silent_run"
|
silent_run.Name = "silent_run"
|
||||||
silent_run.InitializationDuration = 90
|
silent_run.InitializationDuration = 90
|
||||||
|
|
|
||||||
|
|
@ -698,6 +698,7 @@ object GlobalDefinitionsMiscellaneous {
|
||||||
spawn_tube_door_coffin.Damageable = true
|
spawn_tube_door_coffin.Damageable = true
|
||||||
|
|
||||||
resource_silo.Name = "resource_silo"
|
resource_silo.Name = "resource_silo"
|
||||||
|
resource_silo.UseRadius = 22 //20
|
||||||
resource_silo.Damageable = false
|
resource_silo.Damageable = false
|
||||||
resource_silo.Repairable = false
|
resource_silo.Repairable = false
|
||||||
resource_silo.MaxNtuCapacitor = 1000
|
resource_silo.MaxNtuCapacitor = 1000
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ object CommonMessages {
|
||||||
final case class Unuse(player: Player, data: Option[Any] = None)
|
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 Hack(player: Player, obj: PlanetSideServerObject with Hackable, data: Option[Any] = None)
|
||||||
final case class ClearHack()
|
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
|
* The message that progresses some form of user-driven activity with a certain eventual outcome
|
||||||
* and potential feedback per cycle.
|
* and potential feedback per cycle.
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ object Interference {
|
||||||
val sector = zone.blockMap.sector(position, Interference.MaxRange)
|
val sector = zone.blockMap.sector(position, Interference.MaxRange)
|
||||||
val targets = (sector.deployableList ++ sector.vehicleList.filter(_.DeploymentState >= DriveState.Deploying))
|
val targets = (sector.deployableList ++ sector.vehicleList.filter(_.DeploymentState >= DriveState.Deploying))
|
||||||
.collect { case target: PlanetSideGameObject with FactionAffinity
|
.collect { case target: PlanetSideGameObject with FactionAffinity
|
||||||
if target.Faction != faction &&
|
if target.Faction == faction &&
|
||||||
(target.Definition.asInstanceOf[ObjectDefinition].interference ne Interference.AllowAll) =>
|
(target.Definition.asInstanceOf[ObjectDefinition].interference ne Interference.AllowAll) =>
|
||||||
target
|
target
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,12 @@ object GenericHackables {
|
||||||
turretUpgradeTime
|
turretUpgradeTime
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* na
|
* na
|
||||||
*
|
*
|
||||||
* @param player the player doing the hacking
|
* @param player the player doing the hacking
|
||||||
* @param obj the object being hacked
|
* @param obj the object being hacked
|
||||||
* @return the percentage amount of progress per tick
|
* @return the percentage amount of progress per tick
|
||||||
*/
|
*/
|
||||||
def GetHackSpeed(player: Player, obj: PlanetSideServerObject): Float = {
|
def GetHackSpeed(player: Player, obj: PlanetSideServerObject): Float = {
|
||||||
val playerHackLevel = player.avatar.hackingSkillLevel()
|
val playerHackLevel = player.avatar.hackingSkillLevel()
|
||||||
val timeToHack = obj match {
|
val timeToHack = obj match {
|
||||||
|
|
@ -60,23 +60,23 @@ object GenericHackables {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate the progress of the user applying a tool to modify some server object.
|
* 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.
|
* 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)
|
* 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.
|
* is also governed by this action per tick of progress.
|
||||||
* @see `HackMessage`
|
* @see `HackMessage`
|
||||||
* @see `HackState`
|
* @see `HackState`
|
||||||
* @param progressType 1 - remote electronics kit hack (various ...);
|
* @param progressType 1 - remote electronics kit hack (various ...);
|
||||||
* 2 - nano dispenser (upgrade canister) turret upgrade
|
* 2 - nano dispenser (upgrade canister) turret upgrade
|
||||||
* @param tplayer the player performing the action
|
* @param tplayer the player performing the action
|
||||||
* @param target the object being affected
|
* @param target the object being affected
|
||||||
* @param tool_guid the tool being used to affest the object
|
* @param tool_guid the tool being used to affest the object
|
||||||
* @param progress the current progress value
|
* @param progress the current progress value
|
||||||
* @return `true`, if the next cycle of progress should occur;
|
* @return `true`, if the next cycle of progress should occur;
|
||||||
* `false`, otherwise
|
* `false`, otherwise
|
||||||
*/
|
*/
|
||||||
def HackingTickAction(progressType: Int, tplayer: Player, target: PlanetSideServerObject, tool_guid: PlanetSideGUID)(
|
def HackingTickAction(progressType: Int, tplayer: Player, target: PlanetSideServerObject, tool_guid: PlanetSideGUID)(
|
||||||
progress: Float
|
progress: Float
|
||||||
): Boolean = {
|
): Boolean = {
|
||||||
//hack state for progress bar visibility
|
//hack state for progress bar visibility
|
||||||
val vis = if (progress <= 0L) {
|
val vis = if (progress <= 0L) {
|
||||||
|
|
@ -108,37 +108,40 @@ object GenericHackables {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The process of hacking an object is completed.
|
* The process of hacking an object is completed.
|
||||||
* Pass the message onto the hackable object and onto the local events system.
|
* Pass the message onto the hackable object and onto the local events system.
|
||||||
* @param target the `Hackable` object that has been hacked
|
* @param target the `Hackable` object that has been hacked
|
||||||
* @param user the player that is performing this hacking task
|
* @param user the player that is performing this hacking task
|
||||||
* @param unk na;
|
* @param unk na;
|
||||||
* used by `HackMessage` as `unk5`
|
* used by `HackMessage` as `unk5`
|
||||||
* @see `HackMessage`
|
* @see `HackMessage`
|
||||||
*/
|
*/
|
||||||
//TODO add params here depending on which params in HackMessage are important
|
//TODO add params here depending on which params in HackMessage are important
|
||||||
def FinishHacking(target: PlanetSideServerObject with Hackable, user: Player, unk: Long)(): Unit = {
|
def FinishHacking(target: PlanetSideServerObject with Hackable, user: Player, unk: Long)(): Unit = {
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
import scala.concurrent.duration._
|
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
|
// Wait for the target actor to set the HackedBy property, otherwise LocalAction.HackTemporarily will not complete properly
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
val tplayer = user
|
val tplayer = user
|
||||||
ask(target.Actor, CommonMessages.Hack(tplayer, target))(1 second).mapTo[Boolean].onComplete {
|
ask(target.Actor, CommonMessages.Hack(tplayer, target))(timeout = 2 second)
|
||||||
case Success(_) =>
|
.mapTo[CommonMessages.EntityHackState]
|
||||||
val zone = target.Zone
|
.onComplete {
|
||||||
val zoneId = zone.id
|
case Success(_) =>
|
||||||
val pguid = tplayer.GUID
|
val zone = target.Zone
|
||||||
zone.LocalEvents ! LocalServiceMessage(
|
val zoneId = zone.id
|
||||||
zoneId,
|
val pguid = tplayer.GUID
|
||||||
LocalAction.TriggerSound(pguid, target.HackSound, tplayer.Position, 30, 0.49803925f)
|
log.info(s"${user.Name} hacked a ${target.Definition.Name}")
|
||||||
)
|
zone.LocalEvents ! LocalServiceMessage(
|
||||||
zone.LocalEvents ! LocalServiceMessage(
|
zoneId,
|
||||||
zoneId,
|
LocalAction.TriggerSound(pguid, target.HackSound, tplayer.Position, 30, 0.49803925f)
|
||||||
LocalAction
|
)
|
||||||
.HackTemporarily(pguid, zone, target, unk, target.HackEffectDuration(user.avatar.hackingSkillLevel()))
|
zone.LocalEvents ! LocalServiceMessage(
|
||||||
)
|
zoneId,
|
||||||
case Failure(_) => log.warn(s"Hack message failed on target guid: ${target.GUID}")
|
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}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,44 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.serverobject.hackable
|
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 net.psforever.objects.serverobject.CommonMessages
|
||||||
|
|
||||||
|
import scala.annotation.unused
|
||||||
|
|
||||||
object HackableBehavior {
|
object HackableBehavior {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logic governing generic `Hackable` objects that use the `Hack` and `ClearHack` message.
|
* 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.
|
* This is a mix-in trait for combining with existing `Receive` logic.
|
||||||
* @see `Hackable`
|
* @see `Hackable`
|
||||||
*/
|
*/
|
||||||
trait GenericHackable {
|
trait GenericHackable {
|
||||||
this: Actor =>
|
this: Actor =>
|
||||||
def HackableObject: Hackable
|
def HackableObject: PlanetSideGameObject with Hackable
|
||||||
|
|
||||||
val hackableBehavior: Receive = {
|
|
||||||
case CommonMessages.Hack(player, _, _) =>
|
|
||||||
val obj = HackableObject
|
|
||||||
obj.HackedBy = player
|
|
||||||
sender() ! true
|
|
||||||
|
|
||||||
|
val clearHackBehavior: Receive = {
|
||||||
case CommonMessages.ClearHack() =>
|
case CommonMessages.ClearHack() =>
|
||||||
val obj = HackableObject
|
performClearHack(None, sender())
|
||||||
obj.HackedBy = None
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) 2019 PSForever
|
// Copyright (c) 2019 PSForever
|
||||||
package net.psforever.objects.serverobject.resourcesilo
|
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.objects.serverobject.CommonMessages
|
||||||
import net.psforever.actors.zone.BuildingActor
|
import net.psforever.actors.zone.BuildingActor
|
||||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||||
|
|
@ -53,37 +53,31 @@ class ResourceSiloControl(resourceSilo: ResourceSilo)
|
||||||
checkBehavior
|
checkBehavior
|
||||||
.orElse(storageBehavior)
|
.orElse(storageBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
case CommonMessages.Use(player, _) =>
|
case CommonMessages.Use(_, Some(vehicle: Vehicle))
|
||||||
|
if GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition) =>
|
||||||
val siloFaction = resourceSilo.Faction
|
val siloFaction = resourceSilo.Faction
|
||||||
val playerFaction = player.Faction
|
val vehicleFaction = vehicle.Faction
|
||||||
resourceSilo.Zone.Vehicles.find(v => v.PassengerInSeat(player).contains(0)) match {
|
val msgOpt = if (siloFaction == vehicleFaction) {
|
||||||
case Some(vehicle) =>
|
Some(TransferBehavior.Discharging(Ntu.Nanites))
|
||||||
(if (GlobalDefinitions.isBattleFrameVehicle(vehicle.Definition)) {
|
} else if (resourceSilo.MaxNtuCapacitor * 0.4f < resourceSilo.NtuCapacitor) {
|
||||||
//bfr's discharge into friendly silos and charge from enemy and neutral silos
|
//the bfr never drains below 40%
|
||||||
if (siloFaction == playerFaction) {
|
Some(TransferBehavior.Charging(Ntu.Nanites))
|
||||||
Some(TransferBehavior.Discharging(Ntu.Nanites))
|
} else {
|
||||||
} else if (resourceSilo.MaxNtuCapacitor * 0.4f < resourceSilo.NtuCapacitor) {
|
None
|
||||||
//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 _ => ;
|
|
||||||
}
|
}
|
||||||
|
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) =>
|
case ResourceSilo.LowNtuWarning(enabled: Boolean) =>
|
||||||
LowNtuWarning(enabled)
|
LowNtuWarning(enabled)
|
||||||
|
|
@ -91,9 +85,13 @@ class ResourceSiloControl(resourceSilo: ResourceSilo)
|
||||||
case ResourceSilo.UpdateChargeLevel(amount: Float) =>
|
case ResourceSilo.UpdateChargeLevel(amount: Float) =>
|
||||||
UpdateChargeLevel(amount)
|
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 = {
|
def LowNtuWarning(enabled: Boolean): Unit = {
|
||||||
resourceSilo.LowNtuWarningOn = enabled
|
resourceSilo.LowNtuWarningOn = enabled
|
||||||
log.trace(s"LowNtuWarning: Silo ${resourceSilo.GUID} low ntu warning set to $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.
|
* The silo will agree to offers until its nanite capacitor is completely full.
|
||||||
*/
|
*/
|
||||||
def HandleNtuOffer(sender: ActorRef, src: NtuContainer): Unit = {
|
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) {
|
sender ! (if (resourceSilo.NtuCapacitor < resourceSilo.MaxNtuCapacitor) {
|
||||||
Ntu.Request(0, resourceSilo.MaxNtuCapacitor - resourceSilo.NtuCapacitor)
|
Ntu.Request(0, resourceSilo.MaxNtuCapacitor - resourceSilo.NtuCapacitor)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import akka.actor.{ActorRef, Cancellable}
|
||||||
import net.psforever.objects.sourcing.AmenitySource
|
import net.psforever.objects.sourcing.AmenitySource
|
||||||
import org.log4s.Logger
|
import org.log4s.Logger
|
||||||
|
|
||||||
|
import scala.annotation.unused
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
//
|
//
|
||||||
|
|
@ -121,6 +122,7 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
||||||
}
|
}
|
||||||
|
|
||||||
def unpoweredStateLogic : Receive = commonBehavior
|
def unpoweredStateLogic : Receive = commonBehavior
|
||||||
|
.orElse(clearHackBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
case CommonMessages.Use(_, _) =>
|
case CommonMessages.Use(_, _) =>
|
||||||
log.warn(s"unexpected format for CommonMessages.Use in this context")
|
log.warn(s"unexpected format for CommonMessages.Use in this context")
|
||||||
|
|
@ -145,7 +147,7 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
||||||
isPowered && super.tryAutoRepair()
|
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
|
val hadNoUsers = term.NumberUsers == 0
|
||||||
if (term.AddUser(target)) {
|
if (term.AddUser(target)) {
|
||||||
log.trace(s"ProximityTerminal.Use: unit ${term.Definition.Name}@${term.GUID.guid} will act on $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 whereTarget = term.Targets.indexWhere(_ eq target)
|
||||||
val previousUsers = term.NumberUsers
|
val previousUsers = term.NumberUsers
|
||||||
val hadUsers = previousUsers > 0
|
val hadUsers = previousUsers > 0
|
||||||
|
|
@ -223,7 +225,7 @@ object ProximityTerminalControl {
|
||||||
* @param target the object being affected by the unit
|
* @param target the object being affected by the unit
|
||||||
*/
|
*/
|
||||||
def selectAndTryProximityUnitBehavior(
|
def selectAndTryProximityUnitBehavior(
|
||||||
callback: ActorRef,
|
@unused callback: ActorRef,
|
||||||
terminal: Terminal with ProximityUnit,
|
terminal: Terminal with ProximityUnit,
|
||||||
target: PlanetSideGameObject
|
target: PlanetSideGameObject
|
||||||
): Boolean = {
|
): Boolean = {
|
||||||
|
|
|
||||||
|
|
@ -19,24 +19,24 @@ import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
* @param term the `Terminal` object being governed
|
* @param term the `Terminal` object being governed
|
||||||
*/
|
*/
|
||||||
class TerminalControl(term: Terminal)
|
class TerminalControl(term: Terminal)
|
||||||
extends PoweredAmenityControl
|
extends PoweredAmenityControl
|
||||||
with FactionAffinityBehavior.Check
|
with FactionAffinityBehavior.Check
|
||||||
with HackableBehavior.GenericHackable
|
with HackableBehavior.GenericHackable
|
||||||
with DamageableAmenity
|
with DamageableAmenity
|
||||||
with RepairableAmenity
|
with RepairableAmenity
|
||||||
with AmenityAutoRepair {
|
with AmenityAutoRepair {
|
||||||
def FactionObject = term
|
def FactionObject: Terminal = term
|
||||||
def HackableObject = term
|
def HackableObject: Terminal = term
|
||||||
def DamageableObject = term
|
def DamageableObject: Terminal = term
|
||||||
def RepairableObject = term
|
def RepairableObject: Terminal = term
|
||||||
def AutoRepairObject = term
|
def AutoRepairObject: Terminal = term
|
||||||
|
|
||||||
val commonBehavior: Receive = checkBehavior
|
val commonBehavior: Receive = checkBehavior
|
||||||
.orElse(takesDamage)
|
.orElse(takesDamage)
|
||||||
.orElse(canBeRepairedByNanoDispenser)
|
.orElse(canBeRepairedByNanoDispenser)
|
||||||
.orElse(autoRepairBehavior)
|
.orElse(autoRepairBehavior)
|
||||||
|
|
||||||
def poweredStateLogic : Receive =
|
def poweredStateLogic: Receive =
|
||||||
commonBehavior
|
commonBehavior
|
||||||
.orElse(hackableBehavior)
|
.orElse(hackableBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
|
|
@ -53,18 +53,19 @@ class TerminalControl(term: Terminal)
|
||||||
GenericHackables.FinishHacking(term, player, 3212836864L),
|
GenericHackables.FinishHacking(term, player, 3212836864L),
|
||||||
GenericHackables.HackingTickAction(progressType = 1, player, term, item.GUID)
|
GenericHackables.HackingTickAction(progressType = 1, player, term, item.GUID)
|
||||||
)
|
)
|
||||||
case _ => ;
|
case _ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
case _ => ;
|
case _ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
def unpoweredStateLogic : Receive = commonBehavior
|
def unpoweredStateLogic : Receive = commonBehavior
|
||||||
|
.orElse(clearHackBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
case Terminal.Request(player, msg) =>
|
case Terminal.Request(player, msg) =>
|
||||||
sender() ! Terminal.TerminalMessage(player, msg, Terminal.NoDeal())
|
sender() ! Terminal.TerminalMessage(player, msg, Terminal.NoDeal())
|
||||||
|
|
||||||
case _ => ;
|
case _ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def DamageAwareness(target: Target, cause: DamageResult, amount: Any) : Unit = {
|
override protected def DamageAwareness(target: Target, cause: DamageResult, amount: Any) : Unit = {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package net.psforever.objects.serverobject.terminals.capture
|
package net.psforever.objects.serverobject.terminals.capture
|
||||||
|
|
||||||
import akka.util.Timeout
|
|
||||||
import net.psforever.objects.Player
|
import net.psforever.objects.Player
|
||||||
import net.psforever.objects.serverobject.CommonMessages
|
import net.psforever.objects.serverobject.CommonMessages
|
||||||
import net.psforever.objects.sourcing.PlayerSource
|
import net.psforever.objects.sourcing.PlayerSource
|
||||||
|
|
@ -10,17 +9,16 @@ import scala.util.{Failure, Success}
|
||||||
|
|
||||||
object CaptureTerminals {import scala.concurrent.duration._
|
object CaptureTerminals {import scala.concurrent.duration._
|
||||||
private val log = org.log4s.getLogger("CaptureTerminals")
|
private val log = org.log4s.getLogger("CaptureTerminals")
|
||||||
private implicit val timeout: Timeout = 1.second
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The process of hacking an object is completed.
|
* The process of hacking an object is completed.
|
||||||
* Pass the message onto the hackable object and onto the local events system.
|
* Pass the message onto the hackable object and onto the local events system.
|
||||||
* @param target the `Hackable` object that has been hacked
|
* @param target the `Hackable` object that has been hacked
|
||||||
* @param hackingPlayer The player that hacked the control console
|
* @param hackingPlayer The player that hacked the control console
|
||||||
* @param unk na;
|
* @param unk na;
|
||||||
* used by `HackMessage` as `unk5`
|
* used by `HackMessage` as `unk5`
|
||||||
* @see `HackMessage`
|
* @see `HackMessage`
|
||||||
*/
|
*/
|
||||||
//TODO add params here depending on which params in HackMessage are important
|
//TODO add params here depending on which params in HackMessage are important
|
||||||
def FinishHackingCaptureConsole(target: CaptureTerminal, hackingPlayer: Player, unk: Long)(): Unit = {
|
def FinishHackingCaptureConsole(target: CaptureTerminal, hackingPlayer: Player, unk: Long)(): Unit = {
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
|
|
@ -28,31 +26,33 @@ object CaptureTerminals {import scala.concurrent.duration._
|
||||||
log.info(s"${hackingPlayer.toString} hacked a ${target.Definition.Name}")
|
log.info(s"${hackingPlayer.toString} hacked a ${target.Definition.Name}")
|
||||||
// Wait for the target actor to set the HackedBy property
|
// Wait for the target actor to set the HackedBy property
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
ask(target.Actor, CommonMessages.Hack(hackingPlayer, target)).mapTo[Boolean].onComplete {
|
ask(target.Actor, CommonMessages.Hack(hackingPlayer, target))(timeout = 2 second)
|
||||||
case Success(_) =>
|
.mapTo[CommonMessages.EntityHackState]
|
||||||
val zone = target.Zone
|
.onComplete {
|
||||||
val zoneid = zone.id
|
case Success(_) =>
|
||||||
val events = zone.LocalEvents
|
val zone = target.Zone
|
||||||
val isResecured = hackingPlayer.Faction == target.Faction
|
val zoneid = zone.id
|
||||||
events ! LocalServiceMessage(
|
val events = zone.LocalEvents
|
||||||
zoneid,
|
val isResecured = hackingPlayer.Faction == target.Faction
|
||||||
LocalAction.TriggerSound(hackingPlayer.GUID, target.HackSound, hackingPlayer.Position, 30, 0.49803925f)
|
|
||||||
)
|
|
||||||
if (isResecured) {
|
|
||||||
// Resecure the CC
|
|
||||||
events ! LocalServiceMessage(
|
events ! LocalServiceMessage(
|
||||||
zoneid,
|
zoneid,
|
||||||
LocalAction.ResecureCaptureTerminal(target, PlayerSource(hackingPlayer))
|
LocalAction.TriggerSound(hackingPlayer.GUID, target.HackSound, hackingPlayer.Position, 30, 0.49803925f)
|
||||||
)
|
)
|
||||||
} else {
|
if (isResecured) {
|
||||||
// Start the CC hack timer
|
// Resecure the CC
|
||||||
events ! LocalServiceMessage(
|
events ! LocalServiceMessage(
|
||||||
zoneid,
|
zoneid,
|
||||||
LocalAction.StartCaptureTerminalHack(target)
|
LocalAction.ResecureCaptureTerminal(target, PlayerSource(hackingPlayer))
|
||||||
)
|
)
|
||||||
}
|
} else {
|
||||||
case Failure(_) =>
|
// Start the CC hack timer
|
||||||
log.warn(s"Hack message failed on target guid: ${target.GUID}")
|
events ! LocalServiceMessage(
|
||||||
}
|
zoneid,
|
||||||
|
LocalAction.StartCaptureTerminalHack(target)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
case Failure(_) =>
|
||||||
|
log.warn(s"Hack message failed on target guid: ${target.GUID}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ class ImplantTerminalMechControl(mech: ImplantTerminalMech)
|
||||||
seat.unmount(player)
|
seat.unmount(player)
|
||||||
player.VehicleSeated = None
|
player.VehicleSeated = None
|
||||||
if (player.HasGUID) {
|
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 => ;
|
case None => ;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,9 +104,14 @@ 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
|
||||||
AutomaticOperation = false //turn off
|
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)) {
|
if (!super.tryMount(obj, seatNumber, player)) {
|
||||||
AutomaticOperation = true //revert?
|
AutomaticOperation = originalAutoState //revert
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
|
@ -215,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
|
||||||
|
|
@ -289,16 +303,15 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def TryJammerEffectActivate(target: Any, cause: DamageResult): Unit = {
|
override def TryJammerEffectActivate(target: Any, cause: DamageResult): Unit = {
|
||||||
val startsUnjammed = !JammableObject.Jammed
|
|
||||||
super.TryJammerEffectActivate(target, cause)
|
super.TryJammerEffectActivate(target, cause)
|
||||||
if (JammableObject.Jammed && AutomatedTurretObject.Definition.AutoFire.exists(_.retaliatoryDelay > 0)) {
|
if (AutomaticOperationPossible && AutomaticOperation && JammableObject.Jammed) {
|
||||||
if (startsUnjammed) {
|
AutomaticOperation = false
|
||||||
AutomaticOperation = false
|
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
|
val zone = JammableObject.Zone
|
||||||
val zone = JammableObject.Zone
|
AutomatedTurretBehavior.getAttackVectorFromCause(zone, cause).foreach { attacker =>
|
||||||
AutomatedTurretBehavior.getAttackVectorFromCause(zone, cause).foreach { attacker =>
|
AutomatedTurretBehavior.startTracking(zone, zone.id, JammableObject.GUID, List(attacker.GUID))
|
||||||
AutomatedTurretBehavior.startTracking(zone, zone.id, JammableObject.GUID, List(attacker.GUID))
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,7 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
|
||||||
* @return synchronized reference to the globally unique identifier system
|
* @return synchronized reference to the globally unique identifier system
|
||||||
*/
|
*/
|
||||||
def GUID(hub: NumberPoolHub): Boolean = {
|
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.Color.RED
|
||||||
import org.fusesource.jansi.Ansi.ansi
|
import org.fusesource.jansi.Ansi.ansi
|
||||||
println(
|
println(
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package base
|
||||||
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
|
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
|
||||||
import akka.testkit.{ImplicitSender, TestKit}
|
import akka.testkit.{ImplicitSender, TestKit}
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
|
import net.psforever.objects.Default
|
||||||
import org.scalatest.BeforeAndAfterAll
|
import org.scalatest.BeforeAndAfterAll
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
import org.scalatest.wordspec.AnyWordSpecLike
|
import org.scalatest.wordspec.AnyWordSpecLike
|
||||||
|
|
@ -19,6 +20,7 @@ abstract class ActorTest(sys: ActorSystem = ActorSystem("system", ConfigFactory.
|
||||||
with AnyWordSpecLike
|
with AnyWordSpecLike
|
||||||
with Matchers
|
with Matchers
|
||||||
with BeforeAndAfterAll {
|
with BeforeAndAfterAll {
|
||||||
|
Default(sys)
|
||||||
override def afterAll(): Unit = {
|
override def afterAll(): Unit = {
|
||||||
TestKit.shutdownActorSystem(system)
|
TestKit.shutdownActorSystem(system)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -775,7 +775,7 @@ class DamageableWeaponTurretDamageTest extends ActorTest {
|
||||||
zone.AvatarEvents = avatarProbe.ref
|
zone.AvatarEvents = avatarProbe.ref
|
||||||
zone.VehicleEvents = vehicleProbe.ref
|
zone.VehicleEvents = vehicleProbe.ref
|
||||||
val turret = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) //2
|
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.Zone = zone
|
||||||
turret.Position = Vector3(1, 0, 0)
|
turret.Position = Vector3(1, 0, 0)
|
||||||
turret.LogActivity(SpawningActivity(SourceEntry(turret), zone.Number, None)) //seed a spawn event
|
turret.LogActivity(SpawningActivity(SourceEntry(turret), zone.Number, None)) //seed a spawn event
|
||||||
|
|
@ -873,7 +873,7 @@ class DamageableWeaponTurretJammerTest extends ActorTest {
|
||||||
zone.VehicleEvents = vehicleProbe.ref
|
zone.VehicleEvents = vehicleProbe.ref
|
||||||
|
|
||||||
val turret = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) //2, 5, 6
|
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.Zone = zone
|
||||||
turret.Position = Vector3(1, 0, 0)
|
turret.Position = Vector3(1, 0, 0)
|
||||||
val turretWeapon: Tool = turret.Weapons.values.head.Equipment.get.asInstanceOf[Tool]
|
val turretWeapon: Tool = turret.Weapons.values.head.Equipment.get.asInstanceOf[Tool]
|
||||||
|
|
|
||||||
|
|
@ -25,18 +25,17 @@ class DefaultActorStartedTest extends ActorTest {
|
||||||
"Default.Actor" should {
|
"Default.Actor" should {
|
||||||
"send messages to deadLetters" in {
|
"send messages to deadLetters" in {
|
||||||
//after being started
|
//after being started
|
||||||
Default(system)
|
|
||||||
val probe = new TestProbe(system)
|
val probe = new TestProbe(system)
|
||||||
system.eventStream.subscribe(probe.ref, classOf[DeadLetter])
|
system.eventStream.subscribe(probe.ref, classOf[DeadLetter])
|
||||||
Default.Actor ! "hello world"
|
Default.Actor ! "hello world"
|
||||||
val msg1 = probe.receiveOne(250 milliseconds)
|
val msg1 = probe.receiveOne(5000 milliseconds)
|
||||||
assert(msg1.isInstanceOf[DeadLetter])
|
assert(msg1.isInstanceOf[DeadLetter])
|
||||||
assert(msg1.asInstanceOf[DeadLetter].message equals "hello world")
|
assert(msg1.asInstanceOf[DeadLetter].message equals "hello world")
|
||||||
|
|
||||||
//if it was stopped
|
//if it was stopped
|
||||||
system.stop(Default.Actor)
|
system.stop(Default.Actor)
|
||||||
Default.Actor ! "hello world"
|
Default.Actor ! "hello world"
|
||||||
val msg2 = probe.receiveOne(250 milliseconds)
|
val msg2 = probe.receiveOne(5000 milliseconds)
|
||||||
assert(msg2.isInstanceOf[DeadLetter])
|
assert(msg2.isInstanceOf[DeadLetter])
|
||||||
assert(msg2.asInstanceOf[DeadLetter].message equals "hello world")
|
assert(msg2.asInstanceOf[DeadLetter].message equals "hello world")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -584,7 +584,7 @@ class TurretControlConstructTest extends ActorTest {
|
||||||
"TurretControl" should {
|
"TurretControl" should {
|
||||||
"construct" in {
|
"construct" in {
|
||||||
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
|
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() = {}
|
override def SetupNumberPools() = {}
|
||||||
this.actor = new TestProbe(system).ref.toTyped[ZoneActor.Command]
|
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)
|
assert(obj.Seats(0).occupant.isEmpty)
|
||||||
val player1 = Player(Avatar(0, "test1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute))
|
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 {
|
"block mounting by others if already mounted by someone" in {
|
||||||
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
|
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
|
||||||
obj.Faction = PlanetSideEmpire.TR
|
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) {
|
obj.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||||
override def SetupNumberPools() = {}
|
override def SetupNumberPools() = {}
|
||||||
this.actor = new TestProbe(system).ref.toTyped[ZoneActor.Command]
|
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 {
|
"block mounting by players of another faction" in {
|
||||||
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
|
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
|
||||||
obj.Faction = PlanetSideEmpire.TR
|
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)
|
assert(obj.Seats(0).occupant.isEmpty)
|
||||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.VS, CharacterSex.Male, 0, CharacterVoice.Mute))
|
val player = Player(Avatar(0, "test", PlanetSideEmpire.VS, CharacterSex.Male, 0, CharacterVoice.Mute))
|
||||||
|
|
@ -705,7 +705,7 @@ class TurretControlDismountTest extends ActorTest {
|
||||||
override def SetupNumberPools() = {}
|
override def SetupNumberPools() = {}
|
||||||
this.actor = new TestProbe(system).ref.toTyped[ZoneActor.Command]
|
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)
|
assert(obj.Seats(0).occupant.isEmpty)
|
||||||
val player = Player(Avatar(0, "test", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute))
|
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.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)
|
val probe = new TestProbe(system)
|
||||||
|
|
||||||
assert(obj.Seats(0).occupant.isEmpty)
|
assert(obj.Seats(0).occupant.isEmpty)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -774,124 +774,124 @@ class PlayerControlDeathStandingTest extends ActorTest {
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
class PlayerControlInteractWithWaterTest extends ActorTest {
|
//class PlayerControlInteractWithWaterTest extends ActorTest {
|
||||||
val player1: Player =
|
// val player1: Player =
|
||||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)) //guid=1
|
// Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||||
val avatarProbe: TestProbe = TestProbe()
|
// val avatarProbe: TestProbe = TestProbe()
|
||||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
// val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||||
val pool: Pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
// val pool: Pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
||||||
val zone: Zone = new Zone(
|
// val zone: Zone = new Zone(
|
||||||
id = "test",
|
// id = "test",
|
||||||
new ZoneMap(name = "test-map") {
|
// new ZoneMap(name = "test-map") {
|
||||||
environment = List(pool)
|
// environment = List(pool)
|
||||||
},
|
// },
|
||||||
zoneNumber = 0
|
// zoneNumber = 0
|
||||||
) {
|
// ) {
|
||||||
override def SetupNumberPools(): Unit = {}
|
// override def SetupNumberPools(): Unit = {}
|
||||||
GUID(guid)
|
// GUID(guid)
|
||||||
override def LivePlayers: List[Player] = List(player1)
|
// override def LivePlayers: List[Player] = List(player1)
|
||||||
override def AvatarEvents: ClassicActorRef = avatarProbe.ref
|
// override def AvatarEvents: ClassicActorRef = avatarProbe.ref
|
||||||
}
|
// }
|
||||||
zone.blockMap.addTo(player1)
|
// zone.blockMap.addTo(player1)
|
||||||
zone.blockMap.addTo(pool)
|
// 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
|
//class PlayerControlStopInteractWithWaterTest extends ActorTest {
|
||||||
player1.Spawn()
|
// val player1: Player =
|
||||||
guid.register(player1.avatar.locker, 5)
|
// Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
// val avatarProbe: TestProbe = TestProbe()
|
||||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
// val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||||
|
// val pool: Pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
||||||
guid.register(player1, 1)
|
// val zone: Zone = new Zone(
|
||||||
|
// id = "test",
|
||||||
"PlayerControl" should {
|
// new ZoneMap(name = "test-map") {
|
||||||
"cause drowning when player steps too deep in water" in {
|
// environment = List(pool)
|
||||||
assert(player1.Health == 100)
|
// },
|
||||||
player1.Position = Vector3(5,5,-3) //right in the pool
|
// zoneNumber = 0
|
||||||
player1.zoneInteractions() //trigger
|
// ) {
|
||||||
|
// override def SetupNumberPools(): Unit = {}
|
||||||
val msg_drown = avatarProbe.receiveOne(250 milliseconds)
|
// GUID(guid)
|
||||||
assert(
|
// override def LivePlayers: List[Player] = List(player1)
|
||||||
msg_drown match {
|
// override def AvatarEvents: ClassicActorRef = avatarProbe.ref
|
||||||
case AvatarServiceMessage(
|
// }
|
||||||
"TestCharacter1",
|
// zone.blockMap.addTo(player1)
|
||||||
AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), _, OxygenState.Suffocation, 100f), _)
|
// zone.blockMap.addTo(pool)
|
||||||
) => true
|
//
|
||||||
case _ => false
|
// player1.Zone = zone
|
||||||
}
|
// player1.Spawn()
|
||||||
)
|
// guid.register(player1.avatar.locker, 5)
|
||||||
//player will die in 60s
|
// val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||||
//detailing these death messages is not necessary
|
// player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
||||||
assert(player1.Health == 100)
|
//
|
||||||
probe.receiveOne(65 seconds) //wait until our implants deinitialize
|
// guid.register(player1, 1)
|
||||||
assert(player1.Health == 0) //ded
|
//
|
||||||
}
|
// "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
|
||||||
class PlayerControlStopInteractWithWaterTest extends ActorTest {
|
// player1.zoneInteractions() //trigger
|
||||||
val player1: Player =
|
//
|
||||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterSex.Male, 0, CharacterVoice.Mute)) //guid=1
|
// val msg_drown = avatarProbe.receiveOne(250 milliseconds)
|
||||||
val avatarProbe: TestProbe = TestProbe()
|
// assert(
|
||||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
// msg_drown match {
|
||||||
val pool: Pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
// case AvatarServiceMessage(
|
||||||
val zone: Zone = new Zone(
|
// "TestCharacter1",
|
||||||
id = "test",
|
// AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), _, OxygenState.Suffocation, 100f), _)
|
||||||
new ZoneMap(name = "test-map") {
|
// ) => true
|
||||||
environment = List(pool)
|
// case _ => false
|
||||||
},
|
// }
|
||||||
zoneNumber = 0
|
// )
|
||||||
) {
|
// //player would normally die in 60s
|
||||||
override def SetupNumberPools(): Unit = {}
|
// player1.Position = Vector3.Zero //pool's closed
|
||||||
GUID(guid)
|
// player1.zoneInteractions() //trigger
|
||||||
override def LivePlayers: List[Player] = List(player1)
|
// val msg_recover = avatarProbe.receiveOne(250 milliseconds)
|
||||||
override def AvatarEvents: ClassicActorRef = avatarProbe.ref
|
// assert(
|
||||||
}
|
// msg_recover match {
|
||||||
zone.blockMap.addTo(player1)
|
// case AvatarServiceMessage(
|
||||||
zone.blockMap.addTo(pool)
|
// "TestCharacter1",
|
||||||
|
// AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), _, OxygenState.Recovery, _), _)
|
||||||
player1.Zone = zone
|
// ) => true
|
||||||
player1.Spawn()
|
// case _ => false
|
||||||
guid.register(player1.avatar.locker, 5)
|
// }
|
||||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
// )
|
||||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
// assert(player1.Health == 100) //still alive?
|
||||||
|
// probe.expectNoMessage(65 seconds)
|
||||||
guid.register(player1, 1)
|
// assert(player1.Health == 100) //yep, still alive
|
||||||
|
// }
|
||||||
"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 {
|
class PlayerControlInteractWithLavaTest extends ActorTest {
|
||||||
val player1: Player =
|
val player1: Player =
|
||||||
|
|
|
||||||
|
|
@ -486,9 +486,13 @@ class ZonePopulationTest extends ActorTest {
|
||||||
class ZoneGroundDropItemTest extends ActorTest {
|
class ZoneGroundDropItemTest extends ActorTest {
|
||||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||||
val hub = new NumberPoolHub(new MaxNumberSource(20))
|
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)
|
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)
|
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||||
expectNoMessage(200 milliseconds)
|
expectNoMessage(200 milliseconds)
|
||||||
|
|
||||||
|
|
@ -511,9 +515,13 @@ class ZoneGroundDropItemTest extends ActorTest {
|
||||||
class ZoneGroundCanNotDropItem1Test extends ActorTest {
|
class ZoneGroundCanNotDropItem1Test extends ActorTest {
|
||||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||||
val hub = new NumberPoolHub(new MaxNumberSource(20))
|
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
|
//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)
|
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||||
expectNoMessage(200 milliseconds)
|
expectNoMessage(200 milliseconds)
|
||||||
|
|
||||||
|
|
@ -536,9 +544,13 @@ class ZoneGroundCanNotDropItem1Test extends ActorTest {
|
||||||
class ZoneGroundCanNotDropItem2Test extends ActorTest {
|
class ZoneGroundCanNotDropItem2Test extends ActorTest {
|
||||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||||
val hub = new NumberPoolHub(new MaxNumberSource(20))
|
val hub = new NumberPoolHub(new MaxNumberSource(20))
|
||||||
hub.register(item, 10) //!important
|
val zone = new Zone(
|
||||||
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
|
"test",
|
||||||
//zone.GUID(hub) //!important
|
new ZoneMap("test-map"), 0) {
|
||||||
|
override def SetupNumberPools() = {}
|
||||||
|
//GUID(hub) !important
|
||||||
|
}
|
||||||
|
hub.register(item, 10)
|
||||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||||
expectNoMessage(200 milliseconds)
|
expectNoMessage(200 milliseconds)
|
||||||
|
|
||||||
|
|
@ -561,9 +573,13 @@ class ZoneGroundCanNotDropItem2Test extends ActorTest {
|
||||||
class ZoneGroundCanNotDropItem3Test extends ActorTest {
|
class ZoneGroundCanNotDropItem3Test extends ActorTest {
|
||||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||||
val hub = new NumberPoolHub(new MaxNumberSource(20))
|
val hub = new NumberPoolHub(new MaxNumberSource(20))
|
||||||
hub.register(item, 10) //!important
|
val zone = new Zone(
|
||||||
val zone = new Zone("test", new ZoneMap("test-map"), 0) { override def SetupNumberPools() = {} }
|
"test",
|
||||||
zone.GUID(hub) //!important
|
new ZoneMap("test-map"), 0) {
|
||||||
|
override def SetupNumberPools() = {}
|
||||||
|
GUID(hub)
|
||||||
|
}
|
||||||
|
hub.register(item, 10)
|
||||||
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||||
expectNoMessage(200 milliseconds)
|
expectNoMessage(200 milliseconds)
|
||||||
|
|
||||||
|
|
@ -594,9 +610,13 @@ class ZoneGroundCanNotDropItem3Test extends ActorTest {
|
||||||
class ZoneGroundPickupItemTest extends ActorTest {
|
class ZoneGroundPickupItemTest extends ActorTest {
|
||||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||||
val hub = new NumberPoolHub(new MaxNumberSource(20))
|
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)
|
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)
|
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||||
expectNoMessage(200 milliseconds)
|
expectNoMessage(200 milliseconds)
|
||||||
|
|
||||||
|
|
@ -622,9 +642,13 @@ class ZoneGroundPickupItemTest extends ActorTest {
|
||||||
class ZoneGroundCanNotPickupItemTest extends ActorTest {
|
class ZoneGroundCanNotPickupItemTest extends ActorTest {
|
||||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||||
val hub = new NumberPoolHub(new MaxNumberSource(20))
|
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)
|
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)
|
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||||
expectNoMessage(200 milliseconds)
|
expectNoMessage(200 milliseconds)
|
||||||
|
|
||||||
|
|
@ -646,9 +670,13 @@ class ZoneGroundCanNotPickupItemTest extends ActorTest {
|
||||||
class ZoneGroundRemoveItemTest extends ActorTest {
|
class ZoneGroundRemoveItemTest extends ActorTest {
|
||||||
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
val item = AmmoBox(GlobalDefinitions.bullet_9mm)
|
||||||
val hub = new NumberPoolHub(new MaxNumberSource(20))
|
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)
|
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)
|
zone.actor = system.spawn(ZoneActor(zone), ZoneTest.TestName)
|
||||||
expectNoMessage(200 milliseconds)
|
expectNoMessage(200 milliseconds)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -161,31 +161,37 @@ object ImplantTerminalMechTest {
|
||||||
import akka.actor.typed.scaladsl.adapter._
|
import akka.actor.typed.scaladsl.adapter._
|
||||||
|
|
||||||
val guid = new NumberPoolHub(new MaxNumberSource(10))
|
val guid = new NumberPoolHub(new MaxNumberSource(10))
|
||||||
val map = new ZoneMap("test")
|
val terminal = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech) //guid=1
|
||||||
val zone = new Zone("test", map, 0) {
|
val interface = Terminal(GlobalDefinitions.implant_terminal_interface) //guid=2
|
||||||
override def SetupNumberPools() = {}
|
|
||||||
GUID(guid)
|
|
||||||
this.actor = new TestProbe(system).ref.toTyped[ZoneActor.Command]
|
|
||||||
}
|
|
||||||
val building = new Building(
|
val building = new Building(
|
||||||
"Building",
|
"Building",
|
||||||
building_guid = 0,
|
building_guid = 0,
|
||||||
map_id = 0,
|
map_id = 0,
|
||||||
zone,
|
Zone.Nowhere,
|
||||||
StructureType.Building,
|
StructureType.Building,
|
||||||
GlobalDefinitions.building
|
GlobalDefinitions.building
|
||||||
) //guid=3
|
) //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
|
building.Faction = faction
|
||||||
|
interface.Zone = zone
|
||||||
val interface = Terminal(GlobalDefinitions.implant_terminal_interface) //guid=2
|
building.Amenities = interface
|
||||||
interface.Owner = building
|
terminal.Zone = zone
|
||||||
val terminal = ImplantTerminalMech(GlobalDefinitions.implant_terminal_mech) //guid=1
|
building.Amenities = terminal
|
||||||
terminal.Owner = building
|
|
||||||
|
|
||||||
guid.register(terminal, 1)
|
guid.register(terminal, 1)
|
||||||
guid.register(interface, 2)
|
guid.register(interface, 2)
|
||||||
guid.register(building, 3)
|
guid.register(building, 3)
|
||||||
map.linkTerminalToInterface(1, 2)
|
|
||||||
terminal.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], terminal), "terminal-control")
|
terminal.Actor = system.actorOf(Props(classOf[ImplantTerminalMechControl], terminal), "terminal-control")
|
||||||
|
|
||||||
(Player(Avatar(0, "test", faction, CharacterSex.Male, 0, CharacterVoice.Mute)), terminal)
|
(Player(Avatar(0, "test", faction, CharacterSex.Male, 0, CharacterVoice.Mute)), terminal)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue