mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
stop reporting the origin of a projectile as a valid hit position; creating pipelines for either damage proxy management and no damage proxy management
This commit is contained in:
parent
b02de0f80a
commit
01c014a59c
|
|
@ -127,14 +127,14 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
val list = ops.composeDirectDamageInformation(pkt)
|
val list = ops.composeDirectDamageInformation(pkt)
|
||||||
if (!player.spectator) {
|
if (!player.spectator) {
|
||||||
list.foreach {
|
list.foreach {
|
||||||
case (target, projectile, _, _) =>
|
case (target, projectile, _, targetPos) =>
|
||||||
ops.resolveProjectileInteraction(target, projectile, DamageResolution.Hit, target.Position)
|
ops.resolveProjectileInteractionAndProxy(target, projectile, DamageResolution.Hit, targetPos)
|
||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
if (list.isEmpty) {
|
if (list.isEmpty) {
|
||||||
ops.handleProxyDamage(pkt.projectile_guid, pkt.hit_info.map(_.hit_pos).getOrElse(Vector3.Zero)).foreach {
|
ops.handleProxyDamage(pkt.projectile_guid, pkt.hit_info.map(_.hit_pos).getOrElse(Vector3.Zero)).foreach {
|
||||||
case (target, proxy, hitPos, _) =>
|
case (target, proxy, _, targetPos) =>
|
||||||
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Hit, hitPos)
|
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Hit, targetPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,12 +157,12 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
//...
|
//...
|
||||||
val (direct, others) = list.partition { case (_, _, hitPos, targetPos) => hitPos == targetPos }
|
val (direct, others) = list.partition { case (_, _, hitPos, targetPos) => hitPos == targetPos }
|
||||||
direct.foreach {
|
direct.foreach {
|
||||||
case (target, _, _, _) =>
|
case (target, _, _, targetPos) =>
|
||||||
ops.resolveProjectileInteraction(target, projectile, resolution1, target.Position)
|
ops.resolveProjectileInteractionAndProxy(target, projectile, resolution1, targetPos)
|
||||||
}
|
}
|
||||||
others.foreach {
|
others.foreach {
|
||||||
case (target, _, _, _) =>
|
case (target, _, _, targetPos) =>
|
||||||
ops.resolveProjectileInteraction(target, projectile, resolution2, target.Position)
|
ops.resolveProjectileInteraction(target, projectile, resolution2, targetPos)
|
||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
if (
|
if (
|
||||||
|
|
@ -183,11 +183,11 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
if (profile.ExistsOnRemoteClients && projectile.HasGUID) {
|
if (profile.ExistsOnRemoteClients && projectile.HasGUID) {
|
||||||
continent.Projectile ! ZoneProjectile.Remove(projectileGuid)
|
continent.Projectile ! ZoneProjectile.Remove(projectileGuid)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
//...
|
ops.handleProxyDamage(pkt.projectile_uid, pkt.projectile_pos).foreach {
|
||||||
ops.handleProxyDamage(pkt.projectile_uid, pkt.projectile_pos).foreach {
|
case (target, proxy, _, targetPos) =>
|
||||||
case (target, proxy, hitPos, _) =>
|
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Splash, targetPos)
|
||||||
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Splash, hitPos)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,9 +144,9 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
val projectileGuid = pkt.projectile_guid
|
val projectileGuid = pkt.projectile_guid
|
||||||
val list = ops.composeDirectDamageInformation(pkt)
|
val list = ops.composeDirectDamageInformation(pkt)
|
||||||
.collect {
|
.collect {
|
||||||
case (target, projectile, hitPos, _) =>
|
case (target, projectile, hitPos, targetPos) =>
|
||||||
ops.checkForHitPositionDiscrepancy(projectileGuid, hitPos, target)
|
ops.checkForHitPositionDiscrepancy(projectileGuid, hitPos, targetPos)
|
||||||
ops.resolveProjectileInteraction(target, projectile, DamageResolution.Hit, hitPos)
|
ops.resolveProjectileInteractionAndProxy(target, projectile, DamageResolution.Hit, hitPos)
|
||||||
projectile
|
projectile
|
||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
|
|
@ -174,9 +174,9 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
//...
|
//...
|
||||||
val (direct, others) = list.partition { case (_, _, hitPos, targetPos) => hitPos == targetPos }
|
val (direct, others) = list.partition { case (_, _, hitPos, targetPos) => hitPos == targetPos }
|
||||||
direct.foreach {
|
direct.foreach {
|
||||||
case (target, _, hitPos, _) =>
|
case (target, _, hitPos, targetPos) =>
|
||||||
ops.checkForHitPositionDiscrepancy(projectileGuid, hitPos, target)
|
ops.checkForHitPositionDiscrepancy(projectileGuid, hitPos, targetPos)
|
||||||
ops.resolveProjectileInteraction(target, projectile, resolution1, hitPos)
|
ops.resolveProjectileInteractionAndProxy(target, projectile, resolution1, hitPos)
|
||||||
}
|
}
|
||||||
others.foreach {
|
others.foreach {
|
||||||
case (target, _, hitPos, _) =>
|
case (target, _, hitPos, _) =>
|
||||||
|
|
@ -202,19 +202,19 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
//cleanup
|
//cleanup
|
||||||
continent.Projectile ! ZoneProjectile.Remove(projectile.GUID)
|
continent.Projectile ! ZoneProjectile.Remove(projectile.GUID)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
//...
|
ops.handleProxyDamage(pkt.projectile_uid, pkt.projectile_pos).foreach {
|
||||||
ops.handleProxyDamage(pkt.projectile_uid, pkt.projectile_pos).foreach {
|
case (target, proxy, hitPos, _) =>
|
||||||
case (target, proxy, hitPos, _) =>
|
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Splash, hitPos)
|
||||||
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Splash, hitPos)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleLashHit(pkt: LashMessage): Unit = {
|
def handleLashHit(pkt: LashMessage): Unit = {
|
||||||
val list = ops.composeLashDamageInformation(pkt)
|
val list = ops.composeLashDamageInformation(pkt)
|
||||||
list.foreach {
|
list.foreach {
|
||||||
case (target, projectile, hitPos, _) =>
|
case (target, projectile, hitPos, targetPos) =>
|
||||||
ops.checkForHitPositionDiscrepancy(projectile.GUID, hitPos, target)
|
ops.checkForHitPositionDiscrepancy(projectile.GUID, hitPos, targetPos)
|
||||||
ops.resolveProjectileInteraction(target, projectile, DamageResolution.Lash, hitPos)
|
ops.resolveProjectileInteraction(target, projectile, DamageResolution.Lash, hitPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -223,8 +223,8 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
val list = ops.composeAIDamageInformation(pkt)
|
val list = ops.composeAIDamageInformation(pkt)
|
||||||
if (ops.confirmAIDamageTarget(pkt, list.map(_._1))) {
|
if (ops.confirmAIDamageTarget(pkt, list.map(_._1))) {
|
||||||
list.foreach {
|
list.foreach {
|
||||||
case (target, projectile, hitPos, _) =>
|
case (target, projectile, hitPos, targetPos) =>
|
||||||
ops.checkForHitPositionDiscrepancy(pkt.attacker_guid, hitPos, target)
|
ops.checkForHitPositionDiscrepancy(pkt.attacker_guid, hitPos, targetPos)
|
||||||
ops.resolveProjectileInteraction(target, projectile, DamageResolution.Hit, hitPos)
|
ops.resolveProjectileInteraction(target, projectile, DamageResolution.Hit, hitPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -513,6 +513,7 @@ class WeaponAndProjectileOperations(
|
||||||
hit_info match {
|
hit_info match {
|
||||||
case Some(hitInfo) =>
|
case Some(hitInfo) =>
|
||||||
val hitPos = hitInfo.hit_pos
|
val hitPos = hitInfo.hit_pos
|
||||||
|
projectile.Position = hitPos
|
||||||
sessionLogic.validObject(hitInfo.hitobject_guid, decorator = "Hit/hitInfo") match {
|
sessionLogic.validObject(hitInfo.hitobject_guid, decorator = "Hit/hitInfo") match {
|
||||||
case _ if projectile.profile == GlobalDefinitions.flail_projectile =>
|
case _ if projectile.profile == GlobalDefinitions.flail_projectile =>
|
||||||
val radius = projectile.profile.DamageRadius * projectile.profile.DamageRadius
|
val radius = projectile.profile.DamageRadius * projectile.profile.DamageRadius
|
||||||
|
|
@ -522,7 +523,7 @@ class WeaponAndProjectileOperations(
|
||||||
.map(target => (target, projectile, hitPos, target.Position))
|
.map(target => (target, projectile, hitPos, target.Position))
|
||||||
|
|
||||||
case Some(target: PlanetSideGameObject with FactionAffinity with Vitality) =>
|
case Some(target: PlanetSideGameObject with FactionAffinity with Vitality) =>
|
||||||
List((target, projectile, hitInfo.shot_origin, hitPos))
|
List((target, projectile, hitPos, target.Position))
|
||||||
|
|
||||||
case None =>
|
case None =>
|
||||||
Nil
|
Nil
|
||||||
|
|
@ -585,7 +586,9 @@ class WeaponAndProjectileOperations(
|
||||||
FindProjectileEntry(projectile_guid)
|
FindProjectileEntry(projectile_guid)
|
||||||
.flatMap {
|
.flatMap {
|
||||||
projectile =>
|
projectile =>
|
||||||
sessionLogic
|
//projectile may still be moving, and may lash other targets in the future when in a different position
|
||||||
|
projectile.Position = hit_pos
|
||||||
|
sessionLogic
|
||||||
.validObject(victim_guid, decorator = "LashHit/victim_guid")
|
.validObject(victim_guid, decorator = "LashHit/victim_guid")
|
||||||
.collect {
|
.collect {
|
||||||
case target: PlanetSideGameObject with FactionAffinity with Vitality =>
|
case target: PlanetSideGameObject with FactionAffinity with Vitality =>
|
||||||
|
|
@ -826,6 +829,26 @@ class WeaponAndProjectileOperations(
|
||||||
context.system.scheduler.scheduleOnce(500.milliseconds) { explosionFunc() }
|
context.system.scheduler.scheduleOnce(500.milliseconds) { explosionFunc() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a projectile with the given globally unique identifier and mark it as a resolved shot.
|
||||||
|
* A `Resolved` shot has either encountered an obstacle or is being cleaned up for not finding an obstacle.
|
||||||
|
* Check if we are required to deal with damage proxy management as well.
|
||||||
|
* @param projectile projectile
|
||||||
|
* @param resolution resolution status to promote the projectile
|
||||||
|
* @return package that contains information about the damage
|
||||||
|
*/
|
||||||
|
def resolveProjectileInteractionAndProxy(
|
||||||
|
target: PlanetSideGameObject with FactionAffinity with Vitality,
|
||||||
|
projectile: Projectile,
|
||||||
|
resolution: DamageResolution.Value,
|
||||||
|
hitPosition: Vector3
|
||||||
|
): Option[DamageInteraction] = {
|
||||||
|
if (projectile.profile.DamageProxyOnDirectHit.exists(_.test(target))) {
|
||||||
|
handleProxyDamage(projectile, hitPosition)
|
||||||
|
}
|
||||||
|
resolveProjectileInteraction(target, projectile, resolution, hitPosition)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a projectile with the given globally unique identifier and mark it as a resolved shot.
|
* Find a projectile with the given globally unique identifier and mark it as a resolved shot.
|
||||||
* A `Resolved` shot has either encountered an obstacle or is being cleaned up for not finding an obstacle.
|
* A `Resolved` shot has either encountered an obstacle or is being cleaned up for not finding an obstacle.
|
||||||
|
|
@ -842,9 +865,6 @@ class WeaponAndProjectileOperations(
|
||||||
if (projectile.isMiss) {
|
if (projectile.isMiss) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
if (projectile.profile.DamageProxyOnDirectHit.exists(_.test(target))) {
|
|
||||||
handleProxyDamage(projectile, hitPosition)
|
|
||||||
}
|
|
||||||
val outProjectile = ProjectileQuality.modifiers(projectile, resolution, target, hitPosition, Some(player))
|
val outProjectile = ProjectileQuality.modifiers(projectile, resolution, target, hitPosition, Some(player))
|
||||||
if (projectile.tool_def.Size == EquipmentSize.Melee && outProjectile.quality == ProjectileQuality.Modified(25)) {
|
if (projectile.tool_def.Size == EquipmentSize.Melee && outProjectile.quality == ProjectileQuality.Modified(25)) {
|
||||||
avatarActor ! AvatarActor.ConsumeStamina(10)
|
avatarActor ! AvatarActor.ConsumeStamina(10)
|
||||||
|
|
@ -1462,15 +1482,23 @@ class WeaponAndProjectileOperations(
|
||||||
}
|
}
|
||||||
|
|
||||||
def checkForHitPositionDiscrepancy(
|
def checkForHitPositionDiscrepancy(
|
||||||
projectile_guid: PlanetSideGUID,
|
projectileGuid: PlanetSideGUID,
|
||||||
hitPos: Vector3,
|
hitPosition: Vector3,
|
||||||
target: PlanetSideGameObject with Vitality
|
target: PlanetSideGameObject with Vitality
|
||||||
): Unit = {
|
): Unit = {
|
||||||
val hitPositionDiscrepancy = Vector3.DistanceSquared(hitPos, target.Position)
|
checkForHitPositionDiscrepancy(projectileGuid, hitPosition, target.Position)
|
||||||
|
}
|
||||||
|
|
||||||
|
def checkForHitPositionDiscrepancy(
|
||||||
|
projectileGuid: PlanetSideGUID,
|
||||||
|
hitPosition: Vector3,
|
||||||
|
targetPosition: Vector3
|
||||||
|
): Unit = {
|
||||||
|
val hitPositionDiscrepancy = Vector3.DistanceSquared(hitPosition, targetPosition)
|
||||||
if (hitPositionDiscrepancy > Config.app.antiCheat.hitPositionDiscrepancyThreshold) {
|
if (hitPositionDiscrepancy > Config.app.antiCheat.hitPositionDiscrepancyThreshold) {
|
||||||
// If the target position on the server does not match the position where the projectile landed within reason there may be foul play
|
// If the target position on the server does not match the position where the projectile landed within reason there may be foul play
|
||||||
log.warn(
|
log.warn(
|
||||||
s"${player.Name}'s shot #${projectile_guid.guid} has hit discrepancy with target. Target: ${target.Position}, Reported: $hitPos, Distance: $hitPositionDiscrepancy / ${math.sqrt(hitPositionDiscrepancy).toFloat}; suspect"
|
s"${player.Name}'s shot #${projectileGuid.guid} has hit discrepancy with target. Target: $targetPosition, Reported: $hitPosition, Distance: $hitPositionDiscrepancy / ${math.sqrt(hitPositionDiscrepancy).toFloat}; suspect"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue