mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-13 15:34:42 +00:00
commit
cead0e21c8
4 changed files with 111 additions and 65 deletions
|
|
@ -11,7 +11,19 @@ import net.psforever.types.Vector3
|
||||||
* It is used as a position reference for spawning the LLU in the correct location when the base is hacked
|
* It is used as a position reference for spawning the LLU in the correct location when the base is hacked
|
||||||
* @param tDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
* @param tDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
|
||||||
*/
|
*/
|
||||||
class CaptureFlagSocket(tDef: CaptureFlagSocketDefinition) extends Amenity {
|
class CaptureFlagSocket(tDef: CaptureFlagSocketDefinition)
|
||||||
|
extends Amenity {
|
||||||
|
private var spawnedCaptureFlag: Option[CaptureFlag] = None
|
||||||
|
|
||||||
|
def captureFlag: Option[CaptureFlag] = spawnedCaptureFlag
|
||||||
|
|
||||||
|
def captureFlag_=(flag: CaptureFlag): Option[CaptureFlag] = captureFlag_=(Some(flag))
|
||||||
|
|
||||||
|
def captureFlag_=(flag: Option[CaptureFlag]): Option[CaptureFlag] = {
|
||||||
|
spawnedCaptureFlag = flag
|
||||||
|
captureFlag
|
||||||
|
}
|
||||||
|
|
||||||
def Definition : CaptureFlagSocketDefinition = tDef
|
def Definition : CaptureFlagSocketDefinition = tDef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,12 @@ class Building(
|
||||||
}
|
}
|
||||||
|
|
||||||
def GetFlagSocket: Option[CaptureFlagSocket] = this.Amenities.find(_.Definition == GlobalDefinitions.llm_socket).asInstanceOf[Option[CaptureFlagSocket]]
|
def GetFlagSocket: Option[CaptureFlagSocket] = this.Amenities.find(_.Definition == GlobalDefinitions.llm_socket).asInstanceOf[Option[CaptureFlagSocket]]
|
||||||
def GetFlag: Option[CaptureFlag] = this.Amenities.find(_.Definition == GlobalDefinitions.capture_flag).asInstanceOf[Option[CaptureFlag]]
|
def GetFlag: Option[CaptureFlag] = {
|
||||||
|
GetFlagSocket match {
|
||||||
|
case Some(socket) => socket.captureFlag
|
||||||
|
case None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def HackableAmenities: List[Amenity with Hackable] = {
|
def HackableAmenities: List[Amenity with Hackable] = {
|
||||||
Amenities.filter(x => x.isInstanceOf[Hackable]).map(x => x.asInstanceOf[Amenity with Hackable])
|
Amenities.filter(x => x.isInstanceOf[Hackable]).map(x => x.asInstanceOf[Amenity with Hackable])
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ class CaptureFlagManager(val taskResolver: ActorRef, zone: Zone) extends Actor{
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add the flag as an amenity and track it internally
|
// Add the flag as an amenity and track it internally
|
||||||
|
socket.captureFlag = flag
|
||||||
TrackFlag(flag)
|
TrackFlag(flag)
|
||||||
|
|
||||||
taskResolver ! CallBackForTask(
|
taskResolver ! CallBackForTask(
|
||||||
|
|
@ -128,15 +129,19 @@ class CaptureFlagManager(val taskResolver: ActorRef, zone: Zone) extends Actor{
|
||||||
HandleFlagDespawn(flag)
|
HandleFlagDespawn(flag)
|
||||||
|
|
||||||
case CaptureFlagManager.Lost(flag: CaptureFlag, reason: CaptureFlagLostReasonEnum) =>
|
case CaptureFlagManager.Lost(flag: CaptureFlag, reason: CaptureFlagLostReasonEnum) =>
|
||||||
val message = reason match {
|
reason match {
|
||||||
case CaptureFlagLostReasonEnum.Resecured =>
|
case CaptureFlagLostReasonEnum.Resecured =>
|
||||||
CaptureFlagChatMessageStrings.CTF_Failed_SourceResecured(flag.Owner.asInstanceOf[Building])
|
ChatBroadcast(
|
||||||
case CaptureFlagLostReasonEnum.TimedOut =>
|
flag.Zone,
|
||||||
CaptureFlagChatMessageStrings.CTF_Failed_TimedOut(flag.Owner.asInstanceOf[Building].Name, flag.Target)
|
CaptureFlagChatMessageStrings.CTF_Failed_SourceResecured(flag.Owner.asInstanceOf[Building])
|
||||||
|
)
|
||||||
|
case CaptureFlagLostReasonEnum.TimedOut =>
|
||||||
|
ChatBroadcast(
|
||||||
|
flag.Zone,
|
||||||
|
CaptureFlagChatMessageStrings.CTF_Failed_TimedOut(flag.Owner.asInstanceOf[Building].Name, flag.Target)
|
||||||
|
)
|
||||||
|
case CaptureFlagLostReasonEnum.Ended => ; /* no message */
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatBroadcast(flag.Zone, message)
|
|
||||||
|
|
||||||
HandleFlagDespawn(flag)
|
HandleFlagDespawn(flag)
|
||||||
|
|
||||||
case CaptureFlagManager.PickupFlag(flag: CaptureFlag, player: Player) =>
|
case CaptureFlagManager.PickupFlag(flag: CaptureFlag, player: Player) =>
|
||||||
|
|
@ -173,14 +178,13 @@ class CaptureFlagManager(val taskResolver: ActorRef, zone: Zone) extends Actor{
|
||||||
}
|
}
|
||||||
|
|
||||||
private def HandleFlagDespawn(flag: CaptureFlag): Unit = {
|
private def HandleFlagDespawn(flag: CaptureFlag): Unit = {
|
||||||
|
// Remove the flag as an amenity
|
||||||
|
flag.Owner.asInstanceOf[Building].GetFlagSocket.get.captureFlag = None
|
||||||
|
UntrackFlag(flag)
|
||||||
// Unregister LLU from clients,
|
// Unregister LLU from clients,
|
||||||
flag.Zone.LocalEvents ! LocalServiceMessage(flag.Zone.id, LocalAction.LluDespawned(PlanetSideGUID(-1), flag))
|
flag.Zone.LocalEvents ! LocalServiceMessage(flag.Zone.id, LocalAction.LluDespawned(PlanetSideGUID(-1), flag))
|
||||||
|
|
||||||
// Then unregister it from the GUID pool
|
// Then unregister it from the GUID pool
|
||||||
taskResolver ! TaskResolver.GiveTask(GUIDTask.UnregisterObjectTask(flag)(flag.Zone.GUID).task)
|
taskResolver ! TaskResolver.GiveTask(GUIDTask.UnregisterObjectTask(flag)(flag.Zone.GUID).task)
|
||||||
|
|
||||||
// Remove the flag as an amenity
|
|
||||||
UntrackFlag(flag)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def ChatBroadcast(zone: Zone, message: String, fanfare: Boolean = true): Unit = {
|
private def ChatBroadcast(zone: Zone, message: String, fanfare: Boolean = true): Unit = {
|
||||||
|
|
@ -271,6 +275,7 @@ object CaptureFlagChatMessageStrings {
|
||||||
case PlanetSideEmpire.TR => "TerranRepublic"
|
case PlanetSideEmpire.TR => "TerranRepublic"
|
||||||
case PlanetSideEmpire.NC => "NewConglomerate"
|
case PlanetSideEmpire.NC => "NewConglomerate"
|
||||||
case PlanetSideEmpire.VS => "VanuSovereigncy" // Yes, this is wrong. It is like that in packet captures.
|
case PlanetSideEmpire.VS => "VanuSovereigncy" // Yes, this is wrong. It is like that in packet captures.
|
||||||
|
case _ => "TerranRepublic" //todo: BO message?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -278,5 +283,5 @@ object CaptureFlagChatMessageStrings {
|
||||||
object CaptureFlagLostReasonEnum extends Enumeration {
|
object CaptureFlagLostReasonEnum extends Enumeration {
|
||||||
type CaptureFlagLostReasonEnum = Value
|
type CaptureFlagLostReasonEnum = Value
|
||||||
|
|
||||||
val Resecured, TimedOut = Value
|
val Resecured, TimedOut, Ended = Value
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,42 +31,36 @@ class HackCaptureActor(val taskResolver: ActorRef) extends Actor {
|
||||||
def receive: Receive = {
|
def receive: Receive = {
|
||||||
case HackCaptureActor.StartCaptureTerminalHack(target, zone, unk1, unk2, startTime) =>
|
case HackCaptureActor.StartCaptureTerminalHack(target, zone, unk1, unk2, startTime) =>
|
||||||
log.trace(s"StartCaptureTerminalHack: ${target.GUID} is hacked.")
|
log.trace(s"StartCaptureTerminalHack: ${target.GUID} is hacked.")
|
||||||
|
val duration = target.Definition match {
|
||||||
val duration = target.Definition match {
|
case GlobalDefinitions.capture_terminal =>
|
||||||
case GlobalDefinitions.capture_terminal =>
|
// Base CC
|
||||||
// Base CC
|
15 minutes
|
||||||
15 minutes
|
case GlobalDefinitions.secondary_capture =>
|
||||||
case GlobalDefinitions.secondary_capture =>
|
// Tower CC
|
||||||
// Tower CC
|
1 nanosecond
|
||||||
1 nanosecond
|
case GlobalDefinitions.vanu_control_console =>
|
||||||
case GlobalDefinitions.vanu_control_console =>
|
// Cavern CC
|
||||||
// Cavern CC
|
10 minutes
|
||||||
10 minutes
|
}
|
||||||
}
|
target.HackedBy match {
|
||||||
|
case Some(hackInfo) =>
|
||||||
target.HackedBy match {
|
target.HackedBy = hackInfo.Duration(duration.toNanos)
|
||||||
case Some(hackInfo) =>
|
case None =>
|
||||||
target.HackedBy = hackInfo.Duration(duration.toNanos)
|
log.error(s"Initial $target hack information is missing")
|
||||||
case None =>
|
}
|
||||||
log.error(s"Initial $target hack information is missing")
|
hackedObjects.find(_.target == target) match {
|
||||||
}
|
case Some(_) =>
|
||||||
|
log.trace(
|
||||||
hackedObjects.find(_.target == target) match {
|
s"StartCaptureTerminalHack: ${target.GUID} was already hacked - removing it from the hacked objects list before re-adding it."
|
||||||
case Some(_) =>
|
)
|
||||||
log.trace(
|
hackedObjects = hackedObjects.filterNot(x => x.target == target)
|
||||||
s"StartCaptureTerminalHack: ${target.GUID} was already hacked - removing it from the hacked objects list before re-adding it."
|
case _ => ;
|
||||||
)
|
}
|
||||||
hackedObjects = hackedObjects.filterNot(x => x.target == target)
|
hackedObjects = hackedObjects :+ HackCaptureActor.HackEntry(target, zone, unk1, unk2, duration, startTime)
|
||||||
case _ => ;
|
// Restart the timer, in case this is the first object in the hacked objects list or the object was removed and re-added
|
||||||
}
|
RestartTimer()
|
||||||
|
NotifyHackStateChange(target, isResecured = false)
|
||||||
hackedObjects = hackedObjects :+ HackCaptureActor.HackEntry(target, zone, unk1, unk2, duration, startTime)
|
TrySpawnCaptureFlag(target)
|
||||||
|
|
||||||
// Restart the timer, in case this is the first object in the hacked objects list or the object was removed and re-added
|
|
||||||
RestartTimer()
|
|
||||||
|
|
||||||
NotifyHackStateChange(target, isResecured = false)
|
|
||||||
TrySpawnCaptureFlag(target)
|
|
||||||
|
|
||||||
case HackCaptureActor.ProcessCompleteHacks() =>
|
case HackCaptureActor.ProcessCompleteHacks() =>
|
||||||
log.trace("Processing complete hacks")
|
log.trace("Processing complete hacks")
|
||||||
|
|
@ -134,27 +128,57 @@ class HackCaptureActor(val taskResolver: ActorRef) extends Actor {
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
private def TrySpawnCaptureFlag(terminal: CaptureTerminal): Unit = {
|
private def TrySpawnCaptureFlag(terminal: CaptureTerminal): Boolean = {
|
||||||
// Handle LLUs if the base contains a LLU socket
|
// Handle LLUs if the base contains a LLU socket
|
||||||
// If there are no neighbouring bases belonging to the hacking faction this will be handled as a regular timed hack (e.g. neutral base in enemy territory)
|
// If there are no neighbouring bases belonging to the hacking faction this will be handled as a regular timed hack (e.g. neutral base in enemy territory)
|
||||||
val owner = terminal.Owner.asInstanceOf[Building]
|
terminal.Owner match {
|
||||||
val hackingFaction = HackCaptureActor.GetHackingFaction(terminal).get
|
case owner: Building if owner.IsCtfBase =>
|
||||||
val hackingFactionNeighbourBases = owner.Neighbours(hackingFaction)
|
val socket = owner.GetFlagSocket.get
|
||||||
|
val flag = socket.captureFlag
|
||||||
hackingFactionNeighbourBases match {
|
val owningFaction = owner.Faction
|
||||||
case Some(neighbours) =>
|
val hackingFaction = HackCaptureActor.GetHackingFaction(terminal).get
|
||||||
if(owner.IsCtfBase) {
|
owner.Neighbours(hackingFaction) match {
|
||||||
// Find a random neighbouring base matching the hacking faction
|
case Some(neighbours) =>
|
||||||
val targetBase = neighbours.toVector((new Random).nextInt(neighbours.size))
|
if (flag.isEmpty) {
|
||||||
|
log.info(s"An LLU is being spawned for facility ${owner.Name} by $hackingFaction")
|
||||||
// Request LLU is created by CaptureFlagActor via LocalService
|
spawnCaptureFlag(neighbours, terminal, hackingFaction)
|
||||||
terminal.Zone.LocalEvents ! CaptureFlagManager.SpawnCaptureFlag(terminal, targetBase, hackingFaction)
|
true
|
||||||
|
} else if (hackingFaction != flag.get.Faction) {
|
||||||
|
log.info(s"$hackingFaction is overriding the ongoing LLU hack of facility ${owner.Name} by ${flag.get.Faction}")
|
||||||
|
terminal.Zone.LocalEvents ! CaptureFlagManager.Lost(flag.get, CaptureFlagLostReasonEnum.Ended)
|
||||||
|
NotifyHackStateChange(terminal, isResecured = false)
|
||||||
|
RestartTimer()
|
||||||
|
spawnCaptureFlag(neighbours, terminal, hackingFaction)
|
||||||
|
true
|
||||||
|
} else if (hackingFaction == owningFaction) {
|
||||||
|
log.error(s"Owning faction and hacking faction match for facility ${owner.Name}; should we be resecuring instead?")
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
log.warn(s"LLU hack of facility ${owner.Name} by $hackingFaction in progress - no change")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
case None => ;
|
||||||
|
log.info(s"Couldn't find any neighbouring $hackingFaction facilities of ${owner.Name} for LLU hack")
|
||||||
|
false
|
||||||
}
|
}
|
||||||
case None =>
|
|
||||||
log.info("Couldn't find any neighbouring bases for LLU hack.")
|
case thing =>
|
||||||
|
log.error(s"Capture terminal has unexpected owner - $thing - that is not a facility")
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def spawnCaptureFlag(
|
||||||
|
neighbours: Set[Building],
|
||||||
|
terminal: CaptureTerminal,
|
||||||
|
hackingFaction: PlanetSideEmpire.Value
|
||||||
|
): Unit = {
|
||||||
|
// Find a random neighbouring base matching the hacking faction
|
||||||
|
val targetBase = neighbours.toVector((new Random).nextInt(neighbours.size))
|
||||||
|
// Request LLU is created by CaptureFlagActor via LocalService
|
||||||
|
terminal.Zone.LocalEvents ! CaptureFlagManager.SpawnCaptureFlag(terminal, targetBase, hackingFaction)
|
||||||
|
}
|
||||||
|
|
||||||
private def NotifyHackStateChange(terminal: CaptureTerminal, isResecured: Boolean): Unit = {
|
private def NotifyHackStateChange(terminal: CaptureTerminal, isResecured: Boolean): Unit = {
|
||||||
val attribute_value = HackCaptureActor.GetHackUpdateAttributeValue(terminal, isResecured)
|
val attribute_value = HackCaptureActor.GetHackUpdateAttributeValue(terminal, isResecured)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue