mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-03-04 21:10:23 +00:00
Water and Lava (#649)
* planar classes to describe levels of water and other fluid parallel to the ground * corrected purpose of field in OxygenStateMessage and adjusted the structure of the packet; the environment is now 'regions filled with stuff'; messaging pathways to facilitate drowning and drown recovery in SessionActor, WorldSession, and PlayerControl, as well as the avatar event system * drowning height is now a featur - recommend going through GlobalDefinitions; fixed lava pool collision to work on pool entry rather than drown level; lava now burns; painbox damage now is directed towards players control agency first * drowning timer works correctly for both player and vehicle targets; timing and dive depth information for targets defined, but currently originates from a generic location (ObjectDefinition); packet OSM has been modified for efficiency; classes for environment features previously exclusive to drowning mechanics have been pushed towards generic naming conventions * added sea and pools for z4, z5, z8, and z10 * vehicles now take damage (to the point of destruction) when exposed to lava due the expansion of environmental damage reasons and environmental damage modifiers; modification of the environment exposure lingo; streamlining of vital activity record system * added basic drown params to flying vehicle definitions; object trait and control mixin for environment interaction, code moved from SessionActor and WorldSession * separated environmental classes; handled waterlogged flying vehicles, in properties and code; wrote comments and tests * players mounting vehicles and players subjected to the vehicle transfer process should receive updated drown-state status of the vehicle; drowning should suspend while in the middle of vehicle transfer, in the case the process is long * increased damage performed to vehicles by lava
This commit is contained in:
parent
b07fe77c6e
commit
1a6beba335
38 changed files with 3843 additions and 1175 deletions
|
|
@ -4,7 +4,7 @@ package game
|
|||
import org.specs2.mutable._
|
||||
import net.psforever.packet._
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import net.psforever.types.{OxygenState, PlanetSideGUID}
|
||||
import scodec.bits._
|
||||
|
||||
class OxygenStateMessageTest extends Specification {
|
||||
|
|
@ -13,11 +13,12 @@ class OxygenStateMessageTest extends Specification {
|
|||
|
||||
"decode (self)" in {
|
||||
PacketCoding.decodePacket(string_self).require match {
|
||||
case OxygenStateMessage(guid, progress, active, veh_state) =>
|
||||
guid mustEqual PlanetSideGUID(75)
|
||||
progress mustEqual 50.0
|
||||
active mustEqual true
|
||||
veh_state.isDefined mustEqual false
|
||||
case OxygenStateMessage(player, vehicle) =>
|
||||
player.guid mustEqual PlanetSideGUID(75)
|
||||
player.progress mustEqual 50.0
|
||||
player.condition mustEqual OxygenState.Suffocation
|
||||
|
||||
vehicle.isDefined mustEqual false
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
|
|
@ -25,21 +26,23 @@ class OxygenStateMessageTest extends Specification {
|
|||
|
||||
"decode (vehicle)" in {
|
||||
PacketCoding.decodePacket(string_vehicle).require match {
|
||||
case OxygenStateMessage(guid, progress, active, veh_state) =>
|
||||
guid mustEqual PlanetSideGUID(75)
|
||||
progress mustEqual 50.0f
|
||||
active mustEqual true
|
||||
veh_state.isDefined mustEqual true
|
||||
veh_state.get.vehicle_guid mustEqual PlanetSideGUID(1546)
|
||||
veh_state.get.progress mustEqual 50.0f
|
||||
veh_state.get.active mustEqual true
|
||||
case OxygenStateMessage(player, vehicle) =>
|
||||
player.guid mustEqual PlanetSideGUID(75)
|
||||
player.progress mustEqual 50.0f
|
||||
player.condition mustEqual OxygenState.Suffocation
|
||||
|
||||
vehicle.isDefined mustEqual true
|
||||
val v = vehicle.get
|
||||
v.guid mustEqual PlanetSideGUID(1546)
|
||||
v.progress mustEqual 50.0f
|
||||
v.condition mustEqual OxygenState.Suffocation
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (self)" in {
|
||||
val msg = OxygenStateMessage(PlanetSideGUID(75), 50.0f, true)
|
||||
val msg = OxygenStateMessage(PlanetSideGUID(75), 50.0f)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_self
|
||||
|
|
@ -47,7 +50,7 @@ class OxygenStateMessageTest extends Specification {
|
|||
|
||||
"encode (vehicle)" in {
|
||||
val msg =
|
||||
OxygenStateMessage(PlanetSideGUID(75), 50.0f, true, WaterloggedVehicleState(PlanetSideGUID(1546), 50.0f, true))
|
||||
OxygenStateMessage(PlanetSideGUID(75), 50.0f, PlanetSideGUID(1546), 50.0f)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
|
||||
pkt mustEqual string_vehicle
|
||||
|
|
|
|||
307
src/test/scala/objects/EnvironmentTest.scala
Normal file
307
src/test/scala/objects/EnvironmentTest.scala
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package objects
|
||||
|
||||
import net.psforever.objects.{GlobalDefinitions, Player, Tool, Vehicle}
|
||||
import net.psforever.objects.definition.VehicleDefinition
|
||||
import net.psforever.objects.serverobject.environment._
|
||||
import net.psforever.objects.serverobject.terminals.{Terminal, TerminalDefinition}
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.packet.game.objectcreate.ObjectClass
|
||||
import net.psforever.types.Vector3
|
||||
import org.specs2.mutable.Specification
|
||||
|
||||
class EnvironmentCollisionTest extends Specification {
|
||||
"DeepPlane" should {
|
||||
val point: Float = 10f
|
||||
val plane = DeepPlane(point)
|
||||
|
||||
"have altitude" in {
|
||||
plane.altitude mustEqual point
|
||||
}
|
||||
|
||||
"must have interaction that passes" in {
|
||||
plane.testInteraction(Vector3(0,0,10), varDepth = -1) mustEqual true
|
||||
plane.testInteraction(Vector3(0,0, 9), varDepth = 0) mustEqual true
|
||||
plane.testInteraction(Vector3(0,0, 8), varDepth = 1) mustEqual true
|
||||
}
|
||||
|
||||
"must have interaction that fails" in {
|
||||
plane.testInteraction(Vector3(0,0,11), varDepth = -1) mustEqual false
|
||||
plane.testInteraction(Vector3(0,0,10), varDepth = 0) mustEqual false
|
||||
plane.testInteraction(Vector3(0,0, 9), varDepth = 1) mustEqual false
|
||||
}
|
||||
}
|
||||
|
||||
"DeepSquare" should {
|
||||
val point: Float = 10f
|
||||
val square = DeepSquare(point, 9, 9, 1, 1)
|
||||
|
||||
"must have altitude" in {
|
||||
square.altitude mustEqual point
|
||||
}
|
||||
|
||||
"must have interaction that passes" in {
|
||||
square.testInteraction(Vector3(1,1, 0), varDepth = 0) mustEqual true
|
||||
square.testInteraction(Vector3(1,8, 0), varDepth = 0) mustEqual true
|
||||
square.testInteraction(Vector3(8,8, 0), varDepth = 0) mustEqual true
|
||||
square.testInteraction(Vector3(8,1, 0), varDepth = 0) mustEqual true
|
||||
square.testInteraction(Vector3(1,1,10), varDepth = -1) mustEqual true
|
||||
square.testInteraction(Vector3(1,1, 9), varDepth = 0) mustEqual true
|
||||
square.testInteraction(Vector3(1,1, 8), varDepth = 1) mustEqual true
|
||||
}
|
||||
|
||||
"must have interaction that fails" in {
|
||||
square.testInteraction(Vector3(1,0, 0), varDepth = 0) mustEqual false
|
||||
square.testInteraction(Vector3(1,9, 0), varDepth = 0) mustEqual false
|
||||
square.testInteraction(Vector3(0,9, 0), varDepth = 0) mustEqual false
|
||||
square.testInteraction(Vector3(0,1, 0), varDepth = 0) mustEqual false
|
||||
square.testInteraction(Vector3(1,1,11), varDepth = -1) mustEqual false
|
||||
square.testInteraction(Vector3(1,1,10), varDepth = 0) mustEqual false
|
||||
square.testInteraction(Vector3(1,1, 9), varDepth = 1) mustEqual false
|
||||
}
|
||||
}
|
||||
|
||||
"DeepSurface" should {
|
||||
val point: Float = 10f
|
||||
val surface = DeepSurface(point, 9, 9, 1, 1)
|
||||
|
||||
"must have altitude" in {
|
||||
surface.altitude mustEqual point
|
||||
}
|
||||
|
||||
"must have interaction that passes" in {
|
||||
surface.testInteraction(Vector3(1,1,0), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(1,8,0), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(8,8,0), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(8,1,0), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(1,1,9), varDepth = -1) mustEqual true
|
||||
surface.testInteraction(Vector3(1,1,9), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(1,1,9), varDepth = 1) mustEqual true
|
||||
}
|
||||
|
||||
"must have interaction that fails" in {
|
||||
surface.testInteraction(Vector3(1,0, 0), varDepth = 0) mustEqual false
|
||||
surface.testInteraction(Vector3(1,9, 0), varDepth = 0) mustEqual false
|
||||
surface.testInteraction(Vector3(0,9, 0), varDepth = 0) mustEqual false
|
||||
surface.testInteraction(Vector3(0,1, 0), varDepth = 0) mustEqual false
|
||||
surface.testInteraction(Vector3(1,1,11), varDepth = -1) mustEqual false
|
||||
surface.testInteraction(Vector3(1,1,10), varDepth = 0) mustEqual false
|
||||
}
|
||||
}
|
||||
|
||||
"DeepCircularSurface" should {
|
||||
val point: Float = 10f
|
||||
val center = Vector3(3, 3, point)
|
||||
val surface = DeepCircularSurface(center, 3)
|
||||
|
||||
"must have altitude" in {
|
||||
surface.altitude mustEqual point
|
||||
}
|
||||
|
||||
"must have interaction that passes" in {
|
||||
surface.testInteraction(Vector3(3,1,0), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(1,3,0), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(3,5,0), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(5,3,0), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(2,2,9), varDepth = -1) mustEqual true
|
||||
surface.testInteraction(Vector3(2,2,9), varDepth = 0) mustEqual true
|
||||
surface.testInteraction(Vector3(2,2,9), varDepth = 1) mustEqual true
|
||||
}
|
||||
|
||||
"must have interaction that fails" in {
|
||||
surface.testInteraction(Vector3(3,0, 0), varDepth = 0) mustEqual false
|
||||
surface.testInteraction(Vector3(0,3, 0), varDepth = 0) mustEqual false
|
||||
surface.testInteraction(Vector3(3,6, 0), varDepth = 0) mustEqual false
|
||||
surface.testInteraction(Vector3(6,3, 0), varDepth = 0) mustEqual false
|
||||
surface.testInteraction(Vector3(2,2,11), varDepth = -1) mustEqual false
|
||||
surface.testInteraction(Vector3(2,2,10), varDepth = 0) mustEqual false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EnvironmentAttributeTest extends Specification {
|
||||
"Water" should {
|
||||
"interact with drownable object" in {
|
||||
EnvironmentAttribute.Water.canInteractWith(
|
||||
Vehicle(
|
||||
new VehicleDefinition(objectId = ObjectClass.apc_tr) { DrownAtMaxDepth = true }
|
||||
)
|
||||
) mustEqual true
|
||||
}
|
||||
|
||||
"not interact with object that does not drown" in {
|
||||
EnvironmentAttribute.Water.canInteractWith(
|
||||
Vehicle(
|
||||
new VehicleDefinition(objectId = ObjectClass.apc_tr) { DrownAtMaxDepth = false }
|
||||
)
|
||||
) mustEqual false
|
||||
}
|
||||
|
||||
"interact with depth-disable object" in {
|
||||
EnvironmentAttribute.Water.canInteractWith(
|
||||
Vehicle(
|
||||
new VehicleDefinition(objectId = ObjectClass.apc_tr) { DisableAtMaxDepth = true }
|
||||
)
|
||||
) mustEqual true
|
||||
}
|
||||
|
||||
"not interact with object that does not depth-disable" in {
|
||||
EnvironmentAttribute.Water.canInteractWith(
|
||||
Vehicle(
|
||||
new VehicleDefinition(objectId = ObjectClass.apc_tr) { DisableAtMaxDepth = false }
|
||||
)
|
||||
) mustEqual false
|
||||
}
|
||||
}
|
||||
|
||||
"Lava" should {
|
||||
"interact with a vital object that is damageable" in {
|
||||
val obj = Terminal(GlobalDefinitions.order_terminal)
|
||||
obj.isInstanceOf[Vitality] mustEqual true
|
||||
obj.asInstanceOf[Vitality].Definition.Damageable mustEqual true
|
||||
EnvironmentAttribute.Lava.canInteractWith(obj) mustEqual true
|
||||
}
|
||||
|
||||
"not interact with a vital object that is not damageable" in {
|
||||
val obj = Terminal(new TerminalDefinition(objectId = 455) {
|
||||
def Request(player : Player, msg : Any) : Terminal.Exchange = null
|
||||
Damageable = false
|
||||
})
|
||||
obj.isInstanceOf[Vitality] mustEqual true
|
||||
obj.asInstanceOf[Vitality].Definition.Damageable mustEqual false
|
||||
EnvironmentAttribute.Lava.canInteractWith(obj) mustEqual false
|
||||
}
|
||||
|
||||
"not interact with an object that has no vitality" in {
|
||||
val obj = Tool(GlobalDefinitions.suppressor)
|
||||
obj.isInstanceOf[Vitality] mustEqual false
|
||||
EnvironmentAttribute.Lava.canInteractWith(obj) mustEqual false
|
||||
}
|
||||
}
|
||||
|
||||
"Death" should {
|
||||
"interact with a vital object that is damageable" in {
|
||||
val obj = Terminal(GlobalDefinitions.order_terminal)
|
||||
obj.isInstanceOf[Vitality] mustEqual true
|
||||
obj.asInstanceOf[Vitality].Definition.Damageable mustEqual true
|
||||
EnvironmentAttribute.Death.canInteractWith(obj) mustEqual true
|
||||
}
|
||||
|
||||
"not interact with a vital object that is not damageable" in {
|
||||
val obj = Terminal(new TerminalDefinition(objectId = 455) {
|
||||
def Request(player : Player, msg : Any) : Terminal.Exchange = null
|
||||
Damageable = false
|
||||
})
|
||||
obj.isInstanceOf[Vitality] mustEqual true
|
||||
obj.asInstanceOf[Vitality].Definition.Damageable mustEqual false
|
||||
EnvironmentAttribute.Death.canInteractWith(obj) mustEqual false
|
||||
}
|
||||
|
||||
"not interact with an object that has no vitality" in {
|
||||
val obj = Tool(GlobalDefinitions.suppressor)
|
||||
obj.isInstanceOf[Vitality] mustEqual false
|
||||
EnvironmentAttribute.Death.canInteractWith(obj) mustEqual false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeaLevelTest extends Specification {
|
||||
"SeaLevel" should {
|
||||
val point: Float = 10f
|
||||
val plane = DeepPlane(point)
|
||||
val level = SeaLevel(point)
|
||||
|
||||
"have altitude (same as DeepPlane)" in {
|
||||
plane.altitude mustEqual level.altitude
|
||||
}
|
||||
|
||||
"must have interaction that passes (same as DeepPlane)" in {
|
||||
plane.testInteraction(Vector3(0,0,10), varDepth = -1) mustEqual
|
||||
level.testInteraction(Vector3(0,0,10), varDepth = -1)
|
||||
plane.testInteraction(Vector3(0,0, 9), varDepth = 0) mustEqual
|
||||
level.testInteraction(Vector3(0,0, 9), varDepth = 0)
|
||||
plane.testInteraction(Vector3(0,0, 8), varDepth = 1) mustEqual
|
||||
level.testInteraction(Vector3(0,0, 8), varDepth = 1)
|
||||
}
|
||||
|
||||
"must have interaction that fails (same as DeepPlane)" in {
|
||||
plane.testInteraction(Vector3(0,0,11), varDepth = -1) mustEqual
|
||||
level.testInteraction(Vector3(0,0,11), varDepth = -1)
|
||||
plane.testInteraction(Vector3(0,0,10), varDepth = 0) mustEqual
|
||||
level.testInteraction(Vector3(0,0,10), varDepth = 0)
|
||||
plane.testInteraction(Vector3(0,0, 9), varDepth = 1) mustEqual
|
||||
level.testInteraction(Vector3(0,0, 9), varDepth = 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PoolTest extends Specification {
|
||||
"Pool" should {
|
||||
val point: Float = 10f
|
||||
val square = DeepSquare(point, 1, 10, 10, 1)
|
||||
val pool = Pool(EnvironmentAttribute.Water, point, 1, 10, 10, 1)
|
||||
|
||||
"have altitude (same as DeepSquare)" in {
|
||||
pool.collision.altitude mustEqual square.altitude
|
||||
}
|
||||
|
||||
"must have interaction that passes (same as DeepSquare)" in {
|
||||
pool.testInteraction(Vector3(1,1, 0), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(1,1, 0), varDepth = 0)
|
||||
pool.testInteraction(Vector3(1,8, 0), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(1,8, 0), varDepth = 0)
|
||||
pool.testInteraction(Vector3(8,8, 0), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(8,8, 0), varDepth = 0)
|
||||
pool.testInteraction(Vector3(8,1, 0), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(8,1, 0), varDepth = 0)
|
||||
pool.testInteraction(Vector3(1,1,10), varDepth = -1) mustEqual
|
||||
square.testInteraction(Vector3(1,1,10), varDepth = -1)
|
||||
pool.testInteraction(Vector3(1,1, 9), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(1,1, 9), varDepth = 0)
|
||||
pool.testInteraction(Vector3(1,1, 8), varDepth = 1) mustEqual
|
||||
square.testInteraction(Vector3(1,1, 8), varDepth = 1)
|
||||
}
|
||||
|
||||
"must have interaction that fails (same as DeepSquare)" in {
|
||||
pool.testInteraction(Vector3(1,0, 0), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(1,0, 0), varDepth = 0)
|
||||
pool.testInteraction(Vector3(1,9, 0), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(1,9, 0), varDepth = 0)
|
||||
pool.testInteraction(Vector3(0,9, 0), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(0,9, 0), varDepth = 0)
|
||||
pool.testInteraction(Vector3(0,1, 0), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(0,1, 0), varDepth = 0)
|
||||
pool.testInteraction(Vector3(1,1,11), varDepth = -1) mustEqual
|
||||
square.testInteraction(Vector3(1,1,11), varDepth = -1)
|
||||
pool.testInteraction(Vector3(1,1,10), varDepth = 0) mustEqual
|
||||
square.testInteraction(Vector3(1,1,10), varDepth = 0)
|
||||
pool.testInteraction(Vector3(1,1, 9), varDepth = 1) mustEqual
|
||||
square.testInteraction(Vector3(1,1, 9), varDepth = 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PieceOfEnvironmentTest extends Specification {
|
||||
"PieceOfEnvironment" should {
|
||||
import PieceOfEnvironment.testStepIntoInteraction
|
||||
val level = SeaLevel(10f)
|
||||
|
||||
"detect entering a critical region" in {
|
||||
testStepIntoInteraction(level, Vector3(0,0,9), Vector3(0,0,11), varDepth = 0).contains(true) mustEqual true
|
||||
}
|
||||
|
||||
"detect leaving a critical region" in {
|
||||
testStepIntoInteraction(level, Vector3(0,0,11), Vector3(0,0,9), varDepth = 0).contains(false) mustEqual true
|
||||
}
|
||||
|
||||
"not detect moving outside of a critical region" in {
|
||||
testStepIntoInteraction(level, Vector3(0,0,12), Vector3(0,0,11), varDepth = 0).isEmpty mustEqual true
|
||||
}
|
||||
|
||||
"not detect moving within a critical region" in {
|
||||
testStepIntoInteraction(level, Vector3(0,0,9), Vector3(0,0,8), varDepth = 0).isEmpty mustEqual true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object EnvironmentTest { }
|
||||
211
src/test/scala/objects/InteractsWithZoneEnvironmentTest.scala
Normal file
211
src/test/scala/objects/InteractsWithZoneEnvironmentTest.scala
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
package objects
|
||||
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.environment._
|
||||
import net.psforever.objects.vital.{Vitality, VitalityDefinition}
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class InteractsWithZoneEnvironmentTest extends ActorTest {
|
||||
val pool1 = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val pool2 = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 15, 5, 10))
|
||||
val pool3 = Pool(EnvironmentAttribute.Lava, DeepSquare(-1, 15, 10, 10, 5))
|
||||
val testZone = {
|
||||
val testMap = new ZoneMap(name = "test-map") {
|
||||
environment = List(pool1, pool2, pool3)
|
||||
}
|
||||
new Zone("test-zone", testMap, zoneNumber = 0)
|
||||
}
|
||||
|
||||
"InteractsWithZoneEnvironment" should {
|
||||
"not interact with any environment when it does not encroach any environment" in {
|
||||
val testProbe = TestProbe()
|
||||
val obj = InteractsWithZoneEnvironmentTest.testObject()
|
||||
obj.Zone = testZone
|
||||
obj.Actor = testProbe.ref
|
||||
|
||||
assert(obj.Position == Vector3.Zero)
|
||||
obj.zoneInteraction()
|
||||
testProbe.expectNoMessage(max = 500 milliseconds)
|
||||
}
|
||||
|
||||
"acknowledge interaction when moved into the critical region of a registered environment object (just once)" in {
|
||||
val testProbe = TestProbe()
|
||||
val obj = InteractsWithZoneEnvironmentTest.testObject()
|
||||
obj.Zone = testZone
|
||||
obj.Actor = testProbe.ref
|
||||
|
||||
obj.Position = Vector3(1,1,-2)
|
||||
obj.zoneInteraction()
|
||||
val msg = testProbe.receiveOne(max = 250 milliseconds)
|
||||
assert(
|
||||
msg match {
|
||||
case InteractWithEnvironment(o, b, _) => (o eq obj) && (b eq pool1)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
obj.zoneInteraction()
|
||||
testProbe.expectNoMessage(max = 500 milliseconds)
|
||||
}
|
||||
|
||||
"acknowledge ceasation of interaction when moved out of a previous occupied the critical region (just once)" in {
|
||||
val testProbe = TestProbe()
|
||||
val obj = InteractsWithZoneEnvironmentTest.testObject()
|
||||
obj.Zone = testZone
|
||||
obj.Actor = testProbe.ref
|
||||
|
||||
obj.Position = Vector3(1,1,-2)
|
||||
obj.zoneInteraction()
|
||||
val msg1 = testProbe.receiveOne(max = 250 milliseconds)
|
||||
assert(
|
||||
msg1 match {
|
||||
case InteractWithEnvironment(o, b, _) => (o eq obj) && (b eq pool1)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
|
||||
obj.Position = Vector3(1,1,1)
|
||||
obj.zoneInteraction()
|
||||
val msg2 = testProbe.receiveOne(max = 250 milliseconds)
|
||||
assert(
|
||||
msg2 match {
|
||||
case EscapeFromEnvironment(o, b, _) => (o eq obj) && (b eq pool1)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
obj.zoneInteraction()
|
||||
testProbe.expectNoMessage(max = 500 milliseconds)
|
||||
}
|
||||
|
||||
"transition between two different critical regions when the regions that the same attribute" in {
|
||||
val testProbe = TestProbe()
|
||||
val obj = InteractsWithZoneEnvironmentTest.testObject()
|
||||
obj.Zone = testZone
|
||||
obj.Actor = testProbe.ref
|
||||
|
||||
obj.Position = Vector3(7,7,-2)
|
||||
obj.zoneInteraction()
|
||||
val msg1 = testProbe.receiveOne(max = 250 milliseconds)
|
||||
assert(
|
||||
msg1 match {
|
||||
case InteractWithEnvironment(o, b, _) => (o eq obj) && (b eq pool1)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
|
||||
obj.Position = Vector3(12,7,-2)
|
||||
obj.zoneInteraction()
|
||||
val msg2 = testProbe.receiveOne(max = 250 milliseconds)
|
||||
assert(
|
||||
msg2 match {
|
||||
case InteractWithEnvironment(o, b, _) => (o eq obj) && (b eq pool2)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(pool1.attribute == pool2.attribute)
|
||||
}
|
||||
|
||||
"transition between two different critical regions when the regions have different attributes" in {
|
||||
val testProbe = TestProbe()
|
||||
val obj = InteractsWithZoneEnvironmentTest.testObject()
|
||||
obj.Zone = testZone
|
||||
obj.Actor = testProbe.ref
|
||||
|
||||
obj.Position = Vector3(7,7,-2)
|
||||
obj.zoneInteraction()
|
||||
val msg1 = testProbe.receiveOne(max = 250 milliseconds)
|
||||
assert(
|
||||
msg1 match {
|
||||
case InteractWithEnvironment(o, b, _) => (o eq obj) && (b eq pool1)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
|
||||
obj.Position = Vector3(7,12,-2)
|
||||
obj.zoneInteraction()
|
||||
val msgs = testProbe.receiveN(2, max = 250 milliseconds)
|
||||
assert(
|
||||
msgs.head match {
|
||||
case EscapeFromEnvironment(o, b, _) => (o eq obj) && (b eq pool1)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msgs(1) match {
|
||||
case InteractWithEnvironment(o, b, _) => (o eq obj) && (b eq pool3)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(pool1.attribute != pool3.attribute)
|
||||
}
|
||||
}
|
||||
|
||||
"when interactions are disallowed, end any current interaction" in {
|
||||
val testProbe = TestProbe()
|
||||
val obj = InteractsWithZoneEnvironmentTest.testObject()
|
||||
obj.Zone = testZone
|
||||
obj.Actor = testProbe.ref
|
||||
|
||||
obj.Position = Vector3(1,1,-2)
|
||||
obj.zoneInteraction()
|
||||
val msg1 = testProbe.receiveOne(max = 250 milliseconds)
|
||||
assert(
|
||||
msg1 match {
|
||||
case InteractWithEnvironment(o, b, _) => (o eq obj) && (b eq pool1)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
|
||||
obj.allowZoneEnvironmentInteractions = false
|
||||
val msg2 = testProbe.receiveOne(max = 250 milliseconds)
|
||||
assert(
|
||||
msg2 match {
|
||||
case EscapeFromEnvironment(o, b, _) => (o eq obj) && (b eq pool1)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
obj.zoneInteraction()
|
||||
testProbe.expectNoMessage(max = 500 milliseconds)
|
||||
}
|
||||
|
||||
"when interactions are allowed, after having been disallowed, engage in any detected interaction" in {
|
||||
val testProbe = TestProbe()
|
||||
val obj = InteractsWithZoneEnvironmentTest.testObject()
|
||||
obj.Zone = testZone
|
||||
obj.Actor = testProbe.ref
|
||||
|
||||
obj.allowZoneEnvironmentInteractions = false
|
||||
obj.Position = Vector3(1,1,-2)
|
||||
obj.zoneInteraction()
|
||||
testProbe.expectNoMessage(max = 500 milliseconds)
|
||||
|
||||
obj.allowZoneEnvironmentInteractions = true
|
||||
val msg1 = testProbe.receiveOne(max = 250 milliseconds)
|
||||
assert(
|
||||
msg1 match {
|
||||
case InteractWithEnvironment(o, b, _) => (o eq obj) && (b eq pool1)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object InteractsWithZoneEnvironmentTest {
|
||||
def testObject(): PlanetSideServerObject with InteractsWithZoneEnvironment = {
|
||||
new PlanetSideServerObject
|
||||
with InteractsWithZoneEnvironment
|
||||
with Vitality {
|
||||
def Faction: PlanetSideEmpire.Value = PlanetSideEmpire.VS
|
||||
def DamageModel = null
|
||||
def Definition: ObjectDefinition with VitalityDefinition = new ObjectDefinition(objectId = 0) with VitalityDefinition {
|
||||
Damageable = true
|
||||
DrownAtMaxDepth = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package objects
|
||||
/*
|
||||
import akka.actor.Props
|
||||
|
||||
import akka.actor.typed.ActorRef
|
||||
import akka.actor.{ActorSystem, Props}
|
||||
import akka.testkit.TestProbe
|
||||
import base.ActorTest
|
||||
import net.psforever.actors.session.AvatarActor
|
||||
import net.psforever.objects.avatar.{Avatar, PlayerControl}
|
||||
import net.psforever.objects.ballistics._
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
|
|
@ -12,38 +14,41 @@ import net.psforever.objects.vital.Vitality
|
|||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.serverobject.environment.{DeepSquare, EnvironmentAttribute, OxygenStateTarget, Pool}
|
||||
import net.psforever.objects.vital.base.DamageResolution
|
||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.vital.projectile.ProjectileReason
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.types._
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class PlayerControlHealTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val player2 =
|
||||
Player(Avatar(1, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
val avatarProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1, player2)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, null), "player1-control")
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 6)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2, null), "player2-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.medicalapplicator) //guid=3 & 4
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(player2, 2)
|
||||
guid.register(tool, 3)
|
||||
|
|
@ -104,26 +109,25 @@ class PlayerControlHealTest extends ActorTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlHealSelfTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val avatarProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, null), "player1-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.medicalapplicator) //guid=3 & 4
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
|
|
@ -181,30 +185,30 @@ class PlayerControlHealSelfTest extends ActorTest {
|
|||
}
|
||||
|
||||
class PlayerControlRepairTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val player2 =
|
||||
Player(Avatar(1, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
val avatarProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1, player2)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, null), "player1-control")
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 6)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2, null), "player2-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.bank) //guid=3 & 4
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(player2, 2)
|
||||
guid.register(tool, 3)
|
||||
|
|
@ -277,24 +281,24 @@ class PlayerControlRepairTest extends ActorTest {
|
|||
}
|
||||
|
||||
class PlayerControlRepairSelfTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val avatarProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, null), "player1-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.bank) //guid=3 & 4
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
|
|
@ -352,40 +356,44 @@ class PlayerControlRepairSelfTest extends ActorTest {
|
|||
}
|
||||
|
||||
class PlayerControlDamageTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val player2 =
|
||||
Player(Avatar(1, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
val avatarProbe = TestProbe()
|
||||
val activityProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1, player2)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
override def Activity = activityProbe.ref
|
||||
}
|
||||
val activityProbe = TestProbe()
|
||||
val avatarProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, null), name = "player1-control")
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 6)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2, avatarActor), name = "player2-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
|
||||
val projectile = tool.Projectile
|
||||
val playerSource = SourceEntry(player2)
|
||||
val player1Source = PlayerSource(player1)
|
||||
val resolved = DamageInteraction(
|
||||
playerSource,
|
||||
SourceEntry(player2),
|
||||
ProjectileReason(
|
||||
DamageResolution.Hit,
|
||||
Projectile(
|
||||
projectile,
|
||||
tool.Definition,
|
||||
tool.FireMode,
|
||||
PlayerSource(player1),
|
||||
player1Source,
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
|
|
@ -400,12 +408,14 @@ class PlayerControlDamageTest extends ActorTest {
|
|||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"PlayerControl" should {
|
||||
"handle damage" in {
|
||||
assert(player2.Health == player2.Definition.DefaultHealth)
|
||||
assert(player2.Armor == player2.MaxArmor)
|
||||
player2.Actor ! Vitality.Damage(applyDamageTo)
|
||||
val msg_avatar = avatarProbe.receiveN(4, 500 milliseconds)
|
||||
val msg_avatar = avatarProbe.receiveN(3, 500 milliseconds)
|
||||
val msg_stamina = probe.receiveOne(500 milliseconds)
|
||||
val msg_activity = activityProbe.receiveOne(200 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head match {
|
||||
|
|
@ -414,13 +424,13 @@ class PlayerControlDamageTest extends ActorTest {
|
|||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 2, _)) => true
|
||||
case _ => false
|
||||
msg_stamina match {
|
||||
case AvatarActor.ConsumeStamina(_) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(2) match {
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
|
|
@ -428,17 +438,17 @@ class PlayerControlDamageTest extends ActorTest {
|
|||
assert(
|
||||
msg_activity match {
|
||||
case activity: Zone.HotSpot.Activity =>
|
||||
activity.attacker == PlayerSource(player1) &&
|
||||
activity.defender == playerSource &&
|
||||
activity.attacker == player1Source &&
|
||||
activity.defender == PlayerSource(player2) &&
|
||||
activity.location == Vector3(1, 0, 0)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(3) match {
|
||||
msg_avatar(2) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(Service.defaultPlayerGUID, DamageWithPositionMessage(17, Vector3(2, 0, 0)))
|
||||
AvatarAction.HitHint(PlanetSideGUID(1), PlanetSideGUID(2))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
|
|
@ -451,39 +461,49 @@ class PlayerControlDamageTest extends ActorTest {
|
|||
}
|
||||
|
||||
class PlayerControlDeathStandingTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val player2 =
|
||||
Player(Avatar(1, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
val avatarProbe = TestProbe()
|
||||
val activityProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1, player2)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
override def Activity = activityProbe.ref
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, null), name = "player1-control")
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 6)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2, avatarActor), name = "player2-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
|
||||
val projectile = tool.Projectile
|
||||
val player1Source = SourceEntry(player1)
|
||||
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
|
||||
val projectile = tool.Projectile
|
||||
val player1Source = PlayerSource(player1)
|
||||
val resolved = DamageInteraction(
|
||||
SourceEntry(player2),
|
||||
ProjectileReason(
|
||||
DamageResolution.Hit,
|
||||
Projectile(projectile, tool.Definition, tool.FireMode, player1Source, 0, Vector3(2, 0, 0), Vector3(-1, 0, 0)),
|
||||
player2.DamageModel
|
||||
Projectile(
|
||||
projectile,
|
||||
tool.Definition,
|
||||
tool.FireMode,
|
||||
player1Source,
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
player1.DamageModel
|
||||
),
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
|
|
@ -506,7 +526,8 @@ class PlayerControlDeathStandingTest extends ActorTest {
|
|||
assert(player2.isAlive)
|
||||
|
||||
player2.Actor ! Vitality.Damage(applyDamageTo)
|
||||
val msg_avatar = avatarProbe.receiveN(8, 500 milliseconds)
|
||||
val msg_avatar = avatarProbe.receiveN(7, 500 milliseconds)
|
||||
val msg_stamina = probe.receiveOne(500 milliseconds)
|
||||
activityProbe.expectNoMessage(200 milliseconds)
|
||||
assert(
|
||||
msg_avatar.head match {
|
||||
|
|
@ -515,43 +536,42 @@ class PlayerControlDeathStandingTest extends ActorTest {
|
|||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 2, _)) =>
|
||||
true
|
||||
case _ => false
|
||||
msg_stamina match {
|
||||
case AvatarActor.DeinitializeImplants() => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(2) match {
|
||||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.Killed(PlanetSideGUID(2), None)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(3) match {
|
||||
msg_avatar(2) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(4) match {
|
||||
msg_avatar(3) match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 7, _)) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(5) match {
|
||||
msg_avatar(4) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(2), _, Vector3.Zero))
|
||||
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(6) match {
|
||||
msg_avatar(5) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(
|
||||
|
|
@ -564,7 +584,7 @@ class PlayerControlDeathStandingTest extends ActorTest {
|
|||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(7) match {
|
||||
msg_avatar(6) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.DestroyDisplay(killer, victim, _, _))
|
||||
if killer.Name.equals(player1.Name) && victim.Name.equals(player2.Name) =>
|
||||
true
|
||||
|
|
@ -579,51 +599,61 @@ class PlayerControlDeathStandingTest extends ActorTest {
|
|||
}
|
||||
|
||||
class PlayerControlDeathSeatedTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val player2 =
|
||||
Player(Avatar(1, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
val avatarProbe = TestProbe()
|
||||
val activityProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1, player2)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
override def Activity = activityProbe.ref
|
||||
}
|
||||
val avatarProbe = TestProbe()
|
||||
zone.AvatarEvents = avatarProbe.ref
|
||||
val activityProbe = TestProbe()
|
||||
zone.Activity = activityProbe.ref
|
||||
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
player1.Position = Vector3(2, 0, 0)
|
||||
guid.register(player1.avatar.locker, 6)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1), "player1-control")
|
||||
val player2 =
|
||||
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.NC, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=2
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, null), name = "player1-control")
|
||||
player2.Zone = zone
|
||||
player2.Spawn()
|
||||
guid.register(player2.avatar.locker, 7)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2), "player2-control")
|
||||
guid.register(player2.avatar.locker, 6)
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player2.Actor = system.actorOf(Props(classOf[PlayerControl], player2, avatarActor), name = "player2-control")
|
||||
|
||||
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
|
||||
val vehicle = Vehicle(GlobalDefinitions.quadstealth) //guid=5
|
||||
vehicle.Faction = player2.Faction
|
||||
|
||||
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
|
||||
val projectile = tool.Projectile
|
||||
val player1Source = SourceEntry(player1)
|
||||
val resolved = DamageInteraction(
|
||||
SourceEntry(player2),
|
||||
ProjectileReason(
|
||||
DamageResolution.Hit,
|
||||
Projectile(projectile, tool.Definition, tool.FireMode, player1Source, 0, Vector3(2, 0, 0), Vector3(-1, 0, 0)),
|
||||
player2.DamageMode
|
||||
),
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.calculate()
|
||||
guid.register(player1, 1)
|
||||
guid.register(player2, 2)
|
||||
guid.register(tool, 3)
|
||||
guid.register(tool.AmmoSlot.Box, 4)
|
||||
guid.register(vehicle, 5)
|
||||
guid.register(vehicle, 7)
|
||||
val projectile = tool.Projectile
|
||||
val player1Source = PlayerSource(player1)
|
||||
val resolved = DamageInteraction(
|
||||
SourceEntry(player2),
|
||||
ProjectileReason(
|
||||
DamageResolution.Hit,
|
||||
Projectile(
|
||||
projectile,
|
||||
tool.Definition,
|
||||
tool.FireMode,
|
||||
player1Source,
|
||||
0,
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-1, 0, 0)
|
||||
),
|
||||
player1.DamageModel
|
||||
),
|
||||
Vector3(1, 0, 0)
|
||||
)
|
||||
val applyDamageTo = resolved.calculate()
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"PlayerControl" should {
|
||||
|
|
@ -636,11 +666,21 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
|||
assert(player2.isAlive)
|
||||
|
||||
player2.Actor ! Vitality.Damage(applyDamageTo)
|
||||
val msg_avatar = avatarProbe.receiveN(9, 500 milliseconds)
|
||||
val msg_avatar = avatarProbe.receiveN(8, 500 milliseconds)
|
||||
val msg_stamina = probe.receiveOne(500 milliseconds)
|
||||
activityProbe.expectNoMessage(200 milliseconds)
|
||||
assert(
|
||||
msg_stamina match {
|
||||
case AvatarActor.DeinitializeImplants() => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar.head match {
|
||||
case AvatarServiceMessage("TestCharacter2", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 2, _)) =>
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.Killed(PlanetSideGUID(2), Some(PlanetSideGUID(7)))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
|
|
@ -649,7 +689,7 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
|||
msg_avatar(1) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.Killed(PlanetSideGUID(2), Some(PlanetSideGUID(5)))
|
||||
AvatarAction.SendResponse(_, ObjectDetachMessage(PlanetSideGUID(7), PlanetSideGUID(2), _, _, _, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
|
|
@ -657,16 +697,6 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
|||
)
|
||||
assert(
|
||||
msg_avatar(2) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(_, ObjectDetachMessage(PlanetSideGUID(5), PlanetSideGUID(2), _, _, _, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(3) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 29, 1)
|
||||
|
|
@ -676,29 +706,29 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
|||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(4) match {
|
||||
msg_avatar(3) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.ObjectDelete(PlanetSideGUID(2), PlanetSideGUID(2), _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(5) match {
|
||||
msg_avatar(4) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(6) match {
|
||||
msg_avatar(5) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(2), _, Vector3.Zero))
|
||||
AvatarAction.SendResponse(_, DestroyMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(7) match {
|
||||
msg_avatar(6) match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter2",
|
||||
AvatarAction.SendResponse(
|
||||
|
|
@ -711,7 +741,7 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
|||
}
|
||||
)
|
||||
assert(
|
||||
msg_avatar(8) match {
|
||||
msg_avatar(7) match {
|
||||
case AvatarServiceMessage("test", AvatarAction.DestroyDisplay(killer, victim, _, _))
|
||||
if killer.Name.equals(player1.Name) && victim.Name.equals(player2.Name) =>
|
||||
true
|
||||
|
|
@ -724,7 +754,235 @@ class PlayerControlDeathSeatedTest extends ActorTest {
|
|||
}
|
||||
}
|
||||
|
||||
object PlayerControlTest {}
|
||||
class PlayerControlInteractWithWaterTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val avatarProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val zone = new Zone(
|
||||
id = "test",
|
||||
new ZoneMap(name = "test-map") {
|
||||
environment = List(pool)
|
||||
},
|
||||
zoneNumber = 0
|
||||
) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
}
|
||||
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
||||
|
||||
*/
|
||||
guid.register(player1, 1)
|
||||
|
||||
"PlayerControl" should {
|
||||
"cause drowning when player steps too deep in water" in {
|
||||
assert(player1.Health == 100)
|
||||
player1.Position = Vector3(5,5,-3) //right in the pool
|
||||
player1.zoneInteraction() //trigger
|
||||
|
||||
val msg_drown = avatarProbe.receiveOne(250 milliseconds)
|
||||
assert(
|
||||
msg_drown match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), OxygenState.Suffocation, 100f), _)
|
||||
) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
//player will die in 60s
|
||||
//detailing these death messages is not necessary
|
||||
assert(player1.Health == 100)
|
||||
probe.receiveOne(65 seconds) //wait until our implants deinitialize
|
||||
assert(player1.Health == 0) //ded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlStopInteractWithWaterTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val avatarProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val zone = new Zone(
|
||||
id = "test",
|
||||
new ZoneMap(name = "test-map") {
|
||||
environment = List(pool)
|
||||
},
|
||||
zoneNumber = 0
|
||||
) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
}
|
||||
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
||||
|
||||
guid.register(player1, 1)
|
||||
|
||||
"PlayerControl" should {
|
||||
"stop drowning if player steps out of deep water" in {
|
||||
assert(player1.Health == 100)
|
||||
player1.Position = Vector3(5,5,-3) //right in the pool
|
||||
player1.zoneInteraction() //trigger
|
||||
|
||||
val msg_drown = avatarProbe.receiveOne(250 milliseconds)
|
||||
assert(
|
||||
msg_drown match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), OxygenState.Suffocation, 100f), _)
|
||||
) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
//player would normally die in 60s
|
||||
player1.Position = Vector3.Zero //pool's closed
|
||||
player1.zoneInteraction() //trigger
|
||||
val msg_recover = avatarProbe.receiveOne(250 milliseconds)
|
||||
assert(
|
||||
msg_recover match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.OxygenState(OxygenStateTarget(PlanetSideGUID(1), OxygenState.Recovery, _), _)
|
||||
) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player1.Health == 100) //still alive?
|
||||
probe.expectNoMessage(65 seconds)
|
||||
assert(player1.Health == 100) //yep, still alive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlInteractWithLavaTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val avatarProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val pool = Pool(EnvironmentAttribute.Lava, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val zone = new Zone(
|
||||
id = "test-map",
|
||||
new ZoneMap(name = "test-map") {
|
||||
environment = List(pool)
|
||||
},
|
||||
zoneNumber = 0
|
||||
) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
override def Activity = TestProbe().ref
|
||||
}
|
||||
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
||||
|
||||
guid.register(player1, 1)
|
||||
|
||||
"PlayerControl" should {
|
||||
"take continuous damage if player steps into lava" in {
|
||||
assert(player1.Health == 100) //alive
|
||||
player1.Position = Vector3(5,5,-3) //right in the pool
|
||||
player1.zoneInteraction() //trigger
|
||||
|
||||
val msg_burn = avatarProbe.receiveN(3, 1 seconds)
|
||||
assert(
|
||||
msg_burn.head match {
|
||||
case AvatarServiceMessage("test-map", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(1), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_burn(1) match {
|
||||
case AvatarServiceMessage("TestCharacter1", AvatarAction.EnvironmentalDamage(PlanetSideGUID(1), _, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
msg_burn(2) match {
|
||||
case AvatarServiceMessage("test-map", AvatarAction.PlanetsideAttributeToAll(PlanetSideGUID(1), 54, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player1.Health > 0) //still alive?
|
||||
probe.receiveOne(65 seconds) //wait until player1's implants deinitialize
|
||||
assert(player1.Health == 0) //ded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerControlInteractWithDeathTest extends ActorTest {
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val avatarProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val pool = Pool(EnvironmentAttribute.Death, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val zone = new Zone(
|
||||
id = "test-map",
|
||||
new ZoneMap(name = "test-map") {
|
||||
environment = List(pool)
|
||||
},
|
||||
zoneNumber = 0
|
||||
) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
override def Activity = TestProbe().ref
|
||||
}
|
||||
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
||||
|
||||
guid.register(player1, 1)
|
||||
|
||||
"PlayerControl" should {
|
||||
"take continuous damage if player steps into a pool of death" in {
|
||||
assert(player1.Health == 100) //alive
|
||||
player1.Position = Vector3(5,5,-3) //right in the pool
|
||||
player1.zoneInteraction() //trigger
|
||||
|
||||
probe.receiveOne(250 milliseconds) //wait until oplayer1's implants deinitialize
|
||||
assert(player1.Health == 0) //ded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object PlayerControlTest {
|
||||
/**
|
||||
* A `TestProbe` whose `ActorRef` is packaged as a return type with it
|
||||
* and is passable as a typed `AvatarActor.Command` `Behavior` object.
|
||||
* Used for spawning `PlayControl` `Actor` objects with a refence to the `AvatarActor`,
|
||||
* when messaging callback renders it necessary during tests
|
||||
* but when accurate responses are unnecessary to emulate.
|
||||
* @param system what we use to spawn the `Actor`
|
||||
* @return the resulting probe, and it's modified `ActorRef`
|
||||
*/
|
||||
def DummyAvatar(system: ActorSystem): (TestProbe, ActorRef[AvatarActor.Command]) = {
|
||||
import akka.actor.typed.scaladsl.adapter.ClassicActorRefOps
|
||||
val probe = new TestProbe(system)
|
||||
val actor = ClassicActorRefOps(probe.ref).toTyped[AvatarActor.Command]
|
||||
(probe, actor)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
978
src/test/scala/objects/VehicleControlTest.scala
Normal file
978
src/test/scala/objects/VehicleControlTest.scala
Normal file
|
|
@ -0,0 +1,978 @@
|
|||
// Copyright (c) 2020 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.Props
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import akka.testkit.TestProbe
|
||||
import base.{ActorTest, FreedContextActorTest}
|
||||
import net.psforever.actors.zone.ZoneActor
|
||||
import net.psforever.objects.avatar.{Avatar, PlayerControl}
|
||||
import net.psforever.objects.{GlobalDefinitions, Player, Vehicle}
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.MaxNumberSource
|
||||
import net.psforever.objects.serverobject.environment._
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.vehicles.{VehicleControl, VehicleLockState}
|
||||
import net.psforever.objects.vital.VehicleShieldCharge
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.packet.game.{CargoMountPointStatusMessage, ObjectDetachMessage, PlanetsideAttributeMessage}
|
||||
import net.psforever.services.ServiceManager
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
import net.psforever.types._
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class VehicleControlPrepareForDeletionTest extends ActorTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val vehicleProbe = new TestProbe(system)
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = vehicleProbe.ref
|
||||
}
|
||||
|
||||
vehicle.GUID = PlanetSideGUID(1)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"VehicleControl" should {
|
||||
"submit for unregistering when marked for deconstruction" in {
|
||||
vehicle.Actor ! Vehicle.Deconstruct()
|
||||
vehicleProbe.expectNoMessage(5 seconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlPrepareForDeletionPassengerTest extends ActorTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val vehicleProbe = new TestProbe(system)
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = vehicleProbe.ref
|
||||
}
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
|
||||
vehicle.GUID = PlanetSideGUID(1)
|
||||
player1.GUID = PlanetSideGUID(2)
|
||||
vehicle.Seats(1).Occupant = player1 //passenger seat
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"VehicleControl" should {
|
||||
"kick all players when marked for deconstruction" in {
|
||||
vehicle.Actor ! Vehicle.Deconstruct()
|
||||
|
||||
val vehicle_msg = vehicleProbe.receiveN(1, 500 milliseconds)
|
||||
assert(
|
||||
vehicle_msg.head match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.KickPassenger(PlanetSideGUID(2), 4, false, PlanetSideGUID(1))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player1.VehicleSeated.isEmpty)
|
||||
assert(vehicle.Seats(1).Occupant.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlPrepareForDeletionMountedInTest extends FreedContextActorTest {
|
||||
ServiceManager.boot
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
GUID(guid)
|
||||
|
||||
override def SetupNumberPools(): Unit = {}
|
||||
}
|
||||
zone.actor = system.spawn(ZoneActor(zone), "test-zone-actor")
|
||||
// crappy workaround but without it the zone doesn't get initialized in time
|
||||
expectNoMessage(400 milliseconds)
|
||||
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test-cargo")
|
||||
vehicle.Zone = zone
|
||||
val lodestar = Vehicle(GlobalDefinitions.lodestar)
|
||||
lodestar.Faction = PlanetSideEmpire.TR
|
||||
val player1 = Player(VehicleTest.avatar1) //name="test1"
|
||||
val player2 = Player(VehicleTest.avatar2) //name="test2"
|
||||
|
||||
guid.register(vehicle, 1)
|
||||
guid.register(lodestar, 2)
|
||||
player1.GUID = PlanetSideGUID(3)
|
||||
var utilityId = 10
|
||||
lodestar.Utilities.values.foreach { util =>
|
||||
util().GUID = PlanetSideGUID(utilityId)
|
||||
utilityId += 1
|
||||
}
|
||||
vehicle.Seats(1).Occupant = player1 //passenger seat
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
lodestar.Seats(0).Occupant = player2
|
||||
player2.VehicleSeated = lodestar.GUID
|
||||
lodestar.CargoHolds(1).Occupant = vehicle
|
||||
vehicle.MountedIn = lodestar.GUID
|
||||
|
||||
val vehicleProbe = new TestProbe(system)
|
||||
zone.VehicleEvents = vehicleProbe.ref
|
||||
zone.Transport ! Zone.Vehicle.Spawn(lodestar) //can not fake this
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"VehicleControl" should {
|
||||
"if mounted as cargo, self-eject when marked for deconstruction" in {
|
||||
vehicle.Actor ! Vehicle.Deconstruct()
|
||||
|
||||
val vehicle_msg = vehicleProbe.receiveN(6, 500 milliseconds)
|
||||
//dismounting as cargo messages
|
||||
assert(
|
||||
vehicle_msg.head match {
|
||||
case VehicleServiceMessage(
|
||||
_,
|
||||
VehicleAction.SendResponse(_, PlanetsideAttributeMessage(PlanetSideGUID(1), 0, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(1) match {
|
||||
case VehicleServiceMessage(
|
||||
_,
|
||||
VehicleAction.SendResponse(_, PlanetsideAttributeMessage(PlanetSideGUID(1), 68, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(2) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(
|
||||
_,
|
||||
CargoMountPointStatusMessage(PlanetSideGUID(2), _, PlanetSideGUID(1), _, 1, CargoStatus.InProgress, 0)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(3) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(_, ObjectDetachMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _, _, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(4) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(
|
||||
_,
|
||||
CargoMountPointStatusMessage(PlanetSideGUID(2), _, _, PlanetSideGUID(1), 1, CargoStatus.Empty, 0)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
//dismounting as cargo messages
|
||||
//TODO: does not actually kick out the cargo, but instigates the process
|
||||
assert(
|
||||
vehicle_msg(5) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.KickPassenger(PlanetSideGUID(3), 4, false, PlanetSideGUID(1))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player1.VehicleSeated.isEmpty)
|
||||
assert(vehicle.Seats(1).Occupant.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlPrepareForDeletionMountedCargoTest extends FreedContextActorTest {
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(10))
|
||||
ServiceManager.boot
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
GUID(guid)
|
||||
|
||||
override def SetupNumberPools(): Unit = {}
|
||||
}
|
||||
zone.actor = system.spawn(ZoneActor(zone), "test-zone-actor")
|
||||
// crappy workaround but without it the zone doesn't get initialized in time
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Zone = zone
|
||||
val cargoProbe = new TestProbe(system)
|
||||
vehicle.Actor = cargoProbe.ref
|
||||
val lodestar = Vehicle(GlobalDefinitions.lodestar)
|
||||
lodestar.Faction = PlanetSideEmpire.TR
|
||||
val player1 = Player(VehicleTest.avatar1) //name="test1"
|
||||
val player2 = Player(VehicleTest.avatar2) //name="test2"
|
||||
|
||||
guid.register(vehicle, 1)
|
||||
guid.register(lodestar, 2)
|
||||
player1.GUID = PlanetSideGUID(3)
|
||||
player2.GUID = PlanetSideGUID(4)
|
||||
var utilityId = 10
|
||||
lodestar.Utilities.values.foreach { util =>
|
||||
util().GUID = PlanetSideGUID(utilityId)
|
||||
utilityId += 1
|
||||
}
|
||||
vehicle.Seats(1).Occupant = player1 //passenger seat
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
lodestar.Seats(0).Occupant = player2
|
||||
player2.VehicleSeated = lodestar.GUID
|
||||
lodestar.CargoHolds(1).Occupant = vehicle
|
||||
vehicle.MountedIn = lodestar.GUID
|
||||
|
||||
val vehicleProbe = new TestProbe(system)
|
||||
zone.VehicleEvents = vehicleProbe.ref
|
||||
zone.Transport ! Zone.Vehicle.Spawn(lodestar) //can not fake this
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"VehicleControl" should {
|
||||
"if with mounted cargo, eject it when marked for deconstruction" in {
|
||||
lodestar.Actor ! Vehicle.Deconstruct()
|
||||
|
||||
val vehicle_msg = vehicleProbe.receiveN(6, 500 milliseconds)
|
||||
assert(
|
||||
vehicle_msg.head match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.KickPassenger(PlanetSideGUID(4), 4, false, PlanetSideGUID(2))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player2.VehicleSeated.isEmpty)
|
||||
assert(lodestar.Seats(0).Occupant.isEmpty)
|
||||
//cargo dismounting messages
|
||||
assert(
|
||||
vehicle_msg(1) match {
|
||||
case VehicleServiceMessage(
|
||||
_,
|
||||
VehicleAction.SendResponse(_, PlanetsideAttributeMessage(PlanetSideGUID(1), 0, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(2) match {
|
||||
case VehicleServiceMessage(
|
||||
_,
|
||||
VehicleAction.SendResponse(_, PlanetsideAttributeMessage(PlanetSideGUID(1), 68, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(3) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(
|
||||
_,
|
||||
CargoMountPointStatusMessage(PlanetSideGUID(2), _, PlanetSideGUID(1), _, 1, CargoStatus.InProgress, 0)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(4) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(_, ObjectDetachMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _, _, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(5) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(
|
||||
_,
|
||||
CargoMountPointStatusMessage(PlanetSideGUID(2), _, _, PlanetSideGUID(1), 1, CargoStatus.Empty, 0)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingBlockedExosuitTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanNotMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanNotMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.ExoSuit = ExoSuitType.Reinforced
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player(VehicleTest.avatar1)
|
||||
player2.ExoSuit = ExoSuitType.MAX
|
||||
player2.GUID = PlanetSideGUID(2)
|
||||
val player3 = Player(VehicleTest.avatar1)
|
||||
player3.ExoSuit = ExoSuitType.Agile
|
||||
player3.GUID = PlanetSideGUID(3)
|
||||
|
||||
"Vehicle Control" should {
|
||||
"block players from sitting if their exo-suit is not allowed by the seat" in {
|
||||
//disallow
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 0), probe.ref) //Reinforced in non-MAX seat
|
||||
checkCanNotMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 0), probe.ref) //MAX in non-Reinforced seat
|
||||
checkCanNotMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 1), probe.ref) //MAX in non-MAX seat
|
||||
checkCanNotMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 9), probe.ref) //Reinforced in MAX-only seat
|
||||
checkCanNotMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player3, 9), probe.ref) //Agile in MAX-only seat
|
||||
checkCanNotMount()
|
||||
|
||||
//allow
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 1), probe.ref)
|
||||
checkCanMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 9), probe.ref)
|
||||
checkCanMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player3, 0), probe.ref)
|
||||
checkCanMount()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingBlockedSeatPermissionTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanNotMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanNotMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player(VehicleTest.avatar1)
|
||||
player2.GUID = PlanetSideGUID(2)
|
||||
|
||||
"Vehicle Control" should {
|
||||
//11 June 2018: Group is not supported yet so do not bother testing it
|
||||
"block players from sitting if the seat does not allow it" in {
|
||||
|
||||
vehicle.PermissionGroup(2, 3) //passenger group -> empire
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 3), probe.ref) //passenger seat
|
||||
checkCanMount()
|
||||
vehicle.PermissionGroup(2, 0) //passenger group -> locked
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 4), probe.ref) //passenger seat
|
||||
checkCanNotMount()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingDriverSeatTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
|
||||
"Vehicle Control" should {
|
||||
"allow players to sit in the driver seat, even if it is locked, if the vehicle is unowned" in {
|
||||
assert(vehicle.PermissionGroup(0).contains(VehicleLockState.Locked)) //driver group -> locked
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
assert(vehicle.Owner.isEmpty)
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 0), probe.ref)
|
||||
checkCanMount()
|
||||
assert(vehicle.Seats(0).Occupant.nonEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingOwnedLockedDriverSeatTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanNotMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanNotMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player(VehicleTest.avatar1)
|
||||
player2.GUID = PlanetSideGUID(2)
|
||||
|
||||
"Vehicle Control" should {
|
||||
"block players that are not the current owner from sitting in the driver seat (locked)" in {
|
||||
assert(vehicle.PermissionGroup(0).contains(VehicleLockState.Locked)) //driver group -> locked
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
vehicle.Owner = player1.GUID
|
||||
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 0), probe.ref)
|
||||
checkCanMount()
|
||||
assert(vehicle.Seats(0).Occupant.nonEmpty)
|
||||
vehicle.Actor.tell(Mountable.TryDismount(player1, 0), probe.ref)
|
||||
probe.receiveOne(Duration.create(100, "ms")) //discard
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 0), probe.ref)
|
||||
checkCanNotMount()
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingOwnedUnlockedDriverSeatTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player(VehicleTest.avatar1)
|
||||
player2.GUID = PlanetSideGUID(2)
|
||||
|
||||
"Vehicle Control" should {
|
||||
"allow players that are not the current owner to sit in the driver seat (empire)" in {
|
||||
vehicle.PermissionGroup(0, 3) //passenger group -> empire
|
||||
assert(vehicle.PermissionGroup(0).contains(VehicleLockState.Empire)) //driver group -> empire
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
vehicle.Owner = player1.GUID //owner set
|
||||
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 0), probe.ref)
|
||||
checkCanMount()
|
||||
assert(vehicle.Seats(0).Occupant.nonEmpty)
|
||||
vehicle.Actor.tell(Mountable.TryDismount(player1, 0), probe.ref)
|
||||
probe.receiveOne(Duration.create(100, "ms")) //discard
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 0), probe.ref)
|
||||
checkCanMount()
|
||||
assert(vehicle.Seats(0).Occupant.nonEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlShieldsChargingTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = probe.ref
|
||||
}
|
||||
|
||||
"charge vehicle shields" in {
|
||||
assert(vehicle.Shields == 0)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
|
||||
vehicle.Actor ! Vehicle.ChargeShields(15)
|
||||
val msg = probe.receiveOne(500 milliseconds)
|
||||
assert(msg match {
|
||||
case VehicleServiceMessage(_, VehicleAction.PlanetsideAttribute(_, PlanetSideGUID(10), 68, 15)) => true
|
||||
case _ => false
|
||||
})
|
||||
assert(vehicle.Shields == 15)
|
||||
assert(vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlShieldsNotChargingVehicleDeadTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = probe.ref
|
||||
}
|
||||
|
||||
"not charge vehicle shields if the vehicle is destroyed" in {
|
||||
assert(vehicle.Health > 0)
|
||||
vehicle.Health = 0
|
||||
assert(vehicle.Health == 0)
|
||||
assert(vehicle.Shields == 0)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
vehicle.Actor.tell(Vehicle.ChargeShields(15), probe.ref)
|
||||
|
||||
probe.expectNoMessage(1 seconds)
|
||||
assert(vehicle.Shields == 0)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlShieldsNotChargingVehicleShieldsFullTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = probe.ref
|
||||
}
|
||||
|
||||
"not charge vehicle shields if the vehicle is destroyed" in {
|
||||
assert(vehicle.Shields == 0)
|
||||
vehicle.Shields = vehicle.MaxShields
|
||||
assert(vehicle.Shields == vehicle.MaxShields)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
vehicle.Actor ! Vehicle.ChargeShields(15)
|
||||
|
||||
probe.expectNoMessage(1 seconds)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlShieldsNotChargingTooEarlyTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = probe.ref
|
||||
}
|
||||
|
||||
"charge vehicle shields" in {
|
||||
assert(vehicle.Shields == 0)
|
||||
|
||||
vehicle.Actor ! Vehicle.ChargeShields(15)
|
||||
val msg = probe.receiveOne(200 milliseconds)
|
||||
//assert(msg.isInstanceOf[Vehicle.UpdateShieldsCharge])
|
||||
assert(msg match {
|
||||
case VehicleServiceMessage(_, VehicleAction.PlanetsideAttribute(_, PlanetSideGUID(10), 68, 15)) => true
|
||||
case _ => false
|
||||
})
|
||||
assert(vehicle.Shields == 15)
|
||||
|
||||
vehicle.Actor ! Vehicle.ChargeShields(15)
|
||||
probe.expectNoMessage(200 milliseconds)
|
||||
assert(vehicle.Shields == 15)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO implement message protocol for zone startup completion
|
||||
//class VehicleControlShieldsNotChargingDamagedTest extends ActorTest {
|
||||
// val probe = new TestProbe(system)
|
||||
// val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
// vehicle.GUID = PlanetSideGUID(10)
|
||||
// vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
// vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
// VehicleEvents = probe.ref
|
||||
// }
|
||||
// //
|
||||
// val beamer_wep = Tool(GlobalDefinitions.beamer)
|
||||
// val p_source = PlayerSource( Player(Avatar(0, "TestTarget", PlanetSideEmpire.NC, CharacterGender.Female, 1, CharacterVoice.Mute)) )
|
||||
// val projectile = Projectile(beamer_wep.Projectile, GlobalDefinitions.beamer, beamer_wep.FireMode, p_source, GlobalDefinitions.beamer.ObjectId, Vector3.Zero, Vector3.Zero)
|
||||
// val fury_dm = Vehicle(GlobalDefinitions.fury).DamageModel
|
||||
// val obj = DamageInteraction(p_source, ProjectileReason(DamageResolution.Hit, projectile, fury_dm), Vector3(1.2f, 3.4f, 5.6f))
|
||||
//
|
||||
// "not charge vehicle shields if recently damaged" in {
|
||||
// assert(vehicle.Shields == 0)
|
||||
// vehicle.Actor.tell(Vitality.Damage({case v : Vehicle => v.History(obj); obj }), probe.ref)
|
||||
//
|
||||
// val msg = probe.receiveOne(200 milliseconds)
|
||||
// assert(msg.isInstanceOf[Vitality.DamageResolution])
|
||||
// assert(vehicle.Shields == 0)
|
||||
// vehicle.Actor.tell(Vehicle.ChargeShields(15), probe.ref)
|
||||
//
|
||||
// probe.expectNoMessage(200 milliseconds)
|
||||
// assert(vehicle.Shields == 0)
|
||||
// }
|
||||
//}
|
||||
|
||||
class VehicleControlInteractWithWaterPartialTest extends ActorTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury) //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val playerProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val zone = new Zone(
|
||||
id = "test-zone",
|
||||
new ZoneMap(name = "test-map") {
|
||||
environment = List(pool)
|
||||
},
|
||||
zoneNumber = 0
|
||||
) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def Vehicles = List(vehicle)
|
||||
}
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(vehicle, 2)
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
vehicle.Zone = zone
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Seats(0).Occupant = player1
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
player1.Actor = playerProbe.ref
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-control")
|
||||
|
||||
"VehicleControl" should {
|
||||
"causes disability when the vehicle drives too deep in water (check driver messaging)" in {
|
||||
vehicle.Position = Vector3(5,5,-3) //right in the pool
|
||||
vehicle.zoneInteraction() //trigger
|
||||
|
||||
val msg_drown = playerProbe.receiveOne(250 milliseconds)
|
||||
assert(
|
||||
msg_drown match {
|
||||
case InteractWithEnvironment(
|
||||
p1,
|
||||
p2,
|
||||
Some(OxygenStateTarget(PlanetSideGUID(2), OxygenState.Suffocation, 100f))
|
||||
) => (p1 eq player1) && (p2 eq pool)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlInteractWithWaterTest extends ActorTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury) //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val avatarProbe = TestProbe()
|
||||
val vehicleProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val zone = new Zone(
|
||||
id = "test-zone",
|
||||
new ZoneMap(name = "test-map") {
|
||||
environment = List(pool)
|
||||
},
|
||||
zoneNumber = 0
|
||||
) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def Vehicles = List(vehicle)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
override def VehicleEvents = vehicleProbe.ref
|
||||
}
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(vehicle, 2)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
vehicle.Zone = zone
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Seats(0).Occupant = player1
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-control")
|
||||
|
||||
"VehicleControl" should {
|
||||
"causes disability when the vehicle drives too deep in water" in {
|
||||
vehicle.Position = Vector3(5,5,-3) //right in the pool
|
||||
vehicle.zoneInteraction() //trigger
|
||||
|
||||
val msg_drown = avatarProbe.receiveOne(250 milliseconds)
|
||||
assert(
|
||||
msg_drown match {
|
||||
case AvatarServiceMessage(
|
||||
"TestCharacter1",
|
||||
AvatarAction.OxygenState(
|
||||
OxygenStateTarget(PlanetSideGUID(1), OxygenState.Suffocation, 100f),
|
||||
Some(OxygenStateTarget(PlanetSideGUID(2), OxygenState.Suffocation, 100f))
|
||||
)
|
||||
) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
//player will die in 60s
|
||||
//vehicle will disable in 5s; driver will be kicked
|
||||
val msg_kick = vehicleProbe.receiveOne(6 seconds)
|
||||
assert(
|
||||
msg_kick match {
|
||||
case VehicleServiceMessage(
|
||||
"test-zone",
|
||||
VehicleAction.KickPassenger(PlanetSideGUID(1), 4, _, PlanetSideGUID(2))
|
||||
) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
//player will die, but detailing players death messages is not necessary for this test
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlStopInteractWithWaterTest extends ActorTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury) //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val playerProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val pool = Pool(EnvironmentAttribute.Water, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val zone = new Zone(
|
||||
id = "test-zone",
|
||||
new ZoneMap(name = "test-map") {
|
||||
environment = List(pool)
|
||||
},
|
||||
zoneNumber = 0
|
||||
) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def Vehicles = List(vehicle)
|
||||
}
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(vehicle, 2)
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
vehicle.Zone = zone
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Seats(0).Occupant = player1
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
player1.Actor = playerProbe.ref
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-control")
|
||||
|
||||
"VehicleControl" should {
|
||||
"stop becoming disabled if the vehicle drives out of the water" in {
|
||||
vehicle.Position = Vector3(5,5,-3) //right in the pool
|
||||
vehicle.zoneInteraction() //trigger
|
||||
val msg_drown = playerProbe.receiveOne(250 milliseconds)
|
||||
assert(
|
||||
msg_drown match {
|
||||
case InteractWithEnvironment(
|
||||
p1,
|
||||
p2,
|
||||
Some(OxygenStateTarget(PlanetSideGUID(2), OxygenState.Suffocation, 100f))
|
||||
) => (p1 eq player1) && (p2 eq pool)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
|
||||
vehicle.Position = Vector3.Zero //that's enough of that
|
||||
vehicle.zoneInteraction()
|
||||
val msg_recover = playerProbe.receiveOne(250 milliseconds)
|
||||
assert(
|
||||
msg_recover match {
|
||||
case EscapeFromEnvironment(
|
||||
p1,
|
||||
p2,
|
||||
Some(OxygenStateTarget(PlanetSideGUID(2), OxygenState.Recovery, _))
|
||||
) => (p1 eq player1) && (p2 eq pool)
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlInteractWithLavaTest extends ActorTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury) //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val avatarProbe = TestProbe()
|
||||
val vehicleProbe = TestProbe()
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val pool = Pool(EnvironmentAttribute.Lava, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val zone = new Zone(
|
||||
id = "test-zone",
|
||||
new ZoneMap(name = "test-map") {
|
||||
environment = List(pool)
|
||||
},
|
||||
zoneNumber = 0
|
||||
) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def Vehicles = List(vehicle)
|
||||
override def AvatarEvents = avatarProbe.ref
|
||||
override def VehicleEvents = vehicleProbe.ref
|
||||
override def Activity = TestProbe().ref
|
||||
}
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(vehicle, 2)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
vehicle.Zone = zone
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Seats(0).Occupant = player1
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-control")
|
||||
|
||||
"VehicleControl" should {
|
||||
"take continuous damage if vehicle drives into lava" in {
|
||||
assert(vehicle.Health > 0) //alive
|
||||
assert(player1.Health == 100) //alive
|
||||
vehicle.Position = Vector3(5,5,-3) //right in the pool
|
||||
vehicle.zoneInteraction() //trigger
|
||||
|
||||
val msg_burn = vehicleProbe.receiveN(3,1 seconds)
|
||||
msg_burn.foreach { msg =>
|
||||
assert(
|
||||
msg match {
|
||||
case VehicleServiceMessage("test-zone", VehicleAction.PlanetsideAttribute(_, PlanetSideGUID(2), 0, _)) => true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
}
|
||||
//etc..
|
||||
probe.receiveOne(65 seconds) //wait until player1's implants deinitialize
|
||||
assert(vehicle.Health == 0) //ded
|
||||
assert(player1.Health == 0) //ded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlInteractWithDeathTest extends ActorTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury) //guid=2
|
||||
val player1 =
|
||||
Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)) //guid=1
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(15))
|
||||
val pool = Pool(EnvironmentAttribute.Death, DeepSquare(-1, 10, 10, 0, 0))
|
||||
val zone = new Zone(
|
||||
id = "test-zone",
|
||||
new ZoneMap(name = "test-map") {
|
||||
environment = List(pool)
|
||||
},
|
||||
zoneNumber = 0
|
||||
) {
|
||||
override def SetupNumberPools() = {}
|
||||
GUID(guid)
|
||||
override def LivePlayers = List(player1)
|
||||
override def Vehicles = List(vehicle)
|
||||
override def AvatarEvents = TestProbe().ref
|
||||
override def VehicleEvents = TestProbe().ref
|
||||
}
|
||||
|
||||
guid.register(player1, 1)
|
||||
guid.register(vehicle, 2)
|
||||
guid.register(player1.avatar.locker, 5)
|
||||
player1.Zone = zone
|
||||
player1.Spawn()
|
||||
vehicle.Zone = zone
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Seats(0).Occupant = player1
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
val (probe, avatarActor) = PlayerControlTest.DummyAvatar(system)
|
||||
player1.Actor = system.actorOf(Props(classOf[PlayerControl], player1, avatarActor), "player1-control")
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-control")
|
||||
|
||||
"VehicleControl" should {
|
||||
"take continuous damage if vehicle drives into a pool of death" in {
|
||||
assert(vehicle.Health > 0) //alive
|
||||
assert(player1.Health == 100) //alive
|
||||
vehicle.Position = Vector3(5,5,-3) //right in the pool
|
||||
vehicle.zoneInteraction() //trigger
|
||||
|
||||
probe.receiveOne(2 seconds) //wait until player1's implants deinitialize
|
||||
assert(vehicle.Health == 0) //ded
|
||||
assert(player1.Health == 0) //ded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object VehicleControlTest {
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire}
|
||||
|
||||
val avatar1 = Avatar(0, "test1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)
|
||||
val avatar2 = Avatar(1, "test2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute)
|
||||
}
|
||||
|
|
@ -1,29 +1,13 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package objects
|
||||
|
||||
import akka.actor.Props
|
||||
import akka.testkit.TestProbe
|
||||
import base.{ActorTest, FreedContextActorTest}
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.definition.{SeatDefinition, VehicleDefinition}
|
||||
import net.psforever.objects.guid.NumberPoolHub
|
||||
import net.psforever.objects.guid.source.MaxNumberSource
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.vehicles._
|
||||
import net.psforever.objects.vital.VehicleShieldCharge
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.packet.game.{CargoMountPointStatusMessage, ObjectDetachMessage, PlanetsideAttributeMessage}
|
||||
import net.psforever.types.{PlanetSideGUID, _}
|
||||
import org.specs2.mutable._
|
||||
import net.psforever.services.ServiceManager
|
||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import net.psforever.actors.zone.ZoneActor
|
||||
|
||||
class VehicleTest extends Specification {
|
||||
|
||||
import VehicleTest._
|
||||
|
||||
"SeatDefinition" should {
|
||||
|
|
@ -327,659 +311,7 @@ class VehicleTest extends Specification {
|
|||
}
|
||||
}
|
||||
|
||||
class VehicleControlPrepareForDeletionTest extends ActorTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val vehicleProbe = new TestProbe(system)
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = vehicleProbe.ref
|
||||
}
|
||||
|
||||
vehicle.GUID = PlanetSideGUID(1)
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"VehicleControl" should {
|
||||
"submit for unregistering when marked for deconstruction" in {
|
||||
vehicle.Actor ! Vehicle.Deconstruct()
|
||||
vehicleProbe.expectNoMessage(5 seconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlPrepareForDeletionPassengerTest extends ActorTest {
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val vehicleProbe = new TestProbe(system)
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = vehicleProbe.ref
|
||||
}
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
|
||||
vehicle.GUID = PlanetSideGUID(1)
|
||||
player1.GUID = PlanetSideGUID(2)
|
||||
vehicle.Seats(1).Occupant = player1 //passenger seat
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"VehicleControl" should {
|
||||
"kick all players when marked for deconstruction" in {
|
||||
vehicle.Actor ! Vehicle.Deconstruct()
|
||||
|
||||
val vehicle_msg = vehicleProbe.receiveN(1, 500 milliseconds)
|
||||
assert(
|
||||
vehicle_msg.head match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.KickPassenger(PlanetSideGUID(2), 4, false, PlanetSideGUID(1))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player1.VehicleSeated.isEmpty)
|
||||
assert(vehicle.Seats(1).Occupant.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlPrepareForDeletionMountedInTest extends FreedContextActorTest {
|
||||
ServiceManager.boot
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(10))
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
GUID(guid)
|
||||
|
||||
override def SetupNumberPools(): Unit = {}
|
||||
}
|
||||
zone.actor = system.spawn(ZoneActor(zone), "test-zone-actor")
|
||||
// crappy workaround but without it the zone doesn't get initialized in time
|
||||
expectNoMessage(400 milliseconds)
|
||||
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test-cargo")
|
||||
vehicle.Zone = zone
|
||||
val lodestar = Vehicle(GlobalDefinitions.lodestar)
|
||||
lodestar.Faction = PlanetSideEmpire.TR
|
||||
val player1 = Player(VehicleTest.avatar1) //name="test1"
|
||||
val player2 = Player(VehicleTest.avatar2) //name="test2"
|
||||
|
||||
guid.register(vehicle, 1)
|
||||
guid.register(lodestar, 2)
|
||||
player1.GUID = PlanetSideGUID(3)
|
||||
var utilityId = 10
|
||||
lodestar.Utilities.values.foreach { util =>
|
||||
util().GUID = PlanetSideGUID(utilityId)
|
||||
utilityId += 1
|
||||
}
|
||||
vehicle.Seats(1).Occupant = player1 //passenger seat
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
lodestar.Seats(0).Occupant = player2
|
||||
player2.VehicleSeated = lodestar.GUID
|
||||
lodestar.CargoHolds(1).Occupant = vehicle
|
||||
vehicle.MountedIn = lodestar.GUID
|
||||
|
||||
val vehicleProbe = new TestProbe(system)
|
||||
zone.VehicleEvents = vehicleProbe.ref
|
||||
zone.Transport ! Zone.Vehicle.Spawn(lodestar) //can not fake this
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"VehicleControl" should {
|
||||
"if mounted as cargo, self-eject when marked for deconstruction" in {
|
||||
vehicle.Actor ! Vehicle.Deconstruct()
|
||||
|
||||
val vehicle_msg = vehicleProbe.receiveN(6, 500 milliseconds)
|
||||
//dismounting as cargo messages
|
||||
assert(
|
||||
vehicle_msg.head match {
|
||||
case VehicleServiceMessage(
|
||||
_,
|
||||
VehicleAction.SendResponse(_, PlanetsideAttributeMessage(PlanetSideGUID(1), 0, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(1) match {
|
||||
case VehicleServiceMessage(
|
||||
_,
|
||||
VehicleAction.SendResponse(_, PlanetsideAttributeMessage(PlanetSideGUID(1), 68, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(2) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(
|
||||
_,
|
||||
CargoMountPointStatusMessage(PlanetSideGUID(2), _, PlanetSideGUID(1), _, 1, CargoStatus.InProgress, 0)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(3) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(_, ObjectDetachMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _, _, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(4) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(
|
||||
_,
|
||||
CargoMountPointStatusMessage(PlanetSideGUID(2), _, _, PlanetSideGUID(1), 1, CargoStatus.Empty, 0)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
//dismounting as cargo messages
|
||||
//TODO: does not actually kick out the cargo, but instigates the process
|
||||
assert(
|
||||
vehicle_msg(5) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.KickPassenger(PlanetSideGUID(3), 4, false, PlanetSideGUID(1))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player1.VehicleSeated.isEmpty)
|
||||
assert(vehicle.Seats(1).Occupant.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlPrepareForDeletionMountedCargoTest extends FreedContextActorTest {
|
||||
val guid = new NumberPoolHub(new MaxNumberSource(10))
|
||||
ServiceManager.boot
|
||||
val zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
GUID(guid)
|
||||
|
||||
override def SetupNumberPools(): Unit = {}
|
||||
}
|
||||
zone.actor = system.spawn(ZoneActor(zone), "test-zone-actor")
|
||||
// crappy workaround but without it the zone doesn't get initialized in time
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.Zone = zone
|
||||
val cargoProbe = new TestProbe(system)
|
||||
vehicle.Actor = cargoProbe.ref
|
||||
val lodestar = Vehicle(GlobalDefinitions.lodestar)
|
||||
lodestar.Faction = PlanetSideEmpire.TR
|
||||
val player1 = Player(VehicleTest.avatar1) //name="test1"
|
||||
val player2 = Player(VehicleTest.avatar2) //name="test2"
|
||||
|
||||
guid.register(vehicle, 1)
|
||||
guid.register(lodestar, 2)
|
||||
player1.GUID = PlanetSideGUID(3)
|
||||
player2.GUID = PlanetSideGUID(4)
|
||||
var utilityId = 10
|
||||
lodestar.Utilities.values.foreach { util =>
|
||||
util().GUID = PlanetSideGUID(utilityId)
|
||||
utilityId += 1
|
||||
}
|
||||
vehicle.Seats(1).Occupant = player1 //passenger seat
|
||||
player1.VehicleSeated = vehicle.GUID
|
||||
lodestar.Seats(0).Occupant = player2
|
||||
player2.VehicleSeated = lodestar.GUID
|
||||
lodestar.CargoHolds(1).Occupant = vehicle
|
||||
vehicle.MountedIn = lodestar.GUID
|
||||
|
||||
val vehicleProbe = new TestProbe(system)
|
||||
zone.VehicleEvents = vehicleProbe.ref
|
||||
zone.Transport ! Zone.Vehicle.Spawn(lodestar) //can not fake this
|
||||
expectNoMessage(200 milliseconds)
|
||||
|
||||
"VehicleControl" should {
|
||||
"if with mounted cargo, eject it when marked for deconstruction" in {
|
||||
lodestar.Actor ! Vehicle.Deconstruct()
|
||||
|
||||
val vehicle_msg = vehicleProbe.receiveN(6, 500 milliseconds)
|
||||
assert(
|
||||
vehicle_msg.head match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.KickPassenger(PlanetSideGUID(4), 4, false, PlanetSideGUID(2))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(player2.VehicleSeated.isEmpty)
|
||||
assert(lodestar.Seats(0).Occupant.isEmpty)
|
||||
//cargo dismounting messages
|
||||
assert(
|
||||
vehicle_msg(1) match {
|
||||
case VehicleServiceMessage(
|
||||
_,
|
||||
VehicleAction.SendResponse(_, PlanetsideAttributeMessage(PlanetSideGUID(1), 0, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(2) match {
|
||||
case VehicleServiceMessage(
|
||||
_,
|
||||
VehicleAction.SendResponse(_, PlanetsideAttributeMessage(PlanetSideGUID(1), 68, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(3) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(
|
||||
_,
|
||||
CargoMountPointStatusMessage(PlanetSideGUID(2), _, PlanetSideGUID(1), _, 1, CargoStatus.InProgress, 0)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(4) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(_, ObjectDetachMessage(PlanetSideGUID(2), PlanetSideGUID(1), _, _, _, _))
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
assert(
|
||||
vehicle_msg(5) match {
|
||||
case VehicleServiceMessage(
|
||||
"test",
|
||||
VehicleAction.SendResponse(
|
||||
_,
|
||||
CargoMountPointStatusMessage(PlanetSideGUID(2), _, _, PlanetSideGUID(1), 1, CargoStatus.Empty, 0)
|
||||
)
|
||||
) =>
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingBlockedExosuitTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanNotMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanNotMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.ExoSuit = ExoSuitType.Reinforced
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player(VehicleTest.avatar1)
|
||||
player2.ExoSuit = ExoSuitType.MAX
|
||||
player2.GUID = PlanetSideGUID(2)
|
||||
val player3 = Player(VehicleTest.avatar1)
|
||||
player3.ExoSuit = ExoSuitType.Agile
|
||||
player3.GUID = PlanetSideGUID(3)
|
||||
|
||||
"Vehicle Control" should {
|
||||
"block players from sitting if their exo-suit is not allowed by the seat" in {
|
||||
//disallow
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 0), probe.ref) //Reinforced in non-MAX seat
|
||||
checkCanNotMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 0), probe.ref) //MAX in non-Reinforced seat
|
||||
checkCanNotMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 1), probe.ref) //MAX in non-MAX seat
|
||||
checkCanNotMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 9), probe.ref) //Reinforced in MAX-only seat
|
||||
checkCanNotMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player3, 9), probe.ref) //Agile in MAX-only seat
|
||||
checkCanNotMount()
|
||||
|
||||
//allow
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 1), probe.ref)
|
||||
checkCanMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 9), probe.ref)
|
||||
checkCanMount()
|
||||
vehicle.Actor.tell(Mountable.TryMount(player3, 0), probe.ref)
|
||||
checkCanMount()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingBlockedSeatPermissionTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanNotMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanNotMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player(VehicleTest.avatar1)
|
||||
player2.GUID = PlanetSideGUID(2)
|
||||
|
||||
"Vehicle Control" should {
|
||||
//11 June 2018: Group is not supported yet so do not bother testing it
|
||||
"block players from sitting if the seat does not allow it" in {
|
||||
|
||||
vehicle.PermissionGroup(2, 3) //passenger group -> empire
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 3), probe.ref) //passenger seat
|
||||
checkCanMount()
|
||||
vehicle.PermissionGroup(2, 0) //passenger group -> locked
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 4), probe.ref) //passenger seat
|
||||
checkCanNotMount()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingDriverSeatTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
|
||||
"Vehicle Control" should {
|
||||
"allow players to sit in the driver seat, even if it is locked, if the vehicle is unowned" in {
|
||||
assert(vehicle.PermissionGroup(0).contains(VehicleLockState.Locked)) //driver group -> locked
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
assert(vehicle.Owner.isEmpty)
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 0), probe.ref)
|
||||
checkCanMount()
|
||||
assert(vehicle.Seats(0).Occupant.nonEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingOwnedLockedDriverSeatTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanNotMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanNotMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player(VehicleTest.avatar1)
|
||||
player2.GUID = PlanetSideGUID(2)
|
||||
|
||||
"Vehicle Control" should {
|
||||
"block players that are not the current owner from sitting in the driver seat (locked)" in {
|
||||
assert(vehicle.PermissionGroup(0).contains(VehicleLockState.Locked)) //driver group -> locked
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
vehicle.Owner = player1.GUID
|
||||
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 0), probe.ref)
|
||||
checkCanMount()
|
||||
assert(vehicle.Seats(0).Occupant.nonEmpty)
|
||||
vehicle.Actor.tell(Mountable.TryDismount(player1, 0), probe.ref)
|
||||
probe.receiveOne(Duration.create(100, "ms")) //discard
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 0), probe.ref)
|
||||
checkCanNotMount()
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlMountingOwnedUnlockedDriverSeatTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
def checkCanMount(): Unit = {
|
||||
val reply = probe.receiveOne(Duration.create(100, "ms"))
|
||||
reply match {
|
||||
case msg: Mountable.MountMessages =>
|
||||
assert(msg.response.isInstanceOf[Mountable.CanMount])
|
||||
case _ =>
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
val vehicle = Vehicle(GlobalDefinitions.apc_tr)
|
||||
vehicle.Faction = PlanetSideEmpire.TR
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
val player1 = Player(VehicleTest.avatar1)
|
||||
player1.GUID = PlanetSideGUID(1)
|
||||
val player2 = Player(VehicleTest.avatar1)
|
||||
player2.GUID = PlanetSideGUID(2)
|
||||
|
||||
"Vehicle Control" should {
|
||||
"allow players that are not the current owner to sit in the driver seat (empire)" in {
|
||||
vehicle.PermissionGroup(0, 3) //passenger group -> empire
|
||||
assert(vehicle.PermissionGroup(0).contains(VehicleLockState.Empire)) //driver group -> empire
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
vehicle.Owner = player1.GUID //owner set
|
||||
|
||||
vehicle.Actor.tell(Mountable.TryMount(player1, 0), probe.ref)
|
||||
checkCanMount()
|
||||
assert(vehicle.Seats(0).Occupant.nonEmpty)
|
||||
vehicle.Actor.tell(Mountable.TryDismount(player1, 0), probe.ref)
|
||||
probe.receiveOne(Duration.create(100, "ms")) //discard
|
||||
assert(vehicle.Seats(0).Occupant.isEmpty)
|
||||
|
||||
vehicle.Actor.tell(Mountable.TryMount(player2, 0), probe.ref)
|
||||
checkCanMount()
|
||||
assert(vehicle.Seats(0).Occupant.nonEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlShieldsChargingTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = probe.ref
|
||||
}
|
||||
|
||||
"charge vehicle shields" in {
|
||||
assert(vehicle.Shields == 0)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
|
||||
vehicle.Actor ! Vehicle.ChargeShields(15)
|
||||
val msg = probe.receiveOne(500 milliseconds)
|
||||
assert(msg match {
|
||||
case VehicleServiceMessage(_, VehicleAction.PlanetsideAttribute(_, PlanetSideGUID(10), 68, 15)) => true
|
||||
case _ => false
|
||||
})
|
||||
assert(vehicle.Shields == 15)
|
||||
assert(vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlShieldsNotChargingVehicleDeadTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = probe.ref
|
||||
}
|
||||
|
||||
"not charge vehicle shields if the vehicle is destroyed" in {
|
||||
assert(vehicle.Health > 0)
|
||||
vehicle.Health = 0
|
||||
assert(vehicle.Health == 0)
|
||||
assert(vehicle.Shields == 0)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
vehicle.Actor.tell(Vehicle.ChargeShields(15), probe.ref)
|
||||
|
||||
probe.expectNoMessage(1 seconds)
|
||||
assert(vehicle.Shields == 0)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlShieldsNotChargingVehicleShieldsFullTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = probe.ref
|
||||
}
|
||||
|
||||
"not charge vehicle shields if the vehicle is destroyed" in {
|
||||
assert(vehicle.Shields == 0)
|
||||
vehicle.Shields = vehicle.MaxShields
|
||||
assert(vehicle.Shields == vehicle.MaxShields)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
vehicle.Actor ! Vehicle.ChargeShields(15)
|
||||
|
||||
probe.expectNoMessage(1 seconds)
|
||||
assert(!vehicle.History.exists({ p => p.isInstanceOf[VehicleShieldCharge] }))
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleControlShieldsNotChargingTooEarlyTest extends ActorTest {
|
||||
val probe = new TestProbe(system)
|
||||
val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
vehicle.GUID = PlanetSideGUID(10)
|
||||
vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
VehicleEvents = probe.ref
|
||||
}
|
||||
|
||||
"charge vehicle shields" in {
|
||||
assert(vehicle.Shields == 0)
|
||||
|
||||
vehicle.Actor ! Vehicle.ChargeShields(15)
|
||||
val msg = probe.receiveOne(200 milliseconds)
|
||||
//assert(msg.isInstanceOf[Vehicle.UpdateShieldsCharge])
|
||||
assert(msg match {
|
||||
case VehicleServiceMessage(_, VehicleAction.PlanetsideAttribute(_, PlanetSideGUID(10), 68, 15)) => true
|
||||
case _ => false
|
||||
})
|
||||
assert(vehicle.Shields == 15)
|
||||
|
||||
vehicle.Actor ! Vehicle.ChargeShields(15)
|
||||
probe.expectNoMessage(200 milliseconds)
|
||||
assert(vehicle.Shields == 15)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO implement message protocol for zone startup completion
|
||||
//class VehicleControlShieldsNotChargingDamagedTest extends ActorTest {
|
||||
// val probe = new TestProbe(system)
|
||||
// val vehicle = Vehicle(GlobalDefinitions.fury)
|
||||
// vehicle.GUID = PlanetSideGUID(10)
|
||||
// vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle-test")
|
||||
// vehicle.Zone = new Zone("test", new ZoneMap("test"), 0) {
|
||||
// VehicleEvents = probe.ref
|
||||
// }
|
||||
// //
|
||||
// val beamer_wep = Tool(GlobalDefinitions.beamer)
|
||||
// val p_source = PlayerSource( Player(Avatar(0, "TestTarget", PlanetSideEmpire.NC, CharacterGender.Female, 1, CharacterVoice.Mute)) )
|
||||
// val projectile = Projectile(beamer_wep.Projectile, GlobalDefinitions.beamer, beamer_wep.FireMode, p_source, GlobalDefinitions.beamer.ObjectId, Vector3.Zero, Vector3.Zero)
|
||||
// val fury_dm = Vehicle(GlobalDefinitions.fury).DamageModel
|
||||
// val obj = DamageInteraction(p_source, ProjectileReason(DamageResolution.Hit, projectile, fury_dm), Vector3(1.2f, 3.4f, 5.6f))
|
||||
//
|
||||
// "not charge vehicle shields if recently damaged" in {
|
||||
// assert(vehicle.Shields == 0)
|
||||
// vehicle.Actor.tell(Vitality.Damage({case v : Vehicle => v.History(obj); obj }), probe.ref)
|
||||
//
|
||||
// val msg = probe.receiveOne(200 milliseconds)
|
||||
// assert(msg.isInstanceOf[Vitality.DamageResolution])
|
||||
// assert(vehicle.Shields == 0)
|
||||
// vehicle.Actor.tell(Vehicle.ChargeShields(15), probe.ref)
|
||||
//
|
||||
// probe.expectNoMessage(200 milliseconds)
|
||||
// assert(vehicle.Shields == 0)
|
||||
// }
|
||||
//}
|
||||
|
||||
object VehicleTest {
|
||||
|
||||
import net.psforever.objects.avatar.Avatar
|
||||
import net.psforever.types.{CharacterGender, PlanetSideEmpire}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class VitalityTest extends Specification {
|
|||
player.History(HealFromExoSuitChange(pSource, ExoSuitType.Standard))
|
||||
player.History(RepairFromTerm(vSource, 10, GlobalDefinitions.order_terminal))
|
||||
player.History(VehicleShieldCharge(vSource, 10))
|
||||
player.History(PlayerSuicide(pSource))
|
||||
player.History(PlayerSuicide())
|
||||
ok
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ class VitalityTest extends Specification {
|
|||
player.History(HealFromExoSuitChange(pSource, ExoSuitType.Standard))
|
||||
player.History(RepairFromTerm(vSource, 10, GlobalDefinitions.order_terminal))
|
||||
player.History(VehicleShieldCharge(vSource, 10))
|
||||
player.History(PlayerSuicide(pSource))
|
||||
player.History(PlayerSuicide())
|
||||
player.History.size mustEqual 7
|
||||
|
||||
val list = player.ClearHistory()
|
||||
|
|
@ -92,7 +92,7 @@ class VitalityTest extends Specification {
|
|||
player.History(HealFromExoSuitChange(pSource, ExoSuitType.Standard))
|
||||
player.History(RepairFromTerm(vSource, 10, GlobalDefinitions.order_terminal))
|
||||
player.History(VehicleShieldCharge(vSource, 10))
|
||||
player.History(PlayerSuicide(pSource))
|
||||
player.History(PlayerSuicide())
|
||||
|
||||
player.LastShot match {
|
||||
case Some(resolved_projectile) =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue