diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index 3f8b1297..f777096c 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -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 + } } diff --git a/common/src/main/scala/net/psforever/objects/Player.scala b/common/src/main/scala/net/psforever/objects/Player.scala index f2fc55b6..aa5dff72 100644 --- a/common/src/main/scala/net/psforever/objects/Player.scala +++ b/common/src/main/scala/net/psforever/objects/Player.scala @@ -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 diff --git a/common/src/main/scala/net/psforever/objects/Vehicle.scala b/common/src/main/scala/net/psforever/objects/Vehicle.scala index 249923ba..3057d4db 100644 --- a/common/src/main/scala/net/psforever/objects/Vehicle.scala +++ b/common/src/main/scala/net/psforever/objects/Vehicle.scala @@ -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 => ; diff --git a/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala b/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala index ccb0ea4e..ffc4237a 100644 --- a/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala +++ b/common/src/main/scala/net/psforever/objects/definition/VehicleDefinition.scala @@ -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 = { diff --git a/common/src/main/scala/net/psforever/objects/serverobject/CommonMessages.scala b/common/src/main/scala/net/psforever/objects/serverobject/CommonMessages.scala index ad7a26b6..4ec1a6e7 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/CommonMessages.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/CommonMessages.scala @@ -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() } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala b/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala index 3f8436b6..c8dcd465 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala @@ -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 } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/Amenity.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/Amenity.scala index 6458757d..1887c7a8 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/Amenity.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/Amenity.scala @@ -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.
@@ -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 { diff --git a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala index 8c7cfa88..9f63430e 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/structures/Building.scala @@ -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 } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/MedicalTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/MedicalTerminalDefinition.scala index 66581aac..a1b26e03 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/MedicalTerminalDefinition.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/MedicalTerminalDefinition.scala @@ -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 } } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityDefinition.scala index f1ccfcc4..5aa814d3 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityDefinition.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityDefinition.scala @@ -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 +} diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTarget.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTarget.scala new file mode 100644 index 00000000..9c02fba8 --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTarget.scala @@ -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 +} diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminal.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminal.scala index 8b9b7e67..c34cbc11 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminal.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminal.scala @@ -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).
@@ -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() + } + } } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala index fcc8c073..58571191 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityTerminalControl.scala @@ -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() +} diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityUnit.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityUnit.scala index 25843fa1..7792bce5 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityUnit.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityUnit.scala @@ -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) } diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmSiloDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmSiloDefinition.scala deleted file mode 100644 index f7463bf0..00000000 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmSiloDefinition.scala +++ /dev/null @@ -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() - } - } -} diff --git a/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala b/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala index 395971d0..9b769c6b 100644 --- a/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala +++ b/common/src/main/scala/net/psforever/objects/vehicles/Utility.scala @@ -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.
@@ -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 => diff --git a/common/src/main/scala/net/psforever/objects/zones/Zone.scala b/common/src/main/scala/net/psforever/objects/zones/Zone.scala index f4a67355..b57c3476 100644 --- a/common/src/main/scala/net/psforever/objects/zones/Zone.scala +++ b/common/src/main/scala/net/psforever/objects/zones/Zone.scala @@ -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 = { diff --git a/common/src/main/scala/net/psforever/objects/zones/ZoneAware.scala b/common/src/main/scala/net/psforever/objects/zones/ZoneAware.scala new file mode 100644 index 00000000..1c986fad --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/zones/ZoneAware.scala @@ -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 +} diff --git a/common/src/main/scala/net/psforever/types/Vector3.scala b/common/src/main/scala/net/psforever/types/Vector3.scala index 1d135af6..83c740eb 100644 --- a/common/src/main/scala/net/psforever/types/Vector3.scala +++ b/common/src/main/scala/net/psforever/types/Vector3.scala @@ -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 + ) + } } diff --git a/common/src/main/scala/services/local/LocalAction.scala b/common/src/main/scala/services/local/LocalAction.scala index 76964b84..2b3b22c5 100644 --- a/common/src/main/scala/services/local/LocalAction.scala +++ b/common/src/main/scala/services/local/LocalAction.scala @@ -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 diff --git a/common/src/main/scala/services/local/LocalService.scala b/common/src/main/scala/services/local/LocalService.scala index 39ec51f2..f4a07a25 100644 --- a/common/src/main/scala/services/local/LocalService.scala +++ b/common/src/main/scala/services/local/LocalService.scala @@ -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 { diff --git a/common/src/main/scala/services/vehicle/VehicleService.scala b/common/src/main/scala/services/vehicle/VehicleService.scala index e2acb9d1..db49954e 100644 --- a/common/src/main/scala/services/vehicle/VehicleService.scala +++ b/common/src/main/scala/services/vehicle/VehicleService.scala @@ -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") } diff --git a/common/src/test/scala/Vector3Test.scala b/common/src/test/scala/Vector3Test.scala index 6bf392e8..aed9abcf 100644 --- a/common/src/test/scala/Vector3Test.scala +++ b/common/src/test/scala/Vector3Test.scala @@ -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) + } } } diff --git a/common/src/test/scala/objects/terminal/MedicalTerminalTest.scala b/common/src/test/scala/objects/terminal/MedicalTerminalTest.scala deleted file mode 100644 index b27de07b..00000000 --- a/common/src/test/scala/objects/terminal/MedicalTerminalTest.scala +++ /dev/null @@ -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() - } - } -} diff --git a/common/src/test/scala/objects/terminal/ProximityTerminalControlTest.scala b/common/src/test/scala/objects/terminal/ProximityTerminalControlTest.scala deleted file mode 100644 index c2ed10d9..00000000 --- a/common/src/test/scala/objects/terminal/ProximityTerminalControlTest.scala +++ /dev/null @@ -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) - } -} diff --git a/common/src/test/scala/objects/terminal/ProximityTest.scala b/common/src/test/scala/objects/terminal/ProximityTest.scala index a8d18978..41ba3b60 100644 --- a/common/src/test/scala/objects/terminal/ProximityTest.scala +++ b/common/src/test/scala/objects/terminal/ProximityTest.scala @@ -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) + } } diff --git a/common/src/test/scala/objects/terminal/RepairRearmSiloTest.scala b/common/src/test/scala/objects/terminal/RepairRearmSiloTest.scala deleted file mode 100644 index ddc27794..00000000 --- a/common/src/test/scala/objects/terminal/RepairRearmSiloTest.scala +++ /dev/null @@ -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 - } - } -} diff --git a/common/src/test/scala/service/LocalServiceTest.scala b/common/src/test/scala/service/LocalServiceTest.scala index f52f007f..3c597595 100644 --- a/common/src/test/scala/service/LocalServiceTest.scala +++ b/common/src/test/scala/service/LocalServiceTest.scala @@ -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))) } } } diff --git a/pslogin/src/main/scala/Maps.scala b/pslogin/src/main/scala/Maps.scala index 68163d7d..81da7198 100644 --- a/pslogin/src/main/scala/Maps.scala +++ b/pslogin/src/main/scala/Maps.scala @@ -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, diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index ab1ebeb8..39802b21 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -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`
- * `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)