Mine Distance (#1276)

* changing to square distance during mine checks; repeating entity geometric distance check function

* added separate trigger radius rules for players and vehicles
This commit is contained in:
Fate-JH 2025-06-23 13:10:48 -04:00 committed by GitHub
parent 5e0584b83b
commit f74da61fa5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 73 additions and 10 deletions

View file

@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.objects package net.psforever.objects
import net.psforever.objects.avatar.interaction.{WithEntrance, WithGantry, WithLava, WithWater} import net.psforever.objects.avatar.interaction.{TriggerOnPlayerRule, WithEntrance, WithGantry, WithLava, WithWater}
import net.psforever.objects.avatar.{Avatar, LoadoutManager, SpecialCarry} import net.psforever.objects.avatar.{Avatar, LoadoutManager, SpecialCarry}
import net.psforever.objects.ballistics.InteractWithRadiationClouds import net.psforever.objects.ballistics.InteractWithRadiationClouds
import net.psforever.objects.ce.{Deployable, InteractWithMines, InteractWithTurrets} import net.psforever.objects.ce.{Deployable, InteractWithMines, InteractWithTurrets}
@ -47,7 +47,7 @@ class Player(var avatar: Avatar)
new WithGantry(avatar.name), new WithGantry(avatar.name),
new WithMovementTrigger() new WithMovementTrigger()
))) )))
interaction(new InteractWithMines(range = 10)) interaction(new InteractWithMines(range = 10, TriggerOnPlayerRule))
interaction(new InteractWithTurrets()) interaction(new InteractWithTurrets())
interaction(new InteractWithRadiationClouds(range = 10f, Some(this))) interaction(new InteractWithRadiationClouds(range = 10f, Some(this)))

View file

@ -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.{WithLava, WithWater} import net.psforever.objects.vehicles.interaction.{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
@ -101,7 +101,7 @@ class Vehicle(private val vehicleDef: VehicleDefinition)
new WithDeath(), new WithDeath(),
new WithMovementTrigger() new WithMovementTrigger()
))) )))
interaction(new InteractWithMines(range = 20)) interaction(new InteractWithMines(range = 20, TriggerOnVehicleRule))
interaction(new InteractWithTurrets()) interaction(new InteractWithTurrets())
interaction(new InteractWithRadiationCloudsSeatedInVehicle(obj = this, range = 20)) interaction(new InteractWithRadiationCloudsSeatedInVehicle(obj = this, range = 20))

View file

@ -0,0 +1,14 @@
// Copyright (c) 2025 PSForever
package net.psforever.objects.avatar.interaction
import net.psforever.objects.ce.TriggerTest
import net.psforever.objects.ExplosiveDeployable
import net.psforever.objects.geometry.d3.VolumetricGeometry
import net.psforever.objects.zones.Zone
case object TriggerOnPlayerRule
extends TriggerTest {
def test(g: VolumetricGeometry, obj: ExplosiveDeployable, radius: Float): Boolean = {
Zone.distanceCheck(g, obj, radius)
}
}

View file

@ -1,8 +1,9 @@
// Copyright (c) 2021 PSForever // Copyright (c) 2021 PSForever
package net.psforever.objects.ce package net.psforever.objects.ce
import net.psforever.objects.geometry.d3.VolumetricGeometry
import net.psforever.objects.zones.blockmap.SectorPopulation import net.psforever.objects.zones.blockmap.SectorPopulation
import net.psforever.objects.zones.{InteractsWithZone, Zone, ZoneInteraction, ZoneInteractionType} import net.psforever.objects.zones.{InteractsWithZone, ZoneInteraction, ZoneInteractionType}
import net.psforever.objects.{BoomerDeployable, ExplosiveDeployable} import net.psforever.objects.{BoomerDeployable, ExplosiveDeployable}
import net.psforever.types.PlanetSideGUID import net.psforever.types.PlanetSideGUID
@ -13,7 +14,7 @@ case object MineInteraction extends ZoneInteractionType
* "Interact", here, is a graceful word for "trample upon" and the consequence should be an explosion * "Interact", here, is a graceful word for "trample upon" and the consequence should be an explosion
* and maybe death. * and maybe death.
*/ */
class InteractWithMines(val range: Float) class InteractWithMines(val range: Float, rule: TriggerTest)
extends ZoneInteraction { extends ZoneInteraction {
/** /**
* mines that, though detected, are skipped from being alerted; * mines that, though detected, are skipped from being alerted;
@ -23,7 +24,7 @@ class InteractWithMines(val range: Float)
*/ */
private var skipTargets: List[PlanetSideGUID] = List() private var skipTargets: List[PlanetSideGUID] = List()
def Type = MineInteraction def Type: MineInteraction.type = MineInteraction
/** /**
* Trample upon active mines in our current detection sector and alert those mines. * Trample upon active mines in our current detection sector and alert those mines.
@ -32,12 +33,12 @@ class InteractWithMines(val range: Float)
*/ */
def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit = { def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit = {
val faction = target.Faction val faction = target.Faction
lazy val targetGeometry = target.Definition.Geometry(target)
val targets = sector val targets = sector
.deployableList .deployableList
.filter { .filter {
case _: BoomerDeployable => false //boomers are specific types of ExplosiveDeployable but do not count here case _: BoomerDeployable => false //boomers are a specific type of ExplosiveDeployable that do not count here
case ex: ExplosiveDeployable => ex.Faction != faction && case ex: ExplosiveDeployable => ex.Faction != faction && rule.test(targetGeometry, ex, ex.Definition.triggerRadius)
Zone.distanceCheck(target, ex, ex.Definition.triggerRadius)
case _ => false case _ => false
} }
val notSkipped = targets.filterNot { t => skipTargets.contains(t.GUID) } val notSkipped = targets.filterNot { t => skipTargets.contains(t.GUID) }
@ -56,3 +57,19 @@ class InteractWithMines(val range: Float)
skipTargets = List() skipTargets = List()
} }
} }
/**
* The testing rule used to determine if a target is within range
* to agitate the game world deployable extra-territorial munitions.
*/
trait TriggerTest {
/**
* Perform the test
* @param g the geometric representation of a game entity
* @param obj a game entity
* @param distance the maximum distance permissible between game entities
* @return `true`, if the two entities are near enough to each other;
* `false`, otherwise
*/
def test(g: VolumetricGeometry, obj: ExplosiveDeployable, distance: Float): Boolean
}

View file

@ -0,0 +1,14 @@
// Copyright (c) 2025 PSForever
package net.psforever.objects.vehicles.interaction
import net.psforever.objects.ce.TriggerTest
import net.psforever.objects.ExplosiveDeployable
import net.psforever.objects.geometry.d3.VolumetricGeometry
import net.psforever.objects.zones.Zone
case object TriggerOnVehicleRule
extends TriggerTest {
def test(g: VolumetricGeometry, obj: ExplosiveDeployable, radius: Float): Boolean = {
Zone.distanceCheck(g, obj, radius * radius)
}
}

View file

@ -1901,6 +1901,24 @@ object Zone {
distanceCheck(obj1.Definition.Geometry(obj1), obj2.Definition.Geometry(obj2), maxDistance) distanceCheck(obj1.Definition.Geometry(obj1), obj2.Definition.Geometry(obj2), maxDistance)
} }
/**
* Two game entities are considered "near" each other if they are within a certain distance of one another.
* A default function literal mainly used for `serverSideDamage`.
* Best used when one entity - `obj1` - is to be reused in tests against multiple other entities
* as it skips repeatedly calculating the volumetric geometry of the repeating entity.
* @see `ObjectDefinition.Geometry`
* @see `serverSideDamage`
* @param obj1 the geometric representation of a game entity
* @param obj2 a game entity
* @param maxDistance the square of the maximum distance permissible between game entities
* before they are no longer considered "near"
* @return `true`, if the two entities are near enough to each other;
* `false`, otherwise
*/
def distanceCheck(obj1: VolumetricGeometry, obj2: PlanetSideGameObject, maxDistance: Float): Boolean = {
distanceCheck(obj1, obj2.Definition.Geometry(obj2), maxDistance)
}
/** /**
* Two game entities are considered "near" each other if they are within a certain distance of one another. * Two game entities are considered "near" each other if they are within a certain distance of one another.
* @param g1 the geometric representation of a game entity * @param g1 the geometric representation of a game entity