Degraded Lash Damage (#257)

* formulas to calculate consistent distance between origin and impact; lash damage degrades as a function of distance

* clamped the degrade value for lashing damage; clamped the distance value; implemented a rudimentary and unsophisticated shot origin to shot owner distance validation test; fixed a mounting bug

* lashing damage is primarily targeted at exo-suit armor; lashing calculates damage starting at the same distance at which it starts being detected

* clarifying the weapon fired in the warning message
This commit is contained in:
Fate-JH 2019-05-06 08:48:11 -04:00 committed by GitHub
parent 78eb7906c9
commit fca14e6b1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 18 deletions

View file

@ -79,9 +79,10 @@ object MountableBehavior {
val dismountBehavior : Receive = {
case Mountable.TryDismount(user, seat_num) =>
val obj = MountableObject
val velocity = obj.Velocity.getOrElse(Vector3.Zero)
obj.Seat(seat_num) match {
case Some(seat) =>
if(seat.Bailable || obj.Velocity.isEmpty || Vector3.MagnitudeSquared(obj.Velocity.get).toInt == 0) {
if(seat.Bailable || velocity == Vector3.Zero || Vector3.MagnitudeSquared(velocity).toInt == 0) {
seat.Occupant = None
user.VehicleSeated = None
sender ! Mountable.MountMessages(user, Mountable.CanDismount(obj, seat_num))

View file

@ -22,7 +22,7 @@ object InfantrySplashResistance extends ResistanceCalculations[PlayerSource](
object InfantryLashResistance extends ResistanceCalculations[PlayerSource](
ResistanceCalculations.ValidInfantryTarget,
ResistanceCalculations.ExoSuitDirectExtractor
ResistanceCalculations.MaximumResistance
)
object InfantryAggravatedResistance extends ResistanceCalculations[PlayerSource](

View file

@ -46,7 +46,7 @@ object DamageCalculations {
//types
type DamagesType = (Projectile, Int, Float)=>Int
type DamageWithModifiersType = (DamageProfile, List[DamageProfile])=>Int
type DistanceType = (ResolvedProjectile)=>Float
type DistanceType = ResolvedProjectile=>Float
//raw damage selectors
def NoDamageAgainst(profile : DamageProfile) : Int = 0
@ -70,7 +70,7 @@ object DamageCalculations {
* @return the accumulated damage value
*/
//TODO modifiers come from various sources; expand this part of the calculation model in the future
def DamageWithModifiers(extractor : (DamageProfile)=>Int)(base : DamageProfile, modifiers : List[DamageProfile]) : Int = {
def DamageWithModifiers(extractor : DamageProfile=>Int)(base : DamageProfile, modifiers : List[DamageProfile]) : Int = {
extractor(base) + modifiers.foldLeft(0)(_ + extractor(_))
}
@ -133,17 +133,18 @@ object DamageCalculations {
}
/**
* Calculate a flat lash damage value.
* Calculate a lash damage value.
* The target needs to be more than five meters away.
* Since lash damage occurs after the direct hit projectile's damage begins to degrade,
* the minimum of five less than distance or zero is calculated.
* @param projectile information about the weapon discharge (itself)
* @param rawDamage the accumulated amount of damage
* @param distance how far the source was from the target
* @return the modified damage value
*/
def LashDamage(projectile : Projectile, rawDamage : Int, distance : Float) : Int = {
val profile = projectile.profile
if(distance > 5 || distance <= profile.DistanceMax) {
(rawDamage * 0.2f) toInt
if(distance > 5) {
(DirectHitDamageWithDegrade(projectile, rawDamage, math.max(distance - 5, 0f)) * 0.2f) toInt
}
else {
0
@ -156,10 +157,16 @@ object DamageCalculations {
def TooFar(data : ResolvedProjectile) : Float = Float.MaxValue
def DistanceBetweenTargetandSource(data : ResolvedProjectile) : Float = {
Vector3.Distance(data.target.Position, data.projectile.owner.Position)
//Vector3.Distance(data.target.Position, data.projectile.owner.Position)
DistanceBetweenOriginAndImpact(data)
}
def DistanceFromExplosionToTarget(data : ResolvedProjectile) : Float = {
Vector3.Distance(data.target.Position, data.hit_pos)
math.max(Vector3.Distance(data.target.Position, data.hit_pos) - 1, 0)
//DistanceBetweenOriginAndImpact(data)
}
def DistanceBetweenOriginAndImpact(data : ResolvedProjectile) : Float = {
math.max(Vector3.Distance(data.projectile.shot_origin, data.hit_pos) - 0.5f, 0)
}
}

View file

@ -24,8 +24,8 @@ import scala.util.{Failure, Success, Try}
* in essence, should match the type of object container to which these resistances belong;
* never has to be defined explicitly, but will be checked upon object definition
*/
abstract class ResistanceCalculations[TargetType](validate : (ResolvedProjectile)=>Try[TargetType],
extractor : (TargetType)=>Int) extends ProjectileCalculations {
abstract class ResistanceCalculations[TargetType](validate : ResolvedProjectile=>Try[TargetType],
extractor : TargetType=>Int) extends ProjectileCalculations {
/**
* Get resistance valuess.
* @param data the historical `ResolvedProjectile` information
@ -121,4 +121,6 @@ object ResistanceCalculations {
def VehicleAggravatedExtractor(target : VehicleSource) : Int = target.Definition.ResistanceAggravated
def VehicleRadiationExtractor(target : VehicleSource) : Float = target.Definition.RadiationShielding
def MaximumResistance(target : SourceEntry) : Int = Integer.MAX_VALUE
}

View file

@ -4427,16 +4427,24 @@ class WorldSessionActor extends Actor with MDCContextAware {
}) {
log.trace(s"WeaponFireMessage: overwriting unresolved projectile ${projectile_guid.guid}")
}
val (angle, attribution) = obj match {
val (angle, attribution, acceptableDistanceToOwner) = obj match {
case p : Player =>
(p.Orientation, tool.Definition.ObjectId) //TODO upper body facing
(p.Orientation, tool.Definition.ObjectId, 10f) //TODO upper body facing
case v : Vehicle if v.Definition.CanFly =>
(tool.Orientation, obj.Definition.ObjectId, 1000f) //TODO this is too simplistic to find proper angle
case _ : Vehicle =>
(tool.Orientation, obj.Definition.ObjectId) //TODO this is too simplistic to find proper angle
(tool.Orientation, obj.Definition.ObjectId, 225f) //TODO this is too simplistic to find proper angle
case _ =>
(obj.Orientation, obj.Definition.ObjectId)
(obj.Orientation, obj.Definition.ObjectId, 300f)
}
val distanceToOwner = Vector3.DistanceSquared(shot_origin, player.Position)
if(distanceToOwner <= acceptableDistanceToOwner) {
projectiles(projectileIndex) =
Some(Projectile(tool.Projectile, tool.Definition, tool.FireMode, player, attribution, shot_origin, angle))
}
else {
log.warn(s"WeaponFireMessage: $player's ${tool.Definition.Name} projectile is too far from owner position at time of discharge ($distanceToOwner > $acceptableDistanceToOwner); suspect")
}
projectiles(projectileIndex) =
Some(Projectile(tool.Projectile, tool.Definition, tool.FireMode, player, attribution, shot_origin, angle))
}
case _ => ;
}