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.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.serverobject.PlanetSideServerObject
import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.objects.vital.{DamageResistanceModel, Vitality}
@ -16,11 +17,12 @@ import net.psforever.types._
import scala.annotation.tailrec
import scala.util.{Success, Try}
class Player(private val core : Avatar) extends PlanetSideGameObject
class Player(private val core : Avatar) extends PlanetSideServerObject
with FactionAffinity
with Vitality
with ResistanceProfile
with Container
with JammableUnit
with ZoneAware {
private var alive : Boolean = false
private var backpack : Boolean = false

View file

@ -3,7 +3,7 @@ package net.psforever.objects
import akka.actor.ActorRef
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.serverobject.mount.Mountable
import net.psforever.objects.serverobject.PlanetSideServerObject
@ -73,6 +73,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
with Vitality
with OwnableByPlayer
with StandardResistanceProfile
with JammableUnit
with Container {
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.TR
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
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.serverobject.PlanetSideServerObject
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.concurrent.duration._
trait JammableUnit {
private var jammed : Boolean = false
@ -49,3 +57,104 @@ object JammingUnit {
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
package net.psforever.objects.serverobject.turret
import net.psforever.objects.equipment.JammableUnit
import net.psforever.objects.serverobject.structures.Amenity
import net.psforever.types.Vector3
import net.psforever.objects.vital.{DamageResistanceModel, StandardResistanceProfile, Vitality}
class FacilityTurret(tDef : TurretDefinition) extends Amenity
with WeaponTurret
with JammableUnit
with Vitality
with StandardResistanceProfile {
/** some turrets can be updated; they all start without updates */

View file

@ -1,25 +1,19 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.turret
import akka.actor.{Actor, Cancellable}
import net.psforever.objects.{DefaultCancellable, Tool}
import akka.actor.Actor
import net.psforever.objects.ballistics.ResolvedProjectile
import net.psforever.objects.equipment.{JammableUnit, JammingUnit}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.equipment.{JammableMountedWeapons, JammableUnit}
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.vehicles.MountedWeapons
import net.psforever.objects.vital.Vitality
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.Vector3
import services.Service
import services.avatar.{AvatarAction, AvatarServiceMessage}
import services.vehicle.{VehicleAction, VehicleServiceMessage}
import services.vehicle.support.TurretUpgrader
import scala.concurrent.duration._
/**
* An `Actor` that handles messages being dispatched to a specific `MannedTurret`.<br>
* <br>
@ -30,11 +24,12 @@ import scala.concurrent.duration._
*/
class FacilityTurretControl(turret : FacilityTurret) extends Actor
with FactionAffinityBehavior.Check
with MountableBehavior.Dismount {
var jammeredSoundTimer : Cancellable = DefaultCancellable.obj
var jammeredStatusTimer : Cancellable = DefaultCancellable.obj
with MountableBehavior.Dismount
with JammableMountedWeapons {
def MountableObject = turret //do not add type!
def MountableObject = turret
def JammableObject = 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 _ => ;
}
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 {
@ -195,16 +150,4 @@ object FacilityTurretControl {
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
package net.psforever.objects.vehicles
import akka.actor.{Actor, ActorRef, Cancellable}
import net.psforever.objects.{DefaultCancellable, GlobalDefinitions, Tool, Vehicle}
import akka.actor.{Actor, ActorRef}
import net.psforever.objects.{GlobalDefinitions, Vehicle}
import net.psforever.objects.ballistics.{ResolvedProjectile, VehicleSource}
import net.psforever.objects.equipment.{JammableUnit, JammingUnit}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.equipment.{JammableMountedWeapons, JammableUnit}
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
import net.psforever.objects.serverobject.deploy.{Deployment, DeploymentBehavior}
@ -18,8 +17,6 @@ import services.avatar.{AvatarAction, AvatarServiceMessage}
import services.local.{LocalAction, LocalServiceMessage}
import services.vehicle.{VehicleAction, VehicleService, VehicleServiceMessage}
import scala.concurrent.duration._
/**
* An `Actor` that handles messages being dispatched to a specific `Vehicle`.<br>
* <br>
@ -31,15 +28,16 @@ class VehicleControl(vehicle : Vehicle) extends Actor
with FactionAffinityBehavior.Check
with DeploymentBehavior
with MountableBehavior.Mount
with MountableBehavior.Dismount {
var jammeredSoundTimer : Cancellable = DefaultCancellable.obj
var jammeredStatusTimer : Cancellable = DefaultCancellable.obj
with MountableBehavior.Dismount
with JammableMountedWeapons {
//make control actors belonging to utilities when making control actor belonging to vehicle
vehicle.Utilities.foreach({case (_, util) => util.Setup })
def MountableObject = vehicle
def JammableObject = vehicle
def FactionObject = vehicle
def DeploymentObject = vehicle
@ -57,6 +55,7 @@ class VehicleControl(vehicle : Vehicle) extends Actor
def Enabled : Receive = checkBehavior
.orElse(deployBehavior)
.orElse(dismountBehavior)
.orElse(jammableBehavior)
.orElse {
case Mountable.TryMount(user, seat_num) =>
val exosuit = user.ExoSuit
@ -116,16 +115,9 @@ class VehicleControl(vehicle : Vehicle) extends Actor
}
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 =>
CancelJammeredSound(vehicle)
CancelJammeredStatus(vehicle)
context.become(Disabled)
case _ => ;
@ -134,49 +126,11 @@ class VehicleControl(vehicle : Vehicle) extends Actor
def Disabled : Receive = checkBehavior
.orElse(dismountBehavior)
.orElse {
case JammableUnit.ClearJammeredSound() =>
CancelJammeredSound(vehicle)
case JammableUnit.ClearJammeredStatus() =>
StopJammeredStatus(vehicle)
case Vehicle.Reactivate =>
context.become(Enabled)
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 {
@ -310,16 +264,4 @@ object VehicleControl {
zone.VehicleEvents ! VehicleServiceMessage.Decon(RemoverActor.ClearSpecific(List(target), zone))
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
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 scala.annotation.tailrec
@ -34,16 +36,22 @@ class ZonePopulationActor(zone : Zone, playerMap : TrieMap[Avatar, Option[Player
case Zone.Population.Spawn(avatar, player) =>
PopulationSpawn(avatar, player, playerMap) match {
case Some(tplayer) =>
tplayer.Zone = zone
if(tplayer ne player) {
sender ! Zone.Population.PlayerAlreadySpawned(zone, player)
}
else {
player.Actor = context.actorOf(Props(classOf[PlayerControl], player), s"${player.Name}_${player.GUID.guid}")
}
case None =>
sender ! Zone.Population.PlayerCanNotSpawn(zone, player)
}
case Zone.Population.Release(avatar) =>
PopulationRelease(avatar, playerMap) match {
case Some(_) => ;
case Some(tplayer) =>
tplayer.Actor ! akka.actor.PoisonPill
tplayer.Actor = ActorRef.noSender
case 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>
* `25 - Forget certifications (same order as 24)`<br>
* `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>
* `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>
@ -162,7 +162,7 @@ import scodec.codecs._
* `13 - Trunk permissions (same)`<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>
* `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>
* `79 - ???`<br>
* `80 - Damage vehicle (unknown value)`<br>