mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-03-06 05:30:21 +00:00
Better Respawn (#810)
* biolab spawn benefit should now be active; spawn point integrity at point of player avatar creation, or else try again * streamlined the process of determining whether a facility possesses individual benefits; warp gates do not have benefits * fix for mounted turret persistance
This commit is contained in:
parent
97b4ad8f67
commit
010b1c5845
3 changed files with 196 additions and 95 deletions
|
|
@ -200,6 +200,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
var lastTerminalOrderFulfillment: Boolean = true
|
||||
var shiftPosition: Option[Vector3] = None
|
||||
var shiftOrientation: Option[Vector3] = None
|
||||
var nextSpawnPoint: Option[SpawnPoint] = None
|
||||
var setupAvatarFunc: () => Unit = AvatarCreate
|
||||
var setCurrentAvatarFunc: Player => Unit = SetCurrentAvatarNormally
|
||||
var persist: () => Unit = NoPersistence
|
||||
|
|
@ -509,14 +510,14 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
case Some(0) =>
|
||||
deadState = DeadState.Release // cancel movement updates
|
||||
vehicle.Position = position
|
||||
LoadZonePhysicalSpawnPoint(zoneId, position, Vector3.Zero, 0 seconds)
|
||||
LoadZonePhysicalSpawnPoint(zoneId, position, Vector3.Zero, 0 seconds, None)
|
||||
case _ => // not seated as the driver, in which case we can't move
|
||||
}
|
||||
case None =>
|
||||
deadState = DeadState.Release // cancel movement updates
|
||||
player.Position = position
|
||||
// continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.ObjectDelete(player.GUID, player.GUID))
|
||||
LoadZonePhysicalSpawnPoint(zoneId, position, Vector3.Zero, 0 seconds)
|
||||
LoadZonePhysicalSpawnPoint(zoneId, position, Vector3.Zero, 0 seconds, None)
|
||||
case _ => // seated in something that is not a vehicle or the vehicle is cargo, in which case we can't move
|
||||
}
|
||||
}
|
||||
|
|
@ -530,7 +531,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
case Some(0) =>
|
||||
deadState = DeadState.Release // cancel movement updates
|
||||
vehicle.Position = position
|
||||
LoadZonePhysicalSpawnPoint(continent.id, position, Vector3.z(vehicle.Orientation.z), 0 seconds)
|
||||
LoadZonePhysicalSpawnPoint(continent.id, position, Vector3.z(vehicle.Orientation.z), 0 seconds, None)
|
||||
case _ => // not seated as the driver, in which case we can't move
|
||||
}
|
||||
case None =>
|
||||
|
|
@ -610,7 +611,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
deadState = DeadState.Release
|
||||
sendResponse(AvatarDeadStateMessage(DeadState.Release, 0, 0, player.Position, player.Faction, true))
|
||||
interstellarFerry = Some(v) //on the other continent and registered to that continent's GUID system
|
||||
LoadZonePhysicalSpawnPoint(v.Continent, v.Position, v.Orientation, 1 seconds)
|
||||
LoadZonePhysicalSpawnPoint(v.Continent, v.Position, v.Orientation, 1 seconds, None)
|
||||
case _ =>
|
||||
interstellarFerry match {
|
||||
case None =>
|
||||
|
|
@ -1003,16 +1004,14 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
response match {
|
||||
case Some((zone, spawnPoint)) =>
|
||||
val obj = continent.GUID(player.VehicleSeated) match {
|
||||
case Some(obj: Vehicle) if !obj.Destroyed =>
|
||||
obj
|
||||
case _ =>
|
||||
player
|
||||
case Some(obj: Vehicle) if !obj.Destroyed => obj
|
||||
case _ => player
|
||||
}
|
||||
val (pos, ori) = spawnPoint.SpecificPoint(obj)
|
||||
if (previousZoningType == Zoning.Method.InstantAction)
|
||||
LoadZonePhysicalSpawnPoint(zone.id, pos, ori, respawnTime = 0 seconds)
|
||||
LoadZonePhysicalSpawnPoint(zone.id, pos, ori, respawnTime = 0 seconds, Some(spawnPoint))
|
||||
else
|
||||
LoadZonePhysicalSpawnPoint(zone.id, pos, ori, CountSpawnDelay(zone.id, spawnPoint, continent.id))
|
||||
LoadZonePhysicalSpawnPoint(zone.id, pos, ori, CountSpawnDelay(zone.id, spawnPoint, continent.id), Some(spawnPoint))
|
||||
case None =>
|
||||
log.warn(
|
||||
s"SpawnPointResponse: ${player.Name} received no spawn point response when asking InterstellarClusterService; sending home"
|
||||
|
|
@ -1300,37 +1299,58 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
session.zone.map.checksum
|
||||
)
|
||||
)
|
||||
//important! the LoadMapMessage must be processed by the client before the avatar is created
|
||||
setupAvatarFunc()
|
||||
//interimUngunnedVehicle should have been setup by setupAvatarFunc, if it is applicable
|
||||
turnCounterFunc = interimUngunnedVehicle match {
|
||||
case Some(_) =>
|
||||
TurnCounterDuringInterimWhileInPassengerSeat
|
||||
case None =>
|
||||
TurnCounterDuringInterim
|
||||
if (isAcceptableNextSpawnPoint()) {
|
||||
//important! the LoadMapMessage must be processed by the client before the avatar is created
|
||||
setupAvatarFunc()
|
||||
//interimUngunnedVehicle should have been setup by setupAvatarFunc, if it is applicable
|
||||
turnCounterFunc = interimUngunnedVehicle match {
|
||||
case Some(_) =>
|
||||
TurnCounterDuringInterimWhileInPassengerSeat
|
||||
case None =>
|
||||
TurnCounterDuringInterim
|
||||
}
|
||||
keepAliveFunc = NormalKeepAlive
|
||||
upstreamMessageCount = 0
|
||||
setAvatar = false
|
||||
persist()
|
||||
} else {
|
||||
//look for different spawn point in same zone
|
||||
cluster ! ICS.GetNearbySpawnPoint(
|
||||
session.zone.Number,
|
||||
tplayer,
|
||||
Seq(SpawnGroup.Facility, SpawnGroup.Tower, SpawnGroup.AMS),
|
||||
context.self
|
||||
)
|
||||
}
|
||||
keepAliveFunc = NormalKeepAlive
|
||||
upstreamMessageCount = 0
|
||||
setAvatar = false
|
||||
persist()
|
||||
|
||||
case PlayerLoaded(tplayer) =>
|
||||
//same zone
|
||||
log.info(s"${tplayer.Name} will respawn")
|
||||
tplayer.avatar = avatar
|
||||
session = session.copy(player = tplayer)
|
||||
setupAvatarFunc()
|
||||
//interimUngunnedVehicle should have been setup by setupAvatarFunc, if it is applicable
|
||||
turnCounterFunc = interimUngunnedVehicle match {
|
||||
case Some(_) =>
|
||||
TurnCounterDuringInterimWhileInPassengerSeat
|
||||
case None =>
|
||||
TurnCounterDuringInterim
|
||||
if (isAcceptableNextSpawnPoint()) {
|
||||
//try this spawn point
|
||||
setupAvatarFunc()
|
||||
//interimUngunnedVehicle should have been setup by setupAvatarFunc, if it is applicable
|
||||
turnCounterFunc = interimUngunnedVehicle match {
|
||||
case Some(_) =>
|
||||
TurnCounterDuringInterimWhileInPassengerSeat
|
||||
case None =>
|
||||
TurnCounterDuringInterim
|
||||
}
|
||||
keepAliveFunc = NormalKeepAlive
|
||||
upstreamMessageCount = 0
|
||||
setAvatar = false
|
||||
persist()
|
||||
} else {
|
||||
//look for different spawn point in same zone
|
||||
cluster ! ICS.GetNearbySpawnPoint(
|
||||
continent.Number,
|
||||
tplayer,
|
||||
Seq(SpawnGroup.Facility, SpawnGroup.Tower, SpawnGroup.AMS),
|
||||
context.self
|
||||
)
|
||||
}
|
||||
keepAliveFunc = NormalKeepAlive
|
||||
upstreamMessageCount = 0
|
||||
setAvatar = false
|
||||
persist()
|
||||
|
||||
case PlayerFailedToLoad(tplayer) =>
|
||||
player.Continent match {
|
||||
|
|
@ -1386,7 +1406,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
continent.Population ! Zone.Population.Leave(avatar) //does not matter if it doesn't work
|
||||
zoneLoaded = None
|
||||
zoneReload = true
|
||||
LoadZonePhysicalSpawnPoint(toZoneId, pos, orient, 0 seconds)
|
||||
LoadZonePhysicalSpawnPoint(toZoneId, pos, orient, respawnTime = 0 seconds, None)
|
||||
}
|
||||
} else if (tplayer.isAlive) {
|
||||
if (
|
||||
|
|
@ -1399,7 +1419,8 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
if (!setAvatar || waitingOnUpstream) {
|
||||
setCurrentAvatarFunc(tplayer)
|
||||
respawnTimer = context.system.scheduler.scheduleOnce(
|
||||
delay = (if (attempt <= max_attempts / 2) 10 else 5) seconds,
|
||||
delay = (if (attempt <= max_attempts / 2) 10
|
||||
else 5) seconds,
|
||||
self,
|
||||
SetCurrentAvatar(tplayer, max_attempts, attempt + max_attempts / 3)
|
||||
)
|
||||
|
|
@ -1408,8 +1429,10 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
case (Some(v: Vehicle), Some(seatNumber))
|
||||
if seatNumber > 0 && v.WeaponControlledFromSeat(seatNumber).isEmpty =>
|
||||
KeepAlivePersistence
|
||||
case _ => NormalKeepAlive
|
||||
case _ =>
|
||||
NormalKeepAlive
|
||||
}
|
||||
nextSpawnPoint = None
|
||||
}
|
||||
//if not the condition above, player has started playing normally
|
||||
} else {
|
||||
|
|
@ -1693,7 +1716,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
interstellarFerry = Some(droppod) //leverage vehicle gating
|
||||
player.Position = droppod.Position
|
||||
player.VehicleSeated = PlanetSideGUID(0)
|
||||
LoadZonePhysicalSpawnPoint(zone.id, droppod.Position, Vector3.Zero, 0 seconds)
|
||||
LoadZonePhysicalSpawnPoint(zone.id, droppod.Position, Vector3.Zero, 0 seconds, None)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2571,7 +2594,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
sendResponse(PlanetsideAttributeMessage(obj.GUID, 0, obj.Health))
|
||||
UpdateWeaponAtSeatPosition(obj, seat_number)
|
||||
MountingAction(tplayer, obj, seat_number)
|
||||
keepAliveFunc = KeepAlivePersistence
|
||||
|
||||
case Mountable.CanMount(obj: Mountable, _, _) =>
|
||||
log.warn(s"MountVehicleMsg: $obj is some mountable object and nothing will happen for ${player.Name}")
|
||||
|
|
@ -3948,11 +3970,11 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
FindContainedWeapon match {
|
||||
case (Some(o), Some(tool)) =>
|
||||
(o match {
|
||||
case mount: Mountable => mount.PassengerInSeat(player)
|
||||
case _ => None
|
||||
case mount: Mountable => (o, mount.PassengerInSeat(player))
|
||||
case _ => (None, None)
|
||||
}) match {
|
||||
case None | Some(0) => ;
|
||||
case Some(_) =>
|
||||
case (None, None) | (_, None) | (_: Vehicle, Some(0)) => ;
|
||||
case _ =>
|
||||
persist()
|
||||
turnCounterFunc(player.GUID)
|
||||
}
|
||||
|
|
@ -8593,7 +8615,13 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
* @param respawnTime the character downtime spent respawning, as clocked on the redeployment screen;
|
||||
* does not factor in any time required for loading zone or game objects
|
||||
*/
|
||||
def LoadZonePhysicalSpawnPoint(zoneId: String, pos: Vector3, ori: Vector3, respawnTime: FiniteDuration): Unit = {
|
||||
def LoadZonePhysicalSpawnPoint(
|
||||
zoneId: String,
|
||||
pos: Vector3,
|
||||
ori: Vector3,
|
||||
respawnTime: FiniteDuration,
|
||||
physSpawnPoint: Option[SpawnPoint]
|
||||
): Unit = {
|
||||
log.info(s"${player.Name} will load in zone $zoneId at position $pos in $respawnTime")
|
||||
respawnTimer.cancel()
|
||||
reviveTimer.cancel()
|
||||
|
|
@ -8608,6 +8636,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
unk5 = true
|
||||
)
|
||||
)
|
||||
nextSpawnPoint = physSpawnPoint
|
||||
shiftPosition = Some(pos)
|
||||
shiftOrientation = Some(ori)
|
||||
|
||||
|
|
@ -9128,6 +9157,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
/**
|
||||
* Given an origin and a destination, determine how long the process of traveling should take in reconstruction time.
|
||||
* For most destinations, the unit of receiving ("spawn point") determines the reconstruction time.
|
||||
* Possession of a lattice-linked friendly Bio Laboratory halves the time of spawning at facilities.
|
||||
* In a special consideration, travel to any sanctuary or sanctuary-special zone should be as immediate as zone loading.
|
||||
*
|
||||
* @param toZoneId the zone where the target is headed
|
||||
|
|
@ -9137,12 +9167,18 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
*/
|
||||
def CountSpawnDelay(toZoneId: String, toSpawnPoint: SpawnPoint, fromZoneId: String): FiniteDuration = {
|
||||
val sanctuaryZoneId = Zones.sanctuaryZoneId(player.Faction)
|
||||
if (fromZoneId.equals("Nowhere") || sanctuaryZoneId.equals(toZoneId)) { //to sanctuary
|
||||
if (fromZoneId.equals("Nowhere") || sanctuaryZoneId.equals(toZoneId) || !isAcceptableNextSpawnPoint()) {
|
||||
//first login, to sanctuary, resolution of invalid spawn point
|
||||
0 seconds
|
||||
} else if (!player.isAlive) {
|
||||
toSpawnPoint.Definition.Delay seconds //TODO +cumulative death penalty
|
||||
} else {
|
||||
toSpawnPoint.Definition.Delay seconds
|
||||
//for other zones ...
|
||||
//biolabs have/grant benefits
|
||||
val cryoBenefit: Float = toSpawnPoint.Owner match {
|
||||
case b: Building if b.hasLatticeBenefit(GlobalDefinitions.cryo_facility) => 0.5f
|
||||
case _ => 1f
|
||||
}
|
||||
//TODO cumulative death penalty
|
||||
toSpawnPoint.Definition.Delay.toFloat * cryoBenefit seconds
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9714,6 +9750,24 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
}
|
||||
}
|
||||
|
||||
def isAcceptableNextSpawnPoint(): Boolean = isAcceptableSpawnPoint(nextSpawnPoint)
|
||||
|
||||
def isAcceptableSpawnPoint(spawnPoint: SpawnPoint): Boolean = isAcceptableSpawnPoint(Some(spawnPoint))
|
||||
|
||||
def isAcceptableSpawnPoint(spawnPoint: Option[SpawnPoint]): Boolean = {
|
||||
spawnPoint match {
|
||||
case Some(aSpawnPoint) =>
|
||||
!aSpawnPoint.isOffline &&
|
||||
(aSpawnPoint.Owner match {
|
||||
case w: WarpGate => w.Active
|
||||
case b: Building => b.Faction == player.Faction
|
||||
case v: Vehicle => v.Faction == player.Faction && !v.Destroyed && v.DeploymentState == DriveState.Deployed
|
||||
case _ => true
|
||||
})
|
||||
case None => true
|
||||
}
|
||||
}
|
||||
|
||||
def failWithError(error: String) = {
|
||||
log.error(error)
|
||||
middlewareActor ! MiddlewareActor.Teardown()
|
||||
|
|
|
|||
|
|
@ -182,53 +182,6 @@ class Building(
|
|||
(o.nonEmpty, false) //TODO poll pain field strength
|
||||
}
|
||||
|
||||
val latticeBenefit: Int = {
|
||||
if (Faction == PlanetSideEmpire.NEUTRAL) 0
|
||||
else {
|
||||
def FindLatticeBenefit(
|
||||
wantedBenefit: ObjectDefinition,
|
||||
subGraph: Graph[Building, GraphEdge.UnDiEdge]
|
||||
): Boolean = {
|
||||
var found = false
|
||||
|
||||
subGraph find this match {
|
||||
case Some(self) =>
|
||||
if (this.Definition == wantedBenefit) found = true
|
||||
else {
|
||||
self pathUntil (_.Definition == wantedBenefit) match {
|
||||
case Some(_) => found = true
|
||||
case None => ;
|
||||
}
|
||||
}
|
||||
case None => ;
|
||||
}
|
||||
|
||||
found
|
||||
}
|
||||
|
||||
// Check this Building is on the lattice first
|
||||
zone.Lattice find this match {
|
||||
case Some(_) =>
|
||||
val subGraph = Zone.Lattice filter ((b: Building) =>
|
||||
b.Faction == this.Faction
|
||||
&& !b.CaptureTerminalIsHacked
|
||||
&& b.NtuLevel > 0
|
||||
&& (b.Generator.isEmpty || b.Generator.get.Condition != PlanetSideGeneratorState.Destroyed)
|
||||
)
|
||||
|
||||
var stackedBenefit = 0
|
||||
if (FindLatticeBenefit(GlobalDefinitions.amp_station, subGraph)) stackedBenefit |= 1
|
||||
if (FindLatticeBenefit(GlobalDefinitions.comm_station_dsp, subGraph)) stackedBenefit |= 2
|
||||
if (FindLatticeBenefit(GlobalDefinitions.cryo_facility, subGraph)) stackedBenefit |= 4
|
||||
if (FindLatticeBenefit(GlobalDefinitions.comm_station, subGraph)) stackedBenefit |= 8
|
||||
if (FindLatticeBenefit(GlobalDefinitions.tech_plant, subGraph)) stackedBenefit |= 16
|
||||
|
||||
stackedBenefit
|
||||
case None => 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BuildingInfoUpdateMessage(
|
||||
Zone.Number,
|
||||
MapId,
|
||||
|
|
@ -242,7 +195,7 @@ class Building(
|
|||
generatorState,
|
||||
spawnTubesNormal,
|
||||
forceDomeActive,
|
||||
if (generatorState != PlanetSideGeneratorState.Destroyed) latticeBenefit else 0,
|
||||
if (generatorState != PlanetSideGeneratorState.Destroyed) latticeBenefitsValue() else 0,
|
||||
if (generatorState != PlanetSideGeneratorState.Destroyed) 48 else 0, // cavern benefit
|
||||
Nil, // unk4,
|
||||
0, // unk5
|
||||
|
|
@ -254,6 +207,95 @@ class Building(
|
|||
)
|
||||
}
|
||||
|
||||
def hasLatticeBenefit(wantedBenefit: ObjectDefinition): Boolean = {
|
||||
if (Faction == PlanetSideEmpire.NEUTRAL) {
|
||||
false
|
||||
} else {
|
||||
// Check this Building is on the lattice first
|
||||
zone.Lattice find this match {
|
||||
case Some(_) =>
|
||||
val subGraph = Zone.Lattice filter (
|
||||
(b : Building) =>
|
||||
b.Faction == this.Faction &&
|
||||
!b.CaptureTerminalIsHacked &&
|
||||
b.NtuLevel > 0 &&
|
||||
(b.Generator.isEmpty || b.Generator.get.Condition != PlanetSideGeneratorState.Destroyed)
|
||||
)
|
||||
findLatticeBenefit(wantedBenefit, subGraph)
|
||||
case None =>
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def findLatticeBenefit(
|
||||
wantedBenefit: ObjectDefinition,
|
||||
subGraph: Graph[Building, GraphEdge.UnDiEdge]
|
||||
): Boolean = {
|
||||
var found = false
|
||||
subGraph find this match {
|
||||
case Some(self) =>
|
||||
if (this.Definition == wantedBenefit) {
|
||||
found = true
|
||||
} else {
|
||||
self pathUntil (_.Definition == wantedBenefit) match {
|
||||
case Some(_) => found = true
|
||||
case None => ;
|
||||
}
|
||||
}
|
||||
case None => ;
|
||||
}
|
||||
found
|
||||
}
|
||||
|
||||
def latticeConnectedFacilityBenefits(): Set[ObjectDefinition] = {
|
||||
if (Faction == PlanetSideEmpire.NEUTRAL) {
|
||||
Set.empty
|
||||
} else {
|
||||
// Check this Building is on the lattice first
|
||||
zone.Lattice find this match {
|
||||
case Some(_) =>
|
||||
val subGraph = Zone.Lattice filter ((b: Building) =>
|
||||
b.Faction == this.Faction
|
||||
&& !b.CaptureTerminalIsHacked
|
||||
&& b.NtuLevel > 0
|
||||
&& (b.Generator.isEmpty || b.Generator.get.Condition != PlanetSideGeneratorState.Destroyed)
|
||||
)
|
||||
|
||||
import scala.collection.mutable
|
||||
var connectedBases: mutable.Set[ObjectDefinition] = mutable.Set()
|
||||
if (findLatticeBenefit(GlobalDefinitions.amp_station, subGraph)) {
|
||||
connectedBases.add(GlobalDefinitions.amp_station)
|
||||
}
|
||||
if (findLatticeBenefit(GlobalDefinitions.comm_station_dsp, subGraph)) {
|
||||
connectedBases.add(GlobalDefinitions.comm_station_dsp)
|
||||
}
|
||||
if (findLatticeBenefit(GlobalDefinitions.cryo_facility, subGraph)) {
|
||||
connectedBases.add(GlobalDefinitions.cryo_facility)
|
||||
}
|
||||
if (findLatticeBenefit(GlobalDefinitions.comm_station, subGraph)) {
|
||||
connectedBases.add(GlobalDefinitions.comm_station)
|
||||
}
|
||||
if (findLatticeBenefit(GlobalDefinitions.tech_plant, subGraph)) {
|
||||
connectedBases.add(GlobalDefinitions.tech_plant)
|
||||
}
|
||||
connectedBases.toSet
|
||||
case None =>
|
||||
Set.empty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def latticeBenefitsValue(): Int = {
|
||||
latticeConnectedFacilityBenefits().collect {
|
||||
case GlobalDefinitions.amp_station => 1
|
||||
case GlobalDefinitions.comm_station_dsp => 2
|
||||
case GlobalDefinitions.cryo_facility => 4
|
||||
case GlobalDefinitions.comm_station => 8
|
||||
case GlobalDefinitions.tech_plant => 16
|
||||
}.sum
|
||||
}
|
||||
|
||||
def BuildingType: StructureType = buildingType
|
||||
|
||||
override def Zone_=(zone: Zone): Zone = Zone //building never leaves zone after being set in constructor
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import net.psforever.packet.game.BuildingInfoUpdateMessage
|
|||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGeneratorState, Vector3}
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import net.psforever.actors.zone.BuildingActor
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
|
|
@ -154,6 +155,10 @@ class WarpGate(name: String, building_guid: Int, map_id: Int, zone: Zone, buildi
|
|||
|
||||
def NtuCapacitor_=(value: Float): Float = NtuCapacitor
|
||||
|
||||
override def hasLatticeBenefit(wantedBenefit: ObjectDefinition): Boolean = false
|
||||
|
||||
override def latticeConnectedFacilityBenefits(): Set[ObjectDefinition] = Set.empty
|
||||
|
||||
override def Definition: WarpGateDefinition = buildingDefinition
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue