From 4bb294c62199a492a7ca8855cc46160f1bc9c382 Mon Sep 17 00:00:00 2001 From: Fate-JH Date: Fri, 5 Dec 2025 15:01:00 -0500 Subject: [PATCH] being affected by aggravated damage while mounted no longer produces an out of body experience; projectiles that separate into proxy damage may trigger upon contact --- .../WeaponAndProjectileOperations.scala | 15 +++++++++++++++ .../objects/avatar/PlayerControl.scala | 2 +- .../objects/equipment/EffectTarget.scala | 5 ++++- .../global/GlobalDefinitionsProjectile.scala | 18 ++++++++++++++++++ .../objects/vital/prop/DamageProperties.scala | 17 ++++++++++++++++- 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/main/scala/net/psforever/actors/session/support/WeaponAndProjectileOperations.scala b/src/main/scala/net/psforever/actors/session/support/WeaponAndProjectileOperations.scala index 280a282c3..b761d46ba 100644 --- a/src/main/scala/net/psforever/actors/session/support/WeaponAndProjectileOperations.scala +++ b/src/main/scala/net/psforever/actors/session/support/WeaponAndProjectileOperations.scala @@ -668,6 +668,18 @@ class WeaponAndProjectileOperations( .getOrElse(Nil) } + private def handleProxyDamage( + projectile: Projectile, + explosionPosition: Vector3 + ): List[(PlanetSideGameObject with FactionAffinity with Vitality, Projectile, Vector3, Vector3)] = { + val proxyList = resolveDamageProxy(projectile, projectile.GUID, explosionPosition) + proxyList.collectFirst { + case (_, proxy, _, _) if proxy.profile == GlobalDefinitions.oicw_little_buddy => + queueLittleBuddyExplosion(proxy) + } + proxyList + } + /** * Take a projectile that was introduced into the game world and * determine if it generates a secondary damage projectile or @@ -828,6 +840,9 @@ class WeaponAndProjectileOperations( if (projectile.isMiss) { None } else { + if (projectile.profile.DamageProxyOnDirectHit.exists(_.test(target))) { + handleProxyDamage(projectile, hitPosition) + } val outProjectile = ProjectileQuality.modifiers(projectile, resolution, target, hitPosition, Some(player)) if (projectile.tool_def.Size == EquipmentSize.Melee && outProjectile.quality == ProjectileQuality.Modified(25)) { avatarActor ! AvatarActor.ConsumeStamina(10) diff --git a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala index 03f74e764..dea237e9c 100644 --- a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala +++ b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala @@ -880,7 +880,7 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm //initial damage for aggravation, but never treat as "aggravated" false case _ => - cause.interaction.cause.source.Aggravated.nonEmpty + target.VehicleSeated.isEmpty && cause.interaction.cause.source.Aggravated.nonEmpty } //log historical event (always) target.LogActivity(cause) diff --git a/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala b/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala index 53aecdb94..dae476f0f 100644 --- a/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala +++ b/src/main/scala/net/psforever/objects/equipment/EffectTarget.scala @@ -17,7 +17,7 @@ object EffectTarget { * Arbitrary, but useful. */ object Category extends Enumeration { - val Aircraft, Deployable, Equipment, Player, Turret, Vehicle = Value + val Aircraft, Deployable, Equipment, Player, Turret, Vehicle, All = Value } object Validation { @@ -26,6 +26,9 @@ object EffectTarget { //noinspection ScalaUnusedSymbol def Invalid(target: PlanetSideGameObject): Boolean = false + //noinspection ScalaUnusedSymbol + def Valid(target: PlanetSideGameObject): Boolean = true + def Medical(target: PlanetSideGameObject): Boolean = target match { case p: Player => diff --git a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsProjectile.scala b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsProjectile.scala index a82c67748..2267824f7 100644 --- a/src/main/scala/net/psforever/objects/global/GlobalDefinitionsProjectile.scala +++ b/src/main/scala/net/psforever/objects/global/GlobalDefinitionsProjectile.scala @@ -1047,6 +1047,9 @@ object GlobalDefinitionsProjectile { maelstrom_grenade_projectile.InitialVelocity = 30 maelstrom_grenade_projectile.Lifespan = 2f maelstrom_grenade_projectile.DamageProxy = 464 //maelstrom_grenade_damager + maelstrom_grenade_projectile.DamageProxyOnDirectHit = List( + TargetValidation(EffectTarget.Category.All, EffectTarget.Validation.Valid) + ) ProjectileDefinition.CalculateDerivedFields(maelstrom_grenade_projectile) maelstrom_grenade_projectile.Modifiers = SameHit @@ -1062,6 +1065,9 @@ object GlobalDefinitionsProjectile { maelstrom_grenade_projectile_contact.InitialVelocity = 30 maelstrom_grenade_projectile_contact.Lifespan = 15f maelstrom_grenade_projectile_contact.DamageProxy = 464 //maelstrom_grenade_damager + maelstrom_grenade_projectile_contact.DamageProxyOnDirectHit = List( + TargetValidation(EffectTarget.Category.All, EffectTarget.Validation.Valid) + ) ProjectileDefinition.CalculateDerivedFields(maelstrom_grenade_projectile_contact) maelstrom_grenade_projectile_contact.Modifiers = SameHit @@ -1554,6 +1560,9 @@ object GlobalDefinitionsProjectile { radiator_grenade_projectile.InitialVelocity = 30 radiator_grenade_projectile.Lifespan = 3f radiator_grenade_projectile.DamageProxy = 717 //radiator_cloud + radiator_grenade_projectile.DamageProxyOnDirectHit = List( + TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player) + ) ProjectileDefinition.CalculateDerivedFields(radiator_grenade_projectile) radiator_sticky_projectile.Name = "radiator_sticky_projectile" @@ -1563,6 +1572,9 @@ object GlobalDefinitionsProjectile { radiator_sticky_projectile.InitialVelocity = 30 radiator_sticky_projectile.Lifespan = 4f radiator_sticky_projectile.DamageProxy = 717 //radiator_cloud + radiator_sticky_projectile.DamageProxyOnDirectHit = List( + TargetValidation(EffectTarget.Category.All, EffectTarget.Validation.Valid) + ) ProjectileDefinition.CalculateDerivedFields(radiator_sticky_projectile) reaver_rocket_projectile.Name = "reaver_rocket_projectile" @@ -2041,6 +2053,9 @@ object GlobalDefinitionsProjectile { aphelion_plasma_rocket_projectile.DamageRadius = 3f aphelion_plasma_rocket_projectile.ProjectileDamageType = DamageType.Splash //aphelion_plasma_rocket_projectile.DamageProxy = 96 //aphelion_plama_cloud + aphelion_plasma_rocket_projectile.DamageProxyOnDirectHit = List( + TargetValidation(EffectTarget.Category.All, EffectTarget.Validation.Valid) + ) aphelion_plasma_rocket_projectile.InitialVelocity = 75 aphelion_plasma_rocket_projectile.Lifespan = 5f ProjectileDefinition.CalculateDerivedFields(aphelion_plasma_rocket_projectile) @@ -2206,6 +2221,9 @@ object GlobalDefinitionsProjectile { peregrine_particle_cannon_projectile.DamageRadius = 3f peregrine_particle_cannon_projectile.ProjectileDamageType = DamageType.Splash //peregrine_particle_cannon_projectile.DamageProxy = 655 //peregrine_particle_cannon_radiation_cloud + peregrine_particle_cannon_projectile.DamageProxyOnDirectHit = List( + TargetValidation(EffectTarget.Category.All, EffectTarget.Validation.Valid) + ) peregrine_particle_cannon_projectile.InitialVelocity = 500 peregrine_particle_cannon_projectile.Lifespan = .6f ProjectileDefinition.CalculateDerivedFields(peregrine_particle_cannon_projectile) diff --git a/src/main/scala/net/psforever/objects/vital/prop/DamageProperties.scala b/src/main/scala/net/psforever/objects/vital/prop/DamageProperties.scala index c7e8c18c3..5772b39d5 100644 --- a/src/main/scala/net/psforever/objects/vital/prop/DamageProperties.scala +++ b/src/main/scala/net/psforever/objects/vital/prop/DamageProperties.scala @@ -2,7 +2,7 @@ package net.psforever.objects.vital.prop import net.psforever.objects.ballistics.{AggravatedDamage, ChargeDamage} -import net.psforever.objects.equipment.JammingUnit +import net.psforever.objects.equipment.{JammingUnit, TargetValidation} import net.psforever.objects.vital.base.{DamageModifiers, DamageType} import net.psforever.objects.vital.damage.StandardDamageProfile @@ -33,6 +33,9 @@ trait DamageProperties * usually corresponding to a projectile; * also used to produce staged projectiles */ private var damageProxy: List[Int] = Nil + /** damage proxies are expected to activate upon general detonation + * this damage proxy will also activate upon direct hit of these specific types of targets */ + private var damageProxyOnDirectHit: List[TargetValidation] = Nil /** na; * currently used with jammer properties only; * used sepcifically to indicate jammering effect targets explosive deployables */ @@ -107,6 +110,18 @@ trait DamageProperties DamageProxy } + def DamageProxyOnDirectHit: List[TargetValidation] = damageProxyOnDirectHit + + def DamageProxyOnDirectHit_=(elem: TargetValidation): List[TargetValidation] = { + damageProxyOnDirectHit = List(elem) + DamageProxyOnDirectHit + } + + def DamageProxyOnDirectHit_=(list: List[TargetValidation]): List[TargetValidation] = { + damageProxyOnDirectHit = list + DamageProxyOnDirectHit + } + def AdditionalEffect: Boolean = additionalEffect def AdditionalEffect_=(effect: Boolean): Boolean = {