Damage Changes/Explosions (#644)

* created base damage interaction classes and replaced various projectile-based damage that utilized ResolvedProjectile; not refined, maintains redundancy and overloads, but should work

* continuing to reduce the exposure of ResolvedProjectile and replacing it with applications of DamageInteraction, DamageResult, and DamageReason

* removed ResolvedProjectile from the project; adjusted remaining code paths to work around it

* vitals.test became vital.base; no one liked this

* lots of inheritance, polymorphism, and other chicanery; moved around files, so it also looks like more files have changed when they have not (even if they did)

* codecov file correction

* master rebase; vital directory structure changed, so file imports have been modified in several other files; ResolutionSelection has been removed, requiring direct function literal assignment; tests repaired, where necessary; no actual functional change

* code comments

* DamageResult is its own case class now, wrapping around a before/after target and the interaction used in its calaculations; tests have been corrected

* adjusted Player.Die() to demonstrate a damage-based suicide approach

* resolved circular inheritance in projectile damage modifiers; better employed explosion reason, damages players around exploding vehicle as example

* expanded explosions to other object types; exploding is now a flag and the damage is an innate property of the object type; removed advanced references to properties on the damage source, since the damage source is easily accessible; wrote comments; fixed tests

* overhaul to painbox damage to align with normal player damage handling, thus assimilating it properly into the damage system

* future development; normal vector from euler angles; custom proximity test

* where 'innateDamage' should have not replaced 'explosion'

* moved the hitPos for the generator test; attempting to imrpove the reliability of the auto-repair integration tests (didn't ...)

* spelling and private val
This commit is contained in:
Fate-JH 2020-12-08 14:32:42 -05:00 committed by GitHub
parent b3101d9a8d
commit 6c93746767
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 4083 additions and 2490 deletions

View file

@ -6,14 +6,17 @@ import akka.testkit.TestProbe
import base.FreedContextActorTest
import net.psforever.actors.zone.BuildingActor
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.ballistics.{Projectile, ProjectileResolution, ResolvedProjectile, SourceEntry}
import net.psforever.objects.ballistics.{Projectile, SourceEntry}
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.MaxNumberSource
import net.psforever.objects.serverobject.resourcesilo.{ResourceSilo, ResourceSiloControl}
import net.psforever.objects.serverobject.structures.{AutoRepairStats, Building, StructureType}
import net.psforever.objects.serverobject.terminals.{OrderTerminalDefinition, Terminal, TerminalControl}
import net.psforever.objects.vital.Vitality
import net.psforever.objects.vital.base.DamageResolution
import net.psforever.objects.vital.damage.DamageProfile
import net.psforever.objects.vital.interaction.DamageInteraction
import net.psforever.objects.vital.projectile.ProjectileReason
import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.objects.{GlobalDefinitions, Player, Tool}
import net.psforever.services.galaxy.GalaxyService
@ -26,53 +29,51 @@ class AutoRepairFacilityIntegrationTest extends FreedContextActorTest {
import akka.actor.typed.scaladsl.adapter._
system.spawn(InterstellarClusterService(Nil), InterstellarClusterService.InterstellarClusterServiceKey.id)
ServiceManager.boot(system) ! ServiceManager.Register(Props[GalaxyService](), "galaxy")
expectNoMessage(200 milliseconds)
expectNoMessage(1000 milliseconds)
val guid = new NumberPoolHub(new MaxNumberSource(max = 10))
val avatarProbe = new TestProbe(system)
val zone = new Zone("test", new ZoneMap("test"), 0) {
override def SetupNumberPools() = {}
GUID(guid)
override def AvatarEvents = avatarProbe.ref
}
val building = Building.Structure(StructureType.Facility)(name = "integ-fac-test-building", guid = 6, map_id = 0, zone, context)
building.Invalidate()
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor)
val terminal = new Terminal(AutoRepairIntegrationTest.terminal_definition)
val silo = new ResourceSilo()
val guid = new NumberPoolHub(new MaxNumberSource(max = 10))
val zone = new Zone("test", new ZoneMap("test"), 0) {
override def SetupNumberPools() = {}
GUID(guid)
}
val avatarProbe = new TestProbe(system)
zone.AvatarEvents = avatarProbe.ref
guid.register(player, number = 1)
guid.register(weapon, number = 2)
guid.register(weapon.AmmoSlot.Box, number = 3)
guid.register(terminal, number = 4)
guid.register(silo, number = 5)
val building = Building.Structure(StructureType.Facility)(name = "test-building", guid = 6, map_id = 0, zone, context)
building.Invalidate()
guid.register(building, number = 6)
building.Amenities = silo
building.Amenities = terminal
terminal.Actor = context.actorOf(Props(classOf[TerminalControl], terminal), name = "test-terminal")
silo.NtuCapacitor = 1000
silo.Actor = system.actorOf(Props(classOf[ResourceSiloControl], silo), "test-silo")
silo.Actor ! "startup"
building.Actor ! BuildingActor.PowerOn() //artificial
val wep_fmode = weapon.FireMode
val wep_prof = wep_fmode.Add
val proj = weapon.Projectile
val proj_prof = proj.asInstanceOf[DamageProfile]
val projectile = Projectile(proj, weapon.Definition, wep_fmode, player, Vector3(2, 0, 0), Vector3.Zero)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resolved = DamageInteraction(
SourceEntry(terminal),
terminal.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
terminal.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
"AutoRepair" should {
"should activate on damage and trade NTU from the facility's resource silo for repairs" in {
@ -80,7 +81,7 @@ class AutoRepairFacilityIntegrationTest extends FreedContextActorTest {
assert(terminal.Health == terminal.MaxHealth)
terminal.Actor ! Vitality.Damage(applyDamageTo)
avatarProbe.receiveOne(max = 200 milliseconds) //health update event
avatarProbe.receiveOne(max = 1000 milliseconds) //health update event
assert(terminal.Health < terminal.MaxHealth)
var i = 0 //safety counter
while(terminal.Health < terminal.MaxHealth && i < 100) {
@ -97,45 +98,47 @@ class AutoRepairTowerIntegrationTest extends FreedContextActorTest {
import akka.actor.typed.scaladsl.adapter._
system.spawn(InterstellarClusterService(Nil), InterstellarClusterService.InterstellarClusterServiceKey.id)
ServiceManager.boot(system) ! ServiceManager.Register(Props[GalaxyService](), "galaxy")
expectNoMessage(200 milliseconds)
expectNoMessage(1000 milliseconds)
val guid = new NumberPoolHub(new MaxNumberSource(max = 10))
val avatarProbe = new TestProbe(system)
val zone = new Zone("test", new ZoneMap("test"), 0) {
override def SetupNumberPools() = {}
GUID(guid)
override def AvatarEvents = avatarProbe.ref
}
val building = Building.Structure(StructureType.Tower)(name = "integ-twr-test-building", guid = 6, map_id = 0, zone, context)
building.Invalidate()
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
player.Spawn()
val weapon = new Tool(GlobalDefinitions.suppressor)
val terminal = new Terminal(AutoRepairIntegrationTest.terminal_definition)
val guid = new NumberPoolHub(new MaxNumberSource(max = 10))
val zone = new Zone("test", new ZoneMap("test"), 0) {
override def SetupNumberPools() = {}
GUID(guid)
}
val avatarProbe = new TestProbe(system)
zone.AvatarEvents = avatarProbe.ref
terminal.Actor = context.actorOf(Props(classOf[TerminalControl], terminal), name = "test-terminal")
guid.register(player, number = 1)
guid.register(weapon, number = 2)
guid.register(weapon.AmmoSlot.Box, number = 3)
guid.register(terminal, number = 4)
val building = Building.Structure(StructureType.Tower)(name = "test-building", guid = 6, map_id = 0, zone, context)
building.Invalidate()
guid.register(building, number = 6)
building.Amenities = terminal
terminal.Actor = context.actorOf(Props(classOf[TerminalControl], terminal), name = "test-terminal")
building.Amenities = terminal
building.Actor ! BuildingActor.SuppliedWithNtu() //artificial
building.Actor ! BuildingActor.PowerOn() //artificial
val wep_fmode = weapon.FireMode
val wep_prof = wep_fmode.Add
val proj = weapon.Projectile
val proj_prof = proj.asInstanceOf[DamageProfile]
val projectile = Projectile(proj, weapon.Definition, wep_fmode, player, Vector3(2, 0, 0), Vector3.Zero)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resolved = DamageInteraction(
SourceEntry(terminal),
terminal.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
terminal.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
"AutoRepair" should {
"should activate on damage and trade NTU from the tower for repairs" in {

View file

@ -7,13 +7,16 @@ import base.FreedContextActorTest
import net.psforever.actors.commands.NtuCommand
import net.psforever.actors.zone.BuildingActor
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.ballistics.{Projectile, ProjectileResolution, ResolvedProjectile, SourceEntry}
import net.psforever.objects.ballistics.{Projectile, SourceEntry}
import net.psforever.objects.guid.NumberPoolHub
import net.psforever.objects.guid.source.MaxNumberSource
import net.psforever.objects.serverobject.structures.{AutoRepairStats, Building, StructureType}
import net.psforever.objects.serverobject.terminals.{OrderTerminalDefinition, Terminal, TerminalControl}
import net.psforever.objects.vital.Vitality
import net.psforever.objects.vital.base.DamageResolution
import net.psforever.objects.vital.damage.DamageProfile
import net.psforever.objects.vital.interaction.DamageInteraction
import net.psforever.objects.vital.projectile.ProjectileReason
import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.objects.{GlobalDefinitions, Player, Tool}
import net.psforever.services.ServiceManager
@ -54,14 +57,17 @@ class AutoRepairRequestNtuTest extends FreedContextActorTest {
val proj = weapon.Projectile
val proj_prof = proj.asInstanceOf[DamageProfile]
val projectile = Projectile(proj, weapon.Definition, wep_fmode, player, Vector3(2, 0, 0), Vector3.Zero)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resolved = DamageInteraction(
DamageResolution.Hit,
SourceEntry(terminal),
terminal.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
terminal.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
"AutoRepair" should {
"asks owning building for NTU after damage" in {
@ -114,14 +120,17 @@ class AutoRepairRequestNtuRepeatTest extends FreedContextActorTest {
val proj = weapon.Projectile
val proj_prof = proj.asInstanceOf[DamageProfile]
val projectile = Projectile(proj, weapon.Definition, wep_fmode, player, Vector3(2, 0, 0), Vector3.Zero)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resolved = DamageInteraction(
DamageResolution.Hit,
SourceEntry(terminal),
terminal.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
terminal.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
"AutoRepair" should {
"repeatedly asks owning building for NTU after damage" in {
@ -176,14 +185,17 @@ class AutoRepairNoRequestNtuTest extends FreedContextActorTest {
val proj = weapon.Projectile
val proj_prof = proj.asInstanceOf[DamageProfile]
val projectile = Projectile(proj, weapon.Definition, wep_fmode, player, Vector3(2, 0, 0), Vector3.Zero)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resolved = DamageInteraction(
DamageResolution.Hit,
SourceEntry(terminal),
terminal.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
terminal.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
"AutoRepair" should {
"not ask for NTU after damage if it expects no NTU" in {
@ -231,14 +243,17 @@ class AutoRepairRestoreRequestNtuTest extends FreedContextActorTest {
val proj = weapon.Projectile
val proj_prof = proj.asInstanceOf[DamageProfile]
val projectile = Projectile(proj, weapon.Definition, wep_fmode, player, Vector3(2, 0, 0), Vector3.Zero)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resolved = DamageInteraction(
DamageResolution.Hit,
SourceEntry(terminal),
terminal.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
terminal.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
"AutoRepair" should {
"ask for NTU after damage if its expectation of NTU is restored" in {
@ -295,14 +310,17 @@ class AutoRepairRepairWithNtuTest extends FreedContextActorTest {
val proj = weapon.Projectile
val proj_prof = proj.asInstanceOf[DamageProfile]
val projectile = Projectile(proj, weapon.Definition, wep_fmode, player, Vector3(2, 0, 0), Vector3.Zero)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resolved = DamageInteraction(
DamageResolution.Hit,
SourceEntry(terminal),
terminal.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
terminal.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
"AutoRepair" should {
"repair some of the damage when it receives NTU" in {
@ -354,14 +372,17 @@ class AutoRepairRepairWithNtuUntilDoneTest extends FreedContextActorTest {
val proj = weapon.Projectile
val proj_prof = proj.asInstanceOf[DamageProfile]
val projectile = Projectile(proj, weapon.Definition, wep_fmode, player, Vector3(2, 0, 0), Vector3.Zero)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resolved = DamageInteraction(
DamageResolution.Hit,
SourceEntry(terminal),
terminal.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
terminal.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
"AutoRepair" should {
"ask for NTU after damage and repair some of the damage when it receives NTU, until fully-repaired" in {

View file

@ -2,7 +2,8 @@
package objects
import net.psforever.objects._
import net.psforever.objects.vital.damage.{DamageCalculations, DamageModifiers, DamageProfile}
import net.psforever.objects.vital.damage.{DamageProfile, _}
import net.psforever.objects.vital.projectile._
import DamageCalculations._
import net.psforever.objects.vital.resistance.ResistanceCalculations
import ResistanceCalculations._
@ -10,11 +11,13 @@ import net.psforever.objects.vital.resolution.ResolutionCalculations
import ResolutionCalculations._
import net.psforever.objects.ballistics._
import net.psforever.objects.definition.{ProjectileDefinition, VehicleDefinition}
import net.psforever.objects.vital.{DamageType, Vitality}
import net.psforever.objects.vital.Vitality
import net.psforever.packet.game.objectcreate.ObjectClass
import net.psforever.types._
import org.specs2.mutable.Specification
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.vital.base._
import net.psforever.objects.vital.interaction.DamageInteraction
class DamageCalculationsTests extends Specification {
"DamageCalculations" should {
@ -27,11 +30,13 @@ class DamageCalculationsTests extends Specification {
val projectile = Projectile(proj, wep, wep_fmode, player, Vector3(2, 2, 0), Vector3.Zero)
val target = Vehicle(GlobalDefinitions.fury)
target.Position = Vector3(10, 0, 0)
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target.DamageModel
),
Vector3(15, 0, 0)
)
@ -60,173 +65,198 @@ class DamageCalculationsTests extends Specification {
}
"no degrade damage modifier" in {
DamageModifiers.SameHit.Calculate(100, resprojectile) mustEqual 100
SameHit.calculate(100, resprojectile) mustEqual 100
}
"degrade over distance damage modifier (no degrade)" in {
DamageModifiers.DistanceDegrade.Calculate(100, resprojectile) == 100 mustEqual true
DistanceDegrade.calculate(100, resprojectile) == 100 mustEqual true
}
"cut off damage at max distance (no cutoff)" in {
DamageModifiers.MaxDistanceCutoff.Calculate(100, resprojectile) == 100 mustEqual true
MaxDistanceCutoff.calculate(100, resprojectile) == 100 mustEqual true
}
"cut off damage at max distance (cutoff)" in {
val cutoffprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val cutoffprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target.DamageModel
),
Vector3(1500, 0, 0)
)
DamageModifiers.MaxDistanceCutoff.Calculate(100, cutoffprojectile) == 0 mustEqual true
val damage = MaxDistanceCutoff.calculate(100, cutoffprojectile)
damage == 0 mustEqual true
}
"cut off damage at custom distance (no cutoff)" in {
DamageModifiers.CustomDistanceCutoff(10).Calculate(100, resprojectile) == 0 mustEqual true
CustomDistanceCutoff(10).calculate(100, resprojectile) == 0 mustEqual true
}
"cut off damage at custom distance (cutoff)" in {
val coffprojectile = ResolvedProjectile(
ProjectileResolution.Splash,
projectile,
val coffprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
projectile,
target.DamageModel
),
Vector3(10, 0, 0)
)
DamageModifiers.CustomDistanceCutoff(2).Calculate(100, coffprojectile) == 0 mustEqual true
CustomDistanceCutoff(2).calculate(100, coffprojectile) == 0 mustEqual true
}
"degrade over distance damage modifier (some degrade)" in {
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Splash,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
projectile,
target.DamageModel
),
Vector3(100, 0, 0)
)
val damage = DamageModifiers.DistanceDegrade.Calculate(100, resprojectile2)
val damage = DistanceDegrade.calculate(100, resprojectile2)
damage < 100 && damage > 0 mustEqual true
}
"degrade over distance damage modifier (zero'd)" in {
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Splash,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
projectile,
target.DamageModel
),
Vector3(1000, 0, 0)
)
DamageModifiers.DistanceDegrade.Calculate(100, resprojectile2) == 0 mustEqual true
DistanceDegrade.calculate(100, resprojectile2) == 0 mustEqual true
}
"degrade at radial distance damage modifier (no degrade)" in {
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Splash,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
projectile,
target.DamageModel
),
Vector3(10, 0, 0)
)
DamageModifiers.RadialDegrade.Calculate(100, resprojectile2) == 100 mustEqual true
RadialDegrade.calculate(100, resprojectile2) == 100 mustEqual true
}
"degrade at radial distance damage modifier (some degrade)" in {
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Splash,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
projectile,
target.DamageModel
),
Vector3(12, 0, 0)
)
val damage = DamageModifiers.RadialDegrade.Calculate(100, resprojectile2)
val damage = RadialDegrade.calculate(100, resprojectile2)
damage < 100 && damage > 0 mustEqual true
}
"degrade at radial distance damage modifier (zero'd)" in {
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Splash,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
projectile,
target.DamageModel
),
Vector3(100, 0, 0)
)
DamageModifiers.RadialDegrade.Calculate(100, resprojectile2) == 0 mustEqual true
RadialDegrade.calculate(100, resprojectile2) == 0 mustEqual true
}
"lash degrade (no lash; too close)" in {
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Lash,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Lash,
projectile,
target.DamageModel
),
Vector3(5, 0, 0) //compared to Vector3(2, 2, 0)
)
DamageModifiers.Lash.Calculate(100, resprojectile2) == 0 mustEqual true
Lash.calculate(100, resprojectile2) == 0 mustEqual true
}
"lash degrade (lash)" in {
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Lash,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Lash,
projectile,
target.DamageModel
),
Vector3(20, 0, 0)
)
val damage = DamageModifiers.Lash.Calculate(100, resprojectile2)
val damage = Lash.calculate(100, resprojectile2)
damage < 100 && damage > 0 mustEqual true
}
"lash degrade (no lash; too far)" in {
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Lash,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Lash,
projectile,
target.DamageModel
),
Vector3(1000, 0, 0)
)
DamageModifiers.Lash.Calculate(100, resprojectile2) == 0 mustEqual true
Lash.calculate(100, resprojectile2) == 0 mustEqual true
}
"fireball aggravated damage (aggravated splash burn" in {
val burnWeapon = Tool(GlobalDefinitions.flamethrower)
val burnProjectile = Projectile(
burnWeapon.Projectile,
burnWeapon.Definition,
burnWeapon.FireMode,
player,
Vector3(2, 2, 0),
Vector3.Zero
)
val burnRes = ResolvedProjectile(
ProjectileResolution.AggravatedSplashBurn,
projectile,
// val burnWeapon = Tool(GlobalDefinitions.flamethrower)
// val burnProjectile = Projectile(
// burnWeapon.Projectile,
// burnWeapon.Definition,
// burnWeapon.FireMode,
// player,
// Vector3(2, 2, 0),
// Vector3.Zero
// )
val burnRes = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.AggravatedSplashBurn,
projectile,
target.DamageModel
),
Vector3(15, 0, 0)
)
val resistance = burnRes.damage_model.ResistUsing(burnRes)(burnRes)
DamageModifiers.FireballAggravatedBurn.Calculate(100, burnRes) == (1 + resistance) mustEqual true
val resistance = target.DamageModel.ResistUsing(burnRes)(burnRes)
FireballAggravatedBurn.calculate(100, burnRes) == (1 + resistance) mustEqual true
}
"fireball aggravated damage (noral splash, no modification)" in {
val burnWeapon = Tool(GlobalDefinitions.flamethrower)
val burnProjectile = Projectile(
burnWeapon.Projectile,
burnWeapon.Definition,
burnWeapon.FireMode,
player,
Vector3(2, 2, 0),
Vector3.Zero
)
val burnRes = ResolvedProjectile(
ProjectileResolution.Splash,
projectile,
// val burnWeapon = Tool(GlobalDefinitions.flamethrower)
// val burnProjectile = Projectile(
// burnWeapon.Projectile,
// burnWeapon.Definition,
// burnWeapon.FireMode,
// player,
// Vector3(2, 2, 0),
// Vector3.Zero
// )
val burnRes = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
projectile,
target.DamageModel
),
Vector3(15, 0, 0)
)
DamageModifiers.FireballAggravatedBurn.Calculate(100, burnRes) == 100 mustEqual true
FireballAggravatedBurn.calculate(100, burnRes) == 100 mustEqual true
}
val charge_weapon = Tool(GlobalDefinitions.spiker)
@ -243,42 +273,52 @@ class DamageCalculationsTests extends Specification {
"charge (none)" in {
val cprojectile = charge_projectile.quality(ProjectileQuality.Modified(0))
val rescprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
cprojectile,
val rescprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
cprojectile,
target.DamageModel
),
Vector3(15, 0, 0)
)
val damage = DamageModifiers.SpikerChargeDamage.Calculate(chargeBaseDamage, rescprojectile)
val calcDam = minDamageBase + math.floor(chargeBaseDamage * rescprojectile.projectile.quality.mod)
val damage = SpikerChargeDamage.calculate(chargeBaseDamage, rescprojectile)
val calcDam = minDamageBase + math.floor(
chargeBaseDamage * rescprojectile.cause.asInstanceOf[ProjectileReason].projectile.quality.mod
)
damage mustEqual calcDam
}
"charge (half)" in {
val cprojectile = charge_projectile.quality(ProjectileQuality.Modified(0.5f))
val rescprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
cprojectile,
val rescprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
cprojectile,
target.DamageModel
),
Vector3(15, 0, 0)
)
val damage = DamageModifiers.SpikerChargeDamage.Calculate(chargeBaseDamage, rescprojectile)
val calcDam = minDamageBase + math.floor(chargeBaseDamage * rescprojectile.projectile.quality.mod)
val damage = SpikerChargeDamage.calculate(chargeBaseDamage, rescprojectile)
val calcDam = minDamageBase + math.floor(
chargeBaseDamage * rescprojectile.cause.asInstanceOf[ProjectileReason].projectile.quality.mod
)
damage mustEqual calcDam
}
"charge (full)" in {
val cprojectile = charge_projectile.quality(ProjectileQuality.Modified(1))
val rescprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
cprojectile,
val rescprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
cprojectile,
target.DamageModel
),
Vector3(15, 0, 0)
)
val damage = DamageModifiers.SpikerChargeDamage.Calculate(chargeBaseDamage, rescprojectile)
val damage = SpikerChargeDamage.calculate(chargeBaseDamage, rescprojectile)
val calcDam = minDamageBase + chargeBaseDamage
damage mustEqual calcDam
}
@ -294,124 +334,142 @@ class DamageCalculationsTests extends Specification {
)
"flak hit (resolution is splash, no degrade)" in {
val resfprojectile = ResolvedProjectile(
ProjectileResolution.Splash,
flak_projectile,
val resfprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
flak_projectile,
target.DamageModel
),
Vector3(10, 0, 0)
)
val damage = DamageModifiers.FlakHit.Calculate(100, resfprojectile)
val damage = FlakHit.calculate(100, resfprojectile)
damage == 100 mustEqual true
}
"flak hit (resolution is hit, no degrade)" in {
val resfprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
flak_projectile,
val resfprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
flak_projectile,
target.DamageModel
),
Vector3(10, 0, 0)
)
val damage = DamageModifiers.FlakHit.Calculate(100, resfprojectile)
val damage = FlakHit.calculate(100, resfprojectile)
damage == 100 mustEqual true
}
"flak burst (resolution is hit)" in {
val resfprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
flak_projectile,
val resfprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
flak_projectile,
target.DamageModel
),
Vector3(15, 0, 0)
)
val damage = DamageModifiers.FlakBurst.Calculate(100, resfprojectile)
val damage = FlakBurst.calculate(100, resfprojectile)
damage == 100 mustEqual true
}
"flak burst (resolution is splash, no degrade)" in {
val resfprojectile = ResolvedProjectile(
ProjectileResolution.Splash,
flak_projectile,
val resfprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
flak_projectile,
target.DamageModel
),
Vector3(10, 0, 0)
)
val damage = DamageModifiers.FlakBurst.Calculate(100, resfprojectile)
val damage = FlakBurst.calculate(100, resfprojectile)
damage == 100 mustEqual true
}
"flak burst (resolution is splash, some degrade)" in {
val resfprojectile = ResolvedProjectile(
ProjectileResolution.Splash,
flak_projectile,
val resfprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Splash,
flak_projectile,
target.DamageModel
),
Vector3(5, 0, 0)
)
val damage = DamageModifiers.FlakBurst.Calculate(100, resfprojectile)
val damage = FlakBurst.calculate(100, resfprojectile)
damage < 100 mustEqual true
}
"galaxy gunship reduction (target is galaxy_gunship, no shields)" in {
val vehicle = Vehicle(GlobalDefinitions.galaxy_gunship)
val resfprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resfprojectile = DamageInteraction(
SourceEntry(vehicle),
vehicle.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
vehicle.DamageModel
),
Vector3(5, 0, 0)
)
val damage = DamageModifiers.GalaxyGunshipReduction(0.63f).Calculate(100, resfprojectile)
val damage = GalaxyGunshipReduction(0.63f).calculate(100, resfprojectile)
damage == 63 mustEqual true
}
"galaxy gunship reduction (target is galaxy_gunship)" in {
val vehicle = Vehicle(GlobalDefinitions.galaxy_gunship)
vehicle.Shields = 1
val resfprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resfprojectile = DamageInteraction(
SourceEntry(vehicle),
vehicle.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
vehicle.DamageModel
),
Vector3(5, 0, 0)
)
val damage = DamageModifiers.GalaxyGunshipReduction(0.63f).Calculate(100, resfprojectile)
val damage = GalaxyGunshipReduction(0.63f).calculate(100, resfprojectile)
damage == 100 mustEqual true
}
"galaxy gunship reduction (target is vehicle, but not a galaxy_gunship)" in {
val resfprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resfprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target.DamageModel
),
Vector3(5, 0, 0)
)
val damage = DamageModifiers.GalaxyGunshipReduction(0.63f).Calculate(100, resfprojectile)
val damage = GalaxyGunshipReduction(0.63f).calculate(100, resfprojectile)
damage == 100 mustEqual true
}
"galaxy gunship reduction (target is not a vehicle)" in {
val tplayer =
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
val resfprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resfprojectile = DamageInteraction(
SourceEntry(tplayer),
tplayer.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
tplayer.DamageModel
),
Vector3(5, 0, 0)
)
val damage = DamageModifiers.GalaxyGunshipReduction(0.63f).Calculate(100, resfprojectile)
val damage = GalaxyGunshipReduction(0.63f).calculate(100, resfprojectile)
damage == 100 mustEqual true
}
"extract a complete damage profile" in {
val result1 = DamageModifiers.RadialDegrade.Calculate(
val result1 = RadialDegrade.calculate(
AgainstVehicle(proj_prof) + AgainstVehicle(wep_prof),
resprojectile
)
val result2 = DamageCalculations.DamageWithModifiers(AgainstVehicle, resprojectile)
val result2 = DamageCalculations.WithModifiers(AgainstVehicle, resprojectile)
result1 mustEqual result2
}
}
@ -427,11 +485,13 @@ class ResistanceCalculationsTests extends Specification {
"ResistanceCalculations" should {
"ignore all targets" in {
val target = Vehicle(GlobalDefinitions.fury)
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target.DamageModel
),
Vector3.Zero
)
InvalidTarget(resprojectile).isFailure mustEqual true
@ -439,11 +499,13 @@ class ResistanceCalculationsTests extends Specification {
"discern standard infantry targets" in {
val target = player
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target.DamageModel
),
Vector3.Zero
)
ValidInfantryTarget(resprojectile).isSuccess mustEqual true
@ -455,11 +517,13 @@ class ResistanceCalculationsTests extends Specification {
"discern mechanized infantry targets" in {
val target = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
target.ExoSuit = ExoSuitType.MAX
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target.DamageModel
),
Vector3.Zero
)
ValidInfantryTarget(resprojectile).isSuccess mustEqual false
@ -470,11 +534,13 @@ class ResistanceCalculationsTests extends Specification {
"discern ground vehicle targets" in {
val target = Vehicle(GlobalDefinitions.fury)
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target.DamageModel
),
Vector3.Zero
)
ValidInfantryTarget(resprojectile).isSuccess mustEqual false
@ -485,11 +551,13 @@ class ResistanceCalculationsTests extends Specification {
"discern flying vehicle targets" in {
val target = Vehicle(GlobalDefinitions.mosquito)
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target.DamageModel
),
Vector3.Zero
)
ValidInfantryTarget(resprojectile).isSuccess mustEqual false
@ -531,11 +599,13 @@ class ResolutionCalculationsTests extends Specification {
"ResolutionCalculations" should {
"calculate no damage" in {
val target = player
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target.DamageModel
),
Vector3.Zero
)
ResolutionCalculations.NoDamage(resprojectile)(50, 50) mustEqual 0
@ -543,21 +613,25 @@ class ResolutionCalculationsTests extends Specification {
"calculate no infantry damage for vehicles" in {
val target1 = Vehicle(GlobalDefinitions.fury) //!
val resprojectile1 = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile1 = DamageInteraction(
SourceEntry(target1),
target1.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target1.DamageModel
),
Vector3.Zero
)
InfantryDamage(resprojectile1)(50, 10) mustEqual (0, 0)
val target2 = player
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target2),
target2.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target2.DamageModel
),
Vector3.Zero
)
InfantryDamage(resprojectile2)(50, 10) mustEqual (40, 10)
@ -587,21 +661,25 @@ class ResolutionCalculationsTests extends Specification {
player2.Spawn()
"calculate no max damage for vehicles" in {
val target1 = Vehicle(GlobalDefinitions.fury) //!
val resprojectile1 = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile1 = DamageInteraction(
SourceEntry(target1),
target1.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target1.DamageModel
),
Vector3.Zero
)
MaxDamage(resprojectile1)(50, 10) mustEqual (0, 0)
val target2 = player2
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target2),
target2.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target2.DamageModel
),
Vector3.Zero
)
MaxDamage(resprojectile2)(50, 10) mustEqual (0, 40)
@ -623,21 +701,25 @@ class ResolutionCalculationsTests extends Specification {
"do not care if target is infantry for vehicle calculations" in {
val target1 = player
val resprojectile1 = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile1 = DamageInteraction(
SourceEntry(target1),
target1.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target1.DamageModel
),
Vector3.Zero
)
VehicleDamageAfterResist(resprojectile1)(50, 10) mustEqual 40
val target2 = Vehicle(GlobalDefinitions.fury) //!
val resprojectile2 = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile2 = DamageInteraction(
SourceEntry(target2),
target2.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
target2.DamageModel
),
Vector3.Zero
)
VehicleDamageAfterResist(resprojectile2)(50, 10) mustEqual 40
@ -690,14 +772,16 @@ class DamageModelTests extends Specification {
tplayer.Health mustEqual 100
tplayer.Armor mustEqual 50
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(tplayer),
tplayer.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
tplayer.DamageModel
),
Vector3.Zero
)
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
val func = resprojectile.calculate()
func(tplayer)
tplayer.Health mustEqual 65
tplayer.Armor mustEqual 35
@ -710,15 +794,16 @@ class DamageModelTests extends Specification {
tplayer.Health mustEqual 100
tplayer.Armor mustEqual 50
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(tplayer),
tplayer.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
tplayer.DamageModel
),
Vector3.Zero
)
val func: Any => ResolvedProjectile =
resprojectile.damage_model.Calculate(resprojectile, DamageType.Splash)
val func = resprojectile.calculate(DamageType.Splash)
func(tplayer)
tplayer.Health mustEqual 65
tplayer.Armor mustEqual 35
@ -731,14 +816,16 @@ class DamageModelTests extends Specification {
tplayer.Health mustEqual 100
tplayer.Armor mustEqual 50
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(tplayer),
tplayer.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
tplayer.DamageModel
),
Vector3.Zero
)
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
val func = resprojectile.calculate()
tplayer.Armor = 0
func(tplayer)
@ -750,14 +837,16 @@ class DamageModelTests extends Specification {
val vehicle = Vehicle(DamageModelTests.vehicle)
vehicle.Health mustEqual 650
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(vehicle),
vehicle.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
vehicle.DamageModel
),
Vector3.Zero
)
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
val func = resprojectile.calculate()
func(vehicle)
vehicle.Health mustEqual 518
@ -769,14 +858,16 @@ class DamageModelTests extends Specification {
vehicle.Health mustEqual 650
vehicle.Shields mustEqual 10
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(vehicle),
vehicle.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
vehicle.DamageModel
),
Vector3.Zero
)
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
val func = resprojectile.calculate()
func(vehicle)
vehicle.Health mustEqual 528
@ -789,14 +880,16 @@ class DamageModelTests extends Specification {
vehicle.Health mustEqual 650
vehicle.Shields mustEqual 10
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(vehicle),
vehicle.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
vehicle.DamageModel
),
Vector3.Zero
)
val func: Any => ResolvedProjectile = resprojectile.damage_model.Calculate(resprojectile)
val func = resprojectile.calculate()
func(vehicle)
vehicle.Health mustEqual 528
@ -810,15 +903,16 @@ class DamageModelTests extends Specification {
val vehicle = Vehicle(DamageModelTests.vehicle)
vehicle.Health mustEqual 650
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(vehicle),
vehicle.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
vehicle.DamageModel
),
Vector3.Zero
)
val func: Any => ResolvedProjectile =
resprojectile.damage_model.Calculate(resprojectile, DamageType.Splash)
val func = resprojectile.calculate(DamageType.Splash)
func(vehicle)
vehicle.Health mustEqual 518
@ -841,7 +935,7 @@ object DamageModelTests {
InitialVelocity = 75
Lifespan = 5f
ProjectileDefinition.CalculateDerivedFields(pdef = this)
Modifiers = DamageModifiers.RadialDegrade
Modifiers = RadialDegrade
}
final val vehicle = new VehicleDefinition(ObjectClass.fury) {

View file

@ -27,8 +27,12 @@ import net.psforever.services.support.SupportActor
import net.psforever.services.vehicle.support.TurretUpgrader
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import org.specs2.mutable.Specification
import scala.concurrent.duration._
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.vital.interaction.DamageInteraction
import net.psforever.objects.vital.base.DamageResolution
import net.psforever.objects.vital.projectile.ProjectileReason
class DamageableTest extends Specification {
val player1 = Player(Avatar(0, "TestCharacter1", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
@ -39,11 +43,13 @@ class DamageableTest extends Specification {
"Damageable" should {
"permit damage" in {
val target = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
)
@ -52,19 +58,13 @@ class DamageableTest extends Specification {
"ignore attempts at non-zero damage" in {
val target = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectileA,
weaponA.Definition,
weaponA.FireMode,
PlayerSource(player1),
0,
Vector3.Zero,
Vector3.Zero
),
val resolved = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
)
@ -77,21 +77,32 @@ class DamageableTest extends Specification {
new Building("test-building", 0, 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building) {
Faction = player1.Faction
}
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolvedFF = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
)
target.Definition.DamageableByFriendlyFire mustEqual false
target.Faction == player1.Faction mustEqual true
Damageable.CanDamage(target, projectileA.Damage0, resolved) mustEqual false
Damageable.CanDamage(target, projectileA.Damage0, resolvedFF) mustEqual false
target.Owner.Faction = PlanetSideEmpire.NC
val resolvedNonFF = DamageInteraction(
SourceEntry(target),
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
)
target.Faction != player1.Faction mustEqual true
Damageable.CanDamage(target, projectileA.Damage0, resolved) mustEqual true
Damageable.CanDamage(target, projectileA.Damage0, resolvedNonFF) mustEqual true
}
"ignore attempts at damaging a target that is not damageable" in {
@ -100,11 +111,13 @@ class DamageableTest extends Specification {
new Building("test-building", 0, 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building) {
Faction = PlanetSideEmpire.NC
}
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
)
@ -127,11 +140,13 @@ class DamageableTest extends Specification {
new Building("test-building", 0, 0, Zone.Nowhere, StructureType.Building, GlobalDefinitions.building) {
Faction = player1.Faction
}
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
)
@ -151,60 +166,74 @@ class DamageableTest extends Specification {
"permit jamming" in {
val target = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectileB, weaponB.Definition, weaponB.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileB, weaponB.Definition, weaponB.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
)
resolved.projectile.profile.JammerProjectile mustEqual true
resolved.cause.source.HasJammedEffectDuration mustEqual true
Damageable.CanJammer(target, resolved) mustEqual true
}
"ignore attempts at jamming if the projectile is does not cause the effect" in {
val target = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileA, weaponA.Definition, weaponA.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
) //decimator
resolved.projectile.profile.JammerProjectile mustEqual false
resolved.cause.source.HasJammedEffectDuration mustEqual false
Damageable.CanJammer(target, resolved) mustEqual false
}
"ignore attempts at jamming friendly targets" in {
val target = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
target.Faction = player1.Faction
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectileB, weaponB.Definition, weaponB.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileB, weaponB.Definition, weaponB.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
)
resolved.projectile.profile.JammerProjectile mustEqual true
resolved.projectile.owner.Faction == target.Faction mustEqual true
resolved.cause.source.HasJammedEffectDuration mustEqual true
resolved.adversarial match {
case Some(adversarial) => adversarial.attacker.Faction mustEqual adversarial.defender.Faction
case None => ko
}
Damageable.CanJammer(target, resolved) mustEqual false
}
"ignore attempts at jamming targets that are not jammable" in {
val target = new TrapDeployable(GlobalDefinitions.tank_traps)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectileB, weaponB.Definition, weaponB.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileB, weaponB.Definition, weaponB.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel
),
Vector3.Zero
)
resolved.projectile.profile.JammerProjectile mustEqual true
resolved.projectile.owner.Faction == target.Faction mustEqual false
resolved.cause.source.HasJammedEffectDuration mustEqual true
resolved.adversarial match {
case Some(adversarial) => adversarial.attacker.Faction mustNotEqual adversarial.defender.Faction
case None => ko
}
target.isInstanceOf[JammableUnit] mustEqual false
Damageable.CanJammer(target, resolved) mustEqual false
}
@ -215,16 +244,21 @@ class DamageableTest extends Specification {
player2.GUID = PlanetSideGUID(1)
val target = new SensorDeployable(GlobalDefinitions.motionalarmsensor)
target.Faction = player1.Faction
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectileB, weaponB.Definition, weaponB.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
SourceEntry(target),
target.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectileB, weaponB.Definition, weaponB.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
target.DamageModel,
),
Vector3.Zero
)
resolved.projectile.profile.JammerProjectile mustEqual true
resolved.projectile.owner.Faction == target.Faction mustEqual true
resolved.cause.source.HasJammedEffectDuration mustEqual true
resolved.adversarial match {
case Some(adversarial) => adversarial.attacker.Faction mustEqual adversarial.defender.Faction
case None => ko
}
target.isInstanceOf[JammableUnit] mustEqual true
target.HackedBy.nonEmpty mustEqual false
Damageable.CanJammer(target, resolved) mustEqual false
@ -270,22 +304,16 @@ class DamageableEntityDamageTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(gen),
gen.DamageModel,
Vector3(1, 0, 0)
ProjectileReason(
DamageResolution.Hit,
Projectile(projectile, weapon.Definition, weapon.FireMode, PlayerSource(player1), 0, Vector3(2, 0, 0), Vector3(-1, 0, 0)),
gen.DamageModel
),
Vector3(1,0,0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
"DamageableEntity" should {
@ -341,22 +369,24 @@ class DamageableEntityDestroyedTest extends ActorTest {
guid.register(player1, 3)
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(mech),
mech.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
mech.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -415,22 +445,24 @@ class DamageableEntityNotDestroyTwice extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(gen),
gen.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
gen.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -486,22 +518,24 @@ class DamageableAmenityTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(term),
term.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
term.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -579,22 +613,24 @@ class DamageableMountableDamageTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(mech),
mech.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
mech.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
mech.Seats(0).Occupant = player2 //seat the player
player2.VehicleSeated = Some(mech.GUID) //seat the player
expectNoMessage(200 milliseconds)
@ -674,22 +710,24 @@ class DamageableMountableDestroyTest extends ActorTest {
building.Actor = buildingProbe.ref
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(mech),
mech.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
mech.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
mech.Seats(0).Occupant = player2 //seat the player
player2.VehicleSeated = Some(mech.GUID) //seat the player
expectNoMessage(200 milliseconds)
@ -719,7 +757,7 @@ class DamageableMountableDestroyTest extends ActorTest {
)
assert(
msg3 match {
case Player.Die() => true
case Player.Die(_) => true
case _ => false
}
)
@ -764,23 +802,25 @@ class DamageableWeaponTurretDamageTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.suppressor)
val projectile = weapon.Projectile
val turretSource = SourceEntry(turret)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
val pSource = PlayerSource(player1)
val resolved = DamageInteraction(
SourceEntry(turret),
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
pSource,
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
turret.DamageModel
),
turretSource,
turret.DamageModel,
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -801,8 +841,8 @@ class DamageableWeaponTurretDamageTest extends ActorTest {
assert(
msg3 match {
case activity: Zone.HotSpot.Activity =>
activity.attacker == PlayerSource(player1) &&
activity.defender == turretSource &&
activity.attacker == pSource &&
activity.defender == SourceEntry(turret) &&
activity.location == Vector3(1, 0, 0)
case _ => false
}
@ -864,22 +904,24 @@ class DamageableWeaponTurretJammerTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.jammer_grenade)
val projectile = weapon.Projectile
val turretSource = SourceEntry(turret)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
turretSource,
turret.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
turret.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -966,41 +1008,46 @@ class DamageableWeaponTurretDestructionTest extends ActorTest {
val turretSource = SourceEntry(turret)
val weaponA = Tool(GlobalDefinitions.jammer_grenade)
val projectileA = weaponA.Projectile
val resolvedA = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectileA,
weaponA.Definition,
weaponA.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolvedA = DamageInteraction(
turretSource,
turret.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectileA,
weaponA.Definition,
weaponA.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
turret.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageToA = resolvedA.damage_model.Calculate(resolvedA)
val applyDamageToA = resolvedA.calculate()
val weaponB = Tool(GlobalDefinitions.phoenix) //decimator
val projectileB = weaponB.Projectile
val resolvedB = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectileB,
weaponB.Definition,
weaponB.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolvedB = DamageInteraction(
turretSource,
turret.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectileB,
weaponB.Definition,
weaponB.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
turret.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageToB = resolvedB.damage_model.Calculate(resolvedB)
val applyDamageToB = resolvedB.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -1037,7 +1084,7 @@ class DamageableWeaponTurretDestructionTest extends ActorTest {
)
assert(
msg3 match {
case Player.Die() => true
case Player.Die(_) => true
case _ => false
}
)
@ -1107,22 +1154,24 @@ class DamageableVehicleDamageTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.suppressor)
val projectile = weapon.Projectile
val vehicleSource = SourceEntry(atv)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
vehicleSource,
atv.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
atv.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -1152,7 +1201,7 @@ class DamageableVehicleDamageTest extends ActorTest {
msg3 match {
case activity: Zone.HotSpot.Activity =>
activity.attacker == PlayerSource(player1) &&
activity.defender == vehicleSource &&
activity.defender == VehicleSource(atv) &&
activity.location == Vector3(1, 0, 0)
case _ => false
}
@ -1234,23 +1283,25 @@ class DamageableVehicleDamageMountedTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val vehicleSource = SourceEntry(lodestar)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
val pSource = PlayerSource(player1)
val resolved = DamageInteraction(
SourceEntry(lodestar),
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
pSource,
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
lodestar.DamageModel
),
vehicleSource,
lodestar.DamageModel,
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -1281,8 +1332,8 @@ class DamageableVehicleDamageMountedTest extends ActorTest {
assert(
msg3 match {
case activity: Zone.HotSpot.Activity =>
activity.attacker == PlayerSource(player1) &&
activity.defender == vehicleSource &&
activity.attacker == pSource &&
activity.defender == SourceEntry(lodestar) &&
activity.location == Vector3(1, 0, 0)
case _ => false
}
@ -1379,22 +1430,24 @@ class DamageableVehicleJammeringMountedTest extends ActorTest {
val vehicleSource = SourceEntry(lodestar)
val weapon = Tool(GlobalDefinitions.jammer_grenade)
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
vehicleSource,
lodestar.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
lodestar.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -1469,22 +1522,24 @@ class DamageableVehicleDestroyTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.suppressor)
val projectile = weapon.Projectile
val vehicleSource = SourceEntry(atv)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
vehicleSource,
atv.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
atv.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -1513,7 +1568,7 @@ class DamageableVehicleDestroyTest extends ActorTest {
)
assert(
msg3 match {
case Player.Die() => true
case Player.Die(_) => true
case _ => false
}
)
@ -1531,18 +1586,6 @@ class DamageableVehicleDestroyTest extends ActorTest {
}
class DamageableVehicleDestroyMountedTest extends ActorTest {
val guid = new NumberPoolHub(new MaxNumberSource(15))
val zone = new Zone("test", new ZoneMap("test"), 0) {
override def SetupNumberPools() = {}
GUID(guid)
}
val activityProbe = TestProbe()
val avatarProbe = TestProbe()
val vehicleProbe = TestProbe()
zone.Activity = activityProbe.ref
zone.AvatarEvents = avatarProbe.ref
zone.VehicleEvents = vehicleProbe.ref
val atv = Vehicle(GlobalDefinitions.quadassault) //guid=1
atv.Actor = system.actorOf(Props(classOf[VehicleControl], atv), "atv-control")
atv.Position = Vector3(1, 0, 0)
@ -1568,6 +1611,20 @@ class DamageableVehicleDestroyMountedTest extends ActorTest {
val player3Probe = TestProbe()
player3.Actor = player3Probe.ref
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, player3)
}
val activityProbe = TestProbe()
val avatarProbe = TestProbe()
val vehicleProbe = TestProbe()
zone.Activity = activityProbe.ref
zone.AvatarEvents = avatarProbe.ref
zone.VehicleEvents = vehicleProbe.ref
guid.register(atv, 1)
guid.register(atvWeapon, 2)
guid.register(atvWeapon.AmmoSlot.Box, 3)
@ -1595,41 +1652,45 @@ class DamageableVehicleDestroyMountedTest extends ActorTest {
val vehicleSource = SourceEntry(lodestar)
val weaponA = Tool(GlobalDefinitions.jammer_grenade)
val projectileA = weaponA.Projectile
val resolvedA = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectileA,
weaponA.Definition,
weaponA.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolvedA = DamageInteraction(
vehicleSource,
lodestar.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectileA,
weaponA.Definition,
weaponA.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
lodestar.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageToA = resolvedA.damage_model.Calculate(resolvedA)
val applyDamageToA = resolvedA.calculate()
val weaponB = Tool(GlobalDefinitions.phoenix) //decimator
val projectileB = weaponB.Projectile
val resolvedB = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectileB,
weaponB.Definition,
weaponB.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolvedB = DamageInteraction(
vehicleSource,
lodestar.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectileB,
weaponB.Definition,
weaponB.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
lodestar.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageToB = resolvedB.damage_model.Calculate(resolvedB)
val applyDamageToB = resolvedB.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -1699,13 +1760,13 @@ class DamageableVehicleDestroyMountedTest extends ActorTest {
)
assert(
msg_player2 match {
case Player.Die() => true
case Player.Die(_) => true
case _ => false
}
)
assert(
msg_player3 match {
case Player.Die() => true
case Player.Die(_) => true
case _ => false
}
)

View file

@ -20,6 +20,9 @@ import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
import net.psforever.services.support.SupportActor
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.vital.base.DamageResolution
import net.psforever.objects.vital.interaction.DamageInteraction
import net.psforever.objects.vital.projectile.ProjectileReason
import scala.concurrent.duration._
@ -333,14 +336,16 @@ class ExplosiveDeployableJammerTest extends ActorTest {
val jMineSource = SourceEntry(j_mine)
val pSource = PlayerSource(player1)
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectile, weapon.Definition, weapon.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
jMineSource,
j_mine.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectile, weapon.Definition, weapon.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
j_mine.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageToJ = resolved.damage_model.Calculate(resolved)
val applyDamageToJ = resolved.calculate()
"ExplosiveDeployable" should {
"handle being jammered appropriately (no detonation)" in {
@ -428,17 +433,18 @@ class ExplosiveDeployableJammerExplodeTest extends ActorTest {
h_mine.Faction = PlanetSideEmpire.NC
h_mine.Actor = system.actorOf(Props(classOf[ExplosiveDeployableControl], h_mine), "h-mine-control")
val hMineSource = SourceEntry(h_mine)
val pSource = PlayerSource(player1)
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectile, weapon.Definition, weapon.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
hMineSource,
h_mine.DamageModel,
val resolved = DamageInteraction(
SourceEntry(h_mine),
ProjectileReason(
DamageResolution.Hit,
Projectile(projectile, weapon.Definition, weapon.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
h_mine.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageToH = resolved.damage_model.Calculate(resolved)
val applyDamageToH = resolved.calculate()
"ExplosiveDeployable" should {
"handle being jammered appropriately (detonation)" in {
@ -498,7 +504,7 @@ class ExplosiveDeployableJammerExplodeTest extends ActorTest {
)
assert(
msg_activity match {
case Zone.HotSpot.Activity(target, attacker, _) => (target eq hMineSource) && (attacker eq pSource)
case Zone.HotSpot.Conflict(target, attacker, _) => (target.Definition eq h_mine.Definition) && (attacker eq pSource)
case _ => false
}
)
@ -541,14 +547,16 @@ class ExplosiveDeployableDestructionTest extends ActorTest {
val hMineSource = SourceEntry(h_mine)
val pSource = PlayerSource(player1)
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectile, weapon.Definition, weapon.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
val resolved = DamageInteraction(
hMineSource,
h_mine.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectile, weapon.Definition, weapon.FireMode, pSource, 0, Vector3.Zero, Vector3.Zero),
h_mine.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
"ExplosiveDeployable" should {
"handle being destroyed" in {

View file

@ -14,6 +14,10 @@ import net.psforever.objects.serverobject.CommonMessages
import net.psforever.objects.serverobject.generator.{Generator, GeneratorControl, GeneratorDefinition}
import net.psforever.objects.serverobject.structures.{Building, StructureType}
import net.psforever.objects.vital.Vitality
import net.psforever.objects.vital.base.DamageResolution
import net.psforever.objects.vital.interaction.DamageInteraction
import net.psforever.objects.vital.projectile.ProjectileReason
import net.psforever.objects.vital.prop.DamageWithPosition
import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.{InventoryStateMessage, RepairMessage, TriggerEffectMessage}
import net.psforever.types._
@ -80,22 +84,24 @@ class GeneratorControlDamageTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(gen),
gen.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
gen.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -161,22 +167,24 @@ class GeneratorControlCriticalTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(gen),
gen.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
gen.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
val halfHealth = gen.Definition.MaxHealth / 2
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -245,22 +253,24 @@ class GeneratorControlDestroyedTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(gen),
gen.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
gen.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -328,25 +338,6 @@ class GeneratorControlDestroyedTest extends ActorTest {
}
class GeneratorControlKillsTest extends ActorTest {
/*
to perform this test, players need to be added to the SOI organization of the test base in proximity of the generator
under normal player scenario, this is an automatic process
extending from the act of players being in a zone
and players being within the SOI radius from the center of a facility on a periodic check
the test base being used has no established SOI region or automatic SOI check refresh,
but its SOI information can be loaded with the players manually
the players need something to catch the die message
*/
val guid = new NumberPoolHub(new MaxNumberSource(5))
val zone = new Zone("test", new ZoneMap("test"), 0) {
override def SetupNumberPools() = {}
GUID(guid)
}
val avatarProbe = TestProbe()
zone.AvatarEvents = avatarProbe.ref
val activityProbe = TestProbe()
zone.Activity = activityProbe.ref
val gen = Generator(GeneratorTest.generator_definition) //guid=2
gen.Position = Vector3(1, 0, 0)
gen.Actor = system.actorOf(Props(classOf[GeneratorControl], gen), "generator-control")
@ -359,16 +350,24 @@ class GeneratorControlKillsTest extends ActorTest {
player1.Actor = player1Probe.ref
val player2 =
Player(Avatar(0, "TestCharacter2", PlanetSideEmpire.TR, CharacterGender.Female, 1, CharacterVoice.Mute)) //guid=4
player2.Position = Vector3(15, 0, 0) //>14m from generator; lives
player2.Position = Vector3(25, 0, 0) //>14m from generator; lives
player2.Spawn()
val player2Probe = TestProbe()
player2.Actor = player2Probe.ref
val avatarProbe = TestProbe()
val activityProbe = TestProbe()
val guid = new NumberPoolHub(new MaxNumberSource(5))
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 building = Building("test-building", 1, 1, zone, StructureType.Facility) //guid=1
building.Position = Vector3(1, 0, 0)
building.Zone = zone
building.Amenities = gen
building.PlayersInSOI = List(player1, player2)
val buildingProbe = TestProbe()
building.Actor = buildingProbe.ref
@ -379,27 +378,29 @@ class GeneratorControlKillsTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(gen),
gen.DamageModel,
Vector3(1, 0, 0)
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(25, 0, 0),
Vector3(-1, 0, 0)
),
gen.DamageModel
),
Vector3(2, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
"GeneratorControl" should {
"kill players when the generator is destroyed" in {
"damages (kills) players when the generator is destroyed" in {
gen.Health = 1 //no matter what, the next shot destroys the generator
assert(gen.Health == 1)
assert(!gen.Destroyed)
@ -458,11 +459,11 @@ class GeneratorControlKillsTest extends ActorTest {
assert(gen.Destroyed)
assert(gen.Condition == PlanetSideGeneratorState.Destroyed)
val msg_player1 = player1Probe.receiveOne(100 milliseconds)
val msg_player1 = player1Probe.receiveOne(200 milliseconds)
player2Probe.expectNoMessage(200 milliseconds)
assert(
msg_player1 match {
case _ @Player.Die() => true
case _ @ Vitality.Damage(_) => true
case _ => false
}
)
@ -499,22 +500,24 @@ class GeneratorControlNotDestroyTwice extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(gen),
gen.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
gen.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -589,22 +592,24 @@ class GeneratorControlNotDamageIfExplodingTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(gen),
gen.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
gen.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
expectNoMessage(200 milliseconds)
//we're not testing that the math is correct
@ -686,22 +691,24 @@ class GeneratorControlNotRepairIfExplodingTest extends ActorTest {
val weapon = Tool(GlobalDefinitions.phoenix) //decimator
val projectile = weapon.Projectile
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
SourceEntry(gen),
gen.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
weapon.Definition,
weapon.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
gen.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
val tool = Tool(GlobalDefinitions.nano_dispenser) //4 & 5
guid.register(tool, 4)
@ -851,6 +858,10 @@ object GeneratorTest {
Repairable = true
RepairDistance = 13.5f
RepairIfDestroyed = true
explodes = true
innateDamage = new DamageWithPosition {
DamageRadius = 14
}
//note: no auto-repair
}
}

View file

@ -377,22 +377,24 @@ class PlayerControlDamageTest extends ActorTest {
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
val projectile = tool.Projectile
val playerSource = SourceEntry(player2)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(
projectile,
tool.Definition,
tool.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
val resolved = DamageInteraction(
playerSource,
player1.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(
projectile,
tool.Definition,
tool.FireMode,
PlayerSource(player1),
0,
Vector3(2, 0, 0),
Vector3(-1, 0, 0)
),
player1.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
guid.register(player1, 1)
guid.register(player2, 2)
guid.register(tool, 3)
@ -476,14 +478,16 @@ class PlayerControlDeathStandingTest extends ActorTest {
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
val projectile = tool.Projectile
val player1Source = SourceEntry(player1)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectile, tool.Definition, tool.FireMode, player1Source, 0, Vector3(2, 0, 0), Vector3(-1, 0, 0)),
val resolved = DamageInteraction(
SourceEntry(player2),
player2.DamageModel,
ProjectileReason(
DamageResolution.Hit,
Projectile(projectile, tool.Definition, tool.FireMode, player1Source, 0, Vector3(2, 0, 0), Vector3(-1, 0, 0)),
player2.DamageModel
),
Vector3(1, 0, 0)
)
val applyDamageTo = resolved.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
guid.register(player1, 1)
guid.register(player2, 2)
guid.register(tool, 3)
@ -605,14 +609,16 @@ class PlayerControlDeathSeatedTest extends ActorTest {
val tool = Tool(GlobalDefinitions.suppressor) //guid 3 & 4
val projectile = tool.Projectile
val player1Source = SourceEntry(player1)
val resolved = ResolvedProjectile(
ProjectileResolution.Hit,
Projectile(projectile, tool.Definition, tool.FireMode, player1Source, 0, Vector3(2, 0, 0), Vector3(-1, 0, 0)),
val resolved = DamageInteraction(
SourceEntry(player2),
player2.DamageModel,
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.damage_model.Calculate(resolved)
val applyDamageTo = resolved.calculate()
guid.register(player1, 1)
guid.register(player2, 2)
guid.register(tool, 3)

View file

@ -6,7 +6,9 @@ import net.psforever.objects.avatar.Avatar
import net.psforever.objects.ballistics._
import net.psforever.objects.definition.ProjectileDefinition
import net.psforever.objects.serverobject.mblocker.Locker
import net.psforever.objects.vital.DamageType
import net.psforever.objects.vital.base.{DamageResolution, DamageType}
import net.psforever.objects.vital.interaction.DamageInteraction
import net.psforever.objects.vital.projectile.ProjectileReason
import net.psforever.types.{PlanetSideGUID, _}
import org.specs2.mutable.Specification
@ -328,7 +330,7 @@ class ProjectileTest extends Specification {
}
}
"ResolvedProjectile" should {
"Projectile DamageInteraction" should { //TODO wrong place for this test?
val beamer_wep = Tool(GlobalDefinitions.beamer)
val p_source = PlayerSource(player)
val player2 = Player(Avatar(0, "TestTarget", PlanetSideEmpire.NC, CharacterGender.Female, 1, CharacterVoice.Mute))
@ -345,17 +347,20 @@ class ProjectileTest extends Specification {
val fury_dm = fury.DamageModel
"construct" in {
val obj = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val obj = DamageInteraction(
DamageResolution.Hit,
PlayerSource(player2),
fury_dm,
ProjectileReason(
DamageResolution.Hit,
projectile,
fury_dm
),
Vector3(1.2f, 3.4f, 5.6f)
)
obj.projectile mustEqual projectile
obj.cause.asInstanceOf[ProjectileReason].projectile mustEqual projectile
obj.target mustEqual p2_source
obj.damage_model mustEqual fury.DamageModel
obj.hit_pos mustEqual Vector3(1.2f, 3.4f, 5.6f)
obj.cause.asInstanceOf[ProjectileReason].damageModel mustEqual fury.DamageModel
obj.hitPos mustEqual Vector3(1.2f, 3.4f, 5.6f)
}
}
}

View file

@ -962,7 +962,7 @@ class VehicleControlShieldsNotChargingTooEarlyTest extends ActorTest {
// 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 = ResolvedProjectile(projectile, p_source, fury_dm, Vector3(1.2f, 3.4f, 5.6f))
// 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)

View file

@ -5,6 +5,9 @@ import net.psforever.objects.ballistics._
import net.psforever.objects._
import net.psforever.objects.avatar.Avatar
import net.psforever.objects.vital._
import net.psforever.objects.vital.base.DamageResolution
import net.psforever.objects.vital.interaction.DamageInteraction
import net.psforever.objects.vital.projectile.ProjectileReason
import net.psforever.types._
import org.specs2.mutable.Specification
@ -20,16 +23,19 @@ class VitalityTest extends Specification {
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
val pSource = PlayerSource(player)
val projectile = Projectile(proj, wep, wep_fmode, player, Vector3(2, 2, 0), Vector3.Zero)
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(player),
player.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
player.DamageModel
),
Vector3(50, 50, 0)
)
val result = resprojectile.calculate()(player)
player.History(resprojectile) //ResolvedProjectile, straight-up
player.History(DamageFromProjectile(resprojectile))
player.History(result) //DamageResult, straight-up
player.History(DamageFromProjectile(result))
player.History(HealFromKit(pSource, 10, GlobalDefinitions.medkit))
player.History(HealFromTerm(pSource, 10, 0, GlobalDefinitions.order_terminal))
player.History(HealFromImplant(pSource, 10, ImplantType.AdvancedRegen))
@ -68,15 +74,18 @@ class VitalityTest extends Specification {
val player = Player(Avatar(0, "TestCharacter", PlanetSideEmpire.TR, CharacterGender.Male, 0, CharacterVoice.Mute))
val pSource = PlayerSource(player)
val projectile = Projectile(proj, wep, wep_fmode, player, Vector3(2, 2, 0), Vector3.Zero)
val resprojectile = ResolvedProjectile(
ProjectileResolution.Hit,
projectile,
val resprojectile = DamageInteraction(
SourceEntry(player),
player.DamageModel,
ProjectileReason(
DamageResolution.Hit,
projectile,
player.DamageModel
),
Vector3(50, 50, 0)
)
val result = resprojectile.calculate()(player)
player.History(DamageFromProjectile(resprojectile))
player.History(DamageFromProjectile(result))
player.History(HealFromKit(pSource, 10, GlobalDefinitions.medkit))
player.History(HealFromTerm(pSource, 10, 0, GlobalDefinitions.order_terminal))
player.History(HealFromImplant(pSource, 10, ImplantType.AdvancedRegen))
@ -87,7 +96,10 @@ class VitalityTest extends Specification {
player.LastShot match {
case Some(resolved_projectile) =>
resolved_projectile.projectile mustEqual projectile
resolved_projectile.interaction.cause match {
case o: ProjectileReason => o.projectile mustEqual projectile
case _ => ko
}
case None =>
ko
}