mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-07-15 08:24:42 +00:00
extending the force dome protection over a variety of entities in a different manner, with a focus on how to perform state reset (dismounting and dome protect end); completely refactored and reworked the self-reported zone interaction timer for vehicles; separated passenger seat mounting from gunner seat mounting
This commit is contained in:
parent
ba266d0a3e
commit
52dbe6a649
21 changed files with 322 additions and 82 deletions
|
|
@ -9,7 +9,6 @@ import net.psforever.objects.{GlobalDefinitions, PlanetSideGameObject, Player, V
|
||||||
import net.psforever.objects.definition.{BasicDefinition, ObjectDefinition}
|
import net.psforever.objects.definition.{BasicDefinition, ObjectDefinition}
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
import net.psforever.objects.serverobject.environment.interaction.ResetAllEnvironmentInteractions
|
import net.psforever.objects.serverobject.environment.interaction.ResetAllEnvironmentInteractions
|
||||||
import net.psforever.objects.serverobject.hackable.GenericHackables
|
|
||||||
import net.psforever.objects.serverobject.mount.Mountable
|
import net.psforever.objects.serverobject.mount.Mountable
|
||||||
import net.psforever.objects.serverobject.structures.WarpGate
|
import net.psforever.objects.serverobject.structures.WarpGate
|
||||||
import net.psforever.objects.serverobject.terminals.implant.ImplantTerminalMech
|
import net.psforever.objects.serverobject.terminals.implant.ImplantTerminalMech
|
||||||
|
|
@ -105,7 +104,8 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
||||||
ops.MountingAction(tplayer, obj, seatNumber)
|
ops.MountingAction(tplayer, obj, seatNumber)
|
||||||
|
|
||||||
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
||||||
if seatNumber == 0 && obj.Definition.MaxCapacitor > 0 =>
|
if seatNumber == 0 &&
|
||||||
|
obj.Definition.MaxCapacitor > 0 =>
|
||||||
log.info(s"${player.Name} mounts the driver seat of the ${obj.Definition.Name}")
|
log.info(s"${player.Name} mounts the driver seat of the ${obj.Definition.Name}")
|
||||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||||
val obj_guid: PlanetSideGUID = obj.GUID
|
val obj_guid: PlanetSideGUID = obj.GUID
|
||||||
|
|
@ -134,13 +134,9 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
||||||
ops.MountingAction(tplayer, obj, seatNumber)
|
ops.MountingAction(tplayer, obj, seatNumber)
|
||||||
|
|
||||||
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
||||||
if obj.Definition.MaxCapacitor > 0 =>
|
if obj.Definition.MaxCapacitor > 0 &&
|
||||||
log.info(s"${player.Name} mounts ${
|
obj.SeatPermissionGroup(seatNumber).contains(AccessPermissionGroup.Gunner) =>
|
||||||
obj.SeatPermissionGroup(seatNumber) match {
|
log.info(s"${player.Name} mounts the #$seatNumber gunner seat of the ${obj.Definition.Name}")
|
||||||
case Some(seatType) => s"a $seatType seat (#$seatNumber)"
|
|
||||||
case None => "a seat"
|
|
||||||
}
|
|
||||||
} of the ${obj.Definition.Name}")
|
|
||||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||||
val obj_guid: PlanetSideGUID = obj.GUID
|
val obj_guid: PlanetSideGUID = obj.GUID
|
||||||
sessionLogic.terminals.CancelAllProximityUnits()
|
sessionLogic.terminals.CancelAllProximityUnits()
|
||||||
|
|
@ -149,17 +145,26 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
||||||
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=113, obj.Capacitor))
|
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=113, obj.Capacitor))
|
||||||
sessionLogic.general.accessContainer(obj)
|
sessionLogic.general.accessContainer(obj)
|
||||||
ops.updateWeaponAtSeatPosition(obj, seatNumber)
|
ops.updateWeaponAtSeatPosition(obj, seatNumber)
|
||||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
|
||||||
tplayer.Actor ! ResetAllEnvironmentInteractions
|
tplayer.Actor ! ResetAllEnvironmentInteractions
|
||||||
ops.MountingAction(tplayer, obj, seatNumber)
|
ops.MountingAction(tplayer, obj, seatNumber)
|
||||||
|
|
||||||
case Mountable.CanMount(obj: Vehicle, seatNumber, _) =>
|
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
||||||
log.info(s"${player.Name} mounts the ${
|
if obj.Definition.MaxCapacitor > 0 =>
|
||||||
obj.SeatPermissionGroup(seatNumber) match {
|
log.info(s"${player.Name} mounts the #$seatNumber seat of the ${obj.Definition.Name}")
|
||||||
case Some(seatType) => s"a $seatType seat (#$seatNumber)"
|
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||||
case None => "a seat"
|
val obj_guid: PlanetSideGUID = obj.GUID
|
||||||
}
|
sessionLogic.terminals.CancelAllProximityUnits()
|
||||||
} of the ${obj.Definition.Name}")
|
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=0, obj.Health))
|
||||||
|
sendResponse(PlanetsideAttributeMessage(obj_guid, obj.Definition.shieldUiAttribute, obj.Shields))
|
||||||
|
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=113, obj.Capacitor))
|
||||||
|
sessionLogic.general.accessContainer(obj)
|
||||||
|
tplayer.Actor ! ResetAllEnvironmentInteractions
|
||||||
|
ops.MountingAction(tplayer, obj, seatNumber)
|
||||||
|
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||||
|
|
||||||
|
case Mountable.CanMount(obj: Vehicle, seatNumber, _)
|
||||||
|
if obj.SeatPermissionGroup(seatNumber).contains(AccessPermissionGroup.Gunner) =>
|
||||||
|
log.info(s"${player.Name} mounts the #$seatNumber gunner seat of the ${obj.Definition.Name}")
|
||||||
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||||
val obj_guid: PlanetSideGUID = obj.GUID
|
val obj_guid: PlanetSideGUID = obj.GUID
|
||||||
sessionLogic.terminals.CancelAllProximityUnits()
|
sessionLogic.terminals.CancelAllProximityUnits()
|
||||||
|
|
@ -167,10 +172,21 @@ class MountHandlerLogic(val ops: SessionMountHandlers, implicit val context: Act
|
||||||
sendResponse(PlanetsideAttributeMessage(obj_guid, obj.Definition.shieldUiAttribute, obj.Shields))
|
sendResponse(PlanetsideAttributeMessage(obj_guid, obj.Definition.shieldUiAttribute, obj.Shields))
|
||||||
sessionLogic.general.accessContainer(obj)
|
sessionLogic.general.accessContainer(obj)
|
||||||
ops.updateWeaponAtSeatPosition(obj, seatNumber)
|
ops.updateWeaponAtSeatPosition(obj, seatNumber)
|
||||||
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
|
||||||
tplayer.Actor ! ResetAllEnvironmentInteractions
|
tplayer.Actor ! ResetAllEnvironmentInteractions
|
||||||
ops.MountingAction(tplayer, obj, seatNumber)
|
ops.MountingAction(tplayer, obj, seatNumber)
|
||||||
|
|
||||||
|
case Mountable.CanMount(obj: Vehicle, seatNumber, _) =>
|
||||||
|
log.info(s"${player.Name} mounts the #$seatNumber seat of the ${obj.Definition.Name}")
|
||||||
|
sessionLogic.zoning.CancelZoningProcessWithDescriptiveReason("cancel_mount")
|
||||||
|
val obj_guid: PlanetSideGUID = obj.GUID
|
||||||
|
sessionLogic.terminals.CancelAllProximityUnits()
|
||||||
|
sendResponse(PlanetsideAttributeMessage(obj_guid, attribute_type=0, obj.Health))
|
||||||
|
sendResponse(PlanetsideAttributeMessage(obj_guid, obj.Definition.shieldUiAttribute, obj.Shields))
|
||||||
|
sessionLogic.general.accessContainer(obj)
|
||||||
|
tplayer.Actor ! ResetAllEnvironmentInteractions
|
||||||
|
ops.MountingAction(tplayer, obj, seatNumber)
|
||||||
|
sessionLogic.keepAliveFunc = sessionLogic.keepAlivePersistenceFunc
|
||||||
|
|
||||||
case Mountable.CanMount(obj: FacilityTurret, seatNumber, _)
|
case Mountable.CanMount(obj: FacilityTurret, seatNumber, _)
|
||||||
if obj.Definition == GlobalDefinitions.vanu_sentry_turret =>
|
if obj.Definition == GlobalDefinitions.vanu_sentry_turret =>
|
||||||
log.info(s"${player.Name} mounts the ${obj.Definition.Name}")
|
log.info(s"${player.Name} mounts the ${obj.Definition.Name}")
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,12 @@ import akka.actor.{ActorContext, typed}
|
||||||
import net.psforever.actors.session.AvatarActor
|
import net.psforever.actors.session.AvatarActor
|
||||||
import net.psforever.actors.session.support.{SessionData, VehicleFunctions, VehicleOperations}
|
import net.psforever.actors.session.support.{SessionData, VehicleFunctions, VehicleOperations}
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||||
import net.psforever.objects.{Vehicle, Vehicles}
|
import net.psforever.objects.{PlanetSideGameObject, Vehicle, Vehicles}
|
||||||
import net.psforever.objects.serverobject.deploy.Deployment
|
import net.psforever.objects.serverobject.deploy.Deployment
|
||||||
import net.psforever.objects.serverobject.mount.Mountable
|
import net.psforever.objects.serverobject.mount.Mountable
|
||||||
import net.psforever.objects.vehicles.control.BfrFlight
|
import net.psforever.objects.vehicles.control.BfrFlight
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
|
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||||
import net.psforever.packet.game.{ChatMsg, ChildObjectStateMessage, DeployRequestMessage, FrameVehicleStateMessage, VehicleStateMessage, VehicleSubStateMessage}
|
import net.psforever.packet.game.{ChatMsg, ChildObjectStateMessage, DeployRequestMessage, FrameVehicleStateMessage, VehicleStateMessage, VehicleSubStateMessage}
|
||||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
import net.psforever.types.{ChatMessageType, DriveState, Vector3}
|
import net.psforever.types.{ChatMessageType, DriveState, Vector3}
|
||||||
|
|
@ -94,7 +95,7 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
sessionLogic.squad.updateSquad()
|
sessionLogic.squad.updateSquad()
|
||||||
obj.zoneInteractions()
|
VehicleOperations.updateMountableZoneInteractionFromEarliestSeat(obj, player)
|
||||||
case (None, _) =>
|
case (None, _) =>
|
||||||
//log.error(s"VehicleState: no vehicle $vehicle_guid found in zone")
|
//log.error(s"VehicleState: no vehicle $vehicle_guid found in zone")
|
||||||
//TODO placing a "not driving" warning here may trigger as we are disembarking the vehicle
|
//TODO placing a "not driving" warning here may trigger as we are disembarking the vehicle
|
||||||
|
|
@ -168,7 +169,7 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
|
||||||
obj.Velocity = None
|
obj.Velocity = None
|
||||||
obj.Flying = None
|
obj.Flying = None
|
||||||
}
|
}
|
||||||
obj.zoneInteractions()
|
VehicleOperations.updateMountableZoneInteractionFromEarliestSeat(obj, player)
|
||||||
} else {
|
} else {
|
||||||
obj.Velocity = None
|
obj.Velocity = None
|
||||||
obj.Flying = None
|
obj.Flying = None
|
||||||
|
|
@ -216,9 +217,16 @@ class VehicleLogic(val ops: VehicleOperations, implicit val context: ActorContex
|
||||||
case Some(mount: Mountable) => (o, mount.PassengerInSeat(player))
|
case Some(mount: Mountable) => (o, mount.PassengerInSeat(player))
|
||||||
case _ => (None, None)
|
case _ => (None, None)
|
||||||
}) match {
|
}) match {
|
||||||
case (None, None) | (_, None) | (Some(_: Vehicle), Some(0)) =>
|
case (None, _) | (_, None) => //error - we do not recognize being mounted or controlling anything, but what can we do about it?
|
||||||
()
|
()
|
||||||
case _ =>
|
case (Some(_: Vehicle), Some(0)) => //no (see: VSM or FVSM for valid cases)
|
||||||
|
()
|
||||||
|
case (Some(entity: PlanetSideGameObject with InteractsWithZone), Some(_)) => //yes
|
||||||
|
sessionLogic.zoning.spawn.tryQueuedActivity() //todo conditionals?
|
||||||
|
sessionLogic.persist()
|
||||||
|
sessionLogic.turnCounterFunc(player.GUID)
|
||||||
|
VehicleOperations.updateMountableZoneInteractionFromEarliestSeat(entity, player)
|
||||||
|
case _ => //yes
|
||||||
sessionLogic.zoning.spawn.tryQueuedActivity() //todo conditionals?
|
sessionLogic.zoning.spawn.tryQueuedActivity() //todo conditionals?
|
||||||
sessionLogic.persist()
|
sessionLogic.persist()
|
||||||
sessionLogic.turnCounterFunc(player.GUID)
|
sessionLogic.turnCounterFunc(player.GUID)
|
||||||
|
|
|
||||||
|
|
@ -467,6 +467,11 @@ class SessionData(
|
||||||
persist()
|
persist()
|
||||||
if (player.HasGUID) {
|
if (player.HasGUID) {
|
||||||
turnCounterFunc(player.GUID)
|
turnCounterFunc(player.GUID)
|
||||||
|
continent
|
||||||
|
.GUID(player.VehicleSeated)
|
||||||
|
.foreach {
|
||||||
|
VehicleOperations.updateMountableZoneInteractionFromEarliestSeat(_, player)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
turnCounterFunc(PlanetSideGUID(0))
|
turnCounterFunc(PlanetSideGUID(0))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import net.psforever.objects.serverobject.deploy.Deployment
|
||||||
import net.psforever.objects.serverobject.mount.Mountable
|
import net.psforever.objects.serverobject.mount.Mountable
|
||||||
import net.psforever.objects.zones.Zone
|
import net.psforever.objects.zones.Zone
|
||||||
import net.psforever.objects._
|
import net.psforever.objects._
|
||||||
|
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||||
import net.psforever.packet.game.{ChildObjectStateMessage, DeployRequestMessage, VehicleSubStateMessage, _}
|
import net.psforever.packet.game.{ChildObjectStateMessage, DeployRequestMessage, VehicleSubStateMessage, _}
|
||||||
import net.psforever.types.DriveState
|
import net.psforever.types.DriveState
|
||||||
|
|
||||||
|
|
@ -195,3 +196,56 @@ class VehicleOperations(
|
||||||
sendResponse(pkt)
|
sendResponse(pkt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object VehicleOperations {
|
||||||
|
def updateMountableZoneInteractionFromEarliestSeat(obj: PlanetSideGameObject, passenger: Player): Unit = {
|
||||||
|
obj match {
|
||||||
|
case obj: Vehicle =>
|
||||||
|
updateVehicleZoneInteractionFromEarliestSeat(obj, passenger)
|
||||||
|
case obj: Mountable with InteractsWithZone =>
|
||||||
|
updateEntityZoneInteractionFromEarliestSeat(obj, passenger, obj)
|
||||||
|
case _ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def updateVehicleZoneInteractionFromEarliestSeat(obj: Vehicle, passenger: Player): Unit = {
|
||||||
|
//vehicle being ferried; check if the ferry has occupants that might have speaking rights before us
|
||||||
|
var targetVehicle = obj
|
||||||
|
val carrierSeatVacancy: Boolean = obj match {
|
||||||
|
case v if v.MountedIn.nonEmpty =>
|
||||||
|
obj.Zone.GUID(v.MountedIn) match {
|
||||||
|
case Some(carrier: Vehicle) =>
|
||||||
|
targetVehicle = carrier
|
||||||
|
!carrier.Seats.values.exists(_.isOccupied)
|
||||||
|
case _ =>
|
||||||
|
true
|
||||||
|
}
|
||||||
|
case _ => true
|
||||||
|
}
|
||||||
|
if (carrierSeatVacancy) {
|
||||||
|
updateEntityZoneInteractionFromEarliestSeat(obj, passenger, targetVehicle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def updateEntityZoneInteractionFromEarliestSeat(
|
||||||
|
obj: Mountable with InteractsWithZone,
|
||||||
|
passenger: Player,
|
||||||
|
updateTarget: InteractsWithZone
|
||||||
|
): Unit = {
|
||||||
|
val inSeatNumberOpt = obj.PassengerInSeat(passenger)
|
||||||
|
if (inSeatNumberOpt.contains(0)) {
|
||||||
|
//we're responsible as the primary operator
|
||||||
|
updateTarget.zoneInteractions()
|
||||||
|
} else if (!obj.Seat(seatNumber = 0).exists(_.isOccupied)) {
|
||||||
|
//there is no primary operator; are we responsible?
|
||||||
|
//determine if we are the player in the seat closest to the "front"
|
||||||
|
val noPlayersInEarlierSeats = inSeatNumberOpt
|
||||||
|
.exists { seatIndex =>
|
||||||
|
!(1 until seatIndex).exists { i => obj.Seat(i).exists(_.isOccupied) }
|
||||||
|
}
|
||||||
|
if (noPlayersInEarlierSeats) {
|
||||||
|
updateTarget.zoneInteractions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1930,7 +1930,7 @@ class ZoningOperations(
|
||||||
/** Upstream message counter<br>
|
/** Upstream message counter<br>
|
||||||
* Checks for server acknowledgement of the following messages in the following conditions:<br>
|
* Checks for server acknowledgement of the following messages in the following conditions:<br>
|
||||||
* `PlayerStateMessageUpstream` (infantry)<br>
|
* `PlayerStateMessageUpstream` (infantry)<br>
|
||||||
* `VehicleStateMessage` (driver mount only)<br>
|
* `VehicleStateMessage` and `FrameVehicleStateMessage` (driver mount)<br>
|
||||||
* `ChildObjectStateMessage` (any gunner mount that is not the driver)<br>
|
* `ChildObjectStateMessage` (any gunner mount that is not the driver)<br>
|
||||||
* `KeepAliveMessage` (any passenger mount that is not the driver)<br>
|
* `KeepAliveMessage` (any passenger mount that is not the driver)<br>
|
||||||
* As they should arrive roughly every 250 milliseconds this allows for a very crude method of scheduling tasks up to four times per second
|
* As they should arrive roughly every 250 milliseconds this allows for a very crude method of scheduling tasks up to four times per second
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import net.psforever.objects.guid.{GUIDTask, TaskWorkflow}
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
||||||
import net.psforever.objects.serverobject.damage.Damageable
|
import net.psforever.objects.serverobject.damage.Damageable
|
||||||
import net.psforever.objects.serverobject.hackable.Hackable
|
import net.psforever.objects.serverobject.hackable.Hackable
|
||||||
import net.psforever.objects.serverobject.mount.{InteractWithForceDomeProtectionSeatedInEntity, InteractWithRadiationCloudsSeatedInEntity}
|
import net.psforever.objects.serverobject.mount.interaction.{InteractWithForceDomeProtectionSeatedInEntity, InteractWithRadiationCloudsSeatedInEntity}
|
||||||
import net.psforever.objects.serverobject.turret.auto.{AffectedByAutomaticTurretFire, AutomatedTurret}
|
import net.psforever.objects.serverobject.turret.auto.{AffectedByAutomaticTurretFire, AutomatedTurret}
|
||||||
import net.psforever.objects.serverobject.turret.{TurretControl, TurretDefinition, WeaponTurret}
|
import net.psforever.objects.serverobject.turret.{TurretControl, TurretDefinition, WeaponTurret}
|
||||||
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
import net.psforever.objects.sourcing.{PlayerSource, SourceEntry}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import net.psforever.objects.serverobject.hackable.Hackable
|
||||||
import net.psforever.objects.serverobject.interior.{InteriorAwareFromInteraction, Sidedness}
|
import net.psforever.objects.serverobject.interior.{InteriorAwareFromInteraction, Sidedness}
|
||||||
import net.psforever.objects.serverobject.structures.AmenityOwner
|
import net.psforever.objects.serverobject.structures.AmenityOwner
|
||||||
import net.psforever.objects.vehicles._
|
import net.psforever.objects.vehicles._
|
||||||
import net.psforever.objects.vehicles.interaction.{InteractWithForceDomeProtectionSeatedInVehicle, TriggerOnVehicleRule, WithLava, WithWater}
|
import net.psforever.objects.vehicles.interaction.{InteractWithForceDomeProtectionSeatedInVehicle, InteractWithRadiationCloudsSeatedInVehicle, TriggerOnVehicleRule, WithLava, WithWater}
|
||||||
import net.psforever.objects.vital.resistance.StandardResistanceProfile
|
import net.psforever.objects.vital.resistance.StandardResistanceProfile
|
||||||
import net.psforever.objects.vital.Vitality
|
import net.psforever.objects.vital.Vitality
|
||||||
import net.psforever.objects.vital.resolution.DamageResistanceModel
|
import net.psforever.objects.vital.resolution.DamageResistanceModel
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ package net.psforever.objects.avatar.interaction
|
||||||
import net.psforever.objects.serverobject.damage.Damageable
|
import net.psforever.objects.serverobject.damage.Damageable
|
||||||
import net.psforever.objects.serverobject.dome.{ForceDomeControl, ForceDomePhysics}
|
import net.psforever.objects.serverobject.dome.{ForceDomeControl, ForceDomePhysics}
|
||||||
import net.psforever.objects.zones.blockmap.SectorPopulation
|
import net.psforever.objects.zones.blockmap.SectorPopulation
|
||||||
import net.psforever.objects.zones.{InteractsWithZone, ZoneInteraction, ZoneInteractionType}
|
import net.psforever.objects.zones.interaction.{InteractsWithZone, ZoneInteraction, ZoneInteractionType}
|
||||||
|
|
||||||
case object ForceZoneProtection extends ZoneInteractionType
|
case object ForceZoneProtection extends ZoneInteractionType
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,10 @@ trait Damageable {
|
||||||
* cite the `originalTakesDamage` protocol during inheritance overrides */
|
* cite the `originalTakesDamage` protocol during inheritance overrides */
|
||||||
val takesDamage: Receive = {
|
val takesDamage: Receive = {
|
||||||
case Damageable.MakeVulnerable =>
|
case Damageable.MakeVulnerable =>
|
||||||
isVulnerable = false
|
isVulnerable = true
|
||||||
|
|
||||||
case Damageable.MakeInvulnerable =>
|
case Damageable.MakeInvulnerable =>
|
||||||
isVulnerable = true
|
isVulnerable = false
|
||||||
|
|
||||||
case Vitality.Damage(damage_func) =>
|
case Vitality.Damage(damage_func) =>
|
||||||
val obj = DamageableObject
|
val obj = DamageableObject
|
||||||
|
|
@ -47,14 +47,14 @@ trait Damageable {
|
||||||
/** a duplicate of the core implementation for the default mixin hook, for use in overriding */
|
/** a duplicate of the core implementation for the default mixin hook, for use in overriding */
|
||||||
final val originalTakesDamage: Receive = {
|
final val originalTakesDamage: Receive = {
|
||||||
case Damageable.MakeVulnerable =>
|
case Damageable.MakeVulnerable =>
|
||||||
isVulnerable = false
|
isVulnerable = true
|
||||||
|
|
||||||
case Damageable.MakeInvulnerable =>
|
case Damageable.MakeInvulnerable =>
|
||||||
isVulnerable = true
|
isVulnerable = false
|
||||||
|
|
||||||
case Vitality.Damage(damage_func) =>
|
case Vitality.Damage(damage_func) =>
|
||||||
val obj = DamageableObject
|
val obj = DamageableObject
|
||||||
if (obj.CanDamage) {
|
if (isVulnerable && obj.CanDamage) {
|
||||||
PerformDamage(obj, damage_func)
|
PerformDamage(obj, damage_func)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import net.psforever.services.Service
|
||||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
|
||||||
|
import scala.annotation.unused
|
||||||
import scala.util.{Failure, Success}
|
import scala.util.{Failure, Success}
|
||||||
|
|
||||||
object GenericHackables {
|
object GenericHackables {
|
||||||
|
|
@ -49,6 +50,8 @@ object GenericHackables {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def DontStopHackAttempt(@unused target: PlanetSideServerObject, @unused hacker: Player): Boolean = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate the progress of the user applying a tool to modify some server object.
|
* 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.
|
* This action is using the remote electronics kit to convert an enemy unit into an allied unit, primarily.
|
||||||
|
|
@ -62,6 +65,7 @@ object GenericHackables {
|
||||||
* @param target the object being affected
|
* @param target the object being affected
|
||||||
* @param tool_guid the tool being used to affest the object
|
* @param tool_guid the tool being used to affest the object
|
||||||
* @param progress the current progress value
|
* @param progress the current progress value
|
||||||
|
* @param additionalCancellationTests context-specific tests for hack continuation
|
||||||
* @return `true`, if the next cycle of progress should occur;
|
* @return `true`, if the next cycle of progress should occur;
|
||||||
* `false`, otherwise
|
* `false`, otherwise
|
||||||
*/
|
*/
|
||||||
|
|
@ -70,7 +74,7 @@ object GenericHackables {
|
||||||
hacker: Player,
|
hacker: Player,
|
||||||
target: PlanetSideServerObject,
|
target: PlanetSideServerObject,
|
||||||
tool_guid: PlanetSideGUID,
|
tool_guid: PlanetSideGUID,
|
||||||
additionalCancellationTests: (PlanetSideServerObject, Player) => Boolean = ForceDomeProtectsFromHacking
|
additionalCancellationTests: (PlanetSideServerObject, Player) => Boolean
|
||||||
)(
|
)(
|
||||||
progress: Float
|
progress: Float
|
||||||
): Boolean = {
|
): Boolean = {
|
||||||
|
|
@ -93,6 +97,30 @@ object GenericHackables {
|
||||||
)
|
)
|
||||||
progressState != HackState.Cancelled
|
progressState != HackState.Cancelled
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* @param progressType 1 - remote electronics kit hack (various ...);
|
||||||
|
* 2 - nano dispenser (upgrade canister) turret upgrade
|
||||||
|
* @param hacker 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: HackState1,
|
||||||
|
hacker: Player,
|
||||||
|
target: PlanetSideServerObject,
|
||||||
|
tool_guid: PlanetSideGUID
|
||||||
|
)(
|
||||||
|
progress: Float
|
||||||
|
): Boolean = {
|
||||||
|
HackingTickAction(progressType, hacker, target, tool_guid, DontStopHackAttempt)(progress)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The force dome prevents hacking if its protection has been declared over a capitol.
|
* The force dome prevents hacking if its protection has been declared over a capitol.
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
// Copyright (c) 2025 PSForever
|
// Copyright (c) 2025 PSForever
|
||||||
package net.psforever.objects.serverobject.mount
|
package net.psforever.objects.serverobject.mount.interaction
|
||||||
|
|
||||||
import net.psforever.objects.avatar.interaction.InteractWithForceDomeProtection
|
import net.psforever.objects.avatar.interaction.InteractWithForceDomeProtection
|
||||||
import net.psforever.objects.serverobject.damage.Damageable
|
import net.psforever.objects.serverobject.damage.Damageable
|
||||||
import net.psforever.objects.serverobject.dome.ForceDomePhysics
|
import net.psforever.objects.serverobject.dome.ForceDomePhysics
|
||||||
import net.psforever.objects.zones.InteractsWithZone
|
import net.psforever.objects.serverobject.mount.Mountable
|
||||||
|
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||||
|
|
||||||
class InteractWithForceDomeProtectionSeatedInEntity
|
class InteractWithForceDomeProtectionSeatedInEntity
|
||||||
extends InteractWithForceDomeProtection {
|
extends InteractWithForceDomeProtection {
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
// Copyright (c) 2024 PSForever
|
// Copyright (c) 2024 PSForever
|
||||||
package net.psforever.objects.serverobject.mount
|
package net.psforever.objects.serverobject.mount.interaction
|
||||||
|
|
||||||
import net.psforever.objects.ballistics.{Projectile, ProjectileQuality}
|
import net.psforever.objects.ballistics.{Projectile, ProjectileQuality}
|
||||||
|
import net.psforever.objects.serverobject.mount.Mountable
|
||||||
import net.psforever.objects.sourcing.SourceEntry
|
import net.psforever.objects.sourcing.SourceEntry
|
||||||
import net.psforever.objects.vital.Vitality
|
import net.psforever.objects.vital.Vitality
|
||||||
import net.psforever.objects.vital.base.DamageResolution
|
import net.psforever.objects.vital.base.DamageResolution
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package net.psforever.objects.serverobject.mount
|
package net.psforever.objects.serverobject.mount.interaction
|
||||||
|
|
||||||
import net.psforever.objects.zones.interaction.ZoneInteractionType
|
import net.psforever.objects.zones.interaction.ZoneInteractionType
|
||||||
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
package net.psforever.objects.serverobject.terminals.implant
|
package net.psforever.objects.serverobject.terminals.implant
|
||||||
|
|
||||||
import net.psforever.objects.serverobject.hackable.Hackable
|
import net.psforever.objects.serverobject.hackable.Hackable
|
||||||
import net.psforever.objects.serverobject.mount.{InteractWithRadiationCloudsSeatedInEntity, Mountable, Seat}
|
import net.psforever.objects.serverobject.mount.interaction.InteractWithRadiationCloudsSeatedInEntity
|
||||||
|
import net.psforever.objects.serverobject.mount.{Mountable, Seat}
|
||||||
import net.psforever.objects.serverobject.structures.Amenity
|
import net.psforever.objects.serverobject.structures.Amenity
|
||||||
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminalAware
|
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminalAware
|
||||||
import net.psforever.objects.vital.resistance.StandardResistanceProfile
|
import net.psforever.objects.vital.resistance.StandardResistanceProfile
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package net.psforever.objects.serverobject.turret
|
||||||
|
|
||||||
import net.psforever.objects.equipment.JammableUnit
|
import net.psforever.objects.equipment.JammableUnit
|
||||||
import net.psforever.objects.serverobject.interior.Sidedness
|
import net.psforever.objects.serverobject.interior.Sidedness
|
||||||
import net.psforever.objects.serverobject.mount.InteractWithRadiationCloudsSeatedInEntity
|
import net.psforever.objects.serverobject.mount.interaction.InteractWithRadiationCloudsSeatedInEntity
|
||||||
import net.psforever.objects.serverobject.structures.{Amenity, AmenityOwner, Building}
|
import net.psforever.objects.serverobject.structures.{Amenity, AmenityOwner, Building}
|
||||||
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminalAware
|
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminalAware
|
||||||
import net.psforever.objects.serverobject.turret.auto.AutomatedTurret
|
import net.psforever.objects.serverobject.turret.auto.AutomatedTurret
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,12 @@ trait CargoBehavior {
|
||||||
val zone = obj.Zone
|
val zone = obj.Zone
|
||||||
zone.GUID(isMounting) match {
|
zone.GUID(isMounting) match {
|
||||||
case Some(v : Vehicle) => v.Actor ! CargoBehavior.EndCargoMounting(obj.GUID)
|
case Some(v : Vehicle) => v.Actor ! CargoBehavior.EndCargoMounting(obj.GUID)
|
||||||
case _ => ;
|
case _ => ()
|
||||||
}
|
}
|
||||||
isMounting = None
|
isMounting = None
|
||||||
zone.GUID(isDismounting) match {
|
zone.GUID(isDismounting) match {
|
||||||
case Some(v: Vehicle) => v.Actor ! CargoBehavior.EndCargoDismounting(obj.GUID)
|
case Some(v: Vehicle) => v.Actor ! CargoBehavior.EndCargoDismounting(obj.GUID)
|
||||||
case _ => ;
|
case _ => ()
|
||||||
}
|
}
|
||||||
isDismounting = None
|
isDismounting = None
|
||||||
startCargoDismountingNoCleanup(bailed = false)
|
startCargoDismountingNoCleanup(bailed = false)
|
||||||
|
|
@ -38,14 +38,10 @@ trait CargoBehavior {
|
||||||
startCargoDismounting(bailed)
|
startCargoDismounting(bailed)
|
||||||
|
|
||||||
case CargoBehavior.EndCargoMounting(carrier_guid) =>
|
case CargoBehavior.EndCargoMounting(carrier_guid) =>
|
||||||
if (isMounting.contains(carrier_guid)) {
|
endCargoMounting(carrier_guid)
|
||||||
isMounting = None
|
|
||||||
}
|
|
||||||
|
|
||||||
case CargoBehavior.EndCargoDismounting(carrier_guid) =>
|
case CargoBehavior.EndCargoDismounting(carrier_guid) =>
|
||||||
if (isDismounting.contains(carrier_guid)) {
|
endCargoDismounting(carrier_guid)
|
||||||
isDismounting = None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def startCargoMounting(carrier_guid: PlanetSideGUID, mountPoint: Int): Unit = {
|
def startCargoMounting(carrier_guid: PlanetSideGUID, mountPoint: Int): Unit = {
|
||||||
|
|
@ -84,6 +80,18 @@ trait CargoBehavior {
|
||||||
}
|
}
|
||||||
.nonEmpty
|
.nonEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def endCargoMounting(carrierGuid: PlanetSideGUID): Unit = {
|
||||||
|
if (isMounting.contains(carrierGuid)) {
|
||||||
|
isMounting = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def endCargoDismounting(carrierGuid: PlanetSideGUID): Unit = {
|
||||||
|
if (isDismounting.contains(carrierGuid)) {
|
||||||
|
isDismounting = None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object CargoBehavior {
|
object CargoBehavior {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,16 @@ import net.psforever.objects.vital.interaction.DamageResult
|
||||||
class CargoCarrierControl(vehicle: Vehicle)
|
class CargoCarrierControl(vehicle: Vehicle)
|
||||||
extends VehicleControl(vehicle)
|
extends VehicleControl(vehicle)
|
||||||
with CarrierBehavior {
|
with CarrierBehavior {
|
||||||
def CarrierObject = vehicle
|
def CarrierObject: Vehicle = vehicle
|
||||||
|
|
||||||
|
override def TestToStartSelfReporting(): Boolean = {
|
||||||
|
super.TestToStartSelfReporting() &&
|
||||||
|
!CarrierObject
|
||||||
|
.CargoHolds
|
||||||
|
.values
|
||||||
|
.flatMap(_.occupants)
|
||||||
|
.exists(_.Seats.values.exists(_.isOccupied))
|
||||||
|
}
|
||||||
|
|
||||||
override def postStop() : Unit = {
|
override def postStop() : Unit = {
|
||||||
super.postStop()
|
super.postStop()
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import net.psforever.objects.serverobject.environment._
|
||||||
import net.psforever.objects.serverobject.environment.interaction.common.Watery
|
import net.psforever.objects.serverobject.environment.interaction.common.Watery
|
||||||
import net.psforever.objects.serverobject.environment.interaction.{InteractWithEnvironment, RespondsToZoneEnvironment}
|
import net.psforever.objects.serverobject.environment.interaction.{InteractWithEnvironment, RespondsToZoneEnvironment}
|
||||||
import net.psforever.objects.serverobject.hackable.GenericHackables
|
import net.psforever.objects.serverobject.hackable.GenericHackables
|
||||||
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior, RadiationInMountableInteraction}
|
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
|
||||||
import net.psforever.objects.serverobject.repair.RepairableVehicle
|
import net.psforever.objects.serverobject.repair.RepairableVehicle
|
||||||
import net.psforever.objects.serverobject.structures.WarpGate
|
import net.psforever.objects.serverobject.structures.WarpGate
|
||||||
import net.psforever.objects.serverobject.terminals.Terminal
|
import net.psforever.objects.serverobject.terminals.Terminal
|
||||||
|
|
@ -31,6 +31,7 @@ import net.psforever.objects.vehicles.interaction.WithWater
|
||||||
import net.psforever.objects.vital.interaction.DamageResult
|
import net.psforever.objects.vital.interaction.DamageResult
|
||||||
import net.psforever.objects.vital.{DamagingActivity, InGameActivity, ShieldCharge, SpawningActivity, VehicleDismountActivity, VehicleMountActivity}
|
import net.psforever.objects.vital.{DamagingActivity, InGameActivity, ShieldCharge, SpawningActivity, VehicleDismountActivity, VehicleMountActivity}
|
||||||
import net.psforever.objects.zones._
|
import net.psforever.objects.zones._
|
||||||
|
import net.psforever.objects.zones.interaction.IndependentZoneInteraction
|
||||||
import net.psforever.packet.PlanetSideGamePacket
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
||||||
|
|
@ -63,7 +64,8 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
with AggravatedBehavior
|
with AggravatedBehavior
|
||||||
with RespondsToZoneEnvironment
|
with RespondsToZoneEnvironment
|
||||||
with CargoBehavior
|
with CargoBehavior
|
||||||
with AffectedByAutomaticTurretFire {
|
with AffectedByAutomaticTurretFire
|
||||||
|
with IndependentZoneInteraction {
|
||||||
//make control actors belonging to utilities when making control actor belonging to vehicle
|
//make control actors belonging to utilities when making control actor belonging to vehicle
|
||||||
vehicle.Utilities.foreach { case (_, util) => util.Setup }
|
vehicle.Utilities.foreach { case (_, util) => util.Setup }
|
||||||
|
|
||||||
|
|
@ -77,6 +79,7 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
def InteractiveObject: Vehicle = vehicle
|
def InteractiveObject: Vehicle = vehicle
|
||||||
def CargoObject: Vehicle = vehicle
|
def CargoObject: Vehicle = vehicle
|
||||||
def AffectedObject: Vehicle = vehicle
|
def AffectedObject: Vehicle = vehicle
|
||||||
|
def ZoneInteractionObject: Vehicle = vehicle
|
||||||
|
|
||||||
/** cheap flag for whether the vehicle is decaying */
|
/** cheap flag for whether the vehicle is decaying */
|
||||||
var decaying : Boolean = false
|
var decaying : Boolean = false
|
||||||
|
|
@ -84,8 +87,6 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
var decayTimer : Cancellable = Default.Cancellable
|
var decayTimer : Cancellable = Default.Cancellable
|
||||||
/** becoming waterlogged, or drying out? */
|
/** becoming waterlogged, or drying out? */
|
||||||
var submergedCondition : Option[OxygenState] = None
|
var submergedCondition : Option[OxygenState] = None
|
||||||
/** ... */
|
|
||||||
var passengerRadiationCloudTimer: Cancellable = Default.Cancellable
|
|
||||||
|
|
||||||
def receive : Receive = Enabled
|
def receive : Receive = Enabled
|
||||||
|
|
||||||
|
|
@ -94,7 +95,7 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
damageableVehiclePostStop()
|
damageableVehiclePostStop()
|
||||||
decaying = false
|
decaying = false
|
||||||
decayTimer.cancel()
|
decayTimer.cancel()
|
||||||
passengerRadiationCloudTimer.cancel()
|
StopInteractionSelfReporting()
|
||||||
vehicle.Utilities.values.foreach { util =>
|
vehicle.Utilities.values.foreach { util =>
|
||||||
context.stop(util().Actor)
|
context.stop(util().Actor)
|
||||||
util().Actor = Default.Actor
|
util().Actor = Default.Actor
|
||||||
|
|
@ -113,6 +114,7 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
.orElse(environmentBehavior)
|
.orElse(environmentBehavior)
|
||||||
.orElse(cargoBehavior)
|
.orElse(cargoBehavior)
|
||||||
.orElse(takeAutomatedDamage)
|
.orElse(takeAutomatedDamage)
|
||||||
|
.orElse(zoneInteractionBehavior)
|
||||||
.orElse {
|
.orElse {
|
||||||
case Vehicle.Ownership(None) =>
|
case Vehicle.Ownership(None) =>
|
||||||
LoseOwnership()
|
LoseOwnership()
|
||||||
|
|
@ -288,11 +290,6 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
final def Enabled: Receive =
|
final def Enabled: Receive =
|
||||||
commonEnabledBehavior
|
commonEnabledBehavior
|
||||||
.orElse {
|
.orElse {
|
||||||
case VehicleControl.RadiationTick if !passengerRadiationCloudTimer.isCancelled =>
|
|
||||||
vehicle
|
|
||||||
.interaction()
|
|
||||||
.find(_.Type == RadiationInMountableInteraction)
|
|
||||||
.foreach(_.interaction(vehicle.getInteractionSector, vehicle))
|
|
||||||
case _ => ()
|
case _ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,7 +370,7 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
decaying = false
|
decaying = false
|
||||||
decayTimer.cancel()
|
decayTimer.cancel()
|
||||||
}
|
}
|
||||||
passengerRadiationCloudTimer.cancel()
|
TryStopInteractionSelfReporting()
|
||||||
updateZoneInteractionProgressUI(user)
|
updateZoneInteractionProgressUI(user)
|
||||||
|
|
||||||
case Some(seatNumber) => //literally any other seat
|
case Some(seatNumber) => //literally any other seat
|
||||||
|
|
@ -381,9 +378,7 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
user.LogActivity(VehicleMountActivity(vsrc, PlayerSource.inSeat(user, vsrc, seatNumber), vehicle.Zone.Number))
|
user.LogActivity(VehicleMountActivity(vsrc, PlayerSource.inSeat(user, vsrc, seatNumber), vehicle.Zone.Number))
|
||||||
decaying = false
|
decaying = false
|
||||||
decayTimer.cancel()
|
decayTimer.cancel()
|
||||||
if (!vehicle.Seats(0).isOccupied && passengerRadiationCloudTimer.isCancelled) {
|
StopInteractionSelfReporting()
|
||||||
StartRadiationSelfReporting()
|
|
||||||
}
|
|
||||||
updateZoneInteractionProgressUI(user)
|
updateZoneInteractionProgressUI(user)
|
||||||
|
|
||||||
case None => ()
|
case None => ()
|
||||||
|
|
@ -400,15 +395,14 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
|
|
||||||
def dismountCleanup(seatBeingDismounted: Int, user: Player): Unit = {
|
def dismountCleanup(seatBeingDismounted: Int, user: Player): Unit = {
|
||||||
val obj = MountableObject
|
val obj = MountableObject
|
||||||
val allSeatsUnoccupied = !obj.Seats.values.exists(_.isOccupied)
|
|
||||||
// Reset velocity to zero when driver dismounts, to allow jacking/repair if vehicle was moving slightly before dismount
|
// Reset velocity to zero when driver dismounts, to allow jacking/repair if vehicle was moving slightly before dismount
|
||||||
if (!obj.Seats(0).isOccupied) {
|
if (!obj.Seats(0).isOccupied) {
|
||||||
obj.Velocity = Some(Vector3.Zero)
|
obj.Velocity = Some(Vector3.Zero)
|
||||||
}
|
}
|
||||||
if (allSeatsUnoccupied) {
|
val allSeatsUnoccupied = !vehicle.Seats.values.exists(_.isOccupied)
|
||||||
passengerRadiationCloudTimer.cancel()
|
val otherTests = TestToStartSelfReporting()
|
||||||
} else if (seatBeingDismounted == 0) {
|
if (allSeatsUnoccupied && otherTests) {
|
||||||
StartRadiationSelfReporting()
|
StartInteractionSelfReporting()
|
||||||
}
|
}
|
||||||
if (!obj.Seats(seatBeingDismounted).isOccupied) { //this seat really was vacated
|
if (!obj.Seats(seatBeingDismounted).isOccupied) { //this seat really was vacated
|
||||||
user.LogActivity(VehicleDismountActivity(VehicleSource(vehicle), PlayerSource(user), vehicle.Zone.Number))
|
user.LogActivity(VehicleDismountActivity(VehicleSource(vehicle), PlayerSource(user), vehicle.Zone.Number))
|
||||||
|
|
@ -432,14 +426,18 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def StartRadiationSelfReporting(): Unit = {
|
def TestToStartSelfReporting(): Boolean = {
|
||||||
passengerRadiationCloudTimer.cancel()
|
vehicle.MountedIn.isEmpty
|
||||||
passengerRadiationCloudTimer = context.system.scheduler.scheduleWithFixedDelay(
|
}
|
||||||
250.milliseconds,
|
|
||||||
250.milliseconds,
|
def PerformSelfReportRunCheck(): Unit = {
|
||||||
self,
|
val noOccupancy = !vehicle.Seats.values.exists(_.isOccupied)
|
||||||
VehicleControl.RadiationTick
|
val otherTests = TestToStartSelfReporting()
|
||||||
)
|
if (noOccupancy && otherTests) {
|
||||||
|
StartInteractionSelfReporting()
|
||||||
|
} else {
|
||||||
|
StopInteractionSelfReporting()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def PrepareForDisabled(kickPassengers: Boolean) : Unit = {
|
def PrepareForDisabled(kickPassengers: Boolean) : Unit = {
|
||||||
|
|
@ -767,9 +765,31 @@ class VehicleControl(vehicle: Vehicle)
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def DestructionAwareness(target: Target, cause: DamageResult): Unit = {
|
override protected def DestructionAwareness(target: Target, cause: DamageResult): Unit = {
|
||||||
passengerRadiationCloudTimer.cancel()
|
StopInteractionSelfReportingNoReset()
|
||||||
super.DestructionAwareness(target, cause)
|
super.DestructionAwareness(target, cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def endCargoMounting(carrierGuid: PlanetSideGUID): Unit = {
|
||||||
|
super.endCargoMounting(carrierGuid)
|
||||||
|
StopInteractionSelfReporting()
|
||||||
|
vehicle.Zone.GUID(carrierGuid) match {
|
||||||
|
case Some(v: Vehicle) => v.Actor ! IndependentZoneInteraction.SelfReportRunCheck
|
||||||
|
case _ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def endCargoDismounting(carrierGuid: PlanetSideGUID): Unit = {
|
||||||
|
super.endCargoDismounting(carrierGuid)
|
||||||
|
val allSeatsUnoccupied = !vehicle.Seats.values.exists(_.isOccupied)
|
||||||
|
val otherTests = TestToStartSelfReporting()
|
||||||
|
if (allSeatsUnoccupied && otherTests) {
|
||||||
|
StartInteractionSelfReporting()
|
||||||
|
}
|
||||||
|
vehicle.Zone.GUID(carrierGuid) match {
|
||||||
|
case Some(v: Vehicle) => v.Actor ! IndependentZoneInteraction.SelfReportRunCheck
|
||||||
|
case _ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object VehicleControl {
|
object VehicleControl {
|
||||||
|
|
@ -779,7 +799,5 @@ object VehicleControl {
|
||||||
|
|
||||||
private case class Deletion()
|
private case class Deletion()
|
||||||
|
|
||||||
private case object RadiationTick
|
|
||||||
|
|
||||||
final case class AssignOwnership(player: Option[Player])
|
final case class AssignOwnership(player: Option[Player])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ package net.psforever.objects.vehicles.interaction
|
||||||
import net.psforever.objects.Vehicle
|
import net.psforever.objects.Vehicle
|
||||||
import net.psforever.objects.avatar.interaction.{ForceZoneProtection, InteractWithForceDomeProtection}
|
import net.psforever.objects.avatar.interaction.{ForceZoneProtection, InteractWithForceDomeProtection}
|
||||||
import net.psforever.objects.serverobject.dome.ForceDomePhysics
|
import net.psforever.objects.serverobject.dome.ForceDomePhysics
|
||||||
import net.psforever.objects.serverobject.mount.InteractWithForceDomeProtectionSeatedInEntity
|
import net.psforever.objects.serverobject.mount.interaction.InteractWithForceDomeProtectionSeatedInEntity
|
||||||
import net.psforever.objects.zones.InteractsWithZone
|
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||||
|
|
||||||
class InteractWithForceDomeProtectionSeatedInVehicle
|
class InteractWithForceDomeProtectionSeatedInVehicle
|
||||||
extends InteractWithForceDomeProtectionSeatedInEntity {
|
extends InteractWithForceDomeProtectionSeatedInEntity {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright (c) 2021 PSForever
|
// Copyright (c) 2021 PSForever
|
||||||
package net.psforever.objects.vehicles
|
package net.psforever.objects.vehicles.interaction
|
||||||
|
|
||||||
import net.psforever.objects.Vehicle
|
import net.psforever.objects.Vehicle
|
||||||
import net.psforever.objects.serverobject.mount.{InteractWithRadiationCloudsSeatedInEntity, RadiationInMountableInteraction}
|
import net.psforever.objects.serverobject.mount.interaction.{InteractWithRadiationCloudsSeatedInEntity, RadiationInMountableInteraction}
|
||||||
import net.psforever.objects.zones.blockmap.SectorPopulation
|
import net.psforever.objects.zones.blockmap.SectorPopulation
|
||||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||||
|
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
// Copyright (c) 2026 PSForever
|
||||||
|
package net.psforever.objects.zones.interaction
|
||||||
|
|
||||||
|
import akka.actor.{Actor, Cancellable}
|
||||||
|
import net.psforever.objects.Default
|
||||||
|
|
||||||
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
|
trait IndependentZoneInteraction {
|
||||||
|
_: Actor =>
|
||||||
|
/** ... */
|
||||||
|
private var zoneInteractionIntervalDefault: FiniteDuration = 250.milliseconds
|
||||||
|
/** ... */
|
||||||
|
private var zoneInteractionTimer: Cancellable = Default.Cancellable
|
||||||
|
|
||||||
|
def ZoneInteractionObject: InteractsWithZone
|
||||||
|
|
||||||
|
val zoneInteractionBehavior: Receive = {
|
||||||
|
case IndependentZoneInteraction.InteractionTick =>
|
||||||
|
PerformZoneInteractionSelfReporting()
|
||||||
|
|
||||||
|
case IndependentZoneInteraction.SelfReportRunCheck =>
|
||||||
|
PerformSelfReportRunCheck()
|
||||||
|
}
|
||||||
|
|
||||||
|
def ZoneInteractionInterval: FiniteDuration = zoneInteractionIntervalDefault
|
||||||
|
|
||||||
|
def ZoneInteractionInterval_=(interval: FiniteDuration): FiniteDuration = {
|
||||||
|
zoneInteractionIntervalDefault = interval
|
||||||
|
ZoneInteractionInterval
|
||||||
|
}
|
||||||
|
|
||||||
|
def TestToStartSelfReporting(): Boolean
|
||||||
|
|
||||||
|
def PerformZoneInteractionSelfReporting(): Unit = {
|
||||||
|
if (!zoneInteractionTimer.isCancelled) {
|
||||||
|
ZoneInteractionObject.zoneInteractions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def PerformSelfReportRunCheck(): Unit
|
||||||
|
|
||||||
|
final def StartInteractionSelfReporting(): Unit = {
|
||||||
|
org.log4s.getLogger("ZIT").info("starting timer")
|
||||||
|
zoneInteractionTimer.cancel()
|
||||||
|
zoneInteractionTimer = context.system.scheduler.scheduleWithFixedDelay(
|
||||||
|
0.seconds,
|
||||||
|
zoneInteractionIntervalDefault,
|
||||||
|
self,
|
||||||
|
IndependentZoneInteraction.InteractionTick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
final def StartInteractionSelfReporting(initialDelay: FiniteDuration): Unit = {
|
||||||
|
org.log4s.getLogger("ZIT").info("starting timer")
|
||||||
|
zoneInteractionTimer.cancel()
|
||||||
|
zoneInteractionTimer = context.system.scheduler.scheduleWithFixedDelay(
|
||||||
|
initialDelay,
|
||||||
|
zoneInteractionIntervalDefault,
|
||||||
|
self,
|
||||||
|
IndependentZoneInteraction.InteractionTick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
final def TryStopInteractionSelfReporting(): Boolean = {
|
||||||
|
if (!zoneInteractionTimer.isCancelled) {
|
||||||
|
ZoneInteractionObject.resetInteractions()
|
||||||
|
zoneInteractionTimer.cancel()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final def StopInteractionSelfReporting(): Boolean = {
|
||||||
|
ZoneInteractionObject.resetInteractions()
|
||||||
|
zoneInteractionTimer.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
final def StopInteractionSelfReportingNoReset(): Boolean = {
|
||||||
|
zoneInteractionTimer.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
final def ZoneInteractionSelfReportingIsRunning: Boolean = !zoneInteractionTimer.isCancelled
|
||||||
|
}
|
||||||
|
|
||||||
|
object IndependentZoneInteraction {
|
||||||
|
private case object InteractionTick
|
||||||
|
|
||||||
|
final case object SelfReportRunCheck
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue