moved common jammering behavior into a mixin trait and redundant code out of the specific object control actors; created placeholder PlayerControl actor but am not ready to move damage/jammering functionality out from WSA; common jammering behavior modified for WSA use

This commit is contained in:
FateJH 2019-12-20 00:47:22 -05:00
parent fa2123f253
commit a568e52590
10 changed files with 222 additions and 191 deletions

View file

@ -3,8 +3,9 @@ package net.psforever.objects
import net.psforever.objects.avatar.LoadoutManager import net.psforever.objects.avatar.LoadoutManager
import net.psforever.objects.definition.{AvatarDefinition, ExoSuitDefinition, SpecialExoSuitDefinition} import net.psforever.objects.definition.{AvatarDefinition, ExoSuitDefinition, SpecialExoSuitDefinition}
import net.psforever.objects.equipment.{Equipment, EquipmentSize, EquipmentSlot} import net.psforever.objects.equipment.{Equipment, EquipmentSize, EquipmentSlot, JammableUnit}
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem} import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.affinity.FactionAffinity import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.vital.resistance.ResistanceProfile import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.objects.vital.{DamageResistanceModel, Vitality} import net.psforever.objects.vital.{DamageResistanceModel, Vitality}
@ -16,11 +17,12 @@ import net.psforever.types._
import scala.annotation.tailrec import scala.annotation.tailrec
import scala.util.{Success, Try} import scala.util.{Success, Try}
class Player(private val core : Avatar) extends PlanetSideGameObject class Player(private val core : Avatar) extends PlanetSideServerObject
with FactionAffinity with FactionAffinity
with Vitality with Vitality
with ResistanceProfile with ResistanceProfile
with Container with Container
with JammableUnit
with ZoneAware { with ZoneAware {
private var alive : Boolean = false private var alive : Boolean = false
private var backpack : Boolean = false private var backpack : Boolean = false

View file

@ -3,7 +3,7 @@ package net.psforever.objects
import akka.actor.ActorRef import akka.actor.ActorRef
import net.psforever.objects.definition.VehicleDefinition import net.psforever.objects.definition.VehicleDefinition
import net.psforever.objects.equipment.{Equipment, EquipmentSize, EquipmentSlot} import net.psforever.objects.equipment.{Equipment, EquipmentSize, EquipmentSlot, JammableUnit}
import net.psforever.objects.inventory.{Container, GridInventory, InventoryTile} import net.psforever.objects.inventory.{Container, GridInventory, InventoryTile}
import net.psforever.objects.serverobject.mount.Mountable import net.psforever.objects.serverobject.mount.Mountable
import net.psforever.objects.serverobject.PlanetSideServerObject import net.psforever.objects.serverobject.PlanetSideServerObject
@ -73,6 +73,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
with Vitality with Vitality
with OwnableByPlayer with OwnableByPlayer
with StandardResistanceProfile with StandardResistanceProfile
with JammableUnit
with Container { with Container {
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.TR private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.TR
private var health : Int = 1 private var health : Int = 1

View file

@ -0,0 +1,15 @@
// Copyright (c) 2019 PSForever
package net.psforever.objects.avatar
import akka.actor.Actor
import net.psforever.objects.Player
/**
* na;
* stub for future development
*/
class PlayerControl(player : Player) extends Actor {
def receive : Receive = {
case _ => ;
}
}

View file

@ -1,11 +1,19 @@
// Copyright (c) 2019 PSForever // Copyright (c) 2019 PSForever
package net.psforever.objects.equipment package net.psforever.objects.equipment
import net.psforever.objects.PlanetSideGameObject import akka.actor.{Actor, Cancellable}
import net.psforever.objects.{DefaultCancellable, PlanetSideGameObject, Tool}
import net.psforever.objects.ballistics.ResolvedProjectile import net.psforever.objects.ballistics.ResolvedProjectile
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.terminals.TargetValidation import net.psforever.objects.serverobject.terminals.TargetValidation
import net.psforever.objects.vehicles.MountedWeapons
import net.psforever.objects.zones.ZoneAware
import net.psforever.types.Vector3
import services.Service
import services.vehicle.{VehicleAction, VehicleServiceMessage}
import scala.collection.mutable import scala.collection.mutable
import scala.concurrent.duration._
trait JammableUnit { trait JammableUnit {
private var jammed : Boolean = false private var jammed : Boolean = false
@ -49,3 +57,104 @@ object JammingUnit {
targets.map { target => FindJammerDuration(jammer, target) } targets.map { target => FindJammerDuration(jammer, target) }
} }
} }
trait JammableBehavior {
_ : Actor =>
protected var jammeredSoundTimer : Cancellable = DefaultCancellable.obj
protected var jammeredStatusTimer : Cancellable = DefaultCancellable.obj
def JammableObject : PlanetSideServerObject with JammableUnit with ZoneAware
def TryJammerEffectActivate(target : Any, cause : ResolvedProjectile) : Unit
def StartJammeredSound(target : Any, dur : Int = 30000) : Unit = {
import scala.concurrent.ExecutionContext.Implicits.global
jammeredSoundTimer.cancel
jammeredSoundTimer = context.system.scheduler.scheduleOnce(30 seconds, self, JammableUnit.ClearJammeredSound())
}
def StartJammeredStatus(target : Any, dur : Int) : Unit = {
JammableObject.Jammed = true
jammeredStatusTimer.cancel
import scala.concurrent.ExecutionContext.Implicits.global
jammeredStatusTimer = context.system.scheduler.scheduleOnce(dur milliseconds, self, JammableUnit.ClearJammeredStatus())
}
def CancelJammeredSound(target : Any) : Unit = {
jammeredSoundTimer.cancel
}
def CancelJammeredStatus(target : Any) : Unit = {
JammableObject.Jammed = false
jammeredStatusTimer.cancel
}
def jammableBehavior : Receive = {
case JammableUnit.Jammered(cause) =>
TryJammerEffectActivate(JammableObject, cause)
case JammableUnit.ClearJammeredSound() =>
CancelJammeredSound(JammableObject)
case JammableUnit.ClearJammeredStatus() =>
CancelJammeredStatus(JammableObject)
}
}
trait JammableMountedWeapons extends Actor with JammableBehavior {
_ : Actor =>
def TryJammerEffectActivate(target : Any, cause : ResolvedProjectile) : Unit = target match {
case obj : PlanetSideServerObject with MountedWeapons =>
val radius = cause.projectile.profile.DamageRadius
JammingUnit.FindJammerDuration(cause.projectile.profile, obj) match {
case Some(dur) if Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius =>
StartJammeredSound(obj)
StartJammeredStatus(obj, dur)
case _ => ;
}
case _ => ;
}
override def StartJammeredSound(target : Any, dur : Int) : Unit = target match {
case obj : PlanetSideServerObject with MountedWeapons =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 1))
super.StartJammeredSound(obj, dur)
case _ => ;
}
override def StartJammeredStatus(target : Any, dur : Int) : Unit = target match {
case obj : PlanetSideServerObject with MountedWeapons =>
JammableMountedWeapons.JammeredStatus(obj, 1)
super.StartJammeredStatus(obj, dur)
case _ => ;
}
override def CancelJammeredSound(target : Any) : Unit = target match {
case obj : PlanetSideServerObject =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 0))
super.CancelJammeredSound(obj)
case _ => ;
}
override def CancelJammeredStatus(target : Any) : Unit = target match {
case obj : PlanetSideServerObject with MountedWeapons =>
JammableMountedWeapons.JammeredStatus(obj, 0)
super.CancelJammeredStatus(obj)
case _ => ;
}
}
object JammableMountedWeapons {
def JammeredStatus(target : PlanetSideServerObject with MountedWeapons, statusCode : Int) : Unit = {
val zone = target.Zone
val zoneId = zone.Id
zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 27, statusCode))
target.Weapons.values
.map { _.Equipment }
.collect {
case Some(item : Tool) =>
zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, item.GUID, 27, statusCode))
}
}
}

View file

@ -1,12 +1,14 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.turret package net.psforever.objects.serverobject.turret
import net.psforever.objects.equipment.JammableUnit
import net.psforever.objects.serverobject.structures.Amenity import net.psforever.objects.serverobject.structures.Amenity
import net.psforever.types.Vector3 import net.psforever.types.Vector3
import net.psforever.objects.vital.{DamageResistanceModel, StandardResistanceProfile, Vitality} import net.psforever.objects.vital.{DamageResistanceModel, StandardResistanceProfile, Vitality}
class FacilityTurret(tDef : TurretDefinition) extends Amenity class FacilityTurret(tDef : TurretDefinition) extends Amenity
with WeaponTurret with WeaponTurret
with JammableUnit
with Vitality with Vitality
with StandardResistanceProfile { with StandardResistanceProfile {
/** some turrets can be updated; they all start without updates */ /** some turrets can be updated; they all start without updates */

View file

@ -1,25 +1,19 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.turret package net.psforever.objects.serverobject.turret
import akka.actor.{Actor, Cancellable} import akka.actor.Actor
import net.psforever.objects.{DefaultCancellable, Tool}
import net.psforever.objects.ballistics.ResolvedProjectile import net.psforever.objects.ballistics.ResolvedProjectile
import net.psforever.objects.equipment.{JammableUnit, JammingUnit} import net.psforever.objects.equipment.{JammableMountedWeapons, JammableUnit}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior} import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior} import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.vehicles.MountedWeapons
import net.psforever.objects.vital.Vitality import net.psforever.objects.vital.Vitality
import net.psforever.objects.zones.Zone import net.psforever.objects.zones.Zone
import net.psforever.packet.game.PlanetSideGUID import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.Vector3
import services.Service import services.Service
import services.avatar.{AvatarAction, AvatarServiceMessage} import services.avatar.{AvatarAction, AvatarServiceMessage}
import services.vehicle.{VehicleAction, VehicleServiceMessage} import services.vehicle.{VehicleAction, VehicleServiceMessage}
import services.vehicle.support.TurretUpgrader import services.vehicle.support.TurretUpgrader
import scala.concurrent.duration._
/** /**
* An `Actor` that handles messages being dispatched to a specific `MannedTurret`.<br> * An `Actor` that handles messages being dispatched to a specific `MannedTurret`.<br>
* <br> * <br>
@ -30,11 +24,12 @@ import scala.concurrent.duration._
*/ */
class FacilityTurretControl(turret : FacilityTurret) extends Actor class FacilityTurretControl(turret : FacilityTurret) extends Actor
with FactionAffinityBehavior.Check with FactionAffinityBehavior.Check
with MountableBehavior.Dismount { with MountableBehavior.Dismount
var jammeredSoundTimer : Cancellable = DefaultCancellable.obj with JammableMountedWeapons {
var jammeredStatusTimer : Cancellable = DefaultCancellable.obj
def MountableObject = turret //do not add type! def MountableObject = turret
def JammableObject = turret
def FactionObject : FactionAffinity = turret def FactionObject : FactionAffinity = turret
@ -70,48 +65,8 @@ class FacilityTurretControl(turret : FacilityTurret) extends Actor
} }
} }
case JammableUnit.Jammered(cause) =>
TryJammerWithProjectile(turret, cause)
case JammableUnit.ClearJammeredSound() =>
CancelJammeredSound(turret)
case JammableUnit.ClearJammeredStatus() =>
StopJammeredStatus(turret)
case _ => ; case _ => ;
} }
def TryJammerWithProjectile(target : FacilityTurret, cause : ResolvedProjectile) : Unit = {
val radius = cause.projectile.profile.DamageRadius
JammingUnit.FindJammerDuration(cause.projectile.profile, target) match {
case Some(dur) if Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius =>
//jammered sound
target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 54, 1))
import scala.concurrent.ExecutionContext.Implicits.global
jammeredSoundTimer = context.system.scheduler.scheduleOnce(30 seconds, self, JammableUnit.ClearJammeredSound())
//jammered status
StartJammeredStatus(target, dur)
case _ => ;
}
}
def StartJammeredStatus(target : PlanetSideServerObject with MountedWeapons, dur : Int) : Unit = {
jammeredStatusTimer.cancel
FacilityTurretControl.JammeredStatus(target, 1)
import scala.concurrent.ExecutionContext.Implicits.global
jammeredStatusTimer = context.system.scheduler.scheduleOnce(dur milliseconds, self, JammableUnit.ClearJammeredStatus())
}
def StopJammeredStatus(target : PlanetSideServerObject with MountedWeapons) : Boolean = {
FacilityTurretControl.JammeredStatus(target, 0)
jammeredStatusTimer.cancel
}
def CancelJammeredSound(target : PlanetSideServerObject) : Unit = {
jammeredSoundTimer.cancel
target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 54, 0))
}
} }
object FacilityTurretControl { object FacilityTurretControl {
@ -195,16 +150,4 @@ object FacilityTurretControl {
zone.VehicleEvents ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.AddTask(target, zone, TurretUpgrade.None)) zone.VehicleEvents ! VehicleServiceMessage.TurretUpgrade(TurretUpgrader.AddTask(target, zone, TurretUpgrade.None))
} }
} }
def JammeredStatus(target : PlanetSideServerObject with MountedWeapons, statusCode : Int) : Unit = {
val zone = target.Zone
val zoneId = zone.Id
zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 27, statusCode))
target.Weapons.values
.map { _.Equipment }
.collect {
case Some(item : Tool) =>
zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, item.GUID, 27, statusCode))
}
}
} }

View file

@ -1,11 +1,10 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.objects.vehicles package net.psforever.objects.vehicles
import akka.actor.{Actor, ActorRef, Cancellable} import akka.actor.{Actor, ActorRef}
import net.psforever.objects.{DefaultCancellable, GlobalDefinitions, Tool, Vehicle} import net.psforever.objects.{GlobalDefinitions, Vehicle}
import net.psforever.objects.ballistics.{ResolvedProjectile, VehicleSource} import net.psforever.objects.ballistics.{ResolvedProjectile, VehicleSource}
import net.psforever.objects.equipment.{JammableUnit, JammingUnit} import net.psforever.objects.equipment.{JammableMountedWeapons, JammableUnit}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior} import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior} import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.serverobject.deploy.{Deployment, DeploymentBehavior} import net.psforever.objects.serverobject.deploy.{Deployment, DeploymentBehavior}
@ -18,8 +17,6 @@ import services.avatar.{AvatarAction, AvatarServiceMessage}
import services.local.{LocalAction, LocalServiceMessage} import services.local.{LocalAction, LocalServiceMessage}
import services.vehicle.{VehicleAction, VehicleService, VehicleServiceMessage} import services.vehicle.{VehicleAction, VehicleService, VehicleServiceMessage}
import scala.concurrent.duration._
/** /**
* An `Actor` that handles messages being dispatched to a specific `Vehicle`.<br> * An `Actor` that handles messages being dispatched to a specific `Vehicle`.<br>
* <br> * <br>
@ -31,15 +28,16 @@ class VehicleControl(vehicle : Vehicle) extends Actor
with FactionAffinityBehavior.Check with FactionAffinityBehavior.Check
with DeploymentBehavior with DeploymentBehavior
with MountableBehavior.Mount with MountableBehavior.Mount
with MountableBehavior.Dismount { with MountableBehavior.Dismount
var jammeredSoundTimer : Cancellable = DefaultCancellable.obj with JammableMountedWeapons {
var jammeredStatusTimer : Cancellable = DefaultCancellable.obj
//make control actors belonging to utilities when making control actor belonging to vehicle //make control actors belonging to utilities when making control actor belonging to vehicle
vehicle.Utilities.foreach({case (_, util) => util.Setup }) vehicle.Utilities.foreach({case (_, util) => util.Setup })
def MountableObject = vehicle def MountableObject = vehicle
def JammableObject = vehicle
def FactionObject = vehicle def FactionObject = vehicle
def DeploymentObject = vehicle def DeploymentObject = vehicle
@ -57,6 +55,7 @@ class VehicleControl(vehicle : Vehicle) extends Actor
def Enabled : Receive = checkBehavior def Enabled : Receive = checkBehavior
.orElse(deployBehavior) .orElse(deployBehavior)
.orElse(dismountBehavior) .orElse(dismountBehavior)
.orElse(jammableBehavior)
.orElse { .orElse {
case Mountable.TryMount(user, seat_num) => case Mountable.TryMount(user, seat_num) =>
val exosuit = user.ExoSuit val exosuit = user.ExoSuit
@ -116,16 +115,9 @@ class VehicleControl(vehicle : Vehicle) extends Actor
} }
sender ! FactionAffinity.AssertFactionAffinity(vehicle, faction) sender ! FactionAffinity.AssertFactionAffinity(vehicle, faction)
case JammableUnit.Jammered(cause) =>
TryJammerWithProjectile(vehicle, cause)
case JammableUnit.ClearJammeredSound() =>
CancelJammeredSound(vehicle)
case JammableUnit.ClearJammeredStatus() =>
StopJammeredStatus(vehicle)
case Vehicle.PrepareForDeletion => case Vehicle.PrepareForDeletion =>
CancelJammeredSound(vehicle)
CancelJammeredStatus(vehicle)
context.become(Disabled) context.become(Disabled)
case _ => ; case _ => ;
@ -134,49 +126,11 @@ class VehicleControl(vehicle : Vehicle) extends Actor
def Disabled : Receive = checkBehavior def Disabled : Receive = checkBehavior
.orElse(dismountBehavior) .orElse(dismountBehavior)
.orElse { .orElse {
case JammableUnit.ClearJammeredSound() =>
CancelJammeredSound(vehicle)
case JammableUnit.ClearJammeredStatus() =>
StopJammeredStatus(vehicle)
case Vehicle.Reactivate => case Vehicle.Reactivate =>
context.become(Enabled) context.become(Enabled)
case _ => ; case _ => ;
} }
def TryJammerWithProjectile(target : Vehicle, cause : ResolvedProjectile) : Unit = {
val radius = cause.projectile.profile.DamageRadius
JammingUnit.FindJammerDuration(cause.projectile.profile, target) match {
case Some(dur) if Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius =>
//jammered sound
jammeredSoundTimer.cancel
target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 54, 1))
import scala.concurrent.ExecutionContext.Implicits.global
jammeredSoundTimer = context.system.scheduler.scheduleOnce(30 seconds, self, JammableUnit.ClearJammeredSound())
//jammered status
StartJammeredStatus(target, dur)
case _ => ;
}
}
def StartJammeredStatus(target : PlanetSideServerObject with MountedWeapons, dur : Int) : Unit = {
jammeredStatusTimer.cancel
VehicleControl.JammeredStatus(target, 1)
import scala.concurrent.ExecutionContext.Implicits.global
jammeredStatusTimer = context.system.scheduler.scheduleOnce(dur milliseconds, self, JammableUnit.ClearJammeredStatus())
}
def StopJammeredStatus(target : PlanetSideServerObject with MountedWeapons) : Boolean = {
VehicleControl.JammeredStatus(target, 0)
jammeredStatusTimer.cancel
}
def CancelJammeredSound(target : PlanetSideServerObject) : Unit = {
jammeredSoundTimer.cancel
target.Zone.VehicleEvents ! VehicleServiceMessage(target.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 54, 0))
}
} }
object VehicleControl { object VehicleControl {
@ -310,16 +264,4 @@ object VehicleControl {
zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(target), zone)) zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(target), zone))
zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.AddTask(target, zone, Some(1 minute))) zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.AddTask(target, zone, Some(1 minute)))
} }
def JammeredStatus(target : PlanetSideServerObject with MountedWeapons, statusCode : Int) : Unit = {
val zone = target.Zone
val zoneId = zone.Id
zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 27, statusCode))
target.Weapons.values
.map { _.Equipment }
.collect {
case Some(item : Tool) =>
zone.VehicleEvents ! VehicleServiceMessage(zoneId, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, item.GUID, 27, statusCode))
}
}
} }

View file

@ -1,7 +1,9 @@
// Copyright (c) 2017 PSForever // Copyright (c) 2017 PSForever
package net.psforever.objects.zones package net.psforever.objects.zones
import akka.actor.Actor import akka.actor.{Actor, ActorRef, Props}
import net.psforever.objects.avatar.PlayerControl
import net.psforever.objects.vehicles.VehicleControl
import net.psforever.objects.{Avatar, Player} import net.psforever.objects.{Avatar, Player}
import scala.annotation.tailrec import scala.annotation.tailrec
@ -34,16 +36,22 @@ class ZonePopulationActor(zone : Zone, playerMap : TrieMap[Avatar, Option[Player
case Zone.Population.Spawn(avatar, player) => case Zone.Population.Spawn(avatar, player) =>
PopulationSpawn(avatar, player, playerMap) match { PopulationSpawn(avatar, player, playerMap) match {
case Some(tplayer) => case Some(tplayer) =>
tplayer.Zone = zone
if(tplayer ne player) { if(tplayer ne player) {
sender ! Zone.Population.PlayerAlreadySpawned(zone, player) sender ! Zone.Population.PlayerAlreadySpawned(zone, player)
} }
else {
player.Actor = context.actorOf(Props(classOf[PlayerControl], player), s"${player.Name}_${player.GUID.guid}")
}
case None => case None =>
sender ! Zone.Population.PlayerCanNotSpawn(zone, player) sender ! Zone.Population.PlayerCanNotSpawn(zone, player)
} }
case Zone.Population.Release(avatar) => case Zone.Population.Release(avatar) =>
PopulationRelease(avatar, playerMap) match { PopulationRelease(avatar, playerMap) match {
case Some(_) => ; case Some(tplayer) =>
tplayer.Actor ! akka.actor.PoisonPill
tplayer.Actor = ActorRef.noSender
case None => case None =>
sender ! Zone.Population.PlayerHasLeft(zone, None) sender ! Zone.Population.PlayerHasLeft(zone, None)
} }

View file

@ -115,7 +115,7 @@ import scodec.codecs._
* 45 : Advanced Engineering (= Fortification Engineering + Assault Engineering) Must have Combat Engineering<br> * 45 : Advanced Engineering (= Fortification Engineering + Assault Engineering) Must have Combat Engineering<br>
* `25 - Forget certifications (same order as 24)`<br> * `25 - Forget certifications (same order as 24)`<br>
* `26 - Certification reset timer (in seconds)` * `26 - Certification reset timer (in seconds)`
* `27 - PA_JAMMED - plays jammed buzzing sound`<br> * `27 - PA_JAMMED - plays jammed buzzing sound in vicinity of target, jams weapon discharge`<br>
* `28 - PA_IMPLANT_ACTIVE - Plays implant sounds. Valid values seem to be up to 20.`<br> * `28 - PA_IMPLANT_ACTIVE - Plays implant sounds. Valid values seem to be up to 20.`<br>
* `29 - PA_VAPORIZED - Visible ?! That's not the cloaked effect, Maybe for spectator mode ?. Value is 0 to visible, 1 to invisible.`<br> * `29 - PA_VAPORIZED - Visible ?! That's not the cloaked effect, Maybe for spectator mode ?. Value is 0 to visible, 1 to invisible.`<br>
* `31 - Looking for Squad info (marquee and ui):`<br> * `31 - Looking for Squad info (marquee and ui):`<br>
@ -162,7 +162,7 @@ import scodec.codecs._
* `13 - Trunk permissions (same)`<br> * `13 - Trunk permissions (same)`<br>
* `21 - Declare a player the vehicle's owner, by globally unique identifier`<br> * `21 - Declare a player the vehicle's owner, by globally unique identifier`<br>
* `22 - Toggles gunner and passenger mount points (1 = hides, 0 = reveals; this also locks their permissions)`<br> * `22 - Toggles gunner and passenger mount points (1 = hides, 0 = reveals; this also locks their permissions)`<br>
* `54 - Vehicle EMP? Plays sound as if vehicle had been hit by EMP`<br> * `54 - Plays jammed buzzing sound in vicinity of target`<br>
* `68 - Vehicle shield health`<br> * `68 - Vehicle shield health`<br>
* `79 - ???`<br> * `79 - ???`<br>
* `80 - Damage vehicle (unknown value)`<br> * `80 - Damage vehicle (unknown value)`<br>

View file

@ -71,7 +71,9 @@ import services.support.SupportActor
import scala.collection.mutable import scala.collection.mutable
class WorldSessionActor extends Actor with MDCContextAware { class WorldSessionActor extends Actor
with MDCContextAware
with JammableBehavior {
import WorldSessionActor._ import WorldSessionActor._
private[this] val log = org.log4s.getLogger private[this] val log = org.log4s.getLogger
@ -165,8 +167,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
var cargoDismountTimer : Cancellable = DefaultCancellable.obj var cargoDismountTimer : Cancellable = DefaultCancellable.obj
var antChargingTick : Cancellable = DefaultCancellable.obj var antChargingTick : Cancellable = DefaultCancellable.obj
var antDischargingTick : Cancellable = DefaultCancellable.obj var antDischargingTick : Cancellable = DefaultCancellable.obj
var jammeredSoundTimer : Cancellable = DefaultCancellable.obj
var jammeredStatusTimer : Cancellable = DefaultCancellable.obj
/** /**
@ -178,12 +178,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
import scala.language.implicitConversions import scala.language.implicitConversions
implicit def boolToInt(b : Boolean) : Int = if(b) 1 else 0 implicit def boolToInt(b : Boolean) : Int = if(b) 1 else 0
def JammableObject = player
override def postStop() : Unit = { override def postStop() : Unit = {
//TODO normally, player avatar persists a minute or so after disconnect; we are subject to the SessionReaper //TODO normally, player avatar persists a minute or so after disconnect; we are subject to the SessionReaper
clientKeepAlive.cancel clientKeepAlive.cancel
reviveTimer.cancel reviveTimer.cancel
respawnTimer.cancel respawnTimer.cancel
PlayerActionsToCancel()
chatService ! Service.Leave() chatService ! Service.Leave()
continent.AvatarEvents ! Service.Leave() continent.AvatarEvents ! Service.Leave()
continent.LocalEvents ! Service.Leave() continent.LocalEvents ! Service.Leave()
@ -191,6 +192,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
galaxyService ! Service.Leave() galaxyService ! Service.Leave()
LivePlayerList.Remove(sessionId) LivePlayerList.Remove(sessionId)
if(player != null && player.HasGUID) { if(player != null && player.HasGUID) {
PlayerActionsToCancel()
squadService ! Service.Leave(Some(player.CharId.toString)) squadService ! Service.Leave(Some(player.CharId.toString))
val player_guid = player.GUID val player_guid = player.GUID
//handle orphaned deployables //handle orphaned deployables
@ -320,7 +322,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
context.stop(self) context.stop(self)
} }
def Started : Receive = { def Started : Receive = jammableBehavior.orElse {
case ServiceManager.LookupResult("chat", endpoint) => case ServiceManager.LookupResult("chat", endpoint) =>
chatService = endpoint chatService = endpoint
log.info("ID: " + sessionId + " Got chat service " + endpoint) log.info("ID: " + sessionId + " Got chat service " + endpoint)
@ -1174,12 +1176,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
case _ => ; case _ => ;
} }
case ClearJammeredSound() =>
CancelJammeredSound()
case ClearJammeredStatus() =>
CancelJammeredStatus()
case default => case default =>
log.warn(s"Invalid packet class received: $default from $sender") log.warn(s"Invalid packet class received: $default from $sender")
} }
@ -1323,30 +1319,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
} }
} }
if(target.isAlive && cause.projectile.profile.JammerProjectile) { if(target.isAlive && cause.projectile.profile.JammerProjectile) {
val radius = cause.projectile.profile.DamageRadius self ! JammableUnit.Jammered(cause)
JammingUnit.FindJammerDuration(cause.projectile.profile, target) match {
case Some(dur) if Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius =>
//implants
DeactivateImplants()
//jammered sound
sendResponse(PlanetsideAttributeMessage(player.GUID, 54, 1))
continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 54, 1))
import scala.concurrent.ExecutionContext.Implicits.global
jammeredSoundTimer.cancel
jammeredSoundTimer = context.system.scheduler.scheduleOnce(30 seconds, self, ClearJammeredSound())
//jammered status
skipStaminaRegenForTurns = 5
jammeredEquipment = (jammeredEquipment ++ player.Holsters()
.map { _.Equipment }
.collect {
case Some(item) if item.Size != EquipmentSize.Melee =>
sendResponse(PlanetsideAttributeMessage(item.GUID, 27, 1))
item.GUID
}).distinct
jammeredStatusTimer.cancel
jammeredStatusTimer = context.system.scheduler.scheduleOnce(dur milliseconds, self, ClearJammeredStatus())
case _ => ;
}
} }
} }
@ -3425,6 +3398,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
player.Slot(39).Equipment = SimpleItem(remote_electronics_kit) player.Slot(39).Equipment = SimpleItem(remote_electronics_kit)
player.Locker.Inventory += 0 -> SimpleItem(remote_electronics_kit) player.Locker.Inventory += 0 -> SimpleItem(remote_electronics_kit)
player.Inventory.Items.foreach { _.obj.Faction = faction } player.Inventory.Items.foreach { _.obj.Faction = faction }
player.Actor = self
//TODO end temp player character auto-loading //TODO end temp player character auto-loading
self ! ListAccountCharacters self ! ListAccountCharacters
import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global
@ -7801,8 +7775,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
* This is not a complete list but, for the purpose of enforcement, some pointers will be documented here. * This is not a complete list but, for the purpose of enforcement, some pointers will be documented here.
*/ */
def PlayerActionsToCancel() : Unit = { def PlayerActionsToCancel() : Unit = {
CancelJammeredSound() CancelJammeredSound(player)
CancelJammeredStatus() CancelJammeredStatus(player)
progressBarUpdate.cancel progressBarUpdate.cancel
progressBarValue = None progressBarValue = None
lastTerminalOrderFulfillment = true lastTerminalOrderFulfillment = true
@ -10242,16 +10216,55 @@ class WorldSessionActor extends Actor with MDCContextAware {
} }
} }
def CancelJammeredSound() : Unit = { def TryJammerEffectActivate(target : Any, cause : ResolvedProjectile) : Unit = target match {
jammeredSoundTimer.cancel case obj : Player =>
sendResponse(PlanetsideAttributeMessage(player.GUID, 54, 0)) val radius = cause.projectile.profile.DamageRadius
continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(player.GUID, 54, 0)) JammingUnit.FindJammerDuration(cause.projectile.profile, obj) match {
case Some(dur) if Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius =>
DeactivateImplants()
skipStaminaRegenForTurns = 5
StartJammeredSound(obj)
StartJammeredStatus(obj, dur)
case _ => ;
}
case _ => ;
} }
def CancelJammeredStatus() : Unit = { override def StartJammeredSound(target : Any, dur : Int) : Unit = target match {
jammeredStatusTimer.cancel case obj : Player =>
jammeredEquipment.foreach { id => sendResponse(PlanetsideAttributeMessage(id, 27, 0)) } sendResponse(PlanetsideAttributeMessage(obj.GUID, 27, 1))
jammeredEquipment = Nil continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(obj.GUID, 27, 1))
super.StartJammeredSound(obj, dur)
case _ => ;
}
override def StartJammeredStatus(target : Any, dur : Int) : Unit = target match {
case obj : Player =>
jammeredEquipment = (jammeredEquipment ++ obj.Holsters()
.map { _.Equipment }
.collect {
case Some(item) if item.Size != EquipmentSize.Melee =>
sendResponse(PlanetsideAttributeMessage(item.GUID, 27, 1))
item.GUID
}).distinct
super.StartJammeredStatus(obj, dur)
case _ => ;
}
override def CancelJammeredSound(target : Any) : Unit = target match {
case obj : Player =>
sendResponse(PlanetsideAttributeMessage(obj.GUID, 27, 0))
continent.AvatarEvents ! AvatarServiceMessage(continent.Id, AvatarAction.PlanetsideAttribute(obj.GUID, 27, 0))
super.CancelJammeredSound(obj)
case _ => ;
}
override def CancelJammeredStatus(target : Any) : Unit = target match {
case obj : Player =>
jammeredEquipment.foreach { id => sendResponse(PlanetsideAttributeMessage(id, 27, 0)) }
jammeredEquipment = Nil
super.CancelJammeredStatus(obj)
case _ => ;
} }
def failWithError(error : String) = { def failWithError(error : String) = {
@ -10412,15 +10425,11 @@ object WorldSessionActor {
protected final case class SquadUIElement(name : String, index : Int, zone : Int, health : Int, armor : Int, position : Vector3) protected final case class SquadUIElement(name : String, index : Int, zone : Int, health : Int, armor : Int, position : Vector3)
private final case class NtuCharging(tplayer: Player, private final case class NtuCharging(tplayer: Player, vehicle: Vehicle)
vehicle: Vehicle)
private final case class NtuDischarging(tplayer: Player, vehicle: Vehicle, silo_guid: PlanetSideGUID) private final case class NtuDischarging(tplayer: Player, vehicle: Vehicle, silo_guid: PlanetSideGUID)
private final case class FinalizeDeployable(obj : PlanetSideGameObject with Deployable, tool : ConstructionItem, index : Int) private final case class FinalizeDeployable(obj : PlanetSideGameObject with Deployable, tool : ConstructionItem, index : Int)
private final case class LoadedRemoteProjectile(projectile_guid : PlanetSideGUID, projectile : Option[Projectile]) private final case class LoadedRemoteProjectile(projectile_guid : PlanetSideGUID, projectile : Option[Projectile])
private final case class ClearJammeredSound()
private final case class ClearJammeredStatus()
} }