From 7673c8941bccf6449968d469cd38ab877edbb100 Mon Sep 17 00:00:00 2001 From: FateJH Date: Sun, 13 May 2018 21:57:14 -0400 Subject: [PATCH] begun work on repair and rearm silos by dividing up proximity terminal behavior; terminals at Anguta wired --- .../psforever/objects/GlobalDefinitions.scala | 2 + .../terminals/ProximityTerminal.scala | 18 +----- .../terminals/ProximityTerminalControl.scala | 26 +++------ .../terminals/ProximityUnit.scala | 55 +++++++++++++++++++ .../terminals/RepairRearmControl.scala | 22 ++++++++ .../terminals/RepairRearmSilo.scala | 38 +++++++++++++ .../terminals/RepairRearmSiloDefinition.scala | 27 +++++++++ .../serverobject/terminals/Terminal.scala | 6 +- .../terminals/TerminalControl.scala | 3 +- pslogin/src/main/scala/Maps.scala | 6 +- .../src/main/scala/WorldSessionActor.scala | 36 ++++++++---- 11 files changed, 186 insertions(+), 53 deletions(-) create mode 100644 common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityUnit.scala create mode 100644 common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmControl.scala create mode 100644 common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmSilo.scala create mode 100644 common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmSiloDefinition.scala diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index fc511e8d..d39790ef 100644 --- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -524,6 +524,8 @@ object GlobalDefinitions { val medical_terminal = new MedicalTerminalDefinition(529) + val repair_silo = new RepairRearmSiloDefinition(729) + val spawn_pad = new VehicleSpawnPadDefinition val mb_locker = new LockerDefinition 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 c98e7da5..4eafb142 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,8 +1,6 @@ // Copyright (c) 2017 PSForever package net.psforever.objects.serverobject.terminals -import net.psforever.packet.game.PlanetSideGUID - /** * 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).
@@ -11,21 +9,7 @@ import net.psforever.packet.game.PlanetSideGUID * For example, the cavern crystals are considered owner-neutral elements that are not attached to a `Building` object. * @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields */ -class ProximityTerminal(tdef : MedicalTerminalDefinition) extends Terminal(tdef) { - private var users : Set[PlanetSideGUID] = Set.empty - - def NumberUsers : Int = users.size - - def AddUser(player_guid : PlanetSideGUID) : Int = { - users += player_guid - NumberUsers - } - - def RemoveUser(player_guid : PlanetSideGUID) : Int = { - users -= player_guid - NumberUsers - } -} +class ProximityTerminal(tdef : MedicalTerminalDefinition) extends Terminal(tdef) with ProximityUnit object ProximityTerminal { /** 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 407fd0cb..753cdb65 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 @@ -2,36 +2,24 @@ package net.psforever.objects.serverobject.terminals import akka.actor.Actor -import net.psforever.objects.serverobject.CommonMessages import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior} -import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage /** - * * An `Actor` that handles messages being dispatched to a specific `ProximityTerminal`. * Although this "terminal" itself does not accept the same messages as a normal `Terminal` object, * it returns the same type of messages - wrapped in a `TerminalMessage` - to the `sender`. * @param term the proximity unit (terminal) */ -class ProximityTerminalControl(term : ProximityTerminal) extends Actor with FactionAffinityBehavior.Check { +class ProximityTerminalControl(term : Terminal with ProximityUnit) extends Actor with FactionAffinityBehavior.Check with ProximityUnit.Use { def FactionObject : FactionAffinity = term - def receive : Receive = checkBehavior.orElse { - case CommonMessages.Use(player) => - val hadNoUsers = term.NumberUsers == 0 - if(term.AddUser(player.GUID) == 1 && hadNoUsers) { - sender ! TerminalMessage(player, null, Terminal.StartProximityEffect(term)) - } + def TerminalObject : Terminal with ProximityUnit = term - case CommonMessages.Unuse(player) => - val hadUsers = term.NumberUsers > 0 - if(term.RemoveUser(player.GUID) == 0 && hadUsers) { - sender ! TerminalMessage(player, null, Terminal.StopProximityEffect(term)) - } - - case _ => - sender ! Terminal.NoDeal() - } + def receive : Receive = checkBehavior + .orElse(proximityBehavior) + .orElse { + case _ => ; + } override def toString : String = term.Definition.Name } 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 new file mode 100644 index 00000000..8339e51e --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/ProximityUnit.scala @@ -0,0 +1,55 @@ +// 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 + +/** + * 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).
+ *
+ * Unlike conventional terminals, this structure is not necessarily structure-owned. + * For example, the cavern crystals are considered owner-neutral elements that are not attached to a `Building` object. + */ +trait ProximityUnit { + this : Terminal => + + private var users : Set[PlanetSideGUID] = Set.empty + + def NumberUsers : Int = users.size + + def AddUser(player_guid : PlanetSideGUID) : Int = { + users += player_guid + NumberUsers + } + + def RemoveUser(player_guid : PlanetSideGUID) : Int = { + users -= player_guid + NumberUsers + } +} + +object ProximityUnit { + import akka.actor.Actor + + 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)) + } + } + } +} \ No newline at end of file diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmControl.scala new file mode 100644 index 00000000..b5514305 --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmControl.scala @@ -0,0 +1,22 @@ +// Copyright (c) 2017 PSForever +package net.psforever.objects.serverobject.terminals + +import akka.actor.Actor +import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior} + +class RepairRearmControl(term : RepairRearmSilo) extends Actor with FactionAffinityBehavior.Check with ProximityUnit.Use { + def FactionObject : FactionAffinity = term + + def TerminalObject : Terminal with ProximityUnit = term + + def receive : Receive = checkBehavior + .orElse(proximityBehavior) + .orElse { + case Terminal.Request(player, msg) => + sender ! Terminal.TerminalMessage(player, msg, term.Request(player, msg)) + + case _ => ; + } + + override def toString : String = term.Definition.Name +} diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmSilo.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmSilo.scala new file mode 100644 index 00000000..45a01302 --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmSilo.scala @@ -0,0 +1,38 @@ +// Copyright (c) 2017 PSForever +package net.psforever.objects.serverobject.terminals + +/** + * 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).
+ *
+ * Unlike conventional terminals, this structure is not necessarily structure-owned. + * For example, the cavern crystals are considered owner-neutral elements that are not attached to a `Building` object. + * @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields + */ +class RepairRearmSilo(tdef : RepairRearmSiloDefinition) extends Terminal(tdef) with ProximityUnit + +object RepairRearmSilo { + /** + * Overloaded constructor. + * @param tdef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields + */ + def apply(tdef : RepairRearmSiloDefinition) : RepairRearmSilo = { + new RepairRearmSilo(tdef) + } + + import akka.actor.ActorContext + + /** + * Instantiate an configure a `Terminal` object + * @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 : RepairRearmSiloDefinition)(id : Int, context : ActorContext) : RepairRearmSilo = { + import akka.actor.Props + val obj = RepairRearmSilo(tdef) + obj.Actor = context.actorOf(Props(classOf[RepairRearmControl], obj), s"${tdef.Name}_$id") + obj + } +} 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 new file mode 100644 index 00000000..b0daa854 --- /dev/null +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/RepairRearmSiloDefinition.scala @@ -0,0 +1,27 @@ +// Copyright (c) 2017 PSForever +package net.psforever.objects.serverobject.terminals + +import net.psforever.objects.Player +import net.psforever.packet.game.ItemTransactionMessage + +class RepairRearmSiloDefinition(objectId : Int) extends EquipmentTerminalDefinition(objectId) { + Name = "repair_silo" + + 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) match { + case Some(loadout) => + Terminal.VehicleLoadout(Nil, Nil) + case None => + Terminal.NoDeal() + } + } + else { + Terminal.NoDeal() + } + } +} diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala index b031a990..8ee17814 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala @@ -190,17 +190,19 @@ object Terminal { */ final case class InfantryLoadout(exosuit : ExoSuitType.Value, subtype : Int = 0, holsters : List[InventoryItem], inventory : List[InventoryItem]) extends Exchange + final case class VehicleLoadout(weapons : List[InventoryItem], inventory : List[InventoryItem]) extends Exchange + /** * Start the special effects caused by a proximity-base service. * @param terminal the proximity-based unit */ - final case class StartProximityEffect(terminal : ProximityTerminal) extends Exchange + final case class StartProximityEffect(terminal : Terminal with ProximityUnit) extends Exchange /** * Stop the special effects caused by a proximity-base service. * @param terminal the proximity-based unit */ - final case class StopProximityEffect(terminal : ProximityTerminal) extends Exchange + final case class StopProximityEffect(terminal : Terminal with ProximityUnit) extends Exchange /** * Overloaded constructor. diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalControl.scala index ad63babf..4efa324e 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalControl.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalControl.scala @@ -15,8 +15,7 @@ class TerminalControl(term : Terminal) extends Actor with FactionAffinityBehavio case Terminal.Request(player, msg) => sender ! Terminal.TerminalMessage(player, msg, term.Request(player, msg)) - case _ => - sender ! Terminal.NoDeal() + case _ => ; } override def toString : String = term.Definition.Name diff --git a/pslogin/src/main/scala/Maps.scala b/pslogin/src/main/scala/Maps.scala index 4051208c..7d0494dd 100644 --- a/pslogin/src/main/scala/Maps.scala +++ b/pslogin/src/main/scala/Maps.scala @@ -7,7 +7,7 @@ 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.{ProximityTerminal, RepairRearmSilo, Terminal} import net.psforever.objects.serverobject.tube.SpawnTube import net.psforever.types.Vector3 @@ -113,6 +113,8 @@ object Maps { 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(2050, RepairRearmSilo.Constructor(repair_silo)) + LocalObject(2062, RepairRearmSilo.Constructor(repair_silo)) LocalObject(2239, Terminal.Constructor(spawn_terminal)) LocalObject(2244, Terminal.Constructor(spawn_terminal)) LocalObject(2245, Terminal.Constructor(spawn_terminal)) @@ -214,6 +216,8 @@ object Maps { ObjectToBuilding(1576, 2) ObjectToBuilding(1577, 2) ObjectToBuilding(1578, 2) + ObjectToBuilding(2050, 2) + ObjectToBuilding(2062, 2) ObjectToBuilding(2145, 2) ObjectToBuilding(2146, 2) ObjectToBuilding(2147, 2) diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index bfbfe5cf..33514522 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -28,8 +28,7 @@ import net.psforever.objects.serverobject.mblocker.Locker import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad} import net.psforever.objects.serverobject.pad.process.{AutoDriveControls, VehicleSpawnControlGuided} import net.psforever.objects.serverobject.structures.{Building, StructureType, WarpGate} -import net.psforever.objects.serverobject.terminals.{MatrixTerminalDefinition, ProximityTerminal, Terminal} -import net.psforever.objects.serverobject.terminals.Terminal +import net.psforever.objects.serverobject.terminals._ import net.psforever.objects.serverobject.terminals.Terminal.TerminalMessage import net.psforever.objects.serverobject.tube.SpawnTube import net.psforever.objects.vehicles.{AccessPermissionGroup, Utility, VehicleLockState} @@ -895,6 +894,9 @@ class WorldSessionActor extends Actor with MDCContextAware { sendResponse(ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, false)) } + case Terminal.VehicleLoadout(weapons, inventory) => + log.info(s"$tplayer wants to change their vehicle equipment loadout to their option #${msg.unk1 + 1}") + case Terminal.SellCertification(cert, cost) => if(tplayer.Certifications.contains(cert)) { log.info(s"$tplayer is forgetting the $cert certification for $cost points") @@ -2267,6 +2269,16 @@ class WorldSessionActor extends Actor with MDCContextAware { } } + case Some(obj : RepairRearmSilo) => + player.VehicleSeated match { + case Some(vehicle_guid) => + val vehicle = continent.GUID(vehicle_guid).get.asInstanceOf[Vehicle] + sendResponse(UseItemMessage(avatar_guid, unk1, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType)) + sendResponse(UseItemMessage(avatar_guid, unk1, vehicle_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, vehicle.Definition.ObjectId)) + case None => + log.error("UseItem: expected seated vehicle, but found none") + } + case Some(obj : Terminal) => if(obj.Definition.isInstanceOf[MatrixTerminalDefinition]) { //TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks) @@ -2300,7 +2312,7 @@ class WorldSessionActor extends Actor with MDCContextAware { case msg @ ProximityTerminalUseMessage(player_guid, object_guid, _) => log.info(s"ProximityTerminal: $msg") continent.GUID(object_guid) match { - case Some(obj : ProximityTerminal) => + case Some(obj : Terminal with ProximityUnit) => if(usingProximityTerminal.contains(object_guid)) { SelectProximityUnit(obj) } @@ -2308,9 +2320,9 @@ class WorldSessionActor extends Actor with MDCContextAware { StartUsingProximityUnit(obj) } case Some(obj) => ; - log.warn(s"ProximityTerminal: object is not a terminal - $obj") + log.warn(s"ProximityTerminalUse: object is not a proximity terminal - $obj") case None => - log.warn(s"ProximityTerminal: no object with guid $object_guid found") + log.warn(s"ProximityTerminalUse: no object with guid $object_guid found") } case msg @ UnuseItemMessage(player_guid, object_guid) => @@ -3985,7 +3997,7 @@ class WorldSessionActor extends Actor with MDCContextAware { * Special note is warranted in the case of a medical terminal or an advanced medical terminal. * @param terminal the proximity-based unit */ - def StartUsingProximityUnit(terminal : ProximityTerminal) : Unit = { + def StartUsingProximityUnit(terminal : Terminal with ProximityUnit) : Unit = { val term_guid = terminal.GUID if(!usingProximityTerminal.contains(term_guid)) { usingProximityTerminal += term_guid @@ -4006,7 +4018,7 @@ class WorldSessionActor extends Actor with MDCContextAware { * Other sorts of proximity-based units are put on a timer. * @param terminal the proximity-based unit */ - def StopUsingProximityUnit(terminal : ProximityTerminal) : Unit = { + def StopUsingProximityUnit(terminal : Terminal with ProximityUnit) : Unit = { val term_guid = terminal.GUID if(usingProximityTerminal.contains(term_guid)) { usingProximityTerminal -= term_guid @@ -4025,7 +4037,7 @@ class WorldSessionActor extends Actor with MDCContextAware { * 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 : ProximityTerminal) : Unit = { + def SetDelayedProximityUnitReset(terminal : Terminal with ProximityUnit) : Unit = { val terminal_guid = terminal.GUID ClearDelayedProximityUnitReset(terminal_guid) import scala.concurrent.duration._ @@ -4070,7 +4082,7 @@ class WorldSessionActor extends Actor with MDCContextAware { * and determinig which kind of unit is being utilized. * @param terminal the proximity-based unit */ - def SelectProximityUnit(terminal : ProximityTerminal) : Unit = { + def SelectProximityUnit(terminal : Terminal with ProximityUnit) : Unit = { terminal.Definition match { case GlobalDefinitions.adv_med_terminal | GlobalDefinitions.medical_terminal => ProximityMedicalTerminal(terminal) @@ -4089,7 +4101,7 @@ class WorldSessionActor extends Actor with MDCContextAware { * If the player is both fully healed and fully repaired, stop using the terminal. * @param unit the medical terminal */ - def ProximityMedicalTerminal(unit : ProximityTerminal) : Unit = { + def ProximityMedicalTerminal(unit : Terminal with ProximityUnit) : Unit = { val healthFull : Boolean = if(player.Health < player.MaxHealth) { HealAction(player) } @@ -4113,7 +4125,7 @@ class WorldSessionActor extends Actor with MDCContextAware { * If the player is fully healed, stop using the crystal. * @param unit the healing crystal */ - def ProximityHealCrystal(unit : ProximityTerminal) : Unit = { + def ProximityHealCrystal(unit : Terminal with ProximityUnit) : Unit = { val healthFull : Boolean = if(player.Health < player.MaxHealth) { HealAction(player) } @@ -4253,7 +4265,7 @@ 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 : ProximityTerminal) + private final case class DelayedProximityUnitStop(unit : Terminal with ProximityUnit) private final case class UnregisterCorpseOnVehicleDisembark(corpse : Player) /**