incorporating structural changes to hacking for future expansion

This commit is contained in:
Fate-JH 2024-07-26 10:02:22 -04:00
parent e5cde75e72
commit c6b3403e4d
5 changed files with 118 additions and 102 deletions

View file

@ -10,7 +10,8 @@ object CommonMessages {
final case class Unuse(player: Player, data: Option[Any] = None)
final case class Hack(player: Player, obj: PlanetSideServerObject with Hackable, data: Option[Any] = None)
final case class ClearHack()
final case class EntityHackState(obj: PlanetSideGameObject with Hackable, hackState: Boolean)
/**
* The message that progresses some form of user-driven activity with a certain eventual outcome
* and potential feedback per cycle.

View file

@ -31,12 +31,12 @@ object GenericHackables {
turretUpgradeTime
}
/**
* na
*
* @param player the player doing the hacking
* @param obj the object being hacked
* @return the percentage amount of progress per tick
*/
* na
*
* @param player the player doing the hacking
* @param obj the object being hacked
* @return the percentage amount of progress per tick
*/
def GetHackSpeed(player: Player, obj: PlanetSideServerObject): Float = {
val playerHackLevel = player.avatar.hackingSkillLevel()
val timeToHack = obj match {
@ -60,23 +60,23 @@ object GenericHackables {
}
/**
* Evaluate the progress of the user applying a tool to modify some server object.
* This action is using the remote electronics kit to convert an enemy unit into an allied unit, primarily.
* The act of transforming allied units of one kind into allied units of another kind (facility turret upgrades)
* is also governed by this action per tick of progress.
* @see `HackMessage`
* @see `HackState`
* @param progressType 1 - remote electronics kit hack (various ...);
* 2 - nano dispenser (upgrade canister) turret upgrade
* @param tplayer the player performing the action
* @param target the object being affected
* @param tool_guid the tool being used to affest the object
* @param progress the current progress value
* @return `true`, if the next cycle of progress should occur;
* `false`, otherwise
*/
* Evaluate the progress of the user applying a tool to modify some server object.
* This action is using the remote electronics kit to convert an enemy unit into an allied unit, primarily.
* The act of transforming allied units of one kind into allied units of another kind (facility turret upgrades)
* is also governed by this action per tick of progress.
* @see `HackMessage`
* @see `HackState`
* @param progressType 1 - remote electronics kit hack (various ...);
* 2 - nano dispenser (upgrade canister) turret upgrade
* @param tplayer the player performing the action
* @param target the object being affected
* @param tool_guid the tool being used to affest the object
* @param progress the current progress value
* @return `true`, if the next cycle of progress should occur;
* `false`, otherwise
*/
def HackingTickAction(progressType: Int, tplayer: Player, target: PlanetSideServerObject, tool_guid: PlanetSideGUID)(
progress: Float
progress: Float
): Boolean = {
//hack state for progress bar visibility
val vis = if (progress <= 0L) {
@ -108,37 +108,40 @@ object GenericHackables {
}
/**
* The process of hacking an object is completed.
* Pass the message onto the hackable object and onto the local events system.
* @param target the `Hackable` object that has been hacked
* @param user the player that is performing this hacking task
* @param unk na;
* used by `HackMessage` as `unk5`
* @see `HackMessage`
*/
* The process of hacking an object is completed.
* Pass the message onto the hackable object and onto the local events system.
* @param target the `Hackable` object that has been hacked
* @param user the player that is performing this hacking task
* @param unk na;
* used by `HackMessage` as `unk5`
* @see `HackMessage`
*/
//TODO add params here depending on which params in HackMessage are important
def FinishHacking(target: PlanetSideServerObject with Hackable, user: Player, unk: Long)(): Unit = {
import akka.pattern.ask
import scala.concurrent.duration._
log.info(s"${user.Name} hacked a ${target.Definition.Name}")
// Wait for the target actor to set the HackedBy property, otherwise LocalAction.HackTemporarily will not complete properly
import scala.concurrent.ExecutionContext.Implicits.global
val tplayer = user
ask(target.Actor, CommonMessages.Hack(tplayer, target))(1 second).mapTo[Boolean].onComplete {
case Success(_) =>
val zone = target.Zone
val zoneId = zone.id
val pguid = tplayer.GUID
zone.LocalEvents ! LocalServiceMessage(
zoneId,
LocalAction.TriggerSound(pguid, target.HackSound, tplayer.Position, 30, 0.49803925f)
)
zone.LocalEvents ! LocalServiceMessage(
zoneId,
LocalAction
.HackTemporarily(pguid, zone, target, unk, target.HackEffectDuration(user.avatar.hackingSkillLevel()))
)
case Failure(_) => log.warn(s"Hack message failed on target guid: ${target.GUID}")
}
ask(target.Actor, CommonMessages.Hack(tplayer, target))(timeout = 2 second)
.mapTo[CommonMessages.EntityHackState]
.onComplete {
case Success(_) =>
val zone = target.Zone
val zoneId = zone.id
val pguid = tplayer.GUID
log.info(s"${user.Name} hacked a ${target.Definition.Name}")
zone.LocalEvents ! LocalServiceMessage(
zoneId,
LocalAction.TriggerSound(pguid, target.HackSound, tplayer.Position, 30, 0.49803925f)
)
zone.LocalEvents ! LocalServiceMessage(
zoneId,
LocalAction
.HackTemporarily(pguid, zone, target, unk, target.HackEffectDuration(user.avatar.hackingSkillLevel()))
)
case Failure(_) =>
log.warn(s"Hack message failed on target: ${target.Definition.Name}@${target.GUID.guid}")
}
}
}

View file

@ -1,32 +1,44 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.hackable
import akka.actor.Actor
import akka.actor.{Actor, ActorRef}
import net.psforever.objects.{PlanetSideGameObject, Player}
import net.psforever.objects.serverobject.CommonMessages
import scala.annotation.unused
object HackableBehavior {
/**
* The logic governing generic `Hackable` objects that use the `Hack` and `ClearHack` message.
* This is a mix-in trait for combining with existing `Receive` logic.
* @see `Hackable`
*/
* The logic governing generic `Hackable` objects that use the `Hack` and `ClearHack` message.
* This is a mix-in trait for combining with existing `Receive` logic.
* @see `Hackable`
*/
trait GenericHackable {
this: Actor =>
def HackableObject: Hackable
def HackableObject: PlanetSideGameObject with Hackable
val clearHackBehavior: Receive = {
case CommonMessages.ClearHack() =>
val obj = HackableObject
obj.HackedBy = None
performClearHack(None, sender())
}
val hackableBehavior: Receive = clearHackBehavior
.orElse {
case CommonMessages.Hack(player, _, _) =>
val obj = HackableObject
obj.HackedBy = player
sender() ! true
performHack(player, None, sender())
}
def performHack(player: Player, @unused data: Option[Any], replyTo: ActorRef): Unit = {
val obj = HackableObject
obj.HackedBy = player
replyTo ! CommonMessages.EntityHackState(obj, hackState = true)
}
def performClearHack(@unused data: Option[Any], replyTo: ActorRef): Unit = {
val obj = HackableObject
obj.HackedBy = None
replyTo ! CommonMessages.EntityHackState(obj, hackState = false)
}
}
}

View file

@ -4,12 +4,12 @@ package net.psforever.objects.serverobject.terminals
import akka.actor.ActorRef
import net.psforever.objects.{GlobalDefinitions, SimpleItem}
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
import net.psforever.objects.serverobject.damage.Damageable.Target
import net.psforever.objects.serverobject.damage.{Damageable, DamageableAmenity}
import net.psforever.objects.serverobject.hackable.{GenericHackables, Hackable, HackableBehavior}
import net.psforever.objects.serverobject.hackable.{GenericHackables, HackableBehavior}
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, RepairableAmenity}
import net.psforever.objects.serverobject.structures.{Amenity, Building, PoweredAmenityControl}
import net.psforever.objects.serverobject.structures.{Building, PoweredAmenityControl}
import net.psforever.objects.vital.interaction.DamageResult
import net.psforever.services.Service
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
@ -19,24 +19,24 @@ import net.psforever.services.local.{LocalAction, LocalServiceMessage}
* @param term the `Terminal` object being governed
*/
class TerminalControl(term: Terminal)
extends PoweredAmenityControl
extends PoweredAmenityControl
with FactionAffinityBehavior.Check
with HackableBehavior.GenericHackable
with DamageableAmenity
with RepairableAmenity
with AmenityAutoRepair {
def FactionObject: FactionAffinity = term
def HackableObject: Hackable = term
def DamageableObject: Amenity = term
def RepairableObject: Amenity = term
def AutoRepairObject: Amenity = term
def FactionObject: Terminal = term
def HackableObject: Terminal = term
def DamageableObject: Terminal = term
def RepairableObject: Terminal = term
def AutoRepairObject: Terminal = term
val commonBehavior: Receive = checkBehavior
.orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser)
.orElse(autoRepairBehavior)
def poweredStateLogic : Receive =
def poweredStateLogic: Receive =
commonBehavior
.orElse(hackableBehavior)
.orElse {

View file

@ -1,6 +1,5 @@
package net.psforever.objects.serverobject.terminals.capture
import akka.util.Timeout
import net.psforever.objects.Player
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.sourcing.PlayerSource
@ -10,17 +9,16 @@ import scala.util.{Failure, Success}
object CaptureTerminals {import scala.concurrent.duration._
private val log = org.log4s.getLogger("CaptureTerminals")
private implicit val timeout: Timeout = 1.second
/**
* The process of hacking an object is completed.
* Pass the message onto the hackable object and onto the local events system.
* @param target the `Hackable` object that has been hacked
* @param hackingPlayer The player that hacked the control console
* @param unk na;
* used by `HackMessage` as `unk5`
* @see `HackMessage`
*/
* The process of hacking an object is completed.
* Pass the message onto the hackable object and onto the local events system.
* @param target the `Hackable` object that has been hacked
* @param hackingPlayer The player that hacked the control console
* @param unk na;
* used by `HackMessage` as `unk5`
* @see `HackMessage`
*/
//TODO add params here depending on which params in HackMessage are important
def FinishHackingCaptureConsole(target: CaptureTerminal, hackingPlayer: Player, unk: Long)(): Unit = {
import akka.pattern.ask
@ -28,31 +26,33 @@ object CaptureTerminals {import scala.concurrent.duration._
log.info(s"${hackingPlayer.toString} hacked a ${target.Definition.Name}")
// Wait for the target actor to set the HackedBy property
import scala.concurrent.ExecutionContext.Implicits.global
ask(target.Actor, CommonMessages.Hack(hackingPlayer, target)).mapTo[Boolean].onComplete {
case Success(_) =>
val zone = target.Zone
val zoneid = zone.id
val events = zone.LocalEvents
val isResecured = hackingPlayer.Faction == target.Faction
events ! LocalServiceMessage(
zoneid,
LocalAction.TriggerSound(hackingPlayer.GUID, target.HackSound, hackingPlayer.Position, 30, 0.49803925f)
)
if (isResecured) {
// Resecure the CC
ask(target.Actor, CommonMessages.Hack(hackingPlayer, target))(timeout = 2 second)
.mapTo[CommonMessages.EntityHackState]
.onComplete {
case Success(_) =>
val zone = target.Zone
val zoneid = zone.id
val events = zone.LocalEvents
val isResecured = hackingPlayer.Faction == target.Faction
events ! LocalServiceMessage(
zoneid,
LocalAction.ResecureCaptureTerminal(target, PlayerSource(hackingPlayer))
LocalAction.TriggerSound(hackingPlayer.GUID, target.HackSound, hackingPlayer.Position, 30, 0.49803925f)
)
} else {
// Start the CC hack timer
events ! LocalServiceMessage(
zoneid,
LocalAction.StartCaptureTerminalHack(target)
)
}
case Failure(_) =>
log.warn(s"Hack message failed on target guid: ${target.GUID}")
}
if (isResecured) {
// Resecure the CC
events ! LocalServiceMessage(
zoneid,
LocalAction.ResecureCaptureTerminal(target, PlayerSource(hackingPlayer))
)
} else {
// Start the CC hack timer
events ! LocalServiceMessage(
zoneid,
LocalAction.StartCaptureTerminalHack(target)
)
}
case Failure(_) =>
log.warn(s"Hack message failed on target guid: ${target.GUID}")
}
}
}