diff --git a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index fba84867d..6c35ba60e 100644 --- a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -9081,9 +9081,9 @@ object GlobalDefinitions { ), AutoChecks( validation = List( - EffectTarget.Validation.PlayerDetectedBySpitfireTurret, - EffectTarget.Validation.GroundVehicleDetectedByAutoTurret, - EffectTarget.Validation.AircraftDetectedByAutoTurret + EffectTarget.Validation.SmallRoboticsTurretValidatePlayerTarget, + EffectTarget.Validation.SmallRoboticsTurretValidateGroundVehicleTarget, + EffectTarget.Validation.SmallRoboticsTurretValidateAircraftTarget ) ), retaliatoryDelay = 2000L, //8000L @@ -9123,9 +9123,9 @@ object GlobalDefinitions { ), AutoChecks( validation = List( - EffectTarget.Validation.PlayerDetectedBySpitfireTurret, - EffectTarget.Validation.GroundVehicleDetectedByAutoTurret, - EffectTarget.Validation.AircraftDetectedByAutoTurret + EffectTarget.Validation.SmallRoboticsTurretValidatePlayerTarget, + EffectTarget.Validation.SmallRoboticsTurretValidateGroundVehicleTarget, + EffectTarget.Validation.SmallRoboticsTurretValidateAircraftTarget ) ), cooldowns = AutoCooldowns( @@ -9170,7 +9170,7 @@ object GlobalDefinitions { escape = 200f ), AutoChecks( - validation = List(EffectTarget.Validation.AircraftDetectedByAutoTurret) + validation = List(EffectTarget.Validation.SmallRoboticsTurretValidateAircraftTarget) ), retaliatoryDelay = 2000L, //8000L retaliationOverridesTarget = false, @@ -10066,7 +10066,7 @@ object GlobalDefinitions { manned_turret.Name = "manned_turret" manned_turret.MaxHealth = 3600 manned_turret.Damageable = true - manned_turret.DamageDisablesAt = 0 + manned_turret.DamageDisablesAt = 1800 manned_turret.Repairable = true manned_turret.autoRepair = AutoRepairStats(1.0909f, 10000, 1600, 0.05f) manned_turret.RepairIfDestroyed = true @@ -10087,9 +10087,9 @@ object GlobalDefinitions { ), AutoChecks( validation = List( - EffectTarget.Validation.MaxDetectedByAutoTurret, - EffectTarget.Validation.GroundVehicleDetectedByAutoTurret, - EffectTarget.Validation.AircraftDetectedByAutoTurret + EffectTarget.Validation.FacilityTurretValidateMaxTarget, + EffectTarget.Validation.FacilityTurretValidateGroundVehicleTarget, + EffectTarget.Validation.FacilityTurretValidateAircraftTarget ) ), retaliatoryDelay = 4000L, //8000L diff --git a/src/main/scala/net/psforever/objects/TurretDeployable.scala b/src/main/scala/net/psforever/objects/TurretDeployable.scala index d57dd98b1..852f2d4c1 100644 --- a/src/main/scala/net/psforever/objects/TurretDeployable.scala +++ b/src/main/scala/net/psforever/objects/TurretDeployable.scala @@ -12,7 +12,7 @@ import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior import net.psforever.objects.serverobject.damage.Damageable.Target import net.psforever.objects.serverobject.hackable.Hackable import net.psforever.objects.serverobject.mount.Mountable -import net.psforever.objects.serverobject.turret.auto.{AutomatedTurret, AutomatedTurretBehavior} +import net.psforever.objects.serverobject.turret.auto.{AffectedByAutomaticTurretFire, AutomatedTurret, AutomatedTurretBehavior} import net.psforever.objects.serverobject.turret.{MountableTurretControl, TurretDefinition, WeaponTurret} import net.psforever.objects.sourcing.{PlayerSource, SourceEntry} import net.psforever.objects.vital.damage.DamageCalculations @@ -75,7 +75,8 @@ class TurretControl(turret: TurretDeployable) with DeployableBehavior with FactionAffinityBehavior.Check with MountableTurretControl - with AutomatedTurretBehavior { + with AutomatedTurretBehavior + with AffectedByAutomaticTurretFire { def TurretObject: TurretDeployable = turret def DeployableObject: TurretDeployable = turret def MountableObject: TurretDeployable = turret @@ -84,6 +85,7 @@ class TurretControl(turret: TurretDeployable) def DamageableObject: TurretDeployable = turret def RepairableObject: TurretDeployable = turret def AutomatedTurretObject: TurretDeployable = turret + def AffectedObject: TurretDeployable = turret override def postStop(): Unit = { super.postStop() @@ -98,6 +100,7 @@ class TurretControl(turret: TurretDeployable) .orElse(checkBehavior) .orElse(mountBehavior) .orElse(automatedTurretBehavior) + .orElse(takeAutomatedDamage) .orElse { case _ => () } @@ -141,7 +144,7 @@ class TurretControl(turret: TurretDeployable) override protected def DestructionAwareness(target: Target, cause: DamageResult): Unit = { AutomaticOperation = false - //super.DestructionAwareness(target, cause) + super.DestructionAwareness(target, cause) CancelJammeredSound(target) CancelJammeredStatus(target) Deployables.AnnounceDestroyDeployable(turret, None) diff --git a/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala b/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala index db25de38a..9c949ef58 100644 --- a/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala +++ b/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala @@ -189,9 +189,10 @@ object EffectTarget { false } - def PlayerDetectedBySpitfireTurret(target: PlanetSideGameObject): Boolean = - !target.Destroyed && (target match { - case p: Player => + def SmallRoboticsTurretValidatePlayerTarget(target: PlanetSideGameObject): Boolean = + target match { + case p: Player + if p.ExoSuit != ExoSuitType.MAX && p.VehicleSeated.isEmpty => val now = System.currentTimeMillis() val pos = p.Position val faction = p.Faction @@ -206,17 +207,51 @@ object EffectTarget { } .exists(_ < 2000L) lazy val silentRunActive = p.avatar.implants.flatten.find(a => a.definition.implantType == ImplantType.SilentRun).exists(_.active) - lazy val movingFast = p.isMoving(test = 17d) || p.Jumping - p.VehicleSeated.isEmpty && - (if (radarCloakedAms(sector, pos) || radarCloakedAegis(sector, pos)) false - else if (radarCloakedSensor(sector, pos, faction)) tookDamage || usedEquipment - else if (radarEnhancedInterlink(sector, pos, faction) || radarEnhancedSensor(sector, pos, faction)) true - else tookDamage || usedEquipment || !silentRunActive && movingFast) + lazy val cloakedByInfiltrationSuit = p.ExoSuit == ExoSuitType.Infiltration && p.Cloaked + lazy val movingFast = p.isMoving(test = 17d) + if (radarCloakedAms(sector, pos) || radarCloakedAegis(sector, pos)) false + else if (radarCloakedSensor(sector, pos, faction)) tookDamage || usedEquipment + else if (radarEnhancedInterlink(sector, pos, faction) || radarEnhancedSensor(sector, pos, faction)) true + else tookDamage || usedEquipment || p.Jumping || (cloakedByInfiltrationSuit || !silentRunActive) && movingFast case _ => false - }) + } - def PlayerUndetectedByAutoTurret(target: PlanetSideGameObject): Boolean = + def SmallRoboticsTurretValidateMaxTarget(target: PlanetSideGameObject): Boolean = + target match { + case p: Player + if p.ExoSuit == ExoSuitType.MAX && p.VehicleSeated.isEmpty => + val now = System.currentTimeMillis() + val pos = p.Position + val faction = p.Faction + val sector = p.Zone.blockMap.sector(p.Position, range = 51f) + lazy val tookDamage = p.LastDamage.exists(dam => dam.adversarial.nonEmpty && now - dam.interaction.hitTime < 2000L) + lazy val usedEquipment = p.Holsters().flatMap(_.Equipment) + .collect { case t: Tool => now - t.LastDischarge } + .exists(_ < 2000L) + if (radarCloakedAms(sector, pos) || radarCloakedAegis(sector, pos)) false + else if (radarCloakedSensor(sector, pos, faction)) tookDamage || usedEquipment + else true + case _ => + false + } + + def FacilityTurretValidateMaxTarget(target: PlanetSideGameObject): Boolean = + target match { + case p: Player + if p.ExoSuit == ExoSuitType.MAX && p.VehicleSeated.isEmpty => + val pos = p.Position + val faction = p.Faction + val sector = p.Zone.blockMap.sector(p.Position, range = 51f) + !(radarCloakedAms(sector, pos) || + radarCloakedAegis(sector, pos) || + radarCloakedSensor(sector, pos, faction)) && + p.isMoving(test = 17d) + case _ => + false + } + + def AutoTurretBlankPlayerTarget(target: PlanetSideGameObject): Boolean = target match { case p: Player => val pos = p.Position @@ -226,38 +261,42 @@ object EffectTarget { false } - def MaxDetectedByAutoTurret(target: PlanetSideGameObject): Boolean = - !target.Destroyed && (target match { - case p: Player => - val now = System.currentTimeMillis() - val pos = p.Position - val faction = p.Faction - val sector = p.Zone.blockMap.sector(p.Position, range = 51f) - lazy val tookDamage = p.LastDamage.exists(dam => dam.adversarial.nonEmpty && now - dam.interaction.hitTime < 2000L) - lazy val usedEquipment = p.Holsters().flatMap(_.Equipment) - .collect { case t: Tool => now - t.LastDischarge } - .exists(_ < 2000L) - lazy val movingFast = p.isMoving(test = 17d) - p.ExoSuit == ExoSuitType.MAX && - p.VehicleSeated.isEmpty && - (if (radarCloakedAms(sector, pos) || radarCloakedAegis(sector, pos)) false - else if (radarCloakedSensor(sector, pos, faction)) tookDamage || usedEquipment - else if (radarEnhancedInterlink(sector, pos, faction) || radarEnhancedSensor(sector, pos, faction)) true - else tookDamage || usedEquipment || movingFast) - case _ => - false - }) - - def GroundVehicleDetectedByAutoTurret(target: PlanetSideGameObject): Boolean = - !target.Destroyed && (target match { - case v: Vehicle => + def SmallRoboticsTurretValidateGroundVehicleTarget(target: PlanetSideGameObject): Boolean = + target match { + case v: Vehicle + if v.MountedIn.isEmpty => val now = System.currentTimeMillis() val vdef = v.Definition lazy val tookDamage = v.LastDamage.exists(dam => dam.adversarial.nonEmpty && now - dam.interaction.hitTime< 2000L) lazy val usedEquipment = v.Weapons.values.flatMap(_.Equipment) .collect { case t: Tool => now - t.LastDischarge } .exists(_ < 2000L) - !GlobalDefinitions.isFlightVehicle(vdef) && v.MountedIn.isEmpty && ( + !GlobalDefinitions.isFlightVehicle(vdef) && ( + if (vdef == GlobalDefinitions.ams && v.DeploymentState == DriveState.Deployed) false + else !v.Cloaked && ( tookDamage || usedEquipment)) + case _ => + false + } + + def SmallRoboticsTurretValidateAircraftTarget(target: PlanetSideGameObject): Boolean = + target match { + case v: Vehicle if GlobalDefinitions.isFlightVehicle(v.Definition) => + !v.Cloaked + case _ => + false + } + + def FacilityTurretValidateGroundVehicleTarget(target: PlanetSideGameObject): Boolean = + target match { + case v: Vehicle + if v.MountedIn.isEmpty => + val now = System.currentTimeMillis() + val vdef = v.Definition + lazy val tookDamage = v.LastDamage.exists(dam => dam.adversarial.nonEmpty && now - dam.interaction.hitTime< 2000L) + lazy val usedEquipment = v.Weapons.values.flatMap(_.Equipment) + .collect { case t: Tool => now - t.LastDischarge } + .exists(_ < 2000L) + !GlobalDefinitions.isFlightVehicle(vdef) && ( if (vdef == GlobalDefinitions.ams && v.DeploymentState == DriveState.Deployed) false else if ( v.Cloaked || @@ -268,23 +307,23 @@ object EffectTarget { else true) case _ => false - }) + } - def VehicleUndetectedByAutoTurret(target: PlanetSideGameObject): Boolean = + def FacilityTurretValidateAircraftTarget(target: PlanetSideGameObject): Boolean = + target match { + case v: Vehicle if GlobalDefinitions.isFlightVehicle(v.Definition) => + v.Definition != GlobalDefinitions.mosquito || !v.Cloaked + case _ => + false + } + + def AutoTurretBlankVehicleTarget(target: PlanetSideGameObject): Boolean = target match { case v: Vehicle => (v.Definition == GlobalDefinitions.ams && v.DeploymentState == DriveState.Deployed) || v.MountedIn.nonEmpty || v.Cloaked case _ => false } - - def AircraftDetectedByAutoTurret(target: PlanetSideGameObject): Boolean = - !target.Destroyed && (target match { - case v: Vehicle => - GlobalDefinitions.isFlightVehicle(v.Definition) && !v.Cloaked - case _ => - false - }) } private def radarEnhancedInterlink( diff --git a/src/main/scala/net/psforever/objects/serverobject/terminals/capture/CaptureTerminalAwareBehavior.scala b/src/main/scala/net/psforever/objects/serverobject/terminals/capture/CaptureTerminalAwareBehavior.scala index 3d638504d..f12a2e3b5 100644 --- a/src/main/scala/net/psforever/objects/serverobject/terminals/capture/CaptureTerminalAwareBehavior.scala +++ b/src/main/scala/net/psforever/objects/serverobject/terminals/capture/CaptureTerminalAwareBehavior.scala @@ -5,42 +5,46 @@ import net.psforever.objects.serverobject.mount.Mountable import net.psforever.objects.serverobject.structures.Amenity import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage} +import scala.annotation.unused + /** * The behaviours corresponding to an Amenity that is marked as being CaptureTerminalAware * @see CaptureTerminalAware */ trait CaptureTerminalAwareBehavior { - def CaptureTerminalAwareObject : Amenity with CaptureTerminalAware + def CaptureTerminalAwareObject: Amenity with CaptureTerminalAware val captureTerminalAwareBehaviour: Receive = { - case CaptureTerminalAwareBehavior.TerminalStatusChanged(terminal, isResecured) => - isResecured match { - case true => ; // CC is resecured - case false => // CC is hacked - // Remove seated occupants for mountables - CaptureTerminalAwareObject match { - case mountable: Mountable => + case CaptureTerminalAwareBehavior.TerminalStatusChanged(terminal, true) => + captureTerminalIsResecured(terminal) - val guid = mountable.GUID - val zone = mountable.Zone - val zoneId = zone.id - val events = zone.VehicleEvents + case CaptureTerminalAwareBehavior.TerminalStatusChanged(terminal, _) => + captureTerminalIsHacked(terminal) + } - mountable.Seats.values.zipWithIndex.foreach { - case (seat, seat_num) => - seat.occupant match { - case Some(player) => - seat.unmount(player) - player.VehicleSeated = None - if (player.HasGUID) { - events ! VehicleServiceMessage(zoneId, VehicleAction.KickPassenger(player.GUID, seat_num, true, guid)) - } - case None => ; - } - } - case _ => - } - } + protected def captureTerminalIsResecured(@unused terminal: CaptureTerminal): Unit = { /* intentionally blank */ } + + protected def captureTerminalIsHacked(@unused terminal: CaptureTerminal): Unit = { + // Remove seated occupants for mountables + CaptureTerminalAwareObject match { + case mountable: Mountable => + val guid = mountable.GUID + val zone = mountable.Zone + val zoneId = zone.id + val events = zone.VehicleEvents + mountable.Seats.values.zipWithIndex.foreach { + case (seat, seat_num) => + seat.occupant.collect { + case player => + seat.unmount(player) + player.VehicleSeated = None + if (player.HasGUID) { + events ! VehicleServiceMessage(zoneId, VehicleAction.KickPassenger(player.GUID, seat_num, unk2=true, guid)) + } + } + } + case _ => () + } } } diff --git a/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala b/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala index e40b06da5..0fa6232eb 100644 --- a/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala +++ b/src/main/scala/net/psforever/objects/serverobject/turret/FacilityTurretControl.scala @@ -9,13 +9,13 @@ import net.psforever.objects.serverobject.hackable.GenericHackables import net.psforever.objects.serverobject.mount.Mountable import net.psforever.objects.serverobject.repair.AmenityAutoRepair import net.psforever.objects.serverobject.structures.PoweredAmenityControl -import net.psforever.objects.serverobject.terminals.capture.CaptureTerminalAwareBehavior -import net.psforever.objects.serverobject.turret.auto.{AutomatedTurret, AutomatedTurretBehavior} +import net.psforever.objects.serverobject.terminals.capture.{CaptureTerminal, CaptureTerminalAwareBehavior} +import net.psforever.objects.serverobject.turret.auto.{AffectedByAutomaticTurretFire, AutomatedTurret, AutomatedTurretBehavior} import net.psforever.objects.vital.interaction.DamageResult import net.psforever.packet.game.ChangeFireModeMessage import net.psforever.services.Service import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage} -import net.psforever.types.BailType +import net.psforever.types.{BailType, PlanetSideEmpire} /** * A control agency that handles messages being dispatched to a specific `FacilityTurret`. @@ -27,6 +27,7 @@ class FacilityTurretControl(turret: FacilityTurret) with AmenityAutoRepair with MountableTurretControl with AutomatedTurretBehavior + with AffectedByAutomaticTurretFire with CaptureTerminalAwareBehavior { def TurretObject: FacilityTurret = turret def FactionObject: FacilityTurret = turret @@ -37,6 +38,7 @@ class FacilityTurretControl(turret: FacilityTurret) def AutoRepairObject: FacilityTurret = turret def AutomatedTurretObject: FacilityTurret = turret def CaptureTerminalAwareObject: FacilityTurret = turret + def AffectedObject: FacilityTurret = turret private var testToResetToDefaultFireMode: Boolean = false @@ -70,6 +72,7 @@ class FacilityTurretControl(turret: FacilityTurret) override def commonBehavior: Receive = super.commonBehavior .orElse(automatedTurretBehavior) + .orElse(takeAutomatedDamage) .orElse(captureTerminalAwareBehaviour) override def poweredStateLogic: Receive = @@ -247,4 +250,22 @@ class FacilityTurretControl(turret: FacilityTurret) super.CancelJammeredStatus(target) startsJammed && AutomaticOperation_=(AutomaticOperationFunctionalityChecks) } + + override protected def captureTerminalIsResecured(terminal: CaptureTerminal): Unit = { + AutomaticOperation = if (terminal.Owner.Faction == PlanetSideEmpire.NEUTRAL) { + false + } else if (AutomaticOperation || AutomaticOperationFunctionalityChecks) { + AutomaticOperation = false + CurrentTargetLastShotReported = System.currentTimeMillis() + 5000L + true + } else { + false + } + super.captureTerminalIsResecured(terminal) + } + + override protected def captureTerminalIsHacked(terminal: CaptureTerminal): Unit = { + AutomaticOperation = false + super.captureTerminalIsHacked(terminal) + } } diff --git a/src/main/scala/net/psforever/objects/serverobject/turret/auto/AffectedByAutomaticTurretFire.scala b/src/main/scala/net/psforever/objects/serverobject/turret/auto/AffectedByAutomaticTurretFire.scala index 3cbb81af1..1a6580ee3 100644 --- a/src/main/scala/net/psforever/objects/serverobject/turret/auto/AffectedByAutomaticTurretFire.scala +++ b/src/main/scala/net/psforever/objects/serverobject/turret/auto/AffectedByAutomaticTurretFire.scala @@ -29,36 +29,38 @@ trait AffectedByAutomaticTurretFire extends Damageable { protected def performAutomatedDamage(turret: AutomatedTurret): Unit = { val target = AffectedObject - val tool = turret.Weapons.values.head.Equipment.collect { case t: Tool => t }.get - val projectileInfo = tool.Projectile - val targetPos = target.Position - val turretPos = turret.Position - val correctedTargetPosition = targetPos + Vector3.z(value = 1f) - val angle = Vector3.Unit(targetPos - turretPos) - turret.Actor ! SelfReportedConfirmShot(target) - val projectile = new Projectile( - projectileInfo, - tool.Definition, - tool.FireMode, - None, - turret.TurretOwner, - turret.Definition.ObjectId, - turretPos + Vector3.z(value = 1f), - angle, - Some(angle * projectileInfo.FinalVelocity) - ) - val modProjectile = ProjectileQuality.modifiers( - projectile, - DamageResolution.Hit, - target, - correctedTargetPosition, - None - ) - val resolvedProjectile = DamageInteraction( - SourceEntry(target), - ProjectileReason(DamageResolution.Hit, modProjectile, target.DamageModel), - correctedTargetPosition - ) - PerformDamage(target, resolvedProjectile.calculate()) + if (!target.isMoving(test = 1f)) { + val tool = turret.Weapons.values.head.Equipment.collect { case t: Tool => t }.get + val projectileInfo = tool.Projectile + val targetPos = target.Position + val turretPos = turret.Position + val correctedTargetPosition = targetPos + Vector3.z(value = 1f) + val angle = Vector3.Unit(targetPos - turretPos) + turret.Actor ! SelfReportedConfirmShot(target) + val projectile = new Projectile( + projectileInfo, + tool.Definition, + tool.FireMode, + None, + turret.TurretOwner, + turret.Definition.ObjectId, + turretPos + Vector3.z(value = 1f), + angle, + Some(angle * projectileInfo.FinalVelocity) + ) + val modProjectile = ProjectileQuality.modifiers( + projectile, + DamageResolution.Hit, + target, + correctedTargetPosition, + None + ) + val resolvedProjectile = DamageInteraction( + SourceEntry(target), + ProjectileReason(DamageResolution.Hit, modProjectile, target.DamageModel), + correctedTargetPosition + ) + PerformDamage(target, resolvedProjectile.calculate()) + } } } diff --git a/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala b/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala index 8139ef3fa..2545c709c 100644 --- a/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala +++ b/src/main/scala/net/psforever/objects/serverobject/turret/auto/AutomatedTurretBehavior.scala @@ -306,13 +306,16 @@ trait AutomatedTurretBehavior { val weaponGuid = AutomatedTurretObject.Weapons.values.head.Equipment.get.GUID val radius = autoStats.get.ranges.trigger val validation = autoStats.get.checks.validation + val disqualifiers = autoStats.get.checks.blanking val faction = AutomatedTurretObject.Faction val selectedTargets = AutomatedTurretObject .Targets .collect { case target - if target.Faction != faction && + if !target.Destroyed && + target.Faction != faction && AutomatedTurretBehavior.shapedDistanceCheckAgainstValue(autoStats, target.Position, turretPosition, radius, result = -1) && - validation.exists(func => func(target)) => + validation.exists(func => func(target)) && + disqualifiers.takeWhile(func => func(target)).isEmpty => target } val (previousTargets, newTargets) = selectedTargets.partition(target => previouslyTestedTargets.contains(SourceEntry(target).unique)) @@ -399,7 +402,7 @@ trait AutomatedTurretBehavior { AutomatedTurretDispatch.Generic.startShooting(target, target.Name, weaponGuid) AutomatedTurretDispatch.Generic.stopShooting(target, target.Name, weaponGuid) Some((target, target)) - case target: Vehicle => + case target: Mountable => target.Seats.values .flatMap(_.occupants) .collectFirst { passenger => @@ -599,27 +602,7 @@ trait AutomatedTurretBehavior { selfReportingCleanUp() } - /** - * Cleanup for the variables involved in self-reporting. - * Set them to zero. - */ - protected def selfReportingCleanUp(): Unit = { - shotsFired = 0 - targetsDestroyed = 0 - } - - /** - * The self-reporting mode for automatic turrets produces weapon fire data that should be sent to the database. - * The targets destroyed from self-reported fire are also logged to the database. - */ - protected def selfReportingDatabaseUpdate(): Unit = { - AutomatedTurretObject.TurretOwner match { - case p: PlayerSource => - val weaponId = AutomatedTurretObject.Weapons.values.head.Equipment.map(_.Definition.ObjectId).getOrElse(0) - ToDatabase.reportToolDischarge(p.CharId, EquipmentStat(weaponId, shotsFired, shotsFired, targetsDestroyed, 0)) - case _ => () - } - } + /* Retaliation behavior */ /** * Retaliation is when a turret returns fire on a potential target that had just previously dealt damage to it. @@ -656,18 +639,27 @@ trait AutomatedTurretBehavior { case existingTarget if autoStats.exists { auto => auto.retaliationOverridesTarget && - currentTargetSwitchTime + auto.retaliatoryDelay > System.currentTimeMillis() + currentTargetSwitchTime + auto.retaliatoryDelay > System.currentTimeMillis() && + auto.checks.blanking.takeWhile(func => func(target)).isEmpty } => + //conditions necessary for overriding the current target cancelSelfReportedAutoFire() noLongerEngageDetectedTarget(existingTarget) engageNewDetectedTarget(target) target + case existingTarget => + //stay with the current target existingTarget } .orElse { - engageNewDetectedTarget(target) - Some(target) + //no current target + if (autoStats.exists(_.checks.blanking.takeWhile(func => func(target)).isEmpty)) { + engageNewDetectedTarget(target) + Some(target) + } else { + None + } } } @@ -769,6 +761,28 @@ trait AutomatedTurretBehavior { selfReportedRefire = Default.Cancellable true } + + /** + * Cleanup for the variables involved in self-reporting. + * Set them to zero. + */ + protected def selfReportingCleanUp(): Unit = { + shotsFired = 0 + targetsDestroyed = 0 + } + + /** + * The self-reporting mode for automatic turrets produces weapon fire data that should be sent to the database. + * The targets destroyed from self-reported fire are also logged to the database. + */ + protected def selfReportingDatabaseUpdate(): Unit = { + AutomatedTurretObject.TurretOwner match { + case p: PlayerSource => + val weaponId = AutomatedTurretObject.Weapons.values.head.Equipment.map(_.Definition.ObjectId).getOrElse(0) + ToDatabase.reportToolDischarge(p.CharId, EquipmentStat(weaponId, shotsFired, shotsFired, targetsDestroyed, 0)) + case _ => () + } + } } object AutomatedTurretBehavior { @@ -784,8 +798,8 @@ object AutomatedTurretBehavior { private case object PeriodicCheck final val commonBlanking: List[PlanetSideGameObject => Boolean] = List( - EffectTarget.Validation.PlayerUndetectedByAutoTurret, - EffectTarget.Validation.VehicleUndetectedByAutoTurret + EffectTarget.Validation.AutoTurretBlankPlayerTarget, + EffectTarget.Validation.AutoTurretBlankVehicleTarget ) /**