Deployables (#230)

* functions for certifcation ui updates (that don't work)

* initialization of combat engineering deployables ui on load and certification change

* representation classes for ACE and FDU; ability to pull ACE and FDU from equipment terminals

* ammo change functionality and fire mode change functionality for ConstructionItems refactored from Tool operations and supported properly (switch between deployable options)

* zone-specific structure for keeping track of deployables; abaility to dismiss deployables from the map screen (previous functionality); local client creation of explosive-type deployables

* refactored MannedTurret into FacilityTurret and lesser traits to be used in the deployable spitfires and the OMFT's; all ACE deployables are available for placement; partial management of the construction items after the deployable is placed; boomers create boomer triggers

* Avatar-specific storage for deployables and for updating UI elements

* refactored quite a bit of code in WSA for the benefit of deployable management; refinements to deployable creation; server messages about deployable quantities; corrected the FDU encoding pattern; lots of work dedicated just to synchronizing BoomerTrigger objects

* added RemoverActor for deployables and redistributed deconstruction functionality away from WSA to new DeployableRemover; added events to facilitate activities not inheritable with this model

* refactored and distributed Deployables classes; copious amounts of testing and document-writing

* boomers now explode from trigger; support for deployables being destroyed by weapon discharge, including individual health, soure identification, and damage model; shuffled deployable classes to build different hierarchy

* sensor_shield was skipped by accident

* identified stray object in Hanish, Ishundar, and added Irkalla, Ishundar's capture console; fixed issue with Warp command and 'Irkalla'; modified building amenity setup and setup testing in Zone; players load and die properly when seated in an omft; reserve ammunition in omft properly registered

* added local service channel, capture consoles, fixed tests as much as posible

* fixed LocalService tests by booting the ServiceManager; added avatar and local tests

* a simple attempt to refactor Actor messages in a way that is acceptable to Travis CI

* making the explosive deployables vanish upon explosion; sensor health bars are now supported
This commit is contained in:
Fate-JH 2018-09-23 08:00:58 -04:00 committed by GitHub
parent 6cd18c5623
commit 5f3e7e5df8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
113 changed files with 8155 additions and 2312 deletions

View file

@ -1,15 +1,13 @@
// Copyright (c) 2017 PSForever
package objects
import net.psforever.objects.definition.converter.{ACEConverter, CharacterSelectConverter, DestroyedVehicleConverter, REKConverter}
import net.psforever.objects.definition.converter.{CharacterSelectConverter, DestroyedVehicleConverter, REKConverter}
import net.psforever.objects._
import net.psforever.objects.definition._
import net.psforever.objects.equipment.CItem.{DeployedItem, Unit}
import net.psforever.objects.equipment._
import net.psforever.objects.inventory.InventoryTile
import net.psforever.objects.serverobject.terminals.Terminal
import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.vehicles.DestroyedVehicle
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.packet.game.objectcreate._
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire, Vector3}
@ -109,13 +107,7 @@ class ConverterTest extends Specification {
"ConstructionItem" should {
"convert to packet" in {
val cdef = ConstructionItemDefinition(Unit.advanced_ace)
cdef.Modes += DeployedItem.tank_traps
cdef.Modes += DeployedItem.portable_manned_turret_tr
cdef.Modes += DeployedItem.deployable_shield_generator
cdef.Tile = InventoryTile.Tile63
cdef.Packet = new ACEConverter()
val obj = ConstructionItem(cdef)
val obj = ConstructionItem(GlobalDefinitions.ace)
obj.GUID = PlanetSideGUID(90)
obj.Definition.Packet.DetailedConstructorData(obj) match {
case Success(pkt) =>
@ -123,6 +115,7 @@ class ConverterTest extends Specification {
case _ =>
ko
}
obj.Definition.Packet.ConstructorData(obj) match {
case Success(pkt) =>
pkt mustEqual ACEData(0,0)
@ -154,6 +147,158 @@ class ConverterTest extends Specification {
}
}
"BoomerTrigger" should {
"convert" in {
val obj = new BoomerTrigger
obj.GUID = PlanetSideGUID(90)
obj.Definition.Packet.DetailedConstructorData(obj) match {
case Success(pkt) =>
pkt mustEqual DetailedBoomerTriggerData()
case _ =>
ko
}
obj.Definition.Packet.ConstructorData(obj) match {
case Success(pkt) =>
pkt mustEqual BoomerTriggerData()
case _ =>
ko
}
}
}
"SmallDeployable" should {
"convert" in {
val obj = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
obj.Faction = PlanetSideEmpire.TR
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
obj.Definition.Packet.ConstructorData(obj) match {
case Success(pkt) =>
pkt mustEqual SmallDeployableData(
PlacementData(Vector3.Zero, Vector3.Zero),
PlanetSideEmpire.TR,
0,
false,
false
)
case _ =>
ko
}
}
}
"SmallTurret" should {
"convert" in {
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
obj.Faction = PlanetSideEmpire.TR
obj.GUID = PlanetSideGUID(90)
obj.Weapons(1).Equipment.get.GUID = PlanetSideGUID(91)
obj.Weapons(1).Equipment.get.asInstanceOf[Tool].AmmoSlot.Box.GUID = PlanetSideGUID(92)
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
obj.Definition.Packet.ConstructorData(obj) match {
case Success(pkt) =>
pkt mustEqual SmallTurretData(
SmallDeployableData(
PlacementData(Vector3.Zero, Vector3.Zero),
PlanetSideEmpire.TR,
0,
false,
false
),
255,
InventoryData(
List(InternalSlot(ObjectClass.spitfire_weapon, PlanetSideGUID(91), 1,
WeaponData(4, 8, ObjectClass.spitfire_ammo, PlanetSideGUID(92), 0, AmmoBoxData()))
)
)
)
case _ =>
ko
}
}
}
"FieldTurret" should {
"convert" in {
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr)
obj.Faction = PlanetSideEmpire.TR
obj.GUID = PlanetSideGUID(90)
obj.Weapons(1).Equipment.get.GUID = PlanetSideGUID(91)
obj.Weapons(1).Equipment.get.asInstanceOf[Tool].AmmoSlot.Box.GUID = PlanetSideGUID(92)
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
obj.Definition.Packet.ConstructorData(obj) match {
case Success(pkt) =>
pkt mustEqual OneMannedFieldTurretData(
SmallDeployableData(
PlacementData(Vector3.Zero, Vector3.Zero),
PlanetSideEmpire.TR,
0,
false,
false
),
255,
InventoryData(
List(InternalSlot(ObjectClass.energy_gun_tr, PlanetSideGUID(91), 1,
WeaponData(4, 8, ObjectClass.energy_gun_ammo, PlanetSideGUID(92), 0, AmmoBoxData()))
)
)
)
case _ =>
ko
}
}
}
"TRAP" should {
"convert" in {
val obj = new TrapDeployable(GlobalDefinitions.tank_traps)
obj.Faction = PlanetSideEmpire.TR
obj.GUID = PlanetSideGUID(90)
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
obj.Definition.Packet.ConstructorData(obj) match {
case Success(pkt) =>
pkt mustEqual TRAPData(
SmallDeployableData(
PlacementData(Vector3.Zero, Vector3.Zero),
PlanetSideEmpire.TR,
0,
false,
false
),
255
)
case _ =>
ko
}
}
}
"ShieldGenerator" should {
"convert" in {
val obj = new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator)
obj.Faction = PlanetSideEmpire.TR
obj.GUID = PlanetSideGUID(90)
obj.Definition.Packet.DetailedConstructorData(obj).isFailure mustEqual true
obj.Definition.Packet.ConstructorData(obj) match {
case Success(pkt) =>
pkt mustEqual AegisShieldGeneratorData(
CommonFieldData(
PlacementData(Vector3.Zero, Vector3.Zero),
PlanetSideEmpire.TR,
0
),
255
)
case _ =>
ko
}
}
}
"Player" should {
val avatar = Avatar("Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Voice5)
val obj : Player = {

View file

@ -0,0 +1,330 @@
// Copyright (c) 2017 PSForever
package objects
import akka.actor.{Actor, ActorRef, Props}
import base.ActorTest
import net.psforever.objects.ce.DeployedItem
import net.psforever.objects.serverobject.mount.Mountable
import net.psforever.objects.{TurretDeployable, _}
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
import org.specs2.mutable.Specification
import scala.concurrent.duration._
class DeployableTest extends Specification {
"Deployable" should {
"know its owner by GUID" in {
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
obj.Owner mustEqual None
obj.Owner = PlanetSideGUID(10)
obj.Owner mustEqual Some(PlanetSideGUID(10))
}
"know its owner by GUID" in {
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
obj.OwnerName mustEqual None
obj.OwnerName = "TestCharacter"
obj.OwnerName mustEqual Some("TestCharacter")
}
"know its faction allegiance" in {
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
obj.Faction mustEqual PlanetSideEmpire.NEUTRAL
obj.Faction = PlanetSideEmpire.TR
obj.Faction mustEqual PlanetSideEmpire.TR
}
}
}
class SensorDeployableTest extends Specification {
"SensorDeployable" should {
"construct" in {
new SensorDeployable(GlobalDefinitions.motionalarmsensor)
ok
}
}
}
class ExplosiveDeployableTest extends Specification {
"ExplosiveDeployable" should {
"construct" in {
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
obj.Exploded mustEqual false
}
"explode" in {
val obj = new ExplosiveDeployable(GlobalDefinitions.he_mine)
obj.Exploded mustEqual false
obj.Exploded = true
obj.Exploded mustEqual true
}
}
}
class BoomerDeployableTest extends Specification {
"BoomerDeployable" should {
"construct" in {
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
obj.Exploded mustEqual false
obj.Trigger mustEqual None
}
"explode" in {
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
obj.Exploded mustEqual false
obj.Exploded = true
obj.Exploded mustEqual true
}
"manage its trigger" in {
val obj = new BoomerDeployable(GlobalDefinitions.boomer)
obj.Trigger mustEqual None
val trigger = new BoomerTrigger
obj.Trigger = trigger
obj.Trigger mustEqual Some(trigger)
obj.Trigger = None
obj.Trigger mustEqual None
}
}
}
class TrapDeployableTest extends Specification {
"SensorDeployable" should {
"construct" in {
val obj = new TrapDeployable(GlobalDefinitions.tank_traps)
obj.Health mustEqual GlobalDefinitions.tank_traps.MaxHealth
}
"update health values" in {
val obj = new TrapDeployable(GlobalDefinitions.tank_traps)
obj.Health mustEqual GlobalDefinitions.tank_traps.MaxHealth
obj.Health = 0
obj.Health mustEqual 0
}
}
}
class TurretDeployableTest extends Specification {
"TurretDeployable" should {
"define (valid turret objects)" in {
List(
DeployedItem.spitfire_turret.id, DeployedItem.spitfire_cloaked.id, DeployedItem.spitfire_aa.id,
DeployedItem.portable_manned_turret.id, DeployedItem.portable_manned_turret_tr.id,
DeployedItem.portable_manned_turret_nc.id, DeployedItem.portable_manned_turret_vs.id
).foreach(id => {
try { new TurretDeployableDefinition(id) } catch { case _ : Exception => ko }
})
ok
}
"define (invalid object)" in {
new TurretDeployableDefinition(5) must throwA[NoSuchElementException] //wrong object id altogether
}
"construct" in {
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
obj.Health mustEqual obj.MaxHealth
}
"update health values" in {
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
obj.Health mustEqual GlobalDefinitions.spitfire_turret.MaxHealth
obj.Health = 0
obj.Health mustEqual 0
}
"may have mount point" in {
new TurretDeployable(GlobalDefinitions.spitfire_turret).MountPoints mustEqual Map()
new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs).MountPoints mustEqual Map(1 -> 0, 2 -> 0)
}
}
}
class ShieldGeneratorDeployableTest extends Specification {
"ShieldGeneratorDeployable" should {
"construct" in {
val obj = new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator)
obj.Health mustEqual obj.MaxHealth
}
"update health values" in {
val obj = new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator)
obj.Health mustEqual GlobalDefinitions.deployable_shield_generator.MaxHealth
obj.Health = 0
obj.Health mustEqual 0
}
}
}
class TurretControlConstructTest extends ActorTest {
"TurretControl" should {
"construct" in {
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
}
}
}
class TurretControlInitializeTest extends ActorTest {
"TurretControl" should {
"initialize" in {
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
obj.GUID = PlanetSideGUID(1)
assert(obj.Actor == ActorRef.noSender)
val init = system.actorOf(Props(classOf[DeployableTest.TurretInitializer], obj), "init_turret_test")
init ! "initialize"
expectNoMsg(200 milliseconds)
assert(obj.Actor != ActorRef.noSender)
}
}
}
class TurretControlUninitializeTest extends ActorTest {
"TurretControl" should {
"uninitialize" in {
val obj = new TurretDeployable(GlobalDefinitions.spitfire_turret)
val init = system.actorOf(Props(classOf[DeployableTest.TurretInitializer], obj), "init_turret_test")
obj.GUID = PlanetSideGUID(1)
init ! "initialize"
expectNoMsg(200 milliseconds)
assert(obj.Actor != ActorRef.noSender)
init ! "uninitialize"
expectNoMsg(200 milliseconds)
assert(obj.Actor == ActorRef.noSender)
}
}
}
class TurretControlMountTest extends ActorTest {
"TurretControl" should {
"control mounting" in {
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
obj.Faction = PlanetSideEmpire.TR
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
assert(obj.Seats(0).Occupant.isEmpty)
val player1 = Player(Avatar("test1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
obj.Actor ! Mountable.TryMount(player1, 0)
val reply1a = receiveOne(200 milliseconds)
assert(reply1a.isInstanceOf[Mountable.MountMessages])
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
assert(reply1b.player == player1)
assert(reply1b.response.isInstanceOf[Mountable.CanMount])
assert(obj.Seats(0).Occupant.contains(player1))
}
}
}
class TurretControlBlockMountTest extends ActorTest {
"TurretControl" should {
"block mounting by others if already mounted by someone" in {
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
obj.Faction = PlanetSideEmpire.TR
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
assert(obj.Seats(0).Occupant.isEmpty)
val player1 = Player(Avatar("test1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
obj.Actor ! Mountable.TryMount(player1, 0)
val reply1a = receiveOne(200 milliseconds)
assert(reply1a.isInstanceOf[Mountable.MountMessages])
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
assert(reply1b.player == player1)
assert(reply1b.response.isInstanceOf[Mountable.CanMount])
assert(obj.Seats(0).Occupant.contains(player1))
val player2 = Player(Avatar("test2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
obj.Actor ! Mountable.TryMount(player2, 0)
val reply2a = receiveOne(200 milliseconds)
assert(reply2a.isInstanceOf[Mountable.MountMessages])
val reply2b = reply2a.asInstanceOf[Mountable.MountMessages]
assert(reply2b.player == player2)
assert(reply2b.response.isInstanceOf[Mountable.CanNotMount])
}
}
}
class TurretControlBlockBetrayalMountTest extends ActorTest {
"TurretControl" should {
"block mounting by players of another faction" in {
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
obj.Faction = PlanetSideEmpire.TR
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
assert(obj.Seats(0).Occupant.isEmpty)
val player = Player(Avatar("test", PlanetSideEmpire.VS, CharacterGender.Male, 0, CharacterVoice.Mute))
obj.Actor ! Mountable.TryMount(player, 0)
val reply1a = receiveOne(200 milliseconds)
assert(reply1a.isInstanceOf[Mountable.MountMessages])
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
assert(reply1b.player == player)
assert(reply1b.response.isInstanceOf[Mountable.CanNotMount])
assert(obj.Seats(0).Occupant.isEmpty)
}
}
}
class TurretControlDismountTest extends ActorTest {
"TurretControl" should {
"control dismounting" in {
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) { GUID = PlanetSideGUID(1) }
obj.Faction = PlanetSideEmpire.TR
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
assert(obj.Seats(0).Occupant.isEmpty)
val player = Player(Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
obj.Actor ! Mountable.TryMount(player, 0)
val reply1a = receiveOne(200 milliseconds)
assert(reply1a.isInstanceOf[Mountable.MountMessages])
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
assert(reply1b.player == player)
assert(reply1b.response.isInstanceOf[Mountable.CanMount])
assert(obj.Seats(0).Occupant.contains(player))
obj.Actor ! Mountable.TryDismount(player, 0)
val reply2a = receiveOne(200 milliseconds)
assert(reply2a.isInstanceOf[Mountable.MountMessages])
val reply2b = reply2a.asInstanceOf[Mountable.MountMessages]
assert(reply2b.player == player)
assert(reply2b.response.isInstanceOf[Mountable.CanDismount])
assert(obj.Seats(0).Occupant.isEmpty)
}
}
}
class TurretControlBetrayalMountTest extends ActorTest {
"TurretControl" should {
"allow all allegiances" in {
val obj = new TurretDeployable(
new TurretDeployableDefinition(685) { FactionLocked = false } //required (defaults to true)
) { GUID = PlanetSideGUID(1) }
obj.Faction = PlanetSideEmpire.TR
obj.Actor = system.actorOf(Props(classOf[TurretControl], obj), s"${obj.Definition.Name}_test")
assert(obj.Seats(0).Occupant.isEmpty)
val player = Player(Avatar("test", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute))
assert(player.Faction != obj.Faction)
obj.Actor ! Mountable.TryMount(player, 0)
val reply1a = receiveOne(200 milliseconds)
assert(reply1a.isInstanceOf[Mountable.MountMessages])
val reply1b = reply1a.asInstanceOf[Mountable.MountMessages]
assert(reply1b.player == player)
assert(reply1b.response.isInstanceOf[Mountable.CanMount])
assert(obj.Seats(0).Occupant.contains(player))
}
}
}
object DeployableTest {
class TurretInitializer(obj : TurretDeployable) extends Actor {
def receive : Receive = {
case "initialize" =>
obj.Definition.Initialize(obj, context)
case "uninitialize" =>
obj.Definition.Uninitialize(obj, context)
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -2,11 +2,13 @@
package objects
import net.psforever.objects._
import net.psforever.objects.equipment.CItem.{DeployedItem, Unit}
import net.psforever.objects.equipment._
import net.psforever.objects.inventory.InventoryTile
import net.psforever.objects.GlobalDefinitions._
import net.psforever.objects.ce.DeployedItem
import net.psforever.objects.definition._
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.CertificationType
import org.specs2.mutable._
class EquipmentTest extends Specification {
@ -329,62 +331,57 @@ class EquipmentTest extends Specification {
}
"ConstructionItem" should {
val advanced_ace_tr = ConstructionItemDefinition(39)
advanced_ace_tr.Modes += DeployedItem.tank_traps
advanced_ace_tr.Modes += DeployedItem.portable_manned_turret_tr
advanced_ace_tr.Modes += DeployedItem.deployable_shield_generator
advanced_ace_tr.Tile = InventoryTile.Tile63
"define" in {
val sample = ConstructionItemDefinition(Unit.advanced_ace)
sample.Modes += DeployedItem.tank_traps
sample.Modes += DeployedItem.portable_manned_turret_tr
sample.Modes += DeployedItem.deployable_shield_generator
sample.Tile = InventoryTile.Tile63
sample.Modes.head mustEqual DeployedItem.tank_traps
sample.Modes(1) mustEqual DeployedItem.portable_manned_turret_tr
sample.Modes(2) mustEqual DeployedItem.deployable_shield_generator
sample.Tile.Width mustEqual InventoryTile.Tile63.Width
sample.Tile.Height mustEqual InventoryTile.Tile63.Height
}
"construct" in {
val obj : ConstructionItem = ConstructionItem(advanced_ace_tr)
obj.Definition.ObjectId mustEqual advanced_ace_tr.ObjectId
val obj : ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
obj.Definition.ObjectId mustEqual GlobalDefinitions.ace.ObjectId
}
"fire mode" in {
//explanation: router_telepad has one fire mode and that fire mode is our only option
val router_telepad : ConstructionItemDefinition = ConstructionItemDefinition(Unit.router_telepad)
router_telepad.Modes += DeployedItem.router_telepad_deployable
val obj : ConstructionItem = ConstructionItem(router_telepad)
//fmode = 0
obj.FireModeIndex mustEqual 0
obj.FireMode mustEqual DeployedItem.router_telepad_deployable
//fmode -> 1 (0)
obj.FireModeIndex = 1
obj.FireModeIndex mustEqual 0
obj.FireMode mustEqual DeployedItem.router_telepad_deployable
"fire modes" in {
val obj : ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
obj.AmmoType mustEqual DeployedItem.boomer
obj.NextFireMode
obj.AmmoType mustEqual DeployedItem.he_mine
obj.NextFireMode
obj.AmmoType mustEqual DeployedItem.spitfire_turret
obj.NextFireMode
obj.AmmoType mustEqual DeployedItem.motionalarmsensor
obj.NextFireMode
obj.AmmoType mustEqual DeployedItem.boomer
}
"multiple fire modes" in {
//explanation: advanced_ace_tr has three fire modes; adjusting the FireMode changes between them
val obj : ConstructionItem = ConstructionItem(advanced_ace_tr)
//fmode = 0
obj.FireModeIndex mustEqual 0
obj.FireMode mustEqual DeployedItem.tank_traps
//fmode -> 1
"ammo types" in {
val obj : ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
obj.NextFireMode
obj.FireModeIndex mustEqual 1
obj.FireMode mustEqual DeployedItem.portable_manned_turret_tr
//fmode -> 2
obj.AmmoType mustEqual DeployedItem.he_mine
obj.NextAmmoType
obj.AmmoType mustEqual DeployedItem.jammer_mine
obj.NextAmmoType
obj.AmmoType mustEqual DeployedItem.he_mine
}
"when switching fire modes, ammo mode resets to the first entry" in {
val obj : ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
obj.NextFireMode
obj.FireModeIndex mustEqual 2
obj.FireMode mustEqual DeployedItem.deployable_shield_generator
//fmode -> 0
obj.AmmoType mustEqual DeployedItem.he_mine
obj.NextAmmoType
obj.AmmoType mustEqual DeployedItem.jammer_mine
obj.NextFireMode //spitfire_turret
obj.NextFireMode //motionalarmsensor
obj.NextFireMode //boomer
obj.NextFireMode
obj.FireModeIndex mustEqual 0
obj.FireMode mustEqual DeployedItem.tank_traps
obj.AmmoType mustEqual DeployedItem.he_mine
}
"qualify certifications that must be met before ammo types may be used" in {
val obj : ConstructionItem = ConstructionItem(GlobalDefinitions.ace)
obj.AmmoType mustEqual DeployedItem.boomer
obj.ModePermissions mustEqual Set(CertificationType.CombatEngineering)
obj.NextFireMode
obj.AmmoType mustEqual DeployedItem.he_mine
obj.ModePermissions mustEqual Set(CertificationType.CombatEngineering)
obj.NextAmmoType
obj.AmmoType mustEqual DeployedItem.jammer_mine
obj.ModePermissions mustEqual Set(CertificationType.AssaultEngineering)
}
}
@ -399,4 +396,21 @@ class EquipmentTest extends Specification {
obj.Definition.ObjectId mustEqual remote_electronics_kit.ObjectId
}
}
"BoomerTrigger" should {
"construct" in {
val obj : BoomerTrigger = new BoomerTrigger
obj.Definition.ObjectId mustEqual boomer_trigger.ObjectId
obj.Companion mustEqual None
}
"boomer trigger has a companion object referenced by GUID" in {
val obj : BoomerTrigger = new BoomerTrigger
obj.Companion mustEqual None
obj.Companion = PlanetSideGUID(1)
obj.Companion.contains(PlanetSideGUID(1)) mustEqual true
obj.Companion = None
obj.Companion mustEqual None
}
}
}

View file

@ -2,11 +2,8 @@
package objects
import net.psforever.objects._
import net.psforever.objects.equipment.CItem.{DeployedItem, Unit}
import net.psforever.objects.equipment._
import net.psforever.objects.inventory.InventoryTile
import net.psforever.objects.GlobalDefinitions._
import net.psforever.objects.definition._
import net.psforever.types.ExoSuitType
import org.specs2.mutable._

View file

@ -7,7 +7,7 @@ import net.psforever.objects.{Avatar, GlobalDefinitions, Player, Tool}
import net.psforever.objects.definition.ToolDefinition
import net.psforever.objects.serverobject.mount.Mountable
import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.serverobject.turret.{MannedTurret, MannedTurretControl, MannedTurretDefinition, TurretUpgrade}
import net.psforever.objects.serverobject.turret._
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.PlanetSideGUID
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
@ -16,10 +16,10 @@ import org.specs2.mutable.Specification
import scala.collection.mutable
import scala.concurrent.duration._
class MannedTurretTest extends Specification {
"MannedTurretTest" should {
class FacilityTurretTest extends Specification {
"FacilityTurretTest" should {
"define" in {
val obj = new MannedTurretDefinition(480)
val obj = new TurretDefinition(480)
obj.Weapons mustEqual mutable.HashMap.empty[TurretUpgrade.Value, ToolDefinition]
obj.ReserveAmmunition mustEqual false
obj.FactionLocked mustEqual true
@ -28,7 +28,7 @@ class MannedTurretTest extends Specification {
}
"construct" in {
val obj = MannedTurret(GlobalDefinitions.manned_turret)
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
obj.Weapons.size mustEqual 1
obj.Weapons(1).Equipment match {
case Some(tool : Tool) =>
@ -51,7 +51,7 @@ class MannedTurretTest extends Specification {
}
"upgrade to a different weapon" in {
val obj = MannedTurret(GlobalDefinitions.manned_turret)
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
obj.Upgrade = TurretUpgrade.None
obj.Weapons(1).Equipment match {
case Some(tool : Tool) =>
@ -87,26 +87,26 @@ class MannedTurretTest extends Specification {
}
}
class MannedTurretControl1Test extends ActorTest {
"MannedTurretControl" should {
class FacilityTurretControl1Test extends ActorTest {
"FacilityTurretControl" should {
"construct" in {
val obj = MannedTurret(GlobalDefinitions.manned_turret)
obj.Actor = system.actorOf(Props(classOf[MannedTurretControl], obj), "turret-control")
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
obj.Actor = system.actorOf(Props(classOf[FacilityTurretControl], obj), "turret-control")
assert(obj.Actor != ActorRef.noSender)
}
}
}
class MannedTurretControl2Test extends ActorTest {
class FacilityTurretControl2Test extends ActorTest {
val player = Player(Avatar("", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
val obj = MannedTurret(GlobalDefinitions.manned_turret)
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
obj.GUID = PlanetSideGUID(1)
obj.Actor = system.actorOf(Props(classOf[MannedTurretControl], obj), "turret-control")
obj.Actor = system.actorOf(Props(classOf[FacilityTurretControl], obj), "turret-control")
val bldg = Building(0, Zone.Nowhere, StructureType.Building)
bldg.Amenities = obj
bldg.Faction = PlanetSideEmpire.TR
"MannedTurretControl" should {
"FacilityTurretControl" should {
"seat on faction affiliation when FactionLock is true" in {
assert(player.Faction == PlanetSideEmpire.TR)
assert(obj.Faction == PlanetSideEmpire.TR)
@ -124,15 +124,15 @@ class MannedTurretControl2Test extends ActorTest {
}
}
class MannedTurretControl3Test extends ActorTest {
class FacilityTurretControl3Test extends ActorTest {
val player = Player(Avatar("", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
val obj = MannedTurret(GlobalDefinitions.manned_turret)
val obj = FacilityTurret(GlobalDefinitions.manned_turret)
obj.GUID = PlanetSideGUID(1)
obj.Actor = system.actorOf(Props(classOf[MannedTurretControl], obj), "turret-control")
obj.Actor = system.actorOf(Props(classOf[FacilityTurretControl], obj), "turret-control")
val bldg = Building(0, Zone.Nowhere, StructureType.Building)
bldg.Amenities = obj
"MannedTurretControl" should {
"FacilityTurretControl" should {
"block seating on mismatched faction affiliation when FactionLock is true" in {
assert(player.Faction == PlanetSideEmpire.TR)
assert(obj.Faction == PlanetSideEmpire.NEUTRAL)
@ -150,17 +150,17 @@ class MannedTurretControl3Test extends ActorTest {
}
}
class MannedTurretControl4Test extends ActorTest {
class FacilityTurretControl4Test extends ActorTest {
val player = Player(Avatar("", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
val objDef = new MannedTurretDefinition(480)
val objDef = new TurretDefinition(480)
objDef.FactionLocked = false
val obj = MannedTurret(objDef)
val obj = FacilityTurret(objDef)
obj.GUID = PlanetSideGUID(1)
obj.Actor = system.actorOf(Props(classOf[MannedTurretControl], obj), "turret-control")
obj.Actor = system.actorOf(Props(classOf[FacilityTurretControl], obj), "turret-control")
val bldg = Building(0, Zone.Nowhere, StructureType.Building)
bldg.Amenities = obj
"MannedTurretControl" should {
"FacilityTurretControl" should {
"seating even with mismatched faction affiliation when FactionLock is false" in {
assert(player.Faction == PlanetSideEmpire.TR)
assert(obj.Faction == PlanetSideEmpire.NEUTRAL)

View file

@ -191,7 +191,7 @@ class ResourceSiloControlUpdate1Test extends ActorTest {
.actionMessage.asInstanceOf[AvatarAction.PlanetsideAttribute].attribute_value == 0)
val reply4 = probe1.receiveOne(500 milliseconds)
assert(obj.LowNtuWarningOn == false)
assert(!obj.LowNtuWarningOn)
assert(reply4.isInstanceOf[AvatarServiceMessage])
assert(reply4.asInstanceOf[AvatarServiceMessage].forChannel == "nowhere")
assert(reply4.asInstanceOf[AvatarServiceMessage]

View file

@ -246,20 +246,20 @@ class SpawnTubeObjectBuilderTest extends ActorTest {
}
}
class MannedTurretObjectBuilderTest extends ActorTest {
class FacilityTurretObjectBuilderTest extends ActorTest {
import net.psforever.objects.GlobalDefinitions.manned_turret
import net.psforever.objects.serverobject.turret.MannedTurret
"MannedTurretObjectBuilder" should {
import net.psforever.objects.serverobject.turret.FacilityTurret
"FacilityTurretObjectBuilder" should {
"build" in {
val hub = ServerObjectBuilderTest.NumberPoolHub
val actor = system.actorOf(Props(classOf[ServerObjectBuilderTest.BuilderTestActor], ServerObjectBuilder(1,
MannedTurret.Constructor(manned_turret)), hub), "spawn-tube")
FacilityTurret.Constructor(manned_turret)), hub), "spawn-tube")
actor ! "!"
val reply = receiveOne(Duration.create(1000, "ms"))
assert(reply.isInstanceOf[MannedTurret])
assert(reply.asInstanceOf[MannedTurret].HasGUID)
assert(reply.asInstanceOf[MannedTurret].GUID == PlanetSideGUID(1))
assert(reply.isInstanceOf[FacilityTurret])
assert(reply.asInstanceOf[FacilityTurret].HasGUID)
assert(reply.asInstanceOf[FacilityTurret].GUID == PlanetSideGUID(1))
assert(reply == hub(1).get)
}
}

View file

@ -5,7 +5,7 @@ import base.ActorTest
import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskRegister2Test extends ActorTest {
class GUIDTaskRegisterAmmoTest extends ActorTest {
"RegisterEquipment -> RegisterObjectTask" in {
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = AmmoBox(GlobalDefinitions.energy_cell)

View file

@ -6,7 +6,7 @@ import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
class GUIDTaskRegister5Test extends ActorTest {
class GUIDTaskRegisterAvatarTest extends ActorTest {
"RegisterAvatar" in {
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = Player(Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))

View file

@ -4,7 +4,7 @@ package objects.guidtask
import base.ActorTest
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskRegister1Test extends ActorTest {
class GUIDTaskRegisterObjectTest extends ActorTest {
"RegisterObjectTask" in {
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = new GUIDTaskTest.TestObject

View file

@ -6,7 +6,7 @@ import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
class GUIDTaskRegister6Test extends ActorTest {
class GUIDTaskRegisterPlayerTest extends ActorTest {
"RegisterPlayer" in {
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = Player(Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))

View file

@ -5,7 +5,7 @@ import base.ActorTest
import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskRegister3Test extends ActorTest {
class GUIDTaskRegisterToolTest extends ActorTest {
"RegisterEquipment -> RegisterTool" in {
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = Tool(GlobalDefinitions.beamer)

View file

@ -0,0 +1,27 @@
// Copyright (c) 2017 PSForever
package objects.guidtask
import base.ActorTest
import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskRegisterTurretTest extends ActorTest {
"RegisterDeployableTurret" in {
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs)
val obj_wep = obj.Weapons(1).Equipment.get
val obj_ammo = obj_wep.asInstanceOf[Tool].AmmoSlot.Box
val obj_res = obj.Inventory.Items.map(_.obj)
assert(!obj.HasGUID)
assert(!obj_wep.HasGUID)
assert(!obj_ammo.HasGUID)
obj_res.foreach(box => !box.HasGUID)
taskResolver ! TaskResolver.GiveTask(new GUIDTaskTest.RegisterTestTask(probe.ref), List(GUIDTask.RegisterDeployableTurret(obj)(uns)))
probe.expectMsg(scala.util.Success)
assert(obj.HasGUID)
assert(obj_wep.HasGUID)
assert(obj_ammo.HasGUID)
obj_res.foreach(box => box.HasGUID)
}
}

View file

@ -5,7 +5,7 @@ import base.ActorTest
import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskRegister4Test extends ActorTest {
class GUIDTaskRegisterVehicleTest extends ActorTest {
"RegisterVehicle" in {
val (_, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = Vehicle(GlobalDefinitions.fury)

View file

@ -5,7 +5,7 @@ import base.ActorTest
import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskUnregister2Test extends ActorTest {
class GUIDTaskUnregisterAmmoTest extends ActorTest {
"UnregisterEquipment -> UnregisterObjectTask" in {
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = AmmoBox(GlobalDefinitions.energy_cell)

View file

@ -6,7 +6,7 @@ import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
class GUIDTaskUnregister5Test extends ActorTest {
class GUIDTaskUnregisterAvatarTest extends ActorTest {
"UnregisterAvatar" in {
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = Player(Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))

View file

@ -4,7 +4,7 @@ package objects.guidtask
import base.ActorTest
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskUnregister1Test extends ActorTest {
class GUIDTaskUnregisterObjectTest extends ActorTest {
"UnregisterObjectTask" in {
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = new GUIDTaskTest.TestObject

View file

@ -6,7 +6,7 @@ import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
import net.psforever.types.{CharacterGender, CharacterVoice, PlanetSideEmpire}
class GUIDTaskUnregister6Test extends ActorTest {
class GUIDTaskUnregisterPlayerTest extends ActorTest {
"UnregisterPlayer" in {
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = Player(Avatar("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))

View file

@ -5,7 +5,7 @@ import base.ActorTest
import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskUnregister3Test extends ActorTest {
class GUIDTaskUnregisterToolTest extends ActorTest {
"UnregisterEquipment -> UnregisterTool" in {
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = Tool(GlobalDefinitions.beamer)

View file

@ -0,0 +1,31 @@
// Copyright (c) 2017 PSForever
package objects.guidtask
import base.ActorTest
import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskUnregisterTurretTest extends ActorTest {
"UnregisterDeployableTurret" in {
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs)
val obj_wep = obj.Weapons(1).Equipment.get
val obj_ammo = obj_wep.asInstanceOf[Tool].AmmoSlot.Box
val obj_res = obj.Inventory.Items.map(_.obj)
guid.register(obj, "dynamic")
guid.register(obj_wep, "dynamic")
guid.register(obj_ammo, "dynamic")
obj_res.foreach(box => guid.register(box, "dynamic"))
assert(obj.HasGUID)
assert(obj_wep.HasGUID)
assert(obj_ammo.HasGUID)
obj_res.foreach(box => box.HasGUID)
taskResolver ! TaskResolver.GiveTask(new GUIDTaskTest.RegisterTestTask(probe.ref), List(GUIDTask.UnregisterDeployableTurret(obj)(uns)))
probe.expectMsg(scala.util.Success)
assert(!obj.HasGUID)
assert(!obj_wep.HasGUID)
assert(!obj_ammo.HasGUID)
obj_res.foreach(box => !box.HasGUID)
}
}

View file

@ -5,7 +5,7 @@ import base.ActorTest
import net.psforever.objects._
import net.psforever.objects.guid.{GUIDTask, TaskResolver}
class GUIDTaskUnregister4Test extends ActorTest {
class GUIDTaskUnregisterVehicleTest extends ActorTest {
"RegisterVehicle" in {
val (guid, uns, taskResolver, probe) = GUIDTaskTest.CommonTestSetup
val obj = Vehicle(GlobalDefinitions.fury)

View file

@ -9,7 +9,7 @@ import net.psforever.objects.guid.actor.{NumberPoolActor, Register, UniqueNumber
import net.psforever.objects.guid.selector.RandomSelector
import net.psforever.objects.guid.source.LimitedNumberSource
import scala.concurrent.duration.Duration
import scala.concurrent.duration._
import scala.util.{Failure, Success}
class AllocateNumberPoolActors extends ActorTest {
@ -309,6 +309,33 @@ class UniqueNumberSystemTest9 extends ActorTest() {
}
}
class UniqueNumberSystemTestA extends ActorTest {
class EntityTestClass extends IdentifiableEntity
"UniqueNumberSystem" should {
"remain consistent between registrations" in {
val src : LimitedNumberSource = LimitedNumberSource(10)
val guid : NumberPoolHub = new NumberPoolHub(src)
guid.AddPool("pool1", (0 until 10).toList).Selector = new RandomSelector
val uns = system.actorOf(Props(classOf[UniqueNumberSystem], guid, UniqueNumberSystemTest.AllocateNumberPoolActors(guid)), "uns")
expectNoMsg(Duration.create(200, "ms"))
assert(src.CountUsed == 0)
(0 to 4).foreach(i => { assert(guid.register(new EntityTestClass(), i).isSuccess) })
assert(src.CountUsed == 5)
(0 to 5).foreach(_ => { uns ! Register(new EntityTestClass(), "pool1") })
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //6th
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //7th
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //8th
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //9th
assert(receiveOne(200 milliseconds).isInstanceOf[Success[_]]) //10th
assert(receiveOne(200 milliseconds).isInstanceOf[Failure[_]]) //no more
assert(src.CountUsed == 10)
}
}
}
object UniqueNumberSystemTest {
/**
* @see `UniqueNumberSystem.AllocateNumberPoolActors(NumberPoolHub)(implicit ActorContext)`