mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-07-15 16:34:42 +00:00
Merge pull request #1332 from ScrawnyRonnie/cont-lock
Continental Locks and Benefits
This commit is contained in:
commit
3358a2f0ed
9 changed files with 176 additions and 53 deletions
|
|
@ -60,10 +60,6 @@ add_property maelstrom equiptime 1000
|
||||||
add_property maelstrom holstertime 1000
|
add_property maelstrom holstertime 1000
|
||||||
add_property magcutter equiptime 250
|
add_property magcutter equiptime 250
|
||||||
add_property magcutter holstertime 250
|
add_property magcutter holstertime 250
|
||||||
add_property medicalapplicator equiptime 500
|
|
||||||
add_property medicalapplicator holstertime 500
|
|
||||||
add_property medicalapplicator firemode0_refiretime 500
|
|
||||||
add_property medicalapplicator firemode1_refiretime 500
|
|
||||||
add_property mini_chaingun equiptime 750
|
add_property mini_chaingun equiptime 750
|
||||||
add_property mini_chaingun holstertime 750
|
add_property mini_chaingun holstertime 750
|
||||||
add_property nano_dispenser equiptime 750
|
add_property nano_dispenser equiptime 750
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,11 @@ object MiddlewareActor {
|
||||||
packet.isInstanceOf[ChatMsg]
|
packet.isInstanceOf[ChatMsg]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** `PropertyOverrideMessage` ptsd from other large packets causing issues when bundled */
|
||||||
|
private def propertyOverrideMessageGuard(packet: PlanetSidePacket): Boolean = {
|
||||||
|
packet.isInstanceOf[PropertyOverrideMessage]
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function for blanking tasks related to inbound packet resolution.
|
* A function for blanking tasks related to inbound packet resolution.
|
||||||
* Do nothing.
|
* Do nothing.
|
||||||
|
|
@ -259,7 +264,8 @@ class MiddlewareActor(
|
||||||
MiddlewareActor.keepAliveMessageGuard,
|
MiddlewareActor.keepAliveMessageGuard,
|
||||||
MiddlewareActor.characterInfoMessageGuard,
|
MiddlewareActor.characterInfoMessageGuard,
|
||||||
MiddlewareActor.squadDetailDefinitionMessageGuard,
|
MiddlewareActor.squadDetailDefinitionMessageGuard,
|
||||||
MiddlewareActor.chatMsgGuard
|
MiddlewareActor.chatMsgGuard,
|
||||||
|
MiddlewareActor.propertyOverrideMessageGuard
|
||||||
)
|
)
|
||||||
|
|
||||||
private val smpHistoryLength: Int = 100
|
private val smpHistoryLength: Int = 100
|
||||||
|
|
|
||||||
|
|
@ -2218,12 +2218,12 @@ class AvatarActor(
|
||||||
.Holsters()
|
.Holsters()
|
||||||
.foreach(holster =>
|
.foreach(holster =>
|
||||||
holster.Equipment match {
|
holster.Equipment match {
|
||||||
case Some(tool: Tool) if tool.Definition == GlobalDefinitions.medicalapplicator =>
|
/*case Some(tool: Tool) if tool.Definition == GlobalDefinitions.medicalapplicator =>
|
||||||
//todo fix so player may hold medapp when loading the zone (client crash)
|
//todo fix so player may hold medapp when loading the zone (client crash)
|
||||||
val item = SimpleItem(GlobalDefinitions.flail_targeting_laser)
|
val item = SimpleItem(GlobalDefinitions.flail_targeting_laser)
|
||||||
holster.Equipment = None
|
holster.Equipment = None
|
||||||
holster.Equipment = item
|
holster.Equipment = item
|
||||||
item.GUID = PlanetSideGUID(gen.getAndIncrement)
|
item.GUID = PlanetSideGUID(gen.getAndIncrement)*/
|
||||||
case Some(tool: Tool) =>
|
case Some(tool: Tool) =>
|
||||||
tool.AmmoSlots.foreach(slot => {
|
tool.AmmoSlots.foreach(slot => {
|
||||||
slot.Box.GUID = PlanetSideGUID(gen.getAndIncrement)
|
slot.Box.GUID = PlanetSideGUID(gen.getAndIncrement)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import net.psforever.actors.session.{AvatarActor, SessionActor}
|
||||||
import net.psforever.actors.zone.ZoneActor
|
import net.psforever.actors.zone.ZoneActor
|
||||||
import net.psforever.objects.LivePlayerList
|
import net.psforever.objects.LivePlayerList
|
||||||
import net.psforever.objects.sourcing.PlayerSource
|
import net.psforever.objects.sourcing.PlayerSource
|
||||||
import net.psforever.objects.zones.ZoneInfo
|
import net.psforever.objects.zones.{Zone, ZoneInfo}
|
||||||
import net.psforever.packet.game.SetChatFilterMessage
|
import net.psforever.packet.game.SetChatFilterMessage
|
||||||
import net.psforever.services.chat.{DefaultChannel, OutfitChannel, SquadChannel}
|
import net.psforever.services.chat.{DefaultChannel, OutfitChannel, SquadChannel}
|
||||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
|
@ -20,7 +20,7 @@ import net.psforever.services.teamwork.{SquadResponse, SquadService, SquadServic
|
||||||
import net.psforever.types.ChatMessageType.CMT_QUIT
|
import net.psforever.types.ChatMessageType.CMT_QUIT
|
||||||
import org.log4s.Logger
|
import org.log4s.Logger
|
||||||
|
|
||||||
import java.util.concurrent.{Executors, TimeUnit}
|
import java.util.concurrent.{Executors, ScheduledFuture, TimeUnit}
|
||||||
import scala.annotation.unused
|
import scala.annotation.unused
|
||||||
import scala.collection.{Seq, mutable}
|
import scala.collection.{Seq, mutable}
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
|
@ -368,7 +368,9 @@ class ChatOperations(
|
||||||
case (Some(buildings), Some(faction), Some(_)) =>
|
case (Some(buildings), Some(faction), Some(_)) =>
|
||||||
//TODO implement timer
|
//TODO implement timer
|
||||||
//schedule processing of buildings with a delay
|
//schedule processing of buildings with a delay
|
||||||
processBuildingsWithDelay(buildings, faction, 1000) //delay of 1000ms between each building operation
|
processBuildingsWithDelay(buildings, faction, 1000) { zone =>
|
||||||
|
zone.actor ! ZoneActor.AssignLockedBy(zone, notifyPlayers=true)
|
||||||
|
}
|
||||||
true
|
true
|
||||||
case _ =>
|
case _ =>
|
||||||
false
|
false
|
||||||
|
|
@ -379,30 +381,30 @@ class ChatOperations(
|
||||||
buildings: Seq[Building],
|
buildings: Seq[Building],
|
||||||
faction: PlanetSideEmpire.Value,
|
faction: PlanetSideEmpire.Value,
|
||||||
delayMillis: Long
|
delayMillis: Long
|
||||||
): Unit = {
|
)(onComplete: Zone => Unit): Unit = {
|
||||||
val buildingIterator = buildings.iterator
|
val buildingsToProcess = buildings.filter(b => b.CaptureTerminal.isDefined && b.Faction != faction)
|
||||||
scheduler.scheduleAtFixedRate(
|
val iterator = buildingsToProcess.iterator
|
||||||
|
val zone = buildings.head.Zone
|
||||||
|
var handle: ScheduledFuture[_] = null
|
||||||
|
handle = scheduler.scheduleAtFixedRate(
|
||||||
() => {
|
() => {
|
||||||
if (buildingIterator.hasNext) {
|
if (iterator.hasNext) {
|
||||||
val building = buildingIterator.next()
|
val building = iterator.next()
|
||||||
val terminal = building.CaptureTerminal.get
|
val terminal = building.CaptureTerminal.get
|
||||||
val zone = building.Zone
|
|
||||||
val zoneActor = zone.actor
|
val zoneActor = zone.actor
|
||||||
val buildingActor = building.Actor
|
|
||||||
//clear any previous hack
|
|
||||||
if (building.CaptureTerminalIsHacked) {
|
if (building.CaptureTerminalIsHacked) {
|
||||||
zone.LocalEvents ! LocalServiceMessage(
|
zone.LocalEvents ! LocalServiceMessage(
|
||||||
zone.id,
|
zone.id,
|
||||||
LocalAction.ResecureCaptureTerminal(terminal, PlayerSource.Nobody)
|
LocalAction.ResecureCaptureTerminal(terminal, PlayerSource.Nobody)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
//push any updates this might cause
|
|
||||||
zoneActor ! ZoneActor.ZoneMapUpdate()
|
zoneActor ! ZoneActor.ZoneMapUpdate()
|
||||||
//convert faction affiliation
|
building.Actor ! BuildingActor.SetFaction(faction)
|
||||||
buildingActor ! BuildingActor.SetFaction(faction)
|
building.Actor ! BuildingActor.AmenityStateChange(terminal, Some(false))
|
||||||
buildingActor ! BuildingActor.AmenityStateChange(terminal, Some(false))
|
|
||||||
//push for map updates again
|
|
||||||
zoneActor ! ZoneActor.ZoneMapUpdate()
|
zoneActor ! ZoneActor.ZoneMapUpdate()
|
||||||
|
} else {
|
||||||
|
handle.cancel(false)
|
||||||
|
onComplete(zone)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ import net.psforever.objects.serverobject.turret.FacilityTurret
|
||||||
import net.psforever.objects.vehicles._
|
import net.psforever.objects.vehicles._
|
||||||
import net.psforever.objects.zones.{Zone, ZoneHotSpotProjector, Zoning}
|
import net.psforever.objects.zones.{Zone, ZoneHotSpotProjector, Zoning}
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
import net.psforever.packet.game.{AvatarAwardMessage, AvatarSearchCriteriaMessage, AvatarStatisticsMessage, AwardCompletion, BindPlayerMessage, BindStatus, CargoMountPointStatusMessage, ChangeShortcutBankMessage, ChatChannel, CreateShortcutMessage, DroppodFreefallingMessage, LoadMapMessage, ObjectCreateDetailedMessage, ObjectDeleteMessage, PlanetsideStringAttributeMessage, PlayerStateShiftMessage, SetChatFilterMessage, SetCurrentAvatarMessage, ShiftState}
|
import net.psforever.packet.game.{AvatarAwardMessage, AvatarSearchCriteriaMessage, AvatarStatisticsMessage, AwardCompletion, BindPlayerMessage, BindStatus, CargoMountPointStatusMessage, ChangeShortcutBankMessage, ChatChannel, CreateShortcutMessage, DroppodFreefallingMessage, LoadMapMessage, ObjectCreateDetailedMessage, ObjectDeleteMessage, PlayerStateShiftMessage, SetChatFilterMessage, SetCurrentAvatarMessage, ShiftState}
|
||||||
import net.psforever.packet.game.{AvatarDeadStateMessage, BroadcastWarpgateUpdateMessage, ChatMsg, ContinentalLockUpdateMessage, DeadState, DensityLevelUpdateMessage, DeployRequestMessage, DeployableInfo, DeployableObjectsInfoMessage, DeploymentAction, DisconnectMessage, DroppodError, DroppodLaunchResponseMessage, FriendsResponse, GenericObjectActionMessage, GenericObjectStateMsg, HotSpotUpdateMessage, ObjectAttachMessage, ObjectCreateMessage, PlanetsideAttributeEnum, PlanetsideAttributeMessage, PropertyOverrideMessage, ReplicationStreamMessage, SetEmpireMessage, TimeOfDayMessage, TriggerEffectMessage, ZoneForcedCavernConnectionsMessage, ZoneInfoMessage, ZoneLockInfoMessage, ZonePopulationUpdateMessage, HotSpotInfo => PacketHotSpotInfo}
|
import net.psforever.packet.game.{AvatarDeadStateMessage, BroadcastWarpgateUpdateMessage, ChatMsg, ContinentalLockUpdateMessage, DeadState, DensityLevelUpdateMessage, DeployRequestMessage, DeployableInfo, DeployableObjectsInfoMessage, DeploymentAction, DisconnectMessage, DroppodError, DroppodLaunchResponseMessage, FriendsResponse, GenericObjectActionMessage, GenericObjectStateMsg, HotSpotUpdateMessage, ObjectAttachMessage, ObjectCreateMessage, PlanetsideAttributeEnum, PlanetsideAttributeMessage, PropertyOverrideMessage, ReplicationStreamMessage, SetEmpireMessage, TimeOfDayMessage, TriggerEffectMessage, ZoneForcedCavernConnectionsMessage, ZoneInfoMessage, ZoneLockInfoMessage, ZonePopulationUpdateMessage, HotSpotInfo => PacketHotSpotInfo}
|
||||||
import net.psforever.packet.game.{BeginZoningMessage, DroppodLaunchRequestMessage, ReleaseAvatarRequestMessage, SpawnRequestMessage, WarpgateRequest}
|
import net.psforever.packet.game.{BeginZoningMessage, DroppodLaunchRequestMessage, ReleaseAvatarRequestMessage, SpawnRequestMessage, WarpgateRequest}
|
||||||
import net.psforever.packet.game.DeathStatistic
|
import net.psforever.packet.game.DeathStatistic
|
||||||
|
|
@ -559,18 +559,12 @@ class ZoningOperations(
|
||||||
val popTR = zone.Players.count(_.faction == PlanetSideEmpire.TR)
|
val popTR = zone.Players.count(_.faction == PlanetSideEmpire.TR)
|
||||||
val popNC = zone.Players.count(_.faction == PlanetSideEmpire.NC)
|
val popNC = zone.Players.count(_.faction == PlanetSideEmpire.NC)
|
||||||
val popVS = zone.Players.count(_.faction == PlanetSideEmpire.VS)
|
val popVS = zone.Players.count(_.faction == PlanetSideEmpire.VS)
|
||||||
|
|
||||||
zone.Buildings.foreach({ case (_, building) => initBuilding(continentNumber, building.MapId, building) })
|
zone.Buildings.foreach({ case (_, building) => initBuilding(continentNumber, building.MapId, building) })
|
||||||
sendResponse(ZonePopulationUpdateMessage(continentNumber, 414, 138, popTR, 138, popNC, 138, popVS, 138, popBO))
|
sendResponse(ZonePopulationUpdateMessage(continentNumber, 414, 138, popTR, 138, popNC, 138, popVS, 138, popBO))
|
||||||
//TODO should actually not claim that the sanctuary or VR zones are locked by their respective empire
|
if (continentNumber == 11 || continentNumber == 12 || continentNumber == 13)
|
||||||
if (continentNumber == 11)
|
|
||||||
sendResponse(ContinentalLockUpdateMessage(continentNumber, PlanetSideEmpire.NC))
|
|
||||||
else if (continentNumber == 12)
|
|
||||||
sendResponse(ContinentalLockUpdateMessage(continentNumber, PlanetSideEmpire.TR))
|
|
||||||
else if (continentNumber == 13)
|
|
||||||
sendResponse(ContinentalLockUpdateMessage(continentNumber, PlanetSideEmpire.VS))
|
|
||||||
else
|
|
||||||
sendResponse(ContinentalLockUpdateMessage(continentNumber, PlanetSideEmpire.NEUTRAL))
|
sendResponse(ContinentalLockUpdateMessage(continentNumber, PlanetSideEmpire.NEUTRAL))
|
||||||
|
else
|
||||||
|
sendResponse(ContinentalLockUpdateMessage(continentNumber, zone.lockedBy))
|
||||||
//CaptureFlagUpdateMessage()
|
//CaptureFlagUpdateMessage()
|
||||||
//VanuModuleUpdateMessage()
|
//VanuModuleUpdateMessage()
|
||||||
//ModuleLimitsMessage()
|
//ModuleLimitsMessage()
|
||||||
|
|
@ -640,6 +634,8 @@ class ZoningOperations(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
player.Zone.ApplyHomeLockBenefitsOnLogin(player)
|
||||||
|
SessionOutfitHandlers.HandleLoginOutfitCheck(player, sessionLogic)
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleZoneResponse(foundZone: Zone): Unit = {
|
def handleZoneResponse(foundZone: Zone): Unit = {
|
||||||
|
|
@ -2092,7 +2088,7 @@ class ZoningOperations(
|
||||||
session = session.copy(player = p, avatar = a)
|
session = session.copy(player = p, avatar = a)
|
||||||
sessionLogic.persist()
|
sessionLogic.persist()
|
||||||
setupAvatarFunc = AvatarRejoin
|
setupAvatarFunc = AvatarRejoin
|
||||||
dropMedicalApplicators(p)
|
//dropMedicalApplicators(p)
|
||||||
avatarActor ! AvatarActor.ReplaceAvatar(a)
|
avatarActor ! AvatarActor.ReplaceAvatar(a)
|
||||||
avatarLoginResponse(a)
|
avatarLoginResponse(a)
|
||||||
|
|
||||||
|
|
@ -2102,7 +2098,7 @@ class ZoningOperations(
|
||||||
deadState = DeadState.Dead
|
deadState = DeadState.Dead
|
||||||
session = session.copy(player = p, avatar = a)
|
session = session.copy(player = p, avatar = a)
|
||||||
sessionLogic.persist()
|
sessionLogic.persist()
|
||||||
dropMedicalApplicators(p)
|
//dropMedicalApplicators(p)
|
||||||
HandleReleaseAvatar(p, inZone)
|
HandleReleaseAvatar(p, inZone)
|
||||||
avatarActor ! AvatarActor.ReplaceAvatar(a)
|
avatarActor ! AvatarActor.ReplaceAvatar(a)
|
||||||
avatarLoginResponse(a)
|
avatarLoginResponse(a)
|
||||||
|
|
@ -2546,9 +2542,6 @@ class ZoningOperations(
|
||||||
sessionLogic.general.toggleTeleportSystem(obj, TelepadLike.AppraiseTeleportationSystem(obj, continent))
|
sessionLogic.general.toggleTeleportSystem(obj, TelepadLike.AppraiseTeleportationSystem(obj, continent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (player.outfit_id == 0) {
|
|
||||||
SessionOutfitHandlers.HandleLoginOutfitCheck(player, sessionLogic)
|
|
||||||
}
|
|
||||||
/*make weather happen
|
/*make weather happen
|
||||||
sendResponse(WeatherMessage(List(),List(
|
sendResponse(WeatherMessage(List(),List(
|
||||||
StormInfo(Vector3(0.1f, 0.15f, 0.0f), 240, 217),
|
StormInfo(Vector3(0.1f, 0.15f, 0.0f), 240, 217),
|
||||||
|
|
@ -2672,7 +2665,6 @@ class ZoningOperations(
|
||||||
log.debug(s"AvatarRejoin: ${player.Name} - $guid -> $data")
|
log.debug(s"AvatarRejoin: ${player.Name} - $guid -> $data")
|
||||||
}
|
}
|
||||||
setupAvatarFunc = AvatarCreate
|
setupAvatarFunc = AvatarCreate
|
||||||
SessionOutfitHandlers.HandleLoginOutfitCheck(player, sessionLogic)
|
|
||||||
/*make weather happen
|
/*make weather happen
|
||||||
sendResponse(WeatherMessage(List(),List(
|
sendResponse(WeatherMessage(List(),List(
|
||||||
StormInfo(Vector3(0.1f, 0.15f, 0.0f), 240, 217),
|
StormInfo(Vector3(0.1f, 0.15f, 0.0f), 240, 217),
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import net.psforever.actors.commands.NtuCommand
|
||||||
import net.psforever.actors.zone.building._
|
import net.psforever.actors.zone.building._
|
||||||
import net.psforever.objects.serverobject.structures.{Amenity, Building, StructureType, WarpGate}
|
import net.psforever.objects.serverobject.structures.{Amenity, Building, StructureType, WarpGate}
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
|
import net.psforever.packet.game.ContinentalLockUpdateMessage
|
||||||
import net.psforever.persistence
|
import net.psforever.persistence
|
||||||
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
import net.psforever.services.galaxy.{GalaxyAction, GalaxyServiceMessage}
|
||||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
|
@ -76,6 +78,9 @@ object BuildingActor {
|
||||||
|
|
||||||
final case class DensityLevelUpdate(building: Building) extends Command
|
final case class DensityLevelUpdate(building: Building) extends Command
|
||||||
|
|
||||||
|
final case class ContinentalLock(zone: Zone) extends Command
|
||||||
|
|
||||||
|
final case class HomeLockBenefits(msg: PlanetSideGamePacket) extends Command
|
||||||
/**
|
/**
|
||||||
* Set a facility affiliated to one faction to be affiliated to a different faction.
|
* Set a facility affiliated to one faction to be affiliated to a different faction.
|
||||||
* @param details building and event system references
|
* @param details building and event system references
|
||||||
|
|
@ -252,6 +257,14 @@ class BuildingActor(
|
||||||
case DensityLevelUpdate(building) =>
|
case DensityLevelUpdate(building) =>
|
||||||
details.galaxyService ! GalaxyServiceMessage(GalaxyAction.SendResponse(details.building.densityLevelUpdateMessage(building)))
|
details.galaxyService ! GalaxyServiceMessage(GalaxyAction.SendResponse(details.building.densityLevelUpdateMessage(building)))
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
|
case ContinentalLock(zone) =>
|
||||||
|
details.galaxyService ! GalaxyServiceMessage(GalaxyAction.SendResponse(ContinentalLockUpdateMessage(zone.Number, zone.lockedBy)))
|
||||||
|
Behaviors.same
|
||||||
|
|
||||||
|
case HomeLockBenefits(msg) =>
|
||||||
|
details.galaxyService ! GalaxyServiceMessage(GalaxyAction.SendResponse(msg))
|
||||||
|
Behaviors.same
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,8 @@ object ZoneActor {
|
||||||
final case class RewardThisDeath(entity: PlanetSideGameObject with FactionAffinity with InGameHistory) extends Command
|
final case class RewardThisDeath(entity: PlanetSideGameObject with FactionAffinity with InGameHistory) extends Command
|
||||||
|
|
||||||
final case class RewardOurSupporters(target: SourceEntry, history: Iterable[InGameActivity], kill: Kill, bep: Long) extends Command
|
final case class RewardOurSupporters(target: SourceEntry, history: Iterable[InGameActivity], kill: Kill, bep: Long) extends Command
|
||||||
|
|
||||||
|
final case class AssignLockedBy(zone: Zone, notifyPlayers: Boolean) extends Command
|
||||||
}
|
}
|
||||||
|
|
||||||
class ZoneActor(
|
class ZoneActor(
|
||||||
|
|
@ -115,6 +117,7 @@ class ZoneActor(
|
||||||
// TODO this happens during testing, need a way to not always persist during tests
|
// TODO this happens during testing, need a way to not always persist during tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AssignLockedBy(zone, notifyPlayers=false)
|
||||||
case Failure(e) => log.error(e.getMessage)
|
case Failure(e) => log.error(e.getMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,10 +190,29 @@ class ZoneActor(
|
||||||
.values
|
.values
|
||||||
.foreach(_.Actor ! BuildingActor.MapUpdate())
|
.foreach(_.Actor ! BuildingActor.MapUpdate())
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
||||||
|
case AssignLockedBy(zone, notifyPlayers) =>
|
||||||
|
AssignLockedBy(zone, notifyPlayers)
|
||||||
|
Behaviors.same
|
||||||
}
|
}
|
||||||
.receiveSignal {
|
.receiveSignal {
|
||||||
case (_, PostStop) =>
|
case (_, PostStop) =>
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def AssignLockedBy(zone: Zone, notifyPlayers: Boolean): Unit = {
|
||||||
|
val buildings = zone.Buildings.values
|
||||||
|
val facilities = buildings.filter(_.BuildingType == StructureType.Facility).toSeq
|
||||||
|
val factions = facilities.map(_.Faction).toSet
|
||||||
|
zone.lockedBy =
|
||||||
|
if (factions.size == 1) factions.head
|
||||||
|
else PlanetSideEmpire.NEUTRAL
|
||||||
|
zone.benefitRecipient =
|
||||||
|
if (facilities.nonEmpty && facilities.forall(_.Faction == facilities.head.Faction))
|
||||||
|
facilities.head.Faction
|
||||||
|
else
|
||||||
|
zone.benefitRecipient
|
||||||
|
if (facilities.nonEmpty && notifyPlayers) { zone.NotifyContinentalLockBenefits(zone, facilities.head) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,9 @@ import scalax.collection.GraphEdge._
|
||||||
import scala.util.Try
|
import scala.util.Try
|
||||||
import akka.actor.typed
|
import akka.actor.typed
|
||||||
import net.psforever.actors.session.AvatarActor
|
import net.psforever.actors.session.AvatarActor
|
||||||
import net.psforever.actors.zone.ZoneActor
|
import net.psforever.actors.zone.{BuildingActor, ZoneActor}
|
||||||
import net.psforever.actors.zone.building.WarpGateLogic
|
import net.psforever.actors.zone.building.WarpGateLogic
|
||||||
import net.psforever.objects.avatar.Avatar
|
import net.psforever.objects.avatar.{Avatar, PlayerControl}
|
||||||
import net.psforever.objects.definition.ObjectDefinition
|
import net.psforever.objects.definition.ObjectDefinition
|
||||||
import net.psforever.objects.geometry.d3.VolumetricGeometry
|
import net.psforever.objects.geometry.d3.VolumetricGeometry
|
||||||
import net.psforever.objects.guid.pool.NumberPool
|
import net.psforever.objects.guid.pool.NumberPool
|
||||||
|
|
@ -56,6 +56,7 @@ import net.psforever.objects.vital.interaction.{DamageInteraction, DamageResult}
|
||||||
import net.psforever.objects.vital.prop.DamageWithPosition
|
import net.psforever.objects.vital.prop.DamageWithPosition
|
||||||
import net.psforever.objects.vital.Vitality
|
import net.psforever.objects.vital.Vitality
|
||||||
import net.psforever.objects.zones.blockmap.{BlockMap, SectorPopulation}
|
import net.psforever.objects.zones.blockmap.{BlockMap, SectorPopulation}
|
||||||
|
import net.psforever.packet.game.PropertyOverrideMessage
|
||||||
import net.psforever.services.Service
|
import net.psforever.services.Service
|
||||||
import net.psforever.zones.Zones
|
import net.psforever.zones.Zones
|
||||||
|
|
||||||
|
|
@ -194,6 +195,16 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
|
||||||
*/
|
*/
|
||||||
private var zoneInitialized: Promise[Boolean] = Promise[Boolean]()
|
private var zoneInitialized: Promise[Boolean] = Promise[Boolean]()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For ContinentalLockUpdateMessage
|
||||||
|
*/
|
||||||
|
var lockedBy: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used with lockedBy, but persists until another empire locks the cont
|
||||||
|
*/
|
||||||
|
var benefitRecipient: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the zone has completed initializing, this will be the future.
|
* When the zone has completed initializing, this will be the future.
|
||||||
* @see `init(ActorContext)`
|
* @see `init(ActorContext)`
|
||||||
|
|
@ -639,6 +650,79 @@ class Zone(val id: String, val map: ZoneMap, zoneNumber: Int) {
|
||||||
}
|
}
|
||||||
output.toList
|
output.toList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def NotifyContinentalLockBenefits(zone: Zone, building: Building): Unit = {
|
||||||
|
building.Actor ! BuildingActor.ContinentalLock(zone)
|
||||||
|
ApplyHomeLockBenefits(building)
|
||||||
|
}
|
||||||
|
|
||||||
|
def ApplyHomeLockBenefits(building: Building): Unit = {
|
||||||
|
val homeSets: Map[PlanetSideEmpire.Value, Set[Int]] = Map(
|
||||||
|
PlanetSideEmpire.TR -> Set(1, 2),
|
||||||
|
PlanetSideEmpire.VS -> Set(5, 6),
|
||||||
|
PlanetSideEmpire.NC -> Set(7, 10)
|
||||||
|
)
|
||||||
|
val homePerks: Map[PlanetSideEmpire.Value, String] = Map(
|
||||||
|
PlanetSideEmpire.TR -> "battlewagon prowler threemanheavybuggy",
|
||||||
|
PlanetSideEmpire.VS -> "magrider twomanhoverbuggy aurora",
|
||||||
|
PlanetSideEmpire.NC -> "thunderer twomanheavybuggy vanguard"
|
||||||
|
)
|
||||||
|
|
||||||
|
def isLockedBy(homeSet: Set[Int], empire: PlanetSideEmpire.Value): Boolean =
|
||||||
|
Zones.zones.filter(z => homeSet.contains(z.Number)).forall(_.benefitRecipient == empire)
|
||||||
|
|
||||||
|
val perks: Map[PlanetSideEmpire.Value, String] =
|
||||||
|
PlanetSideEmpire.values.map { empire =>
|
||||||
|
val empirePerks = homeSets.collect {
|
||||||
|
case (owner, zoneSet) if owner != empire && isLockedBy(zoneSet, empire) =>
|
||||||
|
homePerks(owner)
|
||||||
|
}
|
||||||
|
empire -> empirePerks.mkString(" ")
|
||||||
|
}.toMap
|
||||||
|
|
||||||
|
if (perks.values.forall(_.isEmpty)) {/*do nothing*/}
|
||||||
|
else {
|
||||||
|
val msg = PropertyOverrideMessage(List(PropertyOverrideMessage.GamePropertyScope(0, List(PropertyOverrideMessage.GamePropertyTarget(343,
|
||||||
|
List(PropertyOverrideMessage.GameProperty("purchase_exempt_vs", perks(PlanetSideEmpire.VS)),
|
||||||
|
PropertyOverrideMessage.GameProperty("purchase_exempt_tr", perks(PlanetSideEmpire.TR)),
|
||||||
|
PropertyOverrideMessage.GameProperty("purchase_exempt_nc", perks(PlanetSideEmpire.NC))))))))
|
||||||
|
building.Actor ! BuildingActor.HomeLockBenefits(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def ApplyHomeLockBenefitsOnLogin(player: Player): Unit = {
|
||||||
|
val homeSets: Map[PlanetSideEmpire.Value, Set[Int]] = Map(
|
||||||
|
PlanetSideEmpire.TR -> Set(1, 2),
|
||||||
|
PlanetSideEmpire.VS -> Set(5, 6),
|
||||||
|
PlanetSideEmpire.NC -> Set(7, 10)
|
||||||
|
)
|
||||||
|
val homePerks: Map[PlanetSideEmpire.Value, String] = Map(
|
||||||
|
PlanetSideEmpire.TR -> "battlewagon prowler threemanheavybuggy",
|
||||||
|
PlanetSideEmpire.VS -> "magrider twomanhoverbuggy aurora",
|
||||||
|
PlanetSideEmpire.NC -> "thunderer twomanheavybuggy vanguard"
|
||||||
|
)
|
||||||
|
|
||||||
|
def isLockedBy(homeSet: Set[Int], empire: PlanetSideEmpire.Value): Boolean =
|
||||||
|
Zones.zones.filter(z => homeSet.contains(z.Number)).forall(_.benefitRecipient == empire)
|
||||||
|
|
||||||
|
val perks: Map[PlanetSideEmpire.Value, String] =
|
||||||
|
PlanetSideEmpire.values.map { empire =>
|
||||||
|
val empirePerks = homeSets.collect {
|
||||||
|
case (owner, zoneSet) if owner != empire && isLockedBy(zoneSet, empire) =>
|
||||||
|
homePerks(owner)
|
||||||
|
}
|
||||||
|
empire -> empirePerks.mkString(" ")
|
||||||
|
}.toMap
|
||||||
|
|
||||||
|
if (perks.values.forall(_.isEmpty)) {/*do nothing*/}
|
||||||
|
else {
|
||||||
|
val msg = PropertyOverrideMessage(List(PropertyOverrideMessage.GamePropertyScope(0, List(PropertyOverrideMessage.GamePropertyTarget(343,
|
||||||
|
List(PropertyOverrideMessage.GameProperty("purchase_exempt_vs", perks(PlanetSideEmpire.VS)),
|
||||||
|
PropertyOverrideMessage.GameProperty("purchase_exempt_tr", perks(PlanetSideEmpire.TR)),
|
||||||
|
PropertyOverrideMessage.GameProperty("purchase_exempt_nc", perks(PlanetSideEmpire.NC))))))))
|
||||||
|
PlayerControl.sendResponse(player.Zone, player.Name, msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -275,19 +275,27 @@ class HackCaptureActor extends Actor {
|
||||||
.collect { case p if p.Faction == hackedByFaction =>
|
.collect { case p if p.Faction == hackedByFaction =>
|
||||||
events ! LocalServiceMessage(p.Name, msg)
|
events ! LocalServiceMessage(p.Name, msg)
|
||||||
}
|
}
|
||||||
val zoneBases = building.Zone.Buildings.filter(base =>
|
val buildings = building.Zone.Buildings.values
|
||||||
base._2.BuildingType == StructureType.Facility)
|
val hackedBaseId = building.GUID
|
||||||
val ownedBases = building.Zone.Buildings.filter(base =>
|
val facilities = buildings.filter(_.BuildingType == StructureType.Facility).toSeq
|
||||||
base._2.BuildingType == StructureType.Facility && base._2.Faction == hackedByFaction
|
val ownedFacilities = facilities.filter(b =>
|
||||||
&& base._2.GUID != building.GUID)
|
b.Faction == hackedByFaction && b.GUID != hackedBaseId
|
||||||
val zoneTowers = building.Zone.Buildings.filter(tower =>
|
)
|
||||||
tower._2.BuildingType == StructureType.Tower && tower._2.Faction != hackedByFaction)
|
val towersToCapture = buildings.filter(b =>
|
||||||
// All major facilities in zone are now owned by the hacking faction. Capture all towers in the zone
|
b.BuildingType == StructureType.Tower && b.Faction != hackedByFaction
|
||||||
// Base that was just hacked is not counted (hence the size - 1) because it wasn't always in ownedBases (async?)
|
).toSeq
|
||||||
if (zoneBases.size - 1 == ownedBases.size && zoneTowers.nonEmpty)
|
if (ownedFacilities.size == facilities.size - 1) {
|
||||||
{
|
building.Zone.lockedBy = hackedByFaction
|
||||||
processBuildingsWithDelay(zoneTowers.values.toSeq, hackedByFaction, 1000)
|
building.Zone.benefitRecipient = hackedByFaction
|
||||||
|
building.Zone.NotifyContinentalLockBenefits(building.Zone, building)
|
||||||
|
if (towersToCapture.nonEmpty) {
|
||||||
|
processBuildingsWithDelay(towersToCapture, hackedByFaction, 1000)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (building.Zone.lockedBy != PlanetSideEmpire.NEUTRAL) {
|
||||||
|
building.Zone.lockedBy = PlanetSideEmpire.NEUTRAL
|
||||||
|
building.Zone.NotifyContinentalLockBenefits(building.Zone, building)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.info("Base hack completed, but base was out of NTU.")
|
log.info("Base hack completed, but base was out of NTU.")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue