vehicle pad deconstruction complete message; message when nc max shield deactivates when out of capacitor power or when max opens fire; message when ams can not deploy because it is blocked by other entities; message when facility capture requires ntu

This commit is contained in:
Fate-JH 2024-08-25 15:51:43 -04:00
parent d67e09bcbd
commit 9f4452a36a
6 changed files with 143 additions and 28 deletions

View file

@ -120,11 +120,8 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
ops.fallHeightTracker(pos.z)
if (isCrouching && !player.Crouching) {
//dev stuff goes here
sendResponse(ChatMsg(ChatMessageType.UNK_228, "@login_reposition_to_sanctuary"))
sendResponse(ChatMsg(ChatMessageType.UNK_229, "@PadDeconstruct_Done"))
//sendResponse(ChatMsg(ChatMessageType.UNK_227, "@NoMount_Permission"))
//sendResponse(ChatMsg(ChatMessageType.UNK_227, "@ArmorShieldOff"))
//sendResponse(ChatMsg(ChatMessageType.UNK_227, "@ArmorShieldOverride"))
//sendResponse(ChatMsg(ChatMessageType.UNK_227, "@fav_light_infantry")) //Light Infantry / Vehicle Driver
//sendResponse(ChatMsg(ChatMessageType.UNK_227, "@fav_heavy_infantry")) //Heavy Infantry
}
player.Position = pos
player.Velocity = vel
@ -1455,6 +1452,10 @@ class GeneralLogic(val ops: GeneralOperations, implicit val context: ActorContex
val drainAmount = player.ExoSuitDef.CapacitorDrainPerSecond.toFloat * timeDiff
player.Capacitor -= drainAmount
sendResponse(PlanetsideAttributeMessage(player.GUID, 7, player.Capacitor.toInt))
if (player.Capacitor <= 0 && player.UsingSpecial == SpecialExoSuitDefinition.Mode.Shielded) {
ops.toggleMaxSpecialState(enable = false)
sendResponse(ChatMsg(ChatMessageType.UNK_227, "@ArmorShieldOff"))
}
} else if (player.Capacitor < player.ExoSuitDef.MaxCapacitor) {
if (player.Faction != PlanetSideEmpire.VS) {
ops.toggleMaxSpecialState(enable = false)

View file

@ -2,9 +2,11 @@
package net.psforever.actors.session.support
import akka.actor.{ActorContext, typed}
import net.psforever.objects.definition.SpecialExoSuitDefinition
import net.psforever.objects.zones.Zoning
import net.psforever.objects.serverobject.turret.VanuSentry
import net.psforever.objects.zones.exp.ToDatabase
import net.psforever.types.ChatMessageType
import scala.collection.mutable
import scala.concurrent.duration._
@ -83,9 +85,10 @@ class WeaponAndProjectileOperations(
if (player.ZoningRequest != Zoning.Method.None) {
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_fire")
}
if (player.isShielded) {
if (player.UsingSpecial == SpecialExoSuitDefinition.Mode.Shielded) {
// Cancel NC MAX shield if it's active
sessionLogic.general.toggleMaxSpecialState(enable = false)
sendResponse(ChatMsg(ChatMessageType.UNK_227, "@ArmorShieldOverride"))
}
val (o, tools) = FindContainedWeapon
val (_, enabledTools) = FindEnabledWeaponsToHandleWeaponFireAccountability(o, tools)

View file

@ -349,6 +349,10 @@ class VehicleSpawnControl(pad: VehicleSpawnPad)
)
} else if (reminderSeq.size == 1) {
//end reminder
standaloneBlockedReminder(
VehicleSpawnPad.VehicleOrder(entry.driver, entry.vehicle, null),
Some("@PadDeconstruct_Done")
)
periodicReminder.cancel()
periodicReminder = Default.Cancellable
reminderSeq = List()
@ -374,7 +378,10 @@ class VehicleSpawnControl(pad: VehicleSpawnPad)
* @param blockedOrder the previous order whose vehicle is blocking the spawn pad from operating
* @param recipients all of the other customers who will be receiving the message
*/
private def BlockedReminder(blockedOrder: VehicleSpawnControl.Order, recipients: Seq[VehicleSpawnPad.VehicleOrder]): Unit = {
private def BlockedReminder(
blockedOrder: VehicleSpawnControl.Order,
recipients: Seq[VehicleSpawnPad.VehicleOrder]
): Unit = {
//everyone else
recursiveBlockedReminder(
recipients.iterator,
@ -389,12 +396,8 @@ class VehicleSpawnControl(pad: VehicleSpawnPad)
.orElse(pad.Zone.GUID(blockedOrder.vehicle.OwnerGuid))
.orElse(pad.Zone.GUID(blockedOrder.DriverGUID)) collect {
case p: Player if p.isAlive =>
recursiveBlockedReminder(
Seq(VehicleSpawnPad.VehicleOrder(
blockedOrder.driver,
blockedOrder.vehicle,
null //permissible
)).iterator,
standaloneBlockedReminder(
VehicleSpawnPad.VehicleOrder(blockedOrder.driver, blockedOrder.vehicle, null),
Some(s"@PadDeconstruct_secsA^${reminderSeq.head}~")
)
}
@ -432,16 +435,22 @@ class VehicleSpawnControl(pad: VehicleSpawnPad)
cause: Option[Any]
): Unit = {
if (iter.hasNext) {
val recipient = iter.next()
pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(
recipient.player.Name,
VehicleSpawnPad.Reminders.Blocked,
cause
)
standaloneBlockedReminder(iter.next(), cause)
recursiveBlockedReminder(iter, cause)
}
}
private def standaloneBlockedReminder(
entry: VehicleSpawnPad.VehicleOrder,
cause: Option[Any]
): Unit = {
pad.Zone.VehicleEvents ! VehicleSpawnPad.PeriodicReminder(
entry.player.Name,
VehicleSpawnPad.Reminders.Blocked,
cause
)
}
@tailrec private final def recursiveOrderReminder(
iter: Iterator[VehicleSpawnPad.VehicleOrder],
size: Int,

View file

@ -5,12 +5,16 @@ import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.sourcing.{PlayerSource, UniquePlayer}
import net.psforever.objects.zones.{HotSpotInfo, ZoneHotSpotProjector}
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import net.psforever.types.{PlanetSideEmpire, Vector3}
import net.psforever.types.{ChatMessageType, PlanetSideEmpire, Vector3}
import net.psforever.util.Config
import akka.pattern.ask
import akka.util.Timeout
import net.psforever.objects.Player
import net.psforever.objects.avatar.scoring.Kill
import net.psforever.objects.serverobject.hackable.Hackable
import net.psforever.objects.zones.exp.ToDatabase
import net.psforever.packet.game.ChatMsg
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
import scala.collection.mutable
import scala.concurrent.duration._
@ -31,6 +35,20 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
updateHotSpotInfoOverTime()
updateTime(now)
}
building.CaptureTerminal
.map(_.HackedBy)
.collect {
case Some(info@Hackable.HackInfo(_, _, start, length, _))
if building.NtuLevel == 0 && {
val approximateHackTimeRemaining = math.max(0, start + length - System.currentTimeMillis())
approximateHackTimeRemaining <= 300.seconds.toMillis && approximateHackTimeRemaining > 295.seconds.toMillis
} =>
MajorFacilityHackParticipation.warningMessageForHackOccupiers(
building,
info,
ChatMsg(ChatMessageType.UNK_227, "@FacilityRequiresResourcesForHackCriticalWarning")
)
}
lastInfoRequest = now
}
@ -287,8 +305,8 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
if (isResecured) {
hackerScore
} else {
val flagCarrierScore = flagCarrier.map (p => List((p.CharId, 0L, "llu"))).getOrElse(Nil)
if (playersInSoi.exists(_.CharId == hackerId) && !flagCarrierScore.exists { case (charId, _,_) => charId == hackerId }) {
val flagCarrierScore = flagCarrier.map(p => List((p.CharId, 0L, "llu"))).getOrElse(Nil)
if (playersInSoi.exists(_.CharId == hackerId) && !flagCarrierScore.exists { case (charId, _, _) => charId == hackerId }) {
hackerScore ++ flagCarrierScore
} else {
flagCarrierScore
@ -326,3 +344,61 @@ final case class MajorFacilityHackParticipation(building: Building) extends Faci
.getOrElse(list)
}
}
object MajorFacilityHackParticipation {
/**
* Dispatch a message to clients affected by some change.
* Establish the hack information by referencing the capture terminal.
* @param building building entity
* @param msg message to send to affected clients
*/
def warningMessageForHackOccupiers(
building: Building,
msg: ChatMsg
): Unit = {
building
.CaptureTerminal
.flatMap(_.HackedBy)
.foreach { hackedInfo =>
warningMessageForHackOccupiers(building, hackedInfo, msg)
}
}
/**
* Dispatch a message to clients affected by some change.
* Select individuals belonging to the hacking faction to be targets for the message.
* @param building building entity
* @param hackedInfo confirmed information about the hack state
* @param msg message to send to affected clients
*/
def warningMessageForHackOccupiers(
building: Building,
hackedInfo: Hackable.HackInfo,
msg: ChatMsg
): Unit = {
val hackerFaction = hackedInfo.hackerFaction
warningMessageForHackOccupiers(
building,
building.PlayersInSOI.filter(_.Faction == hackerFaction),
msg
)
}
/**
* Dispatch a message to clients affected by some change.
* @param building building entity
* @param targets affected clients by player
* @param msg message to send to affected clients
*/
private def warningMessageForHackOccupiers(
building: Building,
targets: Iterable[Player],
msg: ChatMsg
): Unit = {
val events = building.Zone.LocalEvents
val message = LocalAction.SendResponse(msg)
targets.foreach { player =>
events ! LocalServiceMessage(player.Name, message)
}
}
}

View file

@ -6,8 +6,11 @@ import net.psforever.actors.zone.ZoneActor
import net.psforever.objects.definition.VehicleDefinition
import net.psforever.objects.serverobject.deploy.{Deployment, Interference}
import net.psforever.objects.vital.InGameHistory
import net.psforever.objects.{Default, Vehicle}
import net.psforever.types.{DriveState, PlanetSideEmpire, Vector3}
import net.psforever.objects.{Default, GlobalDefinitions, Vehicle}
import net.psforever.packet.game.ChatMsg
import net.psforever.services.Service
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import net.psforever.types.{ChatMessageType, DriveState, PlanetSideEmpire, Vector3}
import scala.annotation.tailrec
import scala.collection.mutable
@ -83,7 +86,17 @@ class ZoneVehicleActor(
case Zone.Vehicle.CanNotDespawn(_, _, _) => ()
case Zone.Vehicle.CanNotDeploy(_, vehicle, _, reason) => ()
case Zone.Vehicle.CanNotDeploy(_, vehicle, toState, _)
if vehicle.Definition == GlobalDefinitions.ams &&
toState == DriveState.Deployed =>
val pos = vehicle.Position
zone.VehicleEvents ! VehicleServiceMessage(
vehicle.Seats.headOption.flatMap(_._2.occupant).map(_.Name).getOrElse("Driver"),
VehicleAction.SendResponse(Service.defaultPlayerGUID, ChatMsg(ChatMessageType.UNK_227, "@nodeploy_ams"))
)
temporaryInterference = temporaryInterference.filterNot(_._1 == pos)
case Zone.Vehicle.CanNotDeploy(_, vehicle, _, reason) =>
val pos = vehicle.Position
val driverMoniker = vehicle.Seats.headOption.flatMap(_._2.occupant).map(_.Name).getOrElse("Driver")
log.warn(s"$driverMoniker's ${vehicle.Definition.Name} can not deploy in ${zone.id} because $reason")

View file

@ -6,16 +6,17 @@ import net.psforever.actors.zone.{BuildingActor, ZoneActor}
import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.hackable.Hackable
import net.psforever.objects.serverobject.llu.CaptureFlag
import net.psforever.objects.serverobject.structures.Building
import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
import net.psforever.objects.zones.Zone
import net.psforever.objects.Default
import net.psforever.packet.game.{GenericAction, HackState7, PlanetsideAttributeEnum}
import net.psforever.objects.serverobject.structures.participation.MajorFacilityHackParticipation
import net.psforever.packet.game.{ChatMsg, GenericAction, HackState7, PlanetsideAttributeEnum}
import net.psforever.objects.sourcing.PlayerSource
import net.psforever.services.Service
import net.psforever.services.local.support.HackCaptureActor.GetHackingFaction
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import net.psforever.types.{ChatMessageType, PlanetSideEmpire, PlanetSideGUID}
import scala.concurrent.duration.{FiniteDuration, _}
import scala.util.Random
@ -234,6 +235,18 @@ class HackCaptureActor extends Actor {
val owner = terminal.Owner.asInstanceOf[Building]
// Notify parent building that state has changed
owner.Actor ! BuildingActor.AmenityStateChange(terminal, Some(isResecured))
// If major facility, check NTU
owner.CaptureTerminal
.map(_.HackedBy)
.collect {
case Some(info: Hackable.HackInfo)
if owner.BuildingType == StructureType.Facility && owner.NtuLevel == 0 =>
MajorFacilityHackParticipation.warningMessageForHackOccupiers(
owner,
info,
ChatMsg(ChatMessageType.UNK_227, "@FacilityRequiresResourcesForHackWarning")
)
}
// Push map update to clients
owner.Zone.actor ! ZoneActor.ZoneMapUpdate()
}