diff --git a/common/src/main/scala/net/psforever/objects/avatar/AuraEffectBehavior.scala b/common/src/main/scala/net/psforever/objects/avatar/AuraEffectBehavior.scala index 3a467a94..0d4cb0ab 100644 --- a/common/src/main/scala/net/psforever/objects/avatar/AuraEffectBehavior.scala +++ b/common/src/main/scala/net/psforever/objects/avatar/AuraEffectBehavior.scala @@ -13,43 +13,63 @@ import scala.concurrent.ExecutionContext.Implicits.global trait AuraEffectBehavior { _ : Actor => private var activeEffectIndex : Long = 0 - private var effectsToIds : mutable.HashMap[Aura.Value, List[Long]] = mutable.HashMap.empty[Aura.Value, List[Long]] - private var idsToTimers : mutable.LongMap[Cancellable] = mutable.LongMap.empty[Cancellable] + private var effectsToIds : mutable.HashMap[Aura.Value, List[Long]] = mutable.HashMap.empty[Aura.Value, List[Long]] + private var idsToTimers : mutable.LongMap[Cancellable] = mutable.LongMap.empty[Cancellable] private var idsToEntries : mutable.LongMap[AuraEffectBehavior.Entry] = mutable.LongMap.empty[AuraEffectBehavior.Entry] def AuraTargetObject : Player val auraBehavior : Receive = { - case AuraEffectBehavior.Aggravate(id, 0) => - CleanupEffect(id) match { - case Aura.None => ; - case _ => UpdateAggravatedEffect(AuraTargetObject) - } + case AuraEffectBehavior.Aggravate(id, 0, 0) => + CancelEffectTimer(id) + PerformCleanupEffect(id) - case AuraEffectBehavior.Aggravate(id, iteration) => ; - idsToTimers.remove(id) match { - case Some(timer) => timer.cancel - case _ => ; - } - idsToEntries.get(id) match { - case Some(entry) => - //TODO stuff ... - idsToTimers += id -> context.system.scheduler.scheduleOnce( - entry.effect.infliction_rate milliseconds, self, AuraEffectBehavior.Aggravate(id, iteration - 1)) - case _ => ; - } + case AuraEffectBehavior.Aggravate(id, 0, leftoverTime) => + PerformAggravationAndRetimeEvent(id, iteration = 0, Some(leftoverTime), leftoverTime = 0) + + case AuraEffectBehavior.Aggravate(id, iteration, leftover) => ; + PerformAggravationAndRetimeEvent(id, iteration - 1, None, leftover) } - def AggravationEffect(data : ResolvedProjectile) : Unit = { - data.projectile.profile.Aggravated match { - case Some(damage) - if data.projectile.profile.ProjectileDamageType == DamageType.Aggravated && damage.effect_type != Aura.None => - AggravationEffect(damage, data) + def PerformAggravationAndRetimeEvent(id : Long, iteration : Int, time : Option[Long], leftoverTime : Long) : Unit = { + CancelEffectTimer(id) + idsToEntries.get(id) match { + case Some(entry) => + //TODO stuff ... + idsToTimers += id -> context.system.scheduler.scheduleOnce( + time.getOrElse(entry.effect.infliction_rate) milliseconds, + self, + AuraEffectBehavior.Aggravate(id, iteration, leftoverTime) + ) + case _ => + PerformCleanupEffect(id) + } + } + + def CancelEffectTimer(id : Long) : Unit = { + idsToTimers.remove(id) match { + case Some(timer) => timer.cancel case _ => ; } } - private def AggravationEffect(aggravation : AggravatedDamage, data : ResolvedProjectile) : Unit = { + def PerformCleanupEffect(id : Long) : Unit = { + CleanupEffect(id) match { + case Aura.None => ; + case _ => UpdateAggravatedEffect(AuraTargetObject) + } + } + + def TryAggravationEffect(data : ResolvedProjectile) : Unit = { + data.projectile.profile.Aggravated match { + case Some(damage) + if data.projectile.profile.ProjectileDamageType == DamageType.Aggravated && damage.effect_type != Aura.None => + TryAggravationEffect(damage, data) + case _ => ; + } + } + + private def TryAggravationEffect(aggravation : AggravatedDamage, data : ResolvedProjectile) : Unit = { val effect = aggravation.effect_type val obj = AuraTargetObject if(obj.Aura.contains(effect)) { //TODO cumulative? @@ -76,7 +96,8 @@ trait AuraEffectBehavior { idsToEntries += id -> AuraEffectBehavior.Entry(id, infos, aggravation, 0) //pair id with timer val iterations = (aggravation.duration / infos.infliction_rate).toInt - idsToTimers += id -> context.system.scheduler.scheduleOnce(infos.infliction_rate milliseconds, self, AuraEffectBehavior.Aggravate(id, iterations)) + val leftoverTime = aggravation.duration % infos.infliction_rate + idsToTimers += id -> context.system.scheduler.scheduleOnce(infos.infliction_rate milliseconds, self, AuraEffectBehavior.Aggravate(id, iterations, leftoverTime)) } } @@ -112,6 +133,10 @@ trait AuraEffectBehavior { idsToTimers.values.foreach { _.cancel } idsToTimers.clear effectsToIds.clear + } + + def EndAllEffectsAndUpdate() : Unit = { + EndAllEffects() UpdateAggravatedEffect(AuraTargetObject) } @@ -126,5 +151,5 @@ trait AuraEffectBehavior { object AuraEffectBehavior { private case class Entry(id : Long, effect : AggravatedInfo, aggravation : AggravatedDamage, damage : Any) - private case class Aggravate(id : Long, iteration : Int) + private case class Aggravate(id : Long, iterations : Int, leftover : Long) } diff --git a/src/main/scala/net/psforever/actors/session/SessionActor.scala b/src/main/scala/net/psforever/actors/session/SessionActor.scala index a76870c1..06cf7d55 100644 --- a/src/main/scala/net/psforever/actors/session/SessionActor.scala +++ b/src/main/scala/net/psforever/actors/session/SessionActor.scala @@ -5411,9 +5411,15 @@ class SessionActor extends Actor with MDCContextAware { projectile.Velocity = projectile_vel //direct_victim_uid ValidObject(direct_victim_uid) match { - case Some(target: PlanetSideGameObject with FactionAffinity with Vitality) => - CheckForHitPositionDiscrepancy(projectile_guid, explosion_pos, target) - ResolveProjectileEntry(projectile, ProjectileResolution.Splash, target, target.Position) match { + case Some( + target: PlanetSideGameObject with FactionAffinity with Vitality + ) => + CheckForHitPositionDiscrepancy( + projectile_guid, + explosion_pos, + target + ) + ResolveProjectileEntry(projectile, ProjectileResolution.Splash, target, explosion_pos) match { case Some(projectile) => HandleDealingDamage(target, projectile) case None => ; diff --git a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala index c581a8a5..dbdf1411 100644 --- a/src/main/scala/net/psforever/objects/GlobalDefinitions.scala +++ b/src/main/scala/net/psforever/objects/GlobalDefinitions.scala @@ -2474,6 +2474,7 @@ object GlobalDefinitions { dynomite_projectile.Damage1 = 175 dynomite_projectile.DamageAtEdge = 0.1f dynomite_projectile.DamageRadius = 10f + dynomite_projectile.GrenadeProjectile = true dynomite_projectile.ProjectileDamageType = DamageType.Splash dynomite_projectile.InitialVelocity = 30 dynomite_projectile.Lifespan = 3f @@ -2691,6 +2692,7 @@ object GlobalDefinitions { frag_cartridge_projectile.Damage1 = 100 frag_cartridge_projectile.DamageAtEdge = 0.1f frag_cartridge_projectile.DamageRadius = 7f + frag_cartridge_projectile.GrenadeProjectile = true frag_cartridge_projectile.ProjectileDamageType = DamageType.Splash frag_cartridge_projectile.InitialVelocity = 30 frag_cartridge_projectile.Lifespan = 15f @@ -2703,6 +2705,7 @@ object GlobalDefinitions { frag_cartridge_projectile_b.Damage1 = 100 frag_cartridge_projectile_b.DamageAtEdge = 0.1f frag_cartridge_projectile_b.DamageRadius = 5f + frag_cartridge_projectile_b.GrenadeProjectile = true frag_cartridge_projectile_b.ProjectileDamageType = DamageType.Splash frag_cartridge_projectile_b.InitialVelocity = 30 frag_cartridge_projectile_b.Lifespan = 2f @@ -2714,6 +2717,7 @@ object GlobalDefinitions { frag_grenade_projectile.Damage1 = 100 frag_grenade_projectile.DamageAtEdge = 0.1f frag_grenade_projectile.DamageRadius = 7f + frag_grenade_projectile.GrenadeProjectile = true frag_grenade_projectile.ProjectileDamageType = DamageType.Splash frag_grenade_projectile.InitialVelocity = 30 frag_grenade_projectile.Lifespan = 15f @@ -2726,6 +2730,7 @@ object GlobalDefinitions { frag_grenade_projectile_enh.Damage1 = 100 frag_grenade_projectile_enh.DamageAtEdge = 0.1f frag_grenade_projectile_enh.DamageRadius = 7f + frag_grenade_projectile_enh.GrenadeProjectile = true frag_grenade_projectile_enh.ProjectileDamageType = DamageType.Splash frag_grenade_projectile_enh.InitialVelocity = 30 frag_grenade_projectile_enh.Lifespan = 2f @@ -2776,6 +2781,7 @@ object GlobalDefinitions { heavy_grenade_projectile.Damage4 = 66 heavy_grenade_projectile.DamageAtEdge = 0.1f heavy_grenade_projectile.DamageRadius = 5f + heavy_grenade_projectile.GrenadeProjectile = true heavy_grenade_projectile.ProjectileDamageType = DamageType.Splash heavy_grenade_projectile.InitialVelocity = 75 heavy_grenade_projectile.Lifespan = 5f @@ -2861,6 +2867,7 @@ object GlobalDefinitions { jammer_cartridge_projectile.Damage1 = 0 jammer_cartridge_projectile.DamageAtEdge = 1.0f jammer_cartridge_projectile.DamageRadius = 10f + jammer_cartridge_projectile.GrenadeProjectile = true jammer_cartridge_projectile.ProjectileDamageType = DamageType.Splash jammer_cartridge_projectile.InitialVelocity = 30 jammer_cartridge_projectile.Lifespan = 15f @@ -2899,6 +2906,7 @@ object GlobalDefinitions { jammer_cartridge_projectile_b.Damage1 = 0 jammer_cartridge_projectile_b.DamageAtEdge = 1.0f jammer_cartridge_projectile_b.DamageRadius = 10f + jammer_cartridge_projectile_b.GrenadeProjectile = true jammer_cartridge_projectile_b.ProjectileDamageType = DamageType.Splash jammer_cartridge_projectile_b.InitialVelocity = 30 jammer_cartridge_projectile_b.Lifespan = 2f @@ -2936,6 +2944,7 @@ object GlobalDefinitions { jammer_grenade_projectile.Damage1 = 0 jammer_grenade_projectile.DamageAtEdge = 1.0f jammer_grenade_projectile.DamageRadius = 10f + jammer_grenade_projectile.GrenadeProjectile = true jammer_grenade_projectile.ProjectileDamageType = DamageType.Splash jammer_grenade_projectile.InitialVelocity = 30 jammer_grenade_projectile.Lifespan = 15f @@ -2974,6 +2983,7 @@ object GlobalDefinitions { jammer_grenade_projectile_enh.Damage1 = 0 jammer_grenade_projectile_enh.DamageAtEdge = 1.0f jammer_grenade_projectile_enh.DamageRadius = 10f + jammer_grenade_projectile_enh.GrenadeProjectile = true jammer_grenade_projectile_enh.ProjectileDamageType = DamageType.Splash jammer_grenade_projectile_enh.InitialVelocity = 30 jammer_grenade_projectile_enh.Lifespan = 3f @@ -3104,6 +3114,7 @@ object GlobalDefinitions { maelstrom_grenade_projectile.Damage1 = 60 maelstrom_grenade_projectile.DamageRadius = 20f maelstrom_grenade_projectile.LashRadius = 5f + maelstrom_grenade_projectile.GrenadeProjectile = true maelstrom_grenade_projectile.ProjectileDamageType = DamageType.Direct maelstrom_grenade_projectile.InitialVelocity = 30 maelstrom_grenade_projectile.Lifespan = 2f @@ -3117,6 +3128,7 @@ object GlobalDefinitions { maelstrom_grenade_projectile_contact.Damage1 = 60 maelstrom_grenade_projectile_contact.DamageRadius = 20f maelstrom_grenade_projectile_contact.LashRadius = 5f + maelstrom_grenade_projectile_contact.GrenadeProjectile = true maelstrom_grenade_projectile_contact.ProjectileDamageType = DamageType.Direct maelstrom_grenade_projectile_contact.InitialVelocity = 30 maelstrom_grenade_projectile_contact.Lifespan = 15f @@ -3241,6 +3253,7 @@ object GlobalDefinitions { mine_sweeper_projectile.Damage1 = 0 mine_sweeper_projectile.DamageAtEdge = .33f mine_sweeper_projectile.DamageRadius = 25f + mine_sweeper_projectile.GrenadeProjectile = true mine_sweeper_projectile.ProjectileDamageType = DamageType.Splash mine_sweeper_projectile.InitialVelocity = 30 mine_sweeper_projectile.Lifespan = 15f @@ -3252,6 +3265,7 @@ object GlobalDefinitions { mine_sweeper_projectile_enh.Damage1 = 0 mine_sweeper_projectile_enh.DamageAtEdge = 0.33f mine_sweeper_projectile_enh.DamageRadius = 25f + mine_sweeper_projectile_enh.GrenadeProjectile = true mine_sweeper_projectile_enh.ProjectileDamageType = DamageType.Splash mine_sweeper_projectile_enh.InitialVelocity = 30 mine_sweeper_projectile_enh.Lifespan = 3f @@ -3455,11 +3469,12 @@ object GlobalDefinitions { plasma_cartridge_projectile.Damage1 = 15 plasma_cartridge_projectile.DamageAtEdge = 0.2f plasma_cartridge_projectile.DamageRadius = 7f + plasma_cartridge_projectile.GrenadeProjectile = true plasma_cartridge_projectile.ProjectileDamageType = DamageType.Aggravated plasma_cartridge_projectile.Aggravated = AggravatedDamage( List(AggravatedInfo(DamageType.Direct, 0.25f, 750), AggravatedInfo(DamageType.Splash, 0.25f, 1000)), Aura.Plasma, - 0, + 4000, //hard-coded default? 1.5f, true, false @@ -3474,11 +3489,12 @@ object GlobalDefinitions { plasma_cartridge_projectile_b.Damage1 = 15 plasma_cartridge_projectile_b.DamageAtEdge = 0.2f plasma_cartridge_projectile_b.DamageRadius = 7f + plasma_cartridge_projectile_b.GrenadeProjectile = true plasma_cartridge_projectile_b.ProjectileDamageType = DamageType.Aggravated plasma_cartridge_projectile_b.Aggravated = AggravatedDamage( List(AggravatedInfo(DamageType.Direct, 0.25f, 750), AggravatedInfo(DamageType.Splash, 0.25f, 1000)), Aura.Plasma, - 0, + 4000, //hard-coded default? 1.5f, true, false @@ -3492,11 +3508,12 @@ object GlobalDefinitions { plasma_grenade_projectile.Damage1 = 30 plasma_grenade_projectile.DamageAtEdge = 0.1f plasma_grenade_projectile.DamageRadius = 7f + plasma_grenade_projectile.GrenadeProjectile = true plasma_grenade_projectile.ProjectileDamageType = DamageType.Aggravated plasma_grenade_projectile.Aggravated = AggravatedDamage( List(AggravatedInfo(DamageType.Direct, 0.25f, 750), AggravatedInfo(DamageType.Splash, 0.25f, 1000)), Aura.Plasma, - 0, + 4000, //hard-coded default? 1.5f, true, false @@ -3511,11 +3528,12 @@ object GlobalDefinitions { plasma_grenade_projectile_B.Damage1 = 30 plasma_grenade_projectile_B.DamageAtEdge = 0.1f plasma_grenade_projectile_B.DamageRadius = 7f + plasma_grenade_projectile_B.GrenadeProjectile = true plasma_grenade_projectile_B.ProjectileDamageType = DamageType.Aggravated plasma_grenade_projectile_B.Aggravated = AggravatedDamage( List(AggravatedInfo(DamageType.Direct, 0.25f, 750), AggravatedInfo(DamageType.Splash, 0.25f, 1000)), Aura.Plasma, - 0, + 4000, //hard-coded default? 1.5f, true, false @@ -3532,6 +3550,7 @@ object GlobalDefinitions { pounder_projectile.Damage4 = 132 pounder_projectile.DamageAtEdge = 0.1f pounder_projectile.DamageRadius = 1f + pounder_projectile.GrenadeProjectile = true pounder_projectile.ProjectileDamageType = DamageType.Splash pounder_projectile.InitialVelocity = 120 pounder_projectile.Lifespan = 2.5f @@ -3547,6 +3566,7 @@ object GlobalDefinitions { pounder_projectile_enh.Damage4 = 132 pounder_projectile_enh.DamageAtEdge = 0.1f pounder_projectile_enh.DamageRadius = 1f + pounder_projectile_enh.GrenadeProjectile = true pounder_projectile_enh.ProjectileDamageType = DamageType.Splash pounder_projectile_enh.InitialVelocity = 120 pounder_projectile_enh.Lifespan = 3.2f @@ -3598,6 +3618,7 @@ object GlobalDefinitions { ProjectileDefinition.CalculateDerivedFields(quasar_projectile) radiator_grenade_projectile.Name = "radiator_grenade_projectile" // Todo : Radiator damages ? + radiator_grenade_projectile.GrenadeProjectile = true //not really, but technically yes radiator_grenade_projectile.ProjectileDamageType = DamageType.Direct radiator_grenade_projectile.InitialVelocity = 30 radiator_grenade_projectile.Lifespan = 3f @@ -3605,6 +3626,7 @@ object GlobalDefinitions { radiator_sticky_projectile.Name = "radiator_sticky_projectile" // TODO for later, maybe : set_resource_parent radiator_sticky_projectile game_objects radiator_grenade_projectile + radiator_sticky_projectile.GrenadeProjectile = true //not really, but technically yes radiator_sticky_projectile.ProjectileDamageType = DamageType.Direct radiator_sticky_projectile.InitialVelocity = 30 radiator_sticky_projectile.Lifespan = 4f diff --git a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala index 7f9db7df..09d0550c 100644 --- a/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala +++ b/src/main/scala/net/psforever/objects/avatar/PlayerControl.scala @@ -30,13 +30,16 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm extends Actor with JammableBehavior with Damageable - with ContainableBehavior { + with ContainableBehavior + with AuraEffectBehavior { def JammableObject = player def DamageableObject = player def ContainerObject = player + def AuraTargetObject = player + private[this] val log = org.log4s.getLogger(player.Name) private[this] val damageLog = org.log4s.getLogger(Damageable.LogChannel) @@ -53,11 +56,13 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm override def postStop(): Unit = { lockerControlAgent ! akka.actor.PoisonPill player.avatar.locker.Actor = Default.Actor + EndAllEffects() } def receive: Receive = jammableBehavior .orElse(takesDamage) + .orElse(auraBehavior) .orElse(containerBehavior) .orElse { case Player.Die() => @@ -544,9 +549,11 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm //alert damage source DamageAwareness(target, cause) } + //special effects if (Damageable.CanJammer(target, cause)) { - target.Actor ! JammableUnit.Jammered(cause) + TryJammerEffectActivate(target, cause) } + TryAggravationEffect(cause) } else { DestructionAwareness(target, Some(cause)) } @@ -599,6 +606,8 @@ class PlayerControl(player: Player, avatarActor: typed.ActorRef[AvatarActor.Comm val nameChannel = target.Name val zoneChannel = zone.id target.Die + //aura effects cancel + EndAllEffects() //unjam CancelJammeredSound(target) CancelJammeredStatus(target) diff --git a/src/main/scala/net/psforever/objects/definition/ProjectileDefinition.scala b/src/main/scala/net/psforever/objects/definition/ProjectileDefinition.scala index 5b83ab1c..0bfab8f2 100644 --- a/src/main/scala/net/psforever/objects/definition/ProjectileDefinition.scala +++ b/src/main/scala/net/psforever/objects/definition/ProjectileDefinition.scala @@ -36,6 +36,7 @@ class ProjectileDefinition(objectId: Int) private var autoLock: Boolean = false private var additionalEffect: Boolean = false private var jammerProjectile: Boolean = false + private var grenade_projectile : Boolean = false private var aggravated_damage : Option[AggravatedDamage] = None //derived calculations private var distanceMax: Float = 0f @@ -175,6 +176,13 @@ class ProjectileDefinition(objectId: Int) JammerProjectile } + def GrenadeProjectile : Boolean = grenade_projectile + + def GrenadeProjectile_=(isGrenade : Boolean) : Boolean = { + grenade_projectile = isGrenade + GrenadeProjectile + } + def Aggravated : Option[AggravatedDamage] = aggravated_damage def Aggravated_=(damage : AggravatedDamage) : Option[AggravatedDamage] = Aggravated_=(Some(damage))