diff --git a/common/src/main/scala/net/psforever/objects/serverobject/mount/MountableBehavior.scala b/common/src/main/scala/net/psforever/objects/serverobject/mount/MountableBehavior.scala index b2d94514..ae073dee 100644 --- a/common/src/main/scala/net/psforever/objects/serverobject/mount/MountableBehavior.scala +++ b/common/src/main/scala/net/psforever/objects/serverobject/mount/MountableBehavior.scala @@ -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)) diff --git a/common/src/main/scala/net/psforever/objects/vital/StandardResistances.scala b/common/src/main/scala/net/psforever/objects/vital/StandardResistances.scala index 00d507c5..2c398c20 100644 --- a/common/src/main/scala/net/psforever/objects/vital/StandardResistances.scala +++ b/common/src/main/scala/net/psforever/objects/vital/StandardResistances.scala @@ -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]( diff --git a/common/src/main/scala/net/psforever/objects/vital/damage/DamageCalculations.scala b/common/src/main/scala/net/psforever/objects/vital/damage/DamageCalculations.scala index 9fa33eb7..f751e2fc 100644 --- a/common/src/main/scala/net/psforever/objects/vital/damage/DamageCalculations.scala +++ b/common/src/main/scala/net/psforever/objects/vital/damage/DamageCalculations.scala @@ -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) } } diff --git a/common/src/main/scala/net/psforever/objects/vital/resistance/ResistanceCalculations.scala b/common/src/main/scala/net/psforever/objects/vital/resistance/ResistanceCalculations.scala index 911d8f68..6082baee 100644 --- a/common/src/main/scala/net/psforever/objects/vital/resistance/ResistanceCalculations.scala +++ b/common/src/main/scala/net/psforever/objects/vital/resistance/ResistanceCalculations.scala @@ -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 } diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala index 2873338c..2c566124 100644 --- a/pslogin/src/main/scala/WorldSessionActor.scala +++ b/pslogin/src/main/scala/WorldSessionActor.scala @@ -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 _ => ; }