mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-07-15 08:24:39 +00:00
Damage Fix, and Stuff (#235)
* redid splash damage radial degrade calculations; lasher damage fixed to 6/0 or 2/4 depending on armor; fixed direct hit distance for weapons that act like slash weapons; gave Falcon a valid projectile * delayed resource silo startup to avoid crash; discovered issue with MAX armor resulting from incorrect manipulation of inventory items during suit transfer * modifications to consider a specific modifier that exists on some vehicles and armored equipment called Subtract, a DamageProfile that reduces damage due to a set flag; manually controlling damage tick marks rather than relying only on HitHint (from client) * Tools now have default firemodes (temporary?); ammo gotten from loadouts is always full; loadouts and exo-suits juggle armor values differently on being changed; log messages for damage to players and vehicles * weapons with one (last) shot need support communicating that one (last) shot * fixing tests * correcting the codec for BindPlayerMessage * changed wording that identifies the damage log entries * switching exosuit no longer causes butterfingers * extending exosuit swap armor value changes to infantry loadout changes * ranges removed from non-vehicle containers * enabled partial damage functionality to facility turrets * BindPlayerMessage replacing BattleplanMessage for purposes of depicting the closest AMS spawn point; specific enums in relation to spawning in BPM and SpawnRequestMessage * rewrote exo-suit switching and loadout switching code, paying extra-special attention for the needs of MAX's * quick amendment for previous commit * switching from mount point check to seat checks in VehicleRemover; started refactoring of Cargo functions before realizing how complicated the full effort would be, so these changes are merely wrapping object identification by GUID * adding a minor server delay to terminal operations
This commit is contained in:
parent
7cec0bb577
commit
4eca226b5b
41 changed files with 900 additions and 453 deletions
|
|
@ -85,6 +85,10 @@ class SpecialExoSuitDefinition(private val suitType : ExoSuitType.Value) extends
|
||||||
obj.MaxArmor = MaxArmor
|
obj.MaxArmor = MaxArmor
|
||||||
obj.InventoryScale = InventoryScale
|
obj.InventoryScale = InventoryScale
|
||||||
obj.InventoryOffset = InventoryOffset
|
obj.InventoryOffset = InventoryOffset
|
||||||
|
obj.Subtract.Damage0 = Subtract.Damage0
|
||||||
|
obj.Subtract.Damage1 = Subtract.Damage1
|
||||||
|
obj.Subtract.Damage2 = Subtract.Damage2
|
||||||
|
obj.Subtract.Damage3 = Subtract.Damage3
|
||||||
obj.ResistanceDirectHit = ResistanceDirectHit
|
obj.ResistanceDirectHit = ResistanceDirectHit
|
||||||
obj.ResistanceSplash = ResistanceSplash
|
obj.ResistanceSplash = ResistanceSplash
|
||||||
obj.ResistanceAggravated = ResistanceAggravated
|
obj.ResistanceAggravated = ResistanceAggravated
|
||||||
|
|
@ -166,6 +170,7 @@ object ExoSuitDefinition {
|
||||||
MAX.InventoryOffset = 6
|
MAX.InventoryOffset = 6
|
||||||
MAX.Holster(0, EquipmentSize.Max)
|
MAX.Holster(0, EquipmentSize.Max)
|
||||||
MAX.Holster(4, EquipmentSize.Melee)
|
MAX.Holster(4, EquipmentSize.Melee)
|
||||||
|
MAX.Subtract.Damage1 = -2
|
||||||
MAX.ResistanceDirectHit = 6
|
MAX.ResistanceDirectHit = 6
|
||||||
MAX.ResistanceSplash = 35
|
MAX.ResistanceSplash = 35
|
||||||
MAX.ResistanceAggravated = 10
|
MAX.ResistanceAggravated = 10
|
||||||
|
|
|
||||||
|
|
@ -555,11 +555,19 @@ object GlobalDefinitions {
|
||||||
|
|
||||||
val maelstrom = ToolDefinition(ObjectClass.maelstrom)
|
val maelstrom = ToolDefinition(ObjectClass.maelstrom)
|
||||||
|
|
||||||
val phoenix = ToolDefinition(ObjectClass.phoenix) //decimator
|
val phoenix = new ToolDefinition(ObjectClass.phoenix) {
|
||||||
|
override def NextFireModeIndex(index : Int) : Int = index
|
||||||
|
} //decimator
|
||||||
|
|
||||||
val striker = ToolDefinition(ObjectClass.striker)
|
val striker = new ToolDefinition(ObjectClass.striker) {
|
||||||
|
override def NextFireModeIndex(index : Int) : Int = index
|
||||||
|
DefaultFireModeIndex = 1
|
||||||
|
}
|
||||||
|
|
||||||
val hunterseeker = ToolDefinition(ObjectClass.hunterseeker) //phoenix
|
val hunterseeker = new ToolDefinition(ObjectClass.hunterseeker) {
|
||||||
|
override def NextFireModeIndex(index : Int) : Int = index
|
||||||
|
DefaultFireModeIndex = 1
|
||||||
|
} //phoenix
|
||||||
|
|
||||||
val lancer = ToolDefinition(ObjectClass.lancer)
|
val lancer = ToolDefinition(ObjectClass.lancer)
|
||||||
|
|
||||||
|
|
@ -573,7 +581,7 @@ object GlobalDefinitions {
|
||||||
|
|
||||||
val bolt_driver = ToolDefinition(ObjectClass.bolt_driver)
|
val bolt_driver = ToolDefinition(ObjectClass.bolt_driver)
|
||||||
|
|
||||||
val oicw = ToolDefinition(ObjectClass.oicw) //scorpion
|
val oicw = ToolDefinition(ObjectClass.oicw)
|
||||||
|
|
||||||
val flamethrower = ToolDefinition(ObjectClass.flamethrower)
|
val flamethrower = ToolDefinition(ObjectClass.flamethrower)
|
||||||
|
|
||||||
|
|
@ -718,7 +726,9 @@ object GlobalDefinitions {
|
||||||
|
|
||||||
val lightgunship_weapon_system = ToolDefinition(ObjectClass.lightgunship_weapon_system)
|
val lightgunship_weapon_system = ToolDefinition(ObjectClass.lightgunship_weapon_system)
|
||||||
|
|
||||||
val wasp_weapon_system = ToolDefinition(ObjectClass.wasp_weapon_system)
|
val wasp_weapon_system = new ToolDefinition(ObjectClass.wasp_weapon_system) {
|
||||||
|
override def NextFireModeIndex(index : Int) : Int = index
|
||||||
|
}
|
||||||
|
|
||||||
val liberator_weapon_system = ToolDefinition(ObjectClass.liberator_weapon_system)
|
val liberator_weapon_system = ToolDefinition(ObjectClass.liberator_weapon_system)
|
||||||
|
|
||||||
|
|
@ -3924,6 +3934,7 @@ object GlobalDefinitions {
|
||||||
nchev_falcon.Name = "nchev_falcon"
|
nchev_falcon.Name = "nchev_falcon"
|
||||||
nchev_falcon.Size = EquipmentSize.Max
|
nchev_falcon.Size = EquipmentSize.Max
|
||||||
nchev_falcon.AmmoTypes += falcon_ammo
|
nchev_falcon.AmmoTypes += falcon_ammo
|
||||||
|
nchev_falcon.ProjectileTypes += falcon_projectile
|
||||||
nchev_falcon.FireModes += new FireModeDefinition
|
nchev_falcon.FireModes += new FireModeDefinition
|
||||||
nchev_falcon.FireModes.head.AmmoTypeIndices += 0
|
nchev_falcon.FireModes.head.AmmoTypeIndices += 0
|
||||||
nchev_falcon.FireModes.head.AmmoSlotIndex = 0
|
nchev_falcon.FireModes.head.AmmoSlotIndex = 0
|
||||||
|
|
@ -4763,6 +4774,7 @@ object GlobalDefinitions {
|
||||||
threemanheavybuggy.TrunkOffset = 30
|
threemanheavybuggy.TrunkOffset = 30
|
||||||
threemanheavybuggy.AutoPilotSpeeds = (22, 8)
|
threemanheavybuggy.AutoPilotSpeeds = (22, 8)
|
||||||
threemanheavybuggy.DestroyedModel = Some(DestroyedVehicle.ThreeManHeavyBuggy)
|
threemanheavybuggy.DestroyedModel = Some(DestroyedVehicle.ThreeManHeavyBuggy)
|
||||||
|
threemanheavybuggy.Subtract.Damage1 = 5
|
||||||
|
|
||||||
twomanheavybuggy.Name = "twomanheavybuggy"
|
twomanheavybuggy.Name = "twomanheavybuggy"
|
||||||
twomanheavybuggy.MaxHealth = 1800
|
twomanheavybuggy.MaxHealth = 1800
|
||||||
|
|
@ -4779,6 +4791,7 @@ object GlobalDefinitions {
|
||||||
twomanheavybuggy.TrunkOffset = 30
|
twomanheavybuggy.TrunkOffset = 30
|
||||||
twomanheavybuggy.AutoPilotSpeeds = (22, 8)
|
twomanheavybuggy.AutoPilotSpeeds = (22, 8)
|
||||||
twomanheavybuggy.DestroyedModel = Some(DestroyedVehicle.TwoManHeavyBuggy)
|
twomanheavybuggy.DestroyedModel = Some(DestroyedVehicle.TwoManHeavyBuggy)
|
||||||
|
twomanheavybuggy.Subtract.Damage1 = 5
|
||||||
|
|
||||||
twomanhoverbuggy.Name = "twomanhoverbuggy"
|
twomanhoverbuggy.Name = "twomanhoverbuggy"
|
||||||
twomanhoverbuggy.MaxHealth = 1600
|
twomanhoverbuggy.MaxHealth = 1600
|
||||||
|
|
@ -4795,6 +4808,7 @@ object GlobalDefinitions {
|
||||||
twomanhoverbuggy.TrunkOffset = 30
|
twomanhoverbuggy.TrunkOffset = 30
|
||||||
twomanhoverbuggy.AutoPilotSpeeds = (22, 10)
|
twomanhoverbuggy.AutoPilotSpeeds = (22, 10)
|
||||||
twomanhoverbuggy.DestroyedModel = Some(DestroyedVehicle.TwoManHoverBuggy)
|
twomanhoverbuggy.DestroyedModel = Some(DestroyedVehicle.TwoManHoverBuggy)
|
||||||
|
twomanhoverbuggy.Subtract.Damage1 = 5
|
||||||
|
|
||||||
mediumtransport.Name = "mediumtransport"
|
mediumtransport.Name = "mediumtransport"
|
||||||
mediumtransport.MaxHealth = 2500
|
mediumtransport.MaxHealth = 2500
|
||||||
|
|
@ -4818,6 +4832,7 @@ object GlobalDefinitions {
|
||||||
mediumtransport.TrunkOffset = 30
|
mediumtransport.TrunkOffset = 30
|
||||||
mediumtransport.AutoPilotSpeeds = (18, 6)
|
mediumtransport.AutoPilotSpeeds = (18, 6)
|
||||||
mediumtransport.DestroyedModel = Some(DestroyedVehicle.MediumTransport)
|
mediumtransport.DestroyedModel = Some(DestroyedVehicle.MediumTransport)
|
||||||
|
mediumtransport.Subtract.Damage1 = 7
|
||||||
|
|
||||||
battlewagon.Name = "battlewagon"
|
battlewagon.Name = "battlewagon"
|
||||||
battlewagon.MaxHealth = 2500
|
battlewagon.MaxHealth = 2500
|
||||||
|
|
@ -4868,6 +4883,7 @@ object GlobalDefinitions {
|
||||||
thunderer.TrunkOffset = 30
|
thunderer.TrunkOffset = 30
|
||||||
thunderer.AutoPilotSpeeds = (18, 6)
|
thunderer.AutoPilotSpeeds = (18, 6)
|
||||||
thunderer.DestroyedModel = Some(DestroyedVehicle.MediumTransport)
|
thunderer.DestroyedModel = Some(DestroyedVehicle.MediumTransport)
|
||||||
|
thunderer.Subtract.Damage1 = 7
|
||||||
|
|
||||||
aurora.Name = "aurora"
|
aurora.Name = "aurora"
|
||||||
aurora.MaxHealth = 2500
|
aurora.MaxHealth = 2500
|
||||||
|
|
@ -4891,6 +4907,7 @@ object GlobalDefinitions {
|
||||||
aurora.TrunkOffset = 30
|
aurora.TrunkOffset = 30
|
||||||
aurora.AutoPilotSpeeds = (18, 6)
|
aurora.AutoPilotSpeeds = (18, 6)
|
||||||
aurora.DestroyedModel = Some(DestroyedVehicle.MediumTransport)
|
aurora.DestroyedModel = Some(DestroyedVehicle.MediumTransport)
|
||||||
|
aurora.Subtract.Damage1 = 7
|
||||||
|
|
||||||
apc_tr.Name = "apc_tr"
|
apc_tr.Name = "apc_tr"
|
||||||
apc_tr.MaxHealth = 6000
|
apc_tr.MaxHealth = 6000
|
||||||
|
|
@ -5043,6 +5060,7 @@ object GlobalDefinitions {
|
||||||
lightning.TrunkOffset = 30
|
lightning.TrunkOffset = 30
|
||||||
lightning.AutoPilotSpeeds = (20, 8)
|
lightning.AutoPilotSpeeds = (20, 8)
|
||||||
lightning.DestroyedModel = Some(DestroyedVehicle.Lightning)
|
lightning.DestroyedModel = Some(DestroyedVehicle.Lightning)
|
||||||
|
lightning.Subtract.Damage1 = 7
|
||||||
|
|
||||||
prowler.Name = "prowler"
|
prowler.Name = "prowler"
|
||||||
prowler.MaxHealth = 4800
|
prowler.MaxHealth = 4800
|
||||||
|
|
@ -5062,6 +5080,7 @@ object GlobalDefinitions {
|
||||||
prowler.TrunkOffset = 30
|
prowler.TrunkOffset = 30
|
||||||
prowler.AutoPilotSpeeds = (14, 6)
|
prowler.AutoPilotSpeeds = (14, 6)
|
||||||
prowler.DestroyedModel = Some(DestroyedVehicle.Prowler)
|
prowler.DestroyedModel = Some(DestroyedVehicle.Prowler)
|
||||||
|
prowler.Subtract.Damage1 = 9
|
||||||
|
|
||||||
vanguard.Name = "vanguard"
|
vanguard.Name = "vanguard"
|
||||||
vanguard.MaxHealth = 5400
|
vanguard.MaxHealth = 5400
|
||||||
|
|
@ -5077,6 +5096,7 @@ object GlobalDefinitions {
|
||||||
vanguard.TrunkOffset = 30
|
vanguard.TrunkOffset = 30
|
||||||
vanguard.AutoPilotSpeeds = (16, 6)
|
vanguard.AutoPilotSpeeds = (16, 6)
|
||||||
vanguard.DestroyedModel = Some(DestroyedVehicle.Vanguard)
|
vanguard.DestroyedModel = Some(DestroyedVehicle.Vanguard)
|
||||||
|
vanguard.Subtract.Damage1 = 9
|
||||||
|
|
||||||
magrider.Name = "magrider"
|
magrider.Name = "magrider"
|
||||||
magrider.MaxHealth = 4200
|
magrider.MaxHealth = 4200
|
||||||
|
|
@ -5094,6 +5114,7 @@ object GlobalDefinitions {
|
||||||
magrider.TrunkOffset = 30
|
magrider.TrunkOffset = 30
|
||||||
magrider.AutoPilotSpeeds = (18, 6)
|
magrider.AutoPilotSpeeds = (18, 6)
|
||||||
magrider.DestroyedModel = Some(DestroyedVehicle.Magrider)
|
magrider.DestroyedModel = Some(DestroyedVehicle.Magrider)
|
||||||
|
magrider.Subtract.Damage1 = 9
|
||||||
|
|
||||||
val utilityConverter = new UtilityVehicleConverter
|
val utilityConverter = new UtilityVehicleConverter
|
||||||
ant.Name = "ant"
|
ant.Name = "ant"
|
||||||
|
|
@ -5110,6 +5131,7 @@ object GlobalDefinitions {
|
||||||
ant.MaximumCapacitor = 1500
|
ant.MaximumCapacitor = 1500
|
||||||
ant.Packet = utilityConverter
|
ant.Packet = utilityConverter
|
||||||
ant.DestroyedModel = Some(DestroyedVehicle.Ant)
|
ant.DestroyedModel = Some(DestroyedVehicle.Ant)
|
||||||
|
ant.Subtract.Damage1 = 5
|
||||||
|
|
||||||
ams.Name = "ams"
|
ams.Name = "ams"
|
||||||
ams.MaxHealth = 3000
|
ams.MaxHealth = 3000
|
||||||
|
|
@ -5129,6 +5151,7 @@ object GlobalDefinitions {
|
||||||
ams.AutoPilotSpeeds = (18, 6)
|
ams.AutoPilotSpeeds = (18, 6)
|
||||||
ams.Packet = utilityConverter
|
ams.Packet = utilityConverter
|
||||||
ams.DestroyedModel = Some(DestroyedVehicle.Ams)
|
ams.DestroyedModel = Some(DestroyedVehicle.Ams)
|
||||||
|
ams.Subtract.Damage1 = 10
|
||||||
|
|
||||||
val variantConverter = new VariantVehicleConverter
|
val variantConverter = new VariantVehicleConverter
|
||||||
router.Name = "router"
|
router.Name = "router"
|
||||||
|
|
@ -5147,6 +5170,7 @@ object GlobalDefinitions {
|
||||||
router.AutoPilotSpeeds = (16, 6)
|
router.AutoPilotSpeeds = (16, 6)
|
||||||
router.Packet = variantConverter
|
router.Packet = variantConverter
|
||||||
router.DestroyedModel = Some(DestroyedVehicle.Router)
|
router.DestroyedModel = Some(DestroyedVehicle.Router)
|
||||||
|
router.Subtract.Damage1 = 5
|
||||||
|
|
||||||
switchblade.Name = "switchblade"
|
switchblade.Name = "switchblade"
|
||||||
switchblade.MaxHealth = 1750
|
switchblade.MaxHealth = 1750
|
||||||
|
|
@ -5164,6 +5188,8 @@ object GlobalDefinitions {
|
||||||
switchblade.AutoPilotSpeeds = (22, 8)
|
switchblade.AutoPilotSpeeds = (22, 8)
|
||||||
switchblade.Packet = variantConverter
|
switchblade.Packet = variantConverter
|
||||||
switchblade.DestroyedModel = Some(DestroyedVehicle.Switchblade)
|
switchblade.DestroyedModel = Some(DestroyedVehicle.Switchblade)
|
||||||
|
switchblade.Subtract.Damage0 = 5
|
||||||
|
switchblade.Subtract.Damage1 = 5
|
||||||
|
|
||||||
flail.Name = "flail"
|
flail.Name = "flail"
|
||||||
flail.MaxHealth = 2400
|
flail.MaxHealth = 2400
|
||||||
|
|
@ -5180,6 +5206,7 @@ object GlobalDefinitions {
|
||||||
flail.AutoPilotSpeeds = (14, 6)
|
flail.AutoPilotSpeeds = (14, 6)
|
||||||
flail.Packet = variantConverter
|
flail.Packet = variantConverter
|
||||||
flail.DestroyedModel = Some(DestroyedVehicle.Flail)
|
flail.DestroyedModel = Some(DestroyedVehicle.Flail)
|
||||||
|
flail.Subtract.Damage1 = 7
|
||||||
|
|
||||||
mosquito.Name = "mosquito"
|
mosquito.Name = "mosquito"
|
||||||
mosquito.MaxHealth = 665
|
mosquito.MaxHealth = 665
|
||||||
|
|
@ -5210,6 +5237,7 @@ object GlobalDefinitions {
|
||||||
lightgunship.AutoPilotSpeeds = (0, 4)
|
lightgunship.AutoPilotSpeeds = (0, 4)
|
||||||
lightgunship.Packet = variantConverter
|
lightgunship.Packet = variantConverter
|
||||||
lightgunship.DestroyedModel = Some(DestroyedVehicle.LightGunship)
|
lightgunship.DestroyedModel = Some(DestroyedVehicle.LightGunship)
|
||||||
|
lightgunship.Subtract.Damage1 = 3
|
||||||
|
|
||||||
wasp.Name = "wasp"
|
wasp.Name = "wasp"
|
||||||
wasp.MaxHealth = 515
|
wasp.MaxHealth = 515
|
||||||
|
|
@ -5247,6 +5275,7 @@ object GlobalDefinitions {
|
||||||
liberator.AutoPilotSpeeds = (0, 4)
|
liberator.AutoPilotSpeeds = (0, 4)
|
||||||
liberator.Packet = variantConverter
|
liberator.Packet = variantConverter
|
||||||
liberator.DestroyedModel = Some(DestroyedVehicle.Liberator)
|
liberator.DestroyedModel = Some(DestroyedVehicle.Liberator)
|
||||||
|
liberator.Subtract.Damage1 = 5
|
||||||
|
|
||||||
vulture.Name = "vulture"
|
vulture.Name = "vulture"
|
||||||
vulture.MaxHealth = 2500
|
vulture.MaxHealth = 2500
|
||||||
|
|
@ -5269,6 +5298,7 @@ object GlobalDefinitions {
|
||||||
vulture.AutoPilotSpeeds = (0, 4)
|
vulture.AutoPilotSpeeds = (0, 4)
|
||||||
vulture.Packet = variantConverter
|
vulture.Packet = variantConverter
|
||||||
vulture.DestroyedModel = Some(DestroyedVehicle.Liberator) //add_property vulture destroyedphysics liberator_destroyed
|
vulture.DestroyedModel = Some(DestroyedVehicle.Liberator) //add_property vulture destroyedphysics liberator_destroyed
|
||||||
|
vulture.Subtract.Damage1 = 5
|
||||||
|
|
||||||
dropship.Name = "dropship"
|
dropship.Name = "dropship"
|
||||||
dropship.MaxHealth = 5000
|
dropship.MaxHealth = 5000
|
||||||
|
|
@ -5323,6 +5353,7 @@ object GlobalDefinitions {
|
||||||
dropship.AutoPilotSpeeds = (0, 4)
|
dropship.AutoPilotSpeeds = (0, 4)
|
||||||
dropship.Packet = variantConverter
|
dropship.Packet = variantConverter
|
||||||
dropship.DestroyedModel = Some(DestroyedVehicle.Dropship)
|
dropship.DestroyedModel = Some(DestroyedVehicle.Dropship)
|
||||||
|
dropship.Subtract.Damage1 = 7
|
||||||
|
|
||||||
galaxy_gunship.Name = "galaxy_gunship"
|
galaxy_gunship.Name = "galaxy_gunship"
|
||||||
galaxy_gunship.MaxHealth = 6000
|
galaxy_gunship.MaxHealth = 6000
|
||||||
|
|
@ -5354,6 +5385,7 @@ object GlobalDefinitions {
|
||||||
galaxy_gunship.AutoPilotSpeeds = (0, 4)
|
galaxy_gunship.AutoPilotSpeeds = (0, 4)
|
||||||
galaxy_gunship.Packet = variantConverter
|
galaxy_gunship.Packet = variantConverter
|
||||||
galaxy_gunship.DestroyedModel = Some(DestroyedVehicle.Dropship) //the adb calls out a galaxy_gunship_destroyed but no such asset exists
|
galaxy_gunship.DestroyedModel = Some(DestroyedVehicle.Dropship) //the adb calls out a galaxy_gunship_destroyed but no such asset exists
|
||||||
|
galaxy_gunship.Subtract.Damage1 = 7
|
||||||
|
|
||||||
lodestar.Name = "lodestar"
|
lodestar.Name = "lodestar"
|
||||||
lodestar.MaxHealth = 5000
|
lodestar.MaxHealth = 5000
|
||||||
|
|
@ -5367,6 +5399,7 @@ object GlobalDefinitions {
|
||||||
lodestar.AutoPilotSpeeds = (0, 4)
|
lodestar.AutoPilotSpeeds = (0, 4)
|
||||||
lodestar.Packet = variantConverter
|
lodestar.Packet = variantConverter
|
||||||
lodestar.DestroyedModel = Some(DestroyedVehicle.Lodestar)
|
lodestar.DestroyedModel = Some(DestroyedVehicle.Lodestar)
|
||||||
|
lodestar.Subtract.Damage1 = 7
|
||||||
|
|
||||||
phantasm.Name = "phantasm"
|
phantasm.Name = "phantasm"
|
||||||
phantasm.MaxHealth = 2500
|
phantasm.MaxHealth = 2500
|
||||||
|
|
|
||||||
|
|
@ -281,6 +281,8 @@ class Player(private val core : Avatar) extends PlanetSideGameObject
|
||||||
ChangeSpecialAbility()
|
ChangeSpecialAbility()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def Subtract = exosuit.Subtract
|
||||||
|
|
||||||
def ResistanceDirectHit = exosuit.ResistanceDirectHit
|
def ResistanceDirectHit = exosuit.ResistanceDirectHit
|
||||||
|
|
||||||
def ResistanceSplash = exosuit.ResistanceSplash
|
def ResistanceSplash = exosuit.ResistanceSplash
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import scala.annotation.tailrec
|
||||||
class Tool(private val toolDef : ToolDefinition) extends Equipment
|
class Tool(private val toolDef : ToolDefinition) extends Equipment
|
||||||
with FireModeSwitch[FireModeDefinition] {
|
with FireModeSwitch[FireModeDefinition] {
|
||||||
/** index of the current fire mode on the `ToolDefinition`'s list of fire modes */
|
/** index of the current fire mode on the `ToolDefinition`'s list of fire modes */
|
||||||
private var fireModeIndex : Int = 0
|
private var fireModeIndex : Int = toolDef.DefaultFireModeIndex
|
||||||
/** current ammunition slot being used by this fire mode */
|
/** current ammunition slot being used by this fire mode */
|
||||||
private var ammoSlots : List[Tool.FireModeSlot] = List.empty
|
private var ammoSlots : List[Tool.FireModeSlot] = List.empty
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package net.psforever.objects.ballistics
|
||||||
import net.psforever.objects.TurretDeployable
|
import net.psforever.objects.TurretDeployable
|
||||||
import net.psforever.objects.ce.ComplexDeployable
|
import net.psforever.objects.ce.ComplexDeployable
|
||||||
import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinition}
|
import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinition}
|
||||||
|
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
|
||||||
final case class ComplexDeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition,
|
final case class ComplexDeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition,
|
||||||
|
|
@ -22,6 +23,7 @@ final case class ComplexDeployableSource(obj_def : ObjectDefinition with BaseDep
|
||||||
def Position = position
|
def Position = position
|
||||||
def Orientation = orientation
|
def Orientation = orientation
|
||||||
def Velocity = None
|
def Velocity = None
|
||||||
|
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
|
||||||
}
|
}
|
||||||
|
|
||||||
object ComplexDeployableSource {
|
object ComplexDeployableSource {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package net.psforever.objects.ballistics
|
||||||
import net.psforever.objects.PlanetSideGameObject
|
import net.psforever.objects.PlanetSideGameObject
|
||||||
import net.psforever.objects.ce.Deployable
|
import net.psforever.objects.ce.Deployable
|
||||||
import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinition}
|
import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinition}
|
||||||
|
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
|
||||||
final case class DeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition,
|
final case class DeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition,
|
||||||
|
|
@ -20,6 +21,7 @@ final case class DeployableSource(obj_def : ObjectDefinition with BaseDeployable
|
||||||
def Position = position
|
def Position = position
|
||||||
def Orientation = orientation
|
def Orientation = orientation
|
||||||
def Velocity = None
|
def Velocity = None
|
||||||
|
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
|
||||||
}
|
}
|
||||||
|
|
||||||
object DeployableSource {
|
object DeployableSource {
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,21 @@ package net.psforever.objects.ballistics
|
||||||
|
|
||||||
import net.psforever.objects.PlanetSideGameObject
|
import net.psforever.objects.PlanetSideGameObject
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
|
import net.psforever.objects.vital.resistance.ResistanceProfileMutators
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
|
||||||
final case class ObjectSource(obj : PlanetSideGameObject with FactionAffinity,
|
final case class ObjectSource(obj : PlanetSideGameObject with FactionAffinity,
|
||||||
faction : PlanetSideEmpire.Value,
|
faction : PlanetSideEmpire.Value,
|
||||||
position : Vector3,
|
position : Vector3,
|
||||||
orientation : Vector3,
|
orientation : Vector3,
|
||||||
velocity : Option[Vector3] = None) extends SourceEntry {
|
velocity : Option[Vector3]) extends SourceEntry {
|
||||||
override def Name = SourceEntry.NameFormat(obj.Definition.Name)
|
override def Name = SourceEntry.NameFormat(obj.Definition.Name)
|
||||||
override def Faction = faction
|
override def Faction = faction
|
||||||
def Definition = obj.Definition
|
def Definition = obj.Definition
|
||||||
def Position = position
|
def Position = position
|
||||||
def Orientation = orientation
|
def Orientation = orientation
|
||||||
def Velocity = velocity
|
def Velocity = velocity
|
||||||
|
def Modifiers = new ResistanceProfileMutators { }
|
||||||
}
|
}
|
||||||
|
|
||||||
object ObjectSource {
|
object ObjectSource {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package net.psforever.objects.ballistics
|
||||||
|
|
||||||
import net.psforever.objects.Player
|
import net.psforever.objects.Player
|
||||||
import net.psforever.objects.definition.ObjectDefinition
|
import net.psforever.objects.definition.ObjectDefinition
|
||||||
|
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||||
import net.psforever.types.{ExoSuitType, PlanetSideEmpire, Vector3}
|
import net.psforever.types.{ExoSuitType, PlanetSideEmpire, Vector3}
|
||||||
|
|
||||||
final case class PlayerSource(name : String,
|
final case class PlayerSource(name : String,
|
||||||
|
|
@ -14,7 +15,8 @@ final case class PlayerSource(name : String,
|
||||||
armor : Int,
|
armor : Int,
|
||||||
position : Vector3,
|
position : Vector3,
|
||||||
orientation : Vector3,
|
orientation : Vector3,
|
||||||
velocity : Option[Vector3] = None) extends SourceEntry {
|
velocity : Option[Vector3],
|
||||||
|
modifiers : ResistanceProfile) extends SourceEntry {
|
||||||
override def Name = name
|
override def Name = name
|
||||||
override def Faction = faction
|
override def Faction = faction
|
||||||
def Definition = obj_def
|
def Definition = obj_def
|
||||||
|
|
@ -25,11 +27,12 @@ final case class PlayerSource(name : String,
|
||||||
def Position = position
|
def Position = position
|
||||||
def Orientation = orientation
|
def Orientation = orientation
|
||||||
def Velocity = velocity
|
def Velocity = velocity
|
||||||
|
def Modifiers = modifiers
|
||||||
}
|
}
|
||||||
|
|
||||||
object PlayerSource {
|
object PlayerSource {
|
||||||
def apply(tplayer : Player) : PlayerSource = {
|
def apply(tplayer : Player) : PlayerSource = {
|
||||||
PlayerSource(tplayer.Name, tplayer.Definition, tplayer.Faction, tplayer.ExoSuit, tplayer.VehicleSeated.nonEmpty,
|
PlayerSource(tplayer.Name, tplayer.Definition, tplayer.Faction, tplayer.ExoSuit, tplayer.VehicleSeated.nonEmpty,
|
||||||
tplayer.Health, tplayer.Armor, tplayer.Position, tplayer.Orientation, tplayer.Velocity)
|
tplayer.Health, tplayer.Armor, tplayer.Position, tplayer.Orientation, tplayer.Velocity, tplayer.asInstanceOf[ResistanceProfile])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import net.psforever.objects.definition.ObjectDefinition
|
||||||
import net.psforever.objects.{PlanetSideGameObject, Player, TurretDeployable, Vehicle}
|
import net.psforever.objects.{PlanetSideGameObject, Player, TurretDeployable, Vehicle}
|
||||||
import net.psforever.objects.entity.WorldEntity
|
import net.psforever.objects.entity.WorldEntity
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
|
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
|
||||||
trait SourceEntry extends WorldEntity {
|
trait SourceEntry extends WorldEntity {
|
||||||
|
|
@ -16,6 +17,7 @@ trait SourceEntry extends WorldEntity {
|
||||||
def Position_=(pos : Vector3) = Position
|
def Position_=(pos : Vector3) = Position
|
||||||
def Orientation_=(pos : Vector3) = Position
|
def Orientation_=(pos : Vector3) = Position
|
||||||
def Velocity_=(pos : Option[Vector3]) = Velocity
|
def Velocity_=(pos : Option[Vector3]) = Velocity
|
||||||
|
def Modifiers : ResistanceProfile
|
||||||
}
|
}
|
||||||
|
|
||||||
object SourceEntry {
|
object SourceEntry {
|
||||||
|
|
@ -24,6 +26,7 @@ object SourceEntry {
|
||||||
def Position = Vector3.Zero
|
def Position = Vector3.Zero
|
||||||
def Orientation = Vector3.Zero
|
def Orientation = Vector3.Zero
|
||||||
def Velocity = Some(Vector3.Zero)
|
def Velocity = Some(Vector3.Zero)
|
||||||
|
def Modifiers = null
|
||||||
}
|
}
|
||||||
|
|
||||||
def apply(target : PlanetSideGameObject with FactionAffinity) : SourceEntry = {
|
def apply(target : PlanetSideGameObject with FactionAffinity) : SourceEntry = {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package net.psforever.objects.ballistics
|
||||||
|
|
||||||
import net.psforever.objects.Vehicle
|
import net.psforever.objects.Vehicle
|
||||||
import net.psforever.objects.definition.VehicleDefinition
|
import net.psforever.objects.definition.VehicleDefinition
|
||||||
|
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||||
|
|
||||||
final case class VehicleSource(obj_def : VehicleDefinition,
|
final case class VehicleSource(obj_def : VehicleDefinition,
|
||||||
|
|
@ -11,7 +12,8 @@ final case class VehicleSource(obj_def : VehicleDefinition,
|
||||||
shields : Int,
|
shields : Int,
|
||||||
position : Vector3,
|
position : Vector3,
|
||||||
orientation : Vector3,
|
orientation : Vector3,
|
||||||
velocity : Option[Vector3] = None) extends SourceEntry {
|
velocity : Option[Vector3],
|
||||||
|
modifiers : ResistanceProfile) extends SourceEntry {
|
||||||
override def Name = SourceEntry.NameFormat(obj_def.Name)
|
override def Name = SourceEntry.NameFormat(obj_def.Name)
|
||||||
override def Faction = faction
|
override def Faction = faction
|
||||||
def Definition : VehicleDefinition = obj_def
|
def Definition : VehicleDefinition = obj_def
|
||||||
|
|
@ -20,6 +22,7 @@ final case class VehicleSource(obj_def : VehicleDefinition,
|
||||||
def Position = position
|
def Position = position
|
||||||
def Orientation = orientation
|
def Orientation = orientation
|
||||||
def Velocity = velocity
|
def Velocity = velocity
|
||||||
|
def Modifiers = modifiers
|
||||||
}
|
}
|
||||||
|
|
||||||
object VehicleSource {
|
object VehicleSource {
|
||||||
|
|
@ -31,7 +34,8 @@ object VehicleSource {
|
||||||
obj.Shields,
|
obj.Shields,
|
||||||
obj.Position,
|
obj.Position,
|
||||||
obj.Orientation,
|
obj.Orientation,
|
||||||
obj.Velocity
|
obj.Velocity,
|
||||||
|
obj.Definition.asInstanceOf[ResistanceProfile]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,13 @@ import net.psforever.objects.PlanetSideGameObject
|
||||||
import net.psforever.objects.ce.{Deployable, DeployableCategory, DeployedItem}
|
import net.psforever.objects.ce.{Deployable, DeployableCategory, DeployedItem}
|
||||||
import net.psforever.objects.definition.converter.SmallDeployableConverter
|
import net.psforever.objects.definition.converter.SmallDeployableConverter
|
||||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||||
import net.psforever.objects.vital.{DamageResistanceModel, NoResistanceSelection, StandardDeployableDamage}
|
import net.psforever.objects.vital.resistance.ResistanceProfileMutators
|
||||||
|
import net.psforever.objects.vital.{DamageResistanceModel, NoResistanceSelection, StandardDeployableDamage, StandardResistanceProfile}
|
||||||
|
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
trait BaseDeployableDefinition extends DamageResistanceModel {
|
trait BaseDeployableDefinition extends DamageResistanceModel
|
||||||
|
with ResistanceProfileMutators {
|
||||||
private var category : DeployableCategory.Value = DeployableCategory.Boomers
|
private var category : DeployableCategory.Value = DeployableCategory.Boomers
|
||||||
private var deployTime : Long = (1 second).toMillis //ms
|
private var deployTime : Long = (1 second).toMillis //ms
|
||||||
private var maxHealth : Int = 1
|
private var maxHealth : Int = 1
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
package net.psforever.objects.definition
|
package net.psforever.objects.definition
|
||||||
|
|
||||||
import net.psforever.objects.ballistics.Projectiles
|
import net.psforever.objects.ballistics.Projectiles
|
||||||
import net.psforever.objects.vital.DamageType
|
import net.psforever.objects.vital.{DamageType, StandardDamageProfile}
|
||||||
import net.psforever.objects.vital.damage.DamageProfile
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The definition that outlines the damage-dealing characteristics of any projectile.
|
* The definition that outlines the damage-dealing characteristics of any projectile.
|
||||||
|
|
@ -11,13 +10,8 @@ import net.psforever.objects.vital.damage.DamageProfile
|
||||||
* @param objectId the object's identifier number
|
* @param objectId the object's identifier number
|
||||||
*/
|
*/
|
||||||
class ProjectileDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
class ProjectileDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
||||||
with DamageProfile {
|
with StandardDamageProfile {
|
||||||
private val projectileType : Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException
|
private val projectileType : Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException
|
||||||
private var damage0 : Int = 0
|
|
||||||
private var damage1 : Option[Int] = None
|
|
||||||
private var damage2 : Option[Int] = None
|
|
||||||
private var damage3 : Option[Int] = None
|
|
||||||
private var damage4 : Option[Int] = None
|
|
||||||
private var acceleration : Int = 0
|
private var acceleration : Int = 0
|
||||||
private var accelerationUntil : Float = 0f
|
private var accelerationUntil : Float = 0f
|
||||||
private var damageType : DamageType.Value = DamageType.None
|
private var damageType : DamageType.Value = DamageType.None
|
||||||
|
|
@ -45,57 +39,6 @@ class ProjectileDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
||||||
UseDamage1Subtract
|
UseDamage1Subtract
|
||||||
}
|
}
|
||||||
|
|
||||||
def Damage0 : Int = damage0
|
|
||||||
|
|
||||||
def Damage0_=(damage : Int) : Int = {
|
|
||||||
damage0 = damage
|
|
||||||
damage0
|
|
||||||
}
|
|
||||||
|
|
||||||
def Damage0_=(damage : Option[Int]) : Int = {
|
|
||||||
damage0 = damage match {
|
|
||||||
case Some(value) => value
|
|
||||||
case None => 0 //can not be set to None
|
|
||||||
}
|
|
||||||
Damage0
|
|
||||||
}
|
|
||||||
|
|
||||||
def Damage1 : Int = damage1.getOrElse(Damage0)
|
|
||||||
|
|
||||||
def Damage1_=(damage : Int) : Int = Damage1_=(Some(damage))
|
|
||||||
|
|
||||||
def Damage1_=(damage : Option[Int]) : Int = {
|
|
||||||
this.damage1 = damage
|
|
||||||
Damage1
|
|
||||||
}
|
|
||||||
|
|
||||||
def Damage2 : Int = damage2.getOrElse(Damage1)
|
|
||||||
|
|
||||||
def Damage2_=(damage : Int) : Int = Damage2_=(Some(damage))
|
|
||||||
|
|
||||||
def Damage2_=(damage : Option[Int]) : Int = {
|
|
||||||
this.damage2 = damage
|
|
||||||
Damage2
|
|
||||||
}
|
|
||||||
|
|
||||||
def Damage3 : Int = damage3.getOrElse(Damage2)
|
|
||||||
|
|
||||||
def Damage3_=(damage : Int) : Int = Damage3_=(Some(damage))
|
|
||||||
|
|
||||||
def Damage3_=(damage : Option[Int]) : Int = {
|
|
||||||
this.damage3 = damage
|
|
||||||
Damage3
|
|
||||||
}
|
|
||||||
|
|
||||||
def Damage4 : Int = damage4.getOrElse(Damage3)
|
|
||||||
|
|
||||||
def Damage4_=(damage : Int) : Int = Damage4_=(Some(damage))
|
|
||||||
|
|
||||||
def Damage4_=(damage : Option[Int]) : Int = {
|
|
||||||
this.damage4 = damage
|
|
||||||
Damage4
|
|
||||||
}
|
|
||||||
|
|
||||||
def Acceleration : Int = acceleration
|
def Acceleration : Int = acceleration
|
||||||
|
|
||||||
def Acceleration_=(accel : Int) : Int = {
|
def Acceleration_=(accel : Int) : Int = {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ class ToolDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
||||||
private val ammoTypes : mutable.ListBuffer[AmmoBoxDefinition] = new mutable.ListBuffer[AmmoBoxDefinition]
|
private val ammoTypes : mutable.ListBuffer[AmmoBoxDefinition] = new mutable.ListBuffer[AmmoBoxDefinition]
|
||||||
private val projectileTypes : mutable.ListBuffer[ProjectileDefinition] = new mutable.ListBuffer[ProjectileDefinition]
|
private val projectileTypes : mutable.ListBuffer[ProjectileDefinition] = new mutable.ListBuffer[ProjectileDefinition]
|
||||||
private val fireModes : mutable.ListBuffer[FireModeDefinition] = new mutable.ListBuffer[FireModeDefinition]
|
private val fireModes : mutable.ListBuffer[FireModeDefinition] = new mutable.ListBuffer[FireModeDefinition]
|
||||||
|
private var defaultFireModeIndex : Option[Int] = None
|
||||||
Name = "tool"
|
Name = "tool"
|
||||||
Packet = ToolDefinition.converter
|
Packet = ToolDefinition.converter
|
||||||
|
|
||||||
|
|
@ -20,6 +21,15 @@ class ToolDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
||||||
def FireModes : mutable.ListBuffer[FireModeDefinition] = fireModes
|
def FireModes : mutable.ListBuffer[FireModeDefinition] = fireModes
|
||||||
|
|
||||||
def NextFireModeIndex(index : Int) : Int = index + 1
|
def NextFireModeIndex(index : Int) : Int = index + 1
|
||||||
|
|
||||||
|
def DefaultFireModeIndex : Int = defaultFireModeIndex.getOrElse(0)
|
||||||
|
|
||||||
|
def DefaultFireModeIndex_=(index : Int) : Int = DefaultFireModeIndex_=(Some(index))
|
||||||
|
|
||||||
|
def DefaultFireModeIndex_=(index : Option[Int]) : Int = {
|
||||||
|
defaultFireModeIndex = index
|
||||||
|
DefaultFireModeIndex
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object ToolDefinition {
|
object ToolDefinition {
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
||||||
}
|
}
|
||||||
|
|
||||||
def Seats : mutable.HashMap[Int, SeatDefinition] = seats
|
def Seats : mutable.HashMap[Int, SeatDefinition] = seats
|
||||||
|
|
||||||
def Cargo : mutable.HashMap[Int, CargoDefinition] = cargo
|
def Cargo : mutable.HashMap[Int, CargoDefinition] = cargo
|
||||||
|
|
||||||
def MountPoints : mutable.HashMap[Int, Int] = mountPoints
|
def MountPoints : mutable.HashMap[Int, Int] = mountPoints
|
||||||
|
|
|
||||||
|
|
@ -226,10 +226,12 @@ class GridInventory extends Container {
|
||||||
else {
|
else {
|
||||||
val collisions : mutable.Set[InventoryItem] = mutable.Set[InventoryItem]()
|
val collisions : mutable.Set[InventoryItem] = mutable.Set[InventoryItem]()
|
||||||
var curr = actualSlot
|
var curr = actualSlot
|
||||||
|
val fixedItems = items.toMap
|
||||||
|
val fixedGrid = grid.toList
|
||||||
for(_ <- 0 until h) {
|
for(_ <- 0 until h) {
|
||||||
for(col <- 0 until w) {
|
for(col <- 0 until w) {
|
||||||
if(grid(curr + col) > -1) {
|
if(fixedGrid(curr + col) > -1) {
|
||||||
collisions += items(grid(curr + col))
|
collisions += fixedItems(fixedGrid(curr + col))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
curr += width
|
curr += width
|
||||||
|
|
|
||||||
|
|
@ -71,16 +71,15 @@ object ResourceSilo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an configure a `Resource Silo` object
|
* Instantiate and configure a `Resource Silo` object
|
||||||
* @param id the unique id that will be assigned to this entity
|
* @param id the unique id that will be assigned to this entity
|
||||||
* @param context a context to allow the object to properly set up `ActorSystem` functionality;
|
* @param context a context to allow the object to properly set up `ActorSystem` functionality;
|
||||||
* not necessary for this object, but required by signature
|
* not necessary for this object, but required by signature
|
||||||
* @return the `Locker` object
|
* @return the `ResourceSilo` object
|
||||||
*/
|
*/
|
||||||
def Constructor(id : Int, context : ActorContext) : ResourceSilo = {
|
def Constructor(id : Int, context : ActorContext) : ResourceSilo = {
|
||||||
val obj = ResourceSilo()
|
val obj = ResourceSilo()
|
||||||
obj.Actor = context.actorOf(Props(classOf[ResourceSiloControl], obj), s"${obj.Definition.Name}_$id")
|
obj.Actor = context.actorOf(Props(classOf[ResourceSiloControl], obj), s"${obj.Definition.Name}_$id")
|
||||||
obj.Actor ! "startup"
|
|
||||||
obj
|
obj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with Factio
|
||||||
sender ! ResourceSilo.ResourceSiloMessage(player, msg, resourceSilo.Use(player, msg))
|
sender ! ResourceSilo.ResourceSiloMessage(player, msg, resourceSilo.Use(player, msg))
|
||||||
case ResourceSilo.LowNtuWarning(enabled: Boolean) =>
|
case ResourceSilo.LowNtuWarning(enabled: Boolean) =>
|
||||||
resourceSilo.LowNtuWarningOn = enabled
|
resourceSilo.LowNtuWarningOn = enabled
|
||||||
log.trace(s"LowNtuWarning: Silo ${resourceSilo.GUID} low ntu warning set to ${enabled}")
|
log.trace(s"LowNtuWarning: Silo ${resourceSilo.GUID} low ntu warning set to $enabled")
|
||||||
avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 47, if(resourceSilo.LowNtuWarningOn) 1 else 0))
|
avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(PlanetSideGUID(resourceSilo.Owner.asInstanceOf[Building].ModelId), 47, if(resourceSilo.LowNtuWarningOn) 1 else 0))
|
||||||
|
|
||||||
case ResourceSilo.UpdateChargeLevel(amount: Int) =>
|
case ResourceSilo.UpdateChargeLevel(amount: Int) =>
|
||||||
|
|
@ -55,10 +55,10 @@ class ResourceSiloControl(resourceSilo : ResourceSilo) extends Actor with Factio
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val ntuBarLevel = scala.math.round((resourceSilo.ChargeLevel.toFloat / resourceSilo.MaximumCharge.toFloat) * 10).toInt
|
val ntuBarLevel = scala.math.round((resourceSilo.ChargeLevel.toFloat / resourceSilo.MaximumCharge.toFloat) * 10)
|
||||||
// Only send updated capacitor display value to all clients if it has actually changed
|
// Only send updated capacitor display value to all clients if it has actually changed
|
||||||
if(resourceSilo.CapacitorDisplay != ntuBarLevel) {
|
if(resourceSilo.CapacitorDisplay != ntuBarLevel) {
|
||||||
log.trace(s"Silo ${resourceSilo.GUID} NTU bar level has changed from ${resourceSilo.CapacitorDisplay} to ${ntuBarLevel}")
|
log.trace(s"Silo ${resourceSilo.GUID} NTU bar level has changed from ${resourceSilo.CapacitorDisplay} to $ntuBarLevel")
|
||||||
resourceSilo.CapacitorDisplay = ntuBarLevel
|
resourceSilo.CapacitorDisplay = ntuBarLevel
|
||||||
resourceSilo.Owner.Actor ! Building.SendMapUpdate(all_clients = true)
|
resourceSilo.Owner.Actor ! Building.SendMapUpdate(all_clients = true)
|
||||||
avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(resourceSilo.GUID, 45, resourceSilo.CapacitorDisplay))
|
avatarService ! AvatarServiceMessage(resourceSilo.Owner.asInstanceOf[Building].Zone.Id, AvatarAction.PlanetsideAttribute(resourceSilo.GUID, 45, resourceSilo.CapacitorDisplay))
|
||||||
|
|
|
||||||
|
|
@ -366,12 +366,12 @@ object EquipmentTerminalDefinition {
|
||||||
(0 until tool.MaxAmmoSlot).foreach(index => {
|
(0 until tool.MaxAmmoSlot).foreach(index => {
|
||||||
val slot = tool.AmmoSlots(index)
|
val slot = tool.AmmoSlots(index)
|
||||||
slot.AmmoTypeIndex += obj.ammo(index).ammoIndex
|
slot.AmmoTypeIndex += obj.ammo(index).ammoIndex
|
||||||
slot.Box = MakeAmmoBox(ammo(index), Some(obj.ammo(index).ammo.capacity))
|
slot.Box = MakeAmmoBox(ammo(index), Some(slot.Definition.Magazine)) //Some(obj.ammo(index).ammo.capacity)
|
||||||
})
|
})
|
||||||
tool
|
tool
|
||||||
|
|
||||||
case obj : ShorthandAmmoBox =>
|
case obj : ShorthandAmmoBox =>
|
||||||
MakeAmmoBox(obj.definition, Some(obj.capacity))
|
MakeAmmoBox(obj.definition) //Some(obj.capacity)
|
||||||
|
|
||||||
case obj : ShorthandConstructionItem =>
|
case obj : ShorthandConstructionItem =>
|
||||||
MakeConstructionItem(obj.definition)
|
MakeConstructionItem(obj.definition)
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,19 @@ package net.psforever.objects.serverobject.turret
|
||||||
|
|
||||||
import net.psforever.objects.serverobject.structures.Amenity
|
import net.psforever.objects.serverobject.structures.Amenity
|
||||||
import net.psforever.types.Vector3
|
import net.psforever.types.Vector3
|
||||||
|
import net.psforever.objects.vital.{DamageResistanceModel, StandardResistanceProfile, Vitality}
|
||||||
|
|
||||||
class FacilityTurret(tDef : TurretDefinition) extends Amenity
|
class FacilityTurret(tDef : TurretDefinition) extends Amenity
|
||||||
with WeaponTurret {
|
with WeaponTurret
|
||||||
|
with Vitality
|
||||||
|
with StandardResistanceProfile {
|
||||||
/** some turrets can be updated; they all start without updates */
|
/** some turrets can be updated; they all start without updates */
|
||||||
private var upgradePath : TurretUpgrade.Value = TurretUpgrade.None
|
private var upgradePath : TurretUpgrade.Value = TurretUpgrade.None
|
||||||
|
|
||||||
WeaponTurret.LoadDefinition(this)
|
WeaponTurret.LoadDefinition(this)
|
||||||
|
|
||||||
|
override def Health_=(toHealth : Int) = super.Health_=(math.max(1, toHealth)) //TODO properly handle destroyed facility turrets
|
||||||
|
|
||||||
def MaxHealth : Int = Definition.MaxHealth
|
def MaxHealth : Int = Definition.MaxHealth
|
||||||
|
|
||||||
def MountPoints : Map[Int, Int] = Definition.MountPoints.toMap
|
def MountPoints : Map[Int, Int] = Definition.MountPoints.toMap
|
||||||
|
|
@ -28,6 +33,8 @@ class FacilityTurret(tDef : TurretDefinition) extends Amenity
|
||||||
Upgrade
|
Upgrade
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def DamageModel = Definition.asInstanceOf[DamageResistanceModel]
|
||||||
|
|
||||||
def Definition : TurretDefinition = tDef
|
def Definition : TurretDefinition = tDef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package net.psforever.objects.serverobject.turret
|
||||||
import akka.actor.Actor
|
import akka.actor.Actor
|
||||||
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
|
import net.psforever.objects.serverobject.mount.{Mountable, MountableBehavior}
|
||||||
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
import net.psforever.objects.serverobject.affinity.{FactionAffinity, FactionAffinityBehavior}
|
||||||
|
import net.psforever.objects.vital.Vitality
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `Actor` that handles messages being dispatched to a specific `MannedTurret`.<br>
|
* An `Actor` that handles messages being dispatched to a specific `MannedTurret`.<br>
|
||||||
|
|
@ -38,6 +39,18 @@ class FacilityTurretControl(turret : FacilityTurret) extends Actor
|
||||||
sender ! Mountable.MountMessages(user, Mountable.CanNotMount(turret, seat_num))
|
sender ! Mountable.MountMessages(user, Mountable.CanNotMount(turret, seat_num))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Vitality.Damage(damage_func) =>
|
||||||
|
if(turret.Health > 0) {
|
||||||
|
val originalHealth = turret.Health
|
||||||
|
damage_func(turret)
|
||||||
|
val health = turret.Health
|
||||||
|
val damageToHealth = originalHealth - health
|
||||||
|
val name = turret.Actor.toString
|
||||||
|
val slashPoint = name.lastIndexOf("/")
|
||||||
|
org.log4s.getLogger("DamageResolution").info(s"${name.substring(slashPoint+1, name.length-1)}: BEFORE=$originalHealth, AFTER=$health, CHANGE=$damageToHealth")
|
||||||
|
sender ! Vitality.DamageResolution(turret)
|
||||||
|
}
|
||||||
|
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ package net.psforever.objects.serverobject.turret
|
||||||
|
|
||||||
import net.psforever.objects.definition.{ObjectDefinition, ToolDefinition}
|
import net.psforever.objects.definition.{ObjectDefinition, ToolDefinition}
|
||||||
import net.psforever.objects.vehicles.Turrets
|
import net.psforever.objects.vehicles.Turrets
|
||||||
|
import net.psforever.objects.vital.{DamageResistanceModel, StandardResolutions, StandardVehicleDamage, StandardVehicleResistance}
|
||||||
|
import net.psforever.objects.vital.resistance.ResistanceProfileMutators
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
|
@ -10,7 +12,9 @@ import scala.collection.mutable
|
||||||
* The definition for any `MannedTurret`.
|
* The definition for any `MannedTurret`.
|
||||||
* @param objectId the object's identifier number
|
* @param objectId the object's identifier number
|
||||||
*/
|
*/
|
||||||
class TurretDefinition(private val objectId : Int) extends ObjectDefinition(objectId) {
|
class TurretDefinition(private val objectId : Int) extends ObjectDefinition(objectId)
|
||||||
|
with ResistanceProfileMutators
|
||||||
|
with DamageResistanceModel {
|
||||||
Turrets(objectId) //let throw NoSuchElementException
|
Turrets(objectId) //let throw NoSuchElementException
|
||||||
|
|
||||||
private var maxHealth : Int = 100
|
private var maxHealth : Int = 100
|
||||||
|
|
@ -25,6 +29,9 @@ class TurretDefinition(private val objectId : Int) extends ObjectDefinition(obje
|
||||||
/** creates internal ammunition reserves that can not become depleted
|
/** creates internal ammunition reserves that can not become depleted
|
||||||
* see `MannedTurret.TurretAmmoBox` for details */
|
* see `MannedTurret.TurretAmmoBox` for details */
|
||||||
private var hasReserveAmmunition : Boolean = false
|
private var hasReserveAmmunition : Boolean = false
|
||||||
|
Damage = StandardVehicleDamage
|
||||||
|
Resistance = StandardVehicleResistance
|
||||||
|
Model = StandardResolutions.FacilityTurrets
|
||||||
|
|
||||||
def MaxHealth : Int = maxHealth
|
def MaxHealth : Int = maxHealth
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,16 @@ class VehicleControl(vehicle : Vehicle) extends Actor
|
||||||
|
|
||||||
case Vitality.Damage(damage_func) =>
|
case Vitality.Damage(damage_func) =>
|
||||||
if(vehicle.Health > 0) {
|
if(vehicle.Health > 0) {
|
||||||
|
val originalHealth = vehicle.Health
|
||||||
|
val originalShields = vehicle.Shields
|
||||||
damage_func(vehicle)
|
damage_func(vehicle)
|
||||||
|
val health = vehicle.Health
|
||||||
|
val shields = vehicle.Shields
|
||||||
|
val damageToHealth = originalHealth - health
|
||||||
|
val damageToShields = originalShields - shields
|
||||||
|
val name = vehicle.Actor.toString
|
||||||
|
val slashPoint = name.lastIndexOf("/")
|
||||||
|
org.log4s.getLogger("DamageResolution").info(s"${name.substring(slashPoint+1, name.length-1)}: BEFORE=$originalHealth/$originalShields, AFTER=$health/$shields, CHANGE=$damageToHealth/$damageToShields")
|
||||||
sender ! Vitality.DamageResolution(vehicle)
|
sender ! Vitality.DamageResolution(vehicle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.objects.vital
|
||||||
|
|
||||||
|
import net.psforever.objects.vital.damage.DamageProfile
|
||||||
|
|
||||||
|
trait StandardDamageProfile extends DamageProfile {
|
||||||
|
private var damage0 : Int = 0
|
||||||
|
private var damage1 : Option[Int] = None
|
||||||
|
private var damage2 : Option[Int] = None
|
||||||
|
private var damage3 : Option[Int] = None
|
||||||
|
private var damage4 : Option[Int] = None
|
||||||
|
|
||||||
|
def Damage0 : Int = damage0
|
||||||
|
|
||||||
|
def Damage0_=(damage : Int) : Int = {
|
||||||
|
damage0 = damage
|
||||||
|
damage0
|
||||||
|
}
|
||||||
|
|
||||||
|
def Damage0_=(damage : Option[Int]) : Int = {
|
||||||
|
damage0 = damage match {
|
||||||
|
case Some(value) => value
|
||||||
|
case None => 0 //can not be set to None
|
||||||
|
}
|
||||||
|
Damage0
|
||||||
|
}
|
||||||
|
|
||||||
|
def Damage1 : Int = damage1.getOrElse(Damage0)
|
||||||
|
|
||||||
|
def Damage1_=(damage : Int) : Int = Damage1_=(Some(damage))
|
||||||
|
|
||||||
|
def Damage1_=(damage : Option[Int]) : Int = {
|
||||||
|
this.damage1 = damage
|
||||||
|
Damage1
|
||||||
|
}
|
||||||
|
|
||||||
|
def Damage2 : Int = damage2.getOrElse(Damage1)
|
||||||
|
|
||||||
|
def Damage2_=(damage : Int) : Int = Damage2_=(Some(damage))
|
||||||
|
|
||||||
|
def Damage2_=(damage : Option[Int]) : Int = {
|
||||||
|
this.damage2 = damage
|
||||||
|
Damage2
|
||||||
|
}
|
||||||
|
|
||||||
|
def Damage3 : Int = damage3.getOrElse(Damage2)
|
||||||
|
|
||||||
|
def Damage3_=(damage : Int) : Int = Damage3_=(Some(damage))
|
||||||
|
|
||||||
|
def Damage3_=(damage : Option[Int]) : Int = {
|
||||||
|
this.damage3 = damage
|
||||||
|
Damage3
|
||||||
|
}
|
||||||
|
|
||||||
|
def Damage4 : Int = damage4.getOrElse(Damage3)
|
||||||
|
|
||||||
|
def Damage4_=(damage : Int) : Int = Damage4_=(Some(damage))
|
||||||
|
|
||||||
|
def Damage4_=(damage : Option[Int]) : Int = {
|
||||||
|
this.damage4 = damage
|
||||||
|
Damage4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.vital
|
package net.psforever.objects.vital
|
||||||
|
|
||||||
import net.psforever.objects.ballistics.ResolvedProjectile
|
|
||||||
import net.psforever.objects.vital.damage._
|
import net.psforever.objects.vital.damage._
|
||||||
import net.psforever.objects.vital.damage.DamageCalculations._
|
import net.psforever.objects.vital.damage.DamageCalculations._
|
||||||
|
|
||||||
|
|
@ -66,21 +65,35 @@ object AircraftSplashDamage extends DamageCalculations(
|
||||||
DistanceFromExplosionToTarget
|
DistanceFromExplosionToTarget
|
||||||
)
|
)
|
||||||
|
|
||||||
object InfantryLashDamage extends NoDamageBase {
|
object InfantrySplashDamageDirect extends DamageCalculations(
|
||||||
override def Calculate(data : ResolvedProjectile) : Int = (InfantryHitDamage.Calculate(data) * 0.2f).toInt
|
SplashDamageWithRadialDegrade,
|
||||||
}
|
DamageWithModifiers(DamageAgainstAircraft),
|
||||||
|
NoDistance
|
||||||
|
)
|
||||||
|
|
||||||
object MaxLashDamage extends NoDamageBase {
|
object InfantryLashDamage extends DamageCalculations(
|
||||||
override def Calculate(data : ResolvedProjectile) : Int = (MaxHitDamage.Calculate(data) * 0.2f).toInt
|
LashDamage,
|
||||||
}
|
DamageWithModifiers(DamageAgainstExoSuit),
|
||||||
|
DistanceBetweenTargetandSource
|
||||||
|
)
|
||||||
|
|
||||||
object VehicleLashDamage extends NoDamageBase {
|
object MaxLashDamage extends DamageCalculations(
|
||||||
override def Calculate(data : ResolvedProjectile) : Int = (VehicleHitDamage.Calculate(data) * 0.2f).toInt
|
LashDamage,
|
||||||
}
|
DamageWithModifiers(DamageAgainstMaxSuit),
|
||||||
|
DistanceBetweenTargetandSource
|
||||||
|
)
|
||||||
|
|
||||||
object AircraftLashDamage extends NoDamageBase {
|
object VehicleLashDamage extends DamageCalculations(
|
||||||
override def Calculate(data : ResolvedProjectile) : Int = (AircraftHitDamage.Calculate(data) * 0.2f).toInt
|
LashDamage,
|
||||||
}
|
DamageWithModifiers(DamageAgainstVehicle),
|
||||||
|
DistanceBetweenTargetandSource
|
||||||
|
)
|
||||||
|
|
||||||
|
object AircraftLashDamage extends DamageCalculations(
|
||||||
|
LashDamage,
|
||||||
|
DamageWithModifiers(DamageAgainstAircraft),
|
||||||
|
DistanceBetweenTargetandSource
|
||||||
|
)
|
||||||
|
|
||||||
object NoDamageSelection extends DamageSelection {
|
object NoDamageSelection extends DamageSelection {
|
||||||
def Direct = None
|
def Direct = None
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
package net.psforever.objects.vital
|
package net.psforever.objects.vital
|
||||||
|
|
||||||
import net.psforever.objects.PlanetSideGameObject
|
import net.psforever.objects.PlanetSideGameObject
|
||||||
|
import net.psforever.objects.vital.damage.DamageProfile
|
||||||
import net.psforever.objects.vital.resistance.ResistanceProfile
|
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,6 +17,8 @@ trait StandardResistanceProfile extends ResistanceProfile {
|
||||||
assert(Definition.isInstanceOf[ResistanceProfile], s"$this object definition must extend ResistanceProfile")
|
assert(Definition.isInstanceOf[ResistanceProfile], s"$this object definition must extend ResistanceProfile")
|
||||||
private val resistDef = Definition.asInstanceOf[ResistanceProfile] //cast only once
|
private val resistDef = Definition.asInstanceOf[ResistanceProfile] //cast only once
|
||||||
|
|
||||||
|
def Subtract : DamageProfile = resistDef.Subtract
|
||||||
|
|
||||||
def ResistanceDirectHit : Int = resistDef.ResistanceDirectHit
|
def ResistanceDirectHit : Int = resistDef.ResistanceDirectHit
|
||||||
|
|
||||||
def ResistanceSplash : Int = resistDef.ResistanceDirectHit
|
def ResistanceSplash : Int = resistDef.ResistanceDirectHit
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ object InfantrySplashResistance extends ResistanceCalculations[PlayerSource](
|
||||||
|
|
||||||
object InfantryLashResistance extends ResistanceCalculations[PlayerSource](
|
object InfantryLashResistance extends ResistanceCalculations[PlayerSource](
|
||||||
ResistanceCalculations.ValidInfantryTarget,
|
ResistanceCalculations.ValidInfantryTarget,
|
||||||
ResistanceCalculations.NoResistExtractor
|
ResistanceCalculations.ExoSuitDirectExtractor
|
||||||
)
|
)
|
||||||
|
|
||||||
object InfantryAggravatedResistance extends ResistanceCalculations[PlayerSource](
|
object InfantryAggravatedResistance extends ResistanceCalculations[PlayerSource](
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,9 @@ object VehicleResolutions extends DamageResistCalculations(
|
||||||
ResolutionCalculations.VehicleApplication
|
ResolutionCalculations.VehicleApplication
|
||||||
)
|
)
|
||||||
|
|
||||||
object SimpleDeployableResolutions extends DamageResistCalculations(
|
object SimpleResolutions extends DamageResistCalculations(
|
||||||
ResolutionCalculations.VehicleDamageAfterResist,
|
ResolutionCalculations.VehicleDamageAfterResist,
|
||||||
ResolutionCalculations.SimpleDeployableApplication
|
ResolutionCalculations.SimpleApplication
|
||||||
)
|
)
|
||||||
|
|
||||||
object ComplexDeployableResolutions extends DamageResistCalculations(
|
object ComplexDeployableResolutions extends DamageResistCalculations(
|
||||||
|
|
@ -38,6 +38,7 @@ object StandardResolutions extends ResolutionSelection {
|
||||||
def Max : ResolutionCalculations.Form = MaxResolutions.Calculate
|
def Max : ResolutionCalculations.Form = MaxResolutions.Calculate
|
||||||
def Vehicle : ResolutionCalculations.Form = VehicleResolutions.Calculate
|
def Vehicle : ResolutionCalculations.Form = VehicleResolutions.Calculate
|
||||||
def Aircraft : ResolutionCalculations.Form = VehicleResolutions.Calculate
|
def Aircraft : ResolutionCalculations.Form = VehicleResolutions.Calculate
|
||||||
def SimpleDeployables : ResolutionCalculations.Form = SimpleDeployableResolutions.Calculate
|
def SimpleDeployables : ResolutionCalculations.Form = SimpleResolutions.Calculate
|
||||||
def ComplexDeployables : ResolutionCalculations.Form = ComplexDeployableResolutions.Calculate
|
def ComplexDeployables : ResolutionCalculations.Form = ComplexDeployableResolutions.Calculate
|
||||||
|
def FacilityTurrets : ResolutionCalculations.Form = SimpleResolutions.Calculate
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,16 @@ abstract class DamageCalculations(damages : DamagesType,
|
||||||
*/
|
*/
|
||||||
def Calculate(data : ResolvedProjectile) : Int = {
|
def Calculate(data : ResolvedProjectile) : Int = {
|
||||||
val projectile = data.projectile
|
val projectile = data.projectile
|
||||||
|
val profile = projectile.profile
|
||||||
|
val modifiers = if(profile.UseDamage1Subtract) {
|
||||||
|
List(projectile.fire_mode.Modifiers, data.target.Modifiers.Subtract)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
List(projectile.fire_mode.Modifiers)
|
||||||
|
}
|
||||||
damages(
|
damages(
|
||||||
projectile,
|
projectile,
|
||||||
extractor(projectile.profile, List(projectile.fire_mode.Modifiers)),
|
extractor(profile, modifiers),
|
||||||
distanceFunc(data)
|
distanceFunc(data)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -70,6 +77,17 @@ object DamageCalculations {
|
||||||
//damage calculation functions
|
//damage calculation functions
|
||||||
def NoDamage(projectile : Projectile, rawDamage : Int, distance : Float) : Int = 0
|
def NoDamage(projectile : Projectile, rawDamage : Int, distance : Float) : Int = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use an unmodified damage value.
|
||||||
|
* @param projectile information about the weapon discharge (itself);
|
||||||
|
* unused
|
||||||
|
* @param rawDamage the accumulated amount of damage
|
||||||
|
* @param distance how far the source was from the target;
|
||||||
|
* unused
|
||||||
|
* @return the rawDamage value
|
||||||
|
*/
|
||||||
|
def SameHit(projectile : Projectile, rawDamage : Int, distance : Float) : Int = rawDamage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modify the base damage based on the degrade distance of the projectile type
|
* Modify the base damage based on the degrade distance of the projectile type
|
||||||
* and its maximum effective distance.
|
* and its maximum effective distance.
|
||||||
|
|
@ -106,8 +124,26 @@ object DamageCalculations {
|
||||||
val radius = projectile.profile.DamageRadius
|
val radius = projectile.profile.DamageRadius
|
||||||
if(distance <= radius) {
|
if(distance <= radius) {
|
||||||
val base : Float = projectile.profile.DamageAtEdge
|
val base : Float = projectile.profile.DamageAtEdge
|
||||||
val degrade : Float = (1 - base) * ((radius - distance) / radius) + base
|
val degrade : Float = (1 - base) * ((radius - distance)/radius) + base
|
||||||
rawDamage + (rawDamage * degrade).toInt
|
(rawDamage * degrade).toInt
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a flat lash damage value.
|
||||||
|
* The target needs to be more than five meters away.
|
||||||
|
* @param projectile information about the weapon discharge (itself)
|
||||||
|
* @param rawDamage the accumulated amount of damage
|
||||||
|
* @param distance how far the source was from the target
|
||||||
|
* @return the modified damage value
|
||||||
|
*/
|
||||||
|
def LashDamage(projectile : Projectile, rawDamage : Int, distance : Float) : Int = {
|
||||||
|
val profile = projectile.profile
|
||||||
|
if(distance > 5 || distance <= profile.DistanceMax) {
|
||||||
|
(rawDamage * 0.2f) toInt
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
0
|
0
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.objects.vital.resistance
|
package net.psforever.objects.vital.resistance
|
||||||
|
|
||||||
import net.psforever.objects.vital.DamageType
|
import net.psforever.objects.vital.damage.DamageProfile
|
||||||
|
import net.psforever.objects.vital.{DamageType, StandardDamageProfile}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The different values for four common methods of modifying incoming damage.
|
* The different values for four common methods of modifying incoming damage.
|
||||||
|
|
@ -9,6 +10,8 @@ import net.psforever.objects.vital.DamageType
|
||||||
* This is for defining pure accessor functions.
|
* This is for defining pure accessor functions.
|
||||||
*/
|
*/
|
||||||
trait ResistanceProfile {
|
trait ResistanceProfile {
|
||||||
|
def Subtract : DamageProfile
|
||||||
|
|
||||||
def ResistanceDirectHit : Int
|
def ResistanceDirectHit : Int
|
||||||
|
|
||||||
def ResistanceSplash : Int
|
def ResistanceSplash : Int
|
||||||
|
|
@ -34,11 +37,25 @@ trait ResistanceProfile {
|
||||||
* This is for defining both accessor and mutator functions.
|
* This is for defining both accessor and mutator functions.
|
||||||
*/
|
*/
|
||||||
trait ResistanceProfileMutators extends ResistanceProfile {
|
trait ResistanceProfileMutators extends ResistanceProfile {
|
||||||
|
private var subtract : DamageProfile = new StandardDamageProfile {
|
||||||
|
//subtract numbers are always negative modifiers
|
||||||
|
override def Damage0_=(damage : Int) : Int = super.Damage0_=( if(damage < 1) damage else -damage)
|
||||||
|
|
||||||
|
override def Damage1_=(damage : Int) : Int = super.Damage1_=( if(damage < 1) damage else -damage)
|
||||||
|
|
||||||
|
override def Damage2_=(damage : Int) : Int = super.Damage2_=( if(damage < 1) damage else -damage)
|
||||||
|
|
||||||
|
override def Damage3_=(damage : Int) : Int = super.Damage3_=( if(damage < 1) damage else -damage)
|
||||||
|
|
||||||
|
override def Damage4_=(damage : Int) : Int = super.Damage4_=( if(damage < 1) damage else -damage)
|
||||||
|
}
|
||||||
private var resistanceDirectHit : Int = 0
|
private var resistanceDirectHit : Int = 0
|
||||||
private var resistanceSplash : Int = 0
|
private var resistanceSplash : Int = 0
|
||||||
private var resistanceAggravated : Int = 0
|
private var resistanceAggravated : Int = 0
|
||||||
private var radiationShielding : Float = 0f
|
private var radiationShielding : Float = 0f
|
||||||
|
|
||||||
|
def Subtract : DamageProfile = subtract
|
||||||
|
|
||||||
def ResistanceDirectHit : Int = resistanceDirectHit
|
def ResistanceDirectHit : Int = resistanceDirectHit
|
||||||
|
|
||||||
def ResistanceDirectHit_=(resist : Int) : Int = {
|
def ResistanceDirectHit_=(resist : Int) : Int = {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package net.psforever.objects.vital.resolution
|
||||||
import net.psforever.objects.{Player, TurretDeployable, Vehicle}
|
import net.psforever.objects.{Player, TurretDeployable, Vehicle}
|
||||||
import net.psforever.objects.ballistics.{PlayerSource, ResolvedProjectile}
|
import net.psforever.objects.ballistics.{PlayerSource, ResolvedProjectile}
|
||||||
import net.psforever.objects.ce.{ComplexDeployable, SimpleDeployable}
|
import net.psforever.objects.ce.{ComplexDeployable, SimpleDeployable}
|
||||||
|
import net.psforever.objects.serverobject.turret.FacilityTurret
|
||||||
import net.psforever.objects.vital.projectile.ProjectileCalculations
|
import net.psforever.objects.vital.projectile.ProjectileCalculations
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -159,12 +160,17 @@ object ResolutionCalculations {
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
|
|
||||||
def SimpleDeployableApplication(damage : Int, data : ResolvedProjectile)(target : Any) : Unit = target match {
|
def SimpleApplication(damage : Int, data : ResolvedProjectile)(target : Any) : Unit = target match {
|
||||||
case ce : SimpleDeployable =>
|
case ce : SimpleDeployable =>
|
||||||
if(ce.Health > 0) {
|
if(ce.Health > 0) {
|
||||||
ce.Health -= damage
|
ce.Health -= damage
|
||||||
ce.History(data)
|
ce.History(data)
|
||||||
}
|
}
|
||||||
|
case turret : FacilityTurret =>
|
||||||
|
if(turret.Health > 0) {
|
||||||
|
turret.Health -= damage
|
||||||
|
turret.History(data)
|
||||||
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import net.psforever.objects.guid.actor.UniqueNumberSystem
|
||||||
import net.psforever.objects.guid.selector.RandomSelector
|
import net.psforever.objects.guid.selector.RandomSelector
|
||||||
import net.psforever.objects.guid.source.LimitedNumberSource
|
import net.psforever.objects.guid.source.LimitedNumberSource
|
||||||
import net.psforever.objects.inventory.Container
|
import net.psforever.objects.inventory.Container
|
||||||
|
import net.psforever.objects.serverobject.resourcesilo.ResourceSilo
|
||||||
import net.psforever.objects.serverobject.structures.{Amenity, Building}
|
import net.psforever.objects.serverobject.structures.{Amenity, Building}
|
||||||
import net.psforever.objects.serverobject.tube.SpawnTube
|
import net.psforever.objects.serverobject.tube.SpawnTube
|
||||||
import net.psforever.objects.serverobject.turret.FacilityTurret
|
import net.psforever.objects.serverobject.turret.FacilityTurret
|
||||||
|
|
@ -358,6 +359,13 @@ class Zone(private val zoneId : String, zoneMap : ZoneMap, zoneNumber : Int) {
|
||||||
case (None, _) | (_, None) => ; //let ZoneActor's sanity check catch this error
|
case (None, _) | (_, None) => ; //let ZoneActor's sanity check catch this error
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
//ntu management (eventually move to a generic building startup function)
|
||||||
|
buildings.values
|
||||||
|
.flatMap(_.Amenities.filter(_.Definition == GlobalDefinitions.resource_silo))
|
||||||
|
.collect {
|
||||||
|
case silo : ResourceSilo =>
|
||||||
|
silo.Actor ! "startup"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def CreateSpawnGroups() : Unit = {
|
private def CreateSpawnGroups() : Unit = {
|
||||||
|
|
|
||||||
|
|
@ -2,33 +2,45 @@
|
||||||
package net.psforever.packet.game
|
package net.psforever.packet.game
|
||||||
|
|
||||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||||
import net.psforever.types.Vector3
|
import net.psforever.types.{SpawnGroup, Vector3}
|
||||||
import scodec.Codec
|
import scodec.Codec
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The purpose of the `BindPlayerMessage` packet.<br>
|
||||||
|
* <br>
|
||||||
|
* `Bind` and `Unbind` are generally manual actions performed by the player.
|
||||||
|
* `Available` is applied to automatic Advanced Mobile Spawn points and other "Bound" points at the time of redeployment.
|
||||||
|
* `Lost` and `Unavailable` remove the status of being bound and have slightly different connotations.
|
||||||
|
* Each generates a different a events chat message if logging it turned on.
|
||||||
|
*/
|
||||||
|
object BindStatus extends Enumeration(1) {
|
||||||
|
type Type = Value
|
||||||
|
|
||||||
|
val
|
||||||
|
Bind,
|
||||||
|
Unbind,
|
||||||
|
Lost,
|
||||||
|
Available,
|
||||||
|
Unavailable
|
||||||
|
= Value
|
||||||
|
|
||||||
|
implicit val codec = PacketHelpers.createEnumerationCodec(this, uint8)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A packet dispatched to maintain a manually-set respawn location.<br>
|
* A packet dispatched to maintain a manually-set respawn location.<br>
|
||||||
* <br>
|
* <br>
|
||||||
* The packet establishes the player's ability to spawn in an arbitrary location that is not a normal local option.
|
* The packet establishes the player's ability to spawn in an arbitrary location that is not a normal local option.
|
||||||
* This process is called "binding."
|
* This process is called "binding one's matrix."
|
||||||
* In addition to player establishing the binding, the packet updates as conditions of the respawn location changes.<br>
|
* In addition to player establishing the binding, the packet updates as conditions of the respawn location changes.<br>
|
||||||
* <br>
|
* <br>
|
||||||
* If `logging` is turned on, packets will display different messages depending on context.
|
* If `logging` is turned on, packets will display different messages depending on context.
|
||||||
|
* The bind descriptor will be used to flavor the events chat message.
|
||||||
* As long as the event is marked to be logged, when the packet is received, a message is displayed in the events window.
|
* As long as the event is marked to be logged, when the packet is received, a message is displayed in the events window.
|
||||||
* If the logged action is applicable, the matrixing sound effect will be played too.
|
* If the logged action is applicable, the matrixing sound effect will be played too.
|
||||||
* Not displaying events is occasionally warranted for aesthetics.
|
* Not displaying events is occasionally warranted for aesthetics.
|
||||||
* The game will always note if this is your first time binding.<br>
|
* The game will always note if this is your first time binding regardless of the state of this flag.<br>
|
||||||
* <br>
|
|
||||||
* One common occurrence of this packet is during zone transport.
|
|
||||||
* Specifically, a packet is dispatched after unloading the current zone but before beginning loading in the new zone.
|
|
||||||
* It is preceded by all of the `ObjectDeleteMessage` packets and itself precedes the `LoadMapMessage` packet.<br>
|
|
||||||
* <br>
|
|
||||||
* Actions:<br>
|
|
||||||
* `1` - bound to respawn point<br>
|
|
||||||
* `2` - general unbound / unbinding from respawn point<br>
|
|
||||||
* `3` - respawn point lost<br>
|
|
||||||
* `4` - bound spawn point became available<br>
|
|
||||||
* `5` - bound spawn point became unavailable (different from 3)<br>
|
|
||||||
* <br>
|
* <br>
|
||||||
* Bind Descriptors:<br>
|
* Bind Descriptors:<br>
|
||||||
* `@amp_station`<br>
|
* `@amp_station`<br>
|
||||||
|
|
@ -41,22 +53,28 @@ import scodec.codecs._
|
||||||
* Exploration:<br>
|
* Exploration:<br>
|
||||||
* Find other bind descriptors.
|
* Find other bind descriptors.
|
||||||
* @param action the purpose of the packet
|
* @param action the purpose of the packet
|
||||||
* @param bindDesc a description of the respawn binding point
|
* @param bind_desc a text description of the respawn binding point
|
||||||
* @param unk1 na; usually set `true` if there is more data in the packet ...
|
* @param unk1 na;
|
||||||
|
* usually set `true` if there is more data in the packet ...
|
||||||
* @param logging true, to report on bind point change visible in the events window;
|
* @param logging true, to report on bind point change visible in the events window;
|
||||||
* false, to render spawn change silent;
|
* false, to render spawn change silent;
|
||||||
* a first time event notification will always show
|
* some first time notifications will always display regardless of this flag
|
||||||
* @param unk2 na; if a value, it is usually 40 (hex`28`)
|
* @param spawn_group the kind of spawn request that will be made;
|
||||||
* @param unk3 na
|
* affects the type of icon displayed;
|
||||||
|
* will coincide with the value of `unk2` in `SpawnRequestMessage` when the spawn option is selected
|
||||||
|
* @param zone_number the number of the zone in which to display this spawn option;
|
||||||
|
* if `zone_number` is not the current zone, and the action is positive,
|
||||||
|
* a small map of the alternate zone with selectable spawn point will become visible
|
||||||
* @param unk4 na
|
* @param unk4 na
|
||||||
* @param pos a position associated with the binding
|
* @param pos coordinates for any displayed deployment map icon;
|
||||||
|
* `x` and `y` determine the position
|
||||||
*/
|
*/
|
||||||
final case class BindPlayerMessage(action : Int,
|
final case class BindPlayerMessage(action : BindStatus.Value,
|
||||||
bindDesc : String,
|
bind_desc : String,
|
||||||
unk1 : Boolean,
|
unk1 : Boolean,
|
||||||
logging : Boolean,
|
logging : Boolean,
|
||||||
unk2 : Int,
|
spawn_group : SpawnGroup.Value,
|
||||||
unk3 : Long,
|
zone_number : Long,
|
||||||
unk4 : Long,
|
unk4 : Long,
|
||||||
pos : Vector3)
|
pos : Vector3)
|
||||||
extends PlanetSideGamePacket {
|
extends PlanetSideGamePacket {
|
||||||
|
|
@ -68,20 +86,18 @@ final case class BindPlayerMessage(action : Int,
|
||||||
object BindPlayerMessage extends Marshallable[BindPlayerMessage] {
|
object BindPlayerMessage extends Marshallable[BindPlayerMessage] {
|
||||||
/**
|
/**
|
||||||
* A common variant of this packet.
|
* A common variant of this packet.
|
||||||
* `16028004000000000000000000000000000000`
|
|
||||||
*/
|
*/
|
||||||
val STANDARD = BindPlayerMessage(2, "", false, false, 2, 0, 0, Vector3(0, 0, 0))
|
val Standard = BindPlayerMessage(BindStatus.Unbind, "", false, false, SpawnGroup.BoundAMS, 0, 0, Vector3.Zero)
|
||||||
|
|
||||||
|
private val spawnGroupCodec = PacketHelpers.createEnumerationCodec(SpawnGroup, uint4)
|
||||||
|
|
||||||
//TODO: there are two ignore(1) in this packet; are they in a good position?
|
|
||||||
implicit val codec : Codec[BindPlayerMessage] = (
|
implicit val codec : Codec[BindPlayerMessage] = (
|
||||||
("action" | uint8L) ::
|
("action" | BindStatus.codec) ::
|
||||||
("bindDesc" | PacketHelpers.encodedString) ::
|
("bind_desc" | PacketHelpers.encodedString) ::
|
||||||
("unk1" | bool) ::
|
("unk1" | bool) ::
|
||||||
("logging" | bool) ::
|
("logging" | bool) ::
|
||||||
ignore(1) ::
|
("spawn_group" | spawnGroupCodec) ::
|
||||||
("unk2" | uint4L) ::
|
("zone_number" | uint32L) ::
|
||||||
ignore(1) ::
|
|
||||||
("unk3" | uint32L) ::
|
|
||||||
("unk4" | uint32L) ::
|
("unk4" | uint32L) ::
|
||||||
("pos" | Vector3.codec_pos)
|
("pos" | Vector3.codec_pos)
|
||||||
).as[BindPlayerMessage]
|
).as[BindPlayerMessage]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
// Copyright (c) 2017 PSForever
|
// Copyright (c) 2017 PSForever
|
||||||
package net.psforever.packet.game
|
package net.psforever.packet.game
|
||||||
|
|
||||||
import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
|
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
|
||||||
|
import net.psforever.types.SpawnGroup
|
||||||
import scodec.Codec
|
import scodec.Codec
|
||||||
import scodec.codecs._
|
import scodec.codecs._
|
||||||
|
|
||||||
|
|
@ -9,20 +10,16 @@ import scodec.codecs._
|
||||||
* na
|
* na
|
||||||
* @param unk1 when defined, na;
|
* @param unk1 when defined, na;
|
||||||
* non-zero when selecting the sanctuary option from a non-sanctuary continent deployment map
|
* non-zero when selecting the sanctuary option from a non-sanctuary continent deployment map
|
||||||
* @param unk2 when defined, indicates type of spawn point by destination;
|
* @param spawn_type the type of spawn point destination
|
||||||
* 0 is nothing;
|
|
||||||
* 2 is ams;
|
|
||||||
* 6 is towers;
|
|
||||||
* 7 is facilities
|
|
||||||
* @param unk3 na
|
* @param unk3 na
|
||||||
* @param unk4 na
|
* @param unk4 na
|
||||||
* @param unk5 when defined, the continent number
|
* @param zone_number when defined, the continent number
|
||||||
*/
|
*/
|
||||||
final case class SpawnRequestMessage(unk1 : Int,
|
final case class SpawnRequestMessage(unk1 : Int,
|
||||||
unk2 : Long,
|
spawn_type : SpawnGroup.Value,
|
||||||
unk3 : Int,
|
unk3 : Int,
|
||||||
unk4 : Int,
|
unk4 : Int,
|
||||||
unk5 : Int)
|
zone_number : Int)
|
||||||
extends PlanetSideGamePacket {
|
extends PlanetSideGamePacket {
|
||||||
type Packet = SpawnRequestMessage
|
type Packet = SpawnRequestMessage
|
||||||
def opcode = GamePacketOpcode.SpawnRequestMessage
|
def opcode = GamePacketOpcode.SpawnRequestMessage
|
||||||
|
|
@ -30,11 +27,13 @@ final case class SpawnRequestMessage(unk1 : Int,
|
||||||
}
|
}
|
||||||
|
|
||||||
object SpawnRequestMessage extends Marshallable[SpawnRequestMessage] {
|
object SpawnRequestMessage extends Marshallable[SpawnRequestMessage] {
|
||||||
|
private val spawnGroupCodec = PacketHelpers.createLongEnumerationCodec(SpawnGroup, uint32L)
|
||||||
|
|
||||||
implicit val codec : Codec[SpawnRequestMessage] = (
|
implicit val codec : Codec[SpawnRequestMessage] = (
|
||||||
("unk1" | uint16L) ::
|
("unk1" | uint16L) ::
|
||||||
("unk2" | uint32L) ::
|
("spawn_type" | spawnGroupCodec) ::
|
||||||
("unk3" | uint16L) ::
|
("unk3" | uint16L) ::
|
||||||
("unk4" | uint16L) ::
|
("unk4" | uint16L) ::
|
||||||
("unk5" | uintL(10))
|
("zone_number" | uintL(10))
|
||||||
).as[SpawnRequestMessage]
|
).as[SpawnRequestMessage]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
common/src/main/scala/net/psforever/types/SpawnGroup.scala
Normal file
39
common/src/main/scala/net/psforever/types/SpawnGroup.scala
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) 2017 PSForever
|
||||||
|
package net.psforever.types
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The spawn group.<br>
|
||||||
|
* <br>
|
||||||
|
* The groups `Sanctuary`, `Tower`, and ,`Facility` are typically hard-defined by the client.
|
||||||
|
* The groups `AMS` and the `Bound*` spawns can only be displayed on the deployment map
|
||||||
|
* by sending a manual `BindPlayerMessage` packet to the client,
|
||||||
|
* and the designated spawn group identifier is returned to the server if the spawn point that is created is selected.
|
||||||
|
* The sanctuary spawn is also used as a fallback for an unknown spawn point
|
||||||
|
* as going back to one's own sanctuary counts as a "safe spawn."<br>
|
||||||
|
* <br>
|
||||||
|
* The `Sanctuary` spawn is commonly accessible on a smaller map (of the sanctuary continent)
|
||||||
|
* off to one side of the greater deployment map.
|
||||||
|
* It does not generate an icon when manually set.
|
||||||
|
* The icons produced by the normal and the bound tower and facility groups are not detailed.
|
||||||
|
* The ones that are not designated as "bound" also do not display icons when manually set.
|
||||||
|
* The AMS spawn group icons have an overhead AMS glyph and are smaller in radius, identical otherwise.
|
||||||
|
*/
|
||||||
|
object SpawnGroup extends Enumeration {
|
||||||
|
type Type = Value
|
||||||
|
|
||||||
|
val
|
||||||
|
Sanctuary,
|
||||||
|
BoundAMS,
|
||||||
|
AMS,
|
||||||
|
Unknown3,
|
||||||
|
BoundTower, //unused?
|
||||||
|
BoundFacility,
|
||||||
|
Tower,
|
||||||
|
Facility,
|
||||||
|
Unknown8,
|
||||||
|
Unknown9,
|
||||||
|
Unknown10,
|
||||||
|
Unknown11,
|
||||||
|
Unknown12
|
||||||
|
= Value
|
||||||
|
}
|
||||||
|
|
@ -198,7 +198,7 @@ class VehicleService extends Actor {
|
||||||
import net.psforever.objects.vehicles.UtilityType
|
import net.psforever.objects.vehicles.UtilityType
|
||||||
import net.psforever.objects.GlobalDefinitions
|
import net.psforever.objects.GlobalDefinitions
|
||||||
zone.Vehicles
|
zone.Vehicles
|
||||||
.filter(veh => veh.Definition == GlobalDefinitions.ams && veh.DeploymentState == DriveState.Deployed)
|
.filter(veh => veh.Health > 0 && veh.Definition == GlobalDefinitions.ams && veh.DeploymentState == DriveState.Deployed)
|
||||||
.flatMap(veh => veh.Utilities.values.filter(util => util.UtilType == UtilityType.ams_respawn_tube) )
|
.flatMap(veh => veh.Utilities.values.filter(util => util.UtilType == UtilityType.ams_respawn_tube) )
|
||||||
.map(util => util().asInstanceOf[SpawnTube])
|
.map(util => util().asInstanceOf[SpawnTube])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,7 @@ class VehicleRemover extends RemoverActor {
|
||||||
val zoneId = entry.zone.Id
|
val zoneId = entry.zone.Id
|
||||||
vehicle.Actor ! Vehicle.PrepareForDeletion
|
vehicle.Actor ! Vehicle.PrepareForDeletion
|
||||||
//kick out all passengers
|
//kick out all passengers
|
||||||
vehicle.Definition.MountPoints.values.foreach(mount => {
|
vehicle.Seats.values.foreach(seat => {
|
||||||
val seat = vehicle.Seat(mount).get
|
|
||||||
seat.Occupant match {
|
seat.Occupant match {
|
||||||
case Some(tplayer) =>
|
case Some(tplayer) =>
|
||||||
seat.Occupant = None
|
seat.Occupant = None
|
||||||
|
|
|
||||||
|
|
@ -4,27 +4,42 @@ package game
|
||||||
import org.specs2.mutable._
|
import org.specs2.mutable._
|
||||||
import net.psforever.packet._
|
import net.psforever.packet._
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
import net.psforever.types.Vector3
|
import net.psforever.types.{SpawnGroup, Vector3}
|
||||||
import scodec.bits._
|
import scodec.bits._
|
||||||
|
|
||||||
class BindPlayerMessageTest extends Specification {
|
class BindPlayerMessageTest extends Specification {
|
||||||
|
val string_standard = hex"16028004000000000000000000000000000000"
|
||||||
val string_ams = hex"16 05 8440616D73 08 28000000 00000000 00000 00000 0000"
|
val string_ams = hex"16 05 8440616D73 08 28000000 00000000 00000 00000 0000"
|
||||||
val string_tech = hex"16 01 8b40746563685f706c616e74 d4 28000000 38000000 00064 012b1 a044"
|
val string_tech = hex"16 01 8b40746563685f706c616e74 d4 28000000 38000000 00064 012b1 a044"
|
||||||
|
val string_akkan = hex"16048440616d7388100000001400000214e171a8e33024"
|
||||||
|
|
||||||
|
"decode (standard)" in {
|
||||||
|
PacketCoding.DecodePacket(string_standard).require match {
|
||||||
|
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||||
|
action mustEqual BindStatus.Unbind
|
||||||
|
bindDesc mustEqual ""
|
||||||
|
unk1 mustEqual false
|
||||||
|
logging mustEqual false
|
||||||
|
unk2 mustEqual SpawnGroup.BoundAMS
|
||||||
|
unk3 mustEqual 0
|
||||||
|
unk4 mustEqual 0
|
||||||
|
pos mustEqual Vector3.Zero
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"decode (ams)" in {
|
"decode (ams)" in {
|
||||||
PacketCoding.DecodePacket(string_ams).require match {
|
PacketCoding.DecodePacket(string_ams).require match {
|
||||||
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||||
action mustEqual 5
|
action mustEqual BindStatus.Unavailable
|
||||||
bindDesc.length mustEqual 4
|
|
||||||
bindDesc mustEqual "@ams"
|
bindDesc mustEqual "@ams"
|
||||||
unk1 mustEqual false
|
unk1 mustEqual false
|
||||||
logging mustEqual false
|
logging mustEqual false
|
||||||
unk2 mustEqual 4
|
unk2 mustEqual SpawnGroup.AMS
|
||||||
unk3 mustEqual 40
|
unk3 mustEqual 10
|
||||||
unk4 mustEqual 0
|
unk4 mustEqual 0
|
||||||
pos.x mustEqual 0f
|
pos mustEqual Vector3.Zero
|
||||||
pos.y mustEqual 0f
|
|
||||||
pos.z mustEqual 0f
|
|
||||||
case _ =>
|
case _ =>
|
||||||
ko
|
ko
|
||||||
}
|
}
|
||||||
|
|
@ -33,40 +48,60 @@ class BindPlayerMessageTest extends Specification {
|
||||||
"decode (tech)" in {
|
"decode (tech)" in {
|
||||||
PacketCoding.DecodePacket(string_tech).require match {
|
PacketCoding.DecodePacket(string_tech).require match {
|
||||||
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||||
action mustEqual 1
|
action mustEqual BindStatus.Bind
|
||||||
bindDesc.length mustEqual 11
|
|
||||||
bindDesc mustEqual "@tech_plant"
|
bindDesc mustEqual "@tech_plant"
|
||||||
unk1 mustEqual true
|
unk1 mustEqual true
|
||||||
logging mustEqual true
|
logging mustEqual true
|
||||||
unk2 mustEqual 10
|
unk2 mustEqual SpawnGroup.BoundFacility
|
||||||
unk3 mustEqual 40
|
unk3 mustEqual 10
|
||||||
unk4 mustEqual 56
|
unk4 mustEqual 14
|
||||||
pos.x mustEqual 2060.0f
|
pos mustEqual Vector3(4610.0f, 6292, 69.625f)
|
||||||
pos.y mustEqual 598.0078f
|
|
||||||
pos.z mustEqual 274.5f
|
|
||||||
case _ =>
|
case _ =>
|
||||||
ko
|
ko
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"decode (akkan)" in {
|
||||||
|
PacketCoding.DecodePacket(string_akkan).require match {
|
||||||
|
case BindPlayerMessage(action, bindDesc, unk1, logging, unk2, unk3, unk4, pos) =>
|
||||||
|
action mustEqual BindStatus.Available
|
||||||
|
bindDesc mustEqual "@ams"
|
||||||
|
unk1 mustEqual true
|
||||||
|
logging mustEqual false
|
||||||
|
unk2 mustEqual SpawnGroup.AMS
|
||||||
|
unk3 mustEqual 4
|
||||||
|
unk4 mustEqual 5
|
||||||
|
pos mustEqual Vector3(2673.039f, 4423.547f, 39.1875f)
|
||||||
|
case _ =>
|
||||||
|
ko
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"encode (standard)" in {
|
||||||
|
val msg = BindPlayerMessage.Standard
|
||||||
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
|
pkt mustEqual string_standard
|
||||||
|
}
|
||||||
|
|
||||||
"encode (ams)" in {
|
"encode (ams)" in {
|
||||||
val msg = BindPlayerMessage(5, "@ams", false, false, 4, 40, 0, Vector3(0, 0, 0))
|
val msg = BindPlayerMessage(BindStatus.Unavailable, "@ams", false, false, SpawnGroup.AMS, 10, 0, Vector3.Zero)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
pkt mustEqual string_ams
|
pkt mustEqual string_ams
|
||||||
}
|
}
|
||||||
|
|
||||||
"encode (tech)" in {
|
"encode (tech)" in {
|
||||||
val msg = BindPlayerMessage(1, "@tech_plant", true, true, 10, 40, 56, Vector3(2060.0f, 598.0078f, 274.5f))
|
val msg = BindPlayerMessage(BindStatus.Bind, "@tech_plant", true, true, SpawnGroup.BoundFacility, 10, 14, Vector3(4610.0f, 6292, 69.625f))
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
pkt mustEqual string_tech
|
pkt mustEqual string_tech
|
||||||
}
|
}
|
||||||
|
|
||||||
"standard" in {
|
"encode (akkan)" in {
|
||||||
val msg = BindPlayerMessage.STANDARD
|
val msg = BindPlayerMessage(BindStatus.Available, "@ams", true, false, SpawnGroup.AMS, 4, 5, Vector3(2673.039f, 4423.547f, 39.1875f))
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
pkt mustEqual hex"16028004000000000000000000000000000000"
|
pkt mustEqual string_akkan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package game
|
||||||
import org.specs2.mutable._
|
import org.specs2.mutable._
|
||||||
import net.psforever.packet._
|
import net.psforever.packet._
|
||||||
import net.psforever.packet.game._
|
import net.psforever.packet.game._
|
||||||
|
import net.psforever.types.SpawnGroup
|
||||||
import scodec.bits._
|
import scodec.bits._
|
||||||
|
|
||||||
class SpawnRequestMessageTest extends Specification {
|
class SpawnRequestMessageTest extends Specification {
|
||||||
|
|
@ -13,7 +14,7 @@ class SpawnRequestMessageTest extends Specification {
|
||||||
PacketCoding.DecodePacket(string).require match {
|
PacketCoding.DecodePacket(string).require match {
|
||||||
case SpawnRequestMessage(unk1,unk2,unk3,unk4,unk5) =>
|
case SpawnRequestMessage(unk1,unk2,unk3,unk4,unk5) =>
|
||||||
unk1 mustEqual 0
|
unk1 mustEqual 0
|
||||||
unk2 mustEqual 7
|
unk2 mustEqual SpawnGroup.Facility
|
||||||
unk3 mustEqual 0
|
unk3 mustEqual 0
|
||||||
unk4 mustEqual 0
|
unk4 mustEqual 0
|
||||||
unk5 mustEqual 2
|
unk5 mustEqual 2
|
||||||
|
|
@ -23,7 +24,7 @@ class SpawnRequestMessageTest extends Specification {
|
||||||
}
|
}
|
||||||
|
|
||||||
"encode" in {
|
"encode" in {
|
||||||
val msg = SpawnRequestMessage(0, 7, 0, 0, 2)
|
val msg = SpawnRequestMessage(0, SpawnGroup.Facility, 0, 0, 2)
|
||||||
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
|
||||||
|
|
||||||
pkt mustEqual string
|
pkt mustEqual string
|
||||||
|
|
|
||||||
|
|
@ -106,12 +106,12 @@ class DamageCalculationsTests extends Specification {
|
||||||
|
|
||||||
"calculate splash damage from components (near)" in {
|
"calculate splash damage from components (near)" in {
|
||||||
val result = DamageWithModifiers(DamageAgainstVehicle)(proj_prof, List(wep_prof))
|
val result = DamageWithModifiers(DamageAgainstVehicle)(proj_prof, List(wep_prof))
|
||||||
SplashDamageWithRadialDegrade(projectile, result, 0) mustEqual 264
|
SplashDamageWithRadialDegrade(projectile, result, 0) mustEqual 132
|
||||||
}
|
}
|
||||||
|
|
||||||
"calculate splash damage from components (medium)" in {
|
"calculate splash damage from components (medium)" in {
|
||||||
val result = DamageWithModifiers(DamageAgainstVehicle)(proj_prof, List(wep_prof))
|
val result = DamageWithModifiers(DamageAgainstVehicle)(proj_prof, List(wep_prof))
|
||||||
SplashDamageWithRadialDegrade(projectile, result, 5) mustEqual 145
|
SplashDamageWithRadialDegrade(projectile, result, 5) mustEqual 13
|
||||||
}
|
}
|
||||||
|
|
||||||
"calculate splash damage from components (far)" in {
|
"calculate splash damage from components (far)" in {
|
||||||
|
|
@ -341,7 +341,7 @@ class DamageModelTests extends Specification {
|
||||||
val func : (Any)=>Unit = resprojectile.damage_model.Calculate(resprojectile, ProjectileResolution.Splash)
|
val func : (Any)=>Unit = resprojectile.damage_model.Calculate(resprojectile, ProjectileResolution.Splash)
|
||||||
|
|
||||||
func(tplayer)
|
func(tplayer)
|
||||||
tplayer.Health mustEqual 81
|
tplayer.Health mustEqual 98
|
||||||
tplayer.Armor mustEqual 35
|
tplayer.Armor mustEqual 35
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -410,7 +410,7 @@ class DamageModelTests extends Specification {
|
||||||
val func : (Any)=>Unit = resprojectile.damage_model.Calculate(resprojectile, ProjectileResolution.Splash)
|
val func : (Any)=>Unit = resprojectile.damage_model.Calculate(resprojectile, ProjectileResolution.Splash)
|
||||||
|
|
||||||
func(vehicle)
|
func(vehicle)
|
||||||
vehicle.Health mustEqual 632
|
vehicle.Health mustEqual 641
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ class EquipmentTest extends Specification {
|
||||||
obj.Size = EquipmentSize.Rifle
|
obj.Size = EquipmentSize.Rifle
|
||||||
obj.AmmoTypes += GlobalDefinitions.shotgun_shell
|
obj.AmmoTypes += GlobalDefinitions.shotgun_shell
|
||||||
obj.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
|
obj.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
|
||||||
|
obj.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
|
||||||
obj.FireModes += new FireModeDefinition
|
obj.FireModes += new FireModeDefinition
|
||||||
obj.FireModes.head.AmmoTypeIndices += 0
|
obj.FireModes.head.AmmoTypeIndices += 0
|
||||||
obj.FireModes.head.AmmoTypeIndices += 1
|
obj.FireModes.head.AmmoTypeIndices += 1
|
||||||
|
|
@ -163,6 +164,29 @@ class EquipmentTest extends Specification {
|
||||||
obj.AmmoType mustEqual Ammo.hellfire_ammo
|
obj.AmmoType mustEqual Ammo.hellfire_ammo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"default fire mode (dual magazine feed)" in {
|
||||||
|
val obj = ToolDefinition(1076)
|
||||||
|
obj.AmmoTypes += GlobalDefinitions.shotgun_shell
|
||||||
|
obj.AmmoTypes += GlobalDefinitions.shotgun_shell_AP
|
||||||
|
obj.ProjectileTypes += GlobalDefinitions.shotgun_shell_projectile
|
||||||
|
obj.ProjectileTypes += GlobalDefinitions.shotgun_shell_AP_projectile
|
||||||
|
obj.FireModes += new FireModeDefinition
|
||||||
|
obj.FireModes.head.AmmoTypeIndices += 0
|
||||||
|
obj.FireModes.head.AmmoSlotIndex = 0
|
||||||
|
obj.FireModes += new FireModeDefinition
|
||||||
|
obj.FireModes(1).AmmoTypeIndices += 1
|
||||||
|
obj.FireModes(1).AmmoSlotIndex = 1
|
||||||
|
|
||||||
|
val tool0 = Tool(obj)
|
||||||
|
tool0.FireModeIndex mustEqual 0
|
||||||
|
tool0.ProjectileType mustEqual GlobalDefinitions.shotgun_shell_projectile.ProjectileType
|
||||||
|
|
||||||
|
obj.DefaultFireModeIndex = 1
|
||||||
|
val tool1 = Tool(obj)
|
||||||
|
tool1.FireModeIndex mustEqual 1
|
||||||
|
tool1.ProjectileType mustEqual GlobalDefinitions.shotgun_shell_AP_projectile.ProjectileType
|
||||||
|
}
|
||||||
|
|
||||||
"multiple fire modes" in {
|
"multiple fire modes" in {
|
||||||
//explanation: sample_weapon has two fire modes; each fire mode has a different ammunition type
|
//explanation: sample_weapon has two fire modes; each fire mode has a different ammunition type
|
||||||
val obj : Tool = Tool(punisher)
|
val obj : Tool = Tool(punisher)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue