mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-07-16 08:55:18 +00:00
attempted cleanup of previous test fire condition; division of turret callbacks between generic targets and vehicle targets; facility turret stops automatic fire when being mounted and resumes automatic mode when being dismounted
This commit is contained in:
parent
20b5de34ab
commit
3ffb817f4a
8 changed files with 192 additions and 76 deletions
|
|
@ -435,9 +435,14 @@ private[support] class WeaponAndProjectileOperations(
|
||||||
def handleAIDamage(pkt: AIDamage): Unit = {
|
def handleAIDamage(pkt: AIDamage): Unit = {
|
||||||
val AIDamage(targetGuid, attackerGuid, projectileTypeId, _, _) = pkt
|
val AIDamage(targetGuid, attackerGuid, projectileTypeId, _, _) = pkt
|
||||||
(continent.GUID(player.VehicleSeated) match {
|
(continent.GUID(player.VehicleSeated) match {
|
||||||
case Some(tobj: PlanetSideServerObject with FactionAffinity with Vitality) if tobj.GUID == targetGuid => Some(tobj)
|
case Some(tobj: PlanetSideServerObject with FactionAffinity with Vitality with OwnableByPlayer)
|
||||||
case _ if player.GUID == targetGuid => Some(player)
|
if tobj.GUID == targetGuid && tobj.OwnerGuid.contains(player.GUID) =>
|
||||||
case _ => None
|
Some(tobj)
|
||||||
|
case _
|
||||||
|
if player.GUID == targetGuid =>
|
||||||
|
Some(player)
|
||||||
|
case _ =>
|
||||||
|
None
|
||||||
}).foreach { target =>
|
}).foreach { target =>
|
||||||
sessionData.validObject(attackerGuid, decorator = "AIDamage/Attacker")
|
sessionData.validObject(attackerGuid, decorator = "AIDamage/Attacker")
|
||||||
.collect {
|
.collect {
|
||||||
|
|
|
||||||
|
|
@ -10057,7 +10057,8 @@ object GlobalDefinitions {
|
||||||
targetValidation = List(EffectTarget.Validation.MaxOnRadar, EffectTarget.Validation.VehiclesOnRadar),
|
targetValidation = List(EffectTarget.Validation.MaxOnRadar, EffectTarget.Validation.VehiclesOnRadar),
|
||||||
retaliatoryDuration = 8000L,
|
retaliatoryDuration = 8000L,
|
||||||
cylindricalCheck = true,
|
cylindricalCheck = true,
|
||||||
cylindricalHeight = 25f
|
cylindricalHeight = 25f,
|
||||||
|
detectionSpeed = 2.seconds
|
||||||
)
|
)
|
||||||
manned_turret.innateDamage = new DamageWithPosition {
|
manned_turret.innateDamage = new DamageWithPosition {
|
||||||
CausesDamageType = DamageType.One
|
CausesDamageType = DamageType.One
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,8 @@ class TurretControl(turret: TurretDeployable)
|
||||||
attacker =>
|
attacker =>
|
||||||
val channel = zone.id
|
val channel = zone.id
|
||||||
val guid = AutomatedTurretObject.GUID
|
val guid = AutomatedTurretObject.GUID
|
||||||
AutomatedTurretBehavior.startTrackingTargets(zone, channel, guid, List(attacker.GUID))
|
AutomatedTurretBehavior.startTracking(attacker, channel, guid, List(attacker.GUID))
|
||||||
AutomatedTurretBehavior.stopTrackingTargets(zone, channel, guid) //TODO delay by a few milliseconds?
|
AutomatedTurretBehavior.stopTracking(attacker, channel, guid) //TODO delay by a few milliseconds?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ class InteractWithTurrets()
|
||||||
def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit = {
|
def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit = {
|
||||||
target match {
|
target match {
|
||||||
case clarifiedTarget: AutomatedTurret.Target =>
|
case clarifiedTarget: AutomatedTurret.Target =>
|
||||||
val posxy = clarifiedTarget.Position.xy
|
val pos = clarifiedTarget.Position
|
||||||
val unique = SourceEntry(clarifiedTarget).unique
|
val unique = SourceEntry(clarifiedTarget).unique
|
||||||
val targets = getTurretTargets(sector, posxy).filter { turret => turret.Definition.AutoFire.nonEmpty && turret.Detected(unique).isEmpty }
|
val targets = getTurretTargets(sector, pos).filter { turret => turret.Definition.AutoFire.nonEmpty && turret.Detected(unique).isEmpty }
|
||||||
targets.foreach { t => t.Actor ! AutomatedTurretBehavior.Alert(clarifiedTarget) }
|
targets.foreach { t => t.Actor ! AutomatedTurretBehavior.Alert(clarifiedTarget) }
|
||||||
case _ => ()
|
case _ => ()
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ class InteractWithTurrets()
|
||||||
}
|
}
|
||||||
|
|
||||||
object InteractWithTurrets {
|
object InteractWithTurrets {
|
||||||
private val Range: Float = {
|
private lazy val Range: Float = {
|
||||||
Seq(
|
Seq(
|
||||||
GlobalDefinitions.spitfire_turret,
|
GlobalDefinitions.spitfire_turret,
|
||||||
GlobalDefinitions.spitfire_cloaked,
|
GlobalDefinitions.spitfire_cloaked,
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,8 @@ object EffectTarget {
|
||||||
!target.Destroyed && (target match {
|
!target.Destroyed && (target match {
|
||||||
case v: Vehicle =>
|
case v: Vehicle =>
|
||||||
val vdef = v.Definition
|
val vdef = v.Definition
|
||||||
!(v.Cloaked ||
|
!(v.MountedIn.nonEmpty ||
|
||||||
|
v.Cloaked ||
|
||||||
GlobalDefinitions.isAtvVehicle(vdef) ||
|
GlobalDefinitions.isAtvVehicle(vdef) ||
|
||||||
vdef == GlobalDefinitions.two_man_assault_buggy ||
|
vdef == GlobalDefinitions.two_man_assault_buggy ||
|
||||||
vdef == GlobalDefinitions.skyguard)
|
vdef == GlobalDefinitions.skyguard)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) 2023 PSForever
|
// Copyright (c) 2023 PSForever
|
||||||
package net.psforever.objects.serverobject.turret
|
package net.psforever.objects.serverobject.turret
|
||||||
|
|
||||||
import akka.actor.{Actor, Cancellable}
|
import akka.actor.{Actor, ActorRef, Cancellable}
|
||||||
import net.psforever.objects.definition.ObjectDefinition
|
import net.psforever.objects.definition.ObjectDefinition
|
||||||
import net.psforever.objects.{Default, Player, Vehicle}
|
import net.psforever.objects.{Default, Player, Vehicle}
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||||
|
|
@ -10,8 +10,11 @@ import net.psforever.objects.sourcing.{SourceEntry, SourceUniqueness}
|
||||||
import net.psforever.objects.vital.Vitality
|
import net.psforever.objects.vital.Vitality
|
||||||
import net.psforever.objects.vital.interaction.DamageResult
|
import net.psforever.objects.vital.interaction.DamageResult
|
||||||
import net.psforever.objects.zones.{InteractsWithZone, Zone}
|
import net.psforever.objects.zones.{InteractsWithZone, Zone}
|
||||||
|
import net.psforever.packet.PlanetSideGamePacket
|
||||||
import net.psforever.packet.game.{ChangeFireStateMessage_Start, ChangeFireStateMessage_Stop, ObjectDetectedMessage}
|
import net.psforever.packet.game.{ChangeFireStateMessage_Start, ChangeFireStateMessage_Stop, ObjectDetectedMessage}
|
||||||
|
import net.psforever.services.Service
|
||||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||||
|
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||||
import net.psforever.types.{PlanetSideGUID, Vector3}
|
import net.psforever.types.{PlanetSideGUID, Vector3}
|
||||||
|
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
|
|
@ -85,6 +88,8 @@ trait AutomatedTurretBehavior {
|
||||||
|
|
||||||
private lazy val autoStats: Option[Automation] = AutomatedTurretObject.Definition.AutoFire
|
private lazy val autoStats: Option[Automation] = AutomatedTurretObject.Definition.AutoFire
|
||||||
|
|
||||||
|
private var previousTestedTargets: Set[Target] = Set()
|
||||||
|
|
||||||
def AutomatedTurretObject: AutomatedTurret
|
def AutomatedTurretObject: AutomatedTurret
|
||||||
|
|
||||||
val automatedTurretBehavior: Actor.Receive = if (autoStats.isDefined) {
|
val automatedTurretBehavior: Actor.Receive = if (autoStats.isDefined) {
|
||||||
|
|
@ -127,6 +132,13 @@ trait AutomatedTurretBehavior {
|
||||||
|
|
||||||
protected def AutomaticOperationFunctionalityChecks: Boolean
|
protected def AutomaticOperationFunctionalityChecks: Boolean
|
||||||
|
|
||||||
|
protected def CurrentTargetLastShotReported: Long = currentTargetLastShotReported
|
||||||
|
|
||||||
|
protected def CurrentTargetLastShotReported_=(value: Long): Long = {
|
||||||
|
currentTargetLastShotReported = value
|
||||||
|
CurrentTargetLastShotReported
|
||||||
|
}
|
||||||
|
|
||||||
private def bringAttentionToTarget(target: Target): Unit = {
|
private def bringAttentionToTarget(target: Target): Unit = {
|
||||||
val targets = AutomatedTurretObject.Targets
|
val targets = AutomatedTurretObject.Targets
|
||||||
val size = targets.size
|
val size = targets.size
|
||||||
|
|
@ -140,12 +152,12 @@ trait AutomatedTurretBehavior {
|
||||||
|
|
||||||
private def confirmShot(target: Target): Unit = {
|
private def confirmShot(target: Target): Unit = {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
if (currentTargetToken.isEmpty || now - currentTargetLastShotReported > autoStats.map { _.targetSelectCooldown }.get) {
|
if (currentTargetToken.isEmpty) {
|
||||||
currentTargetLastShotReported = now
|
currentTargetLastShotReported = now
|
||||||
engageNewDetectedTarget(target)
|
engageNewDetectedTarget(target)
|
||||||
} else if (
|
} else if (
|
||||||
currentTargetToken.contains(SourceEntry(target).unique) &&
|
currentTargetToken.contains(SourceEntry(target).unique) &&
|
||||||
now - currentTargetLastShotReported < autoStats.map { _.missedShotCooldown }.get) {
|
now - currentTargetLastShotReported < autoStats.map(_.missedShotCooldown).getOrElse(0L)) {
|
||||||
currentTargetLastShotReported = now
|
currentTargetLastShotReported = now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -165,27 +177,24 @@ trait AutomatedTurretBehavior {
|
||||||
}
|
}
|
||||||
|
|
||||||
private def resetAlerts(): Unit = {
|
private def resetAlerts(): Unit = {
|
||||||
AutomatedTurretObject.Target.foreach { noLongerEngageDetectedTarget }
|
AutomatedTurretObject.Target.foreach(noLongerEngageDetectedTarget)
|
||||||
|
AutomatedTurretObject.Target = None
|
||||||
AutomatedTurretObject.Clear()
|
AutomatedTurretObject.Clear()
|
||||||
testTargetListQualifications(beforeSize = 1)
|
testTargetListQualifications(beforeSize = 1)
|
||||||
}
|
previousTestedTargets.foreach(noLongerEngageTestedTarget)
|
||||||
|
previousTestedTargets = Set()
|
||||||
private def testNewDetectedTarget(target: Target, channel: String): Unit = {
|
currentTargetToken = None
|
||||||
val zone = target.Zone
|
|
||||||
AutomatedTurretBehavior.startTrackingTargets(zone, channel, AutomatedTurretObject.GUID, List(target.GUID))
|
|
||||||
AutomatedTurretBehavior.startShooting(zone, channel, AutomatedTurretObject.Weapons.values.head.Equipment.get.GUID)
|
|
||||||
context.system.scheduler.scheduleOnce(100.milliseconds, (() => {
|
|
||||||
AutomatedTurretBehavior.stopShooting(zone, channel, AutomatedTurretObject.Weapons.values.head.Equipment.get.GUID)
|
|
||||||
}).asInstanceOf[Runnable])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected def engageNewDetectedTarget(target: Target): Unit = {
|
protected def engageNewDetectedTarget(target: Target): Unit = {
|
||||||
val zone = target.Zone
|
val zone = target.Zone
|
||||||
val zoneid = zone.id
|
val zoneid = zone.id
|
||||||
AutomatedTurretObject.Target = target
|
previousTestedTargets.filterNot(_ == target).foreach(noLongerEngageTestedTarget)
|
||||||
|
previousTestedTargets = Set(target)
|
||||||
currentTargetToken = Some(SourceEntry(target).unique)
|
currentTargetToken = Some(SourceEntry(target).unique)
|
||||||
AutomatedTurretBehavior.startTrackingTargets(zone, zoneid, AutomatedTurretObject.GUID, List(target.GUID))
|
AutomatedTurretObject.Target = target
|
||||||
AutomatedTurretBehavior.startShooting(zone, zoneid, AutomatedTurretObject.Weapons.values.head.Equipment.get.GUID)
|
AutomatedTurretBehavior.startTracking(target, zoneid, AutomatedTurretObject.GUID, List(target.GUID))
|
||||||
|
AutomatedTurretBehavior.startShooting(target, zoneid, AutomatedTurretObject.Weapons.values.head.Equipment.get.GUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected def noLongerDetectTargetIfCurrent(target: Target): Option[Target] = {
|
protected def noLongerDetectTargetIfCurrent(target: Target): Option[Target] = {
|
||||||
|
|
@ -197,22 +206,30 @@ trait AutomatedTurretBehavior {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected def noLongerEngageDetectedTarget(target: Target): Option[Target] = {
|
protected def noLongerEngageDetectedTarget(target: Target): Option[Target] = {
|
||||||
val zone = target.Zone
|
|
||||||
val zoneid = zone.id
|
|
||||||
AutomatedTurretObject.Target = None
|
AutomatedTurretObject.Target = None
|
||||||
currentTargetToken = None
|
currentTargetToken = None
|
||||||
AutomatedTurretBehavior.stopTrackingTargets(zone, zoneid, AutomatedTurretObject.GUID)
|
noLongerEngageTestedTarget(target)
|
||||||
AutomatedTurretBehavior.stopShooting(zone, zoneid, AutomatedTurretObject.Weapons.values.head.Equipment.get.GUID)
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
private def noLongerEngageTestedTarget(target: Target): Option[Target] = {
|
||||||
|
val zone = target.Zone
|
||||||
|
val zoneid = zone.id
|
||||||
|
AutomatedTurretBehavior.stopTracking(target, zoneid, AutomatedTurretObject.GUID)
|
||||||
|
AutomatedTurretBehavior.stopShooting(target, zoneid, AutomatedTurretObject.Weapons.values.head.Equipment.get.GUID)
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
protected def trySelectNewTarget(): Option[Target] = {
|
protected def trySelectNewTarget(): Option[Target] = {
|
||||||
AutomatedTurretObject.Target.orElse {
|
AutomatedTurretObject.Target.orElse {
|
||||||
val turretPosition = AutomatedTurretObject.Position
|
val turretPosition = AutomatedTurretObject.Position
|
||||||
|
val turretGuid = AutomatedTurretObject.GUID
|
||||||
|
val weaponGuid = AutomatedTurretObject.Weapons.values.head.Equipment.get.GUID
|
||||||
val radius = autoStats.get.targetTriggerRange
|
val radius = autoStats.get.targetTriggerRange
|
||||||
val validation = autoStats.get.targetValidation
|
val validation = autoStats.get.targetValidation
|
||||||
val faction = AutomatedTurretObject.Faction
|
val faction = AutomatedTurretObject.Faction
|
||||||
AutomatedTurretObject
|
//noinspection CollectHeadOption
|
||||||
|
val (targets, forValidation) = AutomatedTurretObject
|
||||||
.Targets
|
.Targets
|
||||||
.collect { case target
|
.collect { case target
|
||||||
if /*target.Faction != faction &&*/
|
if /*target.Faction != faction &&*/
|
||||||
|
|
@ -221,18 +238,29 @@ trait AutomatedTurretBehavior {
|
||||||
target
|
target
|
||||||
}
|
}
|
||||||
.sortBy(target => Vector3.DistanceSquared(target.Position, turretPosition))
|
.sortBy(target => Vector3.DistanceSquared(target.Position, turretPosition))
|
||||||
.collectFirst {
|
.collect {
|
||||||
case target: Player =>
|
case target: Player =>
|
||||||
testNewDetectedTarget(target, target.Name)
|
AutomatedTurretBehavior.Generic.testNewDetected(target, target.Name, turretGuid, weaponGuid)
|
||||||
target
|
Seq((target, target))
|
||||||
case target: Vehicle =>
|
case target: Vehicle =>
|
||||||
target.Seats.values
|
target.Seats.values
|
||||||
.flatMap(_.occupants)
|
.flatMap(_.occupants)
|
||||||
.foreach { target =>
|
.collectFirst { passenger =>
|
||||||
testNewDetectedTarget(target, target.Name)
|
AutomatedTurretBehavior.Generic.testNewDetected(passenger, passenger.Name, turretGuid, weaponGuid)
|
||||||
|
(target, passenger)
|
||||||
}
|
}
|
||||||
target
|
|
||||||
}
|
}
|
||||||
|
.flatten
|
||||||
|
.unzip
|
||||||
|
//call an explicit stop for these targets
|
||||||
|
(for {
|
||||||
|
a <- forValidation
|
||||||
|
b <- previousTestedTargets
|
||||||
|
if SourceEntry(a).unique != SourceEntry(b).unique
|
||||||
|
} yield b)
|
||||||
|
.foreach(noLongerEngageTestedTarget)
|
||||||
|
previousTestedTargets = forValidation.toSet
|
||||||
|
targets.headOption
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,7 +302,7 @@ trait AutomatedTurretBehavior {
|
||||||
}
|
}
|
||||||
.orElse {
|
.orElse {
|
||||||
//no target; unless we are deactivated or have any unfinished delays, search for new target
|
//no target; unless we are deactivated or have any unfinished delays, search for new target
|
||||||
if (automaticOperation && now - currentTargetLastShotReported >= selectDelay) {
|
if (automaticOperation && now - currentTargetLastShotReported >= 0) {
|
||||||
trySelectNewTarget()
|
trySelectNewTarget()
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
@ -291,17 +319,17 @@ trait AutomatedTurretBehavior {
|
||||||
if (target.Destroyed) {
|
if (target.Destroyed) {
|
||||||
//if the target died while we were shooting at it
|
//if the target died while we were shooting at it
|
||||||
noLongerEngageDetectedTarget(target)
|
noLongerEngageDetectedTarget(target)
|
||||||
currentTargetLastShotReported = now - eliminationDelay
|
currentTargetLastShotReported = now + eliminationDelay
|
||||||
None
|
None
|
||||||
} else if (AutomatedTurretBehavior.shapedDistanceCheckAgainstValue(autoStats, target.Position, AutomatedTurretObject.Position, escapeRange)) {
|
} else if (AutomatedTurretBehavior.shapedDistanceCheckAgainstValue(autoStats, target.Position, AutomatedTurretObject.Position, escapeRange)) {
|
||||||
//if the target made sufficient distance from the turret
|
//if the target made sufficient distance from the turret
|
||||||
noLongerEngageDetectedTarget(target)
|
noLongerEngageDetectedTarget(target)
|
||||||
currentTargetLastShotReported = now - cooldownDelay
|
currentTargetLastShotReported = now + cooldownDelay
|
||||||
None
|
None
|
||||||
} else if (now - currentTargetLastShotReported >= cooldownDelay) {
|
} else if (now - currentTargetLastShotReported >= cooldownDelay) {
|
||||||
//if the target goes mia through lack of response
|
//if the target goes mia through lack of response
|
||||||
noLongerEngageDetectedTarget(target)
|
noLongerEngageDetectedTarget(target)
|
||||||
currentTargetLastShotReported = now - selectDelay
|
currentTargetLastShotReported = now + selectDelay
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
//continue shooting
|
//continue shooting
|
||||||
|
|
@ -377,32 +405,105 @@ object AutomatedTurretBehavior {
|
||||||
|
|
||||||
private case object PeriodicCheck
|
private case object PeriodicCheck
|
||||||
|
|
||||||
def startTrackingTargets(zone: Zone, channel: String, guid: PlanetSideGUID, list: List[PlanetSideGUID]): Unit = {
|
trait AutomatedTurretDispatch {
|
||||||
zone.LocalEvents ! LocalServiceMessage(
|
private val noTargets :List[PlanetSideGUID] = List(Service.defaultPlayerGUID)
|
||||||
channel,
|
|
||||||
LocalAction.SendResponse(ObjectDetectedMessage(guid, guid, 0, list))
|
def getEventBus(target: Target): ActorRef
|
||||||
)
|
|
||||||
|
def composeMessageEnvelope(channel: String, msg: PlanetSideGamePacket): Any
|
||||||
|
|
||||||
|
def startTracking(target: Target, channel: String, turretGuid: PlanetSideGUID, list: List[PlanetSideGUID]): Unit = {
|
||||||
|
getEventBus(target) ! composeMessageEnvelope(channel, startTrackingMsg(turretGuid, list))
|
||||||
|
}
|
||||||
|
|
||||||
|
def stopTracking(target: Target, channel: String, turretGuid: PlanetSideGUID): Unit = {
|
||||||
|
getEventBus(target) ! composeMessageEnvelope(channel, stopTrackingMsg(turretGuid))
|
||||||
|
}
|
||||||
|
|
||||||
|
def startShooting(target: Target, channel: String, weaponGuid: PlanetSideGUID): Unit = {
|
||||||
|
getEventBus(target) ! composeMessageEnvelope(channel, startShootingMsg(weaponGuid))
|
||||||
|
}
|
||||||
|
|
||||||
|
def stopShooting(target: Target, channel: String, weaponGuid: PlanetSideGUID): Unit = {
|
||||||
|
getEventBus(target) ! composeMessageEnvelope(channel, stopShootingMsg(weaponGuid))
|
||||||
|
}
|
||||||
|
|
||||||
|
def testNewDetected(target: Target, channel: String, turretGuid: PlanetSideGUID, weaponGuid: PlanetSideGUID): Unit = {
|
||||||
|
startTracking(target, channel, turretGuid, List(target.GUID))
|
||||||
|
startShooting(target, channel, weaponGuid)
|
||||||
|
stopShooting(target, channel, weaponGuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def startTrackingMsg(guid: PlanetSideGUID, list: List[PlanetSideGUID]): PlanetSideGamePacket = {
|
||||||
|
ObjectDetectedMessage(guid, guid, 0, list)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def stopTrackingMsg(turretGuid: PlanetSideGUID): PlanetSideGamePacket = {
|
||||||
|
ObjectDetectedMessage(turretGuid, turretGuid, 0, noTargets)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def startShootingMsg(weaponGuid: PlanetSideGUID): PlanetSideGamePacket = {
|
||||||
|
ChangeFireStateMessage_Start(weaponGuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def stopShootingMsg(weaponGuid: PlanetSideGUID): PlanetSideGamePacket = {
|
||||||
|
ChangeFireStateMessage_Stop(weaponGuid)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def stopTrackingTargets(zone: Zone, channel: String, guid: PlanetSideGUID): Unit = {
|
object Generic extends AutomatedTurretDispatch {
|
||||||
zone.LocalEvents ! LocalServiceMessage(
|
def getEventBus(target: Target): ActorRef = {
|
||||||
channel,
|
target.Zone.LocalEvents
|
||||||
LocalAction.SendResponse(ObjectDetectedMessage(guid, guid, 0, List(PlanetSideGUID(0))))
|
}
|
||||||
)
|
|
||||||
|
def composeMessageEnvelope(channel: String, msg: PlanetSideGamePacket): Any = {
|
||||||
|
LocalServiceMessage(channel, LocalAction.SendResponse(msg))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def startShooting(zone: Zone, channel: String, weaponGuid: PlanetSideGUID): Unit = {
|
object Vehicle extends AutomatedTurretDispatch {
|
||||||
zone.LocalEvents ! LocalServiceMessage(
|
def getEventBus(target: Target): ActorRef = {
|
||||||
channel,
|
target.Zone.VehicleEvents
|
||||||
LocalAction.SendResponse(ChangeFireStateMessage_Start(weaponGuid))
|
}
|
||||||
)
|
|
||||||
|
def composeMessageEnvelope(channel: String, msg: PlanetSideGamePacket): Any = {
|
||||||
|
VehicleServiceMessage(channel, VehicleAction.SendResponse(Service.defaultPlayerGUID, msg))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def stopShooting(zone: Zone, channel: String, weaponGuid: PlanetSideGUID): Unit = {
|
def startTracking(target: Target, channel: String, turretGuid: PlanetSideGUID, list: List[PlanetSideGUID]): Unit = {
|
||||||
zone.LocalEvents ! LocalServiceMessage(
|
target match {
|
||||||
channel,
|
case v: Vehicle => Vehicle.startTracking(v, channel, turretGuid, list)
|
||||||
LocalAction.SendResponse(ChangeFireStateMessage_Stop(weaponGuid))
|
case _ => Generic.startTracking(target, channel, turretGuid, list)
|
||||||
)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def stopTracking(target: Target, channel: String, turretGuid: PlanetSideGUID): Unit = {
|
||||||
|
target match {
|
||||||
|
case v: Vehicle => Vehicle.stopTracking(v, channel, turretGuid)
|
||||||
|
case _ => Generic.stopTracking(target, channel, turretGuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def startShooting(target: Target, channel: String, weaponGuid: PlanetSideGUID): Unit = {
|
||||||
|
target match {
|
||||||
|
case v: Vehicle => Vehicle.startShooting(v, channel, weaponGuid)
|
||||||
|
case _ => Generic.startShooting(target, channel, weaponGuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def stopShooting(target: Target, channel: String, weaponGuid: PlanetSideGUID): Unit = {
|
||||||
|
target match {
|
||||||
|
case v: Vehicle => Vehicle.stopShooting(v, channel, weaponGuid)
|
||||||
|
case _ => Generic.stopShooting(target, channel, weaponGuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def testNewDetected(target: Target, channel: String, turretGuid: PlanetSideGUID, weaponGuid: PlanetSideGUID): Unit = {
|
||||||
|
target match {
|
||||||
|
case v: Vehicle => Vehicle.testNewDetected(v, channel, turretGuid, weaponGuid)
|
||||||
|
case _ => Generic.testNewDetected(target, channel, turretGuid, weaponGuid)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getAttackerFromCause(zone: Zone, cause: DamageResult): Option[PlanetSideServerObject with Vitality] = {
|
def getAttackerFromCause(zone: Zone, cause: DamageResult): Option[PlanetSideServerObject with Vitality] = {
|
||||||
|
|
@ -445,7 +546,7 @@ object AutomatedTurretBehavior {
|
||||||
position: Vector3,
|
position: Vector3,
|
||||||
testPosition: Vector3,
|
testPosition: Vector3,
|
||||||
testRange: Float,
|
testRange: Float,
|
||||||
result: Int = 1 //by default, calculation > testRange^2
|
result: Int = 1 //by default, calculation > input
|
||||||
): Boolean = {
|
): Boolean = {
|
||||||
val testRangeSq = testRange * testRange
|
val testRangeSq = testRange * testRange
|
||||||
if (stats.exists(_.cylindricalCheck)) {
|
if (stats.exists(_.cylindricalCheck)) {
|
||||||
|
|
|
||||||
|
|
@ -92,19 +92,24 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def tryMount(obj: PlanetSideServerObject with Mountable, seatNumber: Int, player: Player): Boolean = {
|
override protected def tryMount(obj: PlanetSideServerObject with Mountable, seatNumber: Int, player: Player): Boolean = {
|
||||||
val result = super.tryMount(obj, seatNumber, player)
|
AutomaticOperation = false //turn off
|
||||||
if (result) {
|
if (!super.tryMount(obj, seatNumber, player)) {
|
||||||
AutomaticOperation = false
|
AutomaticOperation = AutomaticOperationFunctionalityChecks //revert?
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
}
|
}
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def tryDismount(obj: Mountable, seatNumber: Int, player: Player, bailType: BailType.Value): Boolean = {
|
override protected def tryDismount(obj: Mountable, seatNumber: Int, player: Player, bailType: BailType.Value): Boolean = {
|
||||||
val result = super.tryDismount(obj, seatNumber, player, bailType)
|
AutomaticOperation = AutomaticOperationFunctionalityChecksExceptMounting //turn on, if can turn on
|
||||||
if (result) {
|
if (!super.tryDismount(obj, seatNumber, player, bailType)) {
|
||||||
AutomaticOperation = AutomaticOperationFunctionalityChecks
|
AutomaticOperation = false //revert
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
CurrentTargetLastShotReported = System.currentTimeMillis() + 4000L
|
||||||
|
true
|
||||||
}
|
}
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def DamageAwareness(target: Damageable.Target, cause: DamageResult, amount: Any) : Unit = {
|
override protected def DamageAwareness(target: Damageable.Target, cause: DamageResult, amount: Any) : Unit = {
|
||||||
|
|
@ -173,10 +178,13 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected def AutomaticOperationFunctionalityChecks: Boolean = {
|
protected def AutomaticOperationFunctionalityChecks: Boolean = {
|
||||||
|
AutomaticOperationFunctionalityChecksExceptMounting && !TurretObject.Seats.values.exists(_.isOccupied)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected def AutomaticOperationFunctionalityChecksExceptMounting: Boolean = {
|
||||||
isPowered &&
|
isPowered &&
|
||||||
!JammableObject.Jammed &&
|
!JammableObject.Jammed &&
|
||||||
TurretObject.Health > TurretObject.Definition.DamageDisablesAt &&
|
TurretObject.Health > TurretObject.Definition.DamageDisablesAt
|
||||||
!TurretObject.Seats.values.exists(_.isOccupied)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def primaryWeaponFireModeOnly(): Unit = {
|
private def primaryWeaponFireModeOnly(): Unit = {
|
||||||
|
|
@ -224,8 +232,8 @@ class FacilityTurretControl(turret: FacilityTurret)
|
||||||
attacker =>
|
attacker =>
|
||||||
val channel = zone.id
|
val channel = zone.id
|
||||||
val guid = AutomatedTurretObject.GUID
|
val guid = AutomatedTurretObject.GUID
|
||||||
AutomatedTurretBehavior.startTrackingTargets(zone, channel, guid, List(attacker.GUID))
|
AutomatedTurretBehavior.startTracking(attacker, channel, guid, List(attacker.GUID))
|
||||||
AutomatedTurretBehavior.stopTrackingTargets(zone, channel, guid) //TODO delay by a few milliseconds?
|
AutomatedTurretBehavior.stopTracking(attacker, channel, guid) //TODO delay by a few milliseconds?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ final case class Automation(
|
||||||
targetEliminationCooldown: Long = 0L, //ms
|
targetEliminationCooldown: Long = 0L, //ms
|
||||||
revertToDefaultFireMode: Boolean = true
|
revertToDefaultFireMode: Boolean = true
|
||||||
) {
|
) {
|
||||||
assert(targetDetectionRange > targetTriggerRange, "trigger range must be less or equal to detection range")
|
assert(targetDetectionRange > targetTriggerRange, "trigger range must be less than detection range")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue