mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
Hacking fixes (#253)
* Remove QoL change to show faction colours on hacked objects as unfortunately it causes side effects like doors opening for the hacker but saying the door is locked * Only send map updates if the resecured object is a capture terminal * Centralise logic to check if a Capture Terminal is hacked for a Building object * Fix hacking a terminal where the base CC has been hacked and add a bit of extra logging for possible edge cases * Clear all hacks from hacked amenities when the CC is resecured * Fix AMS terminals being broken * Clear amenity hacks when CC is both hacked and resecured
This commit is contained in:
parent
6c68bda97c
commit
473d4d14c5
|
|
@ -39,6 +39,14 @@ class Building(private val building_guid : Int, private val map_id : Int, privat
|
|||
amenities
|
||||
}
|
||||
|
||||
def CaptureConsoleIsHacked : Boolean = {
|
||||
Amenities.filter(x => x.Definition == GlobalDefinitions.capture_terminal).headOption.asInstanceOf[Option[CaptureTerminal]] match {
|
||||
case Some(obj: CaptureTerminal) =>
|
||||
obj.HackedBy.isDefined
|
||||
case None => false
|
||||
}
|
||||
}
|
||||
|
||||
def Zone : Zone = zone
|
||||
|
||||
def Info : (
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package services.local
|
|||
import akka.actor.{Actor, ActorRef, Props}
|
||||
import net.psforever.objects.ce.Deployable
|
||||
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
|
||||
import net.psforever.objects.serverobject.structures.Building
|
||||
import net.psforever.objects.serverobject.structures.{Amenity, Building}
|
||||
import net.psforever.objects.serverobject.terminals.{CaptureTerminal, ProximityUnit, Terminal}
|
||||
import net.psforever.objects.zones.{InterstellarCluster, Zone}
|
||||
import net.psforever.objects._
|
||||
|
|
@ -18,6 +18,7 @@ import services.{GenericEventBus, RemoverActor, Service, ServiceManager}
|
|||
import scala.util.Success
|
||||
import scala.concurrent.duration._
|
||||
import akka.pattern.ask
|
||||
import net.psforever.objects.serverobject.hackable.Hackable
|
||||
import net.psforever.objects.vehicles.{Utility, UtilityType}
|
||||
import services.ServiceManager.Lookup
|
||||
import services.support.SupportActor
|
||||
|
|
@ -95,6 +96,12 @@ class LocalService extends Actor {
|
|||
hackClearer ! HackClearActor.ObjectIsResecured(target)
|
||||
case LocalAction.HackCaptureTerminal(player_guid, zone, target, unk1, unk2, isResecured) =>
|
||||
|
||||
// When a CC is hacked (or resecured) all amenities for the base should be unhacked
|
||||
val hackableAmenities = target.Owner.asInstanceOf[Building].Amenities.filter(x => x.isInstanceOf[Hackable]).map(x => x.asInstanceOf[Amenity with Hackable])
|
||||
hackableAmenities.foreach(amenity =>
|
||||
if(amenity.HackedBy.isDefined) { hackClearer ! HackClearActor.ObjectIsResecured(amenity) }
|
||||
)
|
||||
|
||||
if(isResecured){
|
||||
hackCapturer ! HackCaptureActor.ClearHack(target, zone)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ class HackCaptureActor extends Actor {
|
|||
|
||||
case HackCaptureActor.ClearHack(target, _) =>
|
||||
hackedObjects = hackedObjects.filterNot(x => x.target == target)
|
||||
target.Owner.Actor ! Building.SendMapUpdate(all_clients = true)
|
||||
|
||||
if(target.isInstanceOf[CaptureTerminal]) { target.Owner.Actor ! Building.SendMapUpdate(all_clients = true) }
|
||||
|
||||
// Restart the timer in case the object we just removed was the next one scheduled
|
||||
RestartTimer()
|
||||
|
|
|
|||
|
|
@ -1253,24 +1253,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
log.trace(s"Clearing hack for ${target_guid}")
|
||||
// Reset hack state for all players
|
||||
sendResponse(HackMessage(0, target_guid, guid, 0, unk1, HackState.HackCleared, unk2))
|
||||
// Set the object faction displayed back to it's original owner faction
|
||||
|
||||
continent.GUID(target_guid) match {
|
||||
case Some(obj) =>
|
||||
sendResponse(SetEmpireMessage(target_guid, obj.asInstanceOf[FactionAffinity].Faction))
|
||||
case None => ;
|
||||
}
|
||||
|
||||
case LocalResponse.HackObject(target_guid, unk1, unk2) =>
|
||||
if(tplayer_guid != guid && continent.GUID(target_guid).get.asInstanceOf[Hackable].HackedBy.get.hackerFaction != player.Faction) {
|
||||
// If the player is not in the faction that hacked this object then send the packet that it's been hacked, so they can either unhack it or use the hacked object
|
||||
// Don't send this to the faction that hacked the object, otherwise it will interfere with the new SetEmpireMessage QoL change that changes the object colour to their faction (but only visible to that faction)
|
||||
sendResponse(HackMessage(0, target_guid, guid, 100, unk1, HackState.Hacked, unk2))
|
||||
}
|
||||
if(continent.GUID(target_guid).get.asInstanceOf[Hackable].HackedBy.get.hackerFaction == player.Faction) {
|
||||
// Make the hacked object look like it belongs to the hacking empire, but only for that empire's players (so that infiltrators on stealth missions won't be given away to opposing factions)
|
||||
sendResponse(SetEmpireMessage(target_guid, player.Faction))
|
||||
}
|
||||
case LocalResponse.HackCaptureTerminal(target_guid, unk1, unk2, isResecured) =>
|
||||
var value = 0L
|
||||
if(isResecured) {
|
||||
|
|
@ -3802,13 +3786,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case Some(lock_guid) =>
|
||||
val lock = continent.GUID(lock_guid).get.asInstanceOf[IFFLock]
|
||||
|
||||
var baseIsHacked = false
|
||||
lock.Owner.asInstanceOf[Building].Amenities.filter(x => x.Definition == GlobalDefinitions.capture_terminal).headOption.asInstanceOf[Option[CaptureTerminal]] match {
|
||||
case Some(obj: CaptureTerminal) =>
|
||||
baseIsHacked = obj.HackedBy.isDefined
|
||||
case None => ;
|
||||
}
|
||||
|
||||
val playerIsOnInside = Vector3.ScalarProjection(lock.Outwards, player.Position - door.Position) < 0f
|
||||
|
||||
// If an IFF lock exists and the IFF lock faction doesn't match the current player and one of the following conditions are met open the door:
|
||||
|
|
@ -3816,7 +3793,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
// A base is hacked
|
||||
// The lock is hacked
|
||||
// The player is on the inside of the door, determined by the lock orientation
|
||||
lock.HackedBy.isDefined || baseIsHacked || lock.Faction == PlanetSideEmpire.NEUTRAL || playerIsOnInside
|
||||
lock.HackedBy.isDefined || lock.Owner.asInstanceOf[Building].CaptureConsoleIsHacked || lock.Faction == PlanetSideEmpire.NEUTRAL || playerIsOnInside
|
||||
case None => !door.isOpen // If there's no linked IFF lock just open the door if it's closed.
|
||||
})) {
|
||||
door.Actor ! Door.Use(player, msg)
|
||||
|
|
@ -3861,6 +3838,10 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
}
|
||||
case _ => ;
|
||||
}
|
||||
} else {
|
||||
log.warn("IFF lock is being hacked, but don't know how to handle this state")
|
||||
log.warn(s"Lock - HackedBy.isDefined: ${panel.HackedBy.isDefined} Faction: ${panel.Faction} HackedBy.isEmpty: ${panel.HackedBy.isEmpty}")
|
||||
log.warn(s"Hacking player - Faction: ${player.Faction}")
|
||||
}
|
||||
|
||||
case Some(obj : Player) =>
|
||||
|
|
@ -4043,53 +4024,73 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
|
||||
case Some(terminal : Terminal) =>
|
||||
val tdef = terminal.Definition
|
||||
val owned = terminal.Faction == player.Faction
|
||||
val hacked = terminal.HackedBy.nonEmpty
|
||||
if(owned) {
|
||||
if(tdef.isInstanceOf[MatrixTerminalDefinition]) {
|
||||
//TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
|
||||
sendResponse(BindPlayerMessage(BindStatus.Bind, "", true, true, SpawnGroup.Sanctuary, 0, 0, terminal.Position))
|
||||
}
|
||||
else if(tdef == GlobalDefinitions.multivehicle_rearm_terminal || tdef == GlobalDefinitions.bfr_rearm_terminal ||
|
||||
tdef == GlobalDefinitions.air_rearm_terminal || tdef == GlobalDefinitions.ground_rearm_terminal) {
|
||||
FindLocalVehicle match {
|
||||
case Some(vehicle) =>
|
||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, vehicle.GUID, unk2, unk3, unk4, unk5, unk6, unk7, unk8, vehicle.Definition.ObjectId))
|
||||
case None =>
|
||||
log.error("UseItem: expected seated vehicle, but found none")
|
||||
}
|
||||
}
|
||||
else if(tdef == GlobalDefinitions.teleportpad_terminal) {
|
||||
//explicit request
|
||||
terminal.Actor ! Terminal.Request(
|
||||
player,
|
||||
ItemTransactionMessage(object_guid, TransactionType.Buy, 0, "router_telepad", 0, PlanetSideGUID(0))
|
||||
)
|
||||
}
|
||||
else {
|
||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||
}
|
||||
|
||||
// If the base this terminal belongs to has been hacked the owning faction needs to be able to hack it to gain access
|
||||
val ownerIsHacked = terminal.Owner match {
|
||||
case b: Building => b.CaptureConsoleIsHacked
|
||||
case _ => false
|
||||
}
|
||||
else if(hacked) {
|
||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||
}
|
||||
else {
|
||||
player.Slot(player.DrawnSlot).Equipment match {
|
||||
case Some(tool: SimpleItem) =>
|
||||
if (tool.Definition == GlobalDefinitions.remote_electronics_kit) {
|
||||
var playerIsHacking = false
|
||||
|
||||
player.Slot(player.DrawnSlot).Equipment match {
|
||||
case Some(tool: SimpleItem) =>
|
||||
if (tool.Definition == GlobalDefinitions.remote_electronics_kit) {
|
||||
if (!terminal.HackedBy.isEmpty) {
|
||||
log.warn("Player tried to hack a terminal that is already hacked")
|
||||
log.warn(s"Player faction ${player.Faction} terminal faction: ${terminal.Faction} terminal hacked: ${terminal.HackedBy.isDefined} owner hacked: ${ownerIsHacked}")
|
||||
}
|
||||
else if (terminal.Faction != player.Faction || ownerIsHacked) {
|
||||
val hackSpeed = GetPlayerHackSpeed(terminal)
|
||||
|
||||
if(hackSpeed > 0) {
|
||||
if (hackSpeed > 0) {
|
||||
progressBarValue = Some(-hackSpeed)
|
||||
self ! WorldSessionActor.HackingProgress(progressType = 1, player, terminal, tool.GUID, hackSpeed, FinishHacking(terminal, 3212836864L))
|
||||
playerIsHacking = true
|
||||
log.info("Hacking a terminal")
|
||||
}
|
||||
}
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
if(!playerIsHacking) {
|
||||
if (terminal.Faction == player.Faction) {
|
||||
if (tdef.isInstanceOf[MatrixTerminalDefinition]) {
|
||||
//TODO matrix spawn point; for now, just blindly bind to show work (and hope nothing breaks)
|
||||
sendResponse(BindPlayerMessage(BindStatus.Bind, "", true, true, SpawnGroup.Sanctuary, 0, 0, terminal.Position))
|
||||
}
|
||||
else if (tdef == GlobalDefinitions.multivehicle_rearm_terminal || tdef == GlobalDefinitions.bfr_rearm_terminal ||
|
||||
tdef == GlobalDefinitions.air_rearm_terminal || tdef == GlobalDefinitions.ground_rearm_terminal) {
|
||||
FindLocalVehicle match {
|
||||
case Some(vehicle) =>
|
||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, vehicle.GUID, unk2, unk3, unk4, unk5, unk6, unk7, unk8, vehicle.Definition.ObjectId))
|
||||
case None =>
|
||||
log.error("UseItem: expected seated vehicle, but found none")
|
||||
}
|
||||
}
|
||||
else if (tdef == GlobalDefinitions.teleportpad_terminal) {
|
||||
//explicit request
|
||||
terminal.Actor ! Terminal.Request(
|
||||
player,
|
||||
ItemTransactionMessage(object_guid, TransactionType.Buy, 0, "router_telepad", 0, PlanetSideGUID(0))
|
||||
)
|
||||
}
|
||||
else if (!ownerIsHacked || (ownerIsHacked && terminal.HackedBy.isDefined)) {
|
||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||
}
|
||||
else {
|
||||
log.warn("Tried to use a terminal, but can't handle this case")
|
||||
log.warn(s"Terminal - isHacked ${terminal.HackedBy.isDefined} ownerIsHacked ${ownerIsHacked}")
|
||||
}
|
||||
}
|
||||
else if (terminal.HackedBy.isDefined) {
|
||||
sendResponse(UseItemMessage(avatar_guid, item_used_guid, object_guid, unk2, unk3, unk4, unk5, unk6, unk7, unk8, itemType))
|
||||
} else {
|
||||
log.warn("Tried to use a terminal that doesn't belong to this faction and isn't hacked")
|
||||
log.warn(s"Player faction ${player.Faction} terminal faction: ${terminal.Faction} terminal hacked: ${terminal.HackedBy.isDefined} owner hacked: ${ownerIsHacked}")
|
||||
}
|
||||
}
|
||||
case Some(obj : SpawnTube) =>
|
||||
//deconstruction
|
||||
PlayerActionsToCancel()
|
||||
|
|
@ -5157,7 +5158,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
|
|||
case term : CaptureTerminal =>
|
||||
val isResecured = player.Faction == target.Faction
|
||||
localService ! LocalServiceMessage(continent.Id, LocalAction.HackCaptureTerminal(player.GUID, continent, term, unk, 8L, isResecured))
|
||||
case _ =>localService ! LocalServiceMessage(continent.Id, LocalAction.HackTemporarily(player.GUID, continent, target, unk, target.HackEffectDuration(GetPlayerHackLevel())))
|
||||
case _ => localService ! LocalServiceMessage(continent.Id, LocalAction.HackTemporarily(player.GUID, continent, target, unk, target.HackEffectDuration(GetPlayerHackLevel())))
|
||||
}
|
||||
case scala.util.Failure(_) => log.warn(s"Hack message failed on target guid: ${target.GUID}")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue