mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-07-11 22:44:40 +00:00
corrected input data to force door wall inclusion test; adjusted force dome ceiling inclusion test(s); force dome generator locations now retained; invulnerability can not be granted to players or vehicles if they've taken damage recently
This commit is contained in:
parent
f5d7fed1cf
commit
d0d7632f82
7 changed files with 86 additions and 24 deletions
|
|
@ -804,6 +804,15 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm
|
|||
}
|
||||
}
|
||||
|
||||
override protected def canChangeVulnerability(state: Damageable.PersonalVulnerability): Boolean = {
|
||||
state match {
|
||||
case Damageable.MakeInvulnerable =>
|
||||
player.LastDamage.exists { d => System.currentTimeMillis() - d.interaction.hitTime > 2500L }
|
||||
case _ =>
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override protected def PerformDamage(
|
||||
target: Target,
|
||||
applyDamageTo: Output
|
||||
|
|
|
|||
|
|
@ -966,6 +966,7 @@ object GlobalDefinitionsMiscellaneous {
|
|||
Vector3(83.05469f, -106.90625f, 0f)
|
||||
)
|
||||
force_dome_amp_physics.ApplyProtectionTo = List(generator, manned_turret)
|
||||
force_dome_amp_physics.GeneratorOffset = Vector3(0.148f, -21.867f, 17.623f)
|
||||
|
||||
force_dome_comm_physics.Name = "force_dome_comm_physics"
|
||||
force_dome_comm_physics.UseRadius = 121.8149f
|
||||
|
|
@ -978,6 +979,7 @@ object GlobalDefinitionsMiscellaneous {
|
|||
Vector3(-83.640625f, -89.859375f, 0f)
|
||||
)
|
||||
force_dome_comm_physics.ApplyProtectionTo = List(generator, manned_turret)
|
||||
force_dome_comm_physics.GeneratorOffset = Vector3(-19.481f, -4.25f, 12.649f)
|
||||
|
||||
force_dome_cryo_physics.Name = "force_dome_cryo_physics"
|
||||
force_dome_cryo_physics.UseRadius = 127.9241f //127.7963f
|
||||
|
|
@ -989,6 +991,7 @@ object GlobalDefinitionsMiscellaneous {
|
|||
Vector3(72.75476f, -103.47f, 0)
|
||||
)
|
||||
force_dome_cryo_physics.ApplyProtectionTo = List(generator, implant_terminal_mech, manned_turret)
|
||||
force_dome_cryo_physics.GeneratorOffset = Vector3(-20.709f, 5.387f, 19.466f)
|
||||
|
||||
force_dome_dsp_physics.Name = "force_dome_dsp_physics"
|
||||
force_dome_dsp_physics.UseRadius = 175.8838f //175.7081f
|
||||
|
|
@ -1001,6 +1004,7 @@ object GlobalDefinitionsMiscellaneous {
|
|||
Vector3(130.44531f, -93.28125f, 0f)
|
||||
)
|
||||
force_dome_dsp_physics.ApplyProtectionTo = List(generator, manned_turret)
|
||||
force_dome_dsp_physics.GeneratorOffset = Vector3(12.698f, 25.15f, 12.541f)
|
||||
|
||||
force_dome_tech_physics.Name = "force_dome_tech_physics"
|
||||
force_dome_tech_physics.UseRadius = 150.1284f
|
||||
|
|
@ -1016,5 +1020,6 @@ object GlobalDefinitionsMiscellaneous {
|
|||
Vector3(102.12191f, -114.65837f, 0f)
|
||||
)
|
||||
force_dome_tech_physics.ApplyProtectionTo = List(generator, manned_turret)
|
||||
force_dome_tech_physics.GeneratorOffset = Vector3(13.001f, -32.612f, 22.59f)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import net.psforever.objects.vital.Vitality
|
|||
import net.psforever.objects.vital.interaction.{DamageInteraction, DamageResult}
|
||||
import net.psforever.objects.vital.resolution.ResolutionCalculations
|
||||
|
||||
import scala.annotation.unused
|
||||
|
||||
/**
|
||||
* The base "control" `Actor` mixin for damage-handling code.
|
||||
* A valid entity requires health points and
|
||||
|
|
@ -31,10 +33,10 @@ trait Damageable {
|
|||
* `orElse` onto the "control" `Actor` `receive`; or,
|
||||
* cite the `originalTakesDamage` protocol during inheritance overrides */
|
||||
val takesDamage: Receive = {
|
||||
case Damageable.MakeVulnerable =>
|
||||
case Damageable.MakeVulnerable if canChangeVulnerability(Damageable.MakeVulnerable) =>
|
||||
isVulnerable = true
|
||||
|
||||
case Damageable.MakeInvulnerable =>
|
||||
case Damageable.MakeInvulnerable if canChangeVulnerability(Damageable.MakeInvulnerable) =>
|
||||
isVulnerable = false
|
||||
|
||||
case Vitality.Damage(damage_func) =>
|
||||
|
|
@ -43,16 +45,20 @@ trait Damageable {
|
|||
|
||||
/** a duplicate of the core implementation for the default mixin hook, for use in overriding */
|
||||
final val originalTakesDamage: Receive = {
|
||||
case Damageable.MakeVulnerable =>
|
||||
case Damageable.MakeVulnerable if canChangeVulnerability(Damageable.MakeVulnerable) =>
|
||||
isVulnerable = true
|
||||
|
||||
case Damageable.MakeInvulnerable =>
|
||||
case Damageable.MakeInvulnerable if canChangeVulnerability(Damageable.MakeInvulnerable) =>
|
||||
isVulnerable = false
|
||||
|
||||
case Vitality.Damage(damage_func) =>
|
||||
PerformDamageIfVulnerable(DamageableObject, damage_func)
|
||||
}
|
||||
|
||||
protected def canChangeVulnerability(@unused state: Damageable.PersonalVulnerability): Boolean = {
|
||||
true
|
||||
}
|
||||
|
||||
/**
|
||||
* Assess if the target is vulnerable to damage.
|
||||
* If so, attempt damage calculations.
|
||||
|
|
|
|||
|
|
@ -240,8 +240,7 @@ object ForceDomeControl {
|
|||
* where the second condition is one of two qualifications:
|
||||
* 1. within an angular perimeter boundary, and
|
||||
* 2a. below the base coordinate of the force dome or
|
||||
* 2b. within a region above the base of the force dome represented by a literal "dome" (half of a sphere).
|
||||
* @see `Zone.distanceCheck`
|
||||
* 2b. within a region above the facility encapsulated by the force dome
|
||||
* @param segments ground-level perimeter of the force dome is defined by these segments (as vertex pairs)
|
||||
* @param obj1 a game entity, should be the force dome
|
||||
* @param obj2 a game entity, should be a damageable target of the force dome's wrath
|
||||
|
|
@ -257,13 +256,36 @@ object ForceDomeControl {
|
|||
obj2: PlanetSideGameObject,
|
||||
@unused maxDistance: Float
|
||||
): Boolean = {
|
||||
val centerPos @ Vector3(centerX, centerY, centerZ) = obj1.Position
|
||||
val Vector3(targetX, targetY, _) = obj2.Position.xy - centerPos.xy //deltas of segment of target to dome
|
||||
lazy val checkForIntersection = segments.exists { case (point1, point2) =>
|
||||
//want targets within the perimeter; if there's an intersection, target is outside of the perimeter
|
||||
val Vector3(centerX, centerY, centerZ) = obj1.Position
|
||||
val Vector3(targetX, targetY, targetZ) = obj2.Position
|
||||
lazy val insideOfThePerimeter = !segments.exists { case (point1, point2) =>
|
||||
//want targets within the perimeter; if there's any intersection, target is outside of the perimeter
|
||||
segmentIntersectionTestPerSegment(centerX, centerY, targetX, targetY, point1.x, point1.y, point2.x, point2.y)
|
||||
}
|
||||
segments.nonEmpty && !checkForIntersection && (obj2.Position.z <= centerZ || Zone.distanceCheck(obj1, obj2, math.pow(obj1.Definition.UseRadius, 2).toFloat))
|
||||
segments.nonEmpty && insideOfThePerimeter && (targetZ <= centerZ || underForceDomeCeiling(obj1, obj2, targetZ))
|
||||
}
|
||||
|
||||
/**
|
||||
* The force dome is the top portion of an irregular prism.
|
||||
* It's walls are similarly angled inwards, usually.
|
||||
* There's no way to properly represent this without too much work.
|
||||
* Just ensure the target is either below the dome or within a circular region
|
||||
* defined by the base of the generator to the top of the extended stalk as the measurement of a hemisphere.
|
||||
* @see `Zone.distanceCheck`
|
||||
* @param obj1 a game entity, should be the force dome
|
||||
* @param obj2 a game entity, should be a damageable target of the force dome's wrath
|
||||
* @param height target height that must be under the ceiling
|
||||
* @return `true`, if target is detected within the force dome kill region
|
||||
* `false`, otherwise
|
||||
*/
|
||||
private def underForceDomeCeiling(obj1: PlanetSideGameObject, obj2: PlanetSideGameObject, height: Float): Boolean = {
|
||||
obj1 match {
|
||||
case dome: ForceDomePhysics =>
|
||||
val generatorHeightOffsetZ = dome.Definition.GeneratorOffset.z
|
||||
height < dome.Owner.Position.z + generatorHeightOffsetZ * 1.5f || Zone.distanceCheck(obj1, obj2, generatorHeightOffsetZ + 42f)
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -294,21 +316,23 @@ object ForceDomeControl {
|
|||
): Boolean = {
|
||||
//based on Franklin Antonio's "Faster Line Segment Intersection" topic "in Graphics Gems III" book (http://www.graphicsgems.org/)
|
||||
//compare, java.awt.geom.Line2D.linesIntersect
|
||||
val bx = segmentPoint1x - segmentPoint2x //delta-x of segment
|
||||
val by = segmentPoint1y - segmentPoint2y //delta-y of segment
|
||||
val cx = pointX - segmentPoint1x //delta-x of hypotenuse of triangle formed by center, segment endpoint, and intersection point
|
||||
val cy = pointY - segmentPoint1y //delta-y of hypotenuse of triangle formed by center, segment endpoint, and intersection point
|
||||
val alphaNumerator = by * cx - bx * cy
|
||||
val commonDenominator = targetY * bx - targetX * by
|
||||
val betaNumerator = targetX * cy - targetY * cx
|
||||
val ax = targetX - pointX //delta-x of segment from center to target
|
||||
val ay = targetY - pointY //delta-y of segment from center to target
|
||||
val bx = segmentPoint1x - segmentPoint2x //delta-x of test segment
|
||||
val by = segmentPoint1y - segmentPoint2y //delta-y of test segment
|
||||
val cx = pointX - segmentPoint1x //delta-x of hypotenuse of triangle formed by center, test segment endpoint, and intersection point
|
||||
val cy = pointY - segmentPoint1y //delta-y of hypotenuse of triangle formed by center, test segment endpoint, and intersection point
|
||||
val alphaNumerator = by * cx - bx * cy //cross product of matrix [(by, bx)(cy, cx)]
|
||||
val denominator = ay * bx - ax * by //cross product of matrix [(ay, ax)(cy, cx)]
|
||||
val betaNumerator = ax * cy - ay * cx //cross product of matrix [(ax, ay)(cx, cy)]
|
||||
if (
|
||||
commonDenominator > 0 &&
|
||||
(alphaNumerator < 0 || alphaNumerator > commonDenominator || betaNumerator < 0 || betaNumerator > commonDenominator)
|
||||
denominator > 0 &&
|
||||
(alphaNumerator < 0 || alphaNumerator > denominator || betaNumerator < 0 || betaNumerator > denominator)
|
||||
) {
|
||||
false
|
||||
} else if (
|
||||
commonDenominator < 0 &&
|
||||
(alphaNumerator > 0 || alphaNumerator < commonDenominator || betaNumerator > 0 || betaNumerator < commonDenominator)
|
||||
denominator < 0 &&
|
||||
(alphaNumerator > 0 || alphaNumerator < denominator || betaNumerator > 0 || betaNumerator < denominator)
|
||||
) {
|
||||
false
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ class ForceDomeDefinition(objectId: Int)
|
|||
* these points are the closest to where the dome interacts with the ground at a corner;
|
||||
* should be sequential, either clockwise or counterclockwise */
|
||||
private var perimeter: List[Vector3] = List()
|
||||
/** offset of the physical location of the force dome generator stalk */
|
||||
private var genOffset: Vector3 = Vector3.Zero
|
||||
|
||||
def PerimeterOffsets: List[Vector3] = perimeter
|
||||
|
||||
|
|
@ -34,6 +36,13 @@ class ForceDomeDefinition(objectId: Int)
|
|||
protects = protect
|
||||
ApplyProtectionTo
|
||||
}
|
||||
|
||||
def GeneratorOffset: Vector3 = genOffset
|
||||
|
||||
def GeneratorOffset_=(offset: Vector3): Vector3 = {
|
||||
genOffset = offset
|
||||
GeneratorOffset
|
||||
}
|
||||
}
|
||||
|
||||
object ForceDomeDefinition {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class ForceDomePhysics(private val cfddef: ForceDomeDefinition)
|
|||
/** whether the dome is active or not */
|
||||
private var energized: Boolean = false
|
||||
/** defined perimeter of this force dome on the floor;
|
||||
* the walls created by this perimeter are angled inwards towards the facility, but that's not a consideration */
|
||||
* the walls created by this perimeter are angled inwards towards the facility vertically, but that's not a consideration here */
|
||||
private var perimeter: List[(Vector3, Vector3)] = List()
|
||||
|
||||
override def Position: Vector3 = Owner.Position
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObjec
|
|||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||
import net.psforever.objects.serverobject.containable.{Containable, ContainableBehavior}
|
||||
import net.psforever.objects.serverobject.damage.Damageable.Target
|
||||
import net.psforever.objects.serverobject.damage.{AggravatedBehavior, DamageableVehicle}
|
||||
import net.psforever.objects.serverobject.damage.{AggravatedBehavior, Damageable, DamageableVehicle}
|
||||
import net.psforever.objects.serverobject.environment._
|
||||
import net.psforever.objects.serverobject.environment.interaction.common.Watery
|
||||
import net.psforever.objects.serverobject.environment.interaction.{InteractWithEnvironment, RespondsToZoneEnvironment}
|
||||
|
|
@ -742,6 +742,15 @@ class VehicleControl(vehicle: Vehicle)
|
|||
}
|
||||
}
|
||||
|
||||
override protected def canChangeVulnerability(state: Damageable.PersonalVulnerability): Boolean = {
|
||||
state match {
|
||||
case Damageable.MakeInvulnerable =>
|
||||
vehicle.LastDamage.exists { d => System.currentTimeMillis() - d.interaction.hitTime > 2500L }
|
||||
case _ =>
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override protected def DestructionAwareness(target: Target, cause: DamageResult): Unit = {
|
||||
StopInteractionSelfReportingNoReset()
|
||||
super.DestructionAwareness(target, cause)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue