mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-16 00:44:43 +00:00
Feature/caverns (#331)
* Typo fix * Expand building hack info match to include vanu_control_console * Fix cavern crystal animations by allowing Amenities without an Owner to be ZoneAware, allowing them to direct to the correct Zone's LocalEvents * Add logging for when an invalid object reference gets deleted from a client * Show zipline teleporter animation (locally, at least) Co-authored-by: Fate-JH <Jason_DiDonato@yahoo.com>
This commit is contained in:
parent
e8fd09aad8
commit
9d67029238
16 changed files with 69 additions and 47 deletions
|
|
@ -30,6 +30,9 @@ import net.psforever.objects.guid.NumberPoolHub
|
||||||
class ServerObjectBuilder[A <: PlanetSideServerObject](private val id : Int,
|
class ServerObjectBuilder[A <: PlanetSideServerObject](private val id : Int,
|
||||||
private val constructor : ServerObjectBuilder.ConstructorType[A]
|
private val constructor : ServerObjectBuilder.ConstructorType[A]
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
def Id : Int = id
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate and configure the given server object.
|
* Instantiate and configure the given server object.
|
||||||
* Specific configuration should have been handled by curried parameters into `constructor`, i.e.,
|
* Specific configuration should have been handled by curried parameters into `constructor`, i.e.,
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
case _ : AssertionError if vehicle.HasGUID => //same as order being dropped
|
case _ : AssertionError if vehicle.HasGUID => //same as order being dropped
|
||||||
VehicleSpawnControl.DisposeSpawnedVehicle(vehicle, pad.Owner.Zone)
|
VehicleSpawnControl.DisposeSpawnedVehicle(vehicle, pad.Zone)
|
||||||
case _ : AssertionError => ; //shrug
|
case _ : AssertionError => ; //shrug
|
||||||
case e : Exception => //something unexpected
|
case e : Exception => //something unexpected
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|
@ -140,10 +140,10 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase
|
||||||
}) && orders.forall { !_.driver.Name.equals(name) }) {
|
}) && orders.forall { !_.driver.Name.equals(name) }) {
|
||||||
//not a second order from an existing order's player
|
//not a second order from an existing order's player
|
||||||
orders = orders :+ order
|
orders = orders :+ order
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(name, VehicleSpawnPad.Reminders.Queue, Some(orders.length + 1))
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(name, VehicleSpawnPad.Reminders.Queue, Some(orders.length + 1))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VehicleSpawnControl.DisposeSpawnedVehicle(order, pad.Owner.Zone)
|
VehicleSpawnControl.DisposeSpawnedVehicle(order, pad.Zone)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,7 +201,7 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase
|
||||||
* @param recipients all of the other customers who will be receiving the message
|
* @param recipients all of the other customers who will be receiving the message
|
||||||
*/
|
*/
|
||||||
def BlockedReminder(blockedOrder : VehicleSpawnControl.Order, recipients : Seq[VehicleSpawnControl.Order]) : Unit = {
|
def BlockedReminder(blockedOrder : VehicleSpawnControl.Order, recipients : Seq[VehicleSpawnControl.Order]) : Unit = {
|
||||||
val relevantRecipients = blockedOrder.vehicle.Seats(0).Occupant.orElse(pad.Owner.Zone.GUID(blockedOrder.vehicle.Owner)) match {
|
val relevantRecipients = blockedOrder.vehicle.Seats(0).Occupant.orElse(pad.Zone.GUID(blockedOrder.vehicle.Owner)) match {
|
||||||
case Some(p : Player) =>
|
case Some(p : Player) =>
|
||||||
(VehicleSpawnControl.Order(p, blockedOrder.vehicle) +: recipients).iterator //who took possession of the vehicle
|
(VehicleSpawnControl.Order(p, blockedOrder.vehicle) +: recipients).iterator //who took possession of the vehicle
|
||||||
case _ =>
|
case _ =>
|
||||||
|
|
@ -223,15 +223,15 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase
|
||||||
def CancelOrder(entry : VehicleSpawnControl.Order)(implicit context : ActorContext) : Unit = {
|
def CancelOrder(entry : VehicleSpawnControl.Order)(implicit context : ActorContext) : Unit = {
|
||||||
val vehicle = entry.vehicle
|
val vehicle = entry.vehicle
|
||||||
if(vehicle.Seats.values.count(_.isOccupied) == 0) {
|
if(vehicle.Seats.values.count(_.isOccupied) == 0) {
|
||||||
VehicleSpawnControl.DisposeSpawnedVehicle(entry, pad.Owner.Zone)
|
VehicleSpawnControl.DisposeSpawnedVehicle(entry, pad.Zone)
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(entry.driver.Name, VehicleSpawnPad.Reminders.Cancelled)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(entry.driver.Name, VehicleSpawnPad.Reminders.Cancelled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@tailrec private final def recursiveBlockedReminder(iter : Iterator[VehicleSpawnControl.Order], cause : Option[Any]) : Unit = {
|
@tailrec private final def recursiveBlockedReminder(iter : Iterator[VehicleSpawnControl.Order], cause : Option[Any]) : Unit = {
|
||||||
if(iter.hasNext) {
|
if(iter.hasNext) {
|
||||||
val recipient = iter.next
|
val recipient = iter.next
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(recipient.driver.Name, VehicleSpawnPad.Reminders.Blocked, cause)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(recipient.driver.Name, VehicleSpawnPad.Reminders.Blocked, cause)
|
||||||
recursiveBlockedReminder(iter, cause)
|
recursiveBlockedReminder(iter, cause)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -239,7 +239,7 @@ class VehicleSpawnControl(pad : VehicleSpawnPad) extends VehicleSpawnControlBase
|
||||||
@tailrec private final def recursiveOrderReminder(iter : Iterator[VehicleSpawnControl.Order], position : Int = 2) : Unit = {
|
@tailrec private final def recursiveOrderReminder(iter : Iterator[VehicleSpawnControl.Order], position : Int = 2) : Unit = {
|
||||||
if(iter.hasNext) {
|
if(iter.hasNext) {
|
||||||
val recipient = iter.next
|
val recipient = iter.next
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(recipient.driver.Name, VehicleSpawnPad.Reminders.Queue, Some(position))
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(recipient.driver.Name, VehicleSpawnPad.Reminders.Queue, Some(position))
|
||||||
recursiveOrderReminder(iter, position + 1)
|
recursiveOrderReminder(iter, position + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ abstract class VehicleSpawnControlBase(pad : VehicleSpawnPad) extends Actor {
|
||||||
*/
|
*/
|
||||||
private def GetLogger(logid : String) : Logger = baseLogger match {
|
private def GetLogger(logid : String) : Logger = baseLogger match {
|
||||||
case None =>
|
case None =>
|
||||||
if(!pad.HasGUID || pad.Owner.Zone == Zone.Nowhere) {
|
if(!pad.HasGUID || pad.Zone == Zone.Nowhere) {
|
||||||
org.log4s.getLogger(s"uninitialized_${pad.Definition.Name}$logid")
|
org.log4s.getLogger(s"uninitialized_${pad.Definition.Name}$logid")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,12 @@ class VehicleSpawnControlConcealPlayer(pad : VehicleSpawnPad) extends VehicleSpa
|
||||||
//TODO how far can the driver stray from the Terminal before his order is cancelled?
|
//TODO how far can the driver stray from the Terminal before his order is cancelled?
|
||||||
if(driver.Continent == pad.Continent && driver.VehicleSeated.isEmpty) {
|
if(driver.Continent == pad.Continent && driver.VehicleSeated.isEmpty) {
|
||||||
trace(s"hiding ${driver.Name}")
|
trace(s"hiding ${driver.Name}")
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.ConcealPlayer(driver.GUID)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.ConcealPlayer(driver.GUID)
|
||||||
context.system.scheduler.scheduleOnce(2000 milliseconds, loadVehicle, order)
|
context.system.scheduler.scheduleOnce(2000 milliseconds, loadVehicle, order)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace(s"integral component lost; abort order fulfillment")
|
trace(s"integral component lost; abort order fulfillment")
|
||||||
VehicleSpawnControl.DisposeSpawnedVehicle(order.vehicle, pad.Owner.Zone)
|
VehicleSpawnControl.DisposeSpawnedVehicle(order.vehicle, pad.Zone)
|
||||||
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class VehicleSpawnControlDriverControl(pad : VehicleSpawnPad) extends VehicleSpa
|
||||||
}
|
}
|
||||||
if(vehicle.PassengerInSeat(driver).contains(0)) {
|
if(vehicle.PassengerInSeat(driver).contains(0)) {
|
||||||
trace(s"returning control of ${vehicle.Definition.Name} to ${driver.Name}")
|
trace(s"returning control of ${vehicle.Definition.Name} to ${driver.Name}")
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.ServerVehicleOverrideEnd(driver.Name, vehicle, pad)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.ServerVehicleOverrideEnd(driver.Name, vehicle, pad)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace(s"${driver.Name} is not seated in ${vehicle.Definition.Name}; vehicle controls have been locked")
|
trace(s"${driver.Name} is not seated in ${vehicle.Definition.Name}; vehicle controls have been locked")
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class VehicleSpawnControlFinalClearance(pad : VehicleSpawnPad) extends VehicleSp
|
||||||
//ensure the vacant vehicle is above the trench and doors
|
//ensure the vacant vehicle is above the trench and doors
|
||||||
vehicle.Position = pad.Position + Vector3.z(pad.Definition.VehicleCreationZOffset)
|
vehicle.Position = pad.Position + Vector3.z(pad.Definition.VehicleCreationZOffset)
|
||||||
val definition = vehicle.Definition
|
val definition = vehicle.Definition
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleServiceMessage(s"${pad.Continent}", VehicleAction.LoadVehicle(PlanetSideGUID(0), vehicle, definition.ObjectId, vehicle.GUID, definition.Packet.ConstructorData(vehicle).get))
|
pad.Zone.VehicleEvents ! VehicleServiceMessage(s"${pad.Continent}", VehicleAction.LoadVehicle(PlanetSideGUID(0), vehicle, definition.ObjectId, vehicle.GUID, definition.Packet.ConstructorData(vehicle).get))
|
||||||
}
|
}
|
||||||
context.parent ! VehicleSpawnControl.ProcessControl.Reminder
|
context.parent ! VehicleSpawnControl.ProcessControl.Reminder
|
||||||
self ! VehicleSpawnControlFinalClearance.Test(order)
|
self ! VehicleSpawnControlFinalClearance.Test(order)
|
||||||
|
|
@ -36,7 +36,7 @@ class VehicleSpawnControlFinalClearance(pad : VehicleSpawnPad) extends VehicleSp
|
||||||
case test @ VehicleSpawnControlFinalClearance.Test(entry) =>
|
case test @ VehicleSpawnControlFinalClearance.Test(entry) =>
|
||||||
if(Vector3.DistanceSquared(entry.vehicle.Position, pad.Position) > 100.0f) { //10m away from pad
|
if(Vector3.DistanceSquared(entry.vehicle.Position, pad.Position) > 100.0f) { //10m away from pad
|
||||||
trace("pad cleared")
|
trace("pad cleared")
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.ResetSpawnPad(pad)
|
||||||
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import scala.concurrent.duration._
|
||||||
* <br>
|
* <br>
|
||||||
* This object introduces the vehicle into the game environment.
|
* This object introduces the vehicle into the game environment.
|
||||||
* The vehicle must be added to the `Zone` object, loaded onto other players' clients, and given an initial timed deconstruction event.
|
* The vehicle must be added to the `Zone` object, loaded onto other players' clients, and given an initial timed deconstruction event.
|
||||||
* For actual details on this process, please refer to the external source represented by `pad.Owner.Zone.VehicleEvents`.
|
* For actual details on this process, please refer to the external source represented by `pad.Zone.VehicleEvents`.
|
||||||
* It has failure cases should the driver be in an incorrect state.
|
* It has failure cases should the driver be in an incorrect state.
|
||||||
* @param pad the `VehicleSpawnPad` object being governed
|
* @param pad the `VehicleSpawnPad` object being governed
|
||||||
*/
|
*/
|
||||||
|
|
@ -31,12 +31,12 @@ class VehicleSpawnControlLoadVehicle(pad : VehicleSpawnPad) extends VehicleSpawn
|
||||||
trace(s"loading the ${vehicle.Definition.Name}")
|
trace(s"loading the ${vehicle.Definition.Name}")
|
||||||
vehicle.Position = vehicle.Position - Vector3.z(if(GlobalDefinitions.isFlightVehicle(vehicle.Definition)) 9 else 5) //appear below the trench and doors
|
vehicle.Position = vehicle.Position - Vector3.z(if(GlobalDefinitions.isFlightVehicle(vehicle.Definition)) 9 else 5) //appear below the trench and doors
|
||||||
vehicle.Cloaked = vehicle.Definition.CanCloak && driver.Cloaked
|
vehicle.Cloaked = vehicle.Definition.CanCloak && driver.Cloaked
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.LoadVehicle(vehicle)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.LoadVehicle(vehicle)
|
||||||
context.system.scheduler.scheduleOnce(100 milliseconds, railJack, order)
|
context.system.scheduler.scheduleOnce(100 milliseconds, railJack, order)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace("owner lost or vehicle in poor condition; abort order fulfillment")
|
trace("owner lost or vehicle in poor condition; abort order fulfillment")
|
||||||
VehicleSpawnControl.DisposeSpawnedVehicle(order, pad.Owner.Zone)
|
VehicleSpawnControl.DisposeSpawnedVehicle(order, pad.Zone)
|
||||||
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
context.parent ! VehicleSpawnControl.ProcessControl.GetNewOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class VehicleSpawnControlRailJack(pad : VehicleSpawnPad) extends VehicleSpawnCon
|
||||||
|
|
||||||
def receive : Receive = {
|
def receive : Receive = {
|
||||||
case order @ VehicleSpawnControl.Order(_, vehicle) =>
|
case order @ VehicleSpawnControl.Order(_, vehicle) =>
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.AttachToRails(vehicle, pad)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.AttachToRails(vehicle, pad)
|
||||||
context.system.scheduler.scheduleOnce(10 milliseconds, seatDriver, order)
|
context.system.scheduler.scheduleOnce(10 milliseconds, seatDriver, order)
|
||||||
|
|
||||||
case msg @ (VehicleSpawnControl.ProcessControl.Reminder | VehicleSpawnControl.ProcessControl.GetNewOrder) =>
|
case msg @ (VehicleSpawnControl.ProcessControl.Reminder | VehicleSpawnControl.ProcessControl.GetNewOrder) =>
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC
|
||||||
val driver = entry.driver
|
val driver = entry.driver
|
||||||
if(entry.vehicle.Health > 0 && driver.isAlive && driver.Continent == pad.Continent && driver.VehicleSeated.isEmpty) {
|
if(entry.vehicle.Health > 0 && driver.isAlive && driver.Continent == pad.Continent && driver.VehicleSeated.isEmpty) {
|
||||||
trace("driver to be made seated in vehicle")
|
trace("driver to be made seated in vehicle")
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.StartPlayerSeatedInVehicle(entry.driver.Name, entry.vehicle, pad)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.StartPlayerSeatedInVehicle(entry.driver.Name, entry.vehicle, pad)
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
trace("driver lost; vehicle stranded on pad")
|
trace("driver lost; vehicle stranded on pad")
|
||||||
|
|
@ -50,7 +50,7 @@ class VehicleSpawnControlSeatDriver(pad : VehicleSpawnPad) extends VehicleSpawnC
|
||||||
case VehicleSpawnControlSeatDriver.DriverInSeat(entry) =>
|
case VehicleSpawnControlSeatDriver.DriverInSeat(entry) =>
|
||||||
if(entry.driver.isAlive && entry.vehicle.PassengerInSeat(entry.driver).contains(0)) {
|
if(entry.driver.isAlive && entry.vehicle.PassengerInSeat(entry.driver).contains(0)) {
|
||||||
trace(s"driver ${entry.driver.Name} has taken the wheel")
|
trace(s"driver ${entry.driver.Name} has taken the wheel")
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.PlayerSeatedInVehicle(entry.driver.Name, entry.vehicle, pad)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.PlayerSeatedInVehicle(entry.driver.Name, entry.vehicle, pad)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace("driver lost, but operations can continue")
|
trace("driver lost, but operations can continue")
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class VehicleSpawnControlServerVehicleOverride(pad : VehicleSpawnPad) extends Ve
|
||||||
case order @ VehicleSpawnControl.Order(driver, vehicle) =>
|
case order @ VehicleSpawnControl.Order(driver, vehicle) =>
|
||||||
val vehicleFailState = vehicle.Health == 0 || vehicle.Position == Vector3.Zero
|
val vehicleFailState = vehicle.Health == 0 || vehicle.Position == Vector3.Zero
|
||||||
val driverFailState = !driver.isAlive || driver.Continent != pad.Continent || !vehicle.PassengerInSeat(driver).contains(0)
|
val driverFailState = !driver.isAlive || driver.Continent != pad.Continent || !vehicle.PassengerInSeat(driver).contains(0)
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.DetachFromRails(vehicle, pad)
|
||||||
if(vehicleFailState || driverFailState) {
|
if(vehicleFailState || driverFailState) {
|
||||||
if(vehicleFailState) {
|
if(vehicleFailState) {
|
||||||
trace(s"vehicle was already destroyed")
|
trace(s"vehicle was already destroyed")
|
||||||
|
|
@ -36,12 +36,12 @@ class VehicleSpawnControlServerVehicleOverride(pad : VehicleSpawnPad) extends Ve
|
||||||
else {
|
else {
|
||||||
trace(s"driver is not ready")
|
trace(s"driver is not ready")
|
||||||
}
|
}
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.RevealPlayer(order.DriverGUID)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.RevealPlayer(order.DriverGUID)
|
||||||
driverControl ! order
|
driverControl ! order
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace(s"telling ${driver.Name} that the server is assuming control of the ${vehicle.Definition.Name}")
|
trace(s"telling ${driver.Name} that the server is assuming control of the ${vehicle.Definition.Name}")
|
||||||
pad.Owner.Zone.VehicleEvents ! VehicleSpawnPad.ServerVehicleOverrideStart(driver.Name, vehicle, pad)
|
pad.Zone.VehicleEvents ! VehicleSpawnPad.ServerVehicleOverrideStart(driver.Name, vehicle, pad)
|
||||||
context.system.scheduler.scheduleOnce(4000 milliseconds, driverControl, order)
|
context.system.scheduler.scheduleOnce(4000 milliseconds, driverControl, order)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ class PainboxControl(painbox: Painbox) extends Actor {
|
||||||
val owner = painbox.Owner.asInstanceOf[Building]
|
val owner = painbox.Owner.asInstanceOf[Building]
|
||||||
val faction = owner.Faction
|
val faction = owner.Faction
|
||||||
if(faction != PlanetSideEmpire.NEUTRAL && (nearestDoor match { case Some(door) => door.Open.nonEmpty; case _ => true })) {
|
if(faction != PlanetSideEmpire.NEUTRAL && (nearestDoor match { case Some(door) => door.Open.nonEmpty; case _ => true })) {
|
||||||
val events = owner.Zone.AvatarEvents
|
val events = painbox.Zone.AvatarEvents
|
||||||
val damage = painbox.Definition.Damage
|
val damage = painbox.Definition.Damage
|
||||||
val radius = painbox.Definition.Radius * painbox.Definition.Radius
|
val radius = painbox.Definition.Radius * painbox.Definition.Radius
|
||||||
val position = painbox.Position
|
val position = painbox.Position
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
package net.psforever.objects.serverobject.structures
|
package net.psforever.objects.serverobject.structures
|
||||||
|
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.{Zone, ZoneAware}
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
import net.psforever.objects.zones.{ Zone => World }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amenities are elements of the game that belong to other elements of the game.<br>
|
* Amenities are elements of the game that belong to other elements of the game.<br>
|
||||||
|
|
@ -15,7 +16,8 @@ import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
* the `Amenity` objects look to its `Owner` object for some of its properties.
|
* the `Amenity` objects look to its `Owner` object for some of its properties.
|
||||||
* @see `FactionAffinity`
|
* @see `FactionAffinity`
|
||||||
*/
|
*/
|
||||||
abstract class Amenity extends PlanetSideServerObject {
|
abstract class Amenity extends PlanetSideServerObject with ZoneAware {
|
||||||
|
private[this] val log = org.log4s.getLogger("Amenity")
|
||||||
/** what other entity has authority over this amenity; usually either a building or a vehicle */
|
/** what other entity has authority over this amenity; usually either a building or a vehicle */
|
||||||
private var owner : AmenityOwner = Building.NoBuilding
|
private var owner : AmenityOwner = Building.NoBuilding
|
||||||
/** if the entity exists at a specific position relative to the owner's position */
|
/** if the entity exists at a specific position relative to the owner's position */
|
||||||
|
|
@ -27,7 +29,12 @@ abstract class Amenity extends PlanetSideServerObject {
|
||||||
* Reference the object that is in direct association with (is superior to) this one.
|
* Reference the object that is in direct association with (is superior to) this one.
|
||||||
* @return the object associated as this object's "owner"
|
* @return the object associated as this object's "owner"
|
||||||
*/
|
*/
|
||||||
def Owner : AmenityOwner = owner
|
def Owner : AmenityOwner = {
|
||||||
|
if(owner == Building.NoBuilding) {
|
||||||
|
log.warn(s"Amenity $GUID in zone $Zone tried to access owner, but doesn't have one.")
|
||||||
|
}
|
||||||
|
owner
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an object to have a direct association with (be superior to) this one.
|
* Set an object to have a direct association with (be superior to) this one.
|
||||||
|
|
@ -40,6 +47,17 @@ abstract class Amenity extends PlanetSideServerObject {
|
||||||
Owner
|
Owner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def Zone : Zone = {
|
||||||
|
if(super.Zone != World.Nowhere) {
|
||||||
|
super.Zone
|
||||||
|
} else if(Owner.Zone != World.Nowhere) {
|
||||||
|
Owner.Zone
|
||||||
|
} else {
|
||||||
|
log.warn(s"Amenity $GUID tried to access it's Zone, but doesn't have one.")
|
||||||
|
World.Nowhere
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def LocationOffset : Vector3 = offset.getOrElse(Vector3.Zero)
|
def LocationOffset : Vector3 = offset.getOrElse(Vector3.Zero)
|
||||||
|
|
||||||
def LocationOffset_=(off : Vector3) : Vector3 = LocationOffset_=(Some(off))
|
def LocationOffset_=(off : Vector3) : Vector3 = LocationOffset_=(Some(off))
|
||||||
|
|
@ -53,12 +71,4 @@ abstract class Amenity extends PlanetSideServerObject {
|
||||||
}
|
}
|
||||||
LocationOffset
|
LocationOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
override def Zone : Zone = Owner.Zone
|
|
||||||
|
|
||||||
override def Zone_=(zone : Zone) = Owner.Zone
|
|
||||||
|
|
||||||
override def Continent : String = Owner.Continent
|
|
||||||
|
|
||||||
override def Continent_=(str : String) : String = Owner.Continent
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ class Building(private val name: String,
|
||||||
) = {
|
) = {
|
||||||
val ntuLevel : Int = NtuLevel
|
val ntuLevel : Int = NtuLevel
|
||||||
//if we have a capture terminal, get the hack status & time (in milliseconds) from control console if it exists
|
//if we have a capture terminal, get the hack status & time (in milliseconds) from control console if it exists
|
||||||
val (hacking, hackingFaction, hackTime) : (Boolean, PlanetSideEmpire.Value, Long) = Amenities.find(_.Definition == GlobalDefinitions.capture_terminal) match {
|
val (hacking, hackingFaction, hackTime) : (Boolean, PlanetSideEmpire.Value, Long) = Amenities.find(x => x.Definition == GlobalDefinitions.capture_terminal || x.Definition == GlobalDefinitions.vanu_control_console) match {
|
||||||
case Some(obj: CaptureTerminal with Hackable) =>
|
case Some(obj: CaptureTerminal with Hackable) =>
|
||||||
obj.HackedBy match {
|
obj.HackedBy match {
|
||||||
case Some(Hackable.HackInfo(_, _, hfaction, _, start, length)) =>
|
case Some(Hackable.HackInfo(_, _, hfaction, _, start, length)) =>
|
||||||
|
|
@ -187,7 +187,7 @@ class Building(private val name: String,
|
||||||
(false, PlanetSideEmpire.NEUTRAL, 0L)
|
(false, PlanetSideEmpire.NEUTRAL, 0L)
|
||||||
}
|
}
|
||||||
//TODO if we have a generator, get the current repair state
|
//TODO if we have a generator, get the current repair state
|
||||||
val (generatorState, bootGeneratorPain) = (PlanetSideGeneratorState.Normal, false)
|
val (generatorState, boostGeneratorPain) = (PlanetSideGeneratorState.Normal, false) // todo: poll pain field strength
|
||||||
//if we have spawn tubes, determine if any of them are active
|
//if we have spawn tubes, determine if any of them are active
|
||||||
val (spawnTubesNormal, boostSpawnPain) : (Boolean, Boolean) = {
|
val (spawnTubesNormal, boostSpawnPain) : (Boolean, Boolean) = {
|
||||||
val o = Amenities.collect({ case _ : SpawnTube => true }) ///TODO obj.Health > 0
|
val o = Amenities.collect({ case _ : SpawnTube => true }) ///TODO obj.Health > 0
|
||||||
|
|
@ -252,13 +252,13 @@ class Building(private val name: String,
|
||||||
ForceDomeActive,
|
ForceDomeActive,
|
||||||
latticeBenefit,
|
latticeBenefit,
|
||||||
0, //cavern_benefit; !! Field > 0 will cause malformed packet. See class def.
|
0, //cavern_benefit; !! Field > 0 will cause malformed packet. See class def.
|
||||||
Nil,
|
Nil, //unk4
|
||||||
0,
|
0, //unk5
|
||||||
false,
|
false, //unk6
|
||||||
8, //!! Field != 8 will cause malformed packet. See class def.
|
8, //!! unk7 Field != 8 will cause malformed packet. See class def.
|
||||||
None,
|
None, //unk7x
|
||||||
boostSpawnPain, //boost_spawn_pain
|
boostSpawnPain, //boost_spawn_pain
|
||||||
bootGeneratorPain //boost_generator_pain
|
boostGeneratorPain //boost_generator_pain
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ class ProximityTerminalControl(term : Terminal with ProximityUnit) extends Actor
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
terminalAction.cancel
|
terminalAction.cancel
|
||||||
terminalAction = context.system.scheduler.schedule(500 milliseconds, medDef.Interval, self, ProximityTerminalControl.TerminalAction())
|
terminalAction = context.system.scheduler.schedule(500 milliseconds, medDef.Interval, self, ProximityTerminalControl.TerminalAction())
|
||||||
TerminalObject.Owner.Zone.LocalEvents ! Terminal.StartProximityEffect(term)
|
TerminalObject.Zone.LocalEvents ! Terminal.StartProximityEffect(term)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -103,7 +103,7 @@ class ProximityTerminalControl(term : Terminal with ProximityUnit) extends Actor
|
||||||
//de-activation (global / local)
|
//de-activation (global / local)
|
||||||
if(term.NumberUsers == 0 && hadUsers) {
|
if(term.NumberUsers == 0 && hadUsers) {
|
||||||
terminalAction.cancel
|
terminalAction.cancel
|
||||||
TerminalObject.Owner.Zone.LocalEvents ! Terminal.StopProximityEffect(term)
|
TerminalObject.Zone.LocalEvents ! Terminal.StopProximityEffect(term)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,14 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private def BuildLocalObjects(implicit context : ActorContext, guid : NumberPoolHub) : Unit = {
|
private def BuildLocalObjects(implicit context : ActorContext, guid : NumberPoolHub) : Unit = {
|
||||||
Map.LocalObjects.foreach({ builderObject => builderObject.Build })
|
Map.LocalObjects.foreach({ builderObject =>
|
||||||
|
builderObject.Build
|
||||||
|
|
||||||
|
val obj = guid(builderObject.Id)
|
||||||
|
obj collect {
|
||||||
|
case el : ZoneAware => el.Zone = this
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private def BuildSupportObjects() : Unit = {
|
private def BuildSupportObjects() : Unit = {
|
||||||
|
|
|
||||||
|
|
@ -339,7 +339,8 @@ class WorldSessionActor extends Actor
|
||||||
case out @ Some(obj) if obj.HasGUID =>
|
case out @ Some(obj) if obj.HasGUID =>
|
||||||
out
|
out
|
||||||
case None if id.nonEmpty =>
|
case None if id.nonEmpty =>
|
||||||
//delete stale entity reference from client (deferred until later)
|
//delete stale entity reference from client
|
||||||
|
log.warn(s"Player ${player.Name} has an invalid reference to GUID ${id.get} in zone ${continent.Id}. Delete object on client.")
|
||||||
//sendResponse(ObjectDeleteMessage(id.get, 0))
|
//sendResponse(ObjectDeleteMessage(id.get, 0))
|
||||||
None
|
None
|
||||||
case _ =>
|
case _ =>
|
||||||
|
|
@ -4554,6 +4555,7 @@ class WorldSessionActor extends Actor
|
||||||
|
|
||||||
if(isTeleporter) {
|
if(isTeleporter) {
|
||||||
val endPoint = path.get.ZipLinePoints.last
|
val endPoint = path.get.ZipLinePoints.last
|
||||||
|
sendResponse(ZipLineMessage(PlanetSideGUID(0), forwards, 0, path_id, pos)) // todo: send to zone to show teleport animation to all clients
|
||||||
sendResponse(PlayerStateShiftMessage(ShiftState(0, endPoint, player.Orientation.z, None)))
|
sendResponse(PlayerStateShiftMessage(ShiftState(0, endPoint, player.Orientation.z, None)))
|
||||||
} else {
|
} else {
|
||||||
action match {
|
action match {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue