diff --git a/common/src/main/scala/net/psforever/objects/DefaultCancellable.scala b/common/src/main/scala/net/psforever/objects/DefaultCancellable.scala
new file mode 100644
index 000000000..394ba9c9f
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/DefaultCancellable.scala
@@ -0,0 +1,18 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects
+
+/**
+ * Used to initialize the value of a re-usable `Cancellable` object.
+ * By convention, it always acts like it has been cancelled before and can be cancelled.
+ * Should be replaced with pertinent `Cancellable` logic through the initialization of an executor.
+ */
+object DefaultCancellable {
+ import akka.actor.Cancellable
+
+ protected class InternalCancellable extends Cancellable {
+ override def cancel : Boolean = true
+ override def isCancelled : Boolean = true
+ }
+
+ final val obj : Cancellable = new InternalCancellable
+}
diff --git a/common/src/main/scala/net/psforever/objects/ExoSuitDefinition.scala b/common/src/main/scala/net/psforever/objects/ExoSuitDefinition.scala
index 0ef2ba55f..4eea81599 100644
--- a/common/src/main/scala/net/psforever/objects/ExoSuitDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/ExoSuitDefinition.scala
@@ -65,7 +65,7 @@ class ExoSuitDefinition(private val suitType : ExoSuitType.Value) {
object ExoSuitDefinition {
final val Standard = ExoSuitDefinition(ExoSuitType.Standard)
Standard.MaxArmor = 50
- Standard.InventoryScale = new InventoryTile(9,6)
+ Standard.InventoryScale = InventoryTile.Tile96
Standard.InventoryOffset = 6
Standard.Holster(0, EquipmentSize.Pistol)
Standard.Holster(2, EquipmentSize.Rifle)
@@ -73,7 +73,7 @@ object ExoSuitDefinition {
final val Agile = ExoSuitDefinition(ExoSuitType.Agile)
Agile.MaxArmor = 100
- Agile.InventoryScale = new InventoryTile(9,9)
+ Agile.InventoryScale = InventoryTile.Tile99
Agile.InventoryOffset = 6
Agile.Holster(0, EquipmentSize.Pistol)
Agile.Holster(1, EquipmentSize.Pistol)
@@ -83,7 +83,7 @@ object ExoSuitDefinition {
final val Reinforced = ExoSuitDefinition(ExoSuitType.Reinforced)
Reinforced.permission = 1
Reinforced.MaxArmor = 200
- Reinforced.InventoryScale = new InventoryTile(12,9)
+ Reinforced.InventoryScale = InventoryTile.Tile1209
Reinforced.InventoryOffset = 6
Reinforced.Holster(0, EquipmentSize.Pistol)
Reinforced.Holster(1, EquipmentSize.Pistol)
@@ -94,7 +94,7 @@ object ExoSuitDefinition {
final val Infiltration = ExoSuitDefinition(ExoSuitType.Standard)
Infiltration.permission = 1
Infiltration.MaxArmor = 0
- Infiltration.InventoryScale = new InventoryTile(6,6)
+ Infiltration.InventoryScale = InventoryTile.Tile66
Infiltration.InventoryOffset = 6
Infiltration.Holster(0, EquipmentSize.Pistol)
Infiltration.Holster(4, EquipmentSize.Melee)
@@ -102,7 +102,7 @@ object ExoSuitDefinition {
final val MAX = ExoSuitDefinition(ExoSuitType.MAX)
MAX.permission = 1
MAX.MaxArmor = 650
- MAX.InventoryScale = new InventoryTile(16,12)
+ MAX.InventoryScale = InventoryTile.Tile1612
MAX.InventoryOffset = 6
MAX.Holster(0, EquipmentSize.Max)
MAX.Holster(4, EquipmentSize.Melee)
diff --git a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala
index dba9b469e..c8ac95d62 100644
--- a/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala
+++ b/common/src/main/scala/net/psforever/objects/GlobalDefinitions.scala
@@ -2,13 +2,14 @@
package net.psforever.objects
import net.psforever.objects.definition._
-import net.psforever.objects.definition.converter.{CommandDetonaterConverter, LockerContainerConverter, REKConverter}
+import net.psforever.objects.definition.converter._
import net.psforever.objects.serverobject.doors.DoorDefinition
import net.psforever.objects.equipment.CItem.DeployedItem
import net.psforever.objects.equipment._
import net.psforever.objects.inventory.InventoryTile
import net.psforever.objects.serverobject.locks.IFFLockDefinition
-import net.psforever.objects.serverobject.terminals.{CertTerminalDefinition, OrderTerminalDefinition}
+import net.psforever.objects.serverobject.terminals._
+import net.psforever.objects.vehicles.SeatArmorRestriction
import net.psforever.types.PlanetSideEmpire
object GlobalDefinitions {
@@ -163,6 +164,33 @@ object GlobalDefinitions {
}
}
+ def AIMAX(faction : PlanetSideEmpire.Value) : ToolDefinition = {
+ faction match {
+ case PlanetSideEmpire.TR => trhev_dualcycler
+ case PlanetSideEmpire.NC => nchev_scattercannon
+ case PlanetSideEmpire.VS => vshev_quasar
+ case PlanetSideEmpire.NEUTRAL => suppressor //there is no common pool MAX arms
+ }
+ }
+
+ def AVMAX(faction : PlanetSideEmpire.Value) : ToolDefinition = {
+ faction match {
+ case PlanetSideEmpire.TR => trhev_pounder
+ case PlanetSideEmpire.NC => nchev_falcon
+ case PlanetSideEmpire.VS => vshev_comet
+ case PlanetSideEmpire.NEUTRAL => suppressor //there is no common pool MAX arms
+ }
+ }
+
+ def AAMAX(faction : PlanetSideEmpire.Value) : ToolDefinition = {
+ faction match {
+ case PlanetSideEmpire.TR => trhev_burster
+ case PlanetSideEmpire.NC => nchev_sparrow
+ case PlanetSideEmpire.VS => vshev_starfire
+ case PlanetSideEmpire.NEUTRAL => suppressor //there is no common pool MAX arms
+ }
+ }
+
/**
* Using the definition for a piece of `Equipment` determine if it is a grenade-type weapon.
* Only the normal grenades count; the grenade packs are excluded.
@@ -196,17 +224,17 @@ object GlobalDefinitions {
/**
* Using the definition for a piece of `Equipment` determine with which faction it aligns if it is a weapon.
* Only checks `Tool` objects.
- * Useful for determining if some item has to be dropped during an activity like `InfantryLoadout` switching.
+ * Useful for determining if some item has to be dropped during an activity like `Loadout` switching.
* @param edef the `EquipmentDefinition` of the item
* @return the faction alignment, or `Neutral`
*/
def isFactionWeapon(edef : EquipmentDefinition) : PlanetSideEmpire.Value = {
edef match {
- case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` =>
+ case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` | `trhev_dualcycler` | `trhev_pounder` | `trhev_burster` =>
PlanetSideEmpire.TR
- case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` =>
+ case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` | `nchev_scattercannon` | `nchev_falcon` | `nchev_sparrow` =>
PlanetSideEmpire.NC
- case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` =>
+ case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` | `vshev_quasar` | `vshev_comet` | `vshev_starfire` =>
PlanetSideEmpire.VS
case _ =>
PlanetSideEmpire.NEUTRAL
@@ -221,11 +249,11 @@ object GlobalDefinitions {
*/
def isFactionEquipment(edef : EquipmentDefinition) : PlanetSideEmpire.Value = {
edef match {
- case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` | `striker_missile_ammo` =>
+ case `chainblade` | `repeater` | `anniversary_guna` | `cycler` | `mini_chaingun` | `striker` | `striker_missile_ammo` | `trhev_dualcycler` | `trhev_pounder` | `trhev_burster` =>
PlanetSideEmpire.TR
- case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` | `hunter_seeker_missile` =>
+ case `magcutter` | `isp` | `anniversary_gun` | `gauss` | `r_shotgun` | `hunterseeker` | `hunter_seeker_missile` | `nchev_scattercannon` | `nchev_falcon` | `nchev_sparrow` =>
PlanetSideEmpire.NC
- case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` | `energy_cell` | `lancer_cartridge` =>
+ case `forceblade` | `beamer` | `anniversary_gunb` | `pulsar` | `lasher` | `lancer` | `energy_cell` | `lancer_cartridge` | `vshev_quasar` | `vshev_comet` | `vshev_starfire` =>
PlanetSideEmpire.VS
case _ =>
PlanetSideEmpire.NEUTRAL
@@ -234,7 +262,7 @@ object GlobalDefinitions {
/**
* Using the definition for a piece of `Equipment` determine whether it is a "cavern weapon."
- * Useful for determining if some item has to be dropped during an activity like `InfantryLoadout` switching.
+ * Useful for determining if some item has to be dropped during an activity like `Loadout` switching.
* @param edef the `EquipmentDefinition` of the item
* @return `true`, if it is; otherwise, `false`
*/
@@ -457,6 +485,9 @@ object GlobalDefinitions {
bullet_35mm.Capacity = 100
bullet_35mm.Tile = InventoryTile.Tile44
+ val ancient_ammo_vehicle = AmmoBoxDefinition(Ammo.ancient_ammo_vehicle)
+//
+
val
aphelion_laser_ammo = AmmoBoxDefinition(Ammo.aphelion_laser_ammo)
aphelion_laser_ammo.Capacity = 165
@@ -487,6 +518,11 @@ object GlobalDefinitions {
skyguard_flak_cannon_ammo.Capacity = 200
skyguard_flak_cannon_ammo.Tile = InventoryTile.Tile44
+ val
+ firebird_missile = AmmoBoxDefinition(ObjectClass.firebird_missile)
+ firebird_missile.Capacity = 50
+ firebird_missile.Tile = InventoryTile.Tile44
+
val
flux_cannon_thresher_battery = AmmoBoxDefinition(Ammo.flux_cannon_thresher_battery)
flux_cannon_thresher_battery.Capacity = 150
@@ -630,7 +666,7 @@ object GlobalDefinitions {
val
chainblade = ToolDefinition(ObjectClass.chainblade)
chainblade.Size = EquipmentSize.Melee
- chainblade.AmmoTypes += Ammo.melee_ammo
+ chainblade.AmmoTypes += melee_ammo
chainblade.FireModes += new FireModeDefinition
chainblade.FireModes.head.AmmoTypeIndices += 0
chainblade.FireModes.head.AmmoSlotIndex = 0
@@ -643,7 +679,7 @@ object GlobalDefinitions {
val
magcutter = ToolDefinition(ObjectClass.magcutter)
magcutter.Size = EquipmentSize.Melee
- magcutter.AmmoTypes += Ammo.melee_ammo
+ magcutter.AmmoTypes += melee_ammo
magcutter.FireModes += new FireModeDefinition
magcutter.FireModes.head.AmmoTypeIndices += 0
magcutter.FireModes.head.AmmoSlotIndex = 0
@@ -656,7 +692,7 @@ object GlobalDefinitions {
val
forceblade = ToolDefinition(ObjectClass.forceblade)
forceblade.Size = EquipmentSize.Melee
- forceblade.AmmoTypes += Ammo.melee_ammo
+ forceblade.AmmoTypes += melee_ammo
forceblade.FireModes += new FireModeDefinition
forceblade.FireModes.head.AmmoTypeIndices += 0
forceblade.FireModes.head.AmmoSlotIndex = 0
@@ -671,7 +707,7 @@ object GlobalDefinitions {
val
katana = ToolDefinition(ObjectClass.katana)
katana.Size = EquipmentSize.Melee
- katana.AmmoTypes += Ammo.melee_ammo
+ katana.AmmoTypes += melee_ammo
katana.FireModes += new FireModeDefinition
katana.FireModes.head.AmmoTypeIndices += 0
katana.FireModes.head.AmmoSlotIndex = 0
@@ -686,7 +722,7 @@ object GlobalDefinitions {
val
frag_grenade = ToolDefinition(ObjectClass.frag_grenade)
frag_grenade.Size = EquipmentSize.Pistol
- frag_grenade.AmmoTypes += Ammo.frag_grenade_ammo
+ frag_grenade.AmmoTypes += frag_grenade_ammo
frag_grenade.FireModes += new FireModeDefinition
frag_grenade.FireModes.head.AmmoTypeIndices += 0
frag_grenade.FireModes.head.AmmoSlotIndex = 0
@@ -700,7 +736,7 @@ object GlobalDefinitions {
val
plasma_grenade = ToolDefinition(ObjectClass.plasma_grenade)
plasma_grenade.Size = EquipmentSize.Pistol
- plasma_grenade.AmmoTypes += Ammo.plasma_grenade_ammo
+ plasma_grenade.AmmoTypes += plasma_grenade_ammo
plasma_grenade.FireModes += new FireModeDefinition
plasma_grenade.FireModes.head.AmmoTypeIndices += 0
plasma_grenade.FireModes.head.AmmoSlotIndex = 0
@@ -714,7 +750,7 @@ object GlobalDefinitions {
val
jammer_grenade = ToolDefinition(ObjectClass.jammer_grenade)
jammer_grenade.Size = EquipmentSize.Pistol
- jammer_grenade.AmmoTypes += Ammo.jammer_grenade_ammo
+ jammer_grenade.AmmoTypes += jammer_grenade_ammo
jammer_grenade.FireModes += new FireModeDefinition
jammer_grenade.FireModes.head.AmmoTypeIndices += 0
jammer_grenade.FireModes.head.AmmoSlotIndex = 0
@@ -728,8 +764,8 @@ object GlobalDefinitions {
val
repeater = ToolDefinition(ObjectClass.repeater)
repeater.Size = EquipmentSize.Pistol
- repeater.AmmoTypes += Ammo.bullet_9mm
- repeater.AmmoTypes += Ammo.bullet_9mm_AP
+ repeater.AmmoTypes += bullet_9mm
+ repeater.AmmoTypes += bullet_9mm_AP
repeater.FireModes += new FireModeDefinition
repeater.FireModes.head.AmmoTypeIndices += 0
repeater.FireModes.head.AmmoTypeIndices += 1
@@ -740,8 +776,8 @@ object GlobalDefinitions {
val
isp = ToolDefinition(ObjectClass.isp) //mag-scatter
isp.Size = EquipmentSize.Pistol
- isp.AmmoTypes += Ammo.shotgun_shell
- isp.AmmoTypes += Ammo.shotgun_shell_AP
+ isp.AmmoTypes += shotgun_shell
+ isp.AmmoTypes += shotgun_shell_AP
isp.FireModes += new FireModeDefinition
isp.FireModes.head.AmmoTypeIndices += 0
isp.FireModes.head.AmmoTypeIndices += 1
@@ -752,7 +788,7 @@ object GlobalDefinitions {
val
beamer = ToolDefinition(ObjectClass.beamer)
beamer.Size = EquipmentSize.Pistol
- beamer.AmmoTypes += Ammo.energy_cell
+ beamer.AmmoTypes += energy_cell
beamer.FireModes += new FireModeDefinition
beamer.FireModes.head.AmmoTypeIndices += 0
beamer.FireModes.head.AmmoSlotIndex = 0
@@ -766,8 +802,8 @@ object GlobalDefinitions {
val
ilc9 = ToolDefinition(ObjectClass.ilc9) //amp
ilc9.Size = EquipmentSize.Pistol
- ilc9.AmmoTypes += Ammo.bullet_9mm
- ilc9.AmmoTypes += Ammo.bullet_9mm_AP
+ ilc9.AmmoTypes += bullet_9mm
+ ilc9.AmmoTypes += bullet_9mm_AP
ilc9.FireModes += new FireModeDefinition
ilc9.FireModes.head.AmmoTypeIndices += 0
ilc9.FireModes.head.AmmoTypeIndices += 1
@@ -778,8 +814,8 @@ object GlobalDefinitions {
val
suppressor = ToolDefinition(ObjectClass.suppressor)
suppressor.Size = EquipmentSize.Rifle
- suppressor.AmmoTypes += Ammo.bullet_9mm
- suppressor.AmmoTypes += Ammo.bullet_9mm_AP
+ suppressor.AmmoTypes += bullet_9mm
+ suppressor.AmmoTypes += bullet_9mm_AP
suppressor.FireModes += new FireModeDefinition
suppressor.FireModes.head.AmmoTypeIndices += 0
suppressor.FireModes.head.AmmoTypeIndices += 1
@@ -790,12 +826,12 @@ object GlobalDefinitions {
val
punisher = ToolDefinition(ObjectClass.punisher)
punisher.Size = EquipmentSize.Rifle
- punisher.AmmoTypes += Ammo.bullet_9mm
- punisher.AmmoTypes += Ammo.bullet_9mm_AP
- punisher.AmmoTypes += Ammo.rocket
- punisher.AmmoTypes += Ammo.frag_cartridge
- punisher.AmmoTypes += Ammo.jammer_cartridge
- punisher.AmmoTypes += Ammo.plasma_cartridge
+ punisher.AmmoTypes += bullet_9mm
+ punisher.AmmoTypes += bullet_9mm_AP
+ punisher.AmmoTypes += rocket
+ punisher.AmmoTypes += frag_cartridge
+ punisher.AmmoTypes += jammer_cartridge
+ punisher.AmmoTypes += plasma_cartridge
punisher.FireModes += new FireModeDefinition
punisher.FireModes.head.AmmoTypeIndices += 0
punisher.FireModes.head.AmmoTypeIndices += 1
@@ -813,8 +849,8 @@ object GlobalDefinitions {
val
flechette = ToolDefinition(ObjectClass.flechette) //sweeper
flechette.Size = EquipmentSize.Rifle
- flechette.AmmoTypes += Ammo.shotgun_shell
- flechette.AmmoTypes += Ammo.shotgun_shell_AP
+ flechette.AmmoTypes += shotgun_shell
+ flechette.AmmoTypes += shotgun_shell_AP
flechette.FireModes += new FireModeDefinition
flechette.FireModes.head.AmmoTypeIndices += 0
flechette.FireModes.head.AmmoTypeIndices += 1
@@ -825,8 +861,8 @@ object GlobalDefinitions {
val
cycler = ToolDefinition(ObjectClass.cycler)
cycler.Size = EquipmentSize.Rifle
- cycler.AmmoTypes += Ammo.bullet_9mm
- cycler.AmmoTypes += Ammo.bullet_9mm_AP
+ cycler.AmmoTypes += bullet_9mm
+ cycler.AmmoTypes += bullet_9mm_AP
cycler.FireModes += new FireModeDefinition
cycler.FireModes.head.AmmoTypeIndices += 0
cycler.FireModes.head.AmmoTypeIndices += 1
@@ -837,8 +873,8 @@ object GlobalDefinitions {
val
gauss = ToolDefinition(ObjectClass.gauss)
gauss.Size = EquipmentSize.Rifle
- gauss.AmmoTypes += Ammo.bullet_9mm
- gauss.AmmoTypes += Ammo.bullet_9mm_AP
+ gauss.AmmoTypes += bullet_9mm
+ gauss.AmmoTypes += bullet_9mm_AP
gauss.FireModes += new FireModeDefinition
gauss.FireModes.head.AmmoTypeIndices += 0
gauss.FireModes.head.AmmoTypeIndices += 1
@@ -849,7 +885,7 @@ object GlobalDefinitions {
val
pulsar = ToolDefinition(ObjectClass.pulsar)
pulsar.Size = EquipmentSize.Rifle
- pulsar.AmmoTypes += Ammo.energy_cell
+ pulsar.AmmoTypes += energy_cell
pulsar.FireModes += new FireModeDefinition
pulsar.FireModes.head.AmmoTypeIndices += 0
pulsar.FireModes.head.AmmoSlotIndex = 0
@@ -863,7 +899,7 @@ object GlobalDefinitions {
val
anniversary_guna = ToolDefinition(ObjectClass.anniversary_guna) //tr stinger
anniversary_guna.Size = EquipmentSize.Pistol
- anniversary_guna.AmmoTypes += Ammo.anniversary_ammo
+ anniversary_guna.AmmoTypes += anniversary_ammo
anniversary_guna.FireModes += new FireModeDefinition
anniversary_guna.FireModes.head.AmmoTypeIndices += 0
anniversary_guna.FireModes.head.AmmoSlotIndex = 0
@@ -878,7 +914,7 @@ object GlobalDefinitions {
val
anniversary_gun = ToolDefinition(ObjectClass.anniversary_gun) //nc spear
anniversary_gun.Size = EquipmentSize.Pistol
- anniversary_gun.AmmoTypes += Ammo.anniversary_ammo
+ anniversary_gun.AmmoTypes += anniversary_ammo
anniversary_gun.FireModes += new FireModeDefinition
anniversary_gun.FireModes.head.AmmoTypeIndices += 0
anniversary_gun.FireModes.head.AmmoSlotIndex = 0
@@ -893,7 +929,7 @@ object GlobalDefinitions {
val
anniversary_gunb = ToolDefinition(ObjectClass.anniversary_gunb) //vs eraser
anniversary_gunb.Size = EquipmentSize.Pistol
- anniversary_gunb.AmmoTypes += Ammo.anniversary_ammo
+ anniversary_gunb.AmmoTypes += anniversary_ammo
anniversary_gunb.FireModes += new FireModeDefinition
anniversary_gunb.FireModes.head.AmmoTypeIndices += 0
anniversary_gunb.FireModes.head.AmmoSlotIndex = 0
@@ -908,7 +944,7 @@ object GlobalDefinitions {
val
spiker = ToolDefinition(ObjectClass.spiker)
spiker.Size = EquipmentSize.Pistol
- spiker.AmmoTypes += Ammo.ancient_ammo_combo
+ spiker.AmmoTypes += ancient_ammo_combo
spiker.FireModes += new FireModeDefinition
spiker.FireModes.head.AmmoTypeIndices += 0
spiker.FireModes.head.AmmoSlotIndex = 0
@@ -918,8 +954,8 @@ object GlobalDefinitions {
val
mini_chaingun = ToolDefinition(ObjectClass.mini_chaingun)
mini_chaingun.Size = EquipmentSize.Rifle
- mini_chaingun.AmmoTypes += Ammo.bullet_9mm
- mini_chaingun.AmmoTypes += Ammo.bullet_9mm_AP
+ mini_chaingun.AmmoTypes += bullet_9mm
+ mini_chaingun.AmmoTypes += bullet_9mm_AP
mini_chaingun.FireModes += new FireModeDefinition
mini_chaingun.FireModes.head.AmmoTypeIndices += 0
mini_chaingun.FireModes.head.AmmoTypeIndices += 1
@@ -930,8 +966,8 @@ object GlobalDefinitions {
val
r_shotgun = ToolDefinition(ObjectClass.r_shotgun) //jackhammer
r_shotgun.Size = EquipmentSize.Rifle
- r_shotgun.AmmoTypes += Ammo.shotgun_shell
- r_shotgun.AmmoTypes += Ammo.shotgun_shell_AP
+ r_shotgun.AmmoTypes += shotgun_shell
+ r_shotgun.AmmoTypes += shotgun_shell_AP
r_shotgun.FireModes += new FireModeDefinition
r_shotgun.FireModes.head.AmmoTypeIndices += 0
r_shotgun.FireModes.head.AmmoTypeIndices += 1
@@ -948,7 +984,7 @@ object GlobalDefinitions {
val
lasher = ToolDefinition(ObjectClass.lasher)
lasher.Size = EquipmentSize.Rifle
- lasher.AmmoTypes += Ammo.energy_cell
+ lasher.AmmoTypes += energy_cell
lasher.FireModes += new FireModeDefinition
lasher.FireModes.head.AmmoTypeIndices += 0
lasher.FireModes.head.AmmoSlotIndex = 0
@@ -962,7 +998,7 @@ object GlobalDefinitions {
val
maelstrom = ToolDefinition(ObjectClass.maelstrom)
maelstrom.Size = EquipmentSize.Rifle
- maelstrom.AmmoTypes += Ammo.maelstrom_ammo
+ maelstrom.AmmoTypes += maelstrom_ammo
maelstrom.FireModes += new FireModeDefinition
maelstrom.FireModes.head.AmmoTypeIndices += 0
maelstrom.FireModes.head.AmmoSlotIndex = 0
@@ -980,7 +1016,7 @@ object GlobalDefinitions {
val
phoenix = ToolDefinition(ObjectClass.phoenix) //decimator
phoenix.Size = EquipmentSize.Rifle
- phoenix.AmmoTypes += Ammo.phoenix_missile
+ phoenix.AmmoTypes += phoenix_missile
phoenix.FireModes += new FireModeDefinition
phoenix.FireModes.head.AmmoTypeIndices += 0
phoenix.FireModes.head.AmmoSlotIndex = 0
@@ -994,7 +1030,7 @@ object GlobalDefinitions {
val
striker = ToolDefinition(ObjectClass.striker)
striker.Size = EquipmentSize.Rifle
- striker.AmmoTypes += Ammo.striker_missile_ammo
+ striker.AmmoTypes += striker_missile_ammo
striker.FireModes += new FireModeDefinition
striker.FireModes.head.AmmoTypeIndices += 0
striker.FireModes.head.AmmoSlotIndex = 0
@@ -1008,7 +1044,7 @@ object GlobalDefinitions {
val
hunterseeker = ToolDefinition(ObjectClass.hunterseeker) //phoenix
hunterseeker.Size = EquipmentSize.Rifle
- hunterseeker.AmmoTypes += Ammo.hunter_seeker_missile
+ hunterseeker.AmmoTypes += hunter_seeker_missile
hunterseeker.FireModes += new FireModeDefinition
hunterseeker.FireModes.head.AmmoTypeIndices += 0
hunterseeker.FireModes.head.AmmoSlotIndex = 0
@@ -1022,7 +1058,7 @@ object GlobalDefinitions {
val
lancer = ToolDefinition(ObjectClass.lancer)
lancer.Size = EquipmentSize.Rifle
- lancer.AmmoTypes += Ammo.lancer_cartridge
+ lancer.AmmoTypes += lancer_cartridge
lancer.FireModes += new FireModeDefinition
lancer.FireModes.head.AmmoTypeIndices += 0
lancer.FireModes.head.AmmoSlotIndex = 0
@@ -1032,8 +1068,8 @@ object GlobalDefinitions {
val
rocklet = ToolDefinition(ObjectClass.rocklet)
rocklet.Size = EquipmentSize.Rifle
- rocklet.AmmoTypes += Ammo.rocket
- rocklet.AmmoTypes += Ammo.frag_cartridge
+ rocklet.AmmoTypes += rocket
+ rocklet.AmmoTypes += frag_cartridge
rocklet.FireModes += new FireModeDefinition
rocklet.FireModes.head.AmmoTypeIndices += 0
rocklet.FireModes.head.AmmoTypeIndices += 1
@@ -1050,9 +1086,9 @@ object GlobalDefinitions {
val
thumper = ToolDefinition(ObjectClass.thumper)
thumper.Size = EquipmentSize.Rifle
- thumper.AmmoTypes += Ammo.frag_cartridge
- thumper.AmmoTypes += Ammo.plasma_cartridge
- thumper.AmmoTypes += Ammo.jammer_cartridge
+ thumper.AmmoTypes += frag_cartridge
+ thumper.AmmoTypes += plasma_cartridge
+ thumper.AmmoTypes += jammer_cartridge
thumper.FireModes += new FireModeDefinition
thumper.FireModes.head.AmmoTypeIndices += 0
thumper.FireModes.head.AmmoTypeIndices += 1
@@ -1070,7 +1106,7 @@ object GlobalDefinitions {
val
radiator = ToolDefinition(ObjectClass.radiator)
radiator.Size = EquipmentSize.Rifle
- radiator.AmmoTypes += Ammo.ancient_ammo_combo
+ radiator.AmmoTypes += ancient_ammo_combo
radiator.FireModes += new FireModeDefinition
radiator.FireModes.head.AmmoTypeIndices += 0
radiator.FireModes.head.AmmoSlotIndex = 0
@@ -1084,7 +1120,7 @@ object GlobalDefinitions {
val
heavy_sniper = ToolDefinition(ObjectClass.heavy_sniper) //hsr
heavy_sniper.Size = EquipmentSize.Rifle
- heavy_sniper.AmmoTypes += Ammo.bolt
+ heavy_sniper.AmmoTypes += bolt
heavy_sniper.FireModes += new FireModeDefinition
heavy_sniper.FireModes.head.AmmoTypeIndices += 0
heavy_sniper.FireModes.head.AmmoSlotIndex = 0
@@ -1094,7 +1130,7 @@ object GlobalDefinitions {
val
bolt_driver = ToolDefinition(ObjectClass.bolt_driver)
bolt_driver.Size = EquipmentSize.Rifle
- bolt_driver.AmmoTypes += Ammo.bolt
+ bolt_driver.AmmoTypes += bolt
bolt_driver.FireModes += new FireModeDefinition
bolt_driver.FireModes.head.AmmoTypeIndices += 0
bolt_driver.FireModes.head.AmmoSlotIndex = 0
@@ -1104,7 +1140,7 @@ object GlobalDefinitions {
val
oicw = ToolDefinition(ObjectClass.oicw) //scorpion
oicw.Size = EquipmentSize.Rifle
- oicw.AmmoTypes += Ammo.oicw_ammo
+ oicw.AmmoTypes += oicw_ammo
oicw.FireModes += new FireModeDefinition
oicw.FireModes.head.AmmoTypeIndices += 0
oicw.FireModes.head.AmmoSlotIndex = 0
@@ -1118,7 +1154,7 @@ object GlobalDefinitions {
val
flamethrower = ToolDefinition(ObjectClass.flamethrower)
flamethrower.Size = EquipmentSize.Rifle
- flamethrower.AmmoTypes += Ammo.flamethrower_ammo
+ flamethrower.AmmoTypes += flamethrower_ammo
flamethrower.FireModes += new FireModeDefinition
flamethrower.FireModes.head.AmmoTypeIndices += 0
flamethrower.FireModes.head.AmmoSlotIndex = 0
@@ -1131,10 +1167,37 @@ object GlobalDefinitions {
flamethrower.FireModes(1).Chamber = 50
flamethrower.Tile = InventoryTile.Tile63
+ val
+ trhev_dualcycler = ToolDefinition(ObjectClass.trhev_dualcycler)
+
+ val
+ trhev_pounder = ToolDefinition(ObjectClass.trhev_pounder)
+
+ val
+ trhev_burster = ToolDefinition(ObjectClass.trhev_burster)
+
+ val
+ nchev_scattercannon = ToolDefinition(ObjectClass.nchev_scattercannon)
+
+ val
+ nchev_falcon = ToolDefinition(ObjectClass.nchev_falcon)
+
+ val
+ nchev_sparrow = ToolDefinition(ObjectClass.nchev_sparrow)
+
+ val
+ vshev_quasar = ToolDefinition(ObjectClass.vshev_quasar)
+
+ val
+ vshev_comet = ToolDefinition(ObjectClass.vshev_comet)
+
+ val
+ vshev_starfire = ToolDefinition(ObjectClass.vshev_starfire)
+
val
medicalapplicator = ToolDefinition(ObjectClass.medicalapplicator)
medicalapplicator.Size = EquipmentSize.Pistol
- medicalapplicator.AmmoTypes += Ammo.health_canister
+ medicalapplicator.AmmoTypes += health_canister
medicalapplicator.FireModes += new FireModeDefinition
medicalapplicator.FireModes.head.AmmoTypeIndices += 0
medicalapplicator.FireModes.head.AmmoSlotIndex = 0
@@ -1148,8 +1211,8 @@ object GlobalDefinitions {
val
nano_dispenser = ToolDefinition(ObjectClass.nano_dispenser)
nano_dispenser.Size = EquipmentSize.Rifle
- nano_dispenser.AmmoTypes += Ammo.armor_canister
- nano_dispenser.AmmoTypes += Ammo.upgrade_canister
+ nano_dispenser.AmmoTypes += armor_canister
+ nano_dispenser.AmmoTypes += upgrade_canister
nano_dispenser.FireModes += new FireModeDefinition
nano_dispenser.FireModes.head.AmmoTypeIndices += 0
nano_dispenser.FireModes.head.AmmoTypeIndices += 1
@@ -1160,7 +1223,7 @@ object GlobalDefinitions {
val
bank = ToolDefinition(ObjectClass.bank)
bank.Size = EquipmentSize.Pistol
- bank.AmmoTypes += Ammo.armor_canister
+ bank.AmmoTypes += armor_canister
bank.FireModes += new FireModeDefinition
bank.FireModes.head.AmmoTypeIndices += 0
bank.FireModes.head.AmmoSlotIndex = 0
@@ -1179,7 +1242,7 @@ object GlobalDefinitions {
val
trek = ToolDefinition(ObjectClass.trek)
trek.Size = EquipmentSize.Pistol
- trek.AmmoTypes += Ammo.trek_ammo
+ trek.AmmoTypes += trek_ammo
trek.FireModes += new FireModeDefinition
trek.FireModes.head.AmmoTypeIndices += 0
trek.FireModes.head.AmmoSlotIndex = 0
@@ -1222,7 +1285,7 @@ object GlobalDefinitions {
val
fury_weapon_systema = ToolDefinition(ObjectClass.fury_weapon_systema)
fury_weapon_systema.Size = EquipmentSize.VehicleWeapon
- fury_weapon_systema.AmmoTypes += Ammo.hellfire_ammo
+ fury_weapon_systema.AmmoTypes += hellfire_ammo
fury_weapon_systema.FireModes += new FireModeDefinition
fury_weapon_systema.FireModes.head.AmmoTypeIndices += 0
fury_weapon_systema.FireModes.head.AmmoSlotIndex = 0
@@ -1231,30 +1294,486 @@ object GlobalDefinitions {
val
quadassault_weapon_system = ToolDefinition(ObjectClass.quadassault_weapon_system)
quadassault_weapon_system.Size = EquipmentSize.VehicleWeapon
- quadassault_weapon_system.AmmoTypes += Ammo.bullet_12mm
+ quadassault_weapon_system.AmmoTypes += bullet_12mm
quadassault_weapon_system.FireModes += new FireModeDefinition
quadassault_weapon_system.FireModes.head.AmmoTypeIndices += 0
quadassault_weapon_system.FireModes.head.AmmoSlotIndex = 0
- quadassault_weapon_system.FireModes.head.Magazine = 100
+ quadassault_weapon_system.FireModes.head.Magazine = 150
+
+ val
+ scythe = ToolDefinition(ObjectClass.scythe) //TODO resolve ammo slot/pool discrepancy
+ scythe.Size = EquipmentSize.VehicleWeapon
+ scythe.AmmoTypes += ancient_ammo_vehicle
+ scythe.AmmoTypes += ancient_ammo_vehicle
+ scythe.FireModes += new FireModeDefinition
+ scythe.FireModes.head.AmmoTypeIndices += 0
+ scythe.FireModes.head.AmmoSlotIndex = 0
+ scythe.FireModes.head.Magazine = 250
+ scythe.FireModes += new FireModeDefinition
+ scythe.FireModes(1).AmmoTypeIndices += 0
+ scythe.FireModes(1).AmmoSlotIndex = 1 //note: the scythe has two magazines using a single pool; however, it can not ammo-switch or mode-switch
+ scythe.FireModes(1).Magazine = 250
val
chaingun_p = ToolDefinition(ObjectClass.chaingun_p)
chaingun_p.Size = EquipmentSize.VehicleWeapon
- chaingun_p.AmmoTypes += Ammo.bullet_12mm
+ chaingun_p.AmmoTypes += bullet_12mm
chaingun_p.FireModes += new FireModeDefinition
chaingun_p.FireModes.head.AmmoTypeIndices += 0
chaingun_p.FireModes.head.AmmoSlotIndex = 0
chaingun_p.FireModes.head.Magazine = 150
+ val
+ skyguard_weapon_system = ToolDefinition(ObjectClass.skyguard_weapon_system)
+ skyguard_weapon_system.Size = EquipmentSize.VehicleWeapon
+ skyguard_weapon_system.AmmoTypes += skyguard_flak_cannon_ammo
+ skyguard_weapon_system.AmmoTypes += bullet_12mm
+ skyguard_weapon_system.FireModes += new FireModeDefinition
+ skyguard_weapon_system.FireModes.head.AmmoTypeIndices += 0
+ skyguard_weapon_system.FireModes.head.AmmoSlotIndex = 0
+ skyguard_weapon_system.FireModes.head.Magazine = 40
+ skyguard_weapon_system.FireModes += new FireModeDefinition
+ skyguard_weapon_system.FireModes(1).AmmoTypeIndices += 1
+ skyguard_weapon_system.FireModes(1).AmmoSlotIndex = 1
+ skyguard_weapon_system.FireModes(1).Magazine = 1 //TODO check
+
+ val
+ grenade_launcher_marauder = ToolDefinition(ObjectClass.grenade_launcher_marauder)
+ grenade_launcher_marauder.Size = EquipmentSize.VehicleWeapon
+ grenade_launcher_marauder.AmmoTypes += heavy_grenade_mortar
+ grenade_launcher_marauder.FireModes += new FireModeDefinition
+ grenade_launcher_marauder.FireModes.head.AmmoTypeIndices += 0
+ grenade_launcher_marauder.FireModes.head.AmmoSlotIndex = 0
+ grenade_launcher_marauder.FireModes.head.Magazine = 50
+
+ val
+ advanced_missile_launcher_t = ToolDefinition(ObjectClass.advanced_missile_launcher_t)
+ advanced_missile_launcher_t.Size = EquipmentSize.VehicleWeapon
+ advanced_missile_launcher_t.AmmoTypes += firebird_missile
+ advanced_missile_launcher_t.FireModes += new FireModeDefinition
+ advanced_missile_launcher_t.FireModes.head.AmmoTypeIndices += 0
+ advanced_missile_launcher_t.FireModes.head.AmmoSlotIndex = 0
+ advanced_missile_launcher_t.FireModes.head.Magazine = 40
+
+ val
+ flux_cannon_thresher = ToolDefinition(ObjectClass.flux_cannon_thresher)
+ flux_cannon_thresher.Size = EquipmentSize.VehicleWeapon
+ flux_cannon_thresher.AmmoTypes += flux_cannon_thresher_battery
+ flux_cannon_thresher.FireModes += new FireModeDefinition
+ flux_cannon_thresher.FireModes.head.AmmoTypeIndices += 0
+ flux_cannon_thresher.FireModes.head.AmmoSlotIndex = 0
+ flux_cannon_thresher.FireModes.head.Magazine = 100
+
+ val
+ mediumtransport_weapon_systemA = ToolDefinition(ObjectClass.mediumtransport_weapon_systemA)
+ mediumtransport_weapon_systemA.Size = EquipmentSize.VehicleWeapon
+ mediumtransport_weapon_systemA.AmmoTypes += bullet_20mm
+ mediumtransport_weapon_systemA.FireModes += new FireModeDefinition
+ mediumtransport_weapon_systemA.FireModes.head.AmmoTypeIndices += 0
+ mediumtransport_weapon_systemA.FireModes.head.AmmoSlotIndex = 0
+ mediumtransport_weapon_systemA.FireModes.head.Magazine = 150
+
+ val
+ mediumtransport_weapon_systemB = ToolDefinition(ObjectClass.mediumtransport_weapon_systemB)
+ mediumtransport_weapon_systemB.Size = EquipmentSize.VehicleWeapon
+ mediumtransport_weapon_systemB.AmmoTypes += bullet_20mm
+ mediumtransport_weapon_systemB.FireModes += new FireModeDefinition
+ mediumtransport_weapon_systemB.FireModes.head.AmmoTypeIndices += 0
+ mediumtransport_weapon_systemB.FireModes.head.AmmoSlotIndex = 0
+ mediumtransport_weapon_systemB.FireModes.head.Magazine = 150
+
+ val
+ battlewagon_weapon_systema = ToolDefinition(ObjectClass.battlewagon_weapon_systema)
+ battlewagon_weapon_systema.Size = EquipmentSize.VehicleWeapon
+ battlewagon_weapon_systema.AmmoTypes += bullet_15mm
+ battlewagon_weapon_systema.FireModes += new FireModeDefinition
+ battlewagon_weapon_systema.FireModes.head.AmmoTypeIndices += 0
+ battlewagon_weapon_systema.FireModes.head.AmmoSlotIndex = 0
+ battlewagon_weapon_systema.FireModes.head.Magazine = 235
+
+ val
+ battlewagon_weapon_systemb = ToolDefinition(ObjectClass.battlewagon_weapon_systemb)
+ battlewagon_weapon_systemb.Size = EquipmentSize.VehicleWeapon
+ battlewagon_weapon_systemb.AmmoTypes += bullet_15mm
+ battlewagon_weapon_systemb.FireModes += new FireModeDefinition
+ battlewagon_weapon_systemb.FireModes.head.AmmoTypeIndices += 0
+ battlewagon_weapon_systemb.FireModes.head.AmmoSlotIndex = 0
+ battlewagon_weapon_systemb.FireModes.head.Magazine = 235
+
+ val
+ battlewagon_weapon_systemc = ToolDefinition(ObjectClass.battlewagon_weapon_systemc)
+ battlewagon_weapon_systemc.Size = EquipmentSize.VehicleWeapon
+ battlewagon_weapon_systemc.AmmoTypes += bullet_15mm
+ battlewagon_weapon_systemc.FireModes += new FireModeDefinition
+ battlewagon_weapon_systemc.FireModes.head.AmmoTypeIndices += 0
+ battlewagon_weapon_systemc.FireModes.head.AmmoSlotIndex = 0
+ battlewagon_weapon_systemc.FireModes.head.Magazine = 235
+
+ val
+ battlewagon_weapon_systemd = ToolDefinition(ObjectClass.battlewagon_weapon_systemd)
+ battlewagon_weapon_systemd.Size = EquipmentSize.VehicleWeapon
+ battlewagon_weapon_systemd.AmmoTypes += bullet_15mm
+ battlewagon_weapon_systemd.FireModes += new FireModeDefinition
+ battlewagon_weapon_systemd.FireModes.head.AmmoTypeIndices += 0
+ battlewagon_weapon_systemd.FireModes.head.AmmoSlotIndex = 0
+ battlewagon_weapon_systemd.FireModes.head.Magazine = 235
+
+ val
+ thunderer_weapon_systema = ToolDefinition(ObjectClass.thunderer_weapon_systema)
+ thunderer_weapon_systema.Size = EquipmentSize.VehicleWeapon
+ thunderer_weapon_systema.AmmoTypes += gauss_cannon_ammo
+ thunderer_weapon_systema.FireModes += new FireModeDefinition
+ thunderer_weapon_systema.FireModes.head.AmmoTypeIndices += 0
+ thunderer_weapon_systema.FireModes.head.AmmoSlotIndex = 0
+ thunderer_weapon_systema.FireModes.head.Magazine = 15
+
+ val
+ thunderer_weapon_systemb = ToolDefinition(ObjectClass.thunderer_weapon_systemb)
+ thunderer_weapon_systemb.Size = EquipmentSize.VehicleWeapon
+ thunderer_weapon_systemb.AmmoTypes += gauss_cannon_ammo
+ thunderer_weapon_systemb.FireModes += new FireModeDefinition
+ thunderer_weapon_systemb.FireModes.head.AmmoTypeIndices += 0
+ thunderer_weapon_systemb.FireModes.head.AmmoSlotIndex = 0
+ thunderer_weapon_systemb.FireModes.head.Magazine = 15
+
+ val
+ aurora_weapon_systema = ToolDefinition(ObjectClass.aurora_weapon_systema)
+ aurora_weapon_systema.Size = EquipmentSize.VehicleWeapon
+ aurora_weapon_systema.AmmoTypes += fluxpod_ammo
+ aurora_weapon_systema.FireModes += new FireModeDefinition
+ aurora_weapon_systema.FireModes.head.AmmoTypeIndices += 0
+ aurora_weapon_systema.FireModes.head.AmmoSlotIndex = 0
+ aurora_weapon_systema.FireModes.head.Magazine = 12
+ aurora_weapon_systema.FireModes += new FireModeDefinition
+ aurora_weapon_systema.FireModes(1).AmmoTypeIndices += 0
+ aurora_weapon_systema.FireModes(1).AmmoSlotIndex = 1
+ aurora_weapon_systema.FireModes(1).Magazine = 12
+
+ val
+ aurora_weapon_systemb = ToolDefinition(ObjectClass.aurora_weapon_systemb)
+ aurora_weapon_systemb.Size = EquipmentSize.VehicleWeapon
+ aurora_weapon_systemb.AmmoTypes += fluxpod_ammo
+ aurora_weapon_systemb.FireModes += new FireModeDefinition
+ aurora_weapon_systemb.FireModes.head.AmmoTypeIndices += 0
+ aurora_weapon_systemb.FireModes.head.AmmoSlotIndex = 0
+ aurora_weapon_systemb.FireModes.head.Magazine = 12
+ aurora_weapon_systemb.FireModes += new FireModeDefinition
+ aurora_weapon_systemb.FireModes(1).AmmoTypeIndices += 0
+ aurora_weapon_systemb.FireModes(1).AmmoSlotIndex = 1
+ aurora_weapon_systemb.FireModes(1).Magazine = 12
+
+ val
+ apc_weapon_systema = ToolDefinition(ObjectClass.apc_weapon_systema)
+ apc_weapon_systema.Size = EquipmentSize.VehicleWeapon
+ apc_weapon_systema.AmmoTypes += bullet_75mm
+ apc_weapon_systema.FireModes += new FireModeDefinition
+ apc_weapon_systema.FireModes.head.AmmoTypeIndices += 0
+ apc_weapon_systema.FireModes.head.AmmoSlotIndex = 0
+ apc_weapon_systema.FireModes.head.Magazine = 50
+
+ val
+ apc_weapon_systemb = ToolDefinition(ObjectClass.apc_weapon_systemb)
+ apc_weapon_systemb.Size = EquipmentSize.VehicleWeapon
+ apc_weapon_systemb.AmmoTypes += bullet_75mm
+ apc_weapon_systemb.FireModes += new FireModeDefinition
+ apc_weapon_systemb.FireModes.head.AmmoTypeIndices += 0
+ apc_weapon_systemb.FireModes.head.AmmoSlotIndex = 0
+ apc_weapon_systemb.FireModes.head.Magazine = 50
+
+ val
+ apc_ballgun_r = ToolDefinition(ObjectClass.apc_ballgun_r)
+ apc_ballgun_r.Size = EquipmentSize.VehicleWeapon
+ apc_ballgun_r.AmmoTypes += bullet_12mm
+ apc_ballgun_r.FireModes += new FireModeDefinition
+ apc_ballgun_r.FireModes.head.AmmoTypeIndices += 0
+ apc_ballgun_r.FireModes.head.AmmoSlotIndex = 0
+ apc_ballgun_r.FireModes.head.Magazine = 150
+
+ val
+ apc_ballgun_l = ToolDefinition(ObjectClass.apc_ballgun_l)
+ apc_ballgun_l.Size = EquipmentSize.VehicleWeapon
+ apc_ballgun_l.AmmoTypes += bullet_12mm
+ apc_ballgun_l.FireModes += new FireModeDefinition
+ apc_ballgun_l.FireModes.head.AmmoTypeIndices += 0
+ apc_ballgun_l.FireModes.head.AmmoSlotIndex = 0
+ apc_ballgun_l.FireModes.head.Magazine = 150
+
+ val
+ apc_weapon_systemc_tr = ToolDefinition(ObjectClass.apc_weapon_systemc_tr)
+ apc_weapon_systemc_tr.Size = EquipmentSize.VehicleWeapon
+ apc_weapon_systemc_tr.AmmoTypes += bullet_15mm
+ apc_weapon_systemc_tr.FireModes += new FireModeDefinition
+ apc_weapon_systemc_tr.FireModes.head.AmmoTypeIndices += 0
+ apc_weapon_systemc_tr.FireModes.head.AmmoSlotIndex = 0
+ apc_weapon_systemc_tr.FireModes.head.Magazine = 150
+
+ val
+ apc_weapon_systemd_tr = ToolDefinition(ObjectClass.apc_weapon_systemd_tr)
+ apc_weapon_systemd_tr.Size = EquipmentSize.VehicleWeapon
+ apc_weapon_systemd_tr.AmmoTypes += bullet_15mm
+ apc_weapon_systemd_tr.FireModes += new FireModeDefinition
+ apc_weapon_systemd_tr.FireModes.head.AmmoTypeIndices += 0
+ apc_weapon_systemd_tr.FireModes.head.AmmoSlotIndex = 0
+ apc_weapon_systemd_tr.FireModes.head.Magazine = 150
+
+ val
+ apc_weapon_systemc_nc = ToolDefinition(ObjectClass.apc_weapon_systemc_nc)
+ apc_weapon_systemc_nc.Size = EquipmentSize.VehicleWeapon
+ apc_weapon_systemc_nc.AmmoTypes += bullet_20mm
+ apc_weapon_systemc_nc.FireModes += new FireModeDefinition
+ apc_weapon_systemc_nc.FireModes.head.AmmoTypeIndices += 0
+ apc_weapon_systemc_nc.FireModes.head.AmmoSlotIndex = 0
+ apc_weapon_systemc_nc.FireModes.head.Magazine = 150
+
+ val
+ apc_weapon_systemd_nc = ToolDefinition(ObjectClass.apc_weapon_systemd_nc)
+ apc_weapon_systemd_nc.Size = EquipmentSize.VehicleWeapon
+ apc_weapon_systemd_nc.AmmoTypes += bullet_20mm
+ apc_weapon_systemd_nc.FireModes += new FireModeDefinition
+ apc_weapon_systemd_nc.FireModes.head.AmmoTypeIndices += 0
+ apc_weapon_systemd_nc.FireModes.head.AmmoSlotIndex = 0
+ apc_weapon_systemd_nc.FireModes.head.Magazine = 150
+
+ val
+ apc_weapon_systemc_vs = ToolDefinition(ObjectClass.apc_weapon_systemc_vs)
+ apc_weapon_systemc_vs.Size = EquipmentSize.VehicleWeapon
+ apc_weapon_systemc_vs.AmmoTypes += flux_cannon_thresher_battery
+ apc_weapon_systemc_vs.FireModes += new FireModeDefinition
+ apc_weapon_systemc_vs.FireModes.head.AmmoTypeIndices += 0
+ apc_weapon_systemc_vs.FireModes.head.AmmoSlotIndex = 0
+ apc_weapon_systemc_vs.FireModes.head.Magazine = 100
+
+ val
+ apc_weapon_systemd_vs = ToolDefinition(ObjectClass.apc_weapon_systemd_vs)
+ apc_weapon_systemd_vs.Size = EquipmentSize.VehicleWeapon
+ apc_weapon_systemd_vs.AmmoTypes += flux_cannon_thresher_battery
+ apc_weapon_systemd_vs.FireModes += new FireModeDefinition
+ apc_weapon_systemd_vs.FireModes.head.AmmoTypeIndices += 0
+ apc_weapon_systemd_vs.FireModes.head.AmmoSlotIndex = 0
+ apc_weapon_systemd_vs.FireModes.head.Magazine = 100
+
+ val
+ lightning_weapon_system = ToolDefinition(ObjectClass.lightning_weapon_system)
+ lightning_weapon_system.Size = EquipmentSize.VehicleWeapon
+ lightning_weapon_system.AmmoTypes += bullet_75mm
+ lightning_weapon_system.AmmoTypes += bullet_25mm
+ lightning_weapon_system.FireModes += new FireModeDefinition
+ lightning_weapon_system.FireModes.head.AmmoTypeIndices += 0
+ lightning_weapon_system.FireModes.head.AmmoSlotIndex = 0
+ lightning_weapon_system.FireModes.head.Magazine = 20
+ lightning_weapon_system.FireModes += new FireModeDefinition
+ lightning_weapon_system.FireModes(1).AmmoTypeIndices += 1
+ lightning_weapon_system.FireModes(1).AmmoSlotIndex = 1
+ lightning_weapon_system.FireModes(1).Magazine = 1 //TODO check
+
+ val
+ prowler_weapon_systemA = ToolDefinition(ObjectClass.prowler_weapon_systemA)
+ prowler_weapon_systemA.Size = EquipmentSize.VehicleWeapon
+ prowler_weapon_systemA.AmmoTypes += bullet_105mm
+ prowler_weapon_systemA.FireModes += new FireModeDefinition
+ prowler_weapon_systemA.FireModes.head.AmmoTypeIndices += 0
+ prowler_weapon_systemA.FireModes.head.AmmoSlotIndex = 0
+ prowler_weapon_systemA.FireModes.head.Magazine = 20
+
+ val
+ prowler_weapon_systemB = ToolDefinition(ObjectClass.prowler_weapon_systemB)
+ prowler_weapon_systemB.Size = EquipmentSize.VehicleWeapon
+ prowler_weapon_systemB.AmmoTypes += bullet_15mm
+ prowler_weapon_systemB.FireModes += new FireModeDefinition
+ prowler_weapon_systemB.FireModes.head.AmmoTypeIndices += 0
+ prowler_weapon_systemB.FireModes.head.AmmoSlotIndex = 0
+ prowler_weapon_systemB.FireModes.head.Magazine = 235
+
+ val
+ vanguard_weapon_system = ToolDefinition(ObjectClass.vanguard_weapon_system)
+ vanguard_weapon_system.Size = EquipmentSize.VehicleWeapon
+ vanguard_weapon_system.AmmoTypes += bullet_150mm
+ vanguard_weapon_system.AmmoTypes += bullet_20mm
+ vanguard_weapon_system.FireModes += new FireModeDefinition
+ vanguard_weapon_system.FireModes.head.AmmoTypeIndices += 0
+ vanguard_weapon_system.FireModes.head.AmmoSlotIndex = 0
+ vanguard_weapon_system.FireModes.head.Magazine = 10
+ vanguard_weapon_system.FireModes += new FireModeDefinition
+ vanguard_weapon_system.FireModes(1).AmmoTypeIndices += 1
+ vanguard_weapon_system.FireModes(1).AmmoSlotIndex = 1
+ vanguard_weapon_system.FireModes(1).Magazine = 1 //TODO check
+
+ val
+ particle_beam_magrider = ToolDefinition(ObjectClass.particle_beam_magrider)
+ particle_beam_magrider.Size = EquipmentSize.VehicleWeapon
+ particle_beam_magrider.AmmoTypes += pulse_battery
+ particle_beam_magrider.FireModes += new FireModeDefinition
+ particle_beam_magrider.FireModes.head.AmmoTypeIndices += 0
+ particle_beam_magrider.FireModes.head.AmmoSlotIndex = 0
+ particle_beam_magrider.FireModes.head.Magazine = 150
+
+ val
+ heavy_rail_beam_magrider = ToolDefinition(ObjectClass.heavy_rail_beam_magrider)
+ heavy_rail_beam_magrider.Size = EquipmentSize.VehicleWeapon
+ heavy_rail_beam_magrider.AmmoTypes += heavy_rail_beam_battery
+ heavy_rail_beam_magrider.FireModes += new FireModeDefinition
+ heavy_rail_beam_magrider.FireModes.head.AmmoTypeIndices += 0
+ heavy_rail_beam_magrider.FireModes.head.AmmoSlotIndex = 0
+ heavy_rail_beam_magrider.FireModes.head.Magazine = 25
+
+ val
+ flail_weapon = ToolDefinition(ObjectClass.flail_weapon)
+ flail_weapon.Size = EquipmentSize.VehicleWeapon
+ flail_weapon.AmmoTypes += ancient_ammo_vehicle
+ flail_weapon.FireModes += new FireModeDefinition
+ flail_weapon.FireModes.head.AmmoTypeIndices += 0
+ flail_weapon.FireModes.head.AmmoSlotIndex = 0
+ flail_weapon.FireModes.head.Magazine = 100
+
+ val
+ rotarychaingun_mosquito = ToolDefinition(ObjectClass.rotarychaingun_mosquito)
+ rotarychaingun_mosquito.Size = EquipmentSize.VehicleWeapon
+ rotarychaingun_mosquito.AmmoTypes += bullet_12mm
+ rotarychaingun_mosquito.FireModes += new FireModeDefinition
+ rotarychaingun_mosquito.FireModes.head.AmmoTypeIndices += 0
+ rotarychaingun_mosquito.FireModes.head.AmmoSlotIndex = 0
+ rotarychaingun_mosquito.FireModes.head.Magazine = 150
+
+ val
+ lightgunship_weapon_system = ToolDefinition(ObjectClass.lightgunship_weapon_system)
+ lightgunship_weapon_system.Size = EquipmentSize.VehicleWeapon
+ lightgunship_weapon_system.AmmoTypes += bullet_20mm
+ lightgunship_weapon_system.AmmoTypes += reaver_rocket
+ lightgunship_weapon_system.FireModes += new FireModeDefinition
+ lightgunship_weapon_system.FireModes.head.AmmoTypeIndices += 0
+ lightgunship_weapon_system.FireModes.head.AmmoSlotIndex = 0
+ lightgunship_weapon_system.FireModes.head.Magazine = 150
+ lightgunship_weapon_system.FireModes += new FireModeDefinition
+ lightgunship_weapon_system.FireModes(1).AmmoTypeIndices += 1
+ lightgunship_weapon_system.FireModes(1).AmmoSlotIndex = 1
+ lightgunship_weapon_system.FireModes(1).Magazine = 1 //TODO check
+
+ val
+ wasp_weapon_system = ToolDefinition(ObjectClass.wasp_weapon_system)
+ wasp_weapon_system.Size = EquipmentSize.VehicleWeapon
+ wasp_weapon_system.AmmoTypes += wasp_gun_ammo
+ wasp_weapon_system.AmmoTypes += wasp_rocket_ammo
+ wasp_weapon_system.FireModes += new FireModeDefinition
+ wasp_weapon_system.FireModes.head.AmmoTypeIndices += 0
+ wasp_weapon_system.FireModes.head.AmmoSlotIndex = 0
+ wasp_weapon_system.FireModes.head.Magazine = 30
+ wasp_weapon_system.FireModes += new FireModeDefinition
+ wasp_weapon_system.FireModes(1).AmmoTypeIndices += 1
+ wasp_weapon_system.FireModes(1).AmmoSlotIndex = 1
+ wasp_weapon_system.FireModes(1).Magazine = 1 //TODO check
+
+ val
+ liberator_weapon_system = ToolDefinition(ObjectClass.liberator_weapon_system)
+ liberator_weapon_system.Size = EquipmentSize.VehicleWeapon
+ liberator_weapon_system.AmmoTypes += bullet_35mm
+ liberator_weapon_system.FireModes += new FireModeDefinition
+ liberator_weapon_system.FireModes.head.AmmoTypeIndices += 0
+ liberator_weapon_system.FireModes.head.AmmoSlotIndex = 0
+ liberator_weapon_system.FireModes.head.Magazine = 100
+
+ val
+ liberator_bomb_bay = ToolDefinition(ObjectClass.liberator_bomb_bay)
+ liberator_bomb_bay.Size = EquipmentSize.VehicleWeapon
+ liberator_bomb_bay.AmmoTypes += liberator_bomb
+ liberator_bomb_bay.FireModes += new FireModeDefinition
+ liberator_bomb_bay.FireModes.head.AmmoTypeIndices += 0
+ liberator_bomb_bay.FireModes.head.AmmoSlotIndex = 0
+ liberator_bomb_bay.FireModes.head.Magazine = 10
+ liberator_bomb_bay.FireModes += new FireModeDefinition
+ liberator_bomb_bay.FireModes(1).AmmoTypeIndices += 0
+ liberator_bomb_bay.FireModes(1).AmmoSlotIndex = 0
+ liberator_bomb_bay.FireModes(1).Magazine = 10
+
+ val
+ liberator_25mm_cannon = ToolDefinition(ObjectClass.liberator_25mm_cannon)
+ liberator_25mm_cannon.Size = EquipmentSize.VehicleWeapon
+ liberator_25mm_cannon.AmmoTypes += bullet_25mm
+ liberator_25mm_cannon.FireModes += new FireModeDefinition
+ liberator_25mm_cannon.FireModes.head.AmmoTypeIndices += 0
+ liberator_25mm_cannon.FireModes.head.AmmoSlotIndex = 0
+ liberator_25mm_cannon.FireModes.head.Magazine = 150
+
+ val
+ vulture_nose_weapon_system = ToolDefinition(ObjectClass.vulture_nose_weapon_system)
+ vulture_nose_weapon_system.Size = EquipmentSize.VehicleWeapon
+ vulture_nose_weapon_system.AmmoTypes += bullet_35mm
+ vulture_nose_weapon_system.FireModes += new FireModeDefinition
+ vulture_nose_weapon_system.FireModes.head.AmmoTypeIndices += 0
+ vulture_nose_weapon_system.FireModes.head.AmmoSlotIndex = 0
+ vulture_nose_weapon_system.FireModes.head.Magazine = 75 //80?
+
+ val
+ vulture_bomb_bay = ToolDefinition(ObjectClass.vulture_bomb_bay)
+ vulture_bomb_bay.Size = EquipmentSize.VehicleWeapon
+ vulture_bomb_bay.AmmoTypes += liberator_bomb
+ vulture_bomb_bay.FireModes += new FireModeDefinition
+ vulture_bomb_bay.FireModes.head.AmmoTypeIndices += 0
+ vulture_bomb_bay.FireModes.head.AmmoSlotIndex = 0
+ vulture_bomb_bay.FireModes.head.Magazine = 10
+
+ val
+ vulture_tail_cannon = ToolDefinition(ObjectClass.vulture_tail_cannon)
+ vulture_tail_cannon.Size = EquipmentSize.VehicleWeapon
+ vulture_tail_cannon.AmmoTypes += bullet_25mm
+ vulture_tail_cannon.FireModes += new FireModeDefinition
+ vulture_tail_cannon.FireModes.head.AmmoTypeIndices += 0
+ vulture_tail_cannon.FireModes.head.AmmoSlotIndex = 0
+ vulture_tail_cannon.FireModes.head.Magazine = 100
+
+ val
+ cannon_dropship_20mm = ToolDefinition(ObjectClass.cannon_dropship_20mm)
+ cannon_dropship_20mm.Size = EquipmentSize.VehicleWeapon
+ cannon_dropship_20mm.AmmoTypes += bullet_20mm
+ cannon_dropship_20mm.FireModes += new FireModeDefinition
+ cannon_dropship_20mm.FireModes.head.AmmoTypeIndices += 0
+ cannon_dropship_20mm.FireModes.head.AmmoSlotIndex = 0
+ cannon_dropship_20mm.FireModes.head.Magazine = 250
+
+ val
+ dropship_rear_turret = ToolDefinition(ObjectClass.dropship_rear_turret)
+ dropship_rear_turret.Size = EquipmentSize.VehicleWeapon
+ dropship_rear_turret.AmmoTypes += bullet_20mm
+ dropship_rear_turret.FireModes += new FireModeDefinition
+ dropship_rear_turret.FireModes.head.AmmoTypeIndices += 0
+ dropship_rear_turret.FireModes.head.AmmoSlotIndex = 0
+ dropship_rear_turret.FireModes.head.Magazine = 250
+
+ val
+ galaxy_gunship_cannon = ToolDefinition(ObjectClass.galaxy_gunship_cannon)
+ galaxy_gunship_cannon.Size = EquipmentSize.VehicleWeapon
+ galaxy_gunship_cannon.AmmoTypes += heavy_grenade_mortar
+ galaxy_gunship_cannon.FireModes += new FireModeDefinition
+ galaxy_gunship_cannon.FireModes.head.AmmoTypeIndices += 0
+ galaxy_gunship_cannon.FireModes.head.AmmoSlotIndex = 0
+ galaxy_gunship_cannon.FireModes.head.Magazine = 50
+
+ val
+ galaxy_gunship_tailgun = ToolDefinition(ObjectClass.galaxy_gunship_tailgun)
+ galaxy_gunship_tailgun.Size = EquipmentSize.VehicleWeapon
+ galaxy_gunship_tailgun.AmmoTypes += bullet_35mm
+ galaxy_gunship_tailgun.FireModes += new FireModeDefinition
+ galaxy_gunship_tailgun.FireModes.head.AmmoTypeIndices += 0
+ galaxy_gunship_tailgun.FireModes.head.AmmoSlotIndex = 0
+ galaxy_gunship_tailgun.FireModes.head.Magazine = 200
+
+ val
+ galaxy_gunship_gun = ToolDefinition(ObjectClass.galaxy_gunship_gun)
+ galaxy_gunship_gun.Size = EquipmentSize.VehicleWeapon
+ galaxy_gunship_gun.AmmoTypes += bullet_35mm
+ galaxy_gunship_gun.FireModes += new FireModeDefinition
+ galaxy_gunship_gun.FireModes.head.AmmoTypeIndices += 0
+ galaxy_gunship_gun.FireModes.head.AmmoSlotIndex = 0
+ galaxy_gunship_gun.FireModes.head.Magazine = 200
+
val
fury = VehicleDefinition(ObjectClass.fury)
fury.Seats += 0 -> new SeatDefinition()
fury.Seats(0).Bailable = true
fury.Seats(0).ControlledWeapon = 1
+ fury.Weapons += 1 -> fury_weapon_systema
fury.MountPoints += 1 -> 0
fury.MountPoints += 2 -> 0
- fury.Weapons += 1 -> fury_weapon_systema
- fury.TrunkSize = InventoryTile(11, 11)
+ fury.TrunkSize = InventoryTile.Tile1111
fury.TrunkOffset = 30
val
@@ -1262,10 +1781,10 @@ object GlobalDefinitions {
quadassault.Seats += 0 -> new SeatDefinition()
quadassault.Seats(0).Bailable = true
quadassault.Seats(0).ControlledWeapon = 1
+ quadassault.Weapons += 1 -> quadassault_weapon_system
quadassault.MountPoints += 1 -> 0
quadassault.MountPoints += 2 -> 0
- quadassault.Weapons += 1 -> quadassault_weapon_system
- quadassault.TrunkSize = InventoryTile(11, 11)
+ quadassault.TrunkSize = InventoryTile.Tile1111
quadassault.TrunkOffset = 30
val
@@ -1273,10 +1792,10 @@ object GlobalDefinitions {
quadstealth.CanCloak = true
quadstealth.Seats += 0 -> new SeatDefinition()
quadstealth.Seats(0).Bailable = true
+ quadstealth.CanCloak = true
quadstealth.MountPoints += 1 -> 0
quadstealth.MountPoints += 2 -> 0
- quadstealth.CanCloak = true
- quadstealth.TrunkSize = InventoryTile(11, 11)
+ quadstealth.TrunkSize = InventoryTile.Tile1111
quadstealth.TrunkOffset = 30
val
@@ -1286,12 +1805,542 @@ object GlobalDefinitions {
two_man_assault_buggy.Seats += 1 -> new SeatDefinition()
two_man_assault_buggy.Seats(1).Bailable = true
two_man_assault_buggy.Seats(1).ControlledWeapon = 2
+ two_man_assault_buggy.Weapons += 2 -> chaingun_p
two_man_assault_buggy.MountPoints += 1 -> 0
two_man_assault_buggy.MountPoints += 2 -> 1
- two_man_assault_buggy.Weapons += 2 -> chaingun_p
- two_man_assault_buggy.TrunkSize = InventoryTile(11, 11)
+ two_man_assault_buggy.TrunkSize = InventoryTile.Tile1111
two_man_assault_buggy.TrunkOffset = 30
+ val
+ skyguard = VehicleDefinition(ObjectClass.skyguard)
+ skyguard.Seats += 0 -> new SeatDefinition()
+ skyguard.Seats(0).Bailable = true
+ skyguard.Seats += 1 -> new SeatDefinition()
+ skyguard.Seats(1).Bailable = true
+ skyguard.Seats(1).ControlledWeapon = 2
+ skyguard.Weapons += 2 -> skyguard_weapon_system
+ skyguard.MountPoints += 1 -> 0
+ skyguard.MountPoints += 2 -> 0
+ skyguard.MountPoints += 3 -> 1
+ skyguard.TrunkSize = InventoryTile.Tile1511
+ skyguard.TrunkOffset = 30
+
+ val
+ threemanheavybuggy = VehicleDefinition(ObjectClass.threemanheavybuggy)
+ threemanheavybuggy.Seats += 0 -> new SeatDefinition()
+ threemanheavybuggy.Seats(0).Bailable = true
+ threemanheavybuggy.Seats += 1 -> new SeatDefinition()
+ threemanheavybuggy.Seats(1).Bailable = true
+ threemanheavybuggy.Seats(1).ControlledWeapon = 3
+ threemanheavybuggy.Seats += 2 -> new SeatDefinition()
+ threemanheavybuggy.Seats(2).Bailable = true
+ threemanheavybuggy.Seats(2).ControlledWeapon = 4
+ threemanheavybuggy.Weapons += 3 -> chaingun_p
+ threemanheavybuggy.Weapons += 4 -> grenade_launcher_marauder
+ threemanheavybuggy.MountPoints += 1 -> 0
+ threemanheavybuggy.MountPoints += 2 -> 1
+ threemanheavybuggy.MountPoints += 3 -> 2
+ threemanheavybuggy.TrunkSize = InventoryTile.Tile1511
+ threemanheavybuggy.TrunkOffset = 30
+
+ val
+ twomanheavybuggy = VehicleDefinition(ObjectClass.twomanheavybuggy)
+ twomanheavybuggy.Seats += 0 -> new SeatDefinition()
+ twomanheavybuggy.Seats(0).Bailable = true
+ twomanheavybuggy.Seats += 1 -> new SeatDefinition()
+ twomanheavybuggy.Seats(1).Bailable = true
+ twomanheavybuggy.Seats(1).ControlledWeapon = 2
+ twomanheavybuggy.Weapons += 2 -> advanced_missile_launcher_t
+ twomanheavybuggy.MountPoints += 1 -> 0
+ twomanheavybuggy.MountPoints += 2 -> 1
+ twomanheavybuggy.TrunkSize = InventoryTile.Tile1511
+ twomanheavybuggy.TrunkOffset = 30
+
+ val
+ twomanhoverbuggy = VehicleDefinition(ObjectClass.twomanhoverbuggy)
+ twomanhoverbuggy.Seats += 0 -> new SeatDefinition()
+ twomanhoverbuggy.Seats(0).Bailable = true
+ twomanhoverbuggy.Seats += 1 -> new SeatDefinition()
+ twomanhoverbuggy.Seats(1).Bailable = true
+ twomanhoverbuggy.Seats(1).ControlledWeapon = 2
+ twomanhoverbuggy.Weapons += 2 -> flux_cannon_thresher
+ twomanhoverbuggy.MountPoints += 1 -> 0
+ twomanhoverbuggy.MountPoints += 2 -> 1
+ twomanhoverbuggy.TrunkSize = InventoryTile.Tile1511
+ twomanhoverbuggy.TrunkOffset = 30
+
+ val
+ mediumtransport = VehicleDefinition(ObjectClass.mediumtransport)
+ mediumtransport.Seats += 0 -> new SeatDefinition()
+ mediumtransport.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ mediumtransport.Seats += 1 -> new SeatDefinition()
+ mediumtransport.Seats(1).ControlledWeapon = 5
+ mediumtransport.Seats += 2 -> new SeatDefinition()
+ mediumtransport.Seats(2).ControlledWeapon = 6
+ mediumtransport.Seats += 3 -> new SeatDefinition()
+ mediumtransport.Seats += 4 -> new SeatDefinition()
+ mediumtransport.Weapons += 5 -> mediumtransport_weapon_systemA
+ mediumtransport.Weapons += 6 -> mediumtransport_weapon_systemB
+ mediumtransport.MountPoints += 1 -> 0
+ mediumtransport.MountPoints += 2 -> 1
+ mediumtransport.MountPoints += 3 -> 2
+ mediumtransport.MountPoints += 4 -> 3
+ mediumtransport.MountPoints += 5 -> 4
+ mediumtransport.TrunkSize = InventoryTile.Tile1515
+ mediumtransport.TrunkOffset = 30
+
+ val
+ battlewagon = VehicleDefinition(ObjectClass.battlewagon)
+ battlewagon.Seats += 0 -> new SeatDefinition()
+ battlewagon.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ battlewagon.Seats += 1 -> new SeatDefinition()
+ battlewagon.Seats(1).ControlledWeapon = 5
+ battlewagon.Seats += 2 -> new SeatDefinition()
+ battlewagon.Seats(2).ControlledWeapon = 6
+ battlewagon.Seats += 3 -> new SeatDefinition()
+ battlewagon.Seats(3).ControlledWeapon = 7
+ battlewagon.Seats += 4 -> new SeatDefinition()
+ battlewagon.Seats(4).ControlledWeapon = 8
+ battlewagon.Weapons += 5 -> battlewagon_weapon_systema
+ battlewagon.Weapons += 6 -> battlewagon_weapon_systemb
+ battlewagon.Weapons += 7 -> battlewagon_weapon_systemc
+ battlewagon.Weapons += 8 -> battlewagon_weapon_systemd
+ battlewagon.MountPoints += 1 -> 0
+ battlewagon.MountPoints += 2 -> 1
+ battlewagon.MountPoints += 3 -> 2
+ battlewagon.MountPoints += 4 -> 3
+ battlewagon.MountPoints += 5 -> 4
+ battlewagon.TrunkSize = InventoryTile.Tile1515
+ battlewagon.TrunkOffset = 30
+
+ val
+ thunderer = VehicleDefinition(ObjectClass.thunderer)
+ thunderer.Seats += 0 -> new SeatDefinition()
+ thunderer.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ thunderer.Seats += 1 -> new SeatDefinition()
+ thunderer.Seats(1).ControlledWeapon = 5
+ thunderer.Seats += 2 -> new SeatDefinition()
+ thunderer.Seats(2).ControlledWeapon = 6
+ thunderer.Seats += 3 -> new SeatDefinition()
+ thunderer.Seats += 4 -> new SeatDefinition()
+ thunderer.Weapons += 5 -> thunderer_weapon_systema
+ thunderer.Weapons += 6 -> thunderer_weapon_systemb
+ thunderer.MountPoints += 1 -> 0
+ thunderer.MountPoints += 2 -> 1
+ thunderer.MountPoints += 3 -> 2
+ thunderer.MountPoints += 4 -> 3
+ thunderer.MountPoints += 5 -> 4
+ thunderer.TrunkSize = InventoryTile.Tile1515
+ thunderer.TrunkOffset = 30
+
+ val
+ aurora = VehicleDefinition(ObjectClass.aurora)
+ aurora.Seats += 0 -> new SeatDefinition()
+ aurora.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ aurora.Seats += 1 -> new SeatDefinition()
+ aurora.Seats(1).ControlledWeapon = 5
+ aurora.Seats += 2 -> new SeatDefinition()
+ aurora.Seats(2).ControlledWeapon = 6
+ aurora.Seats += 3 -> new SeatDefinition()
+ aurora.Seats += 4 -> new SeatDefinition()
+ aurora.Weapons += 5 -> aurora_weapon_systema
+ aurora.Weapons += 6 -> aurora_weapon_systemb
+ aurora.MountPoints += 1 -> 0
+ aurora.MountPoints += 2 -> 1
+ aurora.MountPoints += 3 -> 2
+ aurora.MountPoints += 4 -> 3
+ aurora.MountPoints += 5 -> 4
+ aurora.TrunkSize = InventoryTile.Tile1515
+ aurora.TrunkOffset = 30
+
+ val
+ apc_tr = VehicleDefinition(ObjectClass.apc_tr)
+ apc_tr.Seats += 0 -> new SeatDefinition()
+ apc_tr.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ apc_tr.Seats += 1 -> new SeatDefinition()
+ apc_tr.Seats(1).ControlledWeapon = 11
+ apc_tr.Seats += 2 -> new SeatDefinition()
+ apc_tr.Seats(2).ControlledWeapon = 12
+ apc_tr.Seats += 3 -> new SeatDefinition()
+ apc_tr.Seats += 4 -> new SeatDefinition()
+ apc_tr.Seats += 5 -> new SeatDefinition()
+ apc_tr.Seats(5).ControlledWeapon = 15
+ apc_tr.Seats += 6 -> new SeatDefinition()
+ apc_tr.Seats(6).ControlledWeapon = 16
+ apc_tr.Seats += 7 -> new SeatDefinition()
+ apc_tr.Seats(7).ControlledWeapon = 13
+ apc_tr.Seats += 8 -> new SeatDefinition()
+ apc_tr.Seats(8).ControlledWeapon = 14
+ apc_tr.Seats += 9 -> new SeatDefinition()
+ apc_tr.Seats(9).ArmorRestriction = SeatArmorRestriction.MaxOnly
+ apc_tr.Seats += 10 -> new SeatDefinition()
+ apc_tr.Seats(10).ArmorRestriction = SeatArmorRestriction.MaxOnly
+ apc_tr.Weapons += 11 -> apc_weapon_systemc_tr
+ apc_tr.Weapons += 12 -> apc_weapon_systemb
+ apc_tr.Weapons += 13 -> apc_weapon_systema
+ apc_tr.Weapons += 14 -> apc_weapon_systemd_tr
+ apc_tr.Weapons += 15 -> apc_ballgun_r
+ apc_tr.Weapons += 16 -> apc_ballgun_l
+ apc_tr.MountPoints += 1 -> 0
+ apc_tr.MountPoints += 2 -> 0
+ apc_tr.MountPoints += 3 -> 1
+ apc_tr.MountPoints += 4 -> 2
+ apc_tr.MountPoints += 5 -> 3
+ apc_tr.MountPoints += 6 -> 4
+ apc_tr.MountPoints += 7 -> 5
+ apc_tr.MountPoints += 8 -> 6
+ apc_tr.MountPoints += 9 -> 7
+ apc_tr.MountPoints += 10 -> 8
+ apc_tr.MountPoints += 11 -> 9
+ apc_tr.MountPoints += 12 -> 10
+ apc_tr.TrunkSize = InventoryTile.Tile2016
+ apc_tr.TrunkOffset = 30
+
+ val
+ apc_nc = VehicleDefinition(ObjectClass.apc_nc)
+ apc_nc.Seats += 0 -> new SeatDefinition()
+ apc_nc.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ apc_nc.Seats += 1 -> new SeatDefinition()
+ apc_nc.Seats(1).ControlledWeapon = 11
+ apc_nc.Seats += 2 -> new SeatDefinition()
+ apc_nc.Seats(2).ControlledWeapon = 12
+ apc_nc.Seats += 3 -> new SeatDefinition()
+ apc_nc.Seats += 4 -> new SeatDefinition()
+ apc_nc.Seats += 5 -> new SeatDefinition()
+ apc_nc.Seats(5).ControlledWeapon = 15
+ apc_nc.Seats += 6 -> new SeatDefinition()
+ apc_nc.Seats(6).ControlledWeapon = 16
+ apc_nc.Seats += 7 -> new SeatDefinition()
+ apc_nc.Seats(7).ControlledWeapon = 13
+ apc_nc.Seats += 8 -> new SeatDefinition()
+ apc_nc.Seats(8).ControlledWeapon = 14
+ apc_nc.Seats += 9 -> new SeatDefinition()
+ apc_nc.Seats(9).ArmorRestriction = SeatArmorRestriction.MaxOnly
+ apc_nc.Seats += 10 -> new SeatDefinition()
+ apc_nc.Seats(10).ArmorRestriction = SeatArmorRestriction.MaxOnly
+ apc_nc.Weapons += 11 -> apc_weapon_systemc_nc
+ apc_nc.Weapons += 12 -> apc_weapon_systemb
+ apc_nc.Weapons += 13 -> apc_weapon_systema
+ apc_nc.Weapons += 14 -> apc_weapon_systemd_nc
+ apc_nc.Weapons += 15 -> apc_ballgun_r
+ apc_nc.Weapons += 16 -> apc_ballgun_l
+ apc_nc.MountPoints += 1 -> 0
+ apc_nc.MountPoints += 2 -> 0
+ apc_nc.MountPoints += 3 -> 1
+ apc_nc.MountPoints += 4 -> 2
+ apc_nc.MountPoints += 5 -> 3
+ apc_nc.MountPoints += 6 -> 4
+ apc_nc.MountPoints += 7 -> 5
+ apc_nc.MountPoints += 8 -> 6
+ apc_nc.MountPoints += 9 -> 7
+ apc_nc.MountPoints += 10 -> 8
+ apc_nc.MountPoints += 11 -> 9
+ apc_nc.MountPoints += 12 -> 10
+ apc_nc.TrunkSize = InventoryTile.Tile2016
+ apc_nc.TrunkOffset = 30
+
+ val
+ apc_vs = VehicleDefinition(ObjectClass.apc_vs)
+ apc_vs.Seats += 0 -> new SeatDefinition()
+ apc_vs.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ apc_vs.Seats += 1 -> new SeatDefinition()
+ apc_vs.Seats(1).ControlledWeapon = 11
+ apc_vs.Seats += 2 -> new SeatDefinition()
+ apc_vs.Seats(2).ControlledWeapon = 12
+ apc_vs.Seats += 3 -> new SeatDefinition()
+ apc_vs.Seats += 4 -> new SeatDefinition()
+ apc_vs.Seats += 5 -> new SeatDefinition()
+ apc_vs.Seats(5).ControlledWeapon = 15
+ apc_vs.Seats += 6 -> new SeatDefinition()
+ apc_vs.Seats(6).ControlledWeapon = 16
+ apc_vs.Seats += 7 -> new SeatDefinition()
+ apc_vs.Seats(7).ControlledWeapon = 13
+ apc_vs.Seats += 8 -> new SeatDefinition()
+ apc_vs.Seats(8).ControlledWeapon = 14
+ apc_vs.Seats += 9 -> new SeatDefinition()
+ apc_vs.Seats(9).ArmorRestriction = SeatArmorRestriction.MaxOnly
+ apc_vs.Seats += 10 -> new SeatDefinition()
+ apc_vs.Seats(10).ArmorRestriction = SeatArmorRestriction.MaxOnly
+ apc_vs.Weapons += 11 -> apc_weapon_systemc_vs
+ apc_vs.Weapons += 12 -> apc_weapon_systemb
+ apc_vs.Weapons += 13 -> apc_weapon_systema
+ apc_vs.Weapons += 14 -> apc_weapon_systemd_vs
+ apc_vs.Weapons += 15 -> apc_ballgun_r
+ apc_vs.Weapons += 16 -> apc_ballgun_l
+ apc_vs.MountPoints += 1 -> 0
+ apc_vs.MountPoints += 2 -> 0
+ apc_vs.MountPoints += 3 -> 1
+ apc_vs.MountPoints += 4 -> 2
+ apc_vs.MountPoints += 5 -> 3
+ apc_vs.MountPoints += 6 -> 4
+ apc_vs.MountPoints += 7 -> 5
+ apc_vs.MountPoints += 8 -> 6
+ apc_vs.MountPoints += 9 -> 7
+ apc_vs.MountPoints += 10 -> 8
+ apc_vs.MountPoints += 11 -> 9
+ apc_vs.MountPoints += 12 -> 10
+ apc_vs.TrunkSize = InventoryTile.Tile2016
+ apc_vs.TrunkOffset = 30
+
+ val
+ lightning = VehicleDefinition(ObjectClass.lightning)
+ lightning.Seats += 0 -> new SeatDefinition()
+ lightning.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ lightning.Seats(0).ControlledWeapon = 1
+ lightning.Weapons += 1 -> lightning_weapon_system
+ lightning.MountPoints += 1 -> 0
+ lightning.MountPoints += 2 -> 0
+ lightning.TrunkSize = InventoryTile.Tile1511
+ lightning.TrunkOffset = 30
+
+ val
+ prowler = VehicleDefinition(ObjectClass.prowler)
+ prowler.Seats += 0 -> new SeatDefinition()
+ prowler.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ prowler.Seats += 1 -> new SeatDefinition()
+ prowler.Seats(1).ControlledWeapon = 3
+ prowler.Seats += 2 -> new SeatDefinition()
+ prowler.Seats(2).ControlledWeapon = 4
+ prowler.Weapons += 3 -> prowler_weapon_systemA
+ prowler.Weapons += 4 -> prowler_weapon_systemB
+ prowler.MountPoints += 1 -> 0
+ prowler.MountPoints += 2 -> 1
+ prowler.MountPoints += 3 -> 2
+ prowler.TrunkSize = InventoryTile.Tile1511
+ prowler.TrunkOffset = 30
+
+ val
+ vanguard = VehicleDefinition(ObjectClass.vanguard)
+ vanguard.Seats += 0 -> new SeatDefinition()
+ vanguard.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ vanguard.Seats += 1 -> new SeatDefinition()
+ vanguard.Seats(1).ControlledWeapon = 2
+ vanguard.Weapons += 2 -> vanguard_weapon_system
+ vanguard.MountPoints += 1 -> 0
+ vanguard.MountPoints += 2 -> 1
+ vanguard.TrunkSize = InventoryTile.Tile1511
+ vanguard.TrunkOffset = 30
+
+ val
+ magrider = VehicleDefinition(ObjectClass.magrider)
+ magrider.Seats += 0 -> new SeatDefinition()
+ magrider.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ magrider.Seats(0).ControlledWeapon = 2
+ magrider.Seats += 1 -> new SeatDefinition()
+ magrider.Seats(1).ControlledWeapon = 3
+ magrider.Weapons += 2 -> particle_beam_magrider
+ magrider.Weapons += 3 -> heavy_rail_beam_magrider
+ magrider.MountPoints += 1 -> 0
+ magrider.MountPoints += 2 -> 1
+ magrider.TrunkSize = InventoryTile.Tile1511
+ magrider.TrunkOffset = 30
+
+ private val utilityConverter = new UtilityVehicleConverter
+ val
+ ant = VehicleDefinition(ObjectClass.ant)
+ ant.Seats += 0 -> new SeatDefinition()
+ ant.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ ant.MountPoints += 1 -> 0
+ ant.MountPoints += 2 -> 0
+ ant.Packet = utilityConverter
+
+ val
+ ams = VehicleDefinition(ObjectClass.ams)
+ ams.Seats += 0 -> new SeatDefinition()
+ ams.Seats(0).ArmorRestriction = SeatArmorRestriction.NoReinforcedOrMax
+ ams.MountPoints += 1 -> 0
+ ams.MountPoints += 2 -> 0
+ ams.Packet = utilityConverter
+
+ private val variantConverter = new VariantVehicleConverter
+ val
+ router = VehicleDefinition(ObjectClass.router)
+ router.Seats += 0 -> new SeatDefinition()
+ router.MountPoints += 1 -> 0
+ router.TrunkSize = InventoryTile.Tile1511
+ router.TrunkOffset = 30
+ router.Packet = variantConverter
+
+ val
+ switchblade = VehicleDefinition(ObjectClass.switchblade)
+ switchblade.Seats += 0 -> new SeatDefinition()
+ switchblade.Seats(0).ControlledWeapon = 1
+ switchblade.Weapons += 1 -> scythe
+ switchblade.MountPoints += 1 -> 0
+ switchblade.MountPoints += 2 -> 0
+ switchblade.TrunkSize = InventoryTile.Tile1511
+ switchblade.TrunkOffset = 30
+ switchblade.Packet = variantConverter
+
+ val
+ flail = VehicleDefinition(ObjectClass.flail)
+ flail.Seats += 0 -> new SeatDefinition()
+ flail.Seats(0).ControlledWeapon = 1
+ flail.Weapons += 1 -> flail_weapon
+ flail.MountPoints += 1 -> 0
+ flail.TrunkSize = InventoryTile.Tile1511
+ flail.TrunkOffset = 30
+ flail.Packet = variantConverter
+
+ val
+ mosquito = VehicleDefinition(ObjectClass.mosquito)
+ mosquito.Seats += 0 -> new SeatDefinition()
+ mosquito.Seats(0).Bailable = true
+ mosquito.Seats(0).ControlledWeapon = 1
+ mosquito.Weapons += 1 -> rotarychaingun_mosquito
+ mosquito.MountPoints += 1 -> 0
+ mosquito.MountPoints += 2 -> 0
+ mosquito.TrunkSize = InventoryTile.Tile1111
+ mosquito.TrunkOffset = 30
+ mosquito.Packet = variantConverter
+
+ val
+ lightgunship = VehicleDefinition(ObjectClass.lightgunship)
+ lightgunship.Seats += 0 -> new SeatDefinition()
+ lightgunship.Seats(0).Bailable = true
+ lightgunship.Seats(0).ControlledWeapon = 1
+ lightgunship.Weapons += 1 -> lightgunship_weapon_system
+ lightgunship.MountPoints += 1 -> 0
+ lightgunship.MountPoints += 2 -> 0
+ lightgunship.TrunkSize = InventoryTile.Tile1511
+ lightgunship.TrunkOffset = 30
+ lightgunship.Packet = variantConverter
+
+ val
+ wasp = VehicleDefinition(ObjectClass.wasp)
+ wasp.Seats += 0 -> new SeatDefinition()
+ wasp.Seats(0).Bailable = true
+ wasp.Seats(0).ControlledWeapon = 1
+ wasp.Weapons += 1 -> wasp_weapon_system
+ wasp.MountPoints += 1 -> 0
+ wasp.MountPoints += 2 -> 0
+ wasp.TrunkSize = InventoryTile.Tile1111
+ wasp.TrunkOffset = 30
+ wasp.Packet = variantConverter
+
+ val
+ liberator = VehicleDefinition(ObjectClass.liberator)
+ liberator.Seats += 0 -> new SeatDefinition()
+ liberator.Seats(0).ControlledWeapon = 3
+ liberator.Seats += 1 -> new SeatDefinition()
+ liberator.Seats(1).ControlledWeapon = 4
+ liberator.Seats += 2 -> new SeatDefinition()
+ liberator.Seats(2).ControlledWeapon = 5
+ liberator.Weapons += 3 -> liberator_weapon_system
+ liberator.Weapons += 4 -> liberator_bomb_bay
+ liberator.Weapons += 5 -> liberator_25mm_cannon
+ liberator.MountPoints += 1 -> 0
+ liberator.MountPoints += 2 -> 1
+ liberator.MountPoints += 3 -> 1
+ liberator.MountPoints += 4 -> 2
+ liberator.TrunkSize = InventoryTile.Tile1515
+ liberator.TrunkOffset = 30
+ liberator.Packet = variantConverter
+
+ val
+ vulture = VehicleDefinition(ObjectClass.vulture)
+ vulture.Seats += 0 -> new SeatDefinition()
+ vulture.Seats(0).ControlledWeapon = 3
+ vulture.Seats += 1 -> new SeatDefinition()
+ vulture.Seats(1).ControlledWeapon = 4
+ vulture.Seats += 2 -> new SeatDefinition()
+ vulture.Seats(2).ControlledWeapon = 5
+ vulture.Weapons += 3 -> vulture_nose_weapon_system
+ vulture.Weapons += 4 -> vulture_bomb_bay
+ vulture.Weapons += 5 -> vulture_tail_cannon
+ vulture.MountPoints += 1 -> 0
+ vulture.MountPoints += 2 -> 1
+ vulture.MountPoints += 3 -> 1
+ vulture.MountPoints += 4 -> 2
+ vulture.TrunkSize = InventoryTile.Tile1611
+ vulture.TrunkOffset = 30
+ vulture.Packet = variantConverter
+
+ val
+ dropship = VehicleDefinition(ObjectClass.dropship)
+ dropship.Seats += 0 -> new SeatDefinition()
+ dropship.Seats += 1 -> new SeatDefinition()
+ dropship.Seats(1).Bailable = true
+ dropship.Seats(1).ControlledWeapon = 12
+ dropship.Seats += 2 -> new SeatDefinition()
+ dropship.Seats(2).Bailable = true
+ dropship.Seats(2).ControlledWeapon = 13
+ dropship.Seats += 3 -> new SeatDefinition()
+ dropship.Seats(3).Bailable = true
+ dropship.Seats += 4 -> new SeatDefinition()
+ dropship.Seats(4).Bailable = true
+ dropship.Seats += 5 -> new SeatDefinition()
+ dropship.Seats(5).Bailable = true
+ dropship.Seats += 6 -> new SeatDefinition()
+ dropship.Seats(6).Bailable = true
+ dropship.Seats += 7 -> new SeatDefinition()
+ dropship.Seats(7).Bailable = true
+ dropship.Seats += 8 -> new SeatDefinition()
+ dropship.Seats(8).Bailable = true
+ dropship.Seats += 9 -> new SeatDefinition()
+ dropship.Seats(9).Bailable = true
+ dropship.Seats(9).ArmorRestriction = SeatArmorRestriction.MaxOnly
+ dropship.Seats += 10 -> new SeatDefinition()
+ dropship.Seats(10).Bailable = true
+ dropship.Seats(10).ArmorRestriction = SeatArmorRestriction.MaxOnly
+ dropship.Seats += 11 -> new SeatDefinition()
+ dropship.Seats(11).Bailable = true
+ dropship.Seats(11).ControlledWeapon = 14
+ dropship.Weapons += 12 -> cannon_dropship_20mm
+ dropship.Weapons += 13 -> cannon_dropship_20mm
+ dropship.Weapons += 14 -> dropship_rear_turret
+ dropship.MountPoints += 1 -> 0
+ dropship.MountPoints += 2 -> 11
+ dropship.MountPoints += 3 -> 1
+ dropship.MountPoints += 4 -> 2
+ dropship.MountPoints += 5 -> 3
+ dropship.MountPoints += 6 -> 4
+ dropship.MountPoints += 7 -> 5
+ dropship.MountPoints += 8 -> 6
+ dropship.MountPoints += 9 -> 7
+ dropship.MountPoints += 10 -> 8
+ dropship.MountPoints += 11 -> 9
+ dropship.MountPoints += 12 -> 10
+ dropship.TrunkSize = InventoryTile.Tile1612
+ dropship.TrunkOffset = 30
+ dropship.Packet = variantConverter
+
+ val
+ galaxy_gunship = VehicleDefinition(ObjectClass.galaxy_gunship)
+ galaxy_gunship.Seats += 0 -> new SeatDefinition()
+ galaxy_gunship.Seats += 1 -> new SeatDefinition()
+ galaxy_gunship.Seats(1).ControlledWeapon = 6
+ galaxy_gunship.Seats += 2 -> new SeatDefinition()
+ galaxy_gunship.Seats(2).ControlledWeapon = 7
+ galaxy_gunship.Seats += 3 -> new SeatDefinition()
+ galaxy_gunship.Seats(3).ControlledWeapon = 8
+ galaxy_gunship.Seats += 4 -> new SeatDefinition()
+ galaxy_gunship.Seats(4).ControlledWeapon = 9
+ galaxy_gunship.Seats += 5 -> new SeatDefinition()
+ galaxy_gunship.Seats(5).ControlledWeapon = 10
+ galaxy_gunship.Weapons += 6 -> galaxy_gunship_cannon
+ galaxy_gunship.Weapons += 7 -> galaxy_gunship_cannon
+ galaxy_gunship.Weapons += 8 -> galaxy_gunship_tailgun
+ galaxy_gunship.Weapons += 9 -> galaxy_gunship_gun
+ galaxy_gunship.Weapons += 10 -> galaxy_gunship_gun
+ galaxy_gunship.MountPoints += 1 -> 0
+ galaxy_gunship.MountPoints += 2 -> 3
+ galaxy_gunship.MountPoints += 3 -> 1
+ galaxy_gunship.MountPoints += 4 -> 2
+ galaxy_gunship.MountPoints += 5 -> 4
+ galaxy_gunship.MountPoints += 6 -> 5
+ galaxy_gunship.TrunkSize = InventoryTile.Tile1816
+ galaxy_gunship.TrunkOffset = 30
+ galaxy_gunship.Packet = variantConverter
+
+ val
+ lodestar = VehicleDefinition(ObjectClass.lodestar)
+ lodestar.Seats += 0 -> new SeatDefinition()
+ lodestar.MountPoints += 1 -> 0
+ lodestar.TrunkSize = InventoryTile.Tile1612
+ lodestar.TrunkOffset = 30
+ lodestar.Packet = variantConverter
+
val
phantasm = VehicleDefinition(ObjectClass.phantasm)
phantasm.CanCloak = true
@@ -1304,14 +2353,30 @@ object GlobalDefinitions {
phantasm.Seats(3).Bailable = true
phantasm.Seats += 4 -> new SeatDefinition()
phantasm.Seats(4).Bailable = true
- phantasm.MountPoints += 1 -> 0 //TODO add and check all
- phantasm.TrunkSize = InventoryTile(11, 8)
- phantasm.TrunkOffset = 30 //TODO check
+ phantasm.MountPoints += 1 -> 0
+ phantasm.MountPoints += 2 -> 1
+ phantasm.MountPoints += 3 -> 2
+ phantasm.MountPoints += 4 -> 3
+ phantasm.MountPoints += 5 -> 4
+ phantasm.TrunkSize = InventoryTile.Tile1107
+ phantasm.TrunkOffset = 30
+ phantasm.Packet = variantConverter
val
order_terminal = new OrderTerminalDefinition
val
cert_terminal = new CertTerminalDefinition
+ val
+ ground_vehicle_terminal = new GroundVehicleTerminalDefinition
+ val
+ air_vehicle_terminal = new AirVehicleTerminalDefinition
+ val
+ dropship_vehicle_terminal = new DropshipVehicleTerminalDefinition
+ val
+ vehicle_terminal_combined = new VehicleTerminalCombinedDefinition
+
+ val
+ spawn_pad = new ObjectDefinition(800) { Name = "spawn_pad" }
val
lock_external = new IFFLockDefinition
diff --git a/common/src/main/scala/net/psforever/objects/InfantryLoadout.scala b/common/src/main/scala/net/psforever/objects/Loadout.scala
similarity index 81%
rename from common/src/main/scala/net/psforever/objects/InfantryLoadout.scala
rename to common/src/main/scala/net/psforever/objects/Loadout.scala
index ac1c27df7..355a7d171 100644
--- a/common/src/main/scala/net/psforever/objects/InfantryLoadout.scala
+++ b/common/src/main/scala/net/psforever/objects/Loadout.scala
@@ -11,7 +11,7 @@ import scala.annotation.tailrec
/**
* From a `Player` their current exo-suit and their `Equipment`, retain a set of instructions to reconstruct this arrangement.
*
- * `InfantryLoadout` objects are composed of the following information, as if a blueprint:
+ * `Loadout` objects are composed of the following information, as if a blueprint:
* - the avatar's current exo-suit
* - the type of specialization, called a "subtype" (mechanized assault exo-suits only)
* - the contents of the avatar's occupied holster slots
@@ -28,25 +28,24 @@ import scala.annotation.tailrec
* Even a whole blueprint can be denied if the user lacks the necessary exo-suit certification.
* A completely new piece of `Equipment` is constructed when the `Loadout` is regurgitated.
*
- * The fifth tab on an `order_terminal` window is for "Favorite" blueprints for `InfantryLoadout` entries.
+ * The fifth tab on an `order_terminal` window is for "Favorite" blueprints for `Loadout` entries.
* The ten-long list is initialized with `FavoritesMessage` packets.
* Specific entries are loaded or removed using `FavoritesRequest` packets.
* @param player the player
* @param label the name by which this inventory will be known when displayed in a Favorites list
*/
-class InfantryLoadout(player : Player, private val label : String) {
+class Loadout(player : Player, private val label : String) {
/** the exo-suit */
private val exosuit : ExoSuitType.Value = player.ExoSuit
/** the MAX specialization, to differentiate the three types of MAXes who all use the same exo-suit name */
private val subtype =
if(exosuit == ExoSuitType.MAX) {
- import net.psforever.packet.game.objectcreate.ObjectClass
- player.Holsters().head.Equipment.get.Definition.ObjectId match {
- case ObjectClass.trhev_dualcycler | ObjectClass.nchev_scattercannon | ObjectClass.vshev_quasar =>
+ player.Holsters().head.Equipment.get.Definition match {
+ case GlobalDefinitions.trhev_dualcycler | GlobalDefinitions.nchev_scattercannon | GlobalDefinitions.vshev_quasar =>
1
- case ObjectClass.trhev_pounder | ObjectClass.nchev_falcon | ObjectClass.vshev_comet =>
+ case GlobalDefinitions.trhev_pounder | GlobalDefinitions.nchev_falcon | GlobalDefinitions.vshev_comet =>
2
- case ObjectClass.trhev_burster | ObjectClass.nchev_sparrow | ObjectClass.vshev_starfire =>
+ case GlobalDefinitions.trhev_burster | GlobalDefinitions.nchev_sparrow | GlobalDefinitions.vshev_starfire =>
3
case _ =>
0
@@ -56,14 +55,14 @@ class InfantryLoadout(player : Player, private val label : String) {
0
}
/** simplified representation of the holster `Equipment` */
- private val holsters : List[InfantryLoadout.SimplifiedEntry] =
- InfantryLoadout.packageSimplifications(player.Holsters())
+ private val holsters : List[Loadout.SimplifiedEntry] =
+ Loadout.packageSimplifications(player.Holsters())
/** simplified representation of the inventory `Equipment` */
- private val inventory : List[InfantryLoadout.SimplifiedEntry] =
- InfantryLoadout.packageSimplifications(player.Inventory.Items.values.toList)
+ private val inventory : List[Loadout.SimplifiedEntry] =
+ Loadout.packageSimplifications(player.Inventory.Items.values.toList)
/**
- * The label by which this `InfantryLoadout` is called.
+ * The label by which this `Loadout` is called.
* @return the label
*/
def Label : String = label
@@ -87,26 +86,26 @@ class InfantryLoadout(player : Player, private val label : String) {
def Subtype : Int = subtype
/**
- * The `Equipment` in the `Player`'s holster slots when this `InfantryLoadout` is created.
+ * The `Equipment` in the `Player`'s holster slots when this `Loadout` is created.
* @return a `List` of the holster item blueprints
*/
- def Holsters : List[InfantryLoadout.SimplifiedEntry] = holsters
+ def Holsters : List[Loadout.SimplifiedEntry] = holsters
/**
- * The `Equipment` in the `Player`'s inventory region when this `InfantryLoadout` is created.
+ * The `Equipment` in the `Player`'s inventory region when this `Loadout` is created.
* @return a `List` of the inventory item blueprints
*/
- def Inventory : List[InfantryLoadout.SimplifiedEntry] = inventory
+ def Inventory : List[Loadout.SimplifiedEntry] = inventory
}
-object InfantryLoadout {
+object Loadout {
/**
* A basic `Trait` connecting all of the `Equipment` blueprints.
*/
sealed trait Simplification
/**
- * An entry in the `InfantryLoadout`, wrapping around a slot index and what is in the slot index.
+ * An entry in the `Loadout`, wrapping around a slot index and what is in the slot index.
* @param item the `Equipment`
* @param index the slot number where the `Equipment` is to be stowed
* @see `InventoryItem`
@@ -163,7 +162,7 @@ object InfantryLoadout {
* @return a `List` of simplified `Equipment`
*/
private def packageSimplifications(equipment : List[InventoryItem]) : List[SimplifiedEntry] = {
- recursiveInventorySimplifications(equipment.iterator)
+ equipment.map(entry => { SimplifiedEntry(buildSimplification(entry.obj), entry.start) })
}
/**
@@ -193,23 +192,6 @@ object InfantryLoadout {
}
}
- /**
- * Traverse a `Player`'s inventory and transform `Equipment` into simplified blueprints.
- * @param iter an `Iterator`
- * @param list an updating `List` of simplified `Equipment` blueprints;
- * empty, by default
- * @return a `List` of simplified `Equipment` blueprints
- */
- @tailrec private def recursiveInventorySimplifications(iter : Iterator[InventoryItem], list : List[SimplifiedEntry] = Nil) : List[SimplifiedEntry] = {
- if(!iter.hasNext) {
- list
- }
- else {
- val entry = iter.next
- recursiveInventorySimplifications(iter, list :+ SimplifiedEntry(buildSimplification(entry.obj), entry.start))
- }
- }
-
/**
* Ammunition slots are internal connection points where `AmmoBox` units and their characteristics represent a `Tool`'s magazine.
* Their simplification process has a layer of complexity that ensures that the content of the slot matches the type of content that should be in the slot.
@@ -235,7 +217,7 @@ object InfantryLoadout {
else {
ShorthandAmmotSlot(
entry.AmmoTypeIndex,
- ShorthandAmmoBox(AmmoBoxDefinition(entry.Tool.Definition.AmmoTypes(entry.Definition.AmmoTypeIndices.head).id), 1)
+ ShorthandAmmoBox(entry.Tool.AmmoTypes(entry.Definition.AmmoTypeIndices.head), 1)
)
}
recursiveFireModeSimplications(iter, list :+ fmodeSimp)
diff --git a/common/src/main/scala/net/psforever/objects/Player.scala b/common/src/main/scala/net/psforever/objects/Player.scala
index 15572f514..37c6a2859 100644
--- a/common/src/main/scala/net/psforever/objects/Player.scala
+++ b/common/src/main/scala/net/psforever/objects/Player.scala
@@ -32,7 +32,7 @@ class Player(private val name : String,
private var drawnSlot : Int = Player.HandsDownSlot
private var lastDrawnSlot : Int = 0
- private val loadouts : Array[Option[InfantryLoadout]] = Array.fill[Option[InfantryLoadout]](10)(None)
+ private val loadouts : Array[Option[Loadout]] = Array.fill[Option[Loadout]](10)(None)
private var bep : Long = 0
private var cep : Long = 0
@@ -230,10 +230,10 @@ class Player(private val name : String,
}
def SaveLoadout(label : String, line : Int) : Unit = {
- loadouts(line) = Some(new InfantryLoadout(this, label))
+ loadouts(line) = Some(new Loadout(this, label))
}
- def LoadLoadout(line : Int) : Option[InfantryLoadout] = loadouts(line)
+ def LoadLoadout(line : Int) : Option[Loadout] = loadouts(line)
def DeleteLoadout(line : Int) : Unit = {
loadouts(line) = None
@@ -551,7 +551,7 @@ object Player {
player.ExoSuit = eSuit
//inventory
player.Inventory.Clear()
- player.Inventory.Resize(esuitDef.InventoryScale.width, esuitDef.InventoryScale.height)
+ player.Inventory.Resize(esuitDef.InventoryScale.Width, esuitDef.InventoryScale.Height)
player.Inventory.Offset = esuitDef.InventoryOffset
//holsters
(0 until 5).foreach(index => { player.Slot(index).Size = esuitDef.Holster(index) })
diff --git a/common/src/main/scala/net/psforever/objects/Tool.scala b/common/src/main/scala/net/psforever/objects/Tool.scala
index 85b2c484c..068f13a0d 100644
--- a/common/src/main/scala/net/psforever/objects/Tool.scala
+++ b/common/src/main/scala/net/psforever/objects/Tool.scala
@@ -1,9 +1,8 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects
-import net.psforever.objects.definition.{AmmoBoxDefinition, ToolDefinition}
+import net.psforever.objects.definition.ToolDefinition
import net.psforever.objects.equipment.{Ammo, Equipment, FireModeDefinition, FireModeSwitch}
-import net.psforever.packet.game.PlanetSideGUID
import scala.annotation.tailrec
@@ -13,14 +12,15 @@ import scala.annotation.tailrec
* "Tool" is a very mechanical name while this class is intended for various weapons and support items.
* The primary trait of a `Tool` is that it has something that counts as an "ammunition,"
* depleted as the `Tool` is used, replaceable as long as one has an appropriate type of `AmmoBox` object.
- * (The former is always called "consuming;" the latter, "reloading.")
- *
+ * (The former is always called "consuming;" the latter, "reloading.")
* Some weapons Chainblade have ammunition but do not consume it.
* @param toolDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
*/
class Tool(private val toolDef : ToolDefinition) extends Equipment with FireModeSwitch[FireModeDefinition] {
+ /** index of the current fire mode on the `ToolDefinition`'s list of fire modes */
private var fireModeIndex : Int = 0
- private val ammoSlot : List[Tool.FireModeSlot] = Tool.LoadDefinition(this)
+ /** current ammunition slot being used by this fire mode */
+ private val ammoSlots : List[Tool.FireModeSlot] = Tool.LoadDefinition(this)
def FireModeIndex : Int = fireModeIndex
@@ -36,24 +36,24 @@ class Tool(private val toolDef : ToolDefinition) extends Equipment with FireMode
FireMode
}
- def AmmoTypeIndex : Int = ammoSlot(fireModeIndex).AmmoTypeIndex
+ def AmmoTypeIndex : Int = FireMode.AmmoTypeIndices(AmmoSlot.AmmoTypeIndex)
def AmmoTypeIndex_=(index : Int) : Int = {
- ammoSlot(fireModeIndex).AmmoTypeIndex = index % FireMode.AmmoTypeIndices.length
+ AmmoSlot.AmmoTypeIndex = index % FireMode.AmmoTypeIndices.length
AmmoTypeIndex
}
- def AmmoType : Ammo.Value = toolDef.AmmoTypes(AmmoTypeIndex)
+ def AmmoType : Ammo.Value = toolDef.AmmoTypes(AmmoTypeIndex).AmmoType
def NextAmmoType : Ammo.Value = {
- AmmoTypeIndex = AmmoTypeIndex + 1
+ AmmoSlot.AmmoTypeIndex = AmmoSlot.AmmoTypeIndex + 1
AmmoType
}
- def Magazine : Int = ammoSlot(fireModeIndex).Magazine
+ def Magazine : Int = AmmoSlot.Magazine
def Magazine_=(mag : Int) : Int = {
- ammoSlot(fireModeIndex).Magazine = Math.min(Math.max(0, mag), MaxMagazine)
+ AmmoSlot.Magazine = Math.min(Math.max(0, mag), MaxMagazine)
Magazine
}
@@ -61,15 +61,15 @@ class Tool(private val toolDef : ToolDefinition) extends Equipment with FireMode
def NextDischarge : Int = math.min(Magazine, FireMode.Chamber)
- def AmmoSlots : List[Tool.FireModeSlot] = ammoSlot
+ def AmmoSlot : Tool.FireModeSlot = ammoSlots(FireMode.AmmoSlotIndex)
- def MaxAmmoSlot : Int = ammoSlot.length
+ def AmmoSlots : List[Tool.FireModeSlot] = ammoSlots
+
+ def MaxAmmoSlot : Int = ammoSlots.length
def Definition : ToolDefinition = toolDef
- override def toString : String = {
- Tool.toString(this)
- }
+ override def toString : String = Tool.toString(this)
}
object Tool {
@@ -77,12 +77,6 @@ object Tool {
new Tool(toolDef)
}
- def apply(guid : PlanetSideGUID, toolDef : ToolDefinition) : Tool = {
- val obj = new Tool(toolDef)
- obj.GUID = guid
- obj
- }
-
/**
* Use the `*Definition` that was provided to this object to initialize its fields and settings.
* @param tool the `Tool` being initialized
@@ -90,10 +84,10 @@ object Tool {
def LoadDefinition(tool : Tool) : List[FireModeSlot] = {
val tdef : ToolDefinition = tool.Definition
val maxSlot = tdef.FireModes.maxBy(fmode => fmode.AmmoSlotIndex).AmmoSlotIndex
- buildFireModes(tool, (0 to maxSlot).iterator, tdef.FireModes.toList)
+ buildFireModes(tdef, (0 to maxSlot).iterator, tdef.FireModes.toList)
}
- @tailrec private def buildFireModes(tool : Tool, iter : Iterator[Int], fmodes : List[FireModeDefinition], list : List[FireModeSlot] = Nil) : List[FireModeSlot] = {
+ @tailrec private def buildFireModes(tdef : ToolDefinition, iter : Iterator[Int], fmodes : List[FireModeDefinition], list : List[FireModeSlot] = Nil) : List[FireModeSlot] = {
if(!iter.hasNext) {
list
}
@@ -101,9 +95,9 @@ object Tool {
val index = iter.next
fmodes.filter(fmode => fmode.AmmoSlotIndex == index) match {
case fmode :: _ =>
- buildFireModes(tool, iter, fmodes, list :+ new FireModeSlot(tool, fmode))
+ buildFireModes(tdef, iter, fmodes, list :+ new FireModeSlot(tdef, fmode))
case Nil =>
- throw new IllegalArgumentException(s"tool ${tool.Definition.Name} ammo slot #$index is missing a fire mode specification; do not skip")
+ throw new IllegalArgumentException(s"tool ${tdef.Name} ammo slot #$index is missing a fire mode specification; do not skip")
}
}
}
@@ -113,32 +107,45 @@ object Tool {
}
/**
- * A hidden class that manages the specifics of the given ammunition for the current fire mode of this tool.
- * It operates much closer to an "ammunition feed" rather than a fire mode.
- * The relationship to fire modes is at least one-to-one and at most one-to-many.
+ * The `FireModeSlot` can be called the "magazine feed," an abstracted "ammunition slot."
+ * Most weapons will have only one ammunition slot and swap different ammunition into it as needed.
+ * In general to swap ammunition means to unload the onld ammunition and load the new ammunition.
+ * Many weapons also have one ammunition slot and multiple fire modes using the same list of ammunition
+ * This slot manages either of two ammunitions where one does not need to unload to be swapped to the other;
+ * however, the fire mod has most likely been changed.
+ * The Punisher -
+ * six ammunition types in total,
+ * two uniquely different types without unloading,
+ * two exclusive groups of ammunition divided into 2 cycled types and 4 cycled types -
+ * is an example of a weapon that benefits from this implementation.
*/
- class FireModeSlot(private val tool : Tool, private val fdef : FireModeDefinition) {
- /*
- By way of demonstration:
- Suppressors have one fire mode, two types of ammunition, one slot (2)
- MA Pistols have two fire modes, one type of ammunition, one slot (1)
- Jackhammers have two fire modes, two types of ammunition, one slot (2)
- Punishers have two fire modes, five types of ammunition, two slots (2, 3)
- */
-
- /** if this fire mode has multiple types of ammunition */
- private var ammoTypeIndex : Int = fdef.AmmoTypeIndices.head
- /** a reference to the actual `AmmoBox` of this slot; will not synch up with `AmmoType` immediately */
- private var box : AmmoBox = AmmoBox(AmmoBoxDefinition(AmmoType)) //defaults to box of one round of the default type for this slot
+ class FireModeSlot(private val tdef : ToolDefinition, private val fdef : FireModeDefinition) {
+ /**
+ * if this fire mode has multiple types of ammunition
+ * this is the index of the fire mode's ammo List, not a reference to the tool's ammo List
+ */
+ private var ammoTypeIndex : Int = 0
+ /** a reference to the actual `AmmoBox` of this slot */
+ private var box : AmmoBox = AmmoBox(tdef.AmmoTypes(ammoTypeIndex), fdef.Magazine)
def AmmoTypeIndex : Int = ammoTypeIndex
def AmmoTypeIndex_=(index : Int) : Int = {
- ammoTypeIndex = index
+ ammoTypeIndex = index % fdef.AmmoTypeIndices.length
AmmoTypeIndex
}
- def AmmoType : Ammo.Value = tool.Definition.AmmoTypes(ammoTypeIndex)
+ /**
+ * This is a reference to the `Ammo.Value` whose `AmmoBoxDefinition` should be loaded into `box`.
+ * It may not be the correct `Ammo.Value` whose `AmmoBoxDefinition` is loaded into `box` such as is the case during ammunition swaps.
+ * Generally, convert from this index, to the index in the fire mode's ammunition list, to the index in the `ToolDefinition`'s ammunition list.
+ * @return the `Ammo` type that should be loaded into the magazine right now
+ */
+ def AmmoType : Ammo.Value = tdef.AmmoTypes(fdef.AmmoTypeIndices(ammoTypeIndex)).AmmoType
+
+ def AllAmmoTypes : List[Ammo.Value] = {
+ fdef.AmmoTypeIndices.map(index => tdef.AmmoTypes(fdef.AmmoTypeIndices(index)).AmmoType).toList
+ }
def Magazine : Int = box.Capacity
@@ -159,7 +166,7 @@ object Tool {
}
}
- def Tool : Tool = tool
+ def Tool : ToolDefinition = tdef
def Definition : FireModeDefinition = fdef
}
diff --git a/common/src/main/scala/net/psforever/objects/Vehicle.scala b/common/src/main/scala/net/psforever/objects/Vehicle.scala
index 19f0101db..1d6acb114 100644
--- a/common/src/main/scala/net/psforever/objects/Vehicle.scala
+++ b/common/src/main/scala/net/psforever/objects/Vehicle.scala
@@ -3,7 +3,7 @@ package net.psforever.objects
import net.psforever.objects.definition.VehicleDefinition
import net.psforever.objects.equipment.{Equipment, EquipmentSize}
-import net.psforever.objects.inventory.GridInventory
+import net.psforever.objects.inventory.{GridInventory, InventoryTile}
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.vehicles.{AccessPermissionGroup, Seat, Utility, VehicleLockState}
import net.psforever.packet.game.PlanetSideGUID
@@ -480,8 +480,12 @@ object Vehicle {
vehicle.Utilities += Utility.Select(i, vehicle)
}
//trunk
- vehicle.trunk.Resize(vdef.TrunkSize.width, vdef.TrunkSize.height)
- vehicle.trunk.Offset = vdef.TrunkOffset
+ vdef.TrunkSize match {
+ case InventoryTile.None => ;
+ case dim =>
+ vehicle.trunk.Resize(dim.Width, dim.Height)
+ vehicle.trunk.Offset = vdef.TrunkOffset
+ }
vehicle
}
diff --git a/common/src/main/scala/net/psforever/objects/definition/ToolDefinition.scala b/common/src/main/scala/net/psforever/objects/definition/ToolDefinition.scala
index 2dbb7303e..f40e3946a 100644
--- a/common/src/main/scala/net/psforever/objects/definition/ToolDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/definition/ToolDefinition.scala
@@ -2,17 +2,17 @@
package net.psforever.objects.definition
import net.psforever.objects.definition.converter.ToolConverter
-import net.psforever.objects.equipment.{Ammo, FireModeDefinition}
+import net.psforever.objects.equipment.FireModeDefinition
import scala.collection.mutable
class ToolDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
- private val ammoTypes : mutable.ListBuffer[Ammo.Value] = new mutable.ListBuffer[Ammo.Value]
+ private val ammoTypes : mutable.ListBuffer[AmmoBoxDefinition] = new mutable.ListBuffer[AmmoBoxDefinition]
private val fireModes : mutable.ListBuffer[FireModeDefinition] = new mutable.ListBuffer[FireModeDefinition]
Name = "tool"
Packet = new ToolConverter()
- def AmmoTypes : mutable.ListBuffer[Ammo.Value] = ammoTypes
+ def AmmoTypes : mutable.ListBuffer[AmmoBoxDefinition] = ammoTypes
def FireModes : mutable.ListBuffer[FireModeDefinition] = fireModes
}
diff --git a/common/src/main/scala/net/psforever/objects/equipment/Ammo.scala b/common/src/main/scala/net/psforever/objects/equipment/Ammo.scala
index e7228abcb..55bf072a4 100644
--- a/common/src/main/scala/net/psforever/objects/equipment/Ammo.scala
+++ b/common/src/main/scala/net/psforever/objects/equipment/Ammo.scala
@@ -43,7 +43,7 @@ object Ammo extends Enumeration {
final val fluxpod_ammo = Value(310)
final val frag_cartridge = Value(327)
final val frag_grenade_ammo = Value(331)
- final val gauss_cannon_ammo = Value(345)
+ final val gauss_cannon_ammo = Value(347)
final val grenade = Value(370)
final val health_canister = Value(389)
final val heavy_grenade_mortar = Value(391)
diff --git a/common/src/main/scala/net/psforever/objects/equipment/FireModeSwitch.scala b/common/src/main/scala/net/psforever/objects/equipment/FireModeSwitch.scala
index 6a3596cc5..82bc4ff8a 100644
--- a/common/src/main/scala/net/psforever/objects/equipment/FireModeSwitch.scala
+++ b/common/src/main/scala/net/psforever/objects/equipment/FireModeSwitch.scala
@@ -18,4 +18,4 @@ trait FireModeSwitch[Mode] {
def FireMode : Mode
def NextFireMode : Mode
-}
\ No newline at end of file
+}
diff --git a/common/src/main/scala/net/psforever/objects/inventory/GridInventory.scala b/common/src/main/scala/net/psforever/objects/inventory/GridInventory.scala
index b513ea553..f5db0b38a 100644
--- a/common/src/main/scala/net/psforever/objects/inventory/GridInventory.scala
+++ b/common/src/main/scala/net/psforever/objects/inventory/GridInventory.scala
@@ -68,7 +68,7 @@ class GridInventory {
* @return the number of free cells
*/
def Capacity : Int = {
- TotalCapacity - items.values.foldLeft(0)((cnt, item) => cnt + (item.obj.Tile.width * item.obj.Tile.height))
+ TotalCapacity - items.values.foldLeft(0)((cnt, item) => cnt + (item.obj.Tile.Width * item.obj.Tile.Height))
}
/**
@@ -112,7 +112,7 @@ class GridInventory {
*/
def CheckCollisions(start : Int, item : Equipment) : Try[List[Int]] = {
val tile : InventoryTile = item.Tile
- CheckCollisions(start, tile.width, tile.height)
+ CheckCollisions(start, tile.Width, tile.Height)
}
/**
@@ -185,8 +185,8 @@ class GridInventory {
val itemx : Int = actualItemStart % width
val itemy : Int = actualItemStart / width
val tile = item.obj.Tile
- val clipsOnX : Boolean = if(itemx < startx) { itemx + tile.width > startx } else { itemx <= startw }
- val clipsOnY : Boolean = if(itemy < starty) { itemy + tile.height > starty } else { itemy <= starth }
+ val clipsOnX : Boolean = if(itemx < startx) { itemx + tile.Width > startx } else { itemx <= startw }
+ val clipsOnY : Boolean = if(itemy < starty) { itemy + tile.Height > starty } else { itemy <= starth }
if(clipsOnX && clipsOnY) {
collisions += item
}
@@ -237,8 +237,8 @@ class GridInventory {
* @return the grid index of the upper left corner where equipment to which the `tile` belongs should be placed
*/
def Fit(tile : InventoryTile) : Option[Int] = {
- val tWidth = tile.width
- val tHeight = tile.height
+ val tWidth = tile.Width
+ val tHeight = tile.Height
val gridIter = (0 until (grid.length - (tHeight - 1) * width))
.filter(cell => grid(cell) == -1 && (width - cell%width >= tWidth))
.iterator
@@ -325,7 +325,7 @@ class GridInventory {
val card = InventoryItem(obj, start)
items += key -> card
val tile = obj.Tile
- SetCells(start, tile.width, tile.height, key)
+ SetCells(start, tile.Width, tile.Height, key)
true
case _ =>
false
@@ -348,7 +348,7 @@ class GridInventory {
items.remove(key) match {
case Some(item) =>
val tile = item.obj.Tile
- SetCells(item.start, tile.width, tile.height)
+ SetCells(item.start, tile.Width, tile.Height)
true
case None =>
false
@@ -362,7 +362,7 @@ class GridInventory {
case Some(index) =>
val item = items.remove(index).get
val tile = item.obj.Tile
- SetCells(item.start, tile.width, tile.height)
+ SetCells(item.start, tile.Width, tile.Height)
true
case None =>
false
@@ -492,11 +492,11 @@ object GridInventory {
(a, b) => {
val aTile = a.obj.Tile
val bTile = b.obj.Tile
- if(aTile.width == bTile.width) {
- aTile.height > bTile.height
+ if(aTile.Width == bTile.Width) {
+ aTile.Height > bTile.Height
}
else {
- aTile.width > bTile.width
+ aTile.Width > bTile.Width
}
}
@@ -513,9 +513,9 @@ object GridInventory {
private def sortKnapsack(list : List[InventoryItem], width : Int, height : Int) : Unit = {
val root = new KnapsackNode(0, 0, width, height)
list.foreach(item => {
- findKnapsackSpace(root, item.obj.Tile.width, item.obj.Tile.height) match {
+ findKnapsackSpace(root, item.obj.Tile.Width, item.obj.Tile.Height) match {
case Some(node) =>
- splitKnapsackSpace(node, item.obj.Tile.width, item.obj.Tile.height)
+ splitKnapsackSpace(node, item.obj.Tile.Width, item.obj.Tile.Height)
item.start = node.y * width + node.x
case _ => ;
item.start = -1
diff --git a/common/src/main/scala/net/psforever/objects/inventory/InventoryTile.scala b/common/src/main/scala/net/psforever/objects/inventory/InventoryTile.scala
index c860a0c32..ea0b58c3e 100644
--- a/common/src/main/scala/net/psforever/objects/inventory/InventoryTile.scala
+++ b/common/src/main/scala/net/psforever/objects/inventory/InventoryTile.scala
@@ -8,7 +8,7 @@ package net.psforever.objects.inventory
* @param height the height of the tile
* @throws IllegalArgumentException if either the width or the height are less than zero
*/
-class InventoryTile(val width : Int, val height : Int) {
+class InventoryTile(private val width : Int, private val height : Int) {
if(width < 0 || height < 0)
throw new IllegalArgumentException(s"tile has no area - width: $width, height: $height")
@@ -19,15 +19,27 @@ class InventoryTile(val width : Int, val height : Int) {
object InventoryTile {
final val None = InventoryTile(0,0) //technically invalid; used to indicate a vehicle with no trunk
- final val Tile11 = InventoryTile(1,1) //placeholder size
+ final val Tile11 = InventoryTile(1,1) //occasional placeholder
final val Tile22 = InventoryTile(2,2) //grenades, boomer trigger
final val Tile23 = InventoryTile(2,3) //canister ammo
final val Tile42 = InventoryTile(4,2) //medkit
final val Tile33 = InventoryTile(3,3) //ammo box, pistols, ace
final val Tile44 = InventoryTile(4,4) //large ammo box
final val Tile55 = InventoryTile(5,5) //bfr ammo box
+ final val Tile66 = InventoryTile(6,6) //standard assault inventory
final val Tile63 = InventoryTile(6,3) //rifles
final val Tile93 = InventoryTile(9,3) //long-body weapons
+ final val Tile96 = InventoryTile(9,6) //standard exo-suit
+ final val Tile99 = InventoryTile(9,9) //agile exo-suit
+ final val Tile1107 = InventoryTile(11, 7) //uncommon small trunk capacity - phantasm
+ final val Tile1111 = InventoryTile(11,11) //common small trunk capacity
+ final val Tile1209 = InventoryTile(12, 9) //reinforced exo-suit
+ final val Tile1511 = InventoryTile(15,11) //common medium trunk capacity
+ final val Tile1515 = InventoryTile(15,15) //common large trunk capacity
+ final val Tile1611 = InventoryTile(16,11) //uncommon medium trunk capacity - vulture
+ final val Tile1612 = InventoryTile(16,12) //MAX; uncommon medium trunk capacity - lodestar
+ final val Tile1816 = InventoryTile(18,16) //uncommon massive trunk capacity - galaxy_gunship
+ final val Tile2016 = InventoryTile(20,16) //uncommon massive trunk capacity - apc
def apply(w : Int, h : Int) : InventoryTile = {
new InventoryTile(w, h)
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala b/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala
index f44975444..b81d8e0f6 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/PlanetSideServerObject.scala
@@ -24,7 +24,7 @@ abstract class PlanetSideServerObject extends PlanetSideGameObject {
* @return the current internal `ActorRef`
*/
def Actor_=(control : ActorRef) : ActorRef = {
- if(actor == ActorRef.noSender) {
+ if(actor == ActorRef.noSender || control == ActorRef.noSender) {
actor = control
}
actor
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/builders/VehicleSpawnPadObjectBuilder.scala b/common/src/main/scala/net/psforever/objects/serverobject/builders/VehicleSpawnPadObjectBuilder.scala
new file mode 100644
index 000000000..d50ecd248
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/builders/VehicleSpawnPadObjectBuilder.scala
@@ -0,0 +1,35 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.builders
+
+import akka.actor.Props
+import net.psforever.objects.definition.ObjectDefinition
+import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
+
+/**
+ * Wrapper `Class` designed to instantiate a `VehicleSpawnPad` server object.
+ * @param spdef an `ObjectDefinition` object ...
+ * @param id the globally unique identifier to which this `VehicleSpawnPad` will be registered
+ */
+class VehicleSpawnPadObjectBuilder(private val spdef : ObjectDefinition, private val id : Int) extends ServerObjectBuilder[VehicleSpawnPad] {
+ import akka.actor.ActorContext
+ import net.psforever.objects.guid.NumberPoolHub
+
+ def Build(implicit context : ActorContext, guid : NumberPoolHub) : VehicleSpawnPad = {
+ val obj = VehicleSpawnPad(spdef)
+ guid.register(obj, id) //non-Actor GUID registration
+ obj.Actor = context.actorOf(Props(classOf[VehicleSpawnControl], obj), s"${spdef.Name}_${obj.GUID.guid}")
+ obj
+ }
+}
+
+object VehicleSpawnPadObjectBuilder {
+ /**
+ * Overloaded constructor for a `DoorObjectBuilder`.
+ * @param spdef an `ObjectDefinition` object
+ * @param id a globally unique identifier
+ * @return a `VehicleSpawnPadObjectBuilder` object
+ */
+ def apply(spdef : ObjectDefinition, id : Int) : VehicleSpawnPadObjectBuilder = {
+ new VehicleSpawnPadObjectBuilder(spdef, id)
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnControl.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnControl.scala
new file mode 100644
index 000000000..412774bf1
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnControl.scala
@@ -0,0 +1,203 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.pad
+
+import akka.actor.{Actor, ActorRef, Cancellable}
+import net.psforever.objects.{DefaultCancellable, Player, Vehicle}
+import net.psforever.types.Vector3
+
+import scala.concurrent.duration._
+
+/**
+ * An `Actor` that handles messages being dispatched to a specific `VehicleSpawnPad`.
+ *
+ * A spawn pad receives vehicle orders from an attached `Terminal` object.
+ * At the time when the order is received, the player who submitted the order is completely visible
+ * and waiting back by the said `Terminal` from where the order was submitted.
+ * Assuming no other orders are currently being processed, the repeated self message will retrieve this as the next order.
+ * The player character is first made transparent with a `GenericObjectActionMessage` packet.
+ * The vehicle model itself is then introduced to the game and three things happen with the following order, more or less:
+ * 1. the vehicle is attached to a lifting platform that is designed to introduce the vehicle;
+ * 2. the player is seated in the vehicle's driver seat (seat 0) and is thus declared the owner;
+ * 3. various properties of the player, the vehicle, and the spawn pad itself are set `PlanetsideAttributesMessage`.
+ * When this step is finished, the lifting platform raises the vehicle and the mounted player into the game world.
+ * The vehicle detaches and is made to roll off the spawn pad a certain distance before being released to user control.
+ * That is what is supposed to happen within a certain measure of timing.
+ *
+ * The orders that are submitted to the spawn pad must be composed of at least three elements:
+ * 1. a player, specifically the one that submitted the order and will be declared the "owner;"
+ * 2. a vehicle;
+ * 3. a callback location for sending messages.
+ * @param pad the `VehicleSpawnPad` object being governed
+ */
+class VehicleSpawnControl(pad : VehicleSpawnPad) extends Actor {
+ /** an executor for progressing a vehicle order through the normal spawning logic */
+ private var process : Cancellable = DefaultCancellable.obj
+ /** a list of vehicle orders that have been submitted for this spawn pad */
+ private var orders : List[VehicleSpawnControl.OrderEntry] = List.empty[VehicleSpawnControl.OrderEntry]
+ /** the current vehicle order being acted upon */
+ private var trackedOrder : Option[VehicleSpawnControl.OrderEntry] = None
+ /** how many times a spawned vehicle (spatially) disrupted the next vehicle from being spawned */
+ private var blockingViolations : Int = 0
+ private[this] val log = org.log4s.getLogger
+ private[this] def trace(msg : String) : Unit = log.trace(msg)
+
+
+ def receive : Receive = {
+ case VehicleSpawnPad.VehicleOrder(player, vehicle) =>
+ trace(s"order from $player for $vehicle received")
+ orders = orders :+ VehicleSpawnControl.OrderEntry(player, vehicle, sender)
+ if(trackedOrder.isEmpty && orders.length == 1) {
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+
+ case VehicleSpawnControl.Process.GetOrder =>
+ process.cancel
+ blockingViolations = 0
+ val (completeOrder, remainingOrders) : (Option[VehicleSpawnControl.OrderEntry], List[VehicleSpawnControl.OrderEntry]) = orders match {
+ case x :: Nil =>
+ (Some(x), Nil)
+ case x :: b =>
+ (Some(x), b)
+ case Nil =>
+ (None, Nil)
+ }
+ orders = remainingOrders
+ completeOrder match {
+ case Some(entry) =>
+ trace(s"processing order $entry")
+ trackedOrder = completeOrder
+ import scala.concurrent.ExecutionContext.Implicits.global
+ process = context.system.scheduler.scheduleOnce(VehicleSpawnControl.concealPlayerTimeout, self, VehicleSpawnControl.Process.ConcealPlayer)
+ case None => ;
+ }
+
+ case VehicleSpawnControl.Process.ConcealPlayer =>
+ process.cancel
+ trackedOrder match {
+ case Some(entry) =>
+ if(entry.player.isAlive && entry.vehicle.Actor != ActorRef.noSender && entry.sendTo != ActorRef.noSender && entry.player.VehicleSeated.isEmpty) {
+ trace(s"hiding player: ${entry.player}")
+ entry.sendTo ! VehicleSpawnPad.ConcealPlayer
+ import scala.concurrent.ExecutionContext.Implicits.global
+ process = context.system.scheduler.scheduleOnce(VehicleSpawnControl.loadVehicleTimeout, self, VehicleSpawnControl.Process.LoadVehicle)
+ }
+ else {
+ trace("integral component lost; abort order fulfillment")
+ //TODO Unregister vehicle ... somehow
+ trackedOrder = None
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+ case None =>
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+
+ case VehicleSpawnControl.Process.LoadVehicle =>
+ process.cancel
+ trackedOrder match {
+ case Some(entry) =>
+ if(entry.vehicle.Actor != ActorRef.noSender && entry.sendTo != ActorRef.noSender) {
+ trace(s"loading vehicle: ${entry.vehicle} defined in order")
+ entry.sendTo ! VehicleSpawnPad.LoadVehicle(entry.vehicle, pad)
+ import scala.concurrent.ExecutionContext.Implicits.global
+ process = context.system.scheduler.scheduleOnce(VehicleSpawnControl.awaitSeatedTimeout, self, VehicleSpawnControl.Process.AwaitSeated)
+ }
+ else {
+ trace("owner or vehicle lost; abort order fulfillment")
+ //TODO Unregister vehicle ... somehow
+ trackedOrder = None
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+
+ case None =>
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+
+ case VehicleSpawnControl.Process.AwaitSeated =>
+ process.cancel
+ trackedOrder match {
+ case Some(entry) =>
+ if(entry.sendTo != ActorRef.noSender) {
+ trace("owner seated in vehicle")
+ import scala.concurrent.ExecutionContext.Implicits.global
+ process = if(entry.player.VehicleOwned.contains(entry.vehicle.GUID)) {
+ entry.sendTo ! VehicleSpawnPad.PlayerSeatedInVehicle(entry.vehicle)
+ context.system.scheduler.scheduleOnce(VehicleSpawnControl.awaitClearanceTimeout, self, VehicleSpawnControl.Process.AwaitClearance)
+ }
+ else {
+ context.system.scheduler.scheduleOnce(VehicleSpawnControl.awaitSeatedTimeout, self, VehicleSpawnControl.Process.AwaitSeated)
+ }
+ }
+ else {
+ trace("owner lost; abort order fulfillment")
+ trackedOrder = None
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+ case None =>
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+
+ //TODO raise spawn pad rails from ground
+
+ //TODO start auto drive away
+
+ //TODO release auto drive away
+
+ case VehicleSpawnControl.Process.AwaitClearance =>
+ process.cancel
+ trackedOrder match {
+ case Some(entry) =>
+ if(entry.sendTo == ActorRef.noSender || entry.vehicle.Actor == ActorRef.noSender) {
+ trace("integral component lost, but order fulfilled; process next order")
+ trackedOrder = None
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+ else if(Vector3.DistanceSquared(entry.vehicle.Position, pad.Position) > 100.0f) { //10m away from pad
+ trace("pad cleared; process next order")
+ trackedOrder = None
+ entry.sendTo ! VehicleSpawnPad.SpawnPadUnblocked(entry.vehicle.GUID)
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+ else {
+ trace(s"pad blocked by ${entry.vehicle} ...")
+ blockingViolations += 1
+ entry.sendTo ! VehicleSpawnPad.SpawnPadBlockedWarning(entry.vehicle, blockingViolations)
+ import scala.concurrent.ExecutionContext.Implicits.global
+ process = context.system.scheduler.scheduleOnce(VehicleSpawnControl.awaitClearanceTimeout, self, VehicleSpawnControl.Process.AwaitClearance)
+ }
+ case None =>
+ self ! VehicleSpawnControl.Process.GetOrder
+ }
+
+ case _ => ;
+ }
+}
+
+object VehicleSpawnControl {
+ final val concealPlayerTimeout : FiniteDuration = 2000000000L nanoseconds //2s
+ final val loadVehicleTimeout : FiniteDuration = 1000000000L nanoseconds //1s
+ final val awaitSeatedTimeout : FiniteDuration = 1000000000L nanoseconds //1s
+ final val awaitClearanceTimeout : FiniteDuration = 5000000000L nanoseconds //5s
+
+ /**
+ * An `Enumeration` of the stages of a full vehicle spawning process, associated with certain messages passed.
+ * Some stages are currently TEMPORARY.
+ * @see VehicleSpawnPad
+ */
+ object Process extends Enumeration {
+ val
+ GetOrder,
+ ConcealPlayer,
+ LoadVehicle,
+ AwaitSeated,
+ AwaitClearance
+ = Value
+ }
+
+ /**
+ * An entry that stores vehicle spawn pad spawning tasks (called "orders").
+ * @param player the player
+ * @param vehicle the vehicle
+ * @param sendTo a callback `Actor` associated with the player (in other words, `WorldSessionActor`)
+ */
+ private final case class OrderEntry(player : Player, vehicle : Vehicle, sendTo : ActorRef)
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnPad.scala b/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnPad.scala
new file mode 100644
index 000000000..f17ed5690
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/pad/VehicleSpawnPad.scala
@@ -0,0 +1,89 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.pad
+
+import net.psforever.objects.{Player, Vehicle}
+import net.psforever.objects.definition.ObjectDefinition
+import net.psforever.objects.serverobject.PlanetSideServerObject
+import net.psforever.packet.game.PlanetSideGUID
+
+/**
+ * A structure-owned server object that is a "spawn pad" for vehicles.
+ *
+ * Spawn pads have no purpose on their own but
+ * maintain the operative queue that introduces the vehicle into the game world and applies initial activity to it and
+ * maintain a position and a direction where the vehicle will be made to appear (as a `PlanetSideServerObject`).
+ * The actual functionality managed by this object is wholly found on its accompanying `Actor`.
+ * @param spDef the `ObjectDefinition` that constructs this object and maintains some of its immutable fields
+ * @see `VehicleSpawnControl`
+ */
+class VehicleSpawnPad(spDef : ObjectDefinition) extends PlanetSideServerObject {
+ def Definition : ObjectDefinition = spDef
+}
+
+object VehicleSpawnPad {
+
+ /**
+ * Communicate to the spawn pad that it should enqueue the following vehicle.
+ * This is the entry point to vehicle spawn pad functionality.
+ * @param player the player who submitted the order (the "owner")
+ * @param vehicle the vehicle produced from the order
+ */
+ final case class VehicleOrder(player : Player, vehicle : Vehicle)
+
+ /**
+ * The first callback step in spawning the vehicle.
+ * An packet `GenericObjectActionMessage(/player/, 36)`, when used on a player character,
+ * will cause that player character's model to fade into transparency.
+ */
+ final case class ConcealPlayer()
+
+ /**
+ * A callback step in spawning the vehicle.
+ * The vehicle is properly introduced into the game world.
+ * If information about the vehicle itself that is important to its spawning has not yet been set,
+ * this callback is the last ideal situation to set that properties without having to adjust the vehicle visually.
+ * The primary operation that should occur is a content-appropriate `ObjectCreateMessage` packet and
+ * having the player sit down in the driver's seat (seat 0) of the vehicle.
+ * @param vehicle the vehicle being spawned
+ * @param pad the pad
+ */
+ final case class LoadVehicle(vehicle : Vehicle, pad : VehicleSpawnPad)
+
+ /**
+ * A TEMPORARY callback step in spawning the vehicle.
+ * From a state of transparency, while the vehicle is attached to the lifting platform of the spawn pad,
+ * the player designated the "owner" by callback is made to sit in the driver's seat (always seat 0).
+ * This message is the next step after that.
+ * @param vehicle the vehicle being spawned
+ */
+ final case class PlayerSeatedInVehicle(vehicle : Vehicle)
+
+ /**
+ * A TEMPORARY callback step in (successfully) spawning the vehicle.
+ * While the vehicle is still occupying the pad just after being spawned and its driver seat mounted,
+ * that vehicle is considered blocking the pad from being used for further spawning operations.
+ * This message allows the user to be made known about this blockage.
+ * @param vehicle the vehicle
+ * @param warning_count the number of times a warning period has occurred
+ */
+ final case class SpawnPadBlockedWarning(vehicle : Vehicle, warning_count : Int)
+
+ /**
+ * A TEMPORARY callback step in (successfully) spawning the vehicle.
+ * While the vehicle is still occupying the pad just after being spawned and its driver seat mounted,
+ * that vehicle is considered blocking the pad from being used for further spawning operations.
+ * A timeout will begin counting until the vehicle is despawned automatically for its driver's negligence.
+ * This message is used to clear the deconstruction countdown, primarily.
+ * @param vehicle_guid the vehicle
+ */
+ final case class SpawnPadUnblocked(vehicle_guid : PlanetSideGUID)
+
+ /**
+ * Overloaded constructor.
+ * @param spDef the spawn pad's definition entry
+ * @return a `VehicleSpawnPad` object
+ */
+ def apply(spDef : ObjectDefinition) : VehicleSpawnPad = {
+ new VehicleSpawnPad(spDef)
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/AirVehicleTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/AirVehicleTerminalDefinition.scala
new file mode 100644
index 000000000..fd62de60c
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/AirVehicleTerminalDefinition.scala
@@ -0,0 +1,18 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.terminals
+
+import net.psforever.objects.Player
+import net.psforever.packet.game.ItemTransactionMessage
+
+class AirVehicleTerminalDefinition extends TerminalDefinition(43) {
+ Name = "air_vehicle_terminal"
+
+ def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
+ flight1Vehicles.get(msg.item_name) match {
+ case Some(vehicle) =>
+ Terminal.BuyVehicle(vehicle(), Nil)
+ case None =>
+ Terminal.NoDeal()
+ }
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/BFRTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/BFRTerminalDefinition.scala
new file mode 100644
index 000000000..263067491
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/BFRTerminalDefinition.scala
@@ -0,0 +1,19 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.terminals
+
+import net.psforever.objects.Player
+import net.psforever.packet.game.ItemTransactionMessage
+
+class BFRTerminalDefinition extends TerminalDefinition(143) {
+ Name = "bfr_terminal"
+
+ def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
+ bfrVehicles.get(msg.item_name) match {
+ case Some(vehicle) =>
+ //Terminal.BuyVehicle(vehicle, Nil)
+ Terminal.NoDeal()
+ case None =>
+ Terminal.NoDeal()
+ }
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/CertTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/CertTerminalDefinition.scala
index 8f990196e..a1583aa0c 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/CertTerminalDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/CertTerminalDefinition.scala
@@ -81,7 +81,7 @@ class CertTerminalDefinition extends TerminalDefinition(171) {
* @param msg the original packet carrying the request
* @return an actionable message that explains how to process the request
*/
- def Sell(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
+ override def Sell(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
certificationList.get(msg.item_name) match {
case Some((cert, cost)) =>
Terminal.SellCertification(cert, cost)
@@ -89,12 +89,4 @@ class CertTerminalDefinition extends TerminalDefinition(171) {
Terminal.NoDeal()
}
}
-
- /**
- * This action is not supported by this type of `Terminal`.
- * @param player the player
- * @param msg the original packet carrying the request
- * @return `Terminal.NoEvent` always
- */
- def Loadout(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = Terminal.NoDeal()
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/DropshipVehicleTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/DropshipVehicleTerminalDefinition.scala
new file mode 100644
index 000000000..7176f9785
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/DropshipVehicleTerminalDefinition.scala
@@ -0,0 +1,19 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.terminals
+
+import net.psforever.objects.Player
+import net.psforever.packet.game.ItemTransactionMessage
+
+class DropshipVehicleTerminalDefinition extends TerminalDefinition(263) {
+ private val flightVehicles = flight1Vehicles ++ flight2Vehicles
+ Name = "dropship_vehicle_terminal"
+
+ def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
+ flightVehicles.get(msg.item_name) match {
+ case Some(vehicle) =>
+ Terminal.BuyVehicle(vehicle(), Nil)
+ case None =>
+ Terminal.NoDeal()
+ }
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/GroundVehicleTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/GroundVehicleTerminalDefinition.scala
new file mode 100644
index 000000000..1087c575a
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/GroundVehicleTerminalDefinition.scala
@@ -0,0 +1,18 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.terminals
+
+import net.psforever.objects.Player
+import net.psforever.packet.game.ItemTransactionMessage
+
+class GroundVehicleTerminalDefinition extends TerminalDefinition(386) {
+ Name = "ground_vehicle_terminal"
+
+ def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
+ groundVehicles.get(msg.item_name) match {
+ case Some(vehicle) =>
+ Terminal.BuyVehicle(vehicle(), Nil)
+ case None =>
+ Terminal.NoDeal()
+ }
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/OrderTerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/OrderTerminalDefinition.scala
index cea418f0f..2735b1bb3 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/OrderTerminalDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/OrderTerminalDefinition.scala
@@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects.serverobject.terminals
-import net.psforever.objects.InfantryLoadout.Simplification
+import net.psforever.objects.Loadout.Simplification
import net.psforever.objects.{Player, Tool}
import net.psforever.objects.definition._
import net.psforever.objects.equipment.Equipment
@@ -13,7 +13,7 @@ import scala.annotation.switch
/**
* The definition for any `Terminal` that is of a type "order_terminal".
* `Buy` and `Sell` `Equipment` items and `AmmoBox` items.
- * Change `ExoSuitType` and retrieve `InfantryLoadout` entries.
+ * Change `ExoSuitType` and retrieve `Loadout` entries.
*/
class OrderTerminalDefinition extends TerminalDefinition(612) {
Name = "order_terminal"
@@ -75,19 +75,19 @@ class OrderTerminalDefinition extends TerminalDefinition(612) {
* @param msg the original packet carrying the request
* @return an actionable message that explains how to process the request
*/
- def Sell(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
+ override def Sell(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
Terminal.SellEquipment()
}
/**
* Process a `TransactionType.InfantryLoadout` action by the user.
- * `InfantryLoadout` objects are blueprints composed of exo-suit specifications and simplified `Equipment`-to-slot mappings.
+ * `Loadout` objects are blueprints composed of exo-suit specifications and simplified `Equipment`-to-slot mappings.
* If a valid loadout is found, its data is transformed back into actual `Equipment` for return to the user.
* @param player the player
* @param msg the original packet carrying the request
* @return an actionable message that explains how to process the request
*/
- def Loadout(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
+ override def Loadout(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
if(msg.item_page == 4) { //Favorites tab
player.LoadLoadout(msg.unk1) match {
case Some(loadout) =>
@@ -105,7 +105,7 @@ class OrderTerminalDefinition extends TerminalDefinition(612) {
/**
* Accept a simplified blueprint for some piece of `Equipment` and create an actual piece of `Equipment` based on it.
- * Used specifically for the reconstruction of `Equipment` via an `InfantryLoadout`.
+ * Used specifically for the reconstruction of `Equipment` via an `Loadout`.
* @param entry the simplified blueprint
* @return some `Equipment` object
* @see `TerminalDefinition.MakeTool`
@@ -115,7 +115,7 @@ class OrderTerminalDefinition extends TerminalDefinition(612) {
* `TerminalDefinition.MakeKit`
*/
private def BuildSimplifiedPattern(entry : Simplification) : Equipment = {
- import net.psforever.objects.InfantryLoadout._
+ import net.psforever.objects.Loadout._
entry match {
case obj : ShorthandTool =>
val ammo : List[AmmoBoxDefinition] = obj.ammo.map(fmode => { fmode.ammo.adef })
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala
index c6cba9f0c..554f09603 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/Terminal.scala
@@ -136,10 +136,24 @@ object Terminal {
final case class SellEquipment() extends Exchange
import net.psforever.types.CertificationType
+
+ /**
+ * Provide the certification type unlocked by the player.
+ * @param cert the certification unlocked
+ * @param cost the certification point cost
+ */
final case class LearnCertification(cert : CertificationType.Value, cost : Int) extends Exchange
+ /**
+ * Provide the certification type freed-up by the player.
+ * @param cert the certification returned
+ * @param cost the certification point cost
+ */
final case class SellCertification(cert : CertificationType.Value, cost : Int) extends Exchange
+ import net.psforever.objects.Vehicle
+ final case class BuyVehicle(vehicle : Vehicle, loadout: List[Any]) extends Exchange
+
/**
* Recover a former exo-suit and `Equipment` configuration that the `Player` possessed.
* A result of a processed request.
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalDefinition.scala
index 5cf8ff3d4..aa98b0f74 100644
--- a/common/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalDefinition.scala
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/TerminalDefinition.scala
@@ -8,10 +8,11 @@ import net.psforever.packet.game.ItemTransactionMessage
import net.psforever.types.ExoSuitType
/**
- * The definition for any `Terminal`.
+ * The basic definition for any `Terminal`.
* @param objectId the object's identifier number
*/
abstract class TerminalDefinition(objectId : Int) extends ObjectDefinition(objectId) {
+ private[this] val log = org.log4s.getLogger("TerminalDefinition")
Name = "terminal"
/**
@@ -22,12 +23,12 @@ abstract class TerminalDefinition(objectId : Int) extends ObjectDefinition(objec
/**
* The unimplemented functionality for this `Terminal`'s `TransactionType.Sell` activity.
*/
- def Sell(player: Player, msg : ItemTransactionMessage) : Terminal.Exchange
+ def Sell(player: Player, msg : ItemTransactionMessage) : Terminal.Exchange = Terminal.NoDeal()
/**
* The unimplemented functionality for this `Terminal`'s `TransactionType.InfantryLoadout` activity.
*/
- def Loadout(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange
+ def Loadout(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = Terminal.NoDeal()
/**
* A `Map` of information for changing exo-suits.
@@ -128,42 +129,42 @@ abstract class TerminalDefinition(objectId : Int) extends ObjectDefinition(objec
* value - a curried function that builds the object
*/
protected val infantryWeapons : Map[String, ()=>Equipment] = Map(
- "ilc9" -> MakeTool(ilc9, bullet_9mm),
- "repeater" -> MakeTool(repeater, bullet_9mm),
- "isp" -> MakeTool(isp, shotgun_shell), //amp
- "beamer" -> MakeTool(beamer, energy_cell),
- "suppressor" -> MakeTool(suppressor, bullet_9mm),
- "anniversary_guna" -> MakeTool(anniversary_guna, anniversary_ammo), //tr stinger
- "anniversary_gun" -> MakeTool(anniversary_gun, anniversary_ammo), //nc spear
- "anniversary_gunb" -> MakeTool(anniversary_gunb, anniversary_ammo), //vs eraser
- "cycler" -> MakeTool(cycler, bullet_9mm),
- "gauss" -> MakeTool(gauss, bullet_9mm),
- "pulsar" -> MakeTool(pulsar, energy_cell),
- "punisher" -> MakeTool(punisher, List(bullet_9mm, rocket)),
- "flechette" -> MakeTool(flechette, shotgun_shell),
- "spiker" -> MakeTool(spiker, ancient_ammo_combo),
- "frag_grenade" -> MakeTool(frag_grenade, frag_grenade_ammo),
- "jammer_grenade" -> MakeTool(jammer_grenade, jammer_grenade_ammo),
- "plasma_grenade" -> MakeTool(plasma_grenade, plasma_grenade_ammo),
- "katana" -> MakeTool(katana, melee_ammo),
- "chainblade" -> MakeTool(chainblade, melee_ammo),
- "magcutter" -> MakeTool(magcutter, melee_ammo),
- "forceblade" -> MakeTool(forceblade, melee_ammo),
- "mini_chaingun" -> MakeTool(mini_chaingun, bullet_9mm),
- "r_shotgun" -> MakeTool(r_shotgun, shotgun_shell), //jackhammer
- "lasher" -> MakeTool(lasher, energy_cell),
- "maelstrom" -> MakeTool(maelstrom, maelstrom_ammo),
- "striker" -> MakeTool(striker, striker_missile_ammo),
- "hunterseeker" -> MakeTool(hunterseeker, hunter_seeker_missile), //phoenix
- "lancer" -> MakeTool(lancer, lancer_cartridge),
- "phoenix" -> MakeTool(phoenix, phoenix_missile), //decimator
- "rocklet" -> MakeTool(rocklet, rocket),
- "thumper" -> MakeTool(thumper, frag_cartridge),
- "radiator" -> MakeTool(radiator, ancient_ammo_combo),
- "heavy_sniper" -> MakeTool(heavy_sniper, bolt), //hsr
- "bolt_driver" -> MakeTool(bolt_driver, bolt),
- "oicw" -> MakeTool(oicw, oicw_ammo), //scorpion
- "flamethrower" -> MakeTool(flamethrower, flamethrower_ammo)
+ "ilc9" -> MakeTool(ilc9),
+ "repeater" -> MakeTool(repeater),
+ "isp" -> MakeTool(isp), //amp
+ "beamer" -> MakeTool(beamer),
+ "suppressor" -> MakeTool(suppressor),
+ "anniversary_guna" -> MakeTool(anniversary_guna), //tr stinger
+ "anniversary_gun" -> MakeTool(anniversary_gun), //nc spear
+ "anniversary_gunb" -> MakeTool(anniversary_gunb), //vs eraser
+ "cycler" -> MakeTool(cycler),
+ "gauss" -> MakeTool(gauss),
+ "pulsar" -> MakeTool(pulsar),
+ "punisher" -> MakeTool(punisher),
+ "flechette" -> MakeTool(flechette),
+ "spiker" -> MakeTool(spiker),
+ "frag_grenade" -> MakeTool(frag_grenade),
+ "jammer_grenade" -> MakeTool(jammer_grenade),
+ "plasma_grenade" -> MakeTool(plasma_grenade),
+ "katana" -> MakeTool(katana),
+ "chainblade" -> MakeTool(chainblade),
+ "magcutter" -> MakeTool(magcutter),
+ "forceblade" -> MakeTool(forceblade),
+ "mini_chaingun" -> MakeTool(mini_chaingun),
+ "r_shotgun" -> MakeTool(r_shotgun), //jackhammer
+ "lasher" -> MakeTool(lasher),
+ "maelstrom" -> MakeTool(maelstrom),
+ "striker" -> MakeTool(striker),
+ "hunterseeker" -> MakeTool(hunterseeker), //phoenix
+ "lancer" -> MakeTool(lancer),
+ "phoenix" -> MakeTool(phoenix), //decimator
+ "rocklet" -> MakeTool(rocklet),
+ "thumper" -> MakeTool(thumper),
+ "radiator" -> MakeTool(radiator),
+ "heavy_sniper" -> MakeTool(heavy_sniper), //hsr
+ "bolt_driver" -> MakeTool(bolt_driver),
+ "oicw" -> MakeTool(oicw), //scorpion
+ "flamethrower" -> MakeTool(flamethrower)
)
/**
@@ -176,20 +177,98 @@ abstract class TerminalDefinition(objectId : Int) extends ObjectDefinition(objec
"super_medkit" -> MakeKit(super_medkit),
"super_armorkit" -> MakeKit(super_armorkit),
"super_staminakit" -> MakeKit(super_staminakit),
- "medicalapplicator" -> MakeTool(medicalapplicator, health_canister),
+ "medicalapplicator" -> MakeTool(medicalapplicator),
"bank" -> MakeTool(bank, armor_canister),
- "nano_dispenser" -> MakeTool(nano_dispenser, armor_canister),
+ "nano_dispenser" -> MakeTool(nano_dispenser),
//TODO "ace" -> MakeConstructionItem(ace),
//TODO "advanced_ace" -> MakeConstructionItem(advanced_ace),
"remote_electronics_kit" -> MakeSimpleItem(remote_electronics_kit),
- "trek" -> MakeTool(trek, trek_ammo),
+ "trek" -> MakeTool(trek),
"command_detonater" -> MakeSimpleItem(command_detonater),
"flail_targeting_laser" -> MakeSimpleItem(flail_targeting_laser)
)
+ /**
+ * A `Map` of operations for producing a ground-based `Vehicle`.
+ * key - an identification string sent by the client
+ * value - a curried function that builds the object
+ */
+ protected val groundVehicles : Map[String, ()=>Vehicle] = Map(
+ "quadassault" -> MakeVehicle(quadassault),
+ "fury" -> MakeVehicle(fury),
+ "quadstealth" -> MakeVehicle(quadstealth),
+ "ant" -> MakeVehicle(ant),
+ "ams" -> MakeVehicle(ams),
+ "mediumtransport" -> MakeVehicle(mediumtransport),
+ "two_man_assault_buggy" -> MakeVehicle(two_man_assault_buggy),
+ "skyguard" -> MakeVehicle(skyguard),
+ "lightning" -> MakeVehicle(lightning),
+ "threemanheavybuggy" -> MakeVehicle(threemanheavybuggy),
+ "battlewagon" -> MakeVehicle(battlewagon),
+ "apc_tr" -> MakeVehicle(apc_tr),
+ "prowler" -> MakeVehicle(prowler),
+ "twomanheavybuggy" -> MakeVehicle(twomanheavybuggy),
+ "thunderer" -> MakeVehicle(thunderer),
+ "apc_nc" -> MakeVehicle(apc_nc),
+ "vanguard" -> MakeVehicle(vanguard),
+ "twomanhoverbuggy" -> MakeVehicle(twomanhoverbuggy),
+ "aurora" -> MakeVehicle(aurora),
+ "apc_vs" -> MakeVehicle(apc_vs),
+ "magrider" -> MakeVehicle(magrider),
+ "flail" -> MakeVehicle(flail),
+ "switchblade" -> MakeVehicle(switchblade),
+ "router" -> MakeVehicle(router)
+ )
+
+ /**
+ * A `Map` of operations for producing most flight-based `Vehicle`.
+ * key - an identification string sent by the client
+ * value - a curried function that builds the object
+ */
+ protected val flight1Vehicles : Map[String, ()=>Vehicle] = Map(
+ "mosquito" -> MakeVehicle(mosquito),
+ "lightgunship" -> MakeVehicle(lightgunship),
+ "wasp" -> MakeVehicle(wasp),
+ "phantasm" -> MakeVehicle(phantasm),
+ "vulture" -> MakeVehicle(vulture),
+ "liberator" -> MakeVehicle(liberator)
+ )
+
+ /**
+ * A `Map` of operations for producing a flight-based `Vehicle` specific to the dropship terminal.
+ * key - an identification string sent by the client
+ * value - a curried function that builds the object
+ */
+ protected val flight2Vehicles : Map[String, ()=>Vehicle] = Map(
+ "dropship" -> MakeVehicle(dropship),
+ "galaxy_gunship" -> MakeVehicle(galaxy_gunship),
+ "lodestar" -> MakeVehicle(lodestar)
+ )
+
+ /**
+ * A `Map` of operations for producing a ground-based `Vehicle` specific to the bfr terminal.
+ * key - an identification string sent by the client
+ * value - a curried function that builds the object
+ */
+ protected val bfrVehicles : Map[String, ()=>Vehicle] = Map(
+// "colossus_gunner" -> (()=>Unit),
+// "colossus_flight" -> (()=>Unit),
+// "peregrine_gunner" -> (()=>Unit),
+// "peregrine_flight" -> (()=>Unit),
+// "aphelion_gunner" -> (()=>Unit),
+// "aphelion_flight" -> (()=>Unit)
+ )
+
/**
* Create a new `Tool` from provided `EquipmentDefinition` objects.
- * @param tdef the `ToolDefinition` objects
+ * @param tdef the `ToolDefinition` object
+ * @return a partial function that, when called, creates the piece of `Equipment`
+ */
+ protected def MakeTool(tdef : ToolDefinition)() : Tool = MakeTool(tdef, Nil)
+
+ /**
+ * Create a new `Tool` from provided `EquipmentDefinition` objects.
+ * @param tdef the `ToolDefinition` object
* @param adef an `AmmoBoxDefinition` object
* @return a partial function that, when called, creates the piece of `Equipment`
*/
@@ -200,24 +279,55 @@ abstract class TerminalDefinition(objectId : Int) extends ObjectDefinition(objec
* Only use this function to create default `Tools` with the default parameters.
* For example, loadouts can retain `Tool` information that utilizes alternate, valid ammunition types;
* and, this method function will not construct a complete object if provided that information.
- * @param tdef the `ToolDefinition` objects
+ * @param tdef the `ToolDefinition` object
* @param adefs a `List` of `AmmoBoxDefinition` objects
* @return a curried function that, when called, creates the piece of `Equipment`
* @see `GlobalDefinitions`
* @see `OrderTerminalDefinition.BuildSimplifiedPattern`
*/
- protected def MakeTool(tdef : ToolDefinition, adefs : List[AmmoBoxDefinition])() : Tool = {
+ protected def MakeTool(tdef : ToolDefinition, adefs : List[AmmoBoxDefinition])() : Tool = {
val obj = Tool(tdef)
- (0 until obj.MaxAmmoSlot).foreach(index => {
- val aType = adefs(index)
- val ammo = MakeAmmoBox(aType, Some(obj.Definition.FireModes(index).Magazine)) //make internal magazine, full
- (obj.AmmoSlots(index).Box = ammo) match {
- case Some(_) => ; //this means it worked
- case None =>
- org.log4s.getLogger("TerminalDefinition").warn(s"plans do not match definition: trying to feed ${ammo.AmmoType} ammunition into Tool (${obj.Definition.ObjectId} @ $index)")
+ adefs match {
+ case _ :: _ =>
+ LoadAmmunitionIntoWeapon(obj, adefs)
+ case Nil => ; //as-is
+ }
+ obj
+ }
+
+ /**
+ * Given a weapon, and custom ammunition profiles, attempt to load those boxes of ammunition into the weapon.
+ *
+ * This is a customization function that should normally go unused.
+ * All of the information necessary to generate a `Tool` from a `Terminal` request should be available on the `ToolDefinition` object.
+ * The ammunition information, regardless of "customization," must satisfy the type limits of the original definition.
+ * As thus, to introduce very strange ammunition to a give `Tool`,
+ * either the definition must be modified or a different definition must be used.
+ * The custom ammunition is organized into order of ammunition slots based on the `FireModeDefinition` objects.
+ * That is:
+ * the first custom element is processed by the first ammunition slot;
+ * the second custom element is processed by the second ammunition slot; and, so forth.
+ * @param weapon the `Tool` object
+ * @param adefs a sequential `List` of ammunition to be loaded into weapon
+ * @see `AmmoBoxDefinition`
+ * @see `FireModeDefinition`
+ */
+ private def LoadAmmunitionIntoWeapon(weapon : Tool, adefs : List[AmmoBoxDefinition]) : Unit = {
+ val definition = weapon.Definition
+ (0 until math.min(weapon.MaxAmmoSlot, adefs.length)).foreach(index => {
+ val ammoSlot = weapon.AmmoSlots(index)
+ adefs.lift(index) match {
+ case Some(aType) =>
+ ammoSlot.AllAmmoTypes.indexOf(aType.AmmoType) match {
+ case -1 =>
+ log.warn(s"terminal plans do not match definition: can not feed ${aType.AmmoType} ammunition into Tool (${definition.ObjectId} @ ammo $index)")
+ case n =>
+ ammoSlot.AmmoTypeIndex = n
+ ammoSlot.Box = MakeAmmoBox(aType, Some(definition.FireModes(index).Magazine)) //make new internal magazine, full
+ }
+ case None => ;
}
})
- obj
}
/**
@@ -229,11 +339,12 @@ abstract class TerminalDefinition(objectId : Int) extends ObjectDefinition(objec
* @see `GlobalDefinitions`
*/
protected def MakeAmmoBox(adef : AmmoBoxDefinition, capacity : Option[Int] = None)() : AmmoBox = {
- val obj = AmmoBox(adef)
- if(capacity.isDefined) {
- obj.Capacity = capacity.get
+ capacity match {
+ case Some(cap) =>
+ AmmoBox(adef, cap)
+ case None =>
+ AmmoBox(adef)
}
- obj
}
/**
@@ -259,4 +370,12 @@ abstract class TerminalDefinition(objectId : Int) extends ObjectDefinition(objec
* @see `GlobalDefinitions`
*/
protected def MakeConstructionItem(cdef : ConstructionItemDefinition)() : ConstructionItem = ConstructionItem(cdef)
+
+ /**
+ * Create a new `Vehicle` from provided `VehicleDefinition` objects.
+ * @param vdef the `VehicleDefinition` object
+ * @return a curried function that, when called, creates the `Vehicle`
+ * @see `GlobalDefinitions`
+ */
+ protected def MakeVehicle(vdef : VehicleDefinition)() : Vehicle = Vehicle(vdef)
}
diff --git a/common/src/main/scala/net/psforever/objects/serverobject/terminals/VehicleTerminalCombinedDefinition.scala b/common/src/main/scala/net/psforever/objects/serverobject/terminals/VehicleTerminalCombinedDefinition.scala
new file mode 100644
index 000000000..c069545a4
--- /dev/null
+++ b/common/src/main/scala/net/psforever/objects/serverobject/terminals/VehicleTerminalCombinedDefinition.scala
@@ -0,0 +1,19 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.objects.serverobject.terminals
+
+import net.psforever.objects.Player
+import net.psforever.packet.game.ItemTransactionMessage
+
+class VehicleTerminalCombinedDefinition extends TerminalDefinition(952) {
+ private val vehicles = groundVehicles ++ flight1Vehicles
+ Name = "vehicle_terminal_combined"
+
+ def Buy(player : Player, msg : ItemTransactionMessage) : Terminal.Exchange = {
+ vehicles.get(msg.item_name) match {
+ case Some(vehicle) =>
+ Terminal.BuyVehicle(vehicle(), Nil)
+ case None =>
+ Terminal.NoDeal()
+ }
+ }
+}
diff --git a/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala b/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala
index 022aa53d7..3e2a63fc3 100644
--- a/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/ZoneActor.scala
@@ -2,7 +2,6 @@
package net.psforever.objects.zones
import akka.actor.Actor
-import net.psforever.objects.serverobject.locks.IFFLock
/**
* na
@@ -35,8 +34,9 @@ class ZoneActor(zone : Zone) extends Actor {
}
})
- //check door to locks association
+ //check door to lock association
import net.psforever.objects.serverobject.doors.Door
+ import net.psforever.objects.serverobject.locks.IFFLock
map.DoorToLock.foreach({ case((door_guid, lock_guid)) =>
try {
if(!guid(door_guid).get.isInstanceOf[Door]) {
@@ -45,7 +45,7 @@ class ZoneActor(zone : Zone) extends Actor {
}
catch {
case _ : Exception =>
- slog.error(s"expected a door, but looking for uninitialized object $door_guid")
+ slog.error(s"expected a door at id $door_guid, but looking for uninitialized object")
}
try {
if(!guid(lock_guid).get.isInstanceOf[IFFLock]) {
@@ -54,7 +54,31 @@ class ZoneActor(zone : Zone) extends Actor {
}
catch {
case _ : Exception =>
- slog.error(s"expected an IFF locks, but looking for uninitialized object $lock_guid")
+ slog.error(s"expected an IFF locks at id $lock_guid, but looking for uninitialized object")
+ }
+ })
+
+ //check vehicle terminal to spawn pad association
+ import net.psforever.objects.serverobject.pad.VehicleSpawnPad
+ import net.psforever.objects.serverobject.terminals.Terminal
+ map.TerminalToSpawnPad.foreach({ case ((term_guid, pad_guid)) =>
+ try {
+ if(!guid(term_guid).get.isInstanceOf[Terminal]) { //TODO check is vehicle terminal
+ slog.error(s"expected id $term_guid to be a terminal, but it was not")
+ }
+ }
+ catch {
+ case _ : Exception =>
+ slog.error(s"expected a terminal at id $term_guid, but looking for uninitialized object")
+ }
+ try {
+ if(!guid(pad_guid).get.isInstanceOf[VehicleSpawnPad]) {
+ slog.error(s"expected id $pad_guid to be a spawn pad, but it was not")
+ }
+ }
+ catch {
+ case _ : Exception =>
+ slog.error(s"expected a spawn pad at id $pad_guid, but looking for uninitialized object")
}
})
}
diff --git a/common/src/main/scala/net/psforever/objects/zones/ZoneMap.scala b/common/src/main/scala/net/psforever/objects/zones/ZoneMap.scala
index dbec207ca..35d38fe96 100644
--- a/common/src/main/scala/net/psforever/objects/zones/ZoneMap.scala
+++ b/common/src/main/scala/net/psforever/objects/zones/ZoneMap.scala
@@ -25,6 +25,7 @@ import net.psforever.objects.serverobject.builders.ServerObjectBuilder
*/
class ZoneMap(private val name : String) {
private var localObjects : List[ServerObjectBuilder[_]] = List()
+ private var linkTerminalPad : Map[Int, Int] = Map()
private var linkDoorLock : Map[Int, Int] = Map()
private var linkObjectBase : Map[Int, Int] = Map()
private var numBases : Int = 0
@@ -64,7 +65,13 @@ class ZoneMap(private val name : String) {
def DoorToLock : Map[Int, Int] = linkDoorLock
- def DoorToLock(door_guid : Int, lock_guid : Int) = {
+ def DoorToLock(door_guid : Int, lock_guid : Int) : Unit = {
linkDoorLock = linkDoorLock ++ Map(door_guid -> lock_guid)
}
+
+ def TerminalToSpawnPad : Map[Int, Int] = linkTerminalPad
+
+ def TerminalToSpawnPad(terminal_guid : Int, pad_guid : Int) : Unit = {
+ linkTerminalPad = linkTerminalPad ++ Map(terminal_guid -> pad_guid)
+ }
}
diff --git a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala
index bec753054..bfc13b89f 100644
--- a/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala
+++ b/common/src/main/scala/net/psforever/packet/GamePacketOpcode.scala
@@ -420,7 +420,7 @@ object GamePacketOpcode extends Enumeration {
case 0x53 => noDecoder(DroppodLaunchRequestMessage)
case 0x54 => game.HackMessage.decode
case 0x55 => noDecoder(DroppodLaunchResponseMessage)
- case 0x56 => noDecoder(GenericObjectActionMessage)
+ case 0x56 => game.GenericObjectActionMessage.decode
case 0x57 => game.AvatarVehicleTimerMessage.decode
// 0x58
case 0x58 => game.AvatarImplantMessage.decode
diff --git a/common/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala b/common/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala
new file mode 100644
index 000000000..0c15f526f
--- /dev/null
+++ b/common/src/main/scala/net/psforever/packet/game/GenericObjectActionMessage.scala
@@ -0,0 +1,39 @@
+// Copyright (c) 2017 PSForever
+package net.psforever.packet.game
+
+import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
+import scodec.bits.BitVector
+import scodec.{Attempt, Codec}
+import scodec.codecs._
+import shapeless.{::, HNil}
+
+/**
+ * Dispatched by the server to enact an effect on some game object.
+ * (Write more some other time.)
+ * @param object_guid the target object
+ * @param code the action code
+ */
+final case class GenericObjectActionMessage(object_guid : PlanetSideGUID,
+ code : Int)
+ extends PlanetSideGamePacket {
+ type Packet = GenericObjectActionMessage
+ def opcode = GamePacketOpcode.GenericObjectActionMessage
+ def encode = GenericObjectActionMessage.encode(this)
+}
+
+object GenericObjectActionMessage extends Marshallable[GenericObjectActionMessage] {
+ implicit val codec : Codec[GenericObjectActionMessage] = (
+ ("object_guid" | PlanetSideGUID.codec) ::
+ ("code" | uint8L) ::
+ ("ex" | bits) //"code" may extract at odd sizes
+ ).exmap[GenericObjectActionMessage] (
+ {
+ case guid :: code :: _ :: HNil =>
+ Attempt.Successful(GenericObjectActionMessage(guid, code))
+ },
+ {
+ case GenericObjectActionMessage(guid, code) =>
+ Attempt.Successful(guid :: code :: BitVector.empty :: HNil)
+ }
+ )
+}
diff --git a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
index c61b03e7a..036bd5ff8 100644
--- a/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
+++ b/common/src/main/scala/net/psforever/packet/game/PlanetsideAttributeMessage.scala
@@ -89,7 +89,7 @@ import scodec.codecs._
* `106 - Custom Head`
*
* Vehicles:
- * 0 - Vehicle health
+ * 0 - Vehicle base health
* 10 - Driver seat permissions (0 = Locked, 1 = Group, 3 = Empire)
* 11 - Gunner seat(s) permissions (same)
* 12 - Passenger seat(s) permissions (same)
diff --git a/common/src/main/scala/net/psforever/packet/game/objectcreate/ObjectClass.scala b/common/src/main/scala/net/psforever/packet/game/objectcreate/ObjectClass.scala
index 37b85c5a6..e9506fc3b 100644
--- a/common/src/main/scala/net/psforever/packet/game/objectcreate/ObjectClass.scala
+++ b/common/src/main/scala/net/psforever/packet/game/objectcreate/ObjectClass.scala
@@ -347,6 +347,8 @@ object ObjectClass {
final val quadstealth_destroyed = 711
final val router = 741
final val router_destroyed = 742
+ final val skyguard = 784
+ final val skyguard_destroyed = 785
final val switchblade = 847
final val switchblade_destroyed = 848
final val threemanheavybuggy = 862 //marauder
@@ -845,7 +847,7 @@ object ObjectClass {
case ObjectClass.lancer => ConstructorData.genericCodec(WeaponData.codec, "weapon")
case ObjectClass.lasher => ConstructorData.genericCodec(WeaponData.codec, "weapon")
case ObjectClass.liberator_25mm_cannon => ConstructorData.genericCodec(WeaponData.codec, "weapon")
- case ObjectClass.liberator_bomb_bay => ConstructorData.genericCodec(WeaponData.codec(2), "weapon")
+ case ObjectClass.liberator_bomb_bay => ConstructorData.genericCodec(WeaponData.codec, "weapon")
case ObjectClass.liberator_weapon_system => ConstructorData.genericCodec(WeaponData.codec, "weapon")
case ObjectClass.lightgunship_weapon_system => ConstructorData.genericCodec(WeaponData.codec(2), "weapon")
case ObjectClass.lightning_weapon_system => ConstructorData.genericCodec(WeaponData.codec(2), "weapon")
@@ -888,7 +890,7 @@ object ObjectClass {
case ObjectClass.rocklet => ConstructorData.genericCodec(WeaponData.codec, "weapon")
case ObjectClass.rotarychaingun_mosquito => ConstructorData.genericCodec(WeaponData.codec, "weapon")
case ObjectClass.scythe => ConstructorData.genericCodec(WeaponData.codec(2), "weapon")
- case ObjectClass.skyguard_weapon_system => ConstructorData.genericCodec(WeaponData.codec, "weapon")
+ case ObjectClass.skyguard_weapon_system => ConstructorData.genericCodec(WeaponData.codec(2), "weapon")
case ObjectClass.spiker => ConstructorData.genericCodec(WeaponData.codec, "weapon")
case ObjectClass.spitfire_aa_weapon => ConstructorData.genericCodec(WeaponData.codec, "weapon")
case ObjectClass.spitfire_weapon => ConstructorData.genericCodec(WeaponData.codec, "weapon")
@@ -1245,6 +1247,8 @@ object ObjectClass {
case ObjectClass.quadstealth_destroyed => ConstructorData.genericCodec(DestroyedVehicleData.codec, "wreckage")
case ObjectClass.router => ConstructorData.genericCodec(VehicleData.codec(VehicleFormat.Variant), "vehicle")
case ObjectClass.router_destroyed => ConstructorData.genericCodec(DestroyedVehicleData.codec, "wreckage")
+ case ObjectClass.skyguard => ConstructorData.genericCodec(VehicleData.codec, "vehicle")
+ case ObjectClass.skyguard_destroyed => ConstructorData.genericCodec(DestroyedVehicleData.codec, "wreckage")
case ObjectClass.switchblade => ConstructorData.genericCodec(VehicleData.codec(VehicleFormat.Variant), "vehicle")
case ObjectClass.switchblade_destroyed => ConstructorData.genericCodec(DestroyedVehicleData.codec, "wreckage")
case ObjectClass.threemanheavybuggy => ConstructorData.genericCodec(VehicleData.codec, "vehicle")
diff --git a/common/src/main/scala/net/psforever/packet/game/objectcreate/Prefab.scala b/common/src/main/scala/net/psforever/packet/game/objectcreate/Prefab.scala
index 8d3a60651..1a3d8aed9 100644
--- a/common/src/main/scala/net/psforever/packet/game/objectcreate/Prefab.scala
+++ b/common/src/main/scala/net/psforever/packet/game/objectcreate/Prefab.scala
@@ -27,6 +27,81 @@ object Prefab {
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, driveState, false, false, false, Some(UtilityVehicleData(0)), None)(VehicleFormat.Utility)
}
+ def apc_nc(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID, weapon6_guid : PlanetSideGUID, ammo6_guid : PlanetSideGUID) : VehicleData = {
+ VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
+ Some(InventoryData(
+ InventoryItemData(ObjectClass.apc_weapon_systemc_nc, weapon1_guid, 11,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_20mm, ammo1_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_weapon_systemb, weapon2_guid, 12,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo2_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_weapon_systema, weapon3_guid, 13,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo3_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_weapon_systemd_nc, weapon4_guid, 14,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_20mm, ammo4_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_ballgun_r, weapon5_guid, 15,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo5_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_ballgun_l, weapon6_guid, 16,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo6_guid, 0, AmmoBoxData(8))
+ ) :: Nil
+ ))
+ )(VehicleFormat.Normal)
+ }
+
+ def apc_tr(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID, weapon6_guid : PlanetSideGUID, ammo6_guid : PlanetSideGUID) : VehicleData = {
+ VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
+ Some(InventoryData(
+ InventoryItemData(ObjectClass.apc_weapon_systemc_tr, weapon1_guid, 11,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_15mm, ammo1_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_weapon_systemb, weapon2_guid, 12,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo2_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_weapon_systema, weapon3_guid, 13,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo3_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_weapon_systemd_tr, weapon4_guid, 14,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_15mm, ammo4_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_ballgun_r, weapon5_guid, 15,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo5_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_ballgun_l, weapon6_guid, 16,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo6_guid, 0, AmmoBoxData(8))
+ ) :: Nil
+ ))
+ )(VehicleFormat.Normal)
+ }
+
+ def apc_vs(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID, weapon6_guid : PlanetSideGUID, ammo6_guid : PlanetSideGUID) : VehicleData = {
+ VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
+ Some(InventoryData(
+ InventoryItemData(ObjectClass.apc_weapon_systemc_vs, weapon1_guid, 11,
+ WeaponData(0x6, 0x8, 0, ObjectClass.flux_cannon_thresher_battery, ammo1_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_weapon_systemb, weapon2_guid, 12,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo2_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_weapon_systema, weapon3_guid, 13,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo3_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_weapon_systemd_vs, weapon4_guid, 14,
+ WeaponData(0x6, 0x8, 0, ObjectClass.flux_cannon_thresher_battery, ammo4_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_ballgun_r, weapon5_guid, 15,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo5_guid, 0, AmmoBoxData(8))
+ ) ::
+ InventoryItemData(ObjectClass.apc_ballgun_l, weapon6_guid, 16,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo6_guid, 0, AmmoBoxData(8))
+ ) :: Nil
+ ))
+ )(VehicleFormat.Normal)
+ }
+
def aurora(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo11_guid : PlanetSideGUID, ammo12_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo21_guid : PlanetSideGUID, ammo22_guid : PlanetSideGUID) : VehicleData = {
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
Some(InventoryData(
@@ -118,56 +193,6 @@ object Prefab {
)(VehicleFormat.Variant)
}
- def juggernaut(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID, weapon6_guid : PlanetSideGUID, ammo6_guid : PlanetSideGUID) : VehicleData = {
- VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
- Some(InventoryData(
- InventoryItemData(ObjectClass.apc_weapon_systemc_tr, weapon1_guid, 11,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_15mm, ammo1_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_weapon_systemb, weapon2_guid, 12,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo2_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_weapon_systema, weapon3_guid, 13,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo3_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_weapon_systemd_tr, weapon4_guid, 14,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_15mm, ammo4_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_ballgun_r, weapon5_guid, 15,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo5_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_ballgun_l, weapon6_guid, 16,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo6_guid, 0, AmmoBoxData(8))
- ) :: Nil
- ))
- )(VehicleFormat.Normal)
- }
-
- def leviathan(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID, weapon6_guid : PlanetSideGUID, ammo6_guid : PlanetSideGUID) : VehicleData = {
- VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
- Some(InventoryData(
- InventoryItemData(ObjectClass.apc_weapon_systemc_vs, weapon1_guid, 11,
- WeaponData(0x6, 0x8, 0, ObjectClass.flux_cannon_thresher_battery, ammo1_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_weapon_systemb, weapon2_guid, 12,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo2_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_weapon_systema, weapon3_guid, 13,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo3_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_weapon_systemd_vs, weapon4_guid, 14,
- WeaponData(0x6, 0x8, 0, ObjectClass.flux_cannon_thresher_battery, ammo4_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_ballgun_r, weapon5_guid, 15,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo5_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_ballgun_l, weapon6_guid, 16,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo6_guid, 0, AmmoBoxData(8))
- ) :: Nil
- ))
- )(VehicleFormat.Normal)
- }
-
def liberator(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID) : VehicleData = {
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
Some(InventoryData(
@@ -187,8 +212,8 @@ object Prefab {
def lightgunship(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
Some(InventoryData(
- InventoryItemData(445, weapon_guid, 1,
- WeaponData(0x6, 0x8, 0, 16, ammo1_guid, 0, AmmoBoxData(8), 722, ammo2_guid,1, AmmoBoxData(8))
+ InventoryItemData(ObjectClass.lightgunship_weapon_system, weapon_guid, 1,
+ WeaponData(0x6, 0x8, 0, ObjectClass.bullet_20mm, ammo1_guid, 0, AmmoBoxData(8), ObjectClass.reaver_rocket, ammo2_guid,1, AmmoBoxData(8))
) :: Nil
))
)(VehicleFormat.Variant)
@@ -270,14 +295,6 @@ object Prefab {
)(VehicleFormat.Normal)
}
- def router(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, terminal_guid : PlanetSideGUID) : VehicleData = {
- VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
- Some(InventoryData(
- InventoryItemData(ObjectClass.teleportpad_terminal, terminal_guid, 1, CommonTerminalData(faction, 2)) :: Nil
- ))
- )(VehicleFormat.Variant)
- }
-
def quadassault(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo_guid : PlanetSideGUID) : VehicleData = {
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, None,
Some(InventoryData(
@@ -292,6 +309,24 @@ object Prefab {
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, false, false, false, None, None)(VehicleFormat.Normal)
}
+ def router(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, terminal_guid : PlanetSideGUID) : VehicleData = {
+ VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.Mobile, false, false, false, Some(VariantVehicleData(0)),
+ Some(InventoryData(
+ InventoryItemData(ObjectClass.teleportpad_terminal, terminal_guid, 1, CommonTerminalData(faction, 2)) :: Nil
+ ))
+ )(VehicleFormat.Variant)
+ }
+
+ def skyguard(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
+ VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
+ Some(InventoryData(
+ InventoryItemData(ObjectClass.skyguard_weapon_system, weapon_guid, 2,
+ WeaponData(0x6, 0x8, 0, ObjectClass.skyguard_flak_cannon_ammo, ammo1_guid, 0, AmmoBoxData(8), ObjectClass.bullet_12mm, ammo2_guid, 1, AmmoBoxData(8))
+ ) :: Nil
+ ))
+ )(VehicleFormat.Normal)
+ }
+
def switchblade(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, driveState : DriveState.Value, weapon_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID) : VehicleData = {
VehicleData(CommonFieldData(loc, faction, 0), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
Some(InventoryData(
@@ -368,31 +403,6 @@ object Prefab {
)(VehicleFormat.Normal)
}
- def vindicator(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID, weapon4_guid : PlanetSideGUID, ammo4_guid : PlanetSideGUID, weapon5_guid : PlanetSideGUID, ammo5_guid : PlanetSideGUID, weapon6_guid : PlanetSideGUID, ammo6_guid : PlanetSideGUID) : VehicleData = {
- VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, None,
- Some(InventoryData(
- InventoryItemData(ObjectClass.apc_weapon_systemc_nc, weapon1_guid, 11,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_20mm, ammo1_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_weapon_systemb, weapon2_guid, 12,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo2_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_weapon_systema, weapon3_guid, 13,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_75mm, ammo3_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_weapon_systemd_nc, weapon4_guid, 14,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_20mm, ammo4_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_ballgun_r, weapon5_guid, 15,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo5_guid, 0, AmmoBoxData(8))
- ) ::
- InventoryItemData(ObjectClass.apc_ballgun_l, weapon6_guid, 16,
- WeaponData(0x6, 0x8, 0, ObjectClass.bullet_12mm, ammo6_guid, 0, AmmoBoxData(8))
- ) :: Nil
- ))
- )(VehicleFormat.Normal)
- }
-
def vulture(loc : PlacementData, faction : PlanetSideEmpire.Value, health : Int, weapon1_guid : PlanetSideGUID, ammo1_guid : PlanetSideGUID, weapon2_guid : PlanetSideGUID, ammo2_guid : PlanetSideGUID, weapon3_guid : PlanetSideGUID, ammo3_guid : PlanetSideGUID) : VehicleData = {
VehicleData(CommonFieldData(loc, faction, 2), 0, health, false, false, DriveState.State7, true, false, false, Some(VariantVehicleData(0)),
Some(InventoryData(
diff --git a/common/src/main/scala/net/psforever/types/Vector3.scala b/common/src/main/scala/net/psforever/types/Vector3.scala
index ac2b92fea..279b74110 100644
--- a/common/src/main/scala/net/psforever/types/Vector3.scala
+++ b/common/src/main/scala/net/psforever/types/Vector3.scala
@@ -4,11 +4,41 @@ package net.psforever.types
import net.psforever.newcodecs._
import scodec.Codec
import scodec.codecs._
-import shapeless.{::, HNil}
final case class Vector3(x : Float,
y : Float,
- z : Float)
+ z : Float) {
+ /**
+ * Operator override for vector addition, treating `Vector3` objects as actual mathematical vectors.
+ * The application of this overload is "vector1 + vector2."
+ * @param vec the other `Vector3` object
+ * @return a new `Vector3` object with the summed values
+ */
+ def +(vec : Vector3) : Vector3 = {
+ new Vector3(x + vec.x, y + vec.y, z + vec.z)
+ }
+
+ /**
+ * Operator override for vector subtraction, treating `Vector3` objects as actual mathematical vectors.
+ * The application of this overload is "vector1 - vector2."
+ * @param vec the other `Vector3` object
+ * @return a new `Vector3` object with the difference values
+ */
+ def -(vec : Vector3) : Vector3 = {
+ new Vector3(x - vec.x, y - vec.y, z - vec.z)
+ }
+
+ /**
+ * Operator override for vector scaling, treating `Vector3` objects as actual mathematical vectors.
+ * The application of this overload is "vector * scalar" exclusively.
+ * "scalar * vector" is invalid.
+ * @param scalar the value to multiply this vector
+ * @return a new `Vector3` object
+ */
+ def *(scalar : Float) : Vector3 = {
+ new Vector3(x*scalar, y*scalar, z*scalar)
+ }
+}
object Vector3 {
implicit val codec_pos : Codec[Vector3] = (
@@ -28,4 +58,48 @@ object Vector3 {
("y" | floatL) ::
("z" | floatL)
).as[Vector3]
+
+ /**
+ * Calculate the actual distance between two points.
+ * @param pos1 the first point
+ * @param pos2 the second point
+ * @return the distance
+ */
+ def Distance(pos1 : Vector3, pos2 : Vector3) : Float = {
+ math.sqrt(DistanceSquared(pos1, pos2)).toFloat
+ }
+
+ /**
+ * Calculate the squared distance between two points.
+ * Though some time is saved care must be taken that any comparative distance is also squared.
+ * @param pos1 the first point
+ * @param pos2 the second point
+ * @return the distance
+ */
+ def DistanceSquared(pos1 : Vector3, pos2 : Vector3) : Float = {
+ val dvec : Vector3 = pos1 - pos2
+ (dvec.x * dvec.x) + (dvec.y * dvec.y) + (dvec.z * dvec.z)
+ }
+
+ /**
+ * Calculate the actual magnitude of a vector.
+ * @param vec the vector
+ * @return the magnitude
+ */
+ def Magnitude(vec : Vector3) : Float = {
+ math.sqrt(MagnitudeSquared(vec)).toFloat
+ }
+
+ /**
+ * Calculate the squared magnitude of a vector.
+ * Though some time is saved care must be taken that any comparative magnitude is also squared.
+ * @param vec the vector
+ * @return the magnitude
+ */
+ def MagnitudeSquared(vec : Vector3) : Float = {
+ val dx : Float = vec.x
+ val dy : Float = vec.y
+ val dz : Float = vec.z
+ (dx * dx) + (dy * dy) + (dz * dz)
+ }
}
diff --git a/common/src/test/scala/Vector3Test.scala b/common/src/test/scala/Vector3Test.scala
new file mode 100644
index 000000000..cedc7c066
--- /dev/null
+++ b/common/src/test/scala/Vector3Test.scala
@@ -0,0 +1,68 @@
+// Copyright (c) 2017 PSForever
+import org.specs2.mutable._
+import net.psforever.types.Vector3
+
+class Vector3Test extends Specification {
+ val vec = Vector3(1.3f, -2.6f, 3.9f)
+
+ "Vector3" should {
+ "construct" in {
+ vec.x mustEqual 1.3f
+ vec.y mustEqual -2.6f
+ vec.z mustEqual 3.9f
+ }
+
+ "calculate magnitude (like a vector) 1" in {
+ val obj = Vector3(2.0f, 0.0f, 0.0f)
+ Vector3.Magnitude(obj) mustEqual 2.0f
+ }
+
+ "calculate magnitude (like a vector) 2" in {
+ val obj = Vector3(3.0f, 4.0f, 0.0f)
+ Vector3.Magnitude(obj) mustEqual 5.0f
+ }
+
+ "calculate magnitude (like a vector) 3" in {
+ Vector3.Magnitude(vec) mustEqual 4.864155f
+ }
+
+ "calculate square magnitude (like a vector)" in {
+ Vector3.MagnitudeSquared(vec) mustEqual 23.66f
+ }
+
+ "calculate distance 1" in {
+ val obj1 = Vector3(0.0f, 0.0f, 0.0f)
+ val obj2 = Vector3(2.0f, 0.0f, 0.0f)
+ Vector3.Distance(obj1, obj2) mustEqual 2.0f
+ }
+
+ "calculate distance 2" in {
+ val obj1 = Vector3(0.0f, 0.0f, 0.0f)
+ val obj2 = Vector3(2.0f, 0.0f, 0.0f)
+ Vector3.Distance(obj1, obj2) mustEqual Vector3.Magnitude(obj2)
+ }
+
+ "calculate distance 3" in {
+ val obj1 = Vector3(3.0f, 4.0f, 5.0f)
+ val obj2 = Vector3(3.0f, 4.0f, 5.0f)
+ Vector3.Distance(obj1, obj2) mustEqual 0f
+ }
+
+ "addition" in {
+ val obj1 = Vector3(3.0f, 4.0f, 5.0f)
+ val obj2 = Vector3(3.0f, 4.0f, 5.0f)
+ obj1 + obj2 mustEqual Vector3(6f, 8f, 10f)
+ }
+
+ "subtraction" in {
+ val obj1 = Vector3(3.0f, 4.0f, 5.0f)
+ val obj2 = Vector3(3.0f, 4.0f, 5.0f)
+ obj1 - obj2 mustEqual Vector3(0f, 0f, 0f)
+ }
+
+ "scalar" in {
+ vec * 3f mustEqual Vector3(3.8999999f, -7.7999997f, 11.700001f)
+ }
+ }
+}
+
diff --git a/common/src/test/scala/game/GenericObjectActionMessageTest.scala b/common/src/test/scala/game/GenericObjectActionMessageTest.scala
new file mode 100644
index 000000000..8ad103886
--- /dev/null
+++ b/common/src/test/scala/game/GenericObjectActionMessageTest.scala
@@ -0,0 +1,28 @@
+// Copyright (c) 2017 PSForever
+package game
+
+import org.specs2.mutable._
+import net.psforever.packet._
+import net.psforever.packet.game._
+import scodec.bits._
+
+class GenericObjectActionMessageTest extends Specification {
+ val string = hex"56 B501 24"
+
+ "decode" in {
+ PacketCoding.DecodePacket(string).require match {
+ case GenericObjectActionMessage(object_guid, action) =>
+ object_guid mustEqual PlanetSideGUID(437)
+ action mustEqual 36
+ case _ =>
+ ko
+ }
+ }
+
+ "encode" in {
+ val msg = GenericObjectActionMessage(PlanetSideGUID(437), 36)
+ val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
+
+ pkt mustEqual string
+ }
+}
diff --git a/common/src/test/scala/objects/ConverterTest.scala b/common/src/test/scala/objects/ConverterTest.scala
index 90e92a44e..b4e5ec24a 100644
--- a/common/src/test/scala/objects/ConverterTest.scala
+++ b/common/src/test/scala/objects/ConverterTest.scala
@@ -40,16 +40,15 @@ class ConverterTest extends Specification {
"convert to packet" in {
val tdef = ToolDefinition(1076)
tdef.Size = EquipmentSize.Rifle
- tdef.AmmoTypes += Ammo.shotgun_shell
- tdef.AmmoTypes += Ammo.shotgun_shell_AP
+ tdef.AmmoTypes += GlobalDefinitions.shotgun_shell
+ tdef.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
tdef.FireModes += new FireModeDefinition
tdef.FireModes.head.AmmoTypeIndices += 0
tdef.FireModes.head.AmmoTypeIndices += 1
tdef.FireModes.head.AmmoSlotIndex = 0
+ tdef.FireModes.head.Magazine = 30
val obj : Tool = Tool(tdef)
- val box = AmmoBox(PlanetSideGUID(90), new AmmoBoxDefinition(Ammo.shotgun_shell.id))
- obj.AmmoSlots.head.Box = box
- obj.AmmoSlots.head.Magazine = 30
+ obj.AmmoSlot.Box.GUID = PlanetSideGUID(90)
obj.Definition.Packet.DetailedConstructorData(obj) match {
case Success(pkt) =>
@@ -139,24 +138,22 @@ class ConverterTest extends Specification {
Give the Player's Holster (2) the Tool
Place the remaining AmmoBox into the Player's inventory in the third slot (8)
*/
- val bullet_9mm = AmmoBoxDefinition(28)
- bullet_9mm.Capacity = 50
- val box1 = AmmoBox(PlanetSideGUID(90), bullet_9mm)
- val box2 = AmmoBox(PlanetSideGUID(91), bullet_9mm)
val tdef = ToolDefinition(1076)
tdef.Name = "sample_weapon"
tdef.Size = EquipmentSize.Rifle
- tdef.AmmoTypes += Ammo.bullet_9mm
+ tdef.AmmoTypes += GlobalDefinitions.bullet_9mm
tdef.FireModes += new FireModeDefinition
tdef.FireModes.head.AmmoTypeIndices += 0
tdef.FireModes.head.AmmoSlotIndex = 0
tdef.FireModes.head.Magazine = 18
- val tool = Tool(PlanetSideGUID(92), tdef)
- tool.AmmoSlots.head.Box = box1
+ val tool = Tool(tdef)
+ tool.GUID = PlanetSideGUID(92)
+ tool.AmmoSlot.Box.GUID = PlanetSideGUID(90)
val obj = Player(PlanetSideGUID(93), "Chord", PlanetSideEmpire.TR, CharacterGender.Male, 0, 5)
obj.Slot(2).Equipment = tool
obj.Slot(5).Equipment.get.GUID = PlanetSideGUID(94)
- obj.Inventory += 8 -> box2
+ obj.Inventory += 8 -> AmmoBox(GlobalDefinitions.bullet_9mm)
+ obj.Slot(8).Equipment.get.GUID = PlanetSideGUID(91)
obj
}
val converter = new CharacterSelectConverter
@@ -263,7 +260,7 @@ class ConverterTest extends Specification {
val fury_weapon_systema_def = ToolDefinition(ObjectClass.fury_weapon_systema)
fury_weapon_systema_def.Size = EquipmentSize.VehicleWeapon
- fury_weapon_systema_def.AmmoTypes += Ammo.hellfire_ammo
+ fury_weapon_systema_def.AmmoTypes += GlobalDefinitions.hellfire_ammo
fury_weapon_systema_def.FireModes += new FireModeDefinition
fury_weapon_systema_def.FireModes.head.AmmoTypeIndices += 0
fury_weapon_systema_def.FireModes.head.AmmoSlotIndex = 0
diff --git a/common/src/test/scala/objects/EquipmentTest.scala b/common/src/test/scala/objects/EquipmentTest.scala
index 284d0b2b7..02847c63c 100644
--- a/common/src/test/scala/objects/EquipmentTest.scala
+++ b/common/src/test/scala/objects/EquipmentTest.scala
@@ -10,7 +10,6 @@ import net.psforever.objects.GlobalDefinitions._
import org.specs2.mutable._
class EquipmentTest extends Specification {
-
"AmmoBox" should {
"define" in {
val obj = AmmoBoxDefinition(86)
@@ -19,8 +18,8 @@ class EquipmentTest extends Specification {
obj.AmmoType mustEqual Ammo.aphelion_immolation_cannon_ammo
obj.Capacity mustEqual 300
- obj.Tile.width mustEqual InventoryTile.Tile44.width
- obj.Tile.height mustEqual InventoryTile.Tile44.height
+ obj.Tile.Width mustEqual InventoryTile.Tile44.Width
+ obj.Tile.Height mustEqual InventoryTile.Tile44.Height
obj.ObjectId mustEqual 86
}
@@ -58,8 +57,8 @@ class EquipmentTest extends Specification {
val obj = ToolDefinition(1076)
obj.Name = "sample_weapon"
obj.Size = EquipmentSize.Rifle
- obj.AmmoTypes += Ammo.shotgun_shell
- obj.AmmoTypes += Ammo.shotgun_shell_AP
+ obj.AmmoTypes += GlobalDefinitions.shotgun_shell
+ obj.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
obj.FireModes += new FireModeDefinition
obj.FireModes.head.AmmoTypeIndices += 0
obj.FireModes.head.AmmoTypeIndices += 1
@@ -74,9 +73,10 @@ class EquipmentTest extends Specification {
obj.FireModes(1).Magazine = 18
obj.Tile = InventoryTile.Tile93
obj.ObjectId mustEqual 1076
+
obj.Name mustEqual "sample_weapon"
- obj.AmmoTypes.head mustEqual Ammo.shotgun_shell
- obj.AmmoTypes(1) mustEqual Ammo.shotgun_shell_AP
+ obj.AmmoTypes.head mustEqual GlobalDefinitions.shotgun_shell
+ obj.AmmoTypes(1) mustEqual GlobalDefinitions.shotgun_shell_AP
obj.FireModes.head.AmmoTypeIndices.head mustEqual 0
obj.FireModes.head.AmmoTypeIndices(1) mustEqual 1
obj.FireModes.head.AmmoSlotIndex mustEqual 0
@@ -89,8 +89,8 @@ class EquipmentTest extends Specification {
obj.FireModes(1).Chamber mustEqual 3
obj.FireModes(1).Magazine mustEqual 18
obj.FireModes(1).ResetAmmoIndexOnSwap mustEqual false
- obj.Tile.width mustEqual InventoryTile.Tile93.width
- obj.Tile.height mustEqual InventoryTile.Tile93.height
+ obj.Tile.Width mustEqual InventoryTile.Tile93.Width
+ obj.Tile.Height mustEqual InventoryTile.Tile93.Height
}
"construct" in {
@@ -118,8 +118,8 @@ class EquipmentTest extends Specification {
//explanation: sample_weapon has two fire modes; adjusting the FireMode changes between them
val tdef = ToolDefinition(1076)
tdef.Size = EquipmentSize.Rifle
- tdef.AmmoTypes += Ammo.shotgun_shell
- tdef.AmmoTypes += Ammo.shotgun_shell_AP
+ tdef.AmmoTypes += GlobalDefinitions.shotgun_shell
+ tdef.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
tdef.FireModes += new FireModeDefinition
tdef.FireModes.head.AmmoTypeIndices += 0
tdef.FireModes.head.AmmoSlotIndex = 0
@@ -149,8 +149,8 @@ class EquipmentTest extends Specification {
//explanation: obj has one fire mode and two ammunitions; adjusting the AmmoType changes between them
val tdef = ToolDefinition(1076)
tdef.Size = EquipmentSize.Rifle
- tdef.AmmoTypes += Ammo.shotgun_shell
- tdef.AmmoTypes += Ammo.shotgun_shell_AP
+ tdef.AmmoTypes += GlobalDefinitions.shotgun_shell
+ tdef.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
tdef.FireModes += new FireModeDefinition
tdef.FireModes.head.AmmoTypeIndices += 0
tdef.FireModes.head.AmmoTypeIndices += 1
@@ -168,14 +168,54 @@ class EquipmentTest extends Specification {
obj.AmmoTypeIndex mustEqual 0
obj.AmmoType mustEqual Ammo.shotgun_shell
}
+
+ "multiple ammo types and multiple fire modes, split (Punisher)" in {
+ val obj = Tool(GlobalDefinitions.punisher)
+ //ammo = 0, fmode = 0
+ obj.FireModeIndex mustEqual 0
+ obj.AmmoTypeIndex mustEqual 0
+ obj.AmmoType mustEqual Ammo.bullet_9mm
+ //ammo = 2, fmode = 1
+ obj.NextFireMode
+ obj.FireModeIndex mustEqual 1
+ obj.AmmoTypeIndex mustEqual 2
+ obj.AmmoType mustEqual Ammo.rocket
+ //ammo = 3, fmode = 1
+ obj.NextAmmoType
+ obj.AmmoTypeIndex mustEqual 3
+ obj.AmmoType mustEqual Ammo.frag_cartridge
+ //ammo = 4, fmode = 1
+ obj.NextAmmoType
+ obj.AmmoTypeIndex mustEqual 4
+ obj.AmmoType mustEqual Ammo.jammer_cartridge
+ //ammo = 0, fmode = 0
+ obj.NextFireMode
+ obj.FireModeIndex mustEqual 0
+ obj.AmmoTypeIndex mustEqual 0
+ obj.AmmoType mustEqual Ammo.bullet_9mm
+ //ammo = 1, fmode = 0
+ obj.NextAmmoType
+ obj.AmmoTypeIndex mustEqual 1
+ obj.AmmoType mustEqual Ammo.bullet_9mm_AP
+ //ammo = 5, fmode = 1
+ obj.NextFireMode
+ obj.NextAmmoType
+ obj.FireModeIndex mustEqual 1
+ obj.AmmoTypeIndex mustEqual 5
+ obj.AmmoType mustEqual Ammo.plasma_cartridge
+ //ammo = 2, fmode = 1
+ obj.NextAmmoType
+ obj.AmmoTypeIndex mustEqual 2
+ obj.AmmoType mustEqual Ammo.rocket
+ }
}
"Kit" should {
"define" in {
val sample = KitDefinition(Kits.medkit)
sample.ObjectId mustEqual medkit.ObjectId
- sample.Tile.width mustEqual medkit.Tile.width
- sample.Tile.height mustEqual medkit.Tile.height
+ sample.Tile.Width mustEqual medkit.Tile.Width
+ sample.Tile.Height mustEqual medkit.Tile.Height
}
"construct" in {
@@ -200,8 +240,8 @@ class EquipmentTest extends Specification {
sample.Modes.head mustEqual DeployedItem.tank_traps
sample.Modes(1) mustEqual DeployedItem.portable_manned_turret_tr
sample.Modes(2) mustEqual DeployedItem.deployable_shield_generator
- sample.Tile.width mustEqual InventoryTile.Tile63.width
- sample.Tile.height mustEqual InventoryTile.Tile63.height
+ sample.Tile.Width mustEqual InventoryTile.Tile63.Width
+ sample.Tile.Height mustEqual InventoryTile.Tile63.Height
}
"construct" in {
diff --git a/common/src/test/scala/objects/InventoryTest.scala b/common/src/test/scala/objects/InventoryTest.scala
index 3af8a011d..34ec74914 100644
--- a/common/src/test/scala/objects/InventoryTest.scala
+++ b/common/src/test/scala/objects/InventoryTest.scala
@@ -57,8 +57,8 @@ class InventoryTest extends Specification {
val obj : GridInventory = GridInventory(9, 6)
obj += 0 -> bullet9mmBox1
obj.Capacity mustEqual 45
- val w = bullet9mmBox2.Tile.width
- val h = bullet9mmBox2.Tile.height
+ val w = bullet9mmBox2.Tile.Width
+ val h = bullet9mmBox2.Tile.Height
val list0 = obj.CheckCollisionsAsList(0, w, h)
list0 match {
case scala.util.Success(list) => list.length mustEqual 1
@@ -91,8 +91,8 @@ class InventoryTest extends Specification {
val obj : GridInventory = GridInventory(9, 6)
obj += 3 -> bullet9mmBox1
obj.Capacity mustEqual 45
- val w = bullet9mmBox2.Tile.width
- val h = bullet9mmBox2.Tile.height
+ val w = bullet9mmBox2.Tile.Width
+ val h = bullet9mmBox2.Tile.Height
val list0 = obj.CheckCollisionsAsList(3, w, h)
list0 match {
case scala.util.Success(list) => list.length mustEqual 1
@@ -125,8 +125,8 @@ class InventoryTest extends Specification {
val obj : GridInventory = GridInventory(9, 6)
obj += 0 -> bullet9mmBox1
obj.Capacity mustEqual 45
- val w = bullet9mmBox2.Tile.width
- val h = bullet9mmBox2.Tile.height
+ val w = bullet9mmBox2.Tile.Width
+ val h = bullet9mmBox2.Tile.Height
val list0 = obj.CheckCollisionsAsList(0, w, h)
list0 match {
case scala.util.Success(list) => list.length mustEqual 1
@@ -159,8 +159,8 @@ class InventoryTest extends Specification {
val obj : GridInventory = GridInventory(9, 6)
obj += 27 -> bullet9mmBox1
obj.Capacity mustEqual 45
- val w = bullet9mmBox2.Tile.width
- val h = bullet9mmBox2.Tile.height
+ val w = bullet9mmBox2.Tile.Width
+ val h = bullet9mmBox2.Tile.Height
val list0 = obj.CheckCollisionsAsList(27, w, h)
list0 match {
case scala.util.Success(list) => list.length mustEqual 1
@@ -205,8 +205,8 @@ class InventoryTest extends Specification {
val obj : GridInventory = GridInventory(12, 9)
obj += 39 -> bullet9mmBox1
obj.Capacity mustEqual 99 //108 - 9
- val w = bullet9mmBox2.Tile.width
- val h = bullet9mmBox2.Tile.height
+ val w = bullet9mmBox2.Tile.Width
+ val h = bullet9mmBox2.Tile.Height
val list0 = obj.CheckCollisionsAsList(0, w, h)
list0 match {
case scala.util.Success(list) => list.isEmpty mustEqual true
diff --git a/common/src/test/scala/objects/VehicleSpawnPadTest.scala b/common/src/test/scala/objects/VehicleSpawnPadTest.scala
new file mode 100644
index 000000000..5005661f5
--- /dev/null
+++ b/common/src/test/scala/objects/VehicleSpawnPadTest.scala
@@ -0,0 +1,110 @@
+// Copyright (c) 2017 PSForever
+package objects
+
+import akka.actor.{ActorRef, Props}
+import net.psforever.objects.serverobject.pad.{VehicleSpawnControl, VehicleSpawnPad}
+import net.psforever.objects.vehicles.VehicleControl
+import net.psforever.objects.{GlobalDefinitions, Player, Vehicle}
+import net.psforever.packet.game.PlanetSideGUID
+import net.psforever.types.{CharacterGender, PlanetSideEmpire, Vector3}
+import org.specs2.mutable.Specification
+
+import scala.concurrent.duration.Duration
+
+class VehicleSpawnPadTest extends Specification {
+ "VehicleSpawnPadDefinition" should {
+ "define" in {
+ GlobalDefinitions.spawn_pad.ObjectId mustEqual 800
+ }
+ }
+
+ "VehicleSpawnPad" should {
+ "construct" in {
+ val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
+ obj.Actor mustEqual ActorRef.noSender
+ obj.Definition mustEqual GlobalDefinitions.spawn_pad
+ }
+ }
+}
+
+class VehicleSpawnControl1Test extends ActorTest() {
+ "VehicleSpawnControl" should {
+ "construct" in {
+ val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
+ obj.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], obj), "door")
+ assert(obj.Actor != ActorRef.noSender)
+ }
+ }
+}
+
+class VehicleSpawnControl2Test extends ActorTest() {
+ "VehicleSpawnControl" should {
+ "spawn a vehicle" in {
+ val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
+ obj.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], obj), "door")
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+ player.Spawn
+ val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
+ vehicle.GUID = PlanetSideGUID(1)
+ vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle")
+
+ obj.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
+ val reply = receiveOne(Duration.create(10000, "ms"))
+ assert(reply == VehicleSpawnPad.ConcealPlayer) //explicit: isInstanceOf does not work
+
+ val reply2 = receiveOne(Duration.create(10000, "ms"))
+ assert(reply2.isInstanceOf[VehicleSpawnPad.LoadVehicle])
+ assert(reply2.asInstanceOf[VehicleSpawnPad.LoadVehicle].vehicle == vehicle)
+ assert(reply2.asInstanceOf[VehicleSpawnPad.LoadVehicle].pad == obj)
+
+ player.VehicleOwned = vehicle
+ val reply3 = receiveOne(Duration.create(10000, "ms"))
+ assert(reply3.isInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle])
+ assert(reply3.asInstanceOf[VehicleSpawnPad.PlayerSeatedInVehicle].vehicle == vehicle)
+
+ val reply4 = receiveOne(Duration.create(10000, "ms"))
+ assert(reply4.isInstanceOf[VehicleSpawnPad.SpawnPadBlockedWarning])
+ assert(reply4.asInstanceOf[VehicleSpawnPad.SpawnPadBlockedWarning].vehicle == vehicle)
+ assert(reply4.asInstanceOf[VehicleSpawnPad.SpawnPadBlockedWarning].warning_count > 0)
+
+ vehicle.Position = Vector3(11f, 0f, 0f) //greater than 10m
+ val reply5 = receiveOne(Duration.create(10000, "ms"))
+ assert(reply5.isInstanceOf[VehicleSpawnPad.SpawnPadUnblocked])
+ assert(reply5.asInstanceOf[VehicleSpawnPad.SpawnPadUnblocked].vehicle_guid == vehicle.GUID)
+ }
+ }
+}
+
+class VehicleSpawnControl3Test extends ActorTest() {
+ "VehicleSpawnControl" should {
+ "not spawn a vehicle if player is dead" in {
+ val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
+ obj.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], obj), "door")
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+ val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
+ vehicle.GUID = PlanetSideGUID(1)
+ vehicle.Actor = system.actorOf(Props(classOf[VehicleControl], vehicle), "vehicle")
+
+ obj.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
+ val reply = receiveOne(Duration.create(5000, "ms"))
+ assert(reply == null)
+ }
+ }
+}
+
+class VehicleSpawnControl4Test extends ActorTest() {
+ "VehicleSpawnControl" should {
+ "not spawn a vehicle if vehicle Actor is missing" in {
+ val obj = VehicleSpawnPad(GlobalDefinitions.spawn_pad)
+ obj.Actor = system.actorOf(Props(classOf[VehicleSpawnControl], obj), "door")
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+ player.Spawn
+ val vehicle = Vehicle(GlobalDefinitions.two_man_assault_buggy)
+ vehicle.GUID = PlanetSideGUID(1)
+
+ obj.Actor ! VehicleSpawnPad.VehicleOrder(player, vehicle)
+ val reply = receiveOne(Duration.create(5000, "ms"))
+ assert(reply == null)
+ }
+ }
+}
diff --git a/common/src/test/scala/objects/VehicleTest.scala b/common/src/test/scala/objects/VehicleTest.scala
index d898a66e5..a61ad4312 100644
--- a/common/src/test/scala/objects/VehicleTest.scala
+++ b/common/src/test/scala/objects/VehicleTest.scala
@@ -44,8 +44,8 @@ class VehicleTest extends Specification {
fury.Weapons.size mustEqual 1
fury.Weapons.get(0) mustEqual None
fury.Weapons.get(1) mustEqual Some(GlobalDefinitions.fury_weapon_systema)
- fury.TrunkSize.width mustEqual 11
- fury.TrunkSize.height mustEqual 11
+ fury.TrunkSize.Width mustEqual 11
+ fury.TrunkSize.Height mustEqual 11
fury.TrunkOffset mustEqual 30
}
}
diff --git a/common/src/test/scala/objects/terminal/AirVehicleTerminalTest.scala b/common/src/test/scala/objects/terminal/AirVehicleTerminalTest.scala
new file mode 100644
index 000000000..ab1bcca82
--- /dev/null
+++ b/common/src/test/scala/objects/terminal/AirVehicleTerminalTest.scala
@@ -0,0 +1,37 @@
+// Copyright (c) 2017 PSForever
+package objects.terminal
+
+import akka.actor.ActorRef
+import net.psforever.objects.{GlobalDefinitions, Player, Tool}
+import net.psforever.objects.serverobject.terminals.Terminal
+import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
+import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType}
+import org.specs2.mutable.Specification
+
+class AirVehicleTerminalTest extends Specification {
+ "Air_Vehicle_Terminal" should {
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+
+ "construct" in {
+ val terminal = Terminal(GlobalDefinitions.air_vehicle_terminal)
+ terminal.Actor mustEqual ActorRef.noSender
+ }
+
+ "player can buy a reaver ('lightgunship')" in {
+ val terminal = Terminal(GlobalDefinitions.air_vehicle_terminal)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "lightgunship", 0, PlanetSideGUID(0))
+ val reply = terminal.Request(player, msg)
+ reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
+ val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
+ reply2.vehicle.Definition mustEqual GlobalDefinitions.lightgunship
+ reply2.loadout mustEqual Nil //TODO
+ }
+
+ "player can not buy a fake vehicle ('reaver')" in {
+ val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "reaver", 0, PlanetSideGUID(0))
+
+ terminal.Request(player, msg) mustEqual Terminal.NoDeal()
+ }
+ }
+}
diff --git a/common/src/test/scala/objects/terminal/DropshipVehicleTerminalTest.scala b/common/src/test/scala/objects/terminal/DropshipVehicleTerminalTest.scala
new file mode 100644
index 000000000..3446ec951
--- /dev/null
+++ b/common/src/test/scala/objects/terminal/DropshipVehicleTerminalTest.scala
@@ -0,0 +1,37 @@
+// Copyright (c) 2017 PSForever
+package objects.terminal
+
+import akka.actor.ActorRef
+import net.psforever.objects.{GlobalDefinitions, Player}
+import net.psforever.objects.serverobject.terminals.Terminal
+import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
+import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType}
+import org.specs2.mutable.Specification
+
+class DropshipVehicleTerminalTest extends Specification {
+ "Dropship_Vehicle_Terminal" should {
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+
+ "construct" in {
+ val terminal = Terminal(GlobalDefinitions.dropship_vehicle_terminal)
+ terminal.Actor mustEqual ActorRef.noSender
+ }
+
+ "player can buy a galaxy ('dropship')" in {
+ val terminal = Terminal(GlobalDefinitions.dropship_vehicle_terminal)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "dropship", 0, PlanetSideGUID(0))
+ val reply = terminal.Request(player, msg)
+ reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
+ val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
+ reply2.vehicle.Definition mustEqual GlobalDefinitions.dropship
+ reply2.loadout mustEqual Nil //TODO
+ }
+
+ "player can not buy a fake vehicle ('galaxy')" in {
+ val terminal = Terminal(GlobalDefinitions.dropship_vehicle_terminal)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "galaxy", 0, PlanetSideGUID(0))
+
+ terminal.Request(player, msg) mustEqual Terminal.NoDeal()
+ }
+ }
+}
diff --git a/common/src/test/scala/objects/terminal/GroundVehicleTerminalTest.scala b/common/src/test/scala/objects/terminal/GroundVehicleTerminalTest.scala
new file mode 100644
index 000000000..0a56463b9
--- /dev/null
+++ b/common/src/test/scala/objects/terminal/GroundVehicleTerminalTest.scala
@@ -0,0 +1,37 @@
+// Copyright (c) 2017 PSForever
+package objects.terminal
+
+import akka.actor.ActorRef
+import net.psforever.objects.{GlobalDefinitions, Player}
+import net.psforever.objects.serverobject.terminals.Terminal
+import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
+import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType}
+import org.specs2.mutable.Specification
+
+class GroundVehicleTerminalTest extends Specification {
+ "Ground_Vehicle_Terminal" should {
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+
+ "construct" in {
+ val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
+ terminal.Actor mustEqual ActorRef.noSender
+ }
+
+ "player can buy a harasser ('two_man_assault_buggy')" in {
+ val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "two_man_assault_buggy", 0, PlanetSideGUID(0))
+ val reply = terminal.Request(player, msg)
+ reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
+ val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
+ reply2.vehicle.Definition mustEqual GlobalDefinitions.two_man_assault_buggy
+ reply2.loadout mustEqual Nil //TODO
+ }
+
+ "player can not buy a fake vehicle ('harasser')" in {
+ val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "harasser", 0, PlanetSideGUID(0))
+
+ terminal.Request(player, msg) mustEqual Terminal.NoDeal()
+ }
+ }
+}
diff --git a/common/src/test/scala/objects/terminal/TerminalControlTest.scala b/common/src/test/scala/objects/terminal/TerminalControlTest.scala
index c5d8b0624..4d587292e 100644
--- a/common/src/test/scala/objects/terminal/TerminalControlTest.scala
+++ b/common/src/test/scala/objects/terminal/TerminalControlTest.scala
@@ -71,3 +71,40 @@ class CertTerminalControl3Test extends ActorTest() {
assert(reply2.response == Terminal.SellCertification(CertificationType.MediumAssault, 2))
}
}
+
+class VehicleTerminalControl1Test extends ActorTest() {
+ "TerminalControl can be used to buy a vehicle ('two_man_assault_buggy')" in {
+ val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
+ terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "two_man_assault_buggy", 0, PlanetSideGUID(0))
+
+ terminal.Actor ! Terminal.Request(player, msg)
+ val reply = receiveOne(Duration.create(500, "ms"))
+ assert(reply.isInstanceOf[Terminal.TerminalMessage])
+ val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
+ assert(reply2.player == player)
+ assert(reply2.msg == msg)
+ assert(reply2.response.isInstanceOf[Terminal.BuyVehicle])
+ val reply3 = reply2.response.asInstanceOf[Terminal.BuyVehicle]
+ assert(reply3.vehicle.Definition == GlobalDefinitions.two_man_assault_buggy)
+ assert(reply3.loadout == Nil) //TODO
+ }
+}
+
+class VehicleTerminalControl2Test extends ActorTest() {
+ "TerminalControl can be used to warn about not buy a vehicle ('harasser')" in {
+ val terminal = Terminal(GlobalDefinitions.ground_vehicle_terminal)
+ terminal.Actor = system.actorOf(Props(classOf[TerminalControl], terminal), "test-cert-term")
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "harasser", 0, PlanetSideGUID(0))
+
+ terminal.Actor ! Terminal.Request(player, msg)
+ val reply = receiveOne(Duration.create(500, "ms"))
+ assert(reply.isInstanceOf[Terminal.TerminalMessage])
+ val reply2 = reply.asInstanceOf[Terminal.TerminalMessage]
+ assert(reply2.player == player)
+ assert(reply2.msg == msg)
+ assert(reply2.response == Terminal.NoDeal())
+ }
+}
diff --git a/common/src/test/scala/objects/terminal/VehicleTerminalCombinedTest.scala b/common/src/test/scala/objects/terminal/VehicleTerminalCombinedTest.scala
new file mode 100644
index 000000000..722ec6adf
--- /dev/null
+++ b/common/src/test/scala/objects/terminal/VehicleTerminalCombinedTest.scala
@@ -0,0 +1,47 @@
+// Copyright (c) 2017 PSForever
+package objects.terminal
+
+import akka.actor.ActorRef
+import net.psforever.objects.{GlobalDefinitions, Player}
+import net.psforever.objects.serverobject.terminals.Terminal
+import net.psforever.packet.game.{ItemTransactionMessage, PlanetSideGUID}
+import net.psforever.types.{CharacterGender, PlanetSideEmpire, TransactionType}
+import org.specs2.mutable.Specification
+
+class VehicleTerminalCombinedTest extends Specification {
+ "Ground_Vehicle_Terminal" should {
+ val player = Player("test", PlanetSideEmpire.TR, CharacterGender.Male, 0, 0)
+
+ "construct" in {
+ val terminal = Terminal(GlobalDefinitions.vehicle_terminal_combined)
+ terminal.Actor mustEqual ActorRef.noSender
+ }
+
+ "player can buy a ground vehicle, the harasser ('two_man_assault_buggy')" in {
+ val terminal = Terminal(GlobalDefinitions.vehicle_terminal_combined)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "two_man_assault_buggy", 0, PlanetSideGUID(0))
+ val reply = terminal.Request(player, msg)
+ reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
+ val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
+ reply2.vehicle.Definition mustEqual GlobalDefinitions.two_man_assault_buggy
+ reply2.loadout mustEqual Nil //TODO
+ }
+
+ "player can buy a flying vehicle, the reaver ('lightgunship')" in {
+ val terminal = Terminal(GlobalDefinitions.vehicle_terminal_combined)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "lightgunship", 0, PlanetSideGUID(0))
+ val reply = terminal.Request(player, msg)
+ reply.isInstanceOf[Terminal.BuyVehicle] mustEqual true
+ val reply2 = reply.asInstanceOf[Terminal.BuyVehicle]
+ reply2.vehicle.Definition mustEqual GlobalDefinitions.lightgunship
+ reply2.loadout mustEqual Nil //TODO
+ }
+
+ "player can not buy a fake vehicle ('harasser')" in {
+ val terminal = Terminal(GlobalDefinitions.vehicle_terminal_combined)
+ val msg = ItemTransactionMessage(PlanetSideGUID(1), TransactionType.Buy, 0, "harasser", 0, PlanetSideGUID(0))
+
+ terminal.Request(player, msg) mustEqual Terminal.NoDeal()
+ }
+ }
+}
diff --git a/pslogin/src/main/scala/PsLogin.scala b/pslogin/src/main/scala/PsLogin.scala
index 870f402ee..e63ef0a16 100644
--- a/pslogin/src/main/scala/PsLogin.scala
+++ b/pslogin/src/main/scala/PsLogin.scala
@@ -14,7 +14,8 @@ import com.typesafe.config.ConfigFactory
import net.psforever.crypto.CryptoInterface
import net.psforever.objects.zones._
import net.psforever.objects.guid.TaskResolver
-import net.psforever.objects.serverobject.builders.{DoorObjectBuilder, IFFLockObjectBuilder, TerminalObjectBuilder}
+import net.psforever.objects.serverobject.builders.{DoorObjectBuilder, IFFLockObjectBuilder, TerminalObjectBuilder, VehicleSpawnPadObjectBuilder}
+import net.psforever.types.Vector3
import org.slf4j
import org.fusesource.jansi.Ansi._
import org.fusesource.jansi.Ansi.Color._
@@ -244,6 +245,10 @@ object PsLogin {
LocalObject(TerminalObjectBuilder(order_terminal, 853))
LocalObject(TerminalObjectBuilder(order_terminal, 855))
LocalObject(TerminalObjectBuilder(order_terminal, 860))
+ LocalObject(TerminalObjectBuilder(ground_vehicle_terminal, 1063))
+ LocalObject(VehicleSpawnPadObjectBuilder(spawn_pad, 500)) //TODO guid not correct
+ LocalObject(TerminalObjectBuilder(dropship_vehicle_terminal, 304))
+ LocalObject(VehicleSpawnPadObjectBuilder(spawn_pad, 501)) //TODO guid not correct
LocalBases = 30
@@ -251,8 +256,14 @@ object PsLogin {
ObjectToBase(332, 29)
ObjectToBase(556, 29)
ObjectToBase(558, 29)
+ ObjectToBase(1063, 29) //TODO unowned courtyard terminal?
+ ObjectToBase(500, 29) //TODO unowned courtyard spawnpad?
+ ObjectToBase(304, 29) //TODO unowned courtyard terminal?
+ ObjectToBase(501, 29) //TODO unowned courtyard spawnpad?
DoorToLock(330, 558)
DoorToLock(332, 556)
+ TerminalToSpawnPad(1063, 500)
+ TerminalToSpawnPad(304, 501)
}
val home3 = new Zone("home3", map13, 13) {
override def Init(implicit context : ActorContext) : Unit = {
@@ -261,6 +272,19 @@ object PsLogin {
import net.psforever.types.PlanetSideEmpire
Base(2).get.Faction = PlanetSideEmpire.VS //HART building C
Base(29).get.Faction = PlanetSideEmpire.NC //South Villa Gun Tower
+
+ GUID(500) match {
+ case Some(pad) =>
+ pad.Position = Vector3(3506.0f, 2820.0f, 92.0f)
+ pad.Orientation = Vector3(0f, 0f, 270.0f)
+ case None => ;
+ }
+ GUID(501) match {
+ case Some(pad) =>
+ pad.Position = Vector3(3508.9844f, 2895.961f, 92.296875f)
+ pad.Orientation = Vector3(0f, 0f, 270.0f)
+ case None => ;
+ }
}
}
diff --git a/pslogin/src/main/scala/WorldSessionActor.scala b/pslogin/src/main/scala/WorldSessionActor.scala
index 9c40a2800..2808cc1cd 100644
--- a/pslogin/src/main/scala/WorldSessionActor.scala
+++ b/pslogin/src/main/scala/WorldSessionActor.scala
@@ -17,8 +17,9 @@ import net.psforever.objects.inventory.{GridInventory, InventoryItem}
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
import net.psforever.objects.serverobject.doors.Door
import net.psforever.objects.serverobject.locks.IFFLock
+import net.psforever.objects.serverobject.pad.VehicleSpawnPad
import net.psforever.objects.serverobject.terminals.Terminal
-import net.psforever.objects.vehicles.{AccessPermissionGroup, Seat, VehicleLockState}
+import net.psforever.objects.vehicles.{AccessPermissionGroup, VehicleLockState}
import net.psforever.objects.zones.{InterstellarCluster, Zone}
import net.psforever.packet.game.objectcreate._
import net.psforever.types._
@@ -45,25 +46,43 @@ class WorldSessionActor extends Actor with MDCContextAware {
var continent : Zone = null
var progressBarValue : Option[Float] = None
- var clientKeepAlive : Cancellable = WorldSessionActor.DefaultCancellable
- var progressBarUpdate : Cancellable = WorldSessionActor.DefaultCancellable
+ var clientKeepAlive : Cancellable = DefaultCancellable.obj
+ var progressBarUpdate : Cancellable = DefaultCancellable.obj
override def postStop() = {
if(clientKeepAlive != null)
clientKeepAlive.cancel()
+ localService ! Service.Leave()
+ vehicleService ! Service.Leave()
+ avatarService ! Service.Leave()
+ LivePlayerList.Remove(sessionId) match {
+ case Some(tplayer) =>
+ tplayer.VehicleSeated match {
+ case Some(vehicle_guid) =>
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(tplayer.GUID, 0, true))
+ case None => ;
+ }
+ tplayer.VehicleOwned match {
+ case Some(vehicle_guid) =>
+ continent.GUID(vehicle_guid) match {
+ case Some(vehicle : Vehicle) =>
+ vehicle.Owner = None
+ //TODO temporary solution; to un-own, permit driver seat to Empire access level
+ vehicle.PermissionGroup(10, VehicleLockState.Empire.id)
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.SeatPermissions(tplayer.GUID, vehicle_guid, 10, VehicleLockState.Empire.id))
+ case _ => ;
+ }
+ case None => ;
+ }
- avatarService ! Service.Leave()
- localService ! Service.Leave()
- vehicleService ! Service.Leave()
- LivePlayerList.Remove(sessionId) match {
- case Some(tplayer) =>
- if(tplayer.HasGUID) {
- val guid = tplayer.GUID
- avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.ObjectDelete(guid, guid))
- taskResolver ! GUIDTask.UnregisterAvatar(tplayer)(continent.GUID)
- //TODO normally, the actual player avatar persists a minute or so after the user disconnects
- }
- case None => ;
+ if(tplayer.HasGUID) {
+ val guid = tplayer.GUID
+ avatarService ! AvatarServiceMessage(tplayer.Continent, AvatarAction.ObjectDelete(guid, guid))
+ taskResolver ! GUIDTask.UnregisterAvatar(tplayer)(continent.GUID)
+ //TODO normally, the actual player avatar persists a minute or so after the user disconnects
+ }
+
+ case None => ;
}
}
@@ -124,6 +143,11 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(PacketCoding.CreateGamePacket(0, ArmorChangedMessage(guid, suit, subtype)))
}
+ case AvatarResponse.ConcealPlayer() =>
+ if(player.GUID != guid) {
+ sendResponse(PacketCoding.CreateGamePacket(0, GenericObjectActionMessage(guid, 36)))
+ }
+
case AvatarResponse.EquipmentInHand(slot, item) =>
if(player.GUID != guid) {
val definition = item.Definition
@@ -186,7 +210,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
else {
val before = player.lastSeenStreamMessage(guid.guid)
- val dist = WorldSessionActor.DistanceSquared(player.Position, msg.pos)
+ val dist = Vector3.DistanceSquared(player.Position, msg.pos)
(msg.pos, now - before, dist)
}
@@ -280,9 +304,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
case VehicleResponse.MountVehicle(vehicle_guid, seat) =>
if(player.GUID != guid) {
sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(vehicle_guid, guid, seat)))
- if(player.VehicleOwned.contains(vehicle_guid)) { //simplistic vehicle ownership management
- player.VehicleOwned = None
- }
}
case VehicleResponse.SeatPermissions(vehicle_guid, seat_group, permission) =>
@@ -524,6 +545,19 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(PacketCoding.CreateGamePacket(0, ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, false)))
}
+ case Terminal.BuyVehicle(vehicle, loadout) =>
+ continent.Map.TerminalToSpawnPad.get(msg.terminal_guid.guid) match {
+ case Some(pad_guid) =>
+ val pad = continent.GUID(pad_guid).get.asInstanceOf[VehicleSpawnPad]
+ vehicle.Faction = tplayer.Faction
+ vehicle.Position = pad.Position
+ vehicle.Orientation = pad.Orientation
+ taskResolver ! RegisterNewVehicle(vehicle, pad)
+ sendResponse(PacketCoding.CreateGamePacket(0, ItemTransactionResultMessage(msg.terminal_guid, TransactionType.Learn, true)))
+ case None =>
+ log.error(s"$tplayer wanted to spawn a vehicle, but there was no spawn pad associated with terminal ${msg.terminal_guid} to accept it")
+ }
+
case Terminal.NoDeal() =>
log.warn(s"$tplayer made a request but the terminal rejected the order $msg")
sendResponse(PacketCoding.CreateGamePacket(0, ItemTransactionResultMessage(msg.terminal_guid, msg.transaction_type, false)))
@@ -533,9 +567,21 @@ class WorldSessionActor extends Actor with MDCContextAware {
reply match {
case Vehicle.CanSeatPlayer(vehicle, seat_num) =>
log.info(s"MountVehicleMsg: ${player.GUID} mounts ${vehicle.GUID} @ $seat_num")
+ vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle.GUID) //clear all deconstruction timers
val vehicle_guid : PlanetSideGUID = vehicle.GUID
tplayer.VehicleSeated = Some(vehicle_guid)
if(seat_num == 0) { //simplistic vehicle ownership management
+ vehicle.Owner match {
+ case Some(owner_guid) =>
+ continent.GUID(owner_guid) match {
+ case Some(previous_owner : Player) =>
+ if(previous_owner.VehicleOwned.contains(vehicle_guid)) {
+ previous_owner.VehicleOwned = None //simplistic ownership management, player loses vehicle ownership
+ }
+ case _ => ;
+ }
+ case None => ;
+ }
player.VehicleOwned = Some(vehicle_guid)
vehicle.Owner = Some(player.GUID)
}
@@ -558,12 +604,52 @@ class WorldSessionActor extends Actor with MDCContextAware {
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.MountVehicle(player_guid, vehicle_guid, seat_num))
case Vehicle.CannotSeatPlayer(vehicle, seat_num) =>
- val seat : Seat = vehicle.Seat(seat_num).get
log.warn(s"MountVehicleMsg: player $tplayer attempted to board vehicle ${vehicle.GUID}'s seat $seat_num, but was not allowed")
case _ => ;
}
+ case VehicleSpawnPad.ConcealPlayer =>
+ sendResponse(PacketCoding.CreateGamePacket(0, GenericObjectActionMessage(player.GUID, 36)))
+ avatarService ! AvatarServiceMessage(continent.Id, AvatarAction.ConcealPlayer(player.GUID))
+
+ case VehicleSpawnPad.LoadVehicle(vehicle, _/*pad*/) =>
+ val player_guid = player.GUID
+ val definition = vehicle.Definition
+ val objedtId = definition.ObjectId
+ val vehicle_guid = vehicle.GUID
+ val vdata = definition.Packet.ConstructorData(vehicle).get
+ sendResponse(PacketCoding.CreateGamePacket(0, ObjectCreateMessage(objedtId, vehicle_guid, vdata)))
+ continent.Transport ! Zone.SpawnVehicle(vehicle)
+ vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.LoadVehicle(player_guid, vehicle, objedtId, vehicle_guid, vdata))
+ sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(vehicle_guid, 22, 1L))) //mount points off?
+ //sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(vehicle_guid, 21, player_guid.guid))) //fte and ownership?
+ //sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(vehicle_guid, player_guid, 0)))
+ vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid) //cancel queue timeout delay
+ vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(vehicle, continent, 21L) //temporary drive away from pad delay
+ vehicle.Actor ! Vehicle.TrySeatPlayer(0, player)
+
+ case VehicleSpawnPad.PlayerSeatedInVehicle(vehicle) =>
+ vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(vehicle, continent, 21L) //sitting in the vehicle clears the drive away delay
+ val vehicle_guid = vehicle.GUID
+ sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(vehicle_guid, 22, 0L))) //mount points on?
+ //sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(vehicle_guid, 0, vehicle.Definition.MaxHealth)))
+ sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(vehicle_guid, 68, 0L))) //???
+ sendResponse(PacketCoding.CreateGamePacket(0, PlanetsideAttributeMessage(vehicle_guid, 113, 0L))) //???
+ ReloadVehicleAccessPermissions(vehicle)
+
+ case VehicleSpawnPad.SpawnPadBlockedWarning(vehicle, warning_count) =>
+ if(warning_count > 2) {
+ sendResponse(PacketCoding.CreateGamePacket(0, TriggerSoundMessage(TriggeredSound.Unknown14, vehicle.Position, 20, 1f)))
+ sendResponse(PacketCoding.CreateGamePacket(0,
+ ChatMsg(ChatMessageType.CMT_TELL, true, "", "\\#FYour vehicle is blocking the spawn pad, and will be deconstructed if not moved.", None))
+ )
+ }
+
+ case VehicleSpawnPad.SpawnPadUnblocked(vehicle_guid) =>
+ //vehicle has moved away from spawn pad after initial spawn
+ vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid) //cancel temporary drive away from pad delay
+
case ListAccountCharacters =>
import net.psforever.objects.definition.converter.CharacterSelectConverter
val gen : AtomicInteger = new AtomicInteger(1)
@@ -605,15 +691,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
failWithError(s"$tplayer failed to load anywhere")
}
- case VehicleLoaded(vehicle) =>
- val definition = vehicle.Definition
- val objedtId = definition.ObjectId
- val vehicle_guid = vehicle.GUID
- val vdata = definition.Packet.ConstructorData(vehicle).get
- sendResponse(PacketCoding.CreateGamePacket(0, ObjectCreateMessage(objedtId, vehicle_guid, vdata)))
- ReloadVehicleAccessPermissions(vehicle)
- continent.Transport ! Zone.SpawnVehicle(vehicle)
- vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.LoadVehicle(player.GUID, vehicle, objedtId, vehicle_guid, vdata))
+ case VehicleLoaded(_/*vehicle*/) => ;
+ //currently being handled by VehicleSpawnPad.LoadVehicle during testing phase
case Zone.ClientInitialization(/*initList*/_) =>
//TODO iterate over initList; for now, just do this
@@ -795,7 +874,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
}
var player : Player = null
- var harasser : Vehicle = null //TODO used in testing
def handleGamePkt(pkt : PlanetSideGamePacket) = pkt match {
case ConnectToWorldRequestMessage(server, token, majorVersion, minorVersion, revision, buildDate, unk) =>
@@ -803,18 +881,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
log.info(s"New world login to $server with Token:$token. $clientVersion")
//TODO begin temp player character auto-loading; remove later
import net.psforever.objects.GlobalDefinitions._
- val
- beamer1 = Tool(beamer)
- beamer1.AmmoSlots.head.Box = AmmoBox(energy_cell, 16)
- val
- suppressor1 = Tool(suppressor)
- suppressor1.AmmoSlots.head.Box = AmmoBox(bullet_9mm, 25)
- val
- forceblade1 = Tool(forceblade)
- forceblade1.AmmoSlots.head.Box = AmmoBox(melee_ammo)
-
player = Player("TestCharacter"+sessionId.toString, PlanetSideEmpire.VS, CharacterGender.Female, 41, 1)
- player.Position = Vector3(3674.8438f, 2726.789f, 91.15625f)
+ //player.Position = Vector3(3674.8438f, 2726.789f, 91.15625f)
+ player.Position = Vector3(3523.039f, 2855.5078f, 90.859375f)
player.Orientation = Vector3(0f, 0f, 90f)
player.Certifications += CertificationType.StandardAssault
player.Certifications += CertificationType.MediumAssault
@@ -823,9 +892,24 @@ class WorldSessionActor extends Actor with MDCContextAware {
player.Certifications += CertificationType.ReinforcedExoSuit
player.Certifications += CertificationType.ATV
player.Certifications += CertificationType.Harasser
- player.Slot(0).Equipment = beamer1
- player.Slot(2).Equipment = suppressor1
- player.Slot(4).Equipment = forceblade1
+ //
+ player.Certifications += CertificationType.GroundSupport
+ player.Certifications += CertificationType.GroundTransport
+ player.Certifications += CertificationType.Flail
+ player.Certifications += CertificationType.Switchblade
+ player.Certifications += CertificationType.AssaultBuggy
+ player.Certifications += CertificationType.ArmoredAssault1
+ player.Certifications += CertificationType.ArmoredAssault2
+ player.Certifications += CertificationType.AirCavalryScout
+ player.Certifications += CertificationType.AirCavalryAssault
+ player.Certifications += CertificationType.AirCavalryInterceptor
+ player.Certifications += CertificationType.AirSupport
+ player.Certifications += CertificationType.GalaxyGunship
+ player.Certifications += CertificationType.Phantasm
+ //player.ExoSuit = ExoSuitType.Infiltrator
+ player.Slot(0).Equipment = Tool(beamer)
+ player.Slot(2).Equipment = Tool(suppressor)
+ player.Slot(4).Equipment = Tool(forceblade)
player.Slot(6).Equipment = AmmoBox(bullet_9mm)
player.Slot(9).Equipment = AmmoBox(bullet_9mm)
player.Slot(12).Equipment = AmmoBox(bullet_9mm)
@@ -917,21 +1001,6 @@ class WorldSessionActor extends Actor with MDCContextAware {
})
ReloadVehicleAccessPermissions(vehicle)
})
- //TODO begin temp vehicle auto-loading
- import net.psforever.objects.GlobalDefinitions._
- if(continent.Vehicles.isEmpty) {
- harasser = Vehicle(two_man_assault_buggy)
- harasser.Position = Vector3(3674.8438f, 2730.789f, 91.15625f)
- harasser.Faction = PlanetSideEmpire.VS
- harasser.Orientation = Vector3(0f, 0f, 90f)
- harasser.Weapons(2).Equipment.get.asInstanceOf[Tool].AmmoSlots.head.Box = AmmoBox(bullet_12mm, 150)
- harasser.Trunk += 30 -> AmmoBox(bullet_12mm, 100)
- taskResolver ! RegisterNewVehicle(harasser)
- }
- else {
- harasser = continent.Vehicles.head //subsequent players after first
- }
- //TODO end temp vehicle auto-loading
avatarService ! Service.Join(player.Continent)
localService ! Service.Join(player.Continent)
vehicleService ! Service.Join(player.Continent)
@@ -1129,6 +1198,7 @@ class WorldSessionActor extends Actor with MDCContextAware {
continent.GUID(object_guid) match {
case Some(vehicle : Vehicle) =>
if(player.VehicleOwned.contains(object_guid) && vehicle.Owner.contains(player.GUID)) {
+ vehicleService ! VehicleServiceMessage.UnscheduleDeconstruction(object_guid)
vehicleService ! VehicleServiceMessage.RequestDeleteVehicle(vehicle, continent)
log.info(s"RequestDestroy: vehicle $object_guid")
}
@@ -1157,14 +1227,14 @@ class WorldSessionActor extends Actor with MDCContextAware {
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDeleteMessage(object_guid, 0)))
log.info("ObjectDelete: " + msg)
- case msg @ MoveItemMessage(item_guid, avatar_guid_1, avatar_guid_2, dest, unk1) =>
+ case msg @ MoveItemMessage(item_guid, source_guid, destination_guid, dest, unk1) =>
player.Find(item_guid) match {
case Some(index) =>
val indexSlot = player.Slot(index)
- var itemOpt = indexSlot.Equipment //use this to short circuit
+ var itemOpt : Option[Equipment] = indexSlot.Equipment
+ //use this to short circuit
val item = itemOpt.get
val destSlot = player.Slot(dest)
-
val destItem = if((-1 < dest && dest < 5) || dest == Player.FreeHandSlot) {
destSlot.Equipment match {
case Some(found) =>
@@ -1181,20 +1251,21 @@ class WorldSessionActor extends Actor with MDCContextAware {
case Success(_) | scala.util.Failure(_) => itemOpt = None; None //abort item move altogether
}
}
-
if(itemOpt.isDefined) {
- log.info(s"MoveItem: $item_guid moved from $avatar_guid_1 @ $index to $avatar_guid_1 @ $dest")
+ log.info(s"MoveItem: $item_guid moved from $source_guid @ $index to $source_guid @ $dest")
indexSlot.Equipment = None
- destItem match { //do we have a swap item?
+ destItem match {
+ //do we have a swap item?
case Some(entry) => //yes, swap
val item2 = entry.obj
player.Slot(entry.start).Equipment = None //remove item2 to make room for item
destSlot.Equipment = item //in case dest and index could block each other
(indexSlot.Equipment = entry.obj) match {
case Some(_) => //item and item2 swapped places successfully
- log.info(s"MoveItem: ${item2.GUID} swapped to $avatar_guid_1 @ $index")
+ log.info(s"MoveItem: ${item2.GUID} swapped to $source_guid @ $index")
//we must shuffle items around cleanly to avoid causing icons to "disappear"
- if(index == Player.FreeHandSlot) { //temporarily put in safe location, A -> C
+ if(index == Player.FreeHandSlot) {
+ //temporarily put in safe location, A -> C
sendResponse(PacketCoding.CreateGamePacket(0, ObjectDetachMessage(player.GUID, item.GUID, Vector3(0f, 0f, 0f), 0f, 0f, 0f))) //ground
}
else {
@@ -1217,13 +1288,13 @@ class WorldSessionActor extends Actor with MDCContextAware {
case None => //just move item over
destSlot.Equipment = item
}
- sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(avatar_guid_1, item_guid, dest)))
+ sendResponse(PacketCoding.CreateGamePacket(0, ObjectAttachMessage(source_guid, item_guid, dest)))
if(0 <= dest && dest < 5) {
avatarService ! AvatarServiceMessage(player.Continent, AvatarAction.EquipmentInHand(player.GUID, dest, item))
}
}
case None =>
- log.info(s"MoveItem: $avatar_guid_1 wanted to move the item $item_guid but could not find it")
+ log.info(s"MoveItem: $source_guid wanted to move the item $item_guid but could not find it")
}
case msg @ ChangeAmmoMessage(item_guid, unk1) =>
@@ -1384,6 +1455,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
player.VehicleSeated = None
sendResponse(PacketCoding.CreateGamePacket(0, DismountVehicleMsg(player_guid, unk1, unk2))) //should be safe; replace with ObjectDetachMessage later
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.DismountVehicle(player_guid, unk1, unk2))
+ if(obj.Seats.count(seat => seat.isOccupied) == 0) {
+ vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(obj, continent, 600L) //start vehicle decay (10m)
+ }
}
case None =>
log.warn(s"DismountVehicleMsg: can not find where player $player_guid is seated in vehicle $vehicle_guid")
@@ -1409,6 +1483,9 @@ class WorldSessionActor extends Actor with MDCContextAware {
seat.Occupant = None
tplayer.VehicleSeated = None
vehicleService ! VehicleServiceMessage(continent.Id, VehicleAction.KickPassenger(player_guid, unk1, unk2))
+ if(obj.Seats.count(seat => seat.isOccupied) == 0) {
+ vehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(obj, continent, 600L) //start vehicle decay (10m)
+ }
case None =>
log.warn(s"DismountVehicleMsg: can not find where player $player_guid is seated in vehicle $vehicle_guid")
}
@@ -1733,12 +1810,16 @@ class WorldSessionActor extends Actor with MDCContextAware {
* @see `RegisterVehicle`
* @return a `TaskResolver.GiveTask` message
*/
- def RegisterNewVehicle(obj : Vehicle) : TaskResolver.GiveTask = {
+ def RegisterNewVehicle(obj : Vehicle, pad : VehicleSpawnPad) : TaskResolver.GiveTask = {
TaskResolver.GiveTask(
new Task() {
private val localVehicle = obj
private val localAnnounce = vehicleService
private val localSession : String = sessionId.toString
+ private val localPad = pad.Actor
+ private val localPlayer = player
+ private val localVehicleService = vehicleService
+ private val localZone = continent
override def isComplete : Task.Resolution.Value = {
if(localVehicle.Actor != ActorRef.noSender) {
@@ -1751,6 +1832,8 @@ class WorldSessionActor extends Actor with MDCContextAware {
def Execute(resolver : ActorRef) : Unit = {
localAnnounce ! VehicleServiceMessage.GiveActorControl(obj, localSession)
+ localPad ! VehicleSpawnPad.VehicleOrder(localPlayer, localVehicle)
+ localVehicleService ! VehicleServiceMessage.DelayedVehicleDeconstruction(localVehicle, localZone, 60L)
resolver ! scala.util.Success(this)
}
}, List(RegisterVehicle(obj)))
@@ -1945,35 +2028,4 @@ object WorldSessionActor {
delta : Float,
completeAction : () => Unit,
tickAction : Option[() => Unit] = None)
- /**
- * A placeholder `Cancellable` object.
- */
- private final val DefaultCancellable = new Cancellable() {
- def cancel : Boolean = true
- def isCancelled() : Boolean = true
- }
-
- /**
- * Calculate the actual distance between two points.
- * @param pos1 the first point
- * @param pos2 the second point
- * @return the distance
- */
- def Distance(pos1 : Vector3, pos2 : Vector3) : Float = {
- math.sqrt(DistanceSquared(pos1, pos2)).toFloat
- }
-
- /**
- * Calculate the squared distance between two points.
- * Though some time is saved care must be taken that any comparative distance is also squared.
- * @param pos1 the first point
- * @param pos2 the second point
- * @return the distance
- */
- def DistanceSquared(pos1 : Vector3, pos2 : Vector3) : Float = {
- val dx : Float = pos1.x - pos2.x
- val dy : Float = pos1.y - pos2.y
- val dz : Float = pos1.z - pos2.z
- (dx * dx) + (dy * dy) + (dz * dz)
- }
}
diff --git a/pslogin/src/main/scala/services/avatar/AvatarAction.scala b/pslogin/src/main/scala/services/avatar/AvatarAction.scala
index 451b38732..3b9f54e65 100644
--- a/pslogin/src/main/scala/services/avatar/AvatarAction.scala
+++ b/pslogin/src/main/scala/services/avatar/AvatarAction.scala
@@ -10,6 +10,7 @@ object AvatarAction {
trait Action
final case class ArmorChanged(player_guid : PlanetSideGUID, suit : ExoSuitType.Value, subtype : Int) extends Action
+ final case class ConcealPlayer(player_guid : PlanetSideGUID) extends Action
//final case class DropItem(pos : Vector3, orient : Vector3, item : PlanetSideGUID) extends Action
final case class EquipmentInHand(player_guid : PlanetSideGUID, slot : Int, item : Equipment) extends Action
final case class EquipmentOnGround(player_guid : PlanetSideGUID, pos : Vector3, orient : Vector3, item : Equipment) extends Action
diff --git a/pslogin/src/main/scala/services/avatar/AvatarResponse.scala b/pslogin/src/main/scala/services/avatar/AvatarResponse.scala
index 87f37e841..75763c8c8 100644
--- a/pslogin/src/main/scala/services/avatar/AvatarResponse.scala
+++ b/pslogin/src/main/scala/services/avatar/AvatarResponse.scala
@@ -10,6 +10,7 @@ object AvatarResponse {
trait Response
final case class ArmorChanged(suit : ExoSuitType.Value, subtype : Int) extends Response
+ final case class ConcealPlayer() extends Response
//final case class DropItem(pos : Vector3, orient : Vector3, item : PlanetSideGUID) extends Response
final case class EquipmentInHand(slot : Int, item : Equipment) extends Response
final case class EquipmentOnGround(pos : Vector3, orient : Vector3, item : Equipment) extends Response
diff --git a/pslogin/src/main/scala/services/avatar/AvatarService.scala b/pslogin/src/main/scala/services/avatar/AvatarService.scala
index 0e3c6f16f..5148b2733 100644
--- a/pslogin/src/main/scala/services/avatar/AvatarService.scala
+++ b/pslogin/src/main/scala/services/avatar/AvatarService.scala
@@ -33,6 +33,10 @@ class AvatarService extends Actor {
AvatarEvents.publish(
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.ArmorChanged(suit, subtype))
)
+ case AvatarAction.ConcealPlayer(player_guid) =>
+ AvatarEvents.publish(
+ AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.ConcealPlayer())
+ )
case AvatarAction.EquipmentInHand(player_guid, slot, obj) =>
AvatarEvents.publish(
AvatarServiceResponse(s"/$forChannel/Avatar", player_guid, AvatarResponse.EquipmentInHand(slot, obj))
diff --git a/pslogin/src/main/scala/services/local/support/DoorCloseActor.scala b/pslogin/src/main/scala/services/local/support/DoorCloseActor.scala
index a2ca622cf..10413da44 100644
--- a/pslogin/src/main/scala/services/local/support/DoorCloseActor.scala
+++ b/pslogin/src/main/scala/services/local/support/DoorCloseActor.scala
@@ -2,6 +2,7 @@
package services.local.support
import akka.actor.{Actor, Cancellable}
+import net.psforever.objects.DefaultCancellable
import net.psforever.objects.serverobject.doors.Door
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.PlanetSideGUID
@@ -16,7 +17,7 @@ import scala.concurrent.duration._
*/
class DoorCloseActor() extends Actor {
/** The periodic `Executor` that checks for doors to be closed */
- private var doorCloserTrigger : Cancellable = DoorCloseActor.DefaultCloser
+ private var doorCloserTrigger : Cancellable = DefaultCancellable.obj
/** A `List` of currently open doors */
private var openDoors : List[DoorCloseActor.DoorEntry] = Nil
//private[this] val log = org.log4s.getLogger
@@ -98,11 +99,6 @@ object DoorCloseActor {
/** The wait before an open door closes; as a `FiniteDuration` for `Executor` simplicity */
private final val timeout : FiniteDuration = timeout_time nanoseconds
- private final val DefaultCloser : Cancellable = new Cancellable() {
- override def cancel : Boolean = true
- override def isCancelled : Boolean = true
- }
-
/**
* Message that carries information about a door that has been opened.
* @param door the door object
diff --git a/pslogin/src/main/scala/services/local/support/HackClearActor.scala b/pslogin/src/main/scala/services/local/support/HackClearActor.scala
index 76a7e7f92..52a402804 100644
--- a/pslogin/src/main/scala/services/local/support/HackClearActor.scala
+++ b/pslogin/src/main/scala/services/local/support/HackClearActor.scala
@@ -2,6 +2,7 @@
package services.local.support
import akka.actor.{Actor, Cancellable}
+import net.psforever.objects.DefaultCancellable
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
import net.psforever.objects.zones.Zone
import net.psforever.packet.game.PlanetSideGUID
@@ -16,7 +17,7 @@ import scala.concurrent.duration._
*/
class HackClearActor() extends Actor {
/** The periodic `Executor` that checks for server objects to be unhacked */
- private var clearTrigger : Cancellable = HackClearActor.DefaultClearer
+ private var clearTrigger : Cancellable = DefaultCancellable.obj
/** A `List` of currently hacked server objects */
private var hackedObjects : List[HackClearActor.HackEntry] = Nil
//private[this] val log = org.log4s.getLogger
@@ -99,11 +100,6 @@ object HackClearActor {
/** The wait before a server object is to unhack; as a `FiniteDuration` for `Executor` simplicity */
private final val timeout : FiniteDuration = timeout_time nanoseconds
- private final val DefaultClearer : Cancellable = new Cancellable() {
- override def cancel : Boolean = true
- override def isCancelled : Boolean = true
- }
-
/**
* Message that carries information about a server object that has been hacked.
* @param target the server object
diff --git a/pslogin/src/main/scala/services/vehicle/VehicleService.scala b/pslogin/src/main/scala/services/vehicle/VehicleService.scala
index 12842a95b..7f49f6eda 100644
--- a/pslogin/src/main/scala/services/vehicle/VehicleService.scala
+++ b/pslogin/src/main/scala/services/vehicle/VehicleService.scala
@@ -2,12 +2,13 @@
package services.vehicle
import akka.actor.{Actor, ActorRef, Props}
-import services.vehicle.support.{DeconstructionActor, VehicleContextActor}
+import services.vehicle.support.{DeconstructionActor, DelayedDeconstructionActor, VehicleContextActor}
import services.{GenericEventBus, Service}
class VehicleService extends Actor {
private val vehicleContext : ActorRef = context.actorOf(Props[VehicleContextActor], "vehicle-context-root")
private val vehicleDecon : ActorRef = context.actorOf(Props[DeconstructionActor], "vehicle-decon-agent")
+ private val vehicleDelayedDecon : ActorRef = context.actorOf(Props[DelayedDeconstructionActor], "vehicle-delayed-decon-agent")
vehicleDecon ! DeconstructionActor.RequestTaskResolver
private [this] val log = org.log4s.getLogger
@@ -79,6 +80,14 @@ class VehicleService extends Actor {
case VehicleServiceMessage.RequestDeleteVehicle(vehicle, continent) =>
vehicleDecon ! DeconstructionActor.RequestDeleteVehicle(vehicle, continent)
+ //message to DelayedDeconstructionActor
+ case VehicleServiceMessage.DelayedVehicleDeconstruction(vehicle, zone, timeAlive) =>
+ vehicleDelayedDecon ! DelayedDeconstructionActor.ScheduleDeconstruction(vehicle, zone, timeAlive)
+
+ //message to DelayedDeconstructionActor
+ case VehicleServiceMessage.UnscheduleDeconstruction(vehicle_guid) =>
+ vehicleDelayedDecon ! DelayedDeconstructionActor.UnscheduleDeconstruction(vehicle_guid)
+
//response from DeconstructionActor
case DeconstructionActor.DeleteVehicle(vehicle_guid, zone_id) =>
VehicleEvents.publish(
diff --git a/pslogin/src/main/scala/services/vehicle/VehicleServiceMessage.scala b/pslogin/src/main/scala/services/vehicle/VehicleServiceMessage.scala
index c3e1c4804..48c03dab3 100644
--- a/pslogin/src/main/scala/services/vehicle/VehicleServiceMessage.scala
+++ b/pslogin/src/main/scala/services/vehicle/VehicleServiceMessage.scala
@@ -3,11 +3,14 @@ package services.vehicle
import net.psforever.objects.Vehicle
import net.psforever.objects.zones.Zone
+import net.psforever.packet.game.PlanetSideGUID
final case class VehicleServiceMessage(forChannel : String, actionMessage : VehicleAction.Action)
object VehicleServiceMessage {
+ final case class DelayedVehicleDeconstruction(vehicle : Vehicle, continent : Zone, timeAlive : Long)
final case class GiveActorControl(vehicle : Vehicle, actorName : String)
final case class RevokeActorControl(vehicle : Vehicle)
final case class RequestDeleteVehicle(vehicle : Vehicle, continent : Zone)
+ final case class UnscheduleDeconstruction(vehicle_guid : PlanetSideGUID)
}
diff --git a/pslogin/src/main/scala/services/vehicle/support/DeconstructionActor.scala b/pslogin/src/main/scala/services/vehicle/support/DeconstructionActor.scala
index 4d09b9272..f19d47aa9 100644
--- a/pslogin/src/main/scala/services/vehicle/support/DeconstructionActor.scala
+++ b/pslogin/src/main/scala/services/vehicle/support/DeconstructionActor.scala
@@ -2,7 +2,7 @@
package services.vehicle.support
import akka.actor.{Actor, ActorRef, Cancellable}
-import net.psforever.objects.Vehicle
+import net.psforever.objects.{DefaultCancellable, Vehicle}
import net.psforever.objects.guid.TaskResolver
import net.psforever.objects.vehicles.Seat
import net.psforever.objects.zones.Zone
@@ -20,11 +20,13 @@ import scala.concurrent.duration._
* A reference to a vehicle should be passed to this object as soon as it is going to be cleaned-up from the game world.
* Once accepted, only a few seconds will remain before the vehicle is deleted.
* To ensure that no players are lost in the deletion, all occupants of the vehicle are kicked out.
- * Furthermore, the vehicle is rendered "dead" and inaccessible right up to the point where it is removed.
+ * Furthermore, the vehicle is rendered "dead" and inaccessible right up to the point where it is removed.
+ *
+ * This `Actor` is intended to sit on top of the event system that handles broadcast messaging.
*/
class DeconstructionActor extends Actor {
/** The periodic `Executor` that scraps the next vehicle on the list */
- private var scrappingProcess : Cancellable = DeconstructionActor.DefaultProcess
+ private var scrappingProcess : Cancellable = DefaultCancellable.obj
/** A `List` of currently doomed vehicles */
private var vehicles : List[DeconstructionActor.VehicleEntry] = Nil
/** The manager that helps unregister the vehicle from its current GUID scope */
@@ -171,11 +173,6 @@ object DeconstructionActor {
/** The wait before completely deleting a vehicle; as a `FiniteDuration` for `Executor` simplicity */
private final val timeout : FiniteDuration = timeout_time nanoseconds
- private final val DefaultProcess : Cancellable = new Cancellable() {
- override def cancel : Boolean = true
- override def isCancelled : Boolean = true
- }
-
final case class RequestTaskResolver()
/**
diff --git a/pslogin/src/main/scala/services/vehicle/support/DelayedDeconstructionActor.scala b/pslogin/src/main/scala/services/vehicle/support/DelayedDeconstructionActor.scala
new file mode 100644
index 000000000..2c508ad8d
--- /dev/null
+++ b/pslogin/src/main/scala/services/vehicle/support/DelayedDeconstructionActor.scala
@@ -0,0 +1,104 @@
+// Copyright (c) 2017 PSForever
+package services.vehicle.support
+
+import akka.actor.{Actor, Cancellable}
+import net.psforever.objects.{DefaultCancellable, Vehicle}
+import net.psforever.objects.zones.Zone
+import net.psforever.packet.game.PlanetSideGUID
+import services.vehicle.VehicleServiceMessage
+
+import scala.concurrent.duration._
+
+/**
+ * Maintain and curate a list of timed `vehicle` object deconstruction tasks.
+ *
+ * These tasks are queued or dismissed by player activity but they are executed independent of player activity.
+ * A common disconnected cause of deconstruction is neglect for an extended period of time.
+ * At that point, the original owner of the vehicle no longer matters.
+ * Deconstruction neglect, however, is averted by having someone become seated.
+ * A realized deconstruction is entirely based on a fixed interval after an unresolved request has been received.
+ * The actual process of deconstructing the vehicle and cleaning up its resources is performed by an external agent.
+ *
+ * This `Actor` is intended to sit on top of the event system that handles broadcast messaging.
+ */
+class DelayedDeconstructionActor extends Actor {
+ /** The periodic `Executor` that scraps the next vehicle on the list */
+ private var monitor : Cancellable = DefaultCancellable.obj
+ /** A `List` of currently doomed vehicles */
+ private var vehicles : List[DelayedDeconstructionActor.VehicleEntry] = Nil
+ private[this] val log = org.log4s.getLogger
+ private[this] def trace(msg : String) : Unit = log.trace(msg)
+
+
+ def receive : Receive = {
+ case DelayedDeconstructionActor.ScheduleDeconstruction(vehicle, zone, timeAlive) =>
+ trace(s"delayed deconstruction order for $vehicle in $timeAlive")
+ vehicles = vehicles :+ DelayedDeconstructionActor.VehicleEntry(vehicle, zone, timeAlive * 1000000000L)
+ if(vehicles.size == 1) { //we were the only entry so the event must be started from scratch
+ import scala.concurrent.ExecutionContext.Implicits.global
+ monitor = context.system.scheduler.scheduleOnce(DelayedDeconstructionActor.periodicTest, self, DelayedDeconstructionActor.PeriodicTaskCulling)
+ }
+
+ case DelayedDeconstructionActor.UnscheduleDeconstruction(vehicle_guid) =>
+ //all tasks for this vehicle are cleared from the queue
+ //clear any task that is no longer valid by determination of unregistered GUID
+ val before = vehicles.length
+ vehicles = vehicles.filter(entry => { !entry.vehicle.HasGUID || entry.vehicle.GUID != vehicle_guid })
+ trace(s"attempting to clear deconstruction order for vehicle $vehicle_guid, found ${before - vehicles.length}")
+ if(vehicles.isEmpty) {
+ monitor.cancel
+ }
+
+ case DelayedDeconstructionActor.PeriodicTaskCulling =>
+ //filter the list of deconstruction tasks for any that are need to be triggered
+ monitor.cancel
+ val now : Long = System.nanoTime
+ val (vehiclesToDecon, vehiclesRemain) = vehicles.partition(entry => { now - entry.logTime >= entry.survivalTime })
+ vehicles = vehiclesRemain
+ trace(s"vehicle culling - ${vehiclesToDecon.length} deconstruction tasks found")
+ vehiclesToDecon.foreach(entry => { context.parent ! VehicleServiceMessage.RequestDeleteVehicle(entry.vehicle, entry.zone) })
+ if(vehiclesRemain.nonEmpty) {
+ import scala.concurrent.ExecutionContext.Implicits.global
+ monitor = context.system.scheduler.scheduleOnce(DelayedDeconstructionActor.periodicTest, self, DelayedDeconstructionActor.PeriodicTaskCulling)
+ }
+
+ case _ => ;
+ }
+}
+
+object DelayedDeconstructionActor {
+ /**
+ * Timer for the repeating executor.
+ */
+ private final val periodicTest : FiniteDuration = 5000000000L nanoseconds //5s
+
+ /**
+ * Queue a future vehicle deconstruction action.
+ * @param vehicle the `Vehicle` object
+ * @param zone the `Zone` that the vehicle currently occupies
+ * @param survivalTime how long until the vehicle will be deconstructed in seconds
+ */
+ final case class ScheduleDeconstruction(vehicle : Vehicle, zone : Zone, survivalTime : Long)
+
+ /**
+ * Dequeue a vehicle from being deconstructed.
+ * @param vehicle_guid the vehicle
+ */
+ final case class UnscheduleDeconstruction(vehicle_guid : PlanetSideGUID)
+
+ /**
+ * A message the `Actor` sends to itself.
+ * The trigger for the periodic deconstruction task.
+ */
+ private final case class PeriodicTaskCulling()
+
+ /**
+ * An entry that stores vehicle deconstruction tasks.
+ * @param vehicle the `Vehicle` object
+ * @param zone the `Zone` that the vehicle currently occupies
+ * @param survivalTime how long until the vehicle will be deconstructed in nanoseconds
+ * @param logTime when this deconstruction request was initially created in nanoseconds;
+ * initialized by default to a "now"
+ */
+ private final case class VehicleEntry(vehicle : Vehicle, zone : Zone, survivalTime : Long, logTime : Long = System.nanoTime())
+}
diff --git a/pslogin/src/main/scala/services/vehicle/support/VehicleContextActor.scala b/pslogin/src/main/scala/services/vehicle/support/VehicleContextActor.scala
index 756a31a34..ebc954aad 100644
--- a/pslogin/src/main/scala/services/vehicle/support/VehicleContextActor.scala
+++ b/pslogin/src/main/scala/services/vehicle/support/VehicleContextActor.scala
@@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package services.vehicle.support
-import akka.actor.{Actor, Props}
+import akka.actor.{Actor, ActorRef, Props}
import net.psforever.objects.vehicles.VehicleControl
import services.vehicle.VehicleServiceMessage
@@ -15,15 +15,18 @@ import services.vehicle.VehicleServiceMessage
*
* The only purpose of this `Actor` is to allow vehicles to borrow a context for the purpose of `Actor` creation.
* It is also be allowed to be responsible for cleaning up that context.
- * (In reality, it can be cleaned up anywhere a `PoisonPill` can be sent.)
+ * (In reality, it can be cleaned up anywhere a `PoisonPill` can be sent.)
+ *
+ * This `Actor` is intended to sit on top of the event system that handles broadcast messaging.
*/
class VehicleContextActor() extends Actor {
def receive : Receive = {
case VehicleServiceMessage.GiveActorControl(vehicle, actorName) =>
- vehicle.Actor = context.actorOf(Props(classOf[VehicleControl], vehicle), s"${vehicle.Definition.Name}_$actorName")
+ vehicle.Actor = context.actorOf(Props(classOf[VehicleControl], vehicle), s"${vehicle.Definition.Name}_$actorName.${System.nanoTime()}")
case VehicleServiceMessage.RevokeActorControl(vehicle) =>
vehicle.Actor ! akka.actor.PoisonPill
+ vehicle.Actor = ActorRef.noSender
case _ => ;
}