Proximity Terminal Fix (#241)

* modifications to ProximityUnit and related classes to internalize the effect control for the terminal, removing the flywheel functiuonality from WSA

* proximity operations for medical terminals (the one in the Anguta lobby, specifically) is functional; some entities besides Player now keep track of the continent they possess, a necessary compromise for proximity ops

* repair rearm silos (Anguta courtyard East) demonstrate operational behavior when lattice benefits are active

* proximity terminals may now juggle multiple targets that move in and out of range and change validity over time

* previous rebase; preparing for special location + offset calculations for utilities

* working location-based proximity repair terminals for the lodestar, utilizing new fields in the vehicle definition, new configuration method in the utilities, and new calculations for Vector3 entities; some comments and tests

* separated ProximityTarget; updated existing terminals; restored defaults; preparing to fix tests

* tests involving the proximity unit workflow

* dismantling a portion of the proximity terminal machinery that is no longer necessary and only poses risk to the system; removing temporary code used to quickly test vehicle silo repairs
This commit is contained in:
Fate-JH 2018-12-23 21:09:12 -05:00 committed by GitHub
parent c4c8609238
commit 961ae1b93b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 1320 additions and 888 deletions

View file

@ -18,7 +18,7 @@ import net.psforever.objects.serverobject.resourcesilo.ResourceSiloDefinition
import net.psforever.objects.serverobject.turret.{TurretDefinition, TurretUpgrade}
import net.psforever.objects.vehicles.{DestroyedVehicle, SeatArmorRestriction, UtilityType}
import net.psforever.objects.vital.{DamageType, StandardResolutions}
import net.psforever.types.{CertificationType, PlanetSideEmpire}
import net.psforever.types.{CertificationType, PlanetSideEmpire, Vector3}
import scala.collection.mutable
import scala.concurrent.duration._
@ -920,9 +920,13 @@ object GlobalDefinitions {
val medical_terminal = new MedicalTerminalDefinition(529)
val pad_landing = new RepairRearmSiloDefinition(719)
val portable_med_terminal = new MedicalTerminalDefinition(689)
val repair_silo = new RepairRearmSiloDefinition(729)
val pad_landing_frame = new MedicalTerminalDefinition(618)
val pad_landing_tower_frame = new MedicalTerminalDefinition(619)
val repair_silo = new MedicalTerminalDefinition(729)
val spawn_pad = new VehicleSpawnPadDefinition
@ -938,33 +942,18 @@ object GlobalDefinitions {
val secondary_capture = new CaptureTerminalDefinition(751) // Tower CC
val lodestar_repair_terminal = new OrderTerminalDefinition { //TODO wrong object class
override def ObjectId : Int = 461
}
val lodestar_repair_terminal = new MedicalTerminalDefinition(461)
val multivehicle_rearm_terminal = new _OrderTerminalDefinition(576) {
Name = "multivehicle_rearm_terminal"
Page += 3 -> _OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition)
Page += 4 -> _OrderTerminalDefinition.VehicleLoadoutPage()
}
val multivehicle_rearm_terminal = new _OrderTerminalDefinition(576)
val bfr_rearm_terminal = new _OrderTerminalDefinition(142) {
Name = "bfr_rearm_terminal"
Page += 3 -> _OrderTerminalDefinition.EquipmentPage(Map.empty[String, ()=>Equipment]) //TODO add stock to page
Page += 4 -> _OrderTerminalDefinition.VehicleLoadoutPage()
}
val bfr_rearm_terminal = new _OrderTerminalDefinition(142)
val manned_turret = new TurretDefinition(480) {
Name = "manned_turret"
MaxHealth = 3600
Weapons += 1 -> new mutable.HashMap()
Weapons(1) += TurretUpgrade.None -> phalanx_sgl_hevgatcan
Weapons(1) += TurretUpgrade.AVCombo -> phalanx_avcombo
Weapons(1) += TurretUpgrade.FlakCombo -> phalanx_flakcombo
MountPoints += 1 -> 0
FactionLocked = true
ReserveAmmunition = false
}
val air_rearm_terminal = new _OrderTerminalDefinition(42)
val ground_rearm_terminal = new _OrderTerminalDefinition(384)
val manned_turret = new TurretDefinition(480)
initMiscellaneous()
/**
* Given a faction, provide the standard assault melee weapon.
@ -5411,7 +5400,9 @@ object GlobalDefinitions {
lodestar.MountPoints += 2 -> 1
lodestar.Cargo += 1 -> new CargoDefinition()
lodestar.Utilities += 2 -> UtilityType.lodestar_repair_terminal
lodestar.UtilityOffset += 2 -> Vector3(0, 20, 0)
lodestar.Utilities += 3 -> UtilityType.lodestar_repair_terminal
lodestar.UtilityOffset += 3 -> Vector3(0, -20, 0)
lodestar.Utilities += 4 -> UtilityType.multivehicle_rearm_terminal
lodestar.Utilities += 5 -> UtilityType.multivehicle_rearm_terminal
lodestar.Utilities += 6 -> UtilityType.bfr_rearm_terminal
@ -5599,4 +5590,92 @@ object GlobalDefinitions {
internal_router_telepad_deployable.DeployTime = Duration.create(1, "ms")
internal_router_telepad_deployable.Packet = new InternalTelepadDeployableConverter
}
/**
* Initialize `Miscellaneous` globals.
*/
private def initMiscellaneous() : Unit = {
adv_med_terminal.Name = "adv_med_terminal"
adv_med_terminal.Interval = 500
adv_med_terminal.HealAmount = 8
adv_med_terminal.ArmorAmount = 15
adv_med_terminal.UseRadius = 0.75f
adv_med_terminal.TargetValidation += ProximityTarget.Player -> ProximityTerminalControl.Validation.Medical
crystals_health_a.Name = "crystals_health_a"
crystals_health_a.Interval = 500
crystals_health_a.HealAmount = 4
crystals_health_a.UseRadius = 5
crystals_health_a.TargetValidation += ProximityTarget.Player -> ProximityTerminalControl.Validation.HealthCrystal
crystals_health_b.Name = "crystals_health_b"
crystals_health_b.Interval = 500
crystals_health_b.HealAmount = 4
crystals_health_b.UseRadius = 1.3f
crystals_health_b.TargetValidation += ProximityTarget.Player -> ProximityTerminalControl.Validation.HealthCrystal
medical_terminal.Name = "medical_terminal"
medical_terminal.Interval = 500
medical_terminal.HealAmount = 5
medical_terminal.ArmorAmount = 10
medical_terminal.UseRadius = 0.75f
medical_terminal.TargetValidation += ProximityTarget.Player -> ProximityTerminalControl.Validation.Medical
portable_med_terminal.Name = "portable_med_terminal"
portable_med_terminal.Interval = 500
portable_med_terminal.HealAmount = 5
portable_med_terminal.ArmorAmount = 10
portable_med_terminal.UseRadius = 3
portable_med_terminal.TargetValidation += ProximityTarget.Player -> ProximityTerminalControl.Validation.Medical
pad_landing_frame.Name = "pad_landing_frame"
pad_landing_frame.Interval = 1000
pad_landing_frame.HealAmount = 60
pad_landing_frame.UseRadius = 20
pad_landing_frame.TargetValidation += ProximityTarget.Aircraft -> ProximityTerminalControl.Validation.PadLanding
pad_landing_tower_frame.Name = "pad_landing_tower_frame"
pad_landing_tower_frame.Interval = 1000
pad_landing_tower_frame.HealAmount = 60
pad_landing_tower_frame.UseRadius = 20
pad_landing_tower_frame.TargetValidation += ProximityTarget.Aircraft -> ProximityTerminalControl.Validation.PadLanding
repair_silo.Name = "repair_silo"
repair_silo.Interval = 1000
repair_silo.HealAmount = 60
repair_silo.UseRadius = 20
repair_silo.TargetValidation += ProximityTarget.Vehicle -> ProximityTerminalControl.Validation.RepairSilo
lodestar_repair_terminal.Name = "lodestar_repair_terminal"
lodestar_repair_terminal.Interval = 1000
lodestar_repair_terminal.HealAmount = 60
lodestar_repair_terminal.UseRadius = 20
lodestar_repair_terminal.TargetValidation += ProximityTarget.Vehicle -> ProximityTerminalControl.Validation.RepairSilo
multivehicle_rearm_terminal.Name = "multivehicle_rearm_terminal"
multivehicle_rearm_terminal.Page += 3 -> _OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition)
multivehicle_rearm_terminal.Page += 4 -> _OrderTerminalDefinition.VehicleLoadoutPage()
bfr_rearm_terminal.Name = "bfr_rearm_terminal"
bfr_rearm_terminal.Page += 3 -> _OrderTerminalDefinition.EquipmentPage(Map.empty[String, ()=>Equipment]) //TODO add stock to page
bfr_rearm_terminal.Page += 4 -> _OrderTerminalDefinition.VehicleLoadoutPage()
air_rearm_terminal.Name = "air_rearm_terminal"
air_rearm_terminal.Page += 3 -> _OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition)
air_rearm_terminal.Page += 4 -> _OrderTerminalDefinition.VehicleLoadoutPage()
ground_rearm_terminal.Name = "ground_rearm_terminal"
ground_rearm_terminal.Page += 3 -> _OrderTerminalDefinition.EquipmentPage(EquipmentTerminalDefinition.vehicleAmmunition)
ground_rearm_terminal.Page += 4 -> _OrderTerminalDefinition.VehicleLoadoutPage()
manned_turret.Name = "manned_turret"
manned_turret.MaxHealth = 3600
manned_turret.Weapons += 1 -> new mutable.HashMap()
manned_turret.Weapons(1) += TurretUpgrade.None -> phalanx_sgl_hevgatcan
manned_turret.Weapons(1) += TurretUpgrade.AVCombo -> phalanx_avcombo
manned_turret.Weapons(1) += TurretUpgrade.FlakCombo -> phalanx_flakcombo
manned_turret.MountPoints += 1 -> 0
manned_turret.FactionLocked = true
manned_turret.ReserveAmmunition = false
}
}

View file

@ -8,6 +8,7 @@ import net.psforever.objects.loadouts.Loadout
import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.objects.vital.{DamageResistanceModel, Vitality}
import net.psforever.objects.zones.ZoneAware
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types._
@ -18,7 +19,8 @@ class Player(private val core : Avatar) extends PlanetSideGameObject
with FactionAffinity
with Vitality
with ResistanceProfile
with Container {
with Container
with ZoneAware {
private var alive : Boolean = false
private var backpack : Boolean = false
private var health : Int = 0

View file

@ -1,6 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects
import akka.actor.ActorRef
import net.psforever.objects.definition.VehicleDefinition
import net.psforever.objects.equipment.{Equipment, EquipmentSize}
import net.psforever.objects.inventory.{Container, GridInventory, InventoryTile}
@ -10,6 +11,7 @@ import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.serverobject.deploy.Deployment
import net.psforever.objects.vehicles._
import net.psforever.objects.vital.{DamageResistanceModel, StandardResistanceProfile, Vitality}
import net.psforever.objects.zones.ZoneAware
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.PlanetSideEmpire
@ -65,6 +67,7 @@ import scala.annotation.tailrec
*/
class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServerObject
with FactionAffinity
with ZoneAware
with Mountable
with MountedWeapons
with Deployment
@ -80,6 +83,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
private var jammered : Boolean = false
private var cloaked : Boolean = false
private var capacitor : Int = 0
private var continent : String = "home2" //the zone id
/**
* Permissions control who gets to access different parts of the vehicle;
@ -513,6 +517,32 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends PlanetSideServ
*/
def Definition : VehicleDefinition = vehicleDef
override def Continent : String = continent
override def Continent_=(zoneId : String) : String = {
continent = zoneId
Continent
}
def canEqual(other: Any): Boolean = other.isInstanceOf[Vehicle]
override def equals(other : Any) : Boolean = other match {
case that: Vehicle =>
(that canEqual this) &&
hashCode() == that.hashCode()
case _ =>
false
}
override def hashCode() : Int = {
Actor match {
case ActorRef.noSender =>
super.hashCode()
case actor =>
actor.hashCode()
}
}
/**
* Override the string representation to provide additional information.
* @return the string output
@ -600,7 +630,12 @@ object Vehicle {
vehicle.cargoHolds = vdef.Cargo.map({ case(num, definition) => num -> Cargo(definition)}).toMap
//create utilities
vehicle.utilities = vdef.Utilities.map({ case(num, util) => num -> Utility(util, vehicle) }).toMap
vehicle.utilities = vdef.Utilities.map({
case(num, util) =>
val obj = Utility(util, vehicle)
obj().LocationOffset = vdef.UtilityOffset.get(num)
num -> obj
}).toMap
//trunk
vdef.TrunkSize match {
case InventoryTile.None => ;

View file

@ -6,6 +6,7 @@ import net.psforever.objects.inventory.InventoryTile
import net.psforever.objects.vehicles.{DestroyedVehicle, UtilityType}
import net.psforever.objects.vital._
import net.psforever.objects.vital.resistance.ResistanceProfileMutators
import net.psforever.types.Vector3
import scala.collection.mutable
import scala.concurrent.duration._
@ -29,6 +30,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
private val weapons : mutable.HashMap[Int, ToolDefinition] = mutable.HashMap[Int, ToolDefinition]()
private var deployment : Boolean = false
private val utilities : mutable.HashMap[Int, UtilityType.Value] = mutable.HashMap()
private val utilityOffsets : mutable.HashMap[Int, Vector3] = mutable.HashMap()
private var deploymentTime_Deploy : Int = 0 //ms
private var deploymentTime_Undeploy : Int = 0 //ms
private var trunkSize : InventoryTile = InventoryTile.None
@ -88,9 +90,10 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
Deployment
}
def Utilities : mutable.HashMap[Int, UtilityType.Value] = utilities
def UtilityOffset : mutable.HashMap[Int, Vector3] = utilityOffsets
def DeployTime : Int = deploymentTime_Deploy
def DeployTime_=(dtime : Int) : Int = {

View file

@ -1,12 +1,12 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject
import net.psforever.objects.Player
import net.psforever.objects.{PlanetSideGameObject, Player}
//temporary location for these messages
object CommonMessages {
final case class Use(player : Player)
final case class Unuse(player : Player)
final case class Use(player : Player, data : Option[Any] = None)
final case class Unuse(player : Player, data : Option[Any] = None)
final case class Hack(player : Player)
final case class ClearHack()
}

View file

@ -4,12 +4,15 @@ package net.psforever.objects.serverobject
import akka.actor.ActorRef
import net.psforever.objects.PlanetSideGameObject
import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.zones.ZoneAware
/**
* An object layered on top of the standard game object class that maintains an internal `ActorRef`.
* A measure of synchronization can be managed using this `Actor`.
*/
abstract class PlanetSideServerObject extends PlanetSideGameObject with FactionAffinity {
abstract class PlanetSideServerObject extends PlanetSideGameObject
with FactionAffinity
with ZoneAware {
private var actor = ActorRef.noSender
/**
@ -30,4 +33,8 @@ abstract class PlanetSideServerObject extends PlanetSideGameObject with Faction
}
actor
}
def Continent : String = "nowhere"
def Continent_=(zone : String) = Continent
}

View file

@ -1,8 +1,9 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.structures
import net.psforever.objects.Vehicle
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.types.PlanetSideEmpire
import net.psforever.types.{PlanetSideEmpire, Vector3}
/**
* Amenities are elements of the game that belong to other elements of the game.<br>
@ -15,7 +16,10 @@ import net.psforever.types.PlanetSideEmpire
* @see `FactionAffinity`
*/
abstract class Amenity extends PlanetSideServerObject {
/** what other entity has authority over this amenity; usually either a building or a vehicle */
private var owner : PlanetSideServerObject = Building.NoBuilding
/** if the entity exists at a specific position relative to the owner's position */
private var offset : Option[Vector3] = None
def Faction : PlanetSideEmpire.Value = Owner.Faction
@ -36,6 +40,26 @@ abstract class Amenity extends PlanetSideServerObject {
owner = obj.asInstanceOf[PlanetSideServerObject]
Owner
}
def LocationOffset : Vector3 = offset.getOrElse(Vector3.Zero)
def LocationOffset_=(off : Vector3) : Vector3 = LocationOffset_=(Some(off))
def LocationOffset_=(off : Option[Vector3]) : Vector3 = {
off match {
case Some(Vector3.Zero) =>
offset = None
case _ =>
offset = off
}
LocationOffset
}
override def Continent = Owner match {
case o : Building => o.Zone.Id
case o : Vehicle => o.Continent
case _ => super.Continent
}
}
object Amenity {

View file

@ -48,6 +48,10 @@ class Building(private val mapId : Int, private val zone : Zone, private val bui
def BuildingType : StructureType.Value = buildingType
override def Continent : String = zone.Id
override def Continent_=(zone : String) : String = Continent
def Definition: ObjectDefinition = Building.BuildingDefinition
}

View file

@ -1,28 +1,40 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.terminals
import scala.concurrent.duration.{Duration, FiniteDuration}
/**
* The definition for any `Terminal` that is of a type "medical_terminal".
* This includes the functionality of the formal medical terminals and some of the cavern crystals.
* Do not confuse the game's internal "medical_terminal" object category and the actual `medical_terminal` object (529).
*/
class MedicalTerminalDefinition(objectId : Int) extends TerminalDefinition(objectId) with ProximityDefinition {
Name = if(objectId == 38) {
"adv_med_terminal"
private var interval : FiniteDuration = Duration(0, "seconds")
private var healAmount : Int = 0
private var armorAmount : Int = 0
def Interval : FiniteDuration = interval
def Interval_=(amount : Int) : FiniteDuration = {
Interval_=(Duration(amount, "milliseconds"))
}
else if(objectId == 225) {
"crystals_health_a"
def Interval_=(amount : FiniteDuration) : FiniteDuration = {
interval = amount
Interval
}
else if(objectId == 226) {
"crystals_health_b"
def HealAmount : Int = healAmount
def HealAmount_=(amount : Int) : Int = {
healAmount = amount
HealAmount
}
else if(objectId == 529) {
"medical_terminal"
}
else if(objectId == 689) {
"portable_med_terminal"
}
else {
throw new IllegalArgumentException("medical terminal must be either object id 38, 225, 226, 529, or 689")
def ArmorAmount : Int = armorAmount
def ArmorAmount_=(amount : Int) : Int = {
armorAmount = amount
ArmorAmount
}
}

View file

@ -1,9 +1,11 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.terminals
import net.psforever.objects.Player
import net.psforever.objects.{PlanetSideGameObject, Player}
import net.psforever.packet.game.ItemTransactionMessage
import scala.collection.mutable
/**
* The definition for any `Terminal` that possesses a proximity-based effect.
* This includes the limited proximity-based functionality of the formal medical terminals
@ -11,5 +13,30 @@ import net.psforever.packet.game.ItemTransactionMessage
* Objects created by this definition being linked by their use of `ProximityTerminalUseMessage`.
*/
trait ProximityDefinition {
private var useRadius : Float = 0f //TODO belongs on a wider range of object definitions
private val targetValidation : mutable.HashMap[ProximityTarget.Value, (PlanetSideGameObject)=>Boolean] = new mutable.HashMap[ProximityTarget.Value, (PlanetSideGameObject)=>Boolean]()
def UseRadius : Float = useRadius
def UseRadius_=(radius : Float) : Float = {
useRadius = radius
UseRadius
}
def TargetValidation : mutable.HashMap[ProximityTarget.Value, (PlanetSideGameObject)=>Boolean] = targetValidation
def Validations : Seq[(PlanetSideGameObject)=>Boolean] = {
targetValidation.headOption match {
case Some(_) =>
targetValidation.values.toSeq
case None =>
Seq(ProximityDefinition.Invalid)
}
}
def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = Terminal.NoDeal()
}
object ProximityDefinition {
protected val Invalid : (PlanetSideGameObject=>Boolean) = (_ : PlanetSideGameObject) => false
}

View file

@ -0,0 +1,15 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.terminals
/**
* A classification of the target of this terminal's interactions.
* Arbitrary, but useful.
*/
object ProximityTarget extends Enumeration {
val
Aircraft,
Equipment,
Player,
Vehicle
= Value
}

View file

@ -1,6 +1,10 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.terminals
import net.psforever.objects.serverobject.structures.Amenity
import net.psforever.types.Vector3
import services.Service
/**
* A server object that is a "terminal" that can be accessed for amenities and services,
* triggered when a certain distance from the unit itself (proximity-based).<br>
@ -35,4 +39,33 @@ object ProximityTerminal {
obj.Actor = context.actorOf(Props(classOf[ProximityTerminalControl], obj), s"${tdef.Name}_$id")
obj
}
/**
* Instantiate an configure a `Terminal` object, with position coordinates.
* @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
* @param id the unique id that will be assigned to this entity
* @param context a context to allow the object to properly set up `ActorSystem` functionality
* @return the `Terminal` object
*/
def Constructor(tdef : TerminalDefinition with ProximityDefinition, pos : Vector3)(id : Int, context : ActorContext) : Terminal = {
import akka.actor.Props
val obj = ProximityTerminal(tdef)
obj.Position = pos
obj.Actor = context.actorOf(Props(classOf[ProximityTerminalControl], obj), s"${tdef.Name}_$id")
obj
}
/**
* Assemble some logic for a provided owned object after both it ands its owner have been constructed.
* @param obj an `Amenity` object;
* anticipating a `Terminal` object using this same definition
* @param context hook to the local `Actor` system
*/
def Setup(obj : Amenity, context : ActorContext) : Unit = {
import akka.actor.{ActorRef, Props}
if(obj.Actor == ActorRef.noSender) {
obj.Actor = context.actorOf(Props(classOf[ProximityTerminalControl], obj), s"${obj.Definition.Name}_${obj.GUID.guid}")
obj.Actor ! Service.Startup()
}
}
}

View file

@ -1,9 +1,14 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.terminals
import akka.actor.Actor
import akka.actor.{Actor, ActorRef, Cancellable}
import net.psforever.objects._
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import services.{Service, ServiceManager}
import scala.collection.mutable
import scala.concurrent.duration._
/**
* An `Actor` that handles messages being dispatched to a specific `ProximityTerminal`.
@ -11,21 +16,155 @@ import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffi
* it returns the same type of messages - wrapped in a `TerminalMessage` - to the `sender`.
* @param term the proximity unit (terminal)
*/
class ProximityTerminalControl(term : Terminal with ProximityUnit) extends Actor with FactionAffinityBehavior.Check with ProximityUnit.Use {
class ProximityTerminalControl(term : Terminal with ProximityUnit) extends Actor with FactionAffinityBehavior.Check {
var service : ActorRef = ActorRef.noSender
var terminalAction : Cancellable = DefaultCancellable.obj
val callbacks : mutable.ListBuffer[ActorRef] = new mutable.ListBuffer[ActorRef]()
val log = org.log4s.getLogger
def FactionObject : FactionAffinity = term
def TerminalObject : Terminal with ProximityUnit = term
def receive : Receive = checkBehavior
.orElse(proximityBehavior)
def receive : Receive = Start
def Start : Receive = checkBehavior
.orElse {
case Service.Startup() =>
ServiceManager.serviceManager ! ServiceManager.Lookup("local")
case ServiceManager.LookupResult("local", ref) =>
service = ref
context.become(Run)
case _ => ;
}
def Run : Receive = checkBehavior
.orElse {
case CommonMessages.Use(_, Some(target : PlanetSideGameObject)) =>
if(term.Definition.asInstanceOf[ProximityDefinition].Validations.exists(p => p(target))) {
Use(target, term.Continent, sender)
}
case CommonMessages.Use(_, Some((target : PlanetSideGameObject, callback : ActorRef))) =>
if(term.Definition.asInstanceOf[ProximityDefinition].Validations.exists(p => p(target))) {
Use(target, term.Continent, callback)
}
case CommonMessages.Use(_, _) =>
log.warn(s"unexpected format for CommonMessages.Use in this context")
case CommonMessages.Unuse(_, Some(target : PlanetSideGameObject)) =>
Unuse(target, term.Continent)
case CommonMessages.Unuse(_, _) =>
log.warn(s"unexpected format for CommonMessages.Unuse in this context")
case ProximityTerminalControl.TerminalAction() =>
val proxDef = term.Definition.asInstanceOf[ProximityDefinition]
val validateFunc : PlanetSideGameObject=>Boolean = term.Validate(proxDef.UseRadius * proxDef.UseRadius, proxDef.Validations)
val callbackList = callbacks.toList
term.Targets.zipWithIndex.foreach({ case((target, index)) =>
if(validateFunc(target)) {
callbackList.lift(index) match {
case Some(cback) =>
cback ! ProximityUnit.Action(term, target)
case None =>
log.error(s"improper callback registered for $target on $term in zone ${term.Owner.Continent}; this may be recoverable")
}
}
else {
Unuse(target, term.Continent)
}
})
case CommonMessages.Hack(player) =>
term.HackedBy = player
sender ! true
case CommonMessages.ClearHack() =>
term.HackedBy = None
case _ => ;
case ProximityUnit.Action(_, _) =>
//reserved
case msg =>
log.warn(s"unexpected message $msg")
}
def Use(target : PlanetSideGameObject, zone : String, callback : ActorRef) : Unit = {
val hadNoUsers = term.NumberUsers == 0
if(term.AddUser(target)) {
log.info(s"ProximityTerminal.Use: unit ${term.Definition.Name}@${term.GUID.guid} will act on $target")
//add callback
callbacks += callback
//activation
if(term.NumberUsers == 1 && hadNoUsers) {
val medDef = term.Definition.asInstanceOf[MedicalTerminalDefinition]
import scala.concurrent.ExecutionContext.Implicits.global
terminalAction.cancel
terminalAction = context.system.scheduler.schedule(500 milliseconds, medDef.Interval, self, ProximityTerminalControl.TerminalAction())
service ! Terminal.StartProximityEffect(term)
}
}
else {
log.warn(s"ProximityTerminal.Use: $target was rejected by unit ${term.Definition.Name}@${term.GUID.guid}")
}
}
def Unuse(target : PlanetSideGameObject, zone : String) : Unit = {
val whereTarget = term.Targets.indexWhere(_ eq target)
val previousUsers = term.NumberUsers
val hadUsers = previousUsers > 0
if(whereTarget > -1 && term.RemoveUser(target)) {
log.info(s"ProximityTerminal.Unuse: unit ${term.Definition.Name}@${term.GUID.guid} will cease operation on $target")
//remove callback
callbacks.remove(whereTarget)
//de-activation (global / local)
if(term.NumberUsers == 0 && hadUsers) {
terminalAction.cancel
service ! Terminal.StopProximityEffect(term)
}
}
else {
log.debug(s"ProximityTerminal.Unuse: target by proximity $target is not known to $term, though the unit tried to 'Unuse' it")
}
}
override def toString : String = term.Definition.Name
}
object ProximityTerminalControl {
object Validation {
def Medical(target : PlanetSideGameObject) : Boolean = target match {
case p : Player =>
p.Health > 0 && (p.Health < p.MaxHealth || p.Armor < p.MaxArmor)
case _ =>
false
}
def HealthCrystal(target : PlanetSideGameObject) : Boolean = target match {
case p : Player =>
p.Health > 0 && p.Health < p.MaxHealth
case _ =>
false
}
def RepairSilo(target : PlanetSideGameObject) : Boolean = target match {
case v : Vehicle =>
!GlobalDefinitions.isFlightVehicle(v.Definition) && v.Health > 0 && v.Health < v.MaxHealth
case _ =>
false
}
def PadLanding(target : PlanetSideGameObject) : Boolean = target match {
case v : Vehicle =>
GlobalDefinitions.isFlightVehicle(v.Definition) && v.Health > 0 && v.Health < v.MaxHealth
case _ =>
false
}
}
private case class TerminalAction()
}

View file

@ -1,9 +1,10 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.terminals
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.objects.PlanetSideGameObject
import net.psforever.types.Vector3
import scala.collection.mutable
/**
* A server object that provides a service, triggered when a certain distance from the unit itself (proximity-based).
@ -16,45 +17,78 @@ trait ProximityUnit {
/**
* A list of targets that are currently affected by this proximity unit.
*/
private var targets : Set[PlanetSideGUID] = Set.empty
private var targets : mutable.ListBuffer[PlanetSideGameObject] = mutable.ListBuffer[PlanetSideGameObject]()
def Targets : Seq[PlanetSideGameObject] = targets toList
def NumberUsers : Int = targets.size
def AddUser(player_guid : PlanetSideGUID) : Int = {
targets += player_guid
NumberUsers
/**
* Accept a new target for this unit.
* @param target the new target
* @return `true`, if the entrant has been added and is new to the list;
* `false` if the entrant is already in the list or can not be added
*/
def AddUser(target : PlanetSideGameObject) : Boolean = {
val alreadyContains = targets.contains(target)
if(!alreadyContains) {
targets += target
targets.contains(target)
}
else {
false
}
}
def RemoveUser(player_guid : PlanetSideGUID) : Int = {
targets -= player_guid
NumberUsers
/**
* Remove an existing target for this unit.
* @param target the target
* @return `true`, if the submitted entity was previously in the list but is not longer in the list;
* `false`, if the submitted entity was never in the list or can not be removed
*/
def RemoveUser(target : PlanetSideGameObject) : Boolean = {
val alreadyContains = targets.contains(target)
if(alreadyContains) {
targets -= target
!targets.contains(target)
}
else {
false
}
}
/**
* Confirm whether the entity is a valid target for the effects of this unit.
* @param target the submitted entity
* @return `true`, if the entity passes the validation tests;
* `false`, otherwise
*/
def Validate(target : PlanetSideGameObject) : Boolean = {
val proxDef = Definition.asInstanceOf[ProximityDefinition]
val radius = proxDef.UseRadius * proxDef.UseRadius
val validation = proxDef.Validations
Validate(radius, validation)(target)
}
/**
* Confirm whether the entity is a valid target for the effects of this unit.
* Curried to accept parameters for the tests separately from the entity to be tested.
* In general, the two requirements beyond the custom validations involve
* distance (from the unit)
* and inclusiveness (known to the unit beforehand).
* @param radius the squared minimum activation distance
* @param validations the custom tests that the entity must pass to be considered valid;
* in general, regardless of the type of the target, any of the tests must be passed
* @param target the submitted entity
* @return `true`, if the entity passes the validation tests;
* `false`, otherwise
*/
def Validate(radius : Float, validations : Seq[(PlanetSideGameObject)=>Boolean])(target : PlanetSideGameObject) : Boolean = {
//org.log4s.getLogger("ProximityUnit").info(s"vehicle: ${Owner.Position}, terminal: $Position, target: ${target.Position}, toOwner: ${Vector3.Distance(Position, Owner.Position)}, toTarget: ${Vector3.Distance(Position, target.Position)}")
targets.contains(target) && Vector3.DistanceSquared(Position, target.Position) <= radius && validations.exists(p => p(target))
}
}
object ProximityUnit {
import akka.actor.Actor
/**
* A mixin `trait` for an `Actor`'s `PartialFunction` that handles messages,
* in this case handling messages that controls the telegraphed state of the `ProximityUnit` object as the number of users changes.
*/
trait Use {
this : Actor =>
def TerminalObject : Terminal with ProximityUnit
val proximityBehavior : Receive = {
case CommonMessages.Use(player) =>
val hadNoUsers = TerminalObject.NumberUsers == 0
if(TerminalObject.AddUser(player.GUID) == 1 && hadNoUsers) {
sender ! TerminalMessage(player, null, Terminal.StartProximityEffect(TerminalObject))
}
case CommonMessages.Unuse(player) =>
val hadUsers = TerminalObject.NumberUsers > 0
if(TerminalObject.RemoveUser(player.GUID) == 0 && hadUsers) {
sender ! TerminalMessage(player, null, Terminal.StopProximityEffect(TerminalObject))
}
}
}
final case class Action(terminal : Terminal with ProximityUnit, target : PlanetSideGameObject)
}

View file

@ -1,44 +0,0 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.terminals
import net.psforever.objects.Player
import net.psforever.objects.inventory.InventoryItem
import net.psforever.objects.loadouts.VehicleLoadout
import net.psforever.objects.serverobject.terminals.EquipmentTerminalDefinition.BuildSimplifiedPattern
import net.psforever.packet.game.ItemTransactionMessage
/**
* The `Definition` for any `Terminal` that is of a type "repair_silo."
* Has both proximity-based operation and direct access purchasing power.
*/
class RepairRearmSiloDefinition(objectId : Int) extends EquipmentTerminalDefinition(objectId) with ProximityDefinition {
Name = if(objectId == 719) {
"pad_landing"
}
else if(objectId == 729) {
"repair_silo"
}
else {
throw new IllegalArgumentException("repair re-arm terminal must be either object id 719 or 729")
}
private val buyFunc : (Player, ItemTransactionMessage)=>Terminal.Exchange = EquipmentTerminalDefinition.Buy(Map.empty, Map.empty, Map.empty)
override def Buy(player: Player, msg : ItemTransactionMessage) : Terminal.Exchange = buyFunc(player, msg)
override def Loadout(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
if(msg.item_page == 4) { //Favorites tab
player.LoadLoadout(msg.unk1 + 10) match {
case Some(loadout : VehicleLoadout) =>
val weapons = loadout.visible_slots.map(entry => { InventoryItem(BuildSimplifiedPattern(entry.item), entry.index) })
val inventory = loadout.inventory.map(entry => { InventoryItem(BuildSimplifiedPattern(entry.item), entry.index) })
Terminal.VehicleLoadout(loadout.vehicle_definition, weapons, inventory)
case _ =>
Terminal.NoDeal()
}
}
else {
Terminal.NoDeal()
}
}
}

View file

@ -9,6 +9,7 @@ import net.psforever.objects.serverobject.structures.Amenity
import net.psforever.objects.serverobject.terminals._
import net.psforever.objects.serverobject.tube.{SpawnTube, SpawnTubeDefinition}
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
import net.psforever.types.Vector3
/**
* An `Enumeration` of the available vehicular utilities.<br>
@ -78,6 +79,28 @@ class Utility(util : UtilityType.Value, vehicle : Vehicle) {
object Utility {
type UtilLogic = (Amenity, ActorContext)=>Unit
/**
* Embedded (owned) entities are known in relation to their parent entity.
* These overrides to the `Position` method and the `Orientation` method reflect this.
*/
sealed trait UtilityWorldEntity {
this : Amenity =>
override def Position : Vector3 = {
val oPos = Owner.Position
(Owner, LocationOffset) match {
case (_, Vector3.Zero) =>
oPos
case (_ : Vehicle, v) =>
oPos + v.Rz(Orientation.z + 90)
case _ =>
oPos
}
}
override def Orientation : Vector3 = Owner.Orientation
}
/**
* Overloaded constructor.
* @param util the type of the `Amenity` object to be created
@ -99,7 +122,7 @@ object Utility {
case UtilityType.bfr_rearm_terminal =>
new TerminalUtility(GlobalDefinitions.bfr_rearm_terminal)
case UtilityType.lodestar_repair_terminal =>
new TerminalUtility(GlobalDefinitions.lodestar_repair_terminal)
new ProximityTerminalUtility(GlobalDefinitions.lodestar_repair_terminal)
case UtilityType.matrix_terminalc =>
new TerminalUtility(GlobalDefinitions.matrix_terminalc)
case UtilityType.multivehicle_rearm_terminal =>
@ -118,22 +141,27 @@ object Utility {
* Override for `SpawnTube` objects so that they inherit the spatial characteristics of their `Owner`.
* @param tubeDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
*/
class SpawnTubeUtility(tubeDef : SpawnTubeDefinition) extends SpawnTube(tubeDef) {
override def Position = Owner.Position
override def Orientation = Owner.Orientation
}
class SpawnTubeUtility(tubeDef : SpawnTubeDefinition) extends SpawnTube(tubeDef) with UtilityWorldEntity
/**
* Override for `Terminal` objects so that they inherit the spatial characteristics of their `Owner`.
* Override for a `Terminal` object so that it inherits the spatial characteristics of its `Owner`.
* @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
*/
class TerminalUtility(tdef : TerminalDefinition) extends Terminal(tdef) {
override def Position = Owner.Position
override def Orientation = Owner.Orientation
}
class TerminalUtility(tdef : TerminalDefinition) extends Terminal(tdef) with UtilityWorldEntity
/**
* na
* Override for a `Terminal` object so that it inherits the spatial characteristics of its `Owner`.
* The `Terminal` `Utility` produced has proximity effects.
* @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
*/
class ProximityTerminalUtility(tdef : TerminalDefinition) extends Terminal(tdef)
with UtilityWorldEntity
with ProximityUnit
/**
* Override for a `Terminal` object so that it inherits the spatial characteristics of its `Owner`.
* The `Terminal` `Utility` produced dispenses a specific item
* that retain knowledge of the `Owner` of the `Terminal` that dispensed it.
* @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
*/
class TeleportPadTerminalUtility(tdef : TerminalDefinition) extends TerminalUtility(tdef) {
@ -192,7 +220,7 @@ object Utility {
case UtilityType.bfr_rearm_terminal =>
_OrderTerminalDefinition.Setup
case UtilityType.lodestar_repair_terminal =>
OrderTerminalABDefinition.Setup //TODO wrong
ProximityTerminal.Setup
case UtilityType.matrix_terminalc =>
MatrixTerminalDefinition.Setup
case UtilityType.multivehicle_rearm_terminal =>

View file

@ -13,12 +13,15 @@ import net.psforever.objects.guid.actor.UniqueNumberSystem
import net.psforever.objects.guid.selector.RandomSelector
import net.psforever.objects.guid.source.LimitedNumberSource
import net.psforever.objects.inventory.Container
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
import net.psforever.objects.serverobject.structures.{Amenity, Building}
import net.psforever.objects.serverobject.terminals.ProximityUnit
import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.serverobject.turret.FacilityTurret
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.Vector3
import services.Service
import scala.collection.concurrent.TrieMap
import scala.collection.mutable.ListBuffer
@ -366,6 +369,13 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
case silo : ResourceSilo =>
silo.Actor ! "startup"
}
//proximity terminals need to startup
buildings.values
.flatMap(_.Amenities.filter(_.isInstanceOf[ProximityUnit]))
.collect {
case o : PlanetSideServerObject =>
o.Actor ! Service.Startup()
}
}
private def CreateSpawnGroups() : Unit = {

View file

@ -0,0 +1,16 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.zones
/**
* The object must be able to recall on which of the defined game worlds (zones) that it exists on command.
* The game world identifier string produced should be equivalent to a `Zone.Id` string for some equivalent `Zone` object.
* The identifier "nowhere" is recommended as the default invalid location.
* @see `InterstellarCluster`
* @see `WorldEntity`
* @see `Zone`
*/
trait ZoneAware {
def Continent : String
def Continent_=(zone : String) : String
}

View file

@ -46,11 +46,49 @@ final case class Vector3(x : Float,
* @return a new `Vector3` object with only two of the components of the original
*/
def xy : Vector3 = Vector3(x, y, 0)
/**
* Perform the x-axis rotation of this `Vector3` element where the angle of rotation is assumed in degrees.
* For chaining rotations.
* @see `Vector3.Rx`
* @param ang a rotation angle
* @return the rotated vector
*/
def Rx(ang : Float) : Vector3 = Vector3.Rx(this, ang)
/**
* Perform the y-axis rotation of this `Vector3` element where the angle of rotation is assumed in degrees.
* For chaining rotations.
* @see `Vector3.Ry`
* @param ang a rotation angle
* @return the rotated vector
*/
def Ry(ang : Float) : Vector3 = Vector3.Ry(this, ang)
/**
* Perform the z-axis rotation of this `Vector3` element where the angle of rotation is assumed in degrees.
* For chaining rotations.
* @see `Vector3.Rz`
* @param ang a rotation angle
* @return the rotated vector
*/
def Rz(ang : Float) : Vector3 = Vector3.Rz(this, ang)
}
object Vector3 {
final val Zero : Vector3 = Vector3(0f, 0f, 0f)
private def closeToInsignificance(d : Float, epsilon : Float = 10f) : Float = {
val ulp = math.ulp(epsilon)
math.signum(d) match {
case -1f =>
val n = math.abs(d)
val p = math.abs(n - n.toInt)
if(p < ulp || d > ulp) d + p else d
case _ =>
val p = math.abs(d - d.toInt)
if(p < ulp || d < ulp) d - p else d
}
}
implicit val codec_pos : Codec[Vector3] = (
("x" | newcodecs.q_float(0.0, 8192.0, 20)) ::
("y" | newcodecs.q_float(0.0, 8192.0, 20)) ::
@ -208,4 +246,82 @@ object Vector3 {
def VectorProjection(vec1 : Vector3, vec2 : Vector3) : Vector3 = {
Unit(vec2) * ScalarProjection(vec1, vec2)
}
/**
* Perform the x-axis rotation of a `Vector3` element where the angle of rotation is assumed in degrees.
* @see `Vector3.RxRadians(Vector3, Double)`
* @param vec a mathematical vector representing direction
* @param ang a rotation angle, in degrees
* @return the rotated vector
*/
def Rx(vec : Vector3, ang : Float) : Vector3 = Rx(vec, math.toRadians(ang))
/**
* Perform the x-axis rotation of a `Vector3` element where the angle of rotation is assumed in radians.
* @see `Vector3.Rx(Vector3, Float)`
* @param vec a mathematical vector representing direction
* @param ang a rotation angle, in radians
* @return the rotated vector
*/
def Rx(vec : Vector3, ang : Double) : Vector3 = {
val cos = math.cos(ang).toFloat
val sin = math.sin(ang).toFloat
val (x, y, z) = (vec.x, vec.y, vec.z)
Vector3(
x,
closeToInsignificance(y * cos - z * sin),
closeToInsignificance(y * sin + z * cos)
)
}
/**
* Perform the x-axis rotation of a `Vector3` element where the angle of rotation is assumed in degrees.
* @see `Vector3.Ry(Vector3, Double)`
* @param vec a mathematical vector representing direction
* @param ang a rotation angle, in degrees
* @return the rotated vector
*/
def Ry(vec : Vector3, ang : Float) : Vector3 = Ry(vec, math.toRadians(ang))
/**
* Perform the y-axis rotation of a `Vector3` element where the angle of rotation is assumed in radians.
* @see `Vector3.Ry(Vector3, Float)`
* @param vec a mathematical vector representing direction
* @param ang a rotation angle, in radians
* @return the rotated vector
*/
def Ry(vec : Vector3, ang : Double) : Vector3 = {
val cos = math.cos(ang).toFloat
val sin = math.sin(ang).toFloat
val (x, y, z) = (vec.x, vec.y, vec.z)
Vector3(
closeToInsignificance(x * cos + z * sin),
y,
closeToInsignificance(z * cos - x * sin)
)
}
/**
* Perform the x-axis rotation of a `Vector3` element where the angle of rotation is assumed in degrees.
* @see `Vector3.Rz(Vector3, Double)`
* @param vec a mathematical vector representing direction
* @param ang a rotation angle, in degrees
* @return the rotated vector
*/
def Rz(vec : Vector3, ang : Float) : Vector3 = Rz(vec, math.toRadians(ang))
/**
* Perform the z-axis rotation of a `Vector3` element where the angle of rotation is assumed in radians.
* @see `Vector3.Rz(Vector3, Float)`
* @param vec a mathematical vector representing direction
* @param ang a rotation angle, in radians
* @return the rotation vector
*/
def Rz(vec : Vector3, ang : Double) : Vector3 = {
val cos = math.cos(ang).toFloat
val sin = math.sin(ang).toFloat
val (x, y, z) = (vec.x, vec.y, vec.z)
Vector3(
closeToInsignificance(x * cos - y * sin),
closeToInsignificance(x * sin - y * cos),
z
)
}
}

View file

@ -23,7 +23,6 @@ object LocalAction {
final case class HackTemporarily(player_guid : PlanetSideGUID, continent : Zone, target : PlanetSideServerObject, unk1 : Long, duration: Int, unk2 : Long = 8L) extends Action
final case class ClearTemporaryHack(player_guid: PlanetSideGUID, target: PlanetSideServerObject with Hackable) extends Action
final case class HackCaptureTerminal(player_guid : PlanetSideGUID, continent : Zone, target : CaptureTerminal, unk1 : Long, unk2 : Long = 8L, isResecured : Boolean) extends Action
final case class ProximityTerminalEffect(player_guid : PlanetSideGUID, object_guid : PlanetSideGUID, effectState : Boolean) extends Action
final case class RouterTelepadTransport(player_guid : PlanetSideGUID, passenger_guid : PlanetSideGUID, src_guid : PlanetSideGUID, dest_guid : PlanetSideGUID) extends Action
final case class SetEmpire(object_guid: PlanetSideGUID, empire: PlanetSideEmpire.Value) extends Action
final case class ToggleTeleportSystem(player_guid : PlanetSideGUID, router : Vehicle, systemPlan : Option[(Utility.InternalTelepad, TelepadDeployable)]) extends Action

View file

@ -5,7 +5,7 @@ import akka.actor.{Actor, ActorRef, Props}
import net.psforever.objects.ce.Deployable
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
import net.psforever.objects.serverobject.structures.Building
import net.psforever.objects.serverobject.terminals.CaptureTerminal
import net.psforever.objects.serverobject.terminals.{CaptureTerminal, ProximityUnit, Terminal}
import net.psforever.objects.zones.{InterstellarCluster, Zone}
import net.psforever.objects._
import net.psforever.packet.game.{PlanetSideGUID, TriggeredEffect, TriggeredEffectLocation}
@ -111,10 +111,6 @@ class LocalService extends Actor {
LocalEvents.publish(
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.HackCaptureTerminal(target.GUID, unk1, unk2, isResecured))
)
case LocalAction.ProximityTerminalEffect(player_guid, object_guid, effectState) =>
LocalEvents.publish(
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.ProximityTerminalEffect(object_guid, effectState))
)
case LocalAction.RouterTelepadTransport(player_guid, passenger_guid, src_guid, dest_guid) =>
LocalEvents.publish(
LocalServiceResponse(s"/$forChannel/Local", player_guid, LocalResponse.RouterTelepadTransport(passenger_guid, src_guid, dest_guid))
@ -159,6 +155,16 @@ class LocalService extends Actor {
LocalServiceResponse(s"/$zone_id/Local", Service.defaultPlayerGUID, LocalResponse.HackClear(target_guid, unk1, unk2))
)
//message from ProximityTerminalControl
case Terminal.StartProximityEffect(terminal) =>
LocalEvents.publish(
LocalServiceResponse(s"/${terminal.Owner.Continent}/Local", PlanetSideGUID(0), LocalResponse.ProximityTerminalEffect(terminal.GUID, true))
)
case Terminal.StopProximityEffect(terminal) =>
LocalEvents.publish(
LocalServiceResponse(s"/${terminal.Owner.Continent}/Local", PlanetSideGUID(0), LocalResponse.ProximityTerminalEffect(terminal.GUID, false))
)
case HackCaptureActor.HackTimeoutReached(capture_terminal_guid, zone_id, _, _, hackedByFaction) =>
import scala.concurrent.ExecutionContext.Implicits.global
ask(cluster, InterstellarCluster.GetWorld(zone_id))(1 seconds).onComplete {

View file

@ -2,9 +2,13 @@
package services.vehicle
import akka.actor.{Actor, ActorRef, Props}
import net.psforever.objects.Vehicle
import net.psforever.objects.ballistics.VehicleSource
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
import net.psforever.objects.serverobject.terminals.{MedicalTerminalDefinition, ProximityUnit}
import net.psforever.objects.vital.RepairFromTerm
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.ObjectCreateMessage
import net.psforever.packet.game.{ObjectCreateMessage, PlanetSideGUID}
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
import services.vehicle.support.{TurretUpgrader, VehicleRemover}
import net.psforever.types.DriveState
@ -189,6 +193,18 @@ class VehicleService extends Actor {
VehicleServiceResponse(s"/${zone.Id}/Vehicle", Service.defaultPlayerGUID, VehicleResponse.UpdateAmsSpawnPoint(AmsSpawnPoints(zone)))
)
//from ProximityTerminalControl (?)
case ProximityUnit.Action(term, target : Vehicle) =>
val medDef = term.Definition.asInstanceOf[MedicalTerminalDefinition]
val healAmount = medDef.HealAmount
if(healAmount != 0 && term.Validate(target) && target.Health < target.MaxHealth) {
target.Health = target.Health + healAmount
target.History(RepairFromTerm(VehicleSource(target), healAmount, medDef))
VehicleEvents.publish(
VehicleServiceResponse(s"/${term.Continent}/Vehicle", PlanetSideGUID(0), VehicleResponse.PlanetsideAttribute(target.GUID, 0, target.Health))
)
}
case msg =>
log.info(s"Unhandled message $msg from $sender")
}

View file

@ -201,5 +201,44 @@ class Vector3Test extends Specification {
Vector3.VectorProjection(A, B) mustEqual Vector3(1.0384614f, 1.3846153f, 0.34615383f)
Vector3.VectorProjection(B, A) mustEqual Vector3(2.9999998f, 1.4999999f, -1.4999999f)
}
"rotate positive x-axis-vector 90-degrees around the z-axis" in {
val A : Vector3 = Vector3(1, 0, 0)
A.Rz(0) mustEqual A
A.Rz(90) mustEqual Vector3(0, 1, 0)
A.Rz(180) mustEqual Vector3(-1, 0, 0)
A.Rz(270) mustEqual Vector3(0, -1, 0)
A.Rz(360) mustEqual A
}
"rotate positive y-axis-vector 90-degrees around the x-axis" in {
val A : Vector3 = Vector3(0, 1, 0)
A.Rx(0) mustEqual A
A.Rx(90) mustEqual Vector3(0, 0, 1)
A.Rx(180) mustEqual Vector3(0, -1, 0)
A.Rx(270) mustEqual Vector3(0, 0, -1)
A.Rx(360) mustEqual A
}
"rotate positive x-axis-vector 90-degrees around the y-axis" in {
val A : Vector3 = Vector3(1, 0, 0)
A.Ry(0) mustEqual A
A.Ry(90) mustEqual Vector3(0, 0, -1)
A.Ry(180) mustEqual Vector3(-1, 0, 0)
A.Ry(270) mustEqual Vector3(0, 0, 1)
A.Ry(360) mustEqual A
}
"compound rotation" in {
val A : Vector3 = Vector3(1, 0, 0)
A.Rz(90)
.Rx(90)
.Ry(90) mustEqual A
}
"45-degree rotation" in {
val A : Vector3 = Vector3(1, 0, 0)
A.Rz(45) mustEqual Vector3(0.70710677f, 0.70710677f, 0)
}
}
}

View file

@ -1,90 +0,0 @@
// Copyright (c) 2017 PSForever
package objects.terminal
import akka.actor.ActorRef
import net.psforever.objects.serverobject.terminals.{MedicalTerminalDefinition, ProximityTerminal, Terminal}
import net.psforever.objects.{Avatar, GlobalDefinitions, Player}
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, TransactionType}
import org.specs2.mutable.Specification
class MedicalTerminalTest extends Specification {
"MedicalTerminal" should {
"define (a)" in {
val a = new MedicalTerminalDefinition(38)
a.ObjectId mustEqual 38
a.Name mustEqual "adv_med_terminal"
}
"define (b)" in {
val b = new MedicalTerminalDefinition(225)
b.ObjectId mustEqual 225
b.Name mustEqual "crystals_health_a"
}
"define (c)" in {
val c = new MedicalTerminalDefinition(226)
c.ObjectId mustEqual 226
c.Name mustEqual "crystals_health_b"
}
"define (d)" in {
val d = new MedicalTerminalDefinition(529)
d.ObjectId mustEqual 529
d.Name mustEqual "medical_terminal"
}
"define (e)" in {
val e = new MedicalTerminalDefinition(689)
e.ObjectId mustEqual 689
e.Name mustEqual "portable_med_terminal"
}
"define (invalid)" in {
var id : Int = (math.random * Int.MaxValue).toInt
if(id == 224) {
id += 2
}
else if(id == 37) {
id += 1
}
else if(id == 528) {
id += 1
}
else if(id == 688) {
id += 1
}
new MedicalTerminalDefinition(id) must throwA[IllegalArgumentException]
}
}
"Medical_Terminal" should {
"construct" in {
ProximityTerminal(GlobalDefinitions.medical_terminal).Actor mustEqual ActorRef.noSender
}
"can add a player to a list of users" in {
val terminal = ProximityTerminal(GlobalDefinitions.medical_terminal)
terminal.NumberUsers mustEqual 0
terminal.AddUser(PlanetSideGUID(10))
terminal.NumberUsers mustEqual 1
}
"can remove a player from a list of users" in {
val terminal = ProximityTerminal(GlobalDefinitions.medical_terminal)
terminal.AddUser(PlanetSideGUID(10))
terminal.NumberUsers mustEqual 1
terminal.RemoveUser(PlanetSideGUID(10))
terminal.NumberUsers mustEqual 0
}
"player can not interact with the proximity terminal normally (buy)" in {
val terminal = ProximityTerminal(GlobalDefinitions.medical_terminal)
val player = Player(Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "lite_armor", 0, PlanetSideGUID(0))
terminal.Request(player, msg) mustEqual Terminal.NoDeal()
}
}
}

View file

@ -1,120 +0,0 @@
// Copyright (c) 2017 PSForever
package objects.terminal
import akka.actor.{ActorSystem, Props}
import base.ActorTest
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.{Avatar, GlobalDefinitions, Player}
import net.psforever.objects.serverobject.terminals._
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
import scala.concurrent.duration.Duration
class ProximityTerminalControl1Test extends ActorTest {
"ProximityTerminalControl" should {
"construct (medical terminal)" in {
val terminal = ProximityTerminal(GlobalDefinitions.medical_terminal)
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-term")
}
}
}
class ProximityTerminalControl2Test extends ActorTest {
"ProximityTerminalControl can not process wrong messages" in {
val (_, terminal) = TerminalControlTest.SetUpAgents(GlobalDefinitions.medical_terminal, PlanetSideEmpire.TR)
terminal.Actor !"hello"
expectNoMsg(Duration.create(500, "ms"))
}
}
//terminal control is mostly a pass-through actor for Terminal.Exchange messages, wrapped in Terminal.TerminalMessage protocol
class MedicalTerminalControl1Test extends ActorTest {
"ProximityTerminalControl sends a message to the first new user only" in {
val (player, terminal) = ProximityTerminalControlTest.SetUpAgents(GlobalDefinitions.medical_terminal, PlanetSideEmpire.TR)
player.GUID = PlanetSideGUID(10)
val player2 = Player(Avatar("someothertest", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player2.GUID = PlanetSideGUID(11)
terminal.Actor ! CommonMessages.Use(player)
val reply = receiveOne(Duration.create(500, "ms"))
assert(reply.isInstanceOf[Terminal.TerminalMessage])
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
assert(reply2.player == player)
assert(reply2.msg == null)
assert(reply2.response.isInstanceOf[Terminal.StartProximityEffect])
assert(reply2.response.asInstanceOf[Terminal.StartProximityEffect].terminal == terminal)
assert(terminal.NumberUsers == 1)
terminal.Actor ! CommonMessages.Use(player2)
expectNoMsg(Duration.create(500, "ms"))
assert(terminal.NumberUsers == 2)
}
}
class MedicalTerminalControl2Test extends ActorTest {
"ProximityTerminalControl sends a message to the last user only" in {
val (player, terminal) : (Player, ProximityTerminal) = ProximityTerminalControlTest.SetUpAgents(GlobalDefinitions.medical_terminal, PlanetSideEmpire.TR)
player.GUID = PlanetSideGUID(10)
val player2 = Player(Avatar("someothertest", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player2.GUID = PlanetSideGUID(11)
terminal.Actor ! CommonMessages.Use(player)
receiveOne(Duration.create(500, "ms"))
terminal.Actor ! CommonMessages.Use(player2)
expectNoMsg(Duration.create(500, "ms"))
assert(terminal.NumberUsers == 2)
terminal.Actor ! CommonMessages.Unuse(player)
expectNoMsg(Duration.create(500, "ms"))
assert(terminal.NumberUsers == 1)
terminal.Actor ! CommonMessages.Unuse(player2)
val reply = receiveOne(Duration.create(500, "ms"))
assert(reply.isInstanceOf[Terminal.TerminalMessage])
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
assert(reply2.player == player2)
assert(reply2.msg == null)
assert(reply2.response.isInstanceOf[Terminal.StopProximityEffect])
assert(reply2.response.asInstanceOf[Terminal.StopProximityEffect].terminal == terminal)
assert(terminal.NumberUsers == 0)
}
}
class MedicalTerminalControl3Test extends ActorTest {
"ProximityTerminalControl sends a message to the last user only (confirmation of test #2)" in {
val (player, terminal) : (Player, ProximityTerminal) = ProximityTerminalControlTest.SetUpAgents(GlobalDefinitions.medical_terminal, PlanetSideEmpire.TR)
player.GUID = PlanetSideGUID(10)
val player2 = Player(Avatar("someothertest", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player2.GUID = PlanetSideGUID(11)
terminal.Actor ! CommonMessages.Use(player)
receiveOne(Duration.create(500, "ms"))
terminal.Actor ! CommonMessages.Use(player2)
expectNoMsg(Duration.create(500, "ms"))
assert(terminal.NumberUsers == 2)
terminal.Actor ! CommonMessages.Unuse(player2)
expectNoMsg(Duration.create(500, "ms"))
assert(terminal.NumberUsers == 1)
terminal.Actor ! CommonMessages.Unuse(player)
val reply = receiveOne(Duration.create(500, "ms"))
assert(reply.isInstanceOf[Terminal.TerminalMessage])
val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
assert(reply2.player == player) //important!
assert(reply2.msg == null)
assert(reply2.response.isInstanceOf[Terminal.StopProximityEffect])
assert(reply2.response.asInstanceOf[Terminal.StopProximityEffect].terminal == terminal)
assert(terminal.NumberUsers == 0)
}
}
object ProximityTerminalControlTest {
def SetUpAgents(tdef : MedicalTerminalDefinition, faction : PlanetSideEmpire.Value)(implicit system : ActorSystem) : (Player, ProximityTerminal) = {
val terminal = ProximityTerminal(tdef)
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-term")
(Player(Avatar("test", faction, CharacterGender.Male, 0, CharacterVoice.Mute)), terminal)
}
}

View file

@ -2,14 +2,19 @@
package objects.terminal
import akka.actor.Props
import akka.testkit.TestProbe
import base.ActorTest
import net.psforever.objects.guid.TaskResolver
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage
import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.serverobject.terminals.{ProximityTerminal, ProximityTerminalControl, ProximityUnit, Terminal}
import net.psforever.objects.zones.{Zone, ZoneActor, ZoneMap}
import net.psforever.objects.{Avatar, GlobalDefinitions, Player}
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
import org.specs2.mutable.Specification
import services.{Service, ServiceManager}
import services.local.{LocalResponse, LocalService, LocalServiceResponse}
import scala.concurrent.duration._
@ -21,39 +26,62 @@ class ProximityTest extends Specification {
}
"keep track of users (add)" in {
val obj = new ProximityTest.SampleTerminal()
val avatar1 = Player(Avatar("TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar1.Spawn
avatar1.Health = 50
val avatar2 = Player(Avatar("TestCharacter2", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar2.Spawn
avatar2.Health = 50
val obj = new ProximityTerminal(GlobalDefinitions.medical_terminal)
obj.NumberUsers mustEqual 0
obj.AddUser(PlanetSideGUID(10)) mustEqual obj.NumberUsers
obj.AddUser(avatar1) mustEqual true
obj.NumberUsers mustEqual 1
obj.AddUser(PlanetSideGUID(20)) mustEqual obj.NumberUsers
obj.AddUser(avatar2) mustEqual true
obj.NumberUsers mustEqual 2
}
"keep track of users (remove)" in {
val obj = new ProximityTest.SampleTerminal()
obj.AddUser(PlanetSideGUID(10))
obj.AddUser(PlanetSideGUID(20))
obj.NumberUsers mustEqual 2
obj.RemoveUser(PlanetSideGUID(10)) mustEqual obj.NumberUsers
val avatar1 = Player(Avatar("TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar1.Spawn
avatar1.Health = 50
val avatar2 = Player(Avatar("TestCharacter2", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar2.Spawn
avatar2.Health = 50
val obj = new ProximityTerminal(GlobalDefinitions.medical_terminal)
obj.NumberUsers mustEqual 0
obj.AddUser(avatar1) mustEqual true
obj.NumberUsers mustEqual 1
obj.RemoveUser(PlanetSideGUID(20)) mustEqual obj.NumberUsers
obj.AddUser(avatar2) mustEqual true
obj.NumberUsers mustEqual 2
obj.RemoveUser(avatar1) mustEqual true
obj.NumberUsers mustEqual 1
obj.RemoveUser(avatar2) mustEqual true
obj.NumberUsers mustEqual 0
}
"can not add a user twice" in {
val obj = new ProximityTest.SampleTerminal()
obj.AddUser(PlanetSideGUID(10))
val avatar = Player(Avatar("TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar.Spawn
avatar.Health = 50
val obj = new ProximityTerminal(GlobalDefinitions.medical_terminal)
obj.AddUser(avatar) mustEqual true
obj.NumberUsers mustEqual 1
obj.AddUser(PlanetSideGUID(10))
obj.AddUser(avatar)// mustEqual false
obj.NumberUsers mustEqual 1
}
"can not remove a user that was not added" in {
val avatar = Player(Avatar("TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar.Spawn
avatar.Health = 50
val obj = new ProximityTest.SampleTerminal()
obj.AddUser(PlanetSideGUID(10))
obj.NumberUsers mustEqual 1
obj.RemoveUser(PlanetSideGUID(20))
obj.NumberUsers mustEqual 1
obj.RemoveUser(avatar) mustEqual false
obj.NumberUsers mustEqual 0
}
}
@ -65,106 +93,216 @@ class ProximityTest extends Specification {
}
}
class ProximityTerminalControl1bTest extends ActorTest {
class ProximityTerminalControlStartTest extends ActorTest {
"ProximityTerminalControl" should {
//setup
val probe = new TestProbe(system)
val service = ServiceManager.boot(system)
service ! ServiceManager.Register(Props(classOf[ProximityTest.ProbedLocalService], probe), "local")
service ! ServiceManager.Register(Props[TaskResolver], "taskResolver")
service ! ServiceManager.Register(Props[TaskResolver], "cluster")
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-prox")
val zone : Zone = new Zone("test", new ZoneMap("test-map"), 0) {
Actor = system.actorOf(Props(classOf[ZoneActor], this), "test-zone")
override def SetupNumberPools() = {
AddPool("dynamic", 1 to 10)
}
}
new Building(0, zone, StructureType.Facility) {
Amenities = terminal
Faction = PlanetSideEmpire.VS
}
val avatar = Player(Avatar("TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar.Continent = "test"
avatar.Spawn
avatar.Health = 50
avatar.GUID = PlanetSideGUID(1)
terminal.GUID = PlanetSideGUID(2)
terminal.Actor ! Service.Startup()
expectNoMsg(500 milliseconds) //spacer
"send out a start message" in {
val obj = ProximityTerminal(GlobalDefinitions.medical_terminal)
obj.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], obj), "prox-ctrl")
val player = Player(Avatar("TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.GUID = PlanetSideGUID(10)
assert(terminal.NumberUsers == 0)
assert(terminal.Owner.Continent.equals("test"))
terminal.Actor ! CommonMessages.Use(avatar, Some(avatar))
assert(obj.NumberUsers == 0)
obj.Actor ! CommonMessages.Use(player)
val msg = receiveOne(200 milliseconds)
assert(obj.NumberUsers == 1)
assert(msg.isInstanceOf[TerminalMessage])
val msgout = msg.asInstanceOf[TerminalMessage]
assert(msgout.player == player)
assert(msgout.msg == null)
assert(msgout.response.isInstanceOf[Terminal.StartProximityEffect])
val msg = probe.receiveOne(500 milliseconds)
assert(terminal.NumberUsers == 1)
assert(msg.isInstanceOf[LocalServiceResponse])
val resp = msg.asInstanceOf[LocalServiceResponse]
assert(resp.replyMessage == LocalResponse.ProximityTerminalEffect(PlanetSideGUID(2), true))
}
}
}
class ProximityTerminalControl2bTest extends ActorTest {
class ProximityTerminalControlTwoUsersTest extends ActorTest {
"ProximityTerminalControl" should {
"will not send out one start message unless first user" in {
val obj = ProximityTerminal(GlobalDefinitions.medical_terminal)
obj.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], obj), "prox-ctrl")
val player1 = Player(Avatar("TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player1.GUID = PlanetSideGUID(10)
val player2 = Player(Avatar("TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player2.GUID = PlanetSideGUID(11)
assert(obj.NumberUsers == 0)
//setup
val probe = new TestProbe(system)
val service = ServiceManager.boot(system)
service ! ServiceManager.Register(Props(classOf[ProximityTest.ProbedLocalService], probe), "local")
service ! ServiceManager.Register(Props[TaskResolver], "taskResolver")
service ! ServiceManager.Register(Props[TaskResolver], "cluster")
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-prox")
val zone : Zone = new Zone("test", new ZoneMap("test-map"), 0) {
Actor = system.actorOf(Props(classOf[ZoneActor], this), "test-zone")
override def SetupNumberPools() = {
AddPool("dynamic", 1 to 10)
}
}
new Building(0, zone, StructureType.Facility) {
Amenities = terminal
Faction = PlanetSideEmpire.VS
}
val avatar = Player(Avatar("TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar.Continent = "test"
avatar.Spawn
avatar.Health = 50
obj.Actor ! CommonMessages.Use(player1)
val msg = receiveOne(200 milliseconds)
assert(obj.NumberUsers == 1)
assert(msg.isInstanceOf[TerminalMessage])
assert(msg.asInstanceOf[TerminalMessage].response.isInstanceOf[Terminal.StartProximityEffect])
obj.Actor ! CommonMessages.Use(player2)
expectNoMsg(500 milliseconds)
assert(obj.NumberUsers == 2)
avatar.GUID = PlanetSideGUID(1)
terminal.GUID = PlanetSideGUID(2)
terminal.Actor ! Service.Startup()
expectNoMsg(500 milliseconds) //spacer
"will not send out a start message if not the first user" in {
assert(terminal.NumberUsers == 0)
assert(terminal.Owner.Continent.equals("test"))
terminal.Actor ! CommonMessages.Use(avatar, Some(avatar))
val msg = probe.receiveOne(500 milliseconds)
assert(terminal.NumberUsers == 1)
assert(msg.isInstanceOf[LocalServiceResponse])
val resp = msg.asInstanceOf[LocalServiceResponse]
assert(resp.replyMessage == LocalResponse.ProximityTerminalEffect(PlanetSideGUID(2), true))
val avatar2 = Player(Avatar("TestCharacter2", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar2.Continent = "test"
avatar2.Spawn
avatar2.Health = 50
terminal.Actor ! CommonMessages.Use(avatar2, Some(avatar2))
probe.expectNoMsg(500 milliseconds)
assert(terminal.NumberUsers == 2)
}
}
}
class ProximityTerminalControl3bTest extends ActorTest {
class ProximityTerminalControlStopTest extends ActorTest {
"ProximityTerminalControl" should {
//setup
val probe = new TestProbe(system)
val service = ServiceManager.boot(system)
service ! ServiceManager.Register(Props(classOf[ProximityTest.ProbedLocalService], probe), "local")
service ! ServiceManager.Register(Props[TaskResolver], "taskResolver")
service ! ServiceManager.Register(Props[TaskResolver], "cluster")
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-prox")
val zone : Zone = new Zone("test", new ZoneMap("test-map"), 0) {
Actor = system.actorOf(Props(classOf[ZoneActor], this), "test-zone")
override def SetupNumberPools() = {
AddPool("dynamic", 1 to 10)
}
}
new Building(0, zone, StructureType.Facility) {
Amenities = terminal
Faction = PlanetSideEmpire.VS
}
val avatar = Player(Avatar("TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar.Continent = "test"
avatar.Spawn
avatar.Health = 50
avatar.GUID = PlanetSideGUID(1)
terminal.GUID = PlanetSideGUID(2)
terminal.Actor ! Service.Startup()
expectNoMsg(500 milliseconds) //spacer
"send out a stop message" in {
val obj = ProximityTerminal(GlobalDefinitions.medical_terminal)
obj.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], obj), "prox-ctrl")
val player = Player(Avatar("TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.GUID = PlanetSideGUID(10)
assert(terminal.NumberUsers == 0)
assert(terminal.Owner.Continent.equals("test"))
assert(obj.NumberUsers == 0)
obj.Actor ! CommonMessages.Use(player)
receiveOne(200 milliseconds)
assert(obj.NumberUsers == 1)
obj.Actor ! CommonMessages.Unuse(player)
val msg = receiveOne(200 milliseconds)
assert(obj.NumberUsers == 0)
assert(msg.isInstanceOf[TerminalMessage])
val msgout = msg.asInstanceOf[TerminalMessage]
assert(msgout.player == player)
assert(msgout.msg == null)
assert(msgout.response.isInstanceOf[Terminal.StopProximityEffect])
terminal.Actor ! CommonMessages.Use(avatar, Some(avatar))
val msg1 = probe.receiveOne(500 milliseconds)
assert(terminal.NumberUsers == 1)
assert(msg1.isInstanceOf[LocalServiceResponse])
val resp1 = msg1.asInstanceOf[LocalServiceResponse]
assert(resp1.replyMessage == LocalResponse.ProximityTerminalEffect(PlanetSideGUID(2), true))
terminal.Actor ! CommonMessages.Unuse(avatar, Some(avatar))
val msg2 = probe.receiveWhile(500 milliseconds) {
case LocalServiceResponse(_, _, replyMessage) => replyMessage
}
assert(terminal.NumberUsers == 0)
assert(msg2.last == LocalResponse.ProximityTerminalEffect(PlanetSideGUID(2), false))
}
}
}
class ProximityTerminalControl4bTest extends ActorTest {
class ProximityTerminalControlNotStopTest extends ActorTest {
"ProximityTerminalControl" should {
"will not send out one stop message until last user" in {
val obj = ProximityTerminal(GlobalDefinitions.medical_terminal)
obj.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], obj), "prox-ctrl")
val player1 = Player(Avatar("TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player1.GUID = PlanetSideGUID(10)
val player2 = Player(Avatar("TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player2.GUID = PlanetSideGUID(11)
assert(obj.NumberUsers == 0)
//setup
val probe = new TestProbe(system)
val service = ServiceManager.boot(system)
service ! ServiceManager.Register(Props(classOf[ProximityTest.ProbedLocalService], probe), "local")
service ! ServiceManager.Register(Props[TaskResolver], "taskResolver")
service ! ServiceManager.Register(Props[TaskResolver], "cluster")
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
terminal.Actor = system.actorOf(Props(classOf[ProximityTerminalControl], terminal), "test-prox")
val zone : Zone = new Zone("test", new ZoneMap("test-map"), 0) {
Actor = system.actorOf(Props(classOf[ZoneActor], this), "test-zone")
override def SetupNumberPools() = {
AddPool("dynamic", 1 to 10)
}
}
new Building(0, zone, StructureType.Facility) {
Amenities = terminal
Faction = PlanetSideEmpire.VS
}
val avatar = Player(Avatar("TestCharacter1", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar.Continent = "test"
avatar.Spawn
avatar.Health = 50
obj.Actor ! CommonMessages.Use(player1)
receiveOne(200 milliseconds) //StartProximityEffect
assert(obj.NumberUsers == 1)
obj.Actor ! CommonMessages.Use(player2)
expectNoMsg(500 milliseconds)
assert(obj.NumberUsers == 2)
obj.Actor ! CommonMessages.Unuse(player1)
expectNoMsg(500 milliseconds)
assert(obj.NumberUsers == 1)
obj.Actor ! CommonMessages.Unuse(player2)
val msg = receiveOne(200 milliseconds)
assert(obj.NumberUsers == 0)
assert(msg.isInstanceOf[TerminalMessage])
val msgout = msg.asInstanceOf[TerminalMessage]
assert(msgout.player == player2)
assert(msgout.msg == null)
assert(msgout.response.isInstanceOf[Terminal.StopProximityEffect])
avatar.GUID = PlanetSideGUID(1)
terminal.GUID = PlanetSideGUID(2)
terminal.Actor ! Service.Startup()
expectNoMsg(500 milliseconds) //spacer
"will not send out one stop message until last user" in {
assert(terminal.NumberUsers == 0)
assert(terminal.Owner.Continent.equals("test"))
terminal.Actor ! CommonMessages.Use(avatar, Some(avatar))
val msg = probe.receiveOne(500 milliseconds)
assert(terminal.NumberUsers == 1)
assert(msg.isInstanceOf[LocalServiceResponse])
val resp = msg.asInstanceOf[LocalServiceResponse]
assert(resp.replyMessage == LocalResponse.ProximityTerminalEffect(PlanetSideGUID(2), true))
val avatar2 = Player(Avatar("TestCharacter2", PlanetSideEmpire.VS, CharacterGender.Female, 1, CharacterVoice.Voice1))
avatar2.Continent = "test"
avatar2.Spawn
avatar2.Health = 50
terminal.Actor ! CommonMessages.Use(avatar2, Some(avatar2))
probe.expectNoMsg(500 milliseconds)
assert(terminal.NumberUsers == 2)
terminal.Actor ! CommonMessages.Unuse(avatar, Some(avatar))
val msg2 = probe.receiveWhile(500 milliseconds) {
case LocalServiceResponse(_, _, replyMessage) => replyMessage
}
assert(terminal.NumberUsers == 1)
assert(!msg2.contains(LocalResponse.ProximityTerminalEffect(PlanetSideGUID(2), false)))
}
}
}
object ProximityTest {
class SampleTerminal extends Terminal(GlobalDefinitions.dropship_vehicle_terminal) with ProximityUnit
class ProbedLocalService(probe : TestProbe) extends LocalService {
self.tell(Service.Join("test"), probe.ref)
}
}

View file

@ -1,91 +0,0 @@
// Copyright (c) 2017 PSForever
package objects.terminal
import akka.actor.ActorRef
import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects._
import net.psforever.objects.serverobject.terminals.Terminal
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, TransactionType}
import org.specs2.mutable.Specification
class RepairRearmSiloTest extends Specification {
"RepairRearmSilo" should {
val player = Player(Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
val silo = Terminal(GlobalDefinitions.repair_silo)
silo.Owner = new Building(0, Zone.Nowhere, StructureType.Building)
silo.Owner.Faction = PlanetSideEmpire.TR
"define" in {
GlobalDefinitions.repair_silo.ObjectId mustEqual 729
}
"construct" in {
val obj = Terminal(GlobalDefinitions.repair_silo)
obj.Actor mustEqual ActorRef.noSender
}
"player can buy a box of ammunition ('bullet_35mm')" in {
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 3, "35mmbullet", 0, PlanetSideGUID(0))
val reply = silo.Request(player, msg)
reply.isInstanceOf[Terminal.BuyEquipment] mustEqual true
val reply2 = reply.asInstanceOf[Terminal.BuyEquipment]
reply2.item.isInstanceOf[AmmoBox] mustEqual true
reply2.item.asInstanceOf[AmmoBox].Definition mustEqual GlobalDefinitions.bullet_35mm
reply2.item.asInstanceOf[AmmoBox].Capacity mustEqual 100
}
"player can not buy fake equipment ('sabot')" in {
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 3, "sabot", 0, PlanetSideGUID(0))
silo.Request(player, msg) mustEqual Terminal.NoDeal()
}
"player can not buy equipment from the wrong page ('35mmbullet', page 1)" in {
val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 1, "35mmbullet", 0, PlanetSideGUID(0))
silo.Request(player, msg) mustEqual Terminal.NoDeal()
}
"player can retrieve a vehicle loadout" in {
val avatar = Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)
val player2 = Player(avatar)
val vehicle = Vehicle(GlobalDefinitions.fury)
vehicle.Slot(30).Equipment = AmmoBox(GlobalDefinitions.bullet_9mm)
avatar.SaveLoadout(vehicle, "test", 10)
val msg = silo.Request(player2, ItemTransactionMessage(PlanetSideGUID(10), TransactionType.Loadout, 4, "", 0, PlanetSideGUID(0)))
msg.isInstanceOf[Terminal.VehicleLoadout] mustEqual true
val loadout = msg.asInstanceOf[Terminal.VehicleLoadout]
loadout.vehicle_definition mustEqual GlobalDefinitions.fury
loadout.weapons.size mustEqual 1
loadout.weapons.head.obj.Definition mustEqual GlobalDefinitions.fury_weapon_systema
loadout.weapons.head.start mustEqual 1
loadout.inventory.head.obj.Definition mustEqual GlobalDefinitions.bullet_9mm
loadout.inventory.head.start mustEqual 30
}
"player can not retrieve a vehicle loadout from the wrong line" in {
val avatar = Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)
val player2 = Player(avatar)
val vehicle = Vehicle(GlobalDefinitions.fury)
vehicle.Slot(30).Equipment = AmmoBox(GlobalDefinitions.bullet_9mm)
avatar.SaveLoadout(vehicle, "test", 10)
val msg = silo.Request(player2, ItemTransactionMessage(PlanetSideGUID(10), TransactionType.Loadout, 3, "", 0, PlanetSideGUID(0))) //page 3
msg.isInstanceOf[Terminal.NoDeal] mustEqual true
}
"player can not retrieve a vehicle loadout from the wrong line" in {
val avatar = Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)
val player2 = Player(avatar)
val vehicle = Vehicle(GlobalDefinitions.fury)
vehicle.Slot(30).Equipment = AmmoBox(GlobalDefinitions.bullet_9mm)
avatar.SaveLoadout(vehicle, "test", 10)
val msg = silo.Request(player2, ItemTransactionMessage(PlanetSideGUID(10), TransactionType.Loadout, 4, "", 1, PlanetSideGUID(0))) //line 11
msg.isInstanceOf[Terminal.NoDeal] mustEqual true
}
}
}

View file

@ -5,6 +5,7 @@ import akka.actor.Props
import base.ActorTest
import net.psforever.objects.{GlobalDefinitions, SensorDeployable, Vehicle}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.terminals.{ProximityTerminal, Terminal}
import net.psforever.packet.game._
import net.psforever.types.{PlanetSideEmpire, Vector3}
import services.{Service, ServiceManager}
@ -141,15 +142,32 @@ class HackClearTest extends ActorTest {
}
}
class ProximityTerminalEffectTest extends ActorTest {
class ProximityTerminalEffectOnTest extends ActorTest {
ServiceManager.boot(system)
val service = system.actorOf(Props[LocalService], "l_service")
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
terminal.GUID = PlanetSideGUID(1)
"LocalService" should {
"pass ProximityTerminalEffect" in {
val service = system.actorOf(Props[LocalService], "l_service")
service ! Service.Join("test")
service ! LocalServiceMessage("test", LocalAction.ProximityTerminalEffect(PlanetSideGUID(10), PlanetSideGUID(40), true))
expectMsg(LocalServiceResponse("/test/Local", PlanetSideGUID(10), LocalResponse.ProximityTerminalEffect(PlanetSideGUID(40), true)))
"pass ProximityTerminalEffect (true)" in {
service ! Service.Join("nowhere")
service ! Terminal.StartProximityEffect(terminal)
expectMsg(LocalServiceResponse("/nowhere/Local", PlanetSideGUID(0), LocalResponse.ProximityTerminalEffect(PlanetSideGUID(1), true)))
}
}
}
class ProximityTerminalEffectOffTest extends ActorTest {
ServiceManager.boot(system)
val service = system.actorOf(Props[LocalService], "l_service")
val terminal = new ProximityTerminal(GlobalDefinitions.medical_terminal)
terminal.GUID = PlanetSideGUID(1)
"LocalService" should {
"pass ProximityTerminalEffect (false)" in {
service ! Service.Join("nowhere")
service ! Terminal.StopProximityEffect(terminal)
expectMsg(LocalServiceResponse("/nowhere/Local", PlanetSideGUID(0), LocalResponse.ProximityTerminalEffect(PlanetSideGUID(1), false)))
}
}
}

View file

@ -9,7 +9,6 @@ import net.psforever.objects.serverobject.locks.IFFLock
import net.psforever.objects.serverobject.mblocker.Locker
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
import net.psforever.objects.serverobject.structures.{Building, FoundationBuilder, StructureType, WarpGate}
import net.psforever.objects.serverobject.terminals.{ProximityTerminal, Terminal}
import net.psforever.objects.serverobject.terminals.{CaptureTerminal, ProximityTerminal, Terminal}
import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
@ -56,7 +55,7 @@ object Maps {
LocalObject(380, Door.Constructor)
LocalObject(381, Door.Constructor)
LocalObject(382, Door.Constructor)
LocalObject(383, Door.Constructor(Vector3(2674.0938f, 4317.367f, 44.59375f), Vector3(0.0f, 0.0f, 180.0f)))
LocalObject(383, Door.Constructor(Vector3(2674.0938f, 4317.367f, 44.59375f), Vector3.z(180.0f)))
LocalObject(384, Door.Constructor(Vector3(2674.086f, 4321.6953f, 44.59375f), Vector3(0.0f, 357.1875f, 357.1875f)))
LocalObject(385, Door.Constructor)
LocalObject(386, Door.Constructor(Vector3(2692.086f, 4316.5703f, 52.03125f), Vector3(0.0f, 2.8125f, 270.0f)))
@ -78,7 +77,7 @@ object Maps {
LocalObject(701, Door.Constructor)
LocalObject(703, Door.Constructor)
LocalObject(716, Door.Constructor)
LocalObject(920, Door.Constructor(Vector3(2708.1953f, 4319.9766f, 39.59375f), Vector3(0.0f, 0.0f, 92.8125f)))
LocalObject(920, Door.Constructor(Vector3(2708.1953f, 4319.9766f, 39.59375f), Vector3.z(92.8125f)))
//Akkan Locks
LocalObject(968, IFFLock.Constructor)
@ -182,16 +181,16 @@ object Maps {
LocalObject(516, Door.Constructor)
LocalObject(517, Door.Constructor)
LocalObject(518, Door.Constructor)
LocalObject(519, Door.Constructor(Vector3(4342.7266f, 5833.461f, 77.890625f), Vector3(0, 0, 272)))
LocalObject(519, Door.Constructor(Vector3(4342.7266f, 5833.461f, 77.890625f), Vector3.z(272)))
LocalObject(520, Door.Constructor)
LocalObject(521, Door.Constructor)
LocalObject(522, Door.Constructor(Vector3(4395.7188f, 5908.2188f, 92.90625f), Vector3(0, 0, 2)))
LocalObject(523, Door.Constructor(Vector3(4402.086f, 5891.914f, 92.90625f), Vector3(0, 0, 182)))
LocalObject(522, Door.Constructor(Vector3(4395.7188f, 5908.2188f, 92.90625f), Vector3.z(2)))
LocalObject(523, Door.Constructor(Vector3(4402.086f, 5891.914f, 92.90625f), Vector3.z(182)))
LocalObject(524, Door.Constructor)
LocalObject(535, Door.Constructor)
LocalObject(536, Door.Constructor)
LocalObject(537, Door.Constructor)
LocalObject(653, Door.Constructor(Vector3(4339.6953f, 5973.828f, 77.875f), Vector3(0, 0, 2)))
LocalObject(653, Door.Constructor(Vector3(4339.6953f, 5973.828f, 77.875f), Vector3.z(2)))
LocalObject(657, Door.Constructor)
LocalObject(810, Door.Constructor)
LocalObject(811, Door.Constructor)
@ -200,19 +199,19 @@ object Maps {
LocalObject(814, Door.Constructor)
LocalObject(815, Door.Constructor)
LocalObject(816, Door.Constructor)
LocalObject(817, Door.Constructor(Vector3(4380.5938f, 5892.047f, 92.890625f), Vector3(0, 0, 2)))
LocalObject(817, Door.Constructor(Vector3(4380.5938f, 5892.047f, 92.890625f), Vector3.z(2)))
LocalObject(818, Door.Constructor)
LocalObject(819, Door.Constructor)
LocalObject(820, Door.Constructor)
LocalObject(821, Door.Constructor)
LocalObject(822, Door.Constructor)
LocalObject(823, Door.Constructor)
LocalObject(824, Door.Constructor(Vector3(4404.328f, 5883.4453f, 70.40625f), Vector3(0, 0, 182)))
LocalObject(825, Door.Constructor(Vector3(4405.133f, 5907.117f, 70.390625f), Vector3(0, 0, 2)))
LocalObject(826, Door.Constructor(Vector3(4413.3984f, 5914.9688f, 62.890625f), Vector3(0, 0, 182)))
LocalObject(827, Door.Constructor(Vector3(4416.4297f, 5886.867f, 62.890625f), Vector3(0, 0, 272)))
LocalObject(824, Door.Constructor(Vector3(4404.328f, 5883.4453f, 70.40625f), Vector3.z(182)))
LocalObject(825, Door.Constructor(Vector3(4405.133f, 5907.117f, 70.390625f), Vector3.z(2)))
LocalObject(826, Door.Constructor(Vector3(4413.3984f, 5914.9688f, 62.890625f), Vector3.z(182)))
LocalObject(827, Door.Constructor(Vector3(4416.4297f, 5886.867f, 62.890625f), Vector3.z(272)))
LocalObject(828, Door.Constructor)
LocalObject(925, Door.Constructor(Vector3(4424.492f, 5884.75f, 77.953125f), Vector3(0, 0, 182)))
LocalObject(925, Door.Constructor(Vector3(4424.492f, 5884.75f, 77.953125f), Vector3.z(182)))
LocalObject(973, IFFLock.Constructor)
LocalObject(980, IFFLock.Constructor)
LocalObject(1142, IFFLock.Constructor)
@ -229,9 +228,9 @@ object Maps {
LocalObject(2016, Terminal.Constructor(order_terminal))
LocalObject(2017, Terminal.Constructor(order_terminal))
LocalObject(2658, ResourceSilo.Constructor)
LocalObject(2724, SpawnTube.Constructor(Vector3(4396.7656f, 5888.258f, 71.15625f), Vector3(0, 0, 92)))
LocalObject(2725, SpawnTube.Constructor(Vector3(4397.211f, 5895.547f, 71.15625f), Vector3(0, 0, 92)))
LocalObject(2726, SpawnTube.Constructor(Vector3(4397.2344f, 5902.8203f, 71.15625f), Vector3(0, 0, 92)))
LocalObject(2724, SpawnTube.Constructor(Vector3(4396.7656f, 5888.258f, 71.15625f), Vector3.z(92)))
LocalObject(2725, SpawnTube.Constructor(Vector3(4397.211f, 5895.547f, 71.15625f), Vector3.z(92)))
LocalObject(2726, SpawnTube.Constructor(Vector3(4397.2344f, 5902.8203f, 71.15625f), Vector3.z(92)))
LocalObject(2948, Door.Constructor) //spawn tube door
LocalObject(2949, Door.Constructor) //spawn tube door
LocalObject(2950, Door.Constructor) //spawn tube door
@ -239,11 +238,11 @@ object Maps {
LocalObject(2854, Terminal.Constructor(spawn_terminal))
LocalObject(2859, Terminal.Constructor(spawn_terminal))
LocalObject(3072, Terminal.Constructor(ground_vehicle_terminal))
LocalObject(1888, VehicleSpawnPad.Constructor(Vector3(4337.0f, 5903.0f, 58.0f), Vector3(0f, 0f, 0f)))
LocalObject(1888, VehicleSpawnPad.Constructor(Vector3(4337.0f, 5903.0f, 58.0f), Vector3.Zero))
LocalObject(176, Terminal.Constructor(air_vehicle_terminal))
LocalObject(1889, VehicleSpawnPad.Constructor(Vector3(4386.0f, 5928.0f, 93.0f), Vector3(0f, 0f, 0f)))
LocalObject(1889, VehicleSpawnPad.Constructor(Vector3(4386.0f, 5928.0f, 93.0f), Vector3.Zero))
LocalObject(177, Terminal.Constructor(air_vehicle_terminal))
LocalObject(1890, VehicleSpawnPad.Constructor(Vector3(4407.0f, 5927.0f, 93.0f), Vector3(0f, 0f, 0f)))
LocalObject(1890, VehicleSpawnPad.Constructor(Vector3(4407.0f, 5927.0f, 93.0f), Vector3.Zero))
// LocalObject(1909, ProximityTerminal.Constructor(medical_terminal))
// LocalObject(1910, ProximityTerminal.Constructor(medical_terminal))
@ -340,14 +339,14 @@ object Maps {
LocalBuilding(10, FoundationBuilder(Building.Structure(StructureType.Facility, Vector3(3749f, 5477f, 0)))) // Todo change pos
LocalObject(223, CaptureTerminal.Constructor(capture_terminal))
LocalObject(464, Door.Constructor)
LocalObject(470, Door.Constructor(Vector3(3645.3984f, 5451.9688f, 88.890625f), Vector3(0, 0, 182)))
LocalObject(470, Door.Constructor(Vector3(3645.3984f, 5451.9688f, 88.890625f), Vector3.z(182)))
LocalObject(471, Door.Constructor)
LocalObject(472, Door.Constructor)
LocalObject(473, Door.Constructor)
LocalObject(474, Door.Constructor)
LocalObject(475, Door.Constructor(Vector3(3740.7422f, 5477.8906f, 98.890625f), Vector3(0, 0, 92)))
LocalObject(475, Door.Constructor(Vector3(3740.7422f, 5477.8906f, 98.890625f), Vector3.z(92)))
LocalObject(476, Door.Constructor)
LocalObject(481, Door.Constructor(Vector3(3758.25f, 5497.8047f, 98.890625f), Vector3(0, 0, 182)))
LocalObject(481, Door.Constructor(Vector3(3758.25f, 5497.8047f, 98.890625f), Vector3.z(182)))
LocalObject(482, Door.Constructor)
LocalObject(483, Door.Constructor)
LocalObject(484, Door.Constructor)
@ -359,22 +358,22 @@ object Maps {
LocalObject(768, Door.Constructor)
LocalObject(769, Door.Constructor)
LocalObject(770, Door.Constructor)
LocalObject(771, Door.Constructor(Vector3(3738.039f, 5470.0547f, 78.890625f), Vector3(0, 0, 272)))
LocalObject(771, Door.Constructor(Vector3(3738.039f, 5470.0547f, 78.890625f), Vector3.z(272)))
LocalObject(772, Door.Constructor)
LocalObject(773, Door.Constructor)
LocalObject(774, Door.Constructor(Vector3(3741.5312f, 5457.7734f, 71.390625f), Vector3(0, 0, 2)))
LocalObject(774, Door.Constructor(Vector3(3741.5312f, 5457.7734f, 71.390625f), Vector3.z(2)))
LocalObject(775, Door.Constructor)
LocalObject(776, Door.Constructor)
LocalObject(777, Door.Constructor)
LocalObject(778, Door.Constructor)
LocalObject(779, Door.Constructor(Vector3(3761.4531f, 5469.5703f, 78.890625f), Vector3(0, 0, 92)))
LocalObject(779, Door.Constructor(Vector3(3761.4531f, 5469.5703f, 78.890625f), Vector3.z(92)))
LocalObject(780, Door.Constructor)
LocalObject(781, Door.Constructor)
LocalObject(782, Door.Constructor)
LocalObject(783, Door.Constructor)
LocalObject(784, Door.Constructor(Vector3(3806.3906f, 5504.9766f, 78.890625f), Vector3(0, 0, 182)))
LocalObject(785, Door.Constructor(Vector3(3806.5938f, 5512.5703f, 78.890625f), Vector3(0, 0, 2)))
LocalObject(923, Door.Constructor(Vector3(3762.7266f, 5477.539f, 88.953125f), Vector3(0, 0, 92)))
LocalObject(784, Door.Constructor(Vector3(3806.3906f, 5504.9766f, 78.890625f), Vector3.z(182)))
LocalObject(785, Door.Constructor(Vector3(3806.5938f, 5512.5703f, 78.890625f), Vector3.z(2)))
LocalObject(923, Door.Constructor(Vector3(3762.7266f, 5477.539f, 88.953125f), Vector3.z(92)))
LocalObject(932, Door.Constructor)
LocalObject(933, Door.Constructor)
@ -409,30 +408,30 @@ object Maps {
LocalObject(1992, Terminal.Constructor(order_terminal))
LocalObject(1993, Terminal.Constructor(order_terminal))
LocalObject(1994, Terminal.Constructor(order_terminal))
LocalObject(2710, SpawnTube.Constructor(Vector3(3742.6016f, 5477.6797f, 79.640625f), Vector3(0, 0, 182)))
LocalObject(2713, SpawnTube.Constructor(Vector3(3749.9062f, 5477.711f, 79.640625f), Vector3(0, 0, 182)))
LocalObject(2714, SpawnTube.Constructor(Vector3(3757.1875f, 5477.5312f, 79.640625f), Vector3(0, 0, 182)))
LocalObject(2710, SpawnTube.Constructor(Vector3(3742.6016f, 5477.6797f, 79.640625f), Vector3.z(182)))
LocalObject(2713, SpawnTube.Constructor(Vector3(3749.9062f, 5477.711f, 79.640625f), Vector3.z(182)))
LocalObject(2714, SpawnTube.Constructor(Vector3(3757.1875f, 5477.5312f, 79.640625f), Vector3.z(182)))
LocalObject(2934, Door.Constructor) //spawn tube door
LocalObject(2937, Door.Constructor) //spawn tube door
LocalObject(2938, Door.Constructor) //spawn tube door
LocalObject(2228, ProximityTerminal.Constructor(pad_landing))
LocalObject(2229, Terminal.Constructor(pad_landing))
LocalObject(2231, ProximityTerminal.Constructor(pad_landing))
LocalObject(2232, Terminal.Constructor(pad_landing))
LocalObject(2234, ProximityTerminal.Constructor(pad_landing))
LocalObject(2235, Terminal.Constructor(pad_landing))
LocalObject(2237, ProximityTerminal.Constructor(pad_landing))
LocalObject(2238, Terminal.Constructor(pad_landing))
LocalObject(2228, ProximityTerminal.Constructor(pad_landing_frame))
LocalObject(2229, Terminal.Constructor(air_rearm_terminal))
LocalObject(2231, ProximityTerminal.Constructor(pad_landing_frame))
LocalObject(2232, Terminal.Constructor(air_rearm_terminal))
LocalObject(2234, ProximityTerminal.Constructor(pad_landing_frame))
LocalObject(2235, Terminal.Constructor(air_rearm_terminal))
LocalObject(2237, ProximityTerminal.Constructor(pad_landing_frame))
LocalObject(2238, Terminal.Constructor(air_rearm_terminal))
LocalObject(2595, ProximityTerminal.Constructor(repair_silo))
LocalObject(2596, Terminal.Constructor(repair_silo))
LocalObject(2596, Terminal.Constructor(ground_rearm_terminal))
LocalObject(2599, ProximityTerminal.Constructor(repair_silo))
LocalObject(2600, Terminal.Constructor(repair_silo))
LocalObject(2600, Terminal.Constructor(ground_rearm_terminal))
LocalObject(3070, Terminal.Constructor(vehicle_terminal_combined))
LocalObject(1886, VehicleSpawnPad.Constructor(Vector3(3675.0f, 5458.0f, 89.0f), Vector3(0f, 0f, 0f)))
LocalObject(1886, VehicleSpawnPad.Constructor(Vector3(3675.0f, 5458.0f, 89.0f), Vector3.Zero))
// LocalObject(169, ProximityTerminal.Constructor(adv_med_terminal))
// LocalObject(1906, ProximityTerminal.Constructor(medical_terminal))
@ -560,20 +559,20 @@ object Maps {
LocalObject(563, Door.Constructor)
LocalObject(566, Door.Constructor)
LocalObject(567, Door.Constructor)
LocalObject(572, Door.Constructor(Vector3(4824.0703f, 5260.3516f, 78.703125f), Vector3(0, 0, 47)))
LocalObject(573, Door.Constructor(Vector3(4833.711f, 5231.8203f, 71.25f), Vector3(0, 0, 47)))
LocalObject(574, Door.Constructor(Vector3(4834.7188f, 5271.9766f, 71.25f), Vector3(0, 0, 317)))
LocalObject(572, Door.Constructor(Vector3(4824.0703f, 5260.3516f, 78.703125f), Vector3.z(47)))
LocalObject(573, Door.Constructor(Vector3(4833.711f, 5231.8203f, 71.25f), Vector3.z(47)))
LocalObject(574, Door.Constructor(Vector3(4834.7188f, 5271.9766f, 71.25f), Vector3.z(317)))
LocalObject(575, Door.Constructor)
LocalObject(576, Door.Constructor(Vector3(4840.7734f, 5265.5f, 71.25f), Vector3(0, 0, 137)))
LocalObject(576, Door.Constructor(Vector3(4840.7734f, 5265.5f, 71.25f), Vector3.z(137)))
LocalObject(577, Door.Constructor)
LocalObject(578, Door.Constructor(Vector3(4854.5625f, 5174.6562f, 66.25f), Vector3(0, 0, 227)))
LocalObject(578, Door.Constructor(Vector3(4854.5625f, 5174.6562f, 66.25f), Vector3.z(227)))
LocalObject(579, Door.Constructor)
LocalObject(580, Door.Constructor)
LocalObject(585, Door.Constructor)
LocalObject(852, Door.Constructor(Vector3(4793.0547f, 5204.914f, 48.734375f), Vector3(0, 0, 47)))
LocalObject(853, Door.Constructor(Vector3(4799.3906f, 5216.047f, 56.234375f), Vector3(0, 0, 317)))
LocalObject(852, Door.Constructor(Vector3(4793.0547f, 5204.914f, 48.734375f), Vector3.z(47)))
LocalObject(853, Door.Constructor(Vector3(4799.3906f, 5216.047f, 56.234375f), Vector3.z(317)))
LocalObject(854, Door.Constructor)
LocalObject(855, Door.Constructor(Vector3(4815.5f, 5198.75f, 56.234375f), Vector3(0, 0, 137)))
LocalObject(855, Door.Constructor(Vector3(4815.5f, 5198.75f, 56.234375f), Vector3.z(137)))
LocalObject(856, Door.Constructor)
LocalObject(857, Door.Constructor)
LocalObject(858, Door.Constructor)
@ -583,18 +582,18 @@ object Maps {
LocalObject(862, Door.Constructor)
LocalObject(863, Door.Constructor)
LocalObject(864, Door.Constructor)
LocalObject(865, Door.Constructor(Vector3(4837.3047f, 5169.672f, 48.75f), Vector3(0, 0, 227)))
LocalObject(866, Door.Constructor(Vector3(4842.9844f, 5174.8906f, 48.75f), Vector3(0, 0, 47)))
LocalObject(865, Door.Constructor(Vector3(4837.3047f, 5169.672f, 48.75f), Vector3.z(227)))
LocalObject(866, Door.Constructor(Vector3(4842.9844f, 5174.8906f, 48.75f), Vector3.z(47)))
LocalObject(867, Door.Constructor)
LocalObject(868, Door.Constructor)
LocalObject(869, Door.Constructor)
LocalObject(870, Door.Constructor)
LocalObject(871, Door.Constructor)
LocalObject(872, Door.Constructor(Vector3(4857.0547f, 5247.992f, 48.734375f), Vector3(0, 0, 317)))
LocalObject(872, Door.Constructor(Vector3(4857.0547f, 5247.992f, 48.734375f), Vector3.z(317)))
LocalObject(873, Door.Constructor)
LocalObject(874, Door.Constructor)
LocalObject(875, Door.Constructor)
LocalObject(927, Door.Constructor(Vector3(4810.4297f, 5243.0703f, 66.296875f), Vector3(0, 0, 227)))
LocalObject(927, Door.Constructor(Vector3(4810.4297f, 5243.0703f, 66.296875f), Vector3.z(227)))
LocalObject(975, IFFLock.Constructor)
LocalObject(1182, IFFLock.Constructor)
@ -618,15 +617,15 @@ object Maps {
LocalObject(2041, Terminal.Constructor(order_terminal))
LocalObject(2042, Terminal.Constructor(order_terminal))
LocalObject(2043, Terminal.Constructor(order_terminal))
LocalObject(2740, SpawnTube.Constructor(Vector3(4808.0234f, 5217.9375f, 57f), Vector3(0, 0, 227)))
LocalObject(2741, SpawnTube.Constructor(Vector3(4812.992f, 5212.6016f, 57f), Vector3(0, 0, 227)))
LocalObject(2742, SpawnTube.Constructor(Vector3(4818.047f, 5207.3125f, 57f), Vector3(0, 0, 227)))
LocalObject(2740, SpawnTube.Constructor(Vector3(4808.0234f, 5217.9375f, 57f), Vector3.z(227)))
LocalObject(2741, SpawnTube.Constructor(Vector3(4812.992f, 5212.6016f, 57f), Vector3.z(227)))
LocalObject(2742, SpawnTube.Constructor(Vector3(4818.047f, 5207.3125f, 57f), Vector3.z(227)))
LocalObject(2964, Door.Constructor) //spawn tube door
LocalObject(2965, Door.Constructor) //spawn tube door
LocalObject(2966, Door.Constructor) //spawn tube door
LocalObject(3074, Terminal.Constructor(vehicle_terminal_combined))
LocalObject(1892, VehicleSpawnPad.Constructor(Vector3(4834.0f, 5185.0f, 67.0f), Vector3(0f, 0f, 45.0f)))
LocalObject(1892, VehicleSpawnPad.Constructor(Vector3(4834.0f, 5185.0f, 67.0f), Vector3.z(45.0f)))
// LocalObject(1912, ProximityTerminal.Constructor(medical_terminal))
// LocalObject(1913, ProximityTerminal.Constructor(medical_terminal))
@ -729,12 +728,12 @@ object Maps {
LocalObject(2797, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2973, Door.Constructor)
LocalObject(2974, Door.Constructor)
LocalObject(590, Door.Constructor(Vector3(5405.992f, 4220.1797f, 39.1875f), Vector3(0, 0, 180)))
LocalObject(591, Door.Constructor(Vector3(5405.992f, 4220.1797f, 49.1875f), Vector3(0, 0, 180)))
LocalObject(592, Door.Constructor(Vector3(5405.992f, 4220.1797f, 69.25f), Vector3(0, 0, 180)))
LocalObject(595, Door.Constructor(Vector3(5405.9844f, 4235.8047f, 69.25f), Vector3(0, 0, 0)))
LocalObject(593, Door.Constructor(Vector3(5405.9844f, 4235.8047f, 39.1875f), Vector3(0, 0, 0)))
LocalObject(594, Door.Constructor(Vector3(5405.9844f, 4235.8047f, 49.1875f), Vector3(0, 0, 0)))
LocalObject(590, Door.Constructor(Vector3(5405.992f, 4220.1797f, 39.1875f), Vector3.z(180)))
LocalObject(591, Door.Constructor(Vector3(5405.992f, 4220.1797f, 49.1875f), Vector3.z(180)))
LocalObject(592, Door.Constructor(Vector3(5405.992f, 4220.1797f, 69.25f), Vector3.z(180)))
LocalObject(595, Door.Constructor(Vector3(5405.9844f, 4235.8047f, 69.25f), Vector3.Zero))
LocalObject(593, Door.Constructor(Vector3(5405.9844f, 4235.8047f, 39.1875f), Vector3.Zero))
LocalObject(594, Door.Constructor(Vector3(5405.9844f, 4235.8047f, 49.1875f), Vector3.Zero))
LocalObject(1208, IFFLock.Constructor)
LocalObject(1209, IFFLock.Constructor)
LocalObject(1210, IFFLock.Constructor)
@ -744,8 +743,8 @@ object Maps {
LocalObject(2053, Terminal.Constructor(order_terminal))
LocalObject(2054, Terminal.Constructor(order_terminal))
LocalObject(2055, Terminal.Constructor(order_terminal))
LocalObject(2749, SpawnTube.Constructor(respawn_tube_tower, Vector3(5404.8125f, 4215.7344f, 29.484375f), Vector3(0, 0, 90)))
LocalObject(2750, SpawnTube.Constructor(respawn_tube_tower, Vector3(5404.7656f, 4232.1562f, 29.484375f), Vector3(0, 0, 90)))
LocalObject(2749, SpawnTube.Constructor(respawn_tube_tower, Vector3(5404.8125f, 4215.7344f, 29.484375f), Vector3.z(90)))
LocalObject(2750, SpawnTube.Constructor(respawn_tube_tower, Vector3(5404.7656f, 4232.1562f, 29.484375f), Vector3.z(90)))
ObjectToBuilding(2797, 25)
ObjectToBuilding(2973, 25)
@ -781,10 +780,10 @@ object Maps {
LocalObject(2792, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2957, Door.Constructor)
LocalObject(2958, Door.Constructor)
LocalObject(542, Door.Constructor(Vector3(4625.9844f, 5910.211f, 55.75f), Vector3(0, 0, 180)))
LocalObject(543, Door.Constructor(Vector3(4625.9844f, 5910.211f, 75.75f), Vector3(0, 0, 180)))
LocalObject(544, Door.Constructor(Vector3(4626.0312f, 5925.836f, 55.75f), Vector3(0, 0, 0)))
LocalObject(545, Door.Constructor(Vector3(4626.0312f, 5925.836f, 75.75f), Vector3(0, 0, 0)))
LocalObject(542, Door.Constructor(Vector3(4625.9844f, 5910.211f, 55.75f), Vector3.z(180)))
LocalObject(543, Door.Constructor(Vector3(4625.9844f, 5910.211f, 75.75f), Vector3.z(180)))
LocalObject(544, Door.Constructor(Vector3(4626.0312f, 5925.836f, 55.75f), Vector3.Zero))
LocalObject(545, Door.Constructor(Vector3(4626.0312f, 5925.836f, 75.75f), Vector3.Zero))
LocalObject(1164, IFFLock.Constructor)
LocalObject(1165, IFFLock.Constructor)
LocalObject(1166, IFFLock.Constructor)
@ -792,8 +791,8 @@ object Maps {
LocalObject(2027, Terminal.Constructor(order_terminal))
LocalObject(2028, Terminal.Constructor(order_terminal))
LocalObject(2029, Terminal.Constructor(order_terminal))
LocalObject(2733, SpawnTube.Constructor(respawn_tube_tower, Vector3(4624.758f, 5905.7344f, 45.984375f), Vector3(0, 0, 90)))
LocalObject(2734, SpawnTube.Constructor(respawn_tube_tower, Vector3(4624.7266f, 5922.1484f, 45.984375f), Vector3(0, 0, 90)))
LocalObject(2733, SpawnTube.Constructor(respawn_tube_tower, Vector3(4624.758f, 5905.7344f, 45.984375f), Vector3.z(90)))
LocalObject(2734, SpawnTube.Constructor(respawn_tube_tower, Vector3(4624.7266f, 5922.1484f, 45.984375f), Vector3.z(90)))
ObjectToBuilding(2792, 33)
ObjectToBuilding(2957, 33)
@ -823,10 +822,10 @@ object Maps {
LocalObject(2789, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2951, Door.Constructor)
LocalObject(2952, Door.Constructor)
LocalObject(525, Door.Constructor(Vector3(4423.9766f, 4850.164f, 86.203125f), Vector3(0, 0, 180)))
LocalObject(526, Door.Constructor(Vector3(4423.9766f, 4850.164f, 106.140625f), Vector3(0, 0, 180)))
LocalObject(527, Door.Constructor(Vector3(4423.9688f, 4865.8594f, 86.203125f), Vector3(0, 0, 0)))
LocalObject(528, Door.Constructor(Vector3(4423.9688f, 4865.8594f, 106.140625f), Vector3(0, 0, 0)))
LocalObject(525, Door.Constructor(Vector3(4423.9766f, 4850.164f, 86.203125f), Vector3.z(180)))
LocalObject(526, Door.Constructor(Vector3(4423.9766f, 4850.164f, 106.140625f), Vector3.z(180)))
LocalObject(527, Door.Constructor(Vector3(4423.9688f, 4865.8594f, 86.203125f), Vector3.Zero))
LocalObject(528, Door.Constructor(Vector3(4423.9688f, 4865.8594f, 106.140625f), Vector3.Zero))
LocalObject(1155, IFFLock.Constructor)
LocalObject(1156, IFFLock.Constructor)
LocalObject(1150, IFFLock.Constructor)
@ -834,8 +833,8 @@ object Maps {
LocalObject(2018, Terminal.Constructor(order_terminal))
LocalObject(2019, Terminal.Constructor(order_terminal))
LocalObject(2020, Terminal.Constructor(order_terminal))
LocalObject(2727, SpawnTube.Constructor(respawn_tube_tower, Vector3(4422.8203f, 4845.711f, 76.4375f), Vector3(0, 0, 90)))
LocalObject(2728, SpawnTube.Constructor(respawn_tube_tower, Vector3(4422.7344f, 4862.1406f, 76.4375f), Vector3(0, 0, 90)))
LocalObject(2727, SpawnTube.Constructor(respawn_tube_tower, Vector3(4422.8203f, 4845.711f, 76.4375f), Vector3.z(90)))
LocalObject(2728, SpawnTube.Constructor(respawn_tube_tower, Vector3(4422.7344f, 4862.1406f, 76.4375f), Vector3.z(90)))
ObjectToBuilding(2789, 34)
ObjectToBuilding(2951, 34)
@ -865,12 +864,12 @@ object Maps {
LocalObject(2779, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2917, Door.Constructor)
LocalObject(2918, Door.Constructor)
LocalObject(414, Door.Constructor(Vector3(3098.0f, 5032.1484f, 81.9375f), Vector3(0, 0, 180)))
LocalObject(415, Door.Constructor(Vector3(3098.0f, 5032.1484f, 91.875f), Vector3(0, 0, 180)))
LocalObject(416, Door.Constructor(Vector3(3098.0f, 5032.1484f, 111.875f), Vector3(0, 0, 180)))
LocalObject(417, Door.Constructor(Vector3(3097.9922f, 5047.875f, 81.953125f), Vector3(0, 0, 0)))
LocalObject(418, Door.Constructor(Vector3(3097.9922f, 5047.875f, 91.875f), Vector3(0, 0, 0)))
LocalObject(419, Door.Constructor(Vector3(3097.9922f, 5047.875f, 111.875f), Vector3(0, 0, 0)))
LocalObject(414, Door.Constructor(Vector3(3098.0f, 5032.1484f, 81.9375f), Vector3.z(180)))
LocalObject(415, Door.Constructor(Vector3(3098.0f, 5032.1484f, 91.875f), Vector3.z(180)))
LocalObject(416, Door.Constructor(Vector3(3098.0f, 5032.1484f, 111.875f), Vector3.z(180)))
LocalObject(417, Door.Constructor(Vector3(3097.9922f, 5047.875f, 81.953125f), Vector3.Zero))
LocalObject(418, Door.Constructor(Vector3(3097.9922f, 5047.875f, 91.875f), Vector3.Zero))
LocalObject(419, Door.Constructor(Vector3(3097.9922f, 5047.875f, 111.875f), Vector3.Zero))
LocalObject(1062, IFFLock.Constructor)
LocalObject(1063, IFFLock.Constructor)
LocalObject(1064, IFFLock.Constructor)
@ -880,8 +879,8 @@ object Maps {
LocalObject(1966, Terminal.Constructor(order_terminal))
LocalObject(1967, Terminal.Constructor(order_terminal))
LocalObject(1968, Terminal.Constructor(order_terminal))
LocalObject(2693, SpawnTube.Constructor(respawn_tube_tower, Vector3(3096.6562f, 5027.742f, 72.1875f), Vector3(0, 0, 90)))
LocalObject(2694, SpawnTube.Constructor(respawn_tube_tower, Vector3(3096.7812f, 5044.1562f, 72.1875f), Vector3(0, 0, 90)))
LocalObject(2693, SpawnTube.Constructor(respawn_tube_tower, Vector3(3096.6562f, 5027.742f, 72.1875f), Vector3.z(90)))
LocalObject(2694, SpawnTube.Constructor(respawn_tube_tower, Vector3(3096.7812f, 5044.1562f, 72.1875f), Vector3.z(90)))
ObjectToBuilding(2779, 35)
ObjectToBuilding(2917, 35)
@ -917,10 +916,10 @@ object Maps {
LocalObject(2785, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2935, Door.Constructor)
LocalObject(2936, Door.Constructor)
LocalObject(477, Door.Constructor(Vector3(3750.0f, 6040.164f, 56.203125f), Vector3(0, 0, 180)))
LocalObject(478, Door.Constructor(Vector3(3750.0f, 6040.164f, 76.15625f), Vector3(0, 0, 180)))
LocalObject(479, Door.Constructor(Vector3(3750.0078f, 6055.789f, 56.203125f), Vector3(0, 0, 0)))
LocalObject(480, Door.Constructor(Vector3(3750.0078f, 6055.789f, 76.15625f), Vector3(0, 0, 0)))
LocalObject(477, Door.Constructor(Vector3(3750.0f, 6040.164f, 56.203125f), Vector3.z(180)))
LocalObject(478, Door.Constructor(Vector3(3750.0f, 6040.164f, 76.15625f), Vector3.z(180)))
LocalObject(479, Door.Constructor(Vector3(3750.0078f, 6055.789f, 56.203125f), Vector3.Zero))
LocalObject(480, Door.Constructor(Vector3(3750.0078f, 6055.789f, 76.15625f), Vector3.Zero))
LocalObject(1109, IFFLock.Constructor)
LocalObject(1110, IFFLock.Constructor)
LocalObject(1111, IFFLock.Constructor)
@ -928,8 +927,8 @@ object Maps {
LocalObject(1995, Terminal.Constructor(order_terminal))
LocalObject(1996, Terminal.Constructor(order_terminal))
LocalObject(1997, Terminal.Constructor(order_terminal))
LocalObject(2711, SpawnTube.Constructor(respawn_tube_tower, Vector3(3748.7266f, 6035.7344f, 46.453125f), Vector3(0, 0, 90)))
LocalObject(2712, SpawnTube.Constructor(respawn_tube_tower, Vector3(3748.6328f, 6052.125f, 46.453125f), Vector3(0, 0, 90)))
LocalObject(2711, SpawnTube.Constructor(respawn_tube_tower, Vector3(3748.7266f, 6035.7344f, 46.453125f), Vector3.z(90)))
LocalObject(2712, SpawnTube.Constructor(respawn_tube_tower, Vector3(3748.6328f, 6052.125f, 46.453125f), Vector3.z(90)))
ObjectToBuilding(2785, 36)
ObjectToBuilding(2935, 36)
@ -959,10 +958,10 @@ object Maps {
LocalObject(2795, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2969, Door.Constructor)
LocalObject(2970, Door.Constructor)
LocalObject(581, Door.Constructor(Vector3(4896.0156f, 4932.125f, 67.75f), Vector3(0, 0, 180)))
LocalObject(582, Door.Constructor(Vector3(4895.992f, 4932.1484f, 87.75f), Vector3(0, 0, 180)))
LocalObject(583, Door.Constructor(Vector3(4896.0156f, 4947.8516f, 67.75f), Vector3(0, 0, 0)))
LocalObject(584, Door.Constructor(Vector3(4896.008f, 4947.8438f, 87.75f), Vector3(0, 0, 0)))
LocalObject(581, Door.Constructor(Vector3(4896.0156f, 4932.125f, 67.75f), Vector3.z(180)))
LocalObject(582, Door.Constructor(Vector3(4895.992f, 4932.1484f, 87.75f), Vector3.z(180)))
LocalObject(583, Door.Constructor(Vector3(4896.0156f, 4947.8516f, 67.75f), Vector3.Zero))
LocalObject(584, Door.Constructor(Vector3(4896.008f, 4947.8438f, 87.75f), Vector3.Zero))
LocalObject(1199, IFFLock.Constructor)
LocalObject(1200, IFFLock.Constructor)
LocalObject(1197, IFFLock.Constructor)
@ -970,8 +969,8 @@ object Maps {
LocalObject(2047, Terminal.Constructor(order_terminal))
LocalObject(2048, Terminal.Constructor(order_terminal))
LocalObject(2049, Terminal.Constructor(order_terminal))
LocalObject(2745, SpawnTube.Constructor(respawn_tube_tower, Vector3(4894.7734f, 4927.742f, 57.984375f), Vector3(0, 0, 90)))
LocalObject(2746, SpawnTube.Constructor(respawn_tube_tower, Vector3(4894.7734f, 4944.117f, 57.984375f), Vector3(0, 0, 90)))
LocalObject(2745, SpawnTube.Constructor(respawn_tube_tower, Vector3(4894.7734f, 4927.742f, 57.984375f), Vector3.z(90)))
LocalObject(2746, SpawnTube.Constructor(respawn_tube_tower, Vector3(4894.7734f, 4944.117f, 57.984375f), Vector3.z(90)))
ObjectToBuilding(2795, 55)
ObjectToBuilding(2969, 55)
@ -1001,10 +1000,10 @@ object Maps {
LocalObject(2784, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2932, Door.Constructor)
LocalObject(2933, Door.Constructor)
LocalObject(466, Door.Constructor(Vector3(3592.0f, 5286.1562f, 69.390625f), Vector3(0, 0, 180)))
LocalObject(467, Door.Constructor(Vector3(3592.0f, 5286.1562f, 89.453125f), Vector3(0, 0, 180)))
LocalObject(468, Door.Constructor(Vector3(3592.0f, 5301.797f, 69.390625f), Vector3(0, 0, 0)))
LocalObject(469, Door.Constructor(Vector3(3592.0f, 5301.797f, 89.4375f), Vector3(0, 0, 0)))
LocalObject(466, Door.Constructor(Vector3(3592.0f, 5286.1562f, 69.390625f), Vector3.z(180)))
LocalObject(467, Door.Constructor(Vector3(3592.0f, 5286.1562f, 89.453125f), Vector3.z(180)))
LocalObject(468, Door.Constructor(Vector3(3592.0f, 5301.797f, 69.390625f), Vector3.Zero))
LocalObject(469, Door.Constructor(Vector3(3592.0f, 5301.797f, 89.4375f), Vector3.Zero))
LocalObject(1101, IFFLock.Constructor)
LocalObject(1102, IFFLock.Constructor)
LocalObject(1103, IFFLock.Constructor)
@ -1012,8 +1011,8 @@ object Maps {
LocalObject(1988, Terminal.Constructor(order_terminal))
LocalObject(1989, Terminal.Constructor(order_terminal))
LocalObject(1990, Terminal.Constructor(order_terminal))
LocalObject(2708, SpawnTube.Constructor(respawn_tube_tower, Vector3(3590.9062f, 5281.742f, 59.6875f), Vector3(0, 0, 90)))
LocalObject(2709, SpawnTube.Constructor(respawn_tube_tower, Vector3(3590.836f, 5298.1484f, 59.6875f), Vector3(0, 0, 90)))
LocalObject(2708, SpawnTube.Constructor(respawn_tube_tower, Vector3(3590.9062f, 5281.742f, 59.6875f), Vector3.z(90)))
LocalObject(2709, SpawnTube.Constructor(respawn_tube_tower, Vector3(3590.836f, 5298.1484f, 59.6875f), Vector3.z(90)))
ObjectToBuilding(2784, 56)
ObjectToBuilding(2932, 56)
@ -1043,12 +1042,12 @@ object Maps {
LocalObject(2793, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2959, Door.Constructor)
LocalObject(2960, Door.Constructor)
LocalObject(546, Door.Constructor(Vector3(4669.992f, 6620.1562f, 42.875f), Vector3(0, 0, 180)))
LocalObject(547, Door.Constructor(Vector3(4669.992f, 6620.1562f, 52.8125f), Vector3(0, 0, 180)))
LocalObject(548, Door.Constructor(Vector3(4669.992f, 6620.1562f, 72.8125f), Vector3(0, 0, 180)))
LocalObject(549, Door.Constructor(Vector3(4669.9844f, 6635.8203f, 42.859375f), Vector3(0, 0, 0)))
LocalObject(550, Door.Constructor(Vector3(4669.9844f, 6635.8203f, 52.8125f), Vector3(0, 0, 0)))
LocalObject(551, Door.Constructor(Vector3(4669.9844f, 6635.8203f, 72.8125f), Vector3(0, 0, 0)))
LocalObject(546, Door.Constructor(Vector3(4669.992f, 6620.1562f, 42.875f), Vector3.z(180)))
LocalObject(547, Door.Constructor(Vector3(4669.992f, 6620.1562f, 52.8125f), Vector3.z(180)))
LocalObject(548, Door.Constructor(Vector3(4669.992f, 6620.1562f, 72.8125f), Vector3.z(180)))
LocalObject(549, Door.Constructor(Vector3(4669.9844f, 6635.8203f, 42.859375f), Vector3.Zero))
LocalObject(550, Door.Constructor(Vector3(4669.9844f, 6635.8203f, 52.8125f), Vector3.Zero))
LocalObject(551, Door.Constructor(Vector3(4669.9844f, 6635.8203f, 72.8125f), Vector3.Zero))
LocalObject(1168, IFFLock.Constructor)
LocalObject(1169, IFFLock.Constructor)
LocalObject(1170, IFFLock.Constructor)
@ -1058,8 +1057,8 @@ object Maps {
LocalObject(2030, Terminal.Constructor(order_terminal))
LocalObject(2031, Terminal.Constructor(order_terminal))
LocalObject(2032, Terminal.Constructor(order_terminal))
LocalObject(2735, SpawnTube.Constructor(respawn_tube_tower, Vector3(4668.7656f, 6615.7344f, 33.109375f), Vector3(0, 0, 90)))
LocalObject(2736, SpawnTube.Constructor(respawn_tube_tower, Vector3(4668.742f, 6632.1562f, 33.109375f), Vector3(0, 0, 90)))
LocalObject(2735, SpawnTube.Constructor(respawn_tube_tower, Vector3(4668.7656f, 6615.7344f, 33.109375f), Vector3.z(90)))
LocalObject(2736, SpawnTube.Constructor(respawn_tube_tower, Vector3(4668.742f, 6632.1562f, 33.109375f), Vector3.z(90)))
ObjectToBuilding(2793, 59)
ObjectToBuilding(2959, 59)
@ -1095,10 +1094,10 @@ object Maps {
LocalObject(2778, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2914, Door.Constructor)
LocalObject(2915, Door.Constructor)
LocalObject(404, Door.Constructor(Vector3(3003.9688f, 5706.1484f, 56.3125f), Vector3(0, 0, 180)))
LocalObject(405, Door.Constructor(Vector3(3003.9688f, 5706.1484f, 76.25f), Vector3(0, 0, 180)))
LocalObject(406, Door.Constructor(Vector3(3004.0469f, 5721.875f, 56.328125f), Vector3(0, 0, 0)))
LocalObject(407, Door.Constructor(Vector3(3004.0469f, 5721.875f, 76.25f), Vector3(0, 0, 0)))
LocalObject(404, Door.Constructor(Vector3(3003.9688f, 5706.1484f, 56.3125f), Vector3.z(180)))
LocalObject(405, Door.Constructor(Vector3(3003.9688f, 5706.1484f, 76.25f), Vector3.z(180)))
LocalObject(406, Door.Constructor(Vector3(3004.0469f, 5721.875f, 56.328125f), Vector3.Zero))
LocalObject(407, Door.Constructor(Vector3(3004.0469f, 5721.875f, 76.25f), Vector3.Zero))
LocalObject(1054, IFFLock.Constructor)
LocalObject(1055, IFFLock.Constructor)
LocalObject(1056, IFFLock.Constructor)
@ -1106,8 +1105,8 @@ object Maps {
LocalObject(1960, Terminal.Constructor(order_terminal))
LocalObject(1961, Terminal.Constructor(order_terminal))
LocalObject(1962, Terminal.Constructor(order_terminal))
LocalObject(2690, SpawnTube.Constructor(respawn_tube_tower, Vector3(3022.711f, 5701.758f, 47f), Vector3(0, 0, 90)))
LocalObject(2691, SpawnTube.Constructor(respawn_tube_tower, Vector3(3002.7188f, 5718.1562f, 47f), Vector3(0, 0, 90)))
LocalObject(2690, SpawnTube.Constructor(respawn_tube_tower, Vector3(3022.711f, 5701.758f, 47f), Vector3.z(90)))
LocalObject(2691, SpawnTube.Constructor(respawn_tube_tower, Vector3(3002.7188f, 5718.1562f, 47f), Vector3.z(90)))
ObjectToBuilding(2778, 65)
ObjectToBuilding(2914, 65)
@ -1137,7 +1136,7 @@ object Maps {
// // BFR test
//// LocalObject(199, Terminal.Constructor(vehicle_terminal_combined)))
//// LocalObject(505,
//// VehicleSpawnPad.Constructor(Vector3(3707.0f, 5522.0f, 89.0f), Vector3(0f, 0f, 0f))
//// VehicleSpawnPad.Constructor(Vector3(3707.0f, 5522.0f, 89.0f), Vector3.Zero)
//// )) //TODO guid not correct
//// ObjectToBuilding(199, 30)
//// ObjectToBuilding(505, 30)
@ -1194,21 +1193,21 @@ object Maps {
LocalObject(371, Door.Constructor) //courtyard
LocalObject(372, Door.Constructor) //courtyard
LocalObject(373, Door.Constructor) //courtyard
LocalObject(375, Door.Constructor(Vector3(3924.0f, 4231.2656f, 271.82812f), Vector3(0, 0, 180))) //2nd level door, south
LocalObject(376, Door.Constructor(Vector3(3924.0f, 4240.2656f, 271.82812f), Vector3(0, 0, 0))) //2nd level door, north
LocalObject(375, Door.Constructor(Vector3(3924.0f, 4231.2656f, 271.82812f), Vector3.z(180))) //2nd level door, south
LocalObject(376, Door.Constructor(Vector3(3924.0f, 4240.2656f, 271.82812f), Vector3.Zero)) //2nd level door, north
LocalObject(383, Door.Constructor) //courtyard
LocalObject(384, Door.Constructor(Vector3(3939.6328f, 4232.547f, 279.26562f), Vector3(0, 0, 270))) //3rd floor door
LocalObject(384, Door.Constructor(Vector3(3939.6328f, 4232.547f, 279.26562f), Vector3.z(270))) //3rd floor door
LocalObject(385, Door.Constructor) //courtyard
LocalObject(387, Door.Constructor(Vector3(3951.9531f, 4260.008f, 271.82812f), Vector3(0, 0, 270))) //2nd level door, stairwell
LocalObject(387, Door.Constructor(Vector3(3951.9531f, 4260.008f, 271.82812f), Vector3.z(270))) //2nd level door, stairwell
LocalObject(391, Door.Constructor) //courtyard
LocalObject(393, Door.Constructor(Vector3(3997.8984f, 4344.3203f, 271.8125f), Vector3(0, 0, 0))) //air term building, upstairs door
LocalObject(394, Door.Constructor(Vector3(3999.9766f, 4314.3203f, 266.82812f), Vector3(0, 0, 270))) //air term building, f.door
LocalObject(393, Door.Constructor(Vector3(3997.8984f, 4344.3203f, 271.8125f), Vector3.Zero)) //air term building, upstairs door
LocalObject(394, Door.Constructor(Vector3(3999.9766f, 4314.3203f, 266.82812f), Vector3.z(270))) //air term building, f.door
LocalObject(396, Door.Constructor) //courtyard
LocalObject(398, Door.Constructor) //courtyard
LocalObject(399, Door.Constructor) //courtyard
LocalObject(402, Door.Constructor) //courtyard
LocalObject(403, Door.Constructor) //courtyard
LocalObject(404, Door.Constructor(Vector3(4060.0078f, 4319.9766f, 266.8125f), Vector3(0, 0, 0))) //b.door
LocalObject(404, Door.Constructor(Vector3(4060.0078f, 4319.9766f, 266.8125f), Vector3.Zero)) //b.door
LocalObject(603, Door.Constructor)
LocalObject(604, Door.Constructor)
LocalObject(605, Door.Constructor)
@ -1218,19 +1217,19 @@ object Maps {
LocalObject(611, Door.Constructor)
LocalObject(614, Door.Constructor)
LocalObject(619, Door.Constructor)
LocalObject(620, Door.Constructor(Vector3(3983.9531f, 4299.992f, 249.29688f), Vector3(0, 0, 90))) //generator room door
LocalObject(620, Door.Constructor(Vector3(3983.9531f, 4299.992f, 249.29688f), Vector3.z(90))) //generator room door
LocalObject(621, Door.Constructor)
LocalObject(622, Door.Constructor(Vector3(3988.0078f, 4248.0156f, 256.82812f), Vector3(0, 0, 180))) //spawn room door
LocalObject(623, Door.Constructor(Vector3(3988.0078f, 4271.9766f, 256.79688f), Vector3(0, 0, 0))) //spawn room door
LocalObject(630, Door.Constructor(Vector3(4000.0078f, 4252.0f, 249.29688f), Vector3(0, 0, 270))) //spawn room door
LocalObject(622, Door.Constructor(Vector3(3988.0078f, 4248.0156f, 256.82812f), Vector3.z(180))) //spawn room door
LocalObject(623, Door.Constructor(Vector3(3988.0078f, 4271.9766f, 256.79688f), Vector3.Zero)) //spawn room door
LocalObject(630, Door.Constructor(Vector3(4000.0078f, 4252.0f, 249.29688f), Vector3.z(270))) //spawn room door
LocalObject(631, Door.Constructor) //spawn room door, kitchen
LocalObject(634, Door.Constructor) //air term building, interior
LocalObject(638, Door.Constructor(Vector3(4016.0078f, 4212.008f, 249.29688f), Vector3(0, 0, 270))) //cc door
LocalObject(642, Door.Constructor(Vector3(4023.9844f, 4212.008f, 249.32812f), Vector3(0, 0, 90))) //cc door, interior
LocalObject(638, Door.Constructor(Vector3(4016.0078f, 4212.008f, 249.29688f), Vector3.z(270))) //cc door
LocalObject(642, Door.Constructor(Vector3(4023.9844f, 4212.008f, 249.32812f), Vector3.z(90))) //cc door, interior
LocalObject(643, Door.Constructor) //cc door, exterior
LocalObject(645, Door.Constructor) //b.door, interior
LocalObject(646, Door.Constructor) //b.door, interior
LocalObject(715, Door.Constructor(Vector3(3961.5938f ,4235.8125f, 266.84375f), Vector3(0, 0, 90))) //f.door
LocalObject(715, Door.Constructor(Vector3(3961.5938f ,4235.8125f, 266.84375f), Vector3.z(90))) //f.door
LocalObject(751, IFFLock.Constructor)
LocalObject(860, IFFLock.Constructor)
LocalObject(863, IFFLock.Constructor)
@ -1265,8 +1264,8 @@ object Maps {
LocalObject(1428, FacilityTurret.Constructor(manned_turret))
LocalObject(1431, FacilityTurret.Constructor(manned_turret))
LocalObject(1432, FacilityTurret.Constructor(manned_turret))
LocalObject(1492, ProximityTerminal.Constructor(medical_terminal)) //lobby
LocalObject(1494, ProximityTerminal.Constructor(medical_terminal)) //kitchen
LocalObject(1492, ProximityTerminal.Constructor(medical_terminal, Vector3(3944.8672f, 4211.336f, 266.85938f))) //lobby
LocalObject(1494, ProximityTerminal.Constructor(medical_terminal, Vector3(4008.3594f, 4269.25f, 249.35938f))) //kitchen
LocalObject(1564, Terminal.Constructor(order_terminal))
LocalObject(1568, Terminal.Constructor(order_terminal))
LocalObject(1569, Terminal.Constructor(order_terminal))
@ -1275,21 +1274,21 @@ object Maps {
LocalObject(1576, Terminal.Constructor(order_terminal))
LocalObject(1577, Terminal.Constructor(order_terminal))
LocalObject(1578, Terminal.Constructor(order_terminal))
LocalObject(1744, ProximityTerminal.Constructor(pad_landing)) //air pad A
LocalObject(1745, Terminal.Constructor(pad_landing)) //air pad A
LocalObject(1747, ProximityTerminal.Constructor(pad_landing)) //air pad B
LocalObject(1748, Terminal.Constructor(pad_landing)) //air pad B
LocalObject(1756, ProximityTerminal.Constructor(pad_landing)) //air pad C
LocalObject(1757, Terminal.Constructor(pad_landing)) //air pad C
LocalObject(1765, ProximityTerminal.Constructor(pad_landing)) //air pad D
LocalObject(1766, Terminal.Constructor(pad_landing)) //air pad D
LocalObject(2145, SpawnTube.Constructor(Vector3(3980.4062f, 4252.7656f, 257.5625f), Vector3(0, 0, 90)))
LocalObject(2146, SpawnTube.Constructor(Vector3(3980.4062f, 4259.992f, 257.5625f), Vector3(0, 0, 90)))
LocalObject(2147, SpawnTube.Constructor(Vector3(3980.4062f, 4267.3047f, 257.5625f), Vector3(0, 0, 90)))
LocalObject(2049, ProximityTerminal.Constructor(repair_silo)) //repair terminal A
LocalObject(2050, Terminal.Constructor(repair_silo)) //rearm terminal A
LocalObject(2061, ProximityTerminal.Constructor(repair_silo)) //repair terminal B
LocalObject(2062, Terminal.Constructor(repair_silo)) //rearm terminal B
LocalObject(1744, ProximityTerminal.Constructor(pad_landing_frame, Vector3(3924.8203f, 4331.789f, 275.92188f))) //air pad North
LocalObject(1745, Terminal.Constructor(air_rearm_terminal)) //air pad North
LocalObject(1747, ProximityTerminal.Constructor(pad_landing_frame, Vector3(3941.8984f, 4288.9844f, 273.20312f))) //air pad South
LocalObject(1748, Terminal.Constructor(air_rearm_terminal)) //air pad South
LocalObject(1756, ProximityTerminal.Constructor(pad_landing_frame, Vector3(3995.3516f, 4251.547f, 280.375f))) //air pad West
LocalObject(1757, Terminal.Constructor(air_rearm_terminal)) //air pad West
LocalObject(1765, ProximityTerminal.Constructor(pad_landing_frame, Vector3(4027.5469f, 4268.414f, 275.92188f))) //air pad East
LocalObject(1766, Terminal.Constructor(air_rearm_terminal)) //air pad East
LocalObject(2145, SpawnTube.Constructor(Vector3(3980.4062f, 4252.7656f, 257.5625f), Vector3.z(90)))
LocalObject(2146, SpawnTube.Constructor(Vector3(3980.4062f, 4259.992f, 257.5625f), Vector3.z(90)))
LocalObject(2147, SpawnTube.Constructor(Vector3(3980.4062f, 4267.3047f, 257.5625f), Vector3.z(90)))
LocalObject(2049, ProximityTerminal.Constructor(repair_silo, Vector3(3882.0078f, 4278.2266f, 266.4375f))) //repair terminal West
LocalObject(2050, Terminal.Constructor(ground_rearm_terminal)) //rearm terminal West
LocalObject(2061, ProximityTerminal.Constructor(repair_silo, Vector3(4053.3516f, 4281.1562f, 266.4375f))) //repair terminal East
LocalObject(2062, Terminal.Constructor(ground_rearm_terminal)) //rearm terminal East
LocalObject(2094, ResourceSilo.Constructor)
LocalObject(2239, Terminal.Constructor(spawn_terminal))
LocalObject(2244, Terminal.Constructor(spawn_terminal))
@ -1309,7 +1308,7 @@ object Maps {
)
LocalObject(224, Terminal.Constructor(dropship_vehicle_terminal))
LocalObject(223,
VehicleSpawnPad.Constructor(Vector3(4012.3594f, 4364.8047f, 271.90625f), Vector3(0f, 0f, 0f))
VehicleSpawnPad.Constructor(Vector3(4012.3594f, 4364.8047f, 271.90625f), Vector3.Zero)
)
ObjectToBuilding(180, 2)
ObjectToBuilding(222, 2)
@ -1475,12 +1474,12 @@ object Maps {
def Building48() : Unit = {
//North Anguta Watchtower
LocalBuilding(48, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(3864.2266f, 4518.0234f, 0))))
LocalObject(364, Door.Constructor(Vector3(3871.9688f, 4509.992f, 269.65625f), Vector3(0f, 0f, 180f))) //s1
LocalObject(365, Door.Constructor(Vector3(3871.9688f, 4509.992f, 279.57812f), Vector3(0f, 0f, 180f))) //s2
LocalObject(366, Door.Constructor(Vector3(3871.9688f, 4509.992f, 299.57812f), Vector3(0f, 0f, 180f))) //s3
LocalObject(367, Door.Constructor(Vector3(3871.9688f, 4525.9844f, 269.65625f), Vector3(0f, 0f, 0f))) //n1
LocalObject(368, Door.Constructor(Vector3(3871.9688f, 4525.9844f, 279.57812f), Vector3(0f, 0f, 0f))) //n2
LocalObject(369, Door.Constructor(Vector3(3871.9688f, 4525.9844f, 299.57812f), Vector3(0f, 0f, 0f))) //n3
LocalObject(364, Door.Constructor(Vector3(3871.9688f, 4509.992f, 269.65625f), Vector3.z(180f))) //s1
LocalObject(365, Door.Constructor(Vector3(3871.9688f, 4509.992f, 279.57812f), Vector3.z(180f))) //s2
LocalObject(366, Door.Constructor(Vector3(3871.9688f, 4509.992f, 299.57812f), Vector3.z(180f))) //s3
LocalObject(367, Door.Constructor(Vector3(3871.9688f, 4525.9844f, 269.65625f), Vector3.Zero)) //n1
LocalObject(368, Door.Constructor(Vector3(3871.9688f, 4525.9844f, 279.57812f), Vector3.Zero)) //n2
LocalObject(369, Door.Constructor(Vector3(3871.9688f, 4525.9844f, 299.57812f), Vector3.Zero)) //n3
LocalObject(854, IFFLock.Constructor)
LocalObject(855, IFFLock.Constructor)
LocalObject(856, IFFLock.Constructor)
@ -1498,8 +1497,8 @@ object Maps {
LocalObject(1561, Terminal.Constructor(order_terminal))
LocalObject(1562, Terminal.Constructor(order_terminal))
LocalObject(1563, Terminal.Constructor(order_terminal))
LocalObject(2138, SpawnTube.Constructor(respawn_tube_tower, Vector3(3870.9688f, 4505.7266f, 259.875f), Vector3(0, 0, 90)))
LocalObject(2139, SpawnTube.Constructor(respawn_tube_tower, Vector3(3870.9688f, 4522.1562f, 259.875f), Vector3(0, 0, 90)))
LocalObject(2138, SpawnTube.Constructor(respawn_tube_tower, Vector3(3870.9688f, 4505.7266f, 259.875f), Vector3.z(90)))
LocalObject(2139, SpawnTube.Constructor(respawn_tube_tower, Vector3(3870.9688f, 4522.1562f, 259.875f), Vector3.z(90)))
LocalObject(2197, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2315, Door.Constructor) //spawn tube door
LocalObject(2316, Door.Constructor) //spawn tube door
@ -1542,10 +1541,10 @@ object Maps {
def Building49() : Unit = {
//North Akna Air Tower
LocalBuilding(49, FoundationBuilder(Building.Structure(StructureType.Tower, Vector3(4358.3203f, 3989.5625f, 0))))
LocalObject(430, Door.Constructor(Vector3(4366.0156f, 3981.9922f, 237.96875f), Vector3(0f, 0f, 180f))) //s1
LocalObject(431, Door.Constructor(Vector3(4366.0156f, 3981.9922f, 257.89062f), Vector3(0f, 0f, 180f))) //s2
LocalObject(432, Door.Constructor(Vector3(4366.0156f, 3997.9297f, 237.96875f), Vector3(0f, 0f, 0f))) //n1
LocalObject(433, Door.Constructor(Vector3(4366.0156f, 3997.9297f, 257.89062f), Vector3(0f, 0f, 0f))) //n2
LocalObject(430, Door.Constructor(Vector3(4366.0156f, 3981.9922f, 237.96875f), Vector3.z(180f))) //s1
LocalObject(431, Door.Constructor(Vector3(4366.0156f, 3981.9922f, 257.89062f), Vector3.z(180f))) //s2
LocalObject(432, Door.Constructor(Vector3(4366.0156f, 3997.9297f, 237.96875f), Vector3.Zero)) //n1
LocalObject(433, Door.Constructor(Vector3(4366.0156f, 3997.9297f, 257.89062f), Vector3.Zero)) //n2
LocalObject(902, IFFLock.Constructor)
LocalObject(903, IFFLock.Constructor)
LocalObject(906, IFFLock.Constructor)
@ -1563,12 +1562,12 @@ object Maps {
LocalObject(1591, Terminal.Constructor(order_terminal))
LocalObject(1592, Terminal.Constructor(order_terminal))
LocalObject(1593, Terminal.Constructor(order_terminal))
LocalObject(1846, ProximityTerminal.Constructor(pad_landing)) //air pad S
LocalObject(1847, Terminal.Constructor(pad_landing)) //air pad S
LocalObject(1849, ProximityTerminal.Constructor(pad_landing)) //air pad N
LocalObject(1850, Terminal.Constructor(pad_landing)) //air pad N
LocalObject(2156, SpawnTube.Constructor(respawn_tube_tower, Vector3(4364.633f, 3994.125f, 228.1875f), Vector3(0, 0, 90)))
LocalObject(2157, SpawnTube.Constructor(respawn_tube_tower, Vector3(4364.633f, 3977.7266f, 228.1875f), Vector3(0, 0, 90)))
LocalObject(1846, ProximityTerminal.Constructor(pad_landing_tower_frame, Vector3(4352.3984f, 3984.7422f, 266.125f))) //air pad South
LocalObject(1847, Terminal.Constructor(air_rearm_terminal)) //air pad South
LocalObject(1849, ProximityTerminal.Constructor(pad_landing_tower_frame, Vector3(4352.3984f, 3995.2812f, 266.125f))) //air pad North
LocalObject(1850, Terminal.Constructor(air_rearm_terminal)) //air pad North
LocalObject(2156, SpawnTube.Constructor(respawn_tube_tower, Vector3(4364.633f, 3994.125f, 228.1875f), Vector3.z(90)))
LocalObject(2157, SpawnTube.Constructor(respawn_tube_tower, Vector3(4364.633f, 3977.7266f, 228.1875f), Vector3.z(90)))
LocalObject(2203, CaptureTerminal.Constructor(secondary_capture))
LocalObject(2333, Door.Constructor) //spawn tube door
LocalObject(2334, Door.Constructor) //spawn tube door
@ -1653,7 +1652,7 @@ object Maps {
LocalBuilding(67, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(1, 0, 0))))
LocalObject(282, Door.Constructor) //spawn tube door
LocalObject(396, Door.Constructor) //entrance
LocalObject(766, SpawnTube.Constructor(Vector3(3138.0f, 2875.0f, 36.2f), Vector3(0, 0, 180)))
LocalObject(766, SpawnTube.Constructor(Vector3(3138.0f, 2875.0f, 36.2f), Vector3.z(180)))
ObjectToBuilding(282, 67)
ObjectToBuilding(396, 67)
ObjectToBuilding(766, 67)
@ -1686,7 +1685,7 @@ object Maps {
LocalBuilding(67, FoundationBuilder(Building.Structure(StructureType.Building, Vector3(1, 0, 0))))
LocalObject(282, Door.Constructor) //spawn tube door
LocalObject(396, Door.Constructor) //entrance
LocalObject(766, SpawnTube.Constructor(Vector3(3138.0f, 2875.0f, 36.2f), Vector3(0, 0, 180)))
LocalObject(766, SpawnTube.Constructor(Vector3(3138.0f, 2875.0f, 36.2f), Vector3.z(180)))
ObjectToBuilding(282, 67)
ObjectToBuilding(396, 67)
ObjectToBuilding(766, 67)
@ -1758,10 +1757,10 @@ object Maps {
LocalObject(691, Locker.Constructor)
LocalObject(692, Locker.Constructor)
LocalObject(693, Locker.Constructor)
LocalObject(778, ProximityTerminal.Constructor(medical_terminal))
LocalObject(779, ProximityTerminal.Constructor(medical_terminal))
LocalObject(780, ProximityTerminal.Constructor(medical_terminal))
LocalObject(781, ProximityTerminal.Constructor(medical_terminal))
LocalObject(778, ProximityTerminal.Constructor(medical_terminal, Vector3(3617.3516f, 2785.3281f, 93.65625f))) //medical terminal Southwest
LocalObject(779, ProximityTerminal.Constructor(medical_terminal, Vector3(3617.3516f, 2830.414f, 93.65625f))) //medical terminal Southeast
LocalObject(780, ProximityTerminal.Constructor(medical_terminal, Vector3(3758.7031f, 2785.3281f, 93.65625f))) //medical terminal Southeast
LocalObject(781, ProximityTerminal.Constructor(medical_terminal, Vector3(3758.7031f, 2830.414f, 93.65625f))) //medical terminal Northeast
LocalObject(842, Terminal.Constructor(order_terminal))
LocalObject(843, Terminal.Constructor(order_terminal))
LocalObject(844, Terminal.Constructor(order_terminal))
@ -1835,10 +1834,10 @@ object Maps {
def Building29() : Unit = {
//South Villa Gun Tower
LocalBuilding(29, FoundationBuilder(Building.Structure(StructureType.Tower)))
LocalObject(330, Door.Constructor(Vector3(3979.9219f, 2592.0547f, 91.140625f), Vector3(0, 0, 180)))
LocalObject(331, Door.Constructor(Vector3(3979.9219f, 2592.0547f, 111.140625f), Vector3(0, 0, 180)))
LocalObject(332, Door.Constructor(Vector3(3979.9688f, 2608.0625f, 91.140625f), Vector3(0, 0, 0)))
LocalObject(333, Door.Constructor(Vector3(3979.9688f, 2608.0625f, 111.140625f), Vector3(0, 0, 0)))
LocalObject(330, Door.Constructor(Vector3(3979.9219f, 2592.0547f, 91.140625f), Vector3.z(180)))
LocalObject(331, Door.Constructor(Vector3(3979.9219f, 2592.0547f, 111.140625f), Vector3.z(180)))
LocalObject(332, Door.Constructor(Vector3(3979.9688f, 2608.0625f, 91.140625f), Vector3.Zero))
LocalObject(333, Door.Constructor(Vector3(3979.9688f, 2608.0625f, 111.140625f), Vector3.Zero))
LocalObject(556, IFFLock.Constructor)
LocalObject(557, IFFLock.Constructor)
LocalObject(558, IFFLock.Constructor)
@ -1882,12 +1881,12 @@ object Maps {
LocalObject(433, Door.Constructor) //vr door
LocalObject(434, Door.Constructor) //vr door
LocalObject(435, Door.Constructor) //vr door
LocalObject(744, SpawnTube.Constructor(Vector3(3684.336f, 2709.0469f, 91.9f), Vector3(0, 0, 180)))
LocalObject(745, SpawnTube.Constructor(Vector3(3684.336f, 2713.75f, 91.9f), Vector3(0, 0, 0)))
LocalObject(746, SpawnTube.Constructor(Vector3(3690.9062f, 2708.4219f, 91.9f), Vector3(0, 0, 180)))
LocalObject(747, SpawnTube.Constructor(Vector3(3691.0703f, 2713.8672f, 91.9f), Vector3(0, 0, 0)))
LocalObject(748, SpawnTube.Constructor(Vector3(3697.664f, 2708.3984f, 91.9f), Vector3(0, 0, 180)))
LocalObject(749, SpawnTube.Constructor(Vector3(3697.711f, 2713.2344f, 91.9f), Vector3(0, 0, 0)))
LocalObject(744, SpawnTube.Constructor(Vector3(3684.336f, 2709.0469f, 91.9f), Vector3.z(180)))
LocalObject(745, SpawnTube.Constructor(Vector3(3684.336f, 2713.75f, 91.9f), Vector3.Zero))
LocalObject(746, SpawnTube.Constructor(Vector3(3690.9062f, 2708.4219f, 91.9f), Vector3.z(180)))
LocalObject(747, SpawnTube.Constructor(Vector3(3691.0703f, 2713.8672f, 91.9f), Vector3.Zero))
LocalObject(748, SpawnTube.Constructor(Vector3(3697.664f, 2708.3984f, 91.9f), Vector3.z(180)))
LocalObject(749, SpawnTube.Constructor(Vector3(3697.711f, 2713.2344f, 91.9f), Vector3.Zero))
LocalObject(852, Terminal.Constructor(order_terminal)) //s. wall
LocalObject(853, Terminal.Constructor(order_terminal)) //n. wall
LocalObject(854, Terminal.Constructor(order_terminal)) //s. wall
@ -1923,9 +1922,9 @@ object Maps {
}
def Building51() : Unit = {
//air terminal west of HART C
LocalObject(12, ProximityTerminal.Constructor(repair_silo)) //repair terminal
LocalObject(13, Terminal.Constructor(repair_silo)) //rearm terminal
//air terminal & silo west of HART C
LocalObject(12, ProximityTerminal.Constructor(repair_silo, Vector3(3646.6328f, 2870.9062f, 91.046875f))) //repair terminal
LocalObject(13, Terminal.Constructor(ground_rearm_terminal)) //rearm terminal
LocalBuilding(51, FoundationBuilder(Building.Structure(StructureType.Platform)))
LocalObject(304, Terminal.Constructor(dropship_vehicle_terminal))
LocalObject(292,

View file

@ -90,8 +90,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
var spectator : Boolean = false
var admin : Boolean = false
var usingMedicalTerminal : Option[PlanetSideGUID] = None
var usingProximityTerminal : Set[PlanetSideGUID] = Set.empty
var delayedProximityTerminalResets : Map[PlanetSideGUID, Cancellable] = Map.empty
var controlled : Option[Int] = None
//keep track of avatar's ServerVehicleOverride state
var traveler : Traveler = null
@ -133,18 +131,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
LivePlayerList.Remove(sessionId)
if(player != null && player.HasGUID) {
val player_guid = player.GUID
//proximity vehicle terminals must be considered too
delayedProximityTerminalResets.foreach({ case (_, task) => task.cancel })
usingProximityTerminal.foreach(term_guid => {
continent.GUID(term_guid) match {
case Some(obj : ProximityTerminal) =>
if(obj.NumberUsers > 0 && obj.RemoveUser(player_guid) == 0) {
//refer to ProximityTerminalControl when modernizng
localService ! LocalServiceMessage(continent.Id, LocalAction.ProximityTerminalEffect(player_guid, term_guid, false))
}
case _ => ;
}
})
//handle orphaned deployables
DisownDeployables()
//clean up boomer triggers and telepads
@ -295,6 +281,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
case Terminal.TerminalMessage(tplayer, msg, order) =>
HandleTerminalMessage(tplayer, msg, order)
case ProximityUnit.Action(term, target) =>
SelectProximityUnitBehavior(term, target)
case VehicleServiceResponse(toChannel, guid, reply) =>
HandleVehicleServiceResponse(toChannel, guid, reply)
@ -835,9 +824,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
case HackingProgress(progressType, tplayer, target, tool_guid, delta, completeAction, tickAction) =>
HandleHackingProgress(progressType, tplayer, target, tool_guid, delta, completeAction, tickAction)
case DelayedProximityUnitStop(terminal) =>
StopUsingProximityUnit(terminal)
case Vitality.DamageResolution(target : Vehicle) =>
HandleVehicleDamageResolution(target)
@ -1304,10 +1290,12 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(ObjectDeleteMessage(object_guid, unk))
}
case LocalResponse.ProximityTerminalEffect(object_guid, effectState) =>
if(tplayer_guid != guid) {
sendResponse(ProximityTerminalUseMessage(PlanetSideGUID(0), object_guid, effectState))
}
case LocalResponse.ProximityTerminalEffect(object_guid, true) =>
sendResponse(ProximityTerminalUseMessage(PlanetSideGUID(0), object_guid, true))
case LocalResponse.ProximityTerminalEffect(object_guid, false) =>
sendResponse(ProximityTerminalUseMessage(PlanetSideGUID(0), object_guid, false))
ForgetAllProximityTerminals(object_guid)
case LocalResponse.RouterTelepadMessage(msg) =>
sendResponse(ChatMsg(ChatMessageType.UNK_229, false, "", msg, None))
@ -1569,6 +1557,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
else {
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, false))
}
lastTerminalOrderFulfillment = true
case Terminal.BuyEquipment(item) =>
tplayer.Fit(item) match {
@ -1578,6 +1567,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
case None =>
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Buy, false))
}
lastTerminalOrderFulfillment = true
case Terminal.SellEquipment() =>
tplayer.FreeHand.Equipment match {
@ -1589,6 +1579,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
case None =>
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Sell, false))
}
lastTerminalOrderFulfillment = true
case Terminal.InfantryLoadout(exosuit, subtype, holsters, inventory) =>
log.info(s"$tplayer wants to change equipment loadout to their option #${msg.unk1 + 1}")
@ -1657,6 +1648,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}) ++ dropHolsters ++ dropInventory).foreach(entry => {
continent.Ground ! Zone.Ground.DropItem(entry.obj, pos, orient)
})
lastTerminalOrderFulfillment = true
case Terminal.VehicleLoadout(definition, weapons, inventory) =>
log.info(s"$tplayer wants to change their vehicle equipment loadout to their option #${msg.unk1 + 1}")
@ -1704,6 +1696,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.error(s"can not apply the loadout - can not find a vehicle")
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Loadout, false))
}
lastTerminalOrderFulfillment = true
case Terminal.LearnCertification(cert) =>
val name = tplayer.Name
@ -1726,6 +1719,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.warn(s"$name already knows the $cert certification, so he can't learn it")
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, false))
}
lastTerminalOrderFulfillment = true
case Terminal.SellCertification(cert) =>
val name = tplayer.Name
@ -1749,6 +1743,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.warn(s"$name doesn't know what a $cert certification is, so he can't forget it")
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, false))
}
lastTerminalOrderFulfillment = true
case Terminal.LearnImplant(implant) =>
val terminal_guid = msg.terminal_guid
@ -1790,6 +1785,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
sendResponse(ItemTransactionResultMessage(terminal_guid, TransactionType.Learn, false))
}
lastTerminalOrderFulfillment = true
case Terminal.SellImplant(implant) =>
val terminal_guid = msg.terminal_guid
@ -1825,16 +1821,17 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
sendResponse(ItemTransactionResultMessage(terminal_guid, TransactionType.Sell, false))
}
lastTerminalOrderFulfillment = true
case Terminal.BuyVehicle(vehicle, weapons, trunk) =>
continent.Map.TerminalToSpawnPad.get(msg.terminal_guid.guid) match {
case Some(pad_guid) =>
val pad = continent.GUID(pad_guid).get.asInstanceOf[VehicleSpawnPad]
vehicle.Faction = tplayer.Faction
vehicle.Continent = continent.Id
vehicle.Position = pad.Position
vehicle.Orientation = pad.Orientation
//default loadout, weapons
log.info(s"default weapons: ${weapons.size}")
val vWeapons = vehicle.Weapons
weapons.foreach(entry => {
val index = entry.start
@ -1843,11 +1840,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
slot.Equipment = None
slot.Equipment = entry.obj
case None =>
log.warn(s"applying default loadout to $vehicle, can not find a mounted weapon @ $index")
log.warn(s"applying default loadout to $vehicle on spawn, but can not find a mounted weapon @ $index")
}
})
//default loadout, trunk
log.info(s"default trunk: ${trunk.size}")
val vTrunk = vehicle.Trunk
vTrunk.Clear()
trunk.foreach(entry => {
@ -1859,22 +1855,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
case None =>
log.error(s"$tplayer wanted to spawn a vehicle, but there was no spawn pad associated with terminal ${msg.terminal_guid} to accept it")
}
lastTerminalOrderFulfillment = true
case Terminal.StartProximityEffect(term) =>
val player_guid = player.GUID
val term_guid = term.GUID
StartUsingProximityUnit(term) //redundant but cautious
sendResponse(ProximityTerminalUseMessage(player_guid, term_guid, true))
localService ! LocalServiceMessage(continent.Id, LocalAction.ProximityTerminalEffect(player_guid, term_guid, true))
case Terminal.StopProximityEffect(term) =>
val player_guid = player.GUID
val term_guid = term.GUID
StopUsingProximityUnit(term) //redundant but cautious
sendResponse(ProximityTerminalUseMessage(player_guid, term_guid, false))
localService ! LocalServiceMessage(continent.Id, LocalAction.ProximityTerminalEffect(player_guid, term_guid, false))
case Terminal.NoDeal() =>
case _ =>
val order : String = if(msg == null) {
s"order $msg"
}
@ -1883,8 +1866,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
log.warn(s"${tplayer.Name} made a request but the terminal rejected the $order")
sendResponse(ItemTransactionResultMessage(msg.terminal_guid, msg.transaction_type, false))
lastTerminalOrderFulfillment = true
}
lastTerminalOrderFulfillment = true
}
/**
@ -2866,7 +2849,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
player.Jumping = is_jumping
if(vel.isDefined && usingMedicalTerminal.isDefined) {
StopUsingProximityUnit(continent.GUID(usingMedicalTerminal.get).get.asInstanceOf[ProximityTerminal])
continent.GUID(usingMedicalTerminal) match {
case Some(term : Terminal with ProximityUnit) =>
StopUsingProximityUnit(term)
case _ => ;
}
}
accessedContainer match {
case Some(veh : Vehicle) =>
@ -3316,10 +3303,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
// Stop using proximity terminals if player unholsters a weapon (which should re-trigger the proximity effect and re-holster the weapon)
if(player.VisibleSlots.contains(held_holsters)) {
usingMedicalTerminal match {
case Some(term_guid) =>
StopUsingProximityUnit(continent.GUID(term_guid).get.asInstanceOf[ProximityTerminal])
case None => ;
continent.GUID(usingMedicalTerminal) match {
case Some(term : Terminal with ProximityUnit) =>
StopUsingProximityUnit(term)
case _ => ;
}
}
}
@ -3764,7 +3751,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
//TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
sendResponse(BindPlayerMessage(BindStatus.Bind, "", true, true, SpawnGroup.Sanctuary, 0, 0, terminal.Position))
}
else if(tdef.isInstanceOf[RepairRearmSiloDefinition] || tdef == GlobalDefinitions.multivehicle_rearm_terminal) {
else if(tdef == GlobalDefinitions.multivehicle_rearm_terminal || tdef == GlobalDefinitions.bfr_rearm_terminal ||
tdef == GlobalDefinitions.air_rearm_terminal || tdef == GlobalDefinitions.ground_rearm_terminal) {
FindLocalVehicle match {
case Some(vehicle) =>
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
@ -3847,12 +3835,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.info(s"ProximityTerminalUse: $msg")
continent.GUID(object_guid) match {
case Some(obj : Terminal with ProximityUnit) =>
if(usingProximityTerminal.contains(object_guid)) {
SelectProximityUnit(obj)
}
else {
StartUsingProximityUnit(obj)
}
HandleProximityTerminalUse(obj)
case Some(obj) => ;
log.warn(s"ProximityTerminalUse: object does not have proximity effects - $obj")
case None =>
@ -6011,7 +5994,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player_guid, 29, 1))
}
PlayerActionsToCancel()
CancelAllProximityUnits()
//TODO other methods of death?
val pentry = PlayerSource(tplayer)
(tplayer.History.find({p => p.isInstanceOf[PlayerSuicide]}) match {
@ -6222,21 +6204,73 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
/**
* Start using a proximity-base service.
* Special note is warranted in the case of a medical terminal or an advanced medical terminal.
* @param terminal the proximity-based unit
* na
* @param terminal na
*/
def StartUsingProximityUnit(terminal : Terminal with ProximityUnit) : Unit = {
def HandleProximityTerminalUse(terminal : Terminal with ProximityUnit) : Unit = {
val term_guid = terminal.GUID
if(!usingProximityTerminal.contains(term_guid)) {
usingProximityTerminal += term_guid
val targets = FindProximityUnitTargetsInScope(terminal)
val currentTargets = terminal.Targets
targets.foreach(target => {
if(!currentTargets.contains(target)) {
StartUsingProximityUnit(terminal, target)
}
else if(targets.isEmpty) {
log.warn(s"HandleProximityTerminalUse: ${player.Name} could not find valid targets to give to proximity unit ${terminal.Definition.Name}@${term_guid.guid}")
}
})
}
/**
* na
* @param terminal na
* @return na
*/
def FindProximityUnitTargetsInScope(terminal : Terminal with ProximityUnit) : Seq[PlanetSideGameObject] = {
terminal.Definition.asInstanceOf[ProximityDefinition].TargetValidation.keySet collect {
case ProximityTarget.Player => Some(player)
case ProximityTarget.Vehicle | ProximityTarget.Aircraft => continent.GUID(player.VehicleSeated)
} collect {
case Some(a) => a
} toSeq
}
/**
* Queue a proximity-base service.
* @param terminal the proximity-based unit
* @param target the entity that is being considered for terminal operation
*/
def StartUsingProximityUnit(terminal : Terminal with ProximityUnit, target : PlanetSideGameObject) : Unit = {
val term_guid = terminal.GUID
if(player.isAlive) {
log.info(s"StartUsingProximityUnit: ${player.Name} wants to use ${terminal.Definition.Name}@${term_guid.guid} on $target")
target match {
case _ : Player =>
terminal.Actor ! CommonMessages.Use(player, Some(target))
case _ : Vehicle =>
terminal.Actor ! CommonMessages.Use(player, Some((target, vehicleService)))
case _ =>
log.error(s"StartUsingProximityUnit: can not deal with target $target")
}
terminal.Definition match {
case GlobalDefinitions.adv_med_terminal | GlobalDefinitions.medical_terminal =>
usingMedicalTerminal = Some(term_guid)
case _ =>
SetDelayedProximityUnitReset(terminal)
case _ => ;
}
terminal.Actor ! CommonMessages.Use(player)
}
}
/**
* Determine which functionality to pursue by a generic proximity-functional unit given the target for its activity.
* @see `VehicleService:receive, ProximityUnit.Action`
* @param terminal the proximity-based unit
* @param target the object being affected by the unit
*/
def SelectProximityUnitBehavior(terminal : Terminal with ProximityUnit, target : PlanetSideGameObject) : Unit = {
target match {
case o : Player =>
HealthAndArmorTerminal(terminal, o)
case _ => ;
}
}
@ -6249,42 +6283,27 @@ class WorldSessionActor extends Actor with MDCContextAware {
*/
def StopUsingProximityUnit(terminal : Terminal with ProximityUnit) : Unit = {
val term_guid = terminal.GUID
if(usingProximityTerminal.contains(term_guid)) {
usingProximityTerminal -= term_guid
ClearDelayedProximityUnitReset(term_guid)
log.info(s"StopUsingProximityUnit: attempting to stop using proximity unit ${terminal.Definition.Name}@${term_guid.guid}")
val targets = FindProximityUnitTargetsInScope(terminal)
if(targets.nonEmpty) {
if(usingMedicalTerminal.contains(term_guid)) {
usingMedicalTerminal = None
}
terminal.Actor ! CommonMessages.Unuse(player)
targets.foreach(target =>
terminal.Actor ! CommonMessages.Unuse(player, Some(target))
)
}
else {
log.warn(s"StopUsingProximityUnit: ${player.Name} could not find valid targets for proximity unit ${terminal.Definition.Name}@${term_guid.guid}")
}
}
/**
* For pure proximity-based units and services, a manual attempt at cutting off the functionality.
* First, if an existing timer can be found, cancel it.
* Then, create a new timer.
* If this timer completes, a message will be sent that will attempt to disassociate from the target proximity unit.
* @param terminal the proximity-based unit
*
*/
def SetDelayedProximityUnitReset(terminal : Terminal with ProximityUnit) : Unit = {
val terminal_guid = terminal.GUID
ClearDelayedProximityUnitReset(terminal_guid)
import scala.concurrent.ExecutionContext.Implicits.global
delayedProximityTerminalResets += terminal_guid ->
context.system.scheduler.scheduleOnce(3000 milliseconds, self, DelayedProximityUnitStop(terminal))
}
/**
* For pure proximity-based units and services, disable any manual attempt at cutting off the functionality.
* If an existing timer can be found, cancel it.
* @param terminal_guid the proximity-based unit
*/
def ClearDelayedProximityUnitReset(terminal_guid : PlanetSideGUID) : Unit = {
delayedProximityTerminalResets.get(terminal_guid) match {
case Some(task) =>
task.cancel
delayedProximityTerminalResets -= terminal_guid
case None => ;
def ForgetAllProximityTerminals(term_guid : PlanetSideGUID) : Unit = {
if(usingMedicalTerminal.contains(term_guid)) {
usingMedicalTerminal = None
}
}
@ -6292,37 +6311,15 @@ class WorldSessionActor extends Actor with MDCContextAware {
* Cease all current interactions with proximity-based units.
* Pair with `PlayerActionsToCancel`, except when logging out (stopping).
* This operations may invoke callback messages.
* @see `postStop`<br>
* `Terminal.StopProximityEffects`
* @see `postStop`
*/
def CancelAllProximityUnits() : Unit = {
delayedProximityTerminalResets.foreach({case(term_guid, task) =>
task.cancel
delayedProximityTerminalResets -= term_guid
})
usingProximityTerminal.foreach(term_guid => {
StopUsingProximityUnit(continent.GUID(term_guid).get.asInstanceOf[ProximityTerminal])
})
}
/**
* Determine which functionality to pursue, by being given a generic proximity-functional unit
* and determinig which kind of unit is being utilized.
* @param terminal the proximity-based unit
*/
def SelectProximityUnit(terminal : Terminal with ProximityUnit) : Unit = {
terminal.Definition match {
case GlobalDefinitions.adv_med_terminal | GlobalDefinitions.medical_terminal =>
ProximityMedicalTerminal(terminal)
case GlobalDefinitions.crystals_health_a | GlobalDefinitions.crystals_health_b =>
SetDelayedProximityUnitReset(terminal)
ProximityHealCrystal(terminal)
case GlobalDefinitions.repair_silo =>
SetDelayedProximityUnitReset(terminal)
//TODO insert vehicle repair here; see ProximityMedicalTerminal for example
continent.GUID(usingMedicalTerminal) match {
case Some(terminal : Terminal with ProximityUnit) =>
FindProximityUnitTargetsInScope(terminal).foreach(target =>
terminal.Actor ! CommonMessages.Unuse(player, Some(target))
)
ForgetAllProximityTerminals(usingMedicalTerminal.get)
case _ => ;
}
}
@ -6332,43 +6329,27 @@ class WorldSessionActor extends Actor with MDCContextAware {
* resotre the player's health and armor points (when they need their health and armor points restored).
* If the player is both fully healed and fully repaired, stop using the terminal.
* @param unit the medical terminal
* @param target the player being healed
*/
def ProximityMedicalTerminal(unit : Terminal with ProximityUnit) : Unit = {
val healthFull : Boolean = if(player.Health < player.MaxHealth) {
player.History(HealFromTerm(PlayerSource(player), 10, 0, unit.Definition))
HealAction(player)
def HealthAndArmorTerminal(unit : Terminal with ProximityUnit, target : Player) : Unit = {
val medDef = unit.Definition.asInstanceOf[MedicalTerminalDefinition]
val healAmount = medDef.HealAmount
val healthFull : Boolean = if(healAmount != 0 && target.Health < target.MaxHealth) {
target.History(HealFromTerm(PlayerSource(target), healAmount, 0, medDef))
HealAction(target, healAmount)
}
else {
true
}
val armorFull : Boolean = if(player.Armor < player.MaxArmor) {
player.History(HealFromTerm(PlayerSource(player), 0, 10, unit.Definition))
ArmorRepairAction(player)
val repairAmount = medDef.ArmorAmount
val armorFull : Boolean = if(repairAmount != 0 && target.Armor < target.MaxArmor) {
target.History(HealFromTerm(PlayerSource(target), 0, repairAmount, medDef))
ArmorRepairAction(target, repairAmount)
}
else {
true
}
if(healthFull && armorFull) {
log.info(s"${player.Name} is all fixed up")
StopUsingProximityUnit(unit)
}
}
/**
* When near a red cavern crystal, resotre the player's health (when they need their health restored).
* If the player is fully healed, stop using the crystal.
* @param unit the healing crystal
*/
def ProximityHealCrystal(unit : Terminal with ProximityUnit) : Unit = {
val healthFull : Boolean = if(player.Health < player.MaxHealth) {
player.History(HealFromTerm(PlayerSource(player), 10, 0, unit.Definition))
HealAction(player)
}
else {
true
}
if(healthFull) {
log.info(s"${player.Name} is all healed up")
StopUsingProximityUnit(unit)
}
}
@ -6382,7 +6363,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
* @return whether the player can be repaired for any more health points
*/
def HealAction(tplayer : Player, healValue : Int = 10) : Boolean = {
log.info(s"Dispensing health to ${tplayer.Name} - <3")
val player_guid = tplayer.GUID
tplayer.Health = tplayer.Health + healValue
sendResponse(PlanetsideAttributeMessage(player_guid, 0, tplayer.Health))
@ -6399,7 +6379,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
* @return whether the player can be repaired for any more armor points
*/
def ArmorRepairAction(tplayer : Player, repairValue : Int = 10) : Boolean = {
log.info(s"Dispensing armor to ${tplayer.Name} - c[=")
val player_guid = tplayer.GUID
tplayer.Armor = tplayer.Armor + repairValue
sendResponse(PlanetsideAttributeMessage(player_guid, 4, tplayer.Armor))
@ -7764,7 +7743,6 @@ object WorldSessionActor {
private final case class ListAccountCharacters()
private final case class SetCurrentAvatar(tplayer : Player)
private final case class VehicleLoaded(vehicle : Vehicle)
private final case class DelayedProximityUnitStop(unit : Terminal with ProximityUnit)
private final case class UnregisterCorpseOnVehicleDisembark(corpse : Player)
private final case class CheckCargoMounting(vehicle_guid : PlanetSideGUID, cargo_vehicle_guid: PlanetSideGUID, cargo_mountpoint: Int, iteration: Int)
private final case class CheckCargoDismount(vehicle_guid : PlanetSideGUID, cargo_vehicle_guid: PlanetSideGUID, cargo_mountpoint: Int, iteration: Int)