mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
Last Infantry Weapons (#987)
* preparations for deploying oicw little buddy projectiles * oicw little buddy projectiles spawn and animate properly, but damage dealing is inconclusive * radiator clouds cause damage to infantry health * oicw little buddy projectiles do damage upon detonation; different descent pattern; projectile types given own Enumeration * proximity terminals for vehicle actions no longer need to use the vehicle event system as a middleman for making changes * redid the workflow of the proximity terminal resolution so that it avoids SessionActor as much as is possible; this may be a mistake, but my future self will pay the price instead * changed the timing and the angles of the little buddy explosions; fixed proximity terminal tests
This commit is contained in:
parent
2b58d126b5
commit
0d8c717b73
|
|
@ -12,7 +12,7 @@ ignore:
|
|||
- "src/main/scala/net/psforever/objects/ObjectType.scala"
|
||||
- "src/main/scala/net/psforever/objects/avatar/Avatars.scala"
|
||||
- "src/main/scala/net/psforever/objects/ballistics/DamageResolution.scala"
|
||||
- "src/main/scala/net/psforever/objects/ballistics/Projectiles.scala"
|
||||
- "src/main/scala/net/psforever/objects/ballistics/Projectiles.Types.scala"
|
||||
- "src/main/scala/net/psforever/objects/equipment/Ammo.scala"
|
||||
- "src/main/scala/net/psforever/objects/equipment/CItem.scala"
|
||||
- "src/main/scala/net/psforever/objects/equipment/EquipmentSize.scala"
|
||||
|
|
|
|||
|
|
@ -659,8 +659,10 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
case Terminal.TerminalMessage(tplayer, msg, order) =>
|
||||
HandleTerminalMessage(tplayer, msg, order)
|
||||
|
||||
case ProximityUnit.Action(term, target) =>
|
||||
SelectProximityUnitBehavior(term, target)
|
||||
case ProximityUnit.Action(_, _) => ;
|
||||
|
||||
case ProximityUnit.StopAction(term, target) =>
|
||||
LocalStopUsingProximityUnit(term, target)
|
||||
|
||||
case VehicleServiceResponse(toChannel, guid, reply) =>
|
||||
HandleVehicleServiceResponse(toChannel, guid, reply)
|
||||
|
|
@ -5200,7 +5202,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
}
|
||||
|
||||
case msg @ GenericObjectActionAtPositionMessage(object_guid, _, _) =>
|
||||
//log.info(s"$msg")
|
||||
ValidObject(object_guid, decorator = "GenericObjectActionAtPosition") match {
|
||||
case Some(tool: Tool) if GlobalDefinitions.isBattleFrameNTUSiphon(tool.Definition) =>
|
||||
FindContainedWeapon match {
|
||||
|
|
@ -5208,7 +5209,8 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
vehicle.Actor ! SpecialEmp.Burst()
|
||||
case _ => ;
|
||||
}
|
||||
case _ => ;
|
||||
case _ =>
|
||||
log.info(s"$msg")
|
||||
}
|
||||
|
||||
case msg @ GenericObjectStateMsg(object_guid, unk1) =>
|
||||
|
|
@ -5381,6 +5383,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
_, //projectile_type,
|
||||
thrown_projectile_vel
|
||||
) =>
|
||||
log.info(s"$msg")
|
||||
HandleWeaponFire(weapon_guid, projectile_guid, shot_origin, thrown_projectile_vel.flatten)
|
||||
|
||||
case WeaponLazeTargetPositionMessage(_, _, _) => ;
|
||||
|
|
@ -7535,7 +7538,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
}
|
||||
|
||||
/**
|
||||
* Queue a proximity-base service.
|
||||
* Queue a proximity-based service.
|
||||
* @param terminal the proximity-based unit
|
||||
* @param target the entity that is being considered for terminal operation
|
||||
*/
|
||||
|
|
@ -7547,7 +7550,7 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
case _: Player =>
|
||||
terminal.Actor ! CommonMessages.Use(player, Some(target))
|
||||
case _: Vehicle =>
|
||||
terminal.Actor ! CommonMessages.Use(player, Some((target, continent.VehicleEvents)))
|
||||
terminal.Actor ! CommonMessages.Use(player, Some(target))
|
||||
case _ =>
|
||||
log.error(
|
||||
s"StartUsingProximityUnit: ${player.Name}, this ${terminal.Definition.Name} can not deal with target $target"
|
||||
|
|
@ -7562,38 +7565,30 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
}
|
||||
|
||||
/**
|
||||
* Determine which functionality to pursue by a generic proximity-functional unit given the target for its activity.
|
||||
* @see `VehicleService:receive, ProximityUnit.Action`
|
||||
* Stop using a proximity-base service.
|
||||
* If the suggested terminal detects our player or our player's vehicle as a valid target for its effect,
|
||||
* inform it that we wish it stop affecting the discovered target(s).
|
||||
* @param terminal the proximity-based unit
|
||||
* @param target the object being affected by the unit
|
||||
*/
|
||||
def SelectProximityUnitBehavior(terminal: Terminal with ProximityUnit, target: PlanetSideGameObject): Unit = {
|
||||
target match {
|
||||
case o: Player =>
|
||||
HealthAndArmorTerminal(terminal, o)
|
||||
case _ => ;
|
||||
def StopUsingProximityUnit(terminal: Terminal with ProximityUnit): Unit = {
|
||||
FindProximityUnitTargetsInScope(terminal).foreach { target =>
|
||||
LocalStopUsingProximityUnit(terminal, target)
|
||||
terminal.Actor ! CommonMessages.Unuse(player, Some(target))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop using a proximity-base service.
|
||||
* Callback to handle flags specific to `SessionActor`.
|
||||
* Special note is warranted when determining the identity of the proximity terminal.
|
||||
* Medical terminals of both varieties can be cancelled by movement.
|
||||
* Other sorts of proximity-based units are put on a timer.
|
||||
* @param terminal the proximity-based unit
|
||||
*/
|
||||
def StopUsingProximityUnit(terminal: Terminal with ProximityUnit): Unit = {
|
||||
def LocalStopUsingProximityUnit(terminal: Terminal with ProximityUnit, target: PlanetSideGameObject): Unit = {
|
||||
val term_guid = terminal.GUID
|
||||
val targets = FindProximityUnitTargetsInScope(terminal)
|
||||
if (targets.nonEmpty) {
|
||||
if (usingMedicalTerminal.contains(term_guid)) {
|
||||
usingMedicalTerminal = None
|
||||
}
|
||||
targets.foreach(target => terminal.Actor ! CommonMessages.Unuse(player, Some(target)))
|
||||
} else {
|
||||
log.warn(
|
||||
s"StopUsingProximityUnit: ${player.Name} could not find valid targets for proximity unit ${terminal.Definition.Name}@${term_guid.guid}"
|
||||
)
|
||||
if (usingMedicalTerminal.contains(term_guid)) {
|
||||
usingMedicalTerminal = None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7623,72 +7618,6 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When standing on the platform of a(n advanced) medical terminal,
|
||||
* resotre the player's health and armor points (when they need their health and armor points restored).
|
||||
* If the player is both fully healed and fully repaired, stop using the terminal.
|
||||
* @param unit the medical terminal
|
||||
* @param target the player being healed
|
||||
*/
|
||||
def HealthAndArmorTerminal(unit: Terminal with ProximityUnit, target: Player): Unit = {
|
||||
val medDef = unit.Definition.asInstanceOf[MedicalTerminalDefinition]
|
||||
val healAmount = medDef.HealAmount
|
||||
val healthFull: Boolean = if (healAmount != 0 && target.Health < target.MaxHealth) {
|
||||
target.History(HealFromTerm(PlayerSource(target), healAmount, 0, medDef))
|
||||
HealAction(target, healAmount)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
val repairAmount = medDef.ArmorAmount
|
||||
val armorFull: Boolean = if (repairAmount != 0 && target.Armor < target.MaxArmor) {
|
||||
target.History(HealFromTerm(PlayerSource(target), 0, repairAmount, medDef))
|
||||
ArmorRepairAction(target, repairAmount)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
if (healthFull && armorFull) {
|
||||
StopUsingProximityUnit(unit)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore, at most, a specific amount of health points on a player.
|
||||
* Send messages to connected client and to events system.
|
||||
* @param tplayer the player
|
||||
* @param healValue the amount to heal;
|
||||
* 10 by default
|
||||
* @return whether the player can be repaired for any more health points
|
||||
*/
|
||||
def HealAction(tplayer: Player, healValue: Int = 10): Boolean = {
|
||||
val player_guid = tplayer.GUID
|
||||
tplayer.Health = tplayer.Health + healValue
|
||||
sendResponse(PlanetsideAttributeMessage(player_guid, 0, tplayer.Health))
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.PlanetsideAttribute(player_guid, 0, tplayer.Health)
|
||||
)
|
||||
tplayer.Health == tplayer.MaxHealth
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore, at most, a specific amount of personal armor points on a player.
|
||||
* Send messages to connected client and to events system.
|
||||
* @param tplayer the player
|
||||
* @param repairValue the amount to repair;
|
||||
* 10 by default
|
||||
* @return whether the player can be repaired for any more armor points
|
||||
*/
|
||||
def ArmorRepairAction(tplayer: Player, repairValue: Int = 10): Boolean = {
|
||||
val player_guid = tplayer.GUID
|
||||
tplayer.Armor = tplayer.Armor + repairValue
|
||||
sendResponse(PlanetsideAttributeMessage(player_guid, 4, tplayer.Armor))
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.PlanetsideAttribute(player_guid, 4, tplayer.Armor)
|
||||
)
|
||||
tplayer.Armor == tplayer.MaxArmor
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is applied to vehicles that are leaving a cargo vehicle's cargo hold to auto reverse them out
|
||||
* Lock all applicable controls of the current vehicle
|
||||
|
|
@ -9353,40 +9282,110 @@ class SessionActor(middlewareActor: typed.ActorRef[MiddlewareActor.Command], con
|
|||
hitPos: Vector3
|
||||
): List[(PlanetSideGameObject with FactionAffinity with Vitality, Projectile, Vector3, Vector3)] = {
|
||||
GlobalDefinitions.getDamageProxy(projectile, hitPos) match {
|
||||
case Some(proxy) if proxy.profile.ExistsOnRemoteClients =>
|
||||
proxy.Position = hitPos
|
||||
continent.Projectile ! ZoneProjectile.Add(player.GUID, proxy)
|
||||
case Nil =>
|
||||
Nil
|
||||
|
||||
case Some(proxy)
|
||||
if proxy.tool_def == GlobalDefinitions.maelstrom =>
|
||||
//server-side maelstrom grenade target selection
|
||||
val radius = proxy.profile.LashRadius * proxy.profile.LashRadius
|
||||
val targets = continent.blockMap
|
||||
.sector(hitPos, proxy.profile.LashRadius)
|
||||
.livePlayerList
|
||||
.filter { target =>
|
||||
Vector3.DistanceSquared(target.Position, hitPos) <= radius
|
||||
}
|
||||
//chainlash is separated from the actual damage application for convenience
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.SendResponse(
|
||||
PlanetSideGUID(0),
|
||||
ChainLashMessage(
|
||||
hitPos,
|
||||
projectile.profile.ObjectId,
|
||||
targets.map { _.GUID }
|
||||
case list =>
|
||||
HandleDamageProxySetupLittleBuddy(list, hitPos)
|
||||
list.flatMap { proxy =>
|
||||
if (proxy.profile.ExistsOnRemoteClients) {
|
||||
proxy.Position = hitPos
|
||||
continent.Projectile ! ZoneProjectile.Add(player.GUID, proxy)
|
||||
Nil
|
||||
} else if (proxy.tool_def == GlobalDefinitions.maelstrom) {
|
||||
//server-side maelstrom grenade target selection
|
||||
val radius = proxy.profile.LashRadius * proxy.profile.LashRadius
|
||||
val targets = continent.blockMap
|
||||
.sector(hitPos, proxy.profile.LashRadius)
|
||||
.livePlayerList
|
||||
.filter { target =>
|
||||
Vector3.DistanceSquared(target.Position, hitPos) <= radius
|
||||
}
|
||||
//chainlash is separated from the actual damage application for convenience
|
||||
continent.AvatarEvents ! AvatarServiceMessage(
|
||||
continent.id,
|
||||
AvatarAction.SendResponse(
|
||||
PlanetSideGUID(0),
|
||||
ChainLashMessage(
|
||||
hitPos,
|
||||
projectile.profile.ObjectId,
|
||||
targets.map { _.GUID }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
targets.map { target =>
|
||||
CheckForHitPositionDiscrepancy(pguid, hitPos, target)
|
||||
(target, proxy, hitPos, target.Position)
|
||||
targets.map { target =>
|
||||
CheckForHitPositionDiscrepancy(pguid, hitPos, target)
|
||||
(target, proxy, hitPos, target.Position)
|
||||
}
|
||||
} else {
|
||||
Nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case _ =>
|
||||
Nil
|
||||
def HandleDamageProxySetupLittleBuddy(listOfProjectiles: List[Projectile], detonationPosition: Vector3): Boolean = {
|
||||
val listOfLittleBuddies: List[Projectile] = listOfProjectiles.filter { _.tool_def == GlobalDefinitions.oicw }
|
||||
val size: Int = listOfLittleBuddies.size
|
||||
if (size > 0) {
|
||||
val desiredDownwardsProjectiles: Int = 2
|
||||
val firstHalf: Int = math.min(size, desiredDownwardsProjectiles) //number that fly straight down
|
||||
val secondHalf: Int = math.max(size - firstHalf, 0) //number that are flared out
|
||||
val z: Float = player.Orientation.z //player's standing direction
|
||||
val north: Vector3 = Vector3(0,1,0) //map North
|
||||
val speed: Float = 144f //speed (packet discovered)
|
||||
val dist: Float = 25 //distance (client defined)
|
||||
val downwardsAngle: Float = -85f
|
||||
val flaredAngle: Float = -70f
|
||||
//angle of separation for downwards, degrees from vertical for flared out
|
||||
val (smallStep, smallAngle): (Float, Float) = if (firstHalf > 1) {
|
||||
(360f / firstHalf, downwardsAngle)
|
||||
} else {
|
||||
(0f, 0f)
|
||||
}
|
||||
val (largeStep, largeAngle): (Float, Float) = if (secondHalf > 1) {
|
||||
(360f / secondHalf, flaredAngle)
|
||||
} else {
|
||||
(0f, 0f)
|
||||
}
|
||||
val smallRotOffset: Float = z + 90f
|
||||
val largeRotOffset: Float = z + math.random().toFloat * 45f
|
||||
val verticalCorrection = Vector3.z(dist - dist * math.sin(math.toRadians(90 - smallAngle + largeAngle)).toFloat)
|
||||
//downwards projectiles
|
||||
var i: Int = 0
|
||||
listOfLittleBuddies.take(firstHalf).foreach { proxy =>
|
||||
val facing = (smallRotOffset + smallStep * i.toFloat) % 360
|
||||
val dir = north.Rx(smallAngle).Rz(facing)
|
||||
proxy.Position = detonationPosition + dir.xy + verticalCorrection
|
||||
proxy.Velocity = dir * speed
|
||||
proxy.Orientation = Vector3(0, (360f + smallAngle) % 360, facing)
|
||||
HandleDamageProxyLittleBuddyExplosion(proxy, dir, dist)
|
||||
i += 1
|
||||
}
|
||||
//flared out projectiles
|
||||
i = 0
|
||||
listOfLittleBuddies.drop(firstHalf).foreach { proxy =>
|
||||
val facing = (largeRotOffset + largeStep * i.toFloat) % 360
|
||||
val dir = north.Rx(largeAngle).Rz(facing)
|
||||
proxy.Position = detonationPosition + dir
|
||||
proxy.Velocity = dir * speed
|
||||
proxy.Orientation = Vector3(0, (360f + largeAngle) % 360, facing)
|
||||
HandleDamageProxyLittleBuddyExplosion(proxy, dir, dist)
|
||||
i += 1
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def HandleDamageProxyLittleBuddyExplosion(proxy: Projectile, orientation: Vector3, distance: Float): Unit = {
|
||||
//explosion
|
||||
val obj = DummyExplodingEntity(proxy)
|
||||
obj.Position = obj.Position + orientation * distance
|
||||
context.system.scheduler.scheduleOnce(500.milliseconds) {
|
||||
val c = continent
|
||||
val o = obj
|
||||
Zone.serverSideDamage(c, o, Zone.explosionDamage(None, o.Position))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2022 PSForever
|
||||
package net.psforever.objects
|
||||
|
||||
import net.psforever.objects.definition.{ObjectDefinition, ProjectileDefinition}
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||
import net.psforever.objects.vital.resolution.{DamageAndResistance, DamageResistanceModel}
|
||||
import net.psforever.objects.vital.{Vitality, VitalityDefinition}
|
||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
|
||||
class DummyExplodingEntity(
|
||||
private val obj: PlanetSideGameObject,
|
||||
private val faction: PlanetSideEmpire.Value
|
||||
)
|
||||
extends PlanetSideGameObject
|
||||
with FactionAffinity
|
||||
with Vitality {
|
||||
override def GUID = obj.GUID
|
||||
|
||||
override def Position: Vector3 = {
|
||||
if (super.Position == Vector3.Zero) {
|
||||
obj.Position
|
||||
} else {
|
||||
super.Position
|
||||
}
|
||||
}
|
||||
|
||||
override def Orientation: Vector3 = {
|
||||
if (super.Orientation == Vector3.Zero) {
|
||||
obj.Orientation
|
||||
} else {
|
||||
super.Orientation
|
||||
}
|
||||
}
|
||||
|
||||
override def Velocity : Option[Vector3] = {
|
||||
super.Velocity.orElse(obj.Velocity)
|
||||
}
|
||||
|
||||
def Faction: PlanetSideEmpire.Value = faction
|
||||
|
||||
def DamageModel: DamageAndResistance = DummyExplodingEntity.DefaultDamageResistanceModel
|
||||
|
||||
def Definition: ObjectDefinition with VitalityDefinition = {
|
||||
new DefinitionWrappedInVitality(obj.Definition)
|
||||
}
|
||||
}
|
||||
|
||||
private class DefinitionWrappedInVitality(definition: ObjectDefinition)
|
||||
extends ObjectDefinition(definition.ObjectId)
|
||||
with VitalityDefinition {
|
||||
innateDamage = definition match {
|
||||
case v: VitalityDefinition if v.innateDamage.nonEmpty => v.innateDamage.get
|
||||
case p: ProjectileDefinition => p
|
||||
case _ => GlobalDefinitions.no_projectile
|
||||
}
|
||||
|
||||
DefaultHealth = 1 //just cuz
|
||||
}
|
||||
|
||||
object DummyExplodingEntity {
|
||||
final val DefaultDamageResistanceModel = new DamageResistanceModel { }
|
||||
|
||||
def apply(obj: PlanetSideGameObject): DummyExplodingEntity = new DummyExplodingEntity(obj, PlanetSideEmpire.NEUTRAL)
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ import net.psforever.objects.serverobject.turret.{FacilityTurretDefinition, Turr
|
|||
import net.psforever.objects.vehicles.{DestroyedVehicle, InternalTelepadDefinition, UtilityType, VehicleSubsystemEntry}
|
||||
import net.psforever.objects.vital.base.DamageType
|
||||
import net.psforever.objects.vital.damage._
|
||||
import net.psforever.objects.vital.etc.{ArmorSiphonMaxDistanceCutoff, ExplodingRadialDegrade, InfantryAggravatedRadiation, InfantryAggravatedRadiationBurn}
|
||||
import net.psforever.objects.vital.etc.{ShieldAgainstRadiation => _, _}
|
||||
import net.psforever.objects.vital.projectile._
|
||||
import net.psforever.objects.vital.prop.DamageWithPosition
|
||||
import net.psforever.objects.vital._
|
||||
|
|
@ -147,299 +147,299 @@ object GlobalDefinitions {
|
|||
*/
|
||||
val no_projectile = new ProjectileDefinition(0) //also called none in ADB
|
||||
|
||||
val bullet_105mm_projectile = ProjectileDefinition(Projectiles.bullet_105mm_projectile)
|
||||
val bullet_105mm_projectile = ProjectileDefinition(Projectiles.Types.bullet_105mm_projectile)
|
||||
|
||||
val bullet_12mm_projectile = ProjectileDefinition(Projectiles.bullet_12mm_projectile)
|
||||
val bullet_12mm_projectile = ProjectileDefinition(Projectiles.Types.bullet_12mm_projectile)
|
||||
|
||||
val bullet_12mm_projectileb = ProjectileDefinition(Projectiles.bullet_12mm_projectileb)
|
||||
val bullet_12mm_projectileb = ProjectileDefinition(Projectiles.Types.bullet_12mm_projectileb)
|
||||
|
||||
val bullet_150mm_projectile = ProjectileDefinition(Projectiles.bullet_150mm_projectile)
|
||||
val bullet_150mm_projectile = ProjectileDefinition(Projectiles.Types.bullet_150mm_projectile)
|
||||
|
||||
val bullet_15mm_apc_projectile = ProjectileDefinition(Projectiles.bullet_15mm_apc_projectile)
|
||||
val bullet_15mm_apc_projectile = ProjectileDefinition(Projectiles.Types.bullet_15mm_apc_projectile)
|
||||
|
||||
val bullet_15mm_projectile = ProjectileDefinition(Projectiles.bullet_15mm_projectile)
|
||||
val bullet_15mm_projectile = ProjectileDefinition(Projectiles.Types.bullet_15mm_projectile)
|
||||
|
||||
val bullet_20mm_apc_projectile = ProjectileDefinition(Projectiles.bullet_20mm_apc_projectile)
|
||||
val bullet_20mm_apc_projectile = ProjectileDefinition(Projectiles.Types.bullet_20mm_apc_projectile)
|
||||
|
||||
val bullet_20mm_projectile = ProjectileDefinition(Projectiles.bullet_20mm_projectile)
|
||||
val bullet_20mm_projectile = ProjectileDefinition(Projectiles.Types.bullet_20mm_projectile)
|
||||
|
||||
val bullet_25mm_projectile = ProjectileDefinition(Projectiles.bullet_25mm_projectile)
|
||||
val bullet_25mm_projectile = ProjectileDefinition(Projectiles.Types.bullet_25mm_projectile)
|
||||
|
||||
val bullet_35mm_projectile = ProjectileDefinition(Projectiles.bullet_35mm_projectile)
|
||||
val bullet_35mm_projectile = ProjectileDefinition(Projectiles.Types.bullet_35mm_projectile)
|
||||
|
||||
val bullet_75mm_apc_projectile = ProjectileDefinition(Projectiles.bullet_75mm_apc_projectile)
|
||||
val bullet_75mm_apc_projectile = ProjectileDefinition(Projectiles.Types.bullet_75mm_apc_projectile)
|
||||
|
||||
val bullet_75mm_projectile = ProjectileDefinition(Projectiles.bullet_75mm_projectile)
|
||||
val bullet_75mm_projectile = ProjectileDefinition(Projectiles.Types.bullet_75mm_projectile)
|
||||
|
||||
val bullet_9mm_AP_projectile = ProjectileDefinition(Projectiles.bullet_9mm_AP_projectile)
|
||||
val bullet_9mm_AP_projectile = ProjectileDefinition(Projectiles.Types.bullet_9mm_AP_projectile)
|
||||
|
||||
val bullet_9mm_projectile = ProjectileDefinition(Projectiles.bullet_9mm_projectile)
|
||||
val bullet_9mm_projectile = ProjectileDefinition(Projectiles.Types.bullet_9mm_projectile)
|
||||
|
||||
val anniversary_projectilea = ProjectileDefinition(Projectiles.anniversary_projectilea)
|
||||
val anniversary_projectilea = ProjectileDefinition(Projectiles.Types.anniversary_projectilea)
|
||||
|
||||
val anniversary_projectileb = ProjectileDefinition(Projectiles.anniversary_projectileb)
|
||||
val anniversary_projectileb = ProjectileDefinition(Projectiles.Types.anniversary_projectileb)
|
||||
|
||||
val aphelion_immolation_cannon_projectile = ProjectileDefinition(Projectiles.aphelion_immolation_cannon_projectile)
|
||||
val aphelion_immolation_cannon_projectile = ProjectileDefinition(Projectiles.Types.aphelion_immolation_cannon_projectile)
|
||||
|
||||
val aphelion_laser_projectile = ProjectileDefinition(Projectiles.aphelion_laser_projectile)
|
||||
val aphelion_laser_projectile = ProjectileDefinition(Projectiles.Types.aphelion_laser_projectile)
|
||||
|
||||
val aphelion_plasma_cloud = ProjectileDefinition(Projectiles.aphelion_plasma_cloud)
|
||||
val aphelion_plasma_cloud = ProjectileDefinition(Projectiles.Types.aphelion_plasma_cloud)
|
||||
|
||||
val aphelion_plasma_rocket_projectile = ProjectileDefinition(Projectiles.aphelion_plasma_rocket_projectile)
|
||||
val aphelion_plasma_rocket_projectile = ProjectileDefinition(Projectiles.Types.aphelion_plasma_rocket_projectile)
|
||||
|
||||
val aphelion_ppa_projectile = ProjectileDefinition(Projectiles.aphelion_ppa_projectile)
|
||||
val aphelion_ppa_projectile = ProjectileDefinition(Projectiles.Types.aphelion_ppa_projectile)
|
||||
|
||||
val aphelion_starfire_projectile = ProjectileDefinition(Projectiles.aphelion_starfire_projectile)
|
||||
val aphelion_starfire_projectile = ProjectileDefinition(Projectiles.Types.aphelion_starfire_projectile)
|
||||
|
||||
val bolt_projectile = ProjectileDefinition(Projectiles.bolt_projectile)
|
||||
val bolt_projectile = ProjectileDefinition(Projectiles.Types.bolt_projectile)
|
||||
|
||||
val burster_projectile = ProjectileDefinition(Projectiles.burster_projectile)
|
||||
val burster_projectile = ProjectileDefinition(Projectiles.Types.burster_projectile)
|
||||
|
||||
val chainblade_projectile = ProjectileDefinition(Projectiles.chainblade_projectile)
|
||||
val chainblade_projectile = ProjectileDefinition(Projectiles.Types.chainblade_projectile)
|
||||
|
||||
val colossus_100mm_projectile = ProjectileDefinition(Projectiles.colossus_100mm_projectile)
|
||||
val colossus_100mm_projectile = ProjectileDefinition(Projectiles.Types.colossus_100mm_projectile)
|
||||
|
||||
val colossus_burster_projectile = ProjectileDefinition(Projectiles.colossus_burster_projectile)
|
||||
val colossus_burster_projectile = ProjectileDefinition(Projectiles.Types.colossus_burster_projectile)
|
||||
|
||||
val colossus_chaingun_projectile = ProjectileDefinition(Projectiles.colossus_chaingun_projectile)
|
||||
val colossus_chaingun_projectile = ProjectileDefinition(Projectiles.Types.colossus_chaingun_projectile)
|
||||
|
||||
val colossus_cluster_bomb_projectile = ProjectileDefinition(Projectiles.colossus_cluster_bomb_projectile)
|
||||
val colossus_cluster_bomb_projectile = ProjectileDefinition(Projectiles.Types.colossus_cluster_bomb_projectile)
|
||||
|
||||
val colossus_tank_cannon_projectile = ProjectileDefinition(Projectiles.colossus_tank_cannon_projectile)
|
||||
val colossus_tank_cannon_projectile = ProjectileDefinition(Projectiles.Types.colossus_tank_cannon_projectile)
|
||||
|
||||
val comet_projectile = ProjectileDefinition(Projectiles.comet_projectile)
|
||||
val comet_projectile = ProjectileDefinition(Projectiles.Types.comet_projectile)
|
||||
|
||||
val dualcycler_projectile = ProjectileDefinition(Projectiles.dualcycler_projectile)
|
||||
val dualcycler_projectile = ProjectileDefinition(Projectiles.Types.dualcycler_projectile)
|
||||
|
||||
val dynomite_projectile = ProjectileDefinition(Projectiles.dynomite_projectile)
|
||||
val dynomite_projectile = ProjectileDefinition(Projectiles.Types.dynomite_projectile)
|
||||
|
||||
val energy_cell_projectile = ProjectileDefinition(Projectiles.energy_cell_projectile)
|
||||
val energy_cell_projectile = ProjectileDefinition(Projectiles.Types.energy_cell_projectile)
|
||||
|
||||
val energy_gun_nc_projectile = ProjectileDefinition(Projectiles.energy_gun_nc_projectile)
|
||||
val energy_gun_nc_projectile = ProjectileDefinition(Projectiles.Types.energy_gun_nc_projectile)
|
||||
|
||||
val energy_gun_tr_projectile = ProjectileDefinition(Projectiles.energy_gun_tr_projectile)
|
||||
val energy_gun_tr_projectile = ProjectileDefinition(Projectiles.Types.energy_gun_tr_projectile)
|
||||
|
||||
val energy_gun_vs_projectile = ProjectileDefinition(Projectiles.energy_gun_vs_projectile)
|
||||
val energy_gun_vs_projectile = ProjectileDefinition(Projectiles.Types.energy_gun_vs_projectile)
|
||||
|
||||
val enhanced_energy_cell_projectile = ProjectileDefinition(Projectiles.enhanced_energy_cell_projectile)
|
||||
val enhanced_energy_cell_projectile = ProjectileDefinition(Projectiles.Types.enhanced_energy_cell_projectile)
|
||||
|
||||
val enhanced_quasar_projectile = ProjectileDefinition(Projectiles.enhanced_quasar_projectile)
|
||||
val enhanced_quasar_projectile = ProjectileDefinition(Projectiles.Types.enhanced_quasar_projectile)
|
||||
|
||||
val falcon_projectile = ProjectileDefinition(Projectiles.falcon_projectile)
|
||||
val falcon_projectile = ProjectileDefinition(Projectiles.Types.falcon_projectile)
|
||||
|
||||
val firebird_missile_projectile = ProjectileDefinition(Projectiles.firebird_missile_projectile)
|
||||
val firebird_missile_projectile = ProjectileDefinition(Projectiles.Types.firebird_missile_projectile)
|
||||
|
||||
val flail_projectile = ProjectileDefinition(Projectiles.flail_projectile)
|
||||
val flail_projectile = ProjectileDefinition(Projectiles.Types.flail_projectile)
|
||||
|
||||
val flamethrower_fire_cloud = ProjectileDefinition(Projectiles.flamethrower_fire_cloud)
|
||||
val flamethrower_fire_cloud = ProjectileDefinition(Projectiles.Types.flamethrower_fire_cloud)
|
||||
|
||||
val flamethrower_fireball = ProjectileDefinition(Projectiles.flamethrower_fireball)
|
||||
val flamethrower_fireball = ProjectileDefinition(Projectiles.Types.flamethrower_fireball)
|
||||
|
||||
val flamethrower_projectile = ProjectileDefinition(Projectiles.flamethrower_projectile)
|
||||
val flamethrower_projectile = ProjectileDefinition(Projectiles.Types.flamethrower_projectile)
|
||||
|
||||
val flux_cannon_apc_projectile = ProjectileDefinition(Projectiles.flux_cannon_apc_projectile)
|
||||
val flux_cannon_apc_projectile = ProjectileDefinition(Projectiles.Types.flux_cannon_apc_projectile)
|
||||
|
||||
val flux_cannon_thresher_projectile = ProjectileDefinition(Projectiles.flux_cannon_thresher_projectile)
|
||||
val flux_cannon_thresher_projectile = ProjectileDefinition(Projectiles.Types.flux_cannon_thresher_projectile)
|
||||
|
||||
val fluxpod_projectile = ProjectileDefinition(Projectiles.fluxpod_projectile)
|
||||
val fluxpod_projectile = ProjectileDefinition(Projectiles.Types.fluxpod_projectile)
|
||||
|
||||
val forceblade_projectile = ProjectileDefinition(Projectiles.forceblade_projectile)
|
||||
val forceblade_projectile = ProjectileDefinition(Projectiles.Types.forceblade_projectile)
|
||||
|
||||
val frag_cartridge_projectile = ProjectileDefinition(Projectiles.frag_cartridge_projectile)
|
||||
val frag_cartridge_projectile = ProjectileDefinition(Projectiles.Types.frag_cartridge_projectile)
|
||||
|
||||
val frag_cartridge_projectile_b = ProjectileDefinition(Projectiles.frag_cartridge_projectile_b)
|
||||
val frag_cartridge_projectile_b = ProjectileDefinition(Projectiles.Types.frag_cartridge_projectile_b)
|
||||
|
||||
val frag_grenade_projectile = ProjectileDefinition(Projectiles.frag_grenade_projectile)
|
||||
val frag_grenade_projectile = ProjectileDefinition(Projectiles.Types.frag_grenade_projectile)
|
||||
|
||||
val frag_grenade_projectile_enh = ProjectileDefinition(Projectiles.frag_grenade_projectile_enh)
|
||||
val frag_grenade_projectile_enh = ProjectileDefinition(Projectiles.Types.frag_grenade_projectile_enh)
|
||||
|
||||
val galaxy_gunship_gun_projectile = ProjectileDefinition(Projectiles.galaxy_gunship_gun_projectile)
|
||||
val galaxy_gunship_gun_projectile = ProjectileDefinition(Projectiles.Types.galaxy_gunship_gun_projectile)
|
||||
|
||||
val gauss_cannon_projectile = ProjectileDefinition(Projectiles.gauss_cannon_projectile)
|
||||
val gauss_cannon_projectile = ProjectileDefinition(Projectiles.Types.gauss_cannon_projectile)
|
||||
|
||||
val grenade_projectile = ProjectileDefinition(Projectiles.grenade_projectile)
|
||||
val grenade_projectile = ProjectileDefinition(Projectiles.Types.grenade_projectile)
|
||||
|
||||
val heavy_grenade_projectile = ProjectileDefinition(Projectiles.heavy_grenade_projectile)
|
||||
val heavy_grenade_projectile = ProjectileDefinition(Projectiles.Types.heavy_grenade_projectile)
|
||||
|
||||
val heavy_rail_beam_projectile = ProjectileDefinition(Projectiles.heavy_rail_beam_projectile)
|
||||
val heavy_rail_beam_projectile = ProjectileDefinition(Projectiles.Types.heavy_rail_beam_projectile)
|
||||
|
||||
val heavy_sniper_projectile = ProjectileDefinition(Projectiles.heavy_sniper_projectile)
|
||||
val heavy_sniper_projectile = ProjectileDefinition(Projectiles.Types.heavy_sniper_projectile)
|
||||
|
||||
val hellfire_projectile = ProjectileDefinition(Projectiles.hellfire_projectile)
|
||||
val hellfire_projectile = ProjectileDefinition(Projectiles.Types.hellfire_projectile)
|
||||
|
||||
val hunter_seeker_missile_dumbfire = ProjectileDefinition(Projectiles.hunter_seeker_missile_dumbfire)
|
||||
val hunter_seeker_missile_dumbfire = ProjectileDefinition(Projectiles.Types.hunter_seeker_missile_dumbfire)
|
||||
|
||||
val hunter_seeker_missile_projectile = ProjectileDefinition(Projectiles.hunter_seeker_missile_projectile)
|
||||
val hunter_seeker_missile_projectile = ProjectileDefinition(Projectiles.Types.hunter_seeker_missile_projectile)
|
||||
|
||||
val jammer_cartridge_projectile = ProjectileDefinition(Projectiles.jammer_cartridge_projectile)
|
||||
val jammer_cartridge_projectile = ProjectileDefinition(Projectiles.Types.jammer_cartridge_projectile)
|
||||
|
||||
val jammer_cartridge_projectile_b = ProjectileDefinition(Projectiles.jammer_cartridge_projectile_b)
|
||||
val jammer_cartridge_projectile_b = ProjectileDefinition(Projectiles.Types.jammer_cartridge_projectile_b)
|
||||
|
||||
val jammer_grenade_projectile = ProjectileDefinition(Projectiles.jammer_grenade_projectile)
|
||||
val jammer_grenade_projectile = ProjectileDefinition(Projectiles.Types.jammer_grenade_projectile)
|
||||
|
||||
val jammer_grenade_projectile_enh = ProjectileDefinition(Projectiles.jammer_grenade_projectile_enh)
|
||||
val jammer_grenade_projectile_enh = ProjectileDefinition(Projectiles.Types.jammer_grenade_projectile_enh)
|
||||
|
||||
val katana_projectile = ProjectileDefinition(Projectiles.katana_projectile)
|
||||
val katana_projectile = ProjectileDefinition(Projectiles.Types.katana_projectile)
|
||||
|
||||
val katana_projectileb = ProjectileDefinition(Projectiles.katana_projectileb)
|
||||
val katana_projectileb = ProjectileDefinition(Projectiles.Types.katana_projectileb)
|
||||
|
||||
val lancer_projectile = ProjectileDefinition(Projectiles.lancer_projectile)
|
||||
val lancer_projectile = ProjectileDefinition(Projectiles.Types.lancer_projectile)
|
||||
|
||||
val lasher_projectile = ProjectileDefinition(Projectiles.lasher_projectile)
|
||||
val lasher_projectile = ProjectileDefinition(Projectiles.Types.lasher_projectile)
|
||||
|
||||
val lasher_projectile_ap = ProjectileDefinition(Projectiles.lasher_projectile_ap)
|
||||
val lasher_projectile_ap = ProjectileDefinition(Projectiles.Types.lasher_projectile_ap)
|
||||
|
||||
val liberator_bomb_cluster_bomblet_projectile = ProjectileDefinition(
|
||||
Projectiles.liberator_bomb_cluster_bomblet_projectile
|
||||
Projectiles.Types.liberator_bomb_cluster_bomblet_projectile
|
||||
)
|
||||
|
||||
val liberator_bomb_cluster_projectile = ProjectileDefinition(Projectiles.liberator_bomb_cluster_projectile)
|
||||
val liberator_bomb_cluster_projectile = ProjectileDefinition(Projectiles.Types.liberator_bomb_cluster_projectile)
|
||||
|
||||
val liberator_bomb_projectile = ProjectileDefinition(Projectiles.liberator_bomb_projectile)
|
||||
val liberator_bomb_projectile = ProjectileDefinition(Projectiles.Types.liberator_bomb_projectile)
|
||||
|
||||
val maelstrom_grenade_damager = ProjectileDefinition(Projectiles.maelstrom_grenade_damager)
|
||||
val maelstrom_grenade_damager = ProjectileDefinition(Projectiles.Types.maelstrom_grenade_damager)
|
||||
|
||||
val maelstrom_grenade_projectile = ProjectileDefinition(Projectiles.maelstrom_grenade_projectile)
|
||||
val maelstrom_grenade_projectile = ProjectileDefinition(Projectiles.Types.maelstrom_grenade_projectile)
|
||||
|
||||
val maelstrom_grenade_projectile_contact = ProjectileDefinition(Projectiles.maelstrom_grenade_projectile_contact)
|
||||
val maelstrom_grenade_projectile_contact = ProjectileDefinition(Projectiles.Types.maelstrom_grenade_projectile_contact)
|
||||
|
||||
val maelstrom_stream_projectile = ProjectileDefinition(Projectiles.maelstrom_stream_projectile)
|
||||
val maelstrom_stream_projectile = ProjectileDefinition(Projectiles.Types.maelstrom_stream_projectile)
|
||||
|
||||
val magcutter_projectile = ProjectileDefinition(Projectiles.magcutter_projectile)
|
||||
val magcutter_projectile = ProjectileDefinition(Projectiles.Types.magcutter_projectile)
|
||||
|
||||
val melee_ammo_projectile = ProjectileDefinition(Projectiles.melee_ammo_projectile)
|
||||
val melee_ammo_projectile = ProjectileDefinition(Projectiles.Types.melee_ammo_projectile)
|
||||
|
||||
val meteor_common = ProjectileDefinition(Projectiles.meteor_common)
|
||||
val meteor_common = ProjectileDefinition(Projectiles.Types.meteor_common)
|
||||
|
||||
val meteor_projectile_b_large = ProjectileDefinition(Projectiles.meteor_projectile_b_large)
|
||||
val meteor_projectile_b_large = ProjectileDefinition(Projectiles.Types.meteor_projectile_b_large)
|
||||
|
||||
val meteor_projectile_b_medium = ProjectileDefinition(Projectiles.meteor_projectile_b_medium)
|
||||
val meteor_projectile_b_medium = ProjectileDefinition(Projectiles.Types.meteor_projectile_b_medium)
|
||||
|
||||
val meteor_projectile_b_small = ProjectileDefinition(Projectiles.meteor_projectile_b_small)
|
||||
val meteor_projectile_b_small = ProjectileDefinition(Projectiles.Types.meteor_projectile_b_small)
|
||||
|
||||
val meteor_projectile_large = ProjectileDefinition(Projectiles.meteor_projectile_large)
|
||||
val meteor_projectile_large = ProjectileDefinition(Projectiles.Types.meteor_projectile_large)
|
||||
|
||||
val meteor_projectile_medium = ProjectileDefinition(Projectiles.meteor_projectile_medium)
|
||||
val meteor_projectile_medium = ProjectileDefinition(Projectiles.Types.meteor_projectile_medium)
|
||||
|
||||
val meteor_projectile_small = ProjectileDefinition(Projectiles.meteor_projectile_small)
|
||||
val meteor_projectile_small = ProjectileDefinition(Projectiles.Types.meteor_projectile_small)
|
||||
|
||||
val mine_projectile = ProjectileDefinition(Projectiles.mine_projectile)
|
||||
val mine_projectile = ProjectileDefinition(Projectiles.Types.mine_projectile)
|
||||
|
||||
val mine_sweeper_projectile = ProjectileDefinition(Projectiles.mine_sweeper_projectile)
|
||||
val mine_sweeper_projectile = ProjectileDefinition(Projectiles.Types.mine_sweeper_projectile)
|
||||
|
||||
val mine_sweeper_projectile_enh = ProjectileDefinition(Projectiles.mine_sweeper_projectile_enh)
|
||||
val mine_sweeper_projectile_enh = ProjectileDefinition(Projectiles.Types.mine_sweeper_projectile_enh)
|
||||
|
||||
val oicw_projectile = ProjectileDefinition(Projectiles.oicw_projectile)
|
||||
val oicw_projectile = ProjectileDefinition(Projectiles.Types.oicw_projectile)
|
||||
|
||||
val oicw_little_buddy = ProjectileDefinition(Projectiles.oicw_little_buddy)
|
||||
val oicw_little_buddy = ProjectileDefinition(Projectiles.Types.oicw_little_buddy)
|
||||
|
||||
val pellet_gun_projectile = ProjectileDefinition(Projectiles.pellet_gun_projectile)
|
||||
val pellet_gun_projectile = ProjectileDefinition(Projectiles.Types.pellet_gun_projectile)
|
||||
|
||||
val peregrine_dual_machine_gun_projectile = ProjectileDefinition(Projectiles.peregrine_dual_machine_gun_projectile)
|
||||
val peregrine_dual_machine_gun_projectile = ProjectileDefinition(Projectiles.Types.peregrine_dual_machine_gun_projectile)
|
||||
|
||||
val peregrine_mechhammer_projectile = ProjectileDefinition(Projectiles.peregrine_mechhammer_projectile)
|
||||
val peregrine_mechhammer_projectile = ProjectileDefinition(Projectiles.Types.peregrine_mechhammer_projectile)
|
||||
|
||||
val peregrine_particle_cannon_projectile = ProjectileDefinition(Projectiles.peregrine_particle_cannon_projectile)
|
||||
val peregrine_particle_cannon_projectile = ProjectileDefinition(Projectiles.Types.peregrine_particle_cannon_projectile)
|
||||
|
||||
val peregrine_particle_cannon_radiation_cloud = ProjectileDefinition(Projectiles.peregrine_particle_cannon_radiation_cloud)
|
||||
val peregrine_particle_cannon_radiation_cloud = ProjectileDefinition(Projectiles.Types.peregrine_particle_cannon_radiation_cloud)
|
||||
|
||||
val peregrine_rocket_pod_projectile = ProjectileDefinition(Projectiles.peregrine_rocket_pod_projectile)
|
||||
val peregrine_rocket_pod_projectile = ProjectileDefinition(Projectiles.Types.peregrine_rocket_pod_projectile)
|
||||
|
||||
val peregrine_sparrow_projectile = ProjectileDefinition(Projectiles.peregrine_sparrow_projectile)
|
||||
val peregrine_sparrow_projectile = ProjectileDefinition(Projectiles.Types.peregrine_sparrow_projectile)
|
||||
|
||||
val phalanx_av_projectile = ProjectileDefinition(Projectiles.phalanx_av_projectile)
|
||||
val phalanx_av_projectile = ProjectileDefinition(Projectiles.Types.phalanx_av_projectile)
|
||||
|
||||
val phalanx_flak_projectile = ProjectileDefinition(Projectiles.phalanx_flak_projectile)
|
||||
val phalanx_flak_projectile = ProjectileDefinition(Projectiles.Types.phalanx_flak_projectile)
|
||||
|
||||
val phalanx_projectile = ProjectileDefinition(Projectiles.phalanx_projectile)
|
||||
val phalanx_projectile = ProjectileDefinition(Projectiles.Types.phalanx_projectile)
|
||||
|
||||
val phoenix_missile_guided_projectile = ProjectileDefinition(Projectiles.phoenix_missile_guided_projectile)
|
||||
val phoenix_missile_guided_projectile = ProjectileDefinition(Projectiles.Types.phoenix_missile_guided_projectile)
|
||||
|
||||
val phoenix_missile_projectile = ProjectileDefinition(Projectiles.phoenix_missile_projectile)
|
||||
val phoenix_missile_projectile = ProjectileDefinition(Projectiles.Types.phoenix_missile_projectile)
|
||||
|
||||
val plasma_cartridge_projectile = ProjectileDefinition(Projectiles.plasma_cartridge_projectile)
|
||||
val plasma_cartridge_projectile = ProjectileDefinition(Projectiles.Types.plasma_cartridge_projectile)
|
||||
|
||||
val plasma_cartridge_projectile_b = ProjectileDefinition(Projectiles.plasma_cartridge_projectile_b)
|
||||
val plasma_cartridge_projectile_b = ProjectileDefinition(Projectiles.Types.plasma_cartridge_projectile_b)
|
||||
|
||||
val plasma_grenade_projectile = ProjectileDefinition(Projectiles.plasma_grenade_projectile)
|
||||
val plasma_grenade_projectile = ProjectileDefinition(Projectiles.Types.plasma_grenade_projectile)
|
||||
|
||||
val plasma_grenade_projectile_B = ProjectileDefinition(Projectiles.plasma_grenade_projectile_B)
|
||||
val plasma_grenade_projectile_B = ProjectileDefinition(Projectiles.Types.plasma_grenade_projectile_B)
|
||||
|
||||
val pounder_projectile = ProjectileDefinition(Projectiles.pounder_projectile)
|
||||
val pounder_projectile = ProjectileDefinition(Projectiles.Types.pounder_projectile)
|
||||
|
||||
val pounder_projectile_enh = ProjectileDefinition(Projectiles.pounder_projectile_enh)
|
||||
val pounder_projectile_enh = ProjectileDefinition(Projectiles.Types.pounder_projectile_enh)
|
||||
|
||||
val ppa_projectile = ProjectileDefinition(Projectiles.ppa_projectile)
|
||||
val ppa_projectile = ProjectileDefinition(Projectiles.Types.ppa_projectile)
|
||||
|
||||
val pulsar_ap_projectile = ProjectileDefinition(Projectiles.pulsar_ap_projectile)
|
||||
val pulsar_ap_projectile = ProjectileDefinition(Projectiles.Types.pulsar_ap_projectile)
|
||||
|
||||
val pulsar_projectile = ProjectileDefinition(Projectiles.pulsar_projectile)
|
||||
val pulsar_projectile = ProjectileDefinition(Projectiles.Types.pulsar_projectile)
|
||||
|
||||
val quasar_projectile = ProjectileDefinition(Projectiles.quasar_projectile)
|
||||
val quasar_projectile = ProjectileDefinition(Projectiles.Types.quasar_projectile)
|
||||
|
||||
val radiator_cloud = ProjectileDefinition(Projectiles.radiator_cloud)
|
||||
val radiator_cloud = ProjectileDefinition(Projectiles.Types.radiator_cloud)
|
||||
|
||||
val radiator_grenade_projectile = ProjectileDefinition(Projectiles.radiator_grenade_projectile)
|
||||
val radiator_grenade_projectile = ProjectileDefinition(Projectiles.Types.radiator_grenade_projectile)
|
||||
|
||||
val radiator_sticky_projectile = ProjectileDefinition(Projectiles.radiator_sticky_projectile)
|
||||
val radiator_sticky_projectile = ProjectileDefinition(Projectiles.Types.radiator_sticky_projectile)
|
||||
|
||||
val reaver_rocket_projectile = ProjectileDefinition(Projectiles.reaver_rocket_projectile)
|
||||
val reaver_rocket_projectile = ProjectileDefinition(Projectiles.Types.reaver_rocket_projectile)
|
||||
|
||||
val rocket_projectile = ProjectileDefinition(Projectiles.rocket_projectile)
|
||||
val rocket_projectile = ProjectileDefinition(Projectiles.Types.rocket_projectile)
|
||||
|
||||
val rocklet_flak_projectile = ProjectileDefinition(Projectiles.rocklet_flak_projectile)
|
||||
val rocklet_flak_projectile = ProjectileDefinition(Projectiles.Types.rocklet_flak_projectile)
|
||||
|
||||
val rocklet_jammer_projectile = ProjectileDefinition(Projectiles.rocklet_jammer_projectile)
|
||||
val rocklet_jammer_projectile = ProjectileDefinition(Projectiles.Types.rocklet_jammer_projectile)
|
||||
|
||||
val scattercannon_projectile = ProjectileDefinition(Projectiles.scattercannon_projectile)
|
||||
val scattercannon_projectile = ProjectileDefinition(Projectiles.Types.scattercannon_projectile)
|
||||
|
||||
val scythe_projectile = ProjectileDefinition(Projectiles.scythe_projectile)
|
||||
val scythe_projectile = ProjectileDefinition(Projectiles.Types.scythe_projectile)
|
||||
|
||||
val scythe_projectile_slave = ProjectileDefinition(Projectiles.scythe_projectile_slave)
|
||||
val scythe_projectile_slave = ProjectileDefinition(Projectiles.Types.scythe_projectile_slave)
|
||||
|
||||
val shotgun_shell_AP_projectile = ProjectileDefinition(Projectiles.shotgun_shell_AP_projectile)
|
||||
val shotgun_shell_AP_projectile = ProjectileDefinition(Projectiles.Types.shotgun_shell_AP_projectile)
|
||||
|
||||
val shotgun_shell_projectile = ProjectileDefinition(Projectiles.shotgun_shell_projectile)
|
||||
val shotgun_shell_projectile = ProjectileDefinition(Projectiles.Types.shotgun_shell_projectile)
|
||||
|
||||
val six_shooter_projectile = ProjectileDefinition(Projectiles.six_shooter_projectile)
|
||||
val six_shooter_projectile = ProjectileDefinition(Projectiles.Types.six_shooter_projectile)
|
||||
|
||||
val skyguard_flak_cannon_projectile = ProjectileDefinition(Projectiles.skyguard_flak_cannon_projectile)
|
||||
val skyguard_flak_cannon_projectile = ProjectileDefinition(Projectiles.Types.skyguard_flak_cannon_projectile)
|
||||
|
||||
val sparrow_projectile = ProjectileDefinition(Projectiles.sparrow_projectile)
|
||||
val sparrow_projectile = ProjectileDefinition(Projectiles.Types.sparrow_projectile)
|
||||
|
||||
val sparrow_secondary_projectile = ProjectileDefinition(Projectiles.sparrow_secondary_projectile)
|
||||
val sparrow_secondary_projectile = ProjectileDefinition(Projectiles.Types.sparrow_secondary_projectile)
|
||||
|
||||
val spiker_projectile = ProjectileDefinition(Projectiles.spiker_projectile)
|
||||
val spiker_projectile = ProjectileDefinition(Projectiles.Types.spiker_projectile)
|
||||
|
||||
val spitfire_aa_ammo_projectile = ProjectileDefinition(Projectiles.spitfire_aa_ammo_projectile)
|
||||
val spitfire_aa_ammo_projectile = ProjectileDefinition(Projectiles.Types.spitfire_aa_ammo_projectile)
|
||||
|
||||
val spitfire_ammo_projectile = ProjectileDefinition(Projectiles.spitfire_ammo_projectile)
|
||||
val spitfire_ammo_projectile = ProjectileDefinition(Projectiles.Types.spitfire_ammo_projectile)
|
||||
|
||||
val starfire_projectile = ProjectileDefinition(Projectiles.starfire_projectile)
|
||||
val starfire_projectile = ProjectileDefinition(Projectiles.Types.starfire_projectile)
|
||||
|
||||
val striker_missile_projectile = ProjectileDefinition(Projectiles.striker_missile_projectile)
|
||||
val striker_missile_projectile = ProjectileDefinition(Projectiles.Types.striker_missile_projectile)
|
||||
|
||||
val striker_missile_targeting_projectile = ProjectileDefinition(Projectiles.striker_missile_targeting_projectile)
|
||||
val striker_missile_targeting_projectile = ProjectileDefinition(Projectiles.Types.striker_missile_targeting_projectile)
|
||||
|
||||
val trek_projectile = ProjectileDefinition(Projectiles.trek_projectile)
|
||||
val trek_projectile = ProjectileDefinition(Projectiles.Types.trek_projectile)
|
||||
|
||||
val vanu_sentry_turret_projectile = ProjectileDefinition(Projectiles.vanu_sentry_turret_projectile)
|
||||
val vanu_sentry_turret_projectile = ProjectileDefinition(Projectiles.Types.vanu_sentry_turret_projectile)
|
||||
|
||||
val vulture_bomb_projectile = ProjectileDefinition(Projectiles.vulture_bomb_projectile)
|
||||
val vulture_bomb_projectile = ProjectileDefinition(Projectiles.Types.vulture_bomb_projectile)
|
||||
|
||||
val vulture_nose_bullet_projectile = ProjectileDefinition(Projectiles.vulture_nose_bullet_projectile)
|
||||
val vulture_nose_bullet_projectile = ProjectileDefinition(Projectiles.Types.vulture_nose_bullet_projectile)
|
||||
|
||||
val vulture_tail_bullet_projectile = ProjectileDefinition(Projectiles.vulture_tail_bullet_projectile)
|
||||
val vulture_tail_bullet_projectile = ProjectileDefinition(Projectiles.Types.vulture_tail_bullet_projectile)
|
||||
|
||||
val wasp_gun_projectile = ProjectileDefinition(Projectiles.wasp_gun_projectile)
|
||||
val wasp_gun_projectile = ProjectileDefinition(Projectiles.Types.wasp_gun_projectile)
|
||||
|
||||
val wasp_rocket_projectile = ProjectileDefinition(Projectiles.wasp_rocket_projectile)
|
||||
val wasp_rocket_projectile = ProjectileDefinition(Projectiles.Types.wasp_rocket_projectile)
|
||||
|
||||
val winchester_projectile = ProjectileDefinition(Projectiles.winchester_projectile)
|
||||
val winchester_projectile = ProjectileDefinition(Projectiles.Types.winchester_projectile)
|
||||
|
||||
val armor_siphon_projectile = ProjectileDefinition(Projectiles.trek_projectile) //fake projectile for storing damage information
|
||||
val armor_siphon_projectile = ProjectileDefinition(Projectiles.Types.trek_projectile) //fake projectile for storing damage information
|
||||
|
||||
val ntu_siphon_emp = ProjectileDefinition(Projectiles.ntu_siphon_emp)
|
||||
val ntu_siphon_emp = ProjectileDefinition(Projectiles.Types.ntu_siphon_emp)
|
||||
init_projectile()
|
||||
|
||||
/*
|
||||
|
|
@ -1180,7 +1180,9 @@ object GlobalDefinitions {
|
|||
|
||||
val repair_silo = new MedicalTerminalDefinition(729)
|
||||
|
||||
val recharge_terminal = new MedicalTerminalDefinition(724)
|
||||
val recharge_terminal = new WeaponRechargeTerminalDefinition(724)
|
||||
|
||||
val recharge_terminal_weapon_module = new WeaponRechargeTerminalDefinition(725)
|
||||
|
||||
val mb_pad_creation = new VehicleSpawnPadDefinition(525)
|
||||
|
||||
|
|
@ -1975,28 +1977,31 @@ object GlobalDefinitions {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a projectile that is the damage proxy of another projectile,
|
||||
* Return projectiles that are the damage proxies of another projectile,
|
||||
* if such a damage proxy is defined in the appropriate field by its unique object identifier.
|
||||
* @see `ProjectileDefinition.DamageProxy`
|
||||
* @param projectile the original projectile
|
||||
* @return the damage proxy projectile definition, if that can be produced
|
||||
* @return the damage proxy projectiles, if they can be produced
|
||||
*/
|
||||
def getDamageProxy(projectile: Projectile, hitPosition: Vector3): Option[Projectile] = {
|
||||
projectile.Definition.DamageProxy match {
|
||||
case Some(uoid) =>
|
||||
def getDamageProxy(projectile: Projectile, hitPosition: Vector3): List[Projectile] = {
|
||||
projectile
|
||||
.Definition
|
||||
.DamageProxy
|
||||
.flatMap { uoid =>
|
||||
((uoid: @switch) match {
|
||||
case 96 => Some(aphelion_plasma_cloud)
|
||||
case 301 => Some(projectile.profile) //'flamethrower_fire_cloud' can not be made into a packet
|
||||
case 464 => Some(projectile.profile) //'maelstrom_grenade_damager' can not be made into a packet
|
||||
case 601 => Some(oicw_little_buddy)
|
||||
case 655 => Some(peregrine_particle_cannon_radiation_cloud)
|
||||
case 717 => Some(radiator_cloud)
|
||||
case _ => None
|
||||
}) match {
|
||||
case Some(proxy)
|
||||
if proxy eq projectile.profile =>
|
||||
Some(projectile)
|
||||
List(projectile)
|
||||
case Some(proxy) =>
|
||||
Some(Projectile(
|
||||
List(Projectile(
|
||||
proxy,
|
||||
projectile.tool_def,
|
||||
projectile.fire_mode,
|
||||
|
|
@ -2006,11 +2011,9 @@ object GlobalDefinitions {
|
|||
Vector3.Zero
|
||||
))
|
||||
case None =>
|
||||
None
|
||||
Nil
|
||||
}
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3638,12 +3641,16 @@ object GlobalDefinitions {
|
|||
oicw_projectile.ProjectileDamageType = DamageType.Splash
|
||||
oicw_projectile.InitialVelocity = 5
|
||||
oicw_projectile.Lifespan = 6.1f
|
||||
oicw_projectile.DamageProxy = List(601, 601, 601, 601, 601) //5 x oicw_little_buddy
|
||||
oicw_projectile.registerAs = "rc-projectiles"
|
||||
oicw_projectile.ExistsOnRemoteClients = true
|
||||
oicw_projectile.RemoteClientData = (13107, 195)
|
||||
oicw_projectile.Packet = projectileConverter
|
||||
ProjectileDefinition.CalculateDerivedFields(oicw_projectile)
|
||||
oicw_projectile.Modifiers = RadialDegrade
|
||||
oicw_projectile.Modifiers = List(
|
||||
//ExplodingRadialDegrade,
|
||||
RadialDegrade
|
||||
)
|
||||
|
||||
oicw_little_buddy.Name = "oicw_little_buddy"
|
||||
oicw_little_buddy.Damage0 = 75
|
||||
|
|
@ -3653,11 +3660,14 @@ object GlobalDefinitions {
|
|||
oicw_little_buddy.ProjectileDamageType = DamageType.Splash
|
||||
oicw_little_buddy.InitialVelocity = 40
|
||||
oicw_little_buddy.Lifespan = 0.5f
|
||||
oicw_little_buddy.ExistsOnRemoteClients = false //TODO true
|
||||
oicw_little_buddy.Packet = projectileConverter
|
||||
oicw_little_buddy.registerAs = "rc-projectiles"
|
||||
oicw_little_buddy.ExistsOnRemoteClients = true //does not use RemoteClientData
|
||||
oicw_little_buddy.Packet = new LittleBuddyProjectileConverter
|
||||
//add_property oicw_little_buddy multi_stage_spawn_server_side true ...
|
||||
ProjectileDefinition.CalculateDerivedFields(oicw_little_buddy)
|
||||
oicw_little_buddy.Modifiers = RadialDegrade
|
||||
oicw_little_buddy.Modifiers = List(
|
||||
ExplosionDamagesOnlyAbove
|
||||
)
|
||||
|
||||
pellet_gun_projectile.Name = "pellet_gun_projectile"
|
||||
// TODO for later, maybe : set_resource_parent pellet_gun_projectile game_objects shotgun_shell_projectile
|
||||
|
|
@ -3943,16 +3953,29 @@ object GlobalDefinitions {
|
|||
radiator_cloud.Damage0 = 2
|
||||
radiator_cloud.DamageAtEdge = 1.0f
|
||||
radiator_cloud.DamageRadius = 5f
|
||||
radiator_cloud.DamageToHealthOnly = true
|
||||
radiator_cloud.radiation_cloud = true
|
||||
radiator_cloud.ProjectileDamageType = DamageType.Radiation
|
||||
//custom aggravated information
|
||||
radiator_cloud.ProjectileDamageTypeSecondary = DamageType.Aggravated
|
||||
radiator_cloud.Aggravated = AggravatedDamage(
|
||||
AggravatedInfo(DamageType.Splash, 1f, 80),
|
||||
Aura.None,
|
||||
AggravatedTiming(250, 2),
|
||||
0f,
|
||||
false,
|
||||
List(TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player))
|
||||
)
|
||||
radiator_cloud.Lifespan = 10.0f
|
||||
ProjectileDefinition.CalculateDerivedFields(radiator_cloud)
|
||||
radiator_cloud.registerAs = "rc-projectiles"
|
||||
radiator_cloud.ExistsOnRemoteClients = true
|
||||
radiator_cloud.Packet = radCloudConverter
|
||||
radiator_cloud.Geometry = GeometryForm.representProjectileBySphere()
|
||||
//radiator_cloud.Geometry = GeometryForm.representProjectileBySphere()
|
||||
radiator_cloud.Modifiers = List(
|
||||
MaxDistanceCutoff,
|
||||
InfantryAggravatedRadiation,
|
||||
InfantryAggravatedRadiationBurn,
|
||||
ShieldAgainstRadiation
|
||||
)
|
||||
|
||||
|
|
@ -3961,6 +3984,7 @@ object GlobalDefinitions {
|
|||
radiator_grenade_projectile.ProjectileDamageType = DamageType.Direct
|
||||
radiator_grenade_projectile.InitialVelocity = 30
|
||||
radiator_grenade_projectile.Lifespan = 3f
|
||||
radiator_grenade_projectile.DamageProxy = 717 //radiator_cloud
|
||||
ProjectileDefinition.CalculateDerivedFields(radiator_grenade_projectile)
|
||||
|
||||
radiator_sticky_projectile.Name = "radiator_sticky_projectile"
|
||||
|
|
@ -3969,6 +3993,7 @@ object GlobalDefinitions {
|
|||
radiator_sticky_projectile.ProjectileDamageType = DamageType.Direct
|
||||
radiator_sticky_projectile.InitialVelocity = 30
|
||||
radiator_sticky_projectile.Lifespan = 4f
|
||||
radiator_sticky_projectile.DamageProxy = 717 //radiator_cloud
|
||||
ProjectileDefinition.CalculateDerivedFields(radiator_sticky_projectile)
|
||||
|
||||
reaver_rocket_projectile.Name = "reaver_rocket_projectile"
|
||||
|
|
@ -4430,7 +4455,7 @@ object GlobalDefinitions {
|
|||
aphelion_plasma_cloud.registerAs = "rc-projectiles"
|
||||
aphelion_plasma_cloud.ExistsOnRemoteClients = true
|
||||
aphelion_plasma_cloud.Packet = radCloudConverter
|
||||
aphelion_plasma_cloud.Geometry = GeometryForm.representProjectileBySphere()
|
||||
//aphelion_plasma_cloud.Geometry = GeometryForm.representProjectileBySphere()
|
||||
aphelion_plasma_cloud.Modifiers = List( //TODO placeholder values
|
||||
MaxDistanceCutoff,
|
||||
InfantryAggravatedRadiation,
|
||||
|
|
@ -4632,7 +4657,7 @@ object GlobalDefinitions {
|
|||
peregrine_particle_cannon_radiation_cloud.registerAs = "rc-projectiles"
|
||||
peregrine_particle_cannon_radiation_cloud.ExistsOnRemoteClients = true
|
||||
peregrine_particle_cannon_radiation_cloud.Packet = radCloudConverter
|
||||
peregrine_particle_cannon_radiation_cloud.Geometry = GeometryForm.representProjectileBySphere()
|
||||
//peregrine_particle_cannon_radiation_cloud.Geometry = GeometryForm.representProjectileBySphere()
|
||||
peregrine_particle_cannon_radiation_cloud.Modifiers = List(
|
||||
MaxDistanceCutoff,
|
||||
ShieldAgainstRadiation
|
||||
|
|
@ -9615,6 +9640,13 @@ object GlobalDefinitions {
|
|||
recharge_terminal.Damageable = false
|
||||
recharge_terminal.Repairable = false
|
||||
|
||||
recharge_terminal_weapon_module.Name = "recharge_terminal_weapon_module"
|
||||
recharge_terminal_weapon_module.Interval = 1000
|
||||
recharge_terminal_weapon_module.UseRadius = 300
|
||||
recharge_terminal_weapon_module.TargetValidation += EffectTarget.Category.Player -> EffectTarget.Validation.AncientWeaponRecharge
|
||||
recharge_terminal_weapon_module.Damageable = false
|
||||
recharge_terminal_weapon_module.Repairable = false
|
||||
|
||||
mb_pad_creation.Name = "mb_pad_creation"
|
||||
mb_pad_creation.Damageable = false
|
||||
mb_pad_creation.Repairable = false
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class Tool(private val toolDef: ToolDefinition)
|
|||
})
|
||||
}
|
||||
|
||||
def ProjectileType: Projectiles.Value = Projectile.ProjectileType
|
||||
def ProjectileType: Projectiles.Types.Value = Projectile.ProjectileType
|
||||
|
||||
def Magazine: Int = AmmoSlot.Magazine
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class InteractWithRadiationClouds(
|
|||
RadiationReason(
|
||||
ProjectileQuality.modifiers(projectile, DamageResolution.Radiation, t, t.Position, user),
|
||||
t.DamageModel,
|
||||
1f
|
||||
0f
|
||||
),
|
||||
position
|
||||
).calculate()
|
||||
|
|
|
|||
|
|
@ -5,151 +5,153 @@ package net.psforever.objects.ballistics
|
|||
* An `Enumeration` of all the projectile types in the game, paired with their object id as the `Value`.
|
||||
*/
|
||||
object Projectiles extends Enumeration {
|
||||
final val no_projectile = Value(0)
|
||||
object Types extends Enumeration {
|
||||
final val no_projectile = Value(0)
|
||||
|
||||
final val bullet_105mm_projectile = Value(1)
|
||||
final val bullet_12mm_projectile = Value(4)
|
||||
final val bullet_12mm_projectileb = Value(5)
|
||||
final val bullet_150mm_projectile = Value(7)
|
||||
final val bullet_15mm_apc_projectile = Value(10)
|
||||
final val bullet_15mm_projectile = Value(11)
|
||||
final val bullet_20mm_apc_projectile = Value(17)
|
||||
final val bullet_20mm_projectile = Value(18)
|
||||
final val bullet_25mm_projectile = Value(20)
|
||||
final val bullet_35mm_projectile = Value(22)
|
||||
final val bullet_75mm_apc_projectile = Value(26)
|
||||
final val bullet_75mm_projectile = Value(27)
|
||||
final val bullet_9mm_AP_projectile = Value(30)
|
||||
final val bullet_9mm_projectile = Value(31)
|
||||
final val anniversary_projectilea = Value(58)
|
||||
final val anniversary_projectileb = Value(59)
|
||||
final val aphelion_immolation_cannon_projectile = Value(87)
|
||||
final val aphelion_laser_projectile = Value(91)
|
||||
final val aphelion_plasma_cloud = Value(96) //radiation cloud
|
||||
final val aphelion_plasma_rocket_projectile = Value(99)
|
||||
final val aphelion_ppa_projectile = Value(103)
|
||||
final val aphelion_starfire_projectile = Value(108)
|
||||
final val bolt_projectile = Value(147)
|
||||
final val burster_projectile = Value(155)
|
||||
final val chainblade_projectile = Value(176)
|
||||
final val colossus_100mm_projectile = Value(181)
|
||||
final val colossus_burster_projectile = Value(188)
|
||||
final val colossus_chaingun_projectile = Value(193)
|
||||
final val colossus_cluster_bomb_projectile = Value(197)
|
||||
final val colossus_tank_cannon_projectile = Value(207)
|
||||
final val comet_projectile = Value(210)
|
||||
final val dualcycler_projectile = Value(266)
|
||||
final val dynomite_projectile = Value(268)
|
||||
final val energy_cell_projectile = Value(273)
|
||||
final val energy_gun_nc_projectile = Value(277)
|
||||
final val energy_gun_tr_projectile = Value(279)
|
||||
final val energy_gun_vs_projectile = Value(281)
|
||||
final val enhanced_energy_cell_projectile = Value(282)
|
||||
final val enhanced_quasar_projectile = Value(283)
|
||||
final val falcon_projectile = Value(286)
|
||||
final val firebird_missile_projectile = Value(288)
|
||||
final val flail_projectile = Value(296)
|
||||
final val flamethrower_fire_cloud = Value(301)
|
||||
final val flamethrower_fireball = Value(302)
|
||||
final val flamethrower_projectile = Value(303)
|
||||
final val flux_cannon_apc_projectile = Value(305)
|
||||
final val flux_cannon_thresher_projectile = Value(308)
|
||||
final val fluxpod_projectile = Value(311)
|
||||
final val forceblade_projectile = Value(325)
|
||||
final val frag_cartridge_projectile = Value(328)
|
||||
final val frag_cartridge_projectile_b = Value(329)
|
||||
final val frag_grenade_projectile = Value(332)
|
||||
final val frag_grenade_projectile_enh = Value(333)
|
||||
final val galaxy_gunship_gun_projectile = Value(341)
|
||||
final val gauss_cannon_projectile = Value(348)
|
||||
final val grenade_projectile = Value(372)
|
||||
final val heavy_grenade_projectile = Value(392)
|
||||
final val heavy_rail_beam_projectile = Value(395)
|
||||
final val heavy_sniper_projectile = Value(397)
|
||||
final val hellfire_projectile = Value(400)
|
||||
final val hunter_seeker_missile_dumbfire = Value(404)
|
||||
final val hunter_seeker_missile_projectile = Value(405)
|
||||
final val jammer_cartridge_projectile = Value(414)
|
||||
final val jammer_cartridge_projectile_b = Value(415)
|
||||
final val jammer_grenade_projectile = Value(418)
|
||||
final val jammer_grenade_projectile_enh = Value(419)
|
||||
final val katana_projectile = Value(422)
|
||||
final val katana_projectileb = Value(423)
|
||||
final val lancer_projectile = Value(427)
|
||||
final val lasher_projectile = Value(430)
|
||||
final val lasher_projectile_ap = Value(431)
|
||||
final val liberator_bomb_cluster_bomblet_projectile = Value(436)
|
||||
final val liberator_bomb_cluster_projectile = Value(437)
|
||||
final val liberator_bomb_projectile = Value(438)
|
||||
final val maelstrom_grenade_damager = Value(464)
|
||||
final val maelstrom_grenade_projectile = Value(465)
|
||||
final val maelstrom_grenade_projectile_contact = Value(466)
|
||||
final val maelstrom_stream_projectile = Value(467)
|
||||
final val magcutter_projectile = Value(469)
|
||||
final val melee_ammo_projectile = Value(541)
|
||||
final val meteor_common = Value(543)
|
||||
final val meteor_projectile_b_large = Value(544)
|
||||
final val meteor_projectile_b_medium = Value(545)
|
||||
final val meteor_projectile_b_small = Value(546)
|
||||
final val meteor_projectile_large = Value(547)
|
||||
final val meteor_projectile_medium = Value(548)
|
||||
final val meteor_projectile_small = Value(549)
|
||||
final val mine_projectile = Value(551)
|
||||
final val mine_sweeper_projectile = Value(554)
|
||||
final val mine_sweeper_projectile_enh = Value(555)
|
||||
final val ntu_siphon_emp = Value(596)
|
||||
final val oicw_little_buddy = Value(601)
|
||||
final val oicw_projectile = Value(602)
|
||||
final val pellet_gun_projectile = Value(631)
|
||||
final val peregrine_dual_machine_gun_projectile = Value(639)
|
||||
final val peregrine_mechhammer_projectile = Value(647)
|
||||
final val peregrine_particle_cannon_projectile = Value(654)
|
||||
final val peregrine_particle_cannon_radiation_cloud = Value(655) //radiation cloud
|
||||
final val peregrine_rocket_pod_projectile = Value(657)
|
||||
final val peregrine_sparrow_projectile = Value(661)
|
||||
final val phalanx_av_projectile = Value(665)
|
||||
final val phalanx_flak_projectile = Value(667)
|
||||
final val phalanx_projectile = Value(669)
|
||||
final val phoenix_missile_guided_projectile = Value(675)
|
||||
final val phoenix_missile_projectile = Value(676)
|
||||
final val plasma_cartridge_projectile = Value(678)
|
||||
final val plasma_cartridge_projectile_b = Value(679)
|
||||
final val plasma_grenade_projectile = Value(682)
|
||||
final val plasma_grenade_projectile_B = Value(683)
|
||||
final val pounder_projectile = Value(694)
|
||||
final val pounder_projectile_enh = Value(695)
|
||||
final val ppa_projectile = Value(696)
|
||||
final val pulsar_ap_projectile = Value(702)
|
||||
final val pulsar_projectile = Value(703)
|
||||
final val quasar_projectile = Value(713)
|
||||
final val radiator_cloud = Value(717) //radiation cloud
|
||||
final val radiator_grenade_projectile = Value(718)
|
||||
final val radiator_sticky_projectile = Value(719)
|
||||
final val reaver_rocket_projectile = Value(723)
|
||||
final val rocket_projectile = Value(735)
|
||||
final val rocklet_flak_projectile = Value(738)
|
||||
final val rocklet_jammer_projectile = Value(739)
|
||||
final val scattercannon_projectile = Value(746)
|
||||
final val scythe_projectile = Value(748)
|
||||
final val scythe_projectile_slave = Value(749)
|
||||
final val shotgun_shell_AP_projectile = Value(757)
|
||||
final val shotgun_shell_projectile = Value(758)
|
||||
final val six_shooter_projectile = Value(763)
|
||||
final val skyguard_flak_cannon_projectile = Value(787)
|
||||
final val sparrow_projectile = Value(792)
|
||||
final val sparrow_secondary_projectile = Value(793)
|
||||
final val spiker_projectile = Value(818)
|
||||
final val spitfire_aa_ammo_projectile = Value(821)
|
||||
final val spitfire_ammo_projectile = Value(824)
|
||||
final val starfire_projectile = Value(831)
|
||||
final val striker_missile_projectile = Value(840)
|
||||
final val striker_missile_targeting_projectile = Value(841)
|
||||
final val trek_projectile = Value(878)
|
||||
final val vanu_sentry_turret_projectile = Value(944)
|
||||
final val vulture_bomb_projectile = Value(988)
|
||||
final val vulture_nose_bullet_projectile = Value(989)
|
||||
final val vulture_tail_bullet_projectile = Value(991)
|
||||
final val wasp_gun_projectile = Value(999)
|
||||
final val wasp_rocket_projectile = Value(1001)
|
||||
final val winchester_projectile = Value(1005)
|
||||
final val bullet_105mm_projectile = Value(1)
|
||||
final val bullet_12mm_projectile = Value(4)
|
||||
final val bullet_12mm_projectileb = Value(5)
|
||||
final val bullet_150mm_projectile = Value(7)
|
||||
final val bullet_15mm_apc_projectile = Value(10)
|
||||
final val bullet_15mm_projectile = Value(11)
|
||||
final val bullet_20mm_apc_projectile = Value(17)
|
||||
final val bullet_20mm_projectile = Value(18)
|
||||
final val bullet_25mm_projectile = Value(20)
|
||||
final val bullet_35mm_projectile = Value(22)
|
||||
final val bullet_75mm_apc_projectile = Value(26)
|
||||
final val bullet_75mm_projectile = Value(27)
|
||||
final val bullet_9mm_AP_projectile = Value(30)
|
||||
final val bullet_9mm_projectile = Value(31)
|
||||
final val anniversary_projectilea = Value(58)
|
||||
final val anniversary_projectileb = Value(59)
|
||||
final val aphelion_immolation_cannon_projectile = Value(87)
|
||||
final val aphelion_laser_projectile = Value(91)
|
||||
final val aphelion_plasma_cloud = Value(96) //radiation cloud
|
||||
final val aphelion_plasma_rocket_projectile = Value(99)
|
||||
final val aphelion_ppa_projectile = Value(103)
|
||||
final val aphelion_starfire_projectile = Value(108)
|
||||
final val bolt_projectile = Value(147)
|
||||
final val burster_projectile = Value(155)
|
||||
final val chainblade_projectile = Value(176)
|
||||
final val colossus_100mm_projectile = Value(181)
|
||||
final val colossus_burster_projectile = Value(188)
|
||||
final val colossus_chaingun_projectile = Value(193)
|
||||
final val colossus_cluster_bomb_projectile = Value(197)
|
||||
final val colossus_tank_cannon_projectile = Value(207)
|
||||
final val comet_projectile = Value(210)
|
||||
final val dualcycler_projectile = Value(266)
|
||||
final val dynomite_projectile = Value(268)
|
||||
final val energy_cell_projectile = Value(273)
|
||||
final val energy_gun_nc_projectile = Value(277)
|
||||
final val energy_gun_tr_projectile = Value(279)
|
||||
final val energy_gun_vs_projectile = Value(281)
|
||||
final val enhanced_energy_cell_projectile = Value(282)
|
||||
final val enhanced_quasar_projectile = Value(283)
|
||||
final val falcon_projectile = Value(286)
|
||||
final val firebird_missile_projectile = Value(288)
|
||||
final val flail_projectile = Value(296)
|
||||
final val flamethrower_fire_cloud = Value(301)
|
||||
final val flamethrower_fireball = Value(302)
|
||||
final val flamethrower_projectile = Value(303)
|
||||
final val flux_cannon_apc_projectile = Value(305)
|
||||
final val flux_cannon_thresher_projectile = Value(308)
|
||||
final val fluxpod_projectile = Value(311)
|
||||
final val forceblade_projectile = Value(325)
|
||||
final val frag_cartridge_projectile = Value(328)
|
||||
final val frag_cartridge_projectile_b = Value(329)
|
||||
final val frag_grenade_projectile = Value(332)
|
||||
final val frag_grenade_projectile_enh = Value(333)
|
||||
final val galaxy_gunship_gun_projectile = Value(341)
|
||||
final val gauss_cannon_projectile = Value(348)
|
||||
final val grenade_projectile = Value(372)
|
||||
final val heavy_grenade_projectile = Value(392)
|
||||
final val heavy_rail_beam_projectile = Value(395)
|
||||
final val heavy_sniper_projectile = Value(397)
|
||||
final val hellfire_projectile = Value(400)
|
||||
final val hunter_seeker_missile_dumbfire = Value(404)
|
||||
final val hunter_seeker_missile_projectile = Value(405)
|
||||
final val jammer_cartridge_projectile = Value(414)
|
||||
final val jammer_cartridge_projectile_b = Value(415)
|
||||
final val jammer_grenade_projectile = Value(418)
|
||||
final val jammer_grenade_projectile_enh = Value(419)
|
||||
final val katana_projectile = Value(422)
|
||||
final val katana_projectileb = Value(423)
|
||||
final val lancer_projectile = Value(427)
|
||||
final val lasher_projectile = Value(430)
|
||||
final val lasher_projectile_ap = Value(431)
|
||||
final val liberator_bomb_cluster_bomblet_projectile = Value(436)
|
||||
final val liberator_bomb_cluster_projectile = Value(437)
|
||||
final val liberator_bomb_projectile = Value(438)
|
||||
final val maelstrom_grenade_damager = Value(464)
|
||||
final val maelstrom_grenade_projectile = Value(465)
|
||||
final val maelstrom_grenade_projectile_contact = Value(466)
|
||||
final val maelstrom_stream_projectile = Value(467)
|
||||
final val magcutter_projectile = Value(469)
|
||||
final val melee_ammo_projectile = Value(541)
|
||||
final val meteor_common = Value(543)
|
||||
final val meteor_projectile_b_large = Value(544)
|
||||
final val meteor_projectile_b_medium = Value(545)
|
||||
final val meteor_projectile_b_small = Value(546)
|
||||
final val meteor_projectile_large = Value(547)
|
||||
final val meteor_projectile_medium = Value(548)
|
||||
final val meteor_projectile_small = Value(549)
|
||||
final val mine_projectile = Value(551)
|
||||
final val mine_sweeper_projectile = Value(554)
|
||||
final val mine_sweeper_projectile_enh = Value(555)
|
||||
final val ntu_siphon_emp = Value(596)
|
||||
final val oicw_little_buddy = Value(601)
|
||||
final val oicw_projectile = Value(602)
|
||||
final val pellet_gun_projectile = Value(631)
|
||||
final val peregrine_dual_machine_gun_projectile = Value(639)
|
||||
final val peregrine_mechhammer_projectile = Value(647)
|
||||
final val peregrine_particle_cannon_projectile = Value(654)
|
||||
final val peregrine_particle_cannon_radiation_cloud = Value(655) //radiation cloud
|
||||
final val peregrine_rocket_pod_projectile = Value(657)
|
||||
final val peregrine_sparrow_projectile = Value(661)
|
||||
final val phalanx_av_projectile = Value(665)
|
||||
final val phalanx_flak_projectile = Value(667)
|
||||
final val phalanx_projectile = Value(669)
|
||||
final val phoenix_missile_guided_projectile = Value(675)
|
||||
final val phoenix_missile_projectile = Value(676)
|
||||
final val plasma_cartridge_projectile = Value(678)
|
||||
final val plasma_cartridge_projectile_b = Value(679)
|
||||
final val plasma_grenade_projectile = Value(682)
|
||||
final val plasma_grenade_projectile_B = Value(683)
|
||||
final val pounder_projectile = Value(694)
|
||||
final val pounder_projectile_enh = Value(695)
|
||||
final val ppa_projectile = Value(696)
|
||||
final val pulsar_ap_projectile = Value(702)
|
||||
final val pulsar_projectile = Value(703)
|
||||
final val quasar_projectile = Value(713)
|
||||
final val radiator_cloud = Value(717) //radiation cloud
|
||||
final val radiator_grenade_projectile = Value(718)
|
||||
final val radiator_sticky_projectile = Value(719)
|
||||
final val reaver_rocket_projectile = Value(723)
|
||||
final val rocket_projectile = Value(735)
|
||||
final val rocklet_flak_projectile = Value(738)
|
||||
final val rocklet_jammer_projectile = Value(739)
|
||||
final val scattercannon_projectile = Value(746)
|
||||
final val scythe_projectile = Value(748)
|
||||
final val scythe_projectile_slave = Value(749)
|
||||
final val shotgun_shell_AP_projectile = Value(757)
|
||||
final val shotgun_shell_projectile = Value(758)
|
||||
final val six_shooter_projectile = Value(763)
|
||||
final val skyguard_flak_cannon_projectile = Value(787)
|
||||
final val sparrow_projectile = Value(792)
|
||||
final val sparrow_secondary_projectile = Value(793)
|
||||
final val spiker_projectile = Value(818)
|
||||
final val spitfire_aa_ammo_projectile = Value(821)
|
||||
final val spitfire_ammo_projectile = Value(824)
|
||||
final val starfire_projectile = Value(831)
|
||||
final val striker_missile_projectile = Value(840)
|
||||
final val striker_missile_targeting_projectile = Value(841)
|
||||
final val trek_projectile = Value(878)
|
||||
final val vanu_sentry_turret_projectile = Value(944)
|
||||
final val vulture_bomb_projectile = Value(988)
|
||||
final val vulture_nose_bullet_projectile = Value(989)
|
||||
final val vulture_tail_bullet_projectile = Value(991)
|
||||
final val wasp_gun_projectile = Value(999)
|
||||
final val wasp_rocket_projectile = Value(1001)
|
||||
final val winchester_projectile = Value(1005)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class ProjectileDefinition(objectId: Int)
|
|||
extends ObjectDefinition(objectId)
|
||||
with DamageWithPosition {
|
||||
/** ascertain that this object is a valid projectile type */
|
||||
private val projectileType: Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException
|
||||
private val projectileType: Projectiles.Types.Value = Projectiles.Types(objectId) //let throw NoSuchElementException
|
||||
/** how much faster (or slower) the projectile moves (m/s^2^) */
|
||||
private var acceleration: Int = 0
|
||||
/** when the acceleration stops being applied (s) */
|
||||
|
|
@ -64,7 +64,7 @@ class ProjectileDefinition(objectId: Int)
|
|||
Modifiers = DistanceDegrade
|
||||
registerAs = "projectiles"
|
||||
|
||||
def ProjectileType: Projectiles.Value = projectileType
|
||||
def ProjectileType: Projectiles.Types.Value = projectileType
|
||||
|
||||
def Acceleration: Int = acceleration
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ class ProjectileDefinition(objectId: Int)
|
|||
}
|
||||
|
||||
object ProjectileDefinition {
|
||||
def apply(projectileType: Projectiles.Value): ProjectileDefinition = {
|
||||
def apply(projectileType: Projectiles.Types.Value): ProjectileDefinition = {
|
||||
new ProjectileDefinition(projectileType.id)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) 2022 PSForever
|
||||
package net.psforever.objects.definition.converter
|
||||
|
||||
import net.psforever.objects.ballistics.Projectile
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
|
||||
import scala.util.{Success, Try}
|
||||
|
||||
class LittleBuddyProjectileConverter extends ObjectCreateConverter[Projectile]() {
|
||||
override def ConstructorData(obj: Projectile): Try[LittleBuddyProjectileData] = lilBudData(obj)
|
||||
|
||||
override def DetailedConstructorData(obj: Projectile): Try[LittleBuddyProjectileData] = lilBudData(obj)
|
||||
|
||||
private def lilBudData(obj: Projectile): Try[LittleBuddyProjectileData] = {
|
||||
Success(
|
||||
LittleBuddyProjectileData(
|
||||
CommonFieldDataWithPlacement(
|
||||
PlacementData(
|
||||
obj.Position,
|
||||
obj.Orientation,
|
||||
obj.Velocity
|
||||
),
|
||||
CommonFieldData(
|
||||
obj.owner.Faction,
|
||||
bops = false,
|
||||
alternate = false,
|
||||
v1 = true,
|
||||
v2 = None,
|
||||
jammered = false,
|
||||
v4 = None,
|
||||
v5 = None,
|
||||
guid = PlanetSideGUID(0)
|
||||
)
|
||||
),
|
||||
u2 = 0,
|
||||
u4 = true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ object EffectTarget {
|
|||
def RepairSilo(target: PlanetSideGameObject): Boolean =
|
||||
target match {
|
||||
case v: Vehicle =>
|
||||
!GlobalDefinitions.isFlightVehicle(v.Definition) && v.Health > 0 && v.Health < v.MaxHealth && v.History.exists(x => x.isInstanceOf[DamagingActivity] && x.time >= (System.currentTimeMillis() - 5000L))
|
||||
!GlobalDefinitions.isFlightVehicle(v.Definition) && v.Health > 0 && v.Health < v.MaxHealth && !v.History.takeWhile(System.currentTimeMillis() - _.time <= 5000L).exists(_.isInstanceOf[DamagingActivity])
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
|
|
@ -50,22 +50,7 @@ object EffectTarget {
|
|||
def PadLanding(target: PlanetSideGameObject): Boolean =
|
||||
target match {
|
||||
case v: Vehicle =>
|
||||
GlobalDefinitions.isFlightVehicle(v.Definition) && v.Health > 0 && v.Health < v.MaxHealth && v.History.exists(x => x.isInstanceOf[DamagingActivity] && x.time >= (System.currentTimeMillis() - 5000000000L))
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
|
||||
def AncientVehicleWeaponRecharge(target: PlanetSideGameObject): Boolean =
|
||||
target match {
|
||||
case v: Vehicle =>
|
||||
GlobalDefinitions.isCavernVehicle(v.Definition) && v.Health > 0 &&
|
||||
v.Weapons.values
|
||||
.map { _.Equipment }
|
||||
.flatMap {
|
||||
case Some(weapon: Tool) => weapon.AmmoSlots
|
||||
case _ => Nil
|
||||
}
|
||||
.exists { slot => slot.Box.Capacity < slot.Definition.Magazine }
|
||||
GlobalDefinitions.isFlightVehicle(v.Definition) && v.Health > 0 && v.Health < v.MaxHealth && !v.History.takeWhile(System.currentTimeMillis() - _.time <= 5000L).exists(_.isInstanceOf[DamagingActivity])
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
|
|
@ -135,5 +120,34 @@ object EffectTarget {
|
|||
case _ =>
|
||||
false
|
||||
}
|
||||
|
||||
def AncientWeaponRecharge(target: PlanetSideGameObject): Boolean = {
|
||||
target match {
|
||||
case p: Player =>
|
||||
(p.Holsters().map { _.Equipment }.flatten.toIterable ++ p.Inventory.Items.map { _.obj })
|
||||
.flatMap {
|
||||
case weapon: Tool => weapon.AmmoSlots
|
||||
case _ => Nil
|
||||
}
|
||||
.exists { slot => slot.Box.Capacity < slot.Definition.Magazine }
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def AncientVehicleWeaponRecharge(target: PlanetSideGameObject): Boolean =
|
||||
target match {
|
||||
case v: Vehicle =>
|
||||
GlobalDefinitions.isCavernVehicle(v.Definition) && v.Health > 0 &&
|
||||
v.Weapons.values
|
||||
.map { _.Equipment }
|
||||
.flatMap {
|
||||
case Some(weapon: Tool) => weapon.AmmoSlots
|
||||
case _ => Nil
|
||||
}
|
||||
.exists { slot => slot.Box.Capacity < slot.Definition.Magazine }
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,28 +3,15 @@ package net.psforever.objects.serverobject.terminals
|
|||
|
||||
import net.psforever.objects.Player
|
||||
|
||||
import scala.concurrent.duration.{Duration, FiniteDuration}
|
||||
|
||||
/**
|
||||
* The definition for any `Terminal` that is of a type "medical_terminal".
|
||||
* This includes the functionality of the formal medical terminals and some of the cavern crystals.
|
||||
* Do not confuse the game's internal "medical_terminal" object category and the actual `medical_terminal` object (529).
|
||||
*/
|
||||
class MedicalTerminalDefinition(objectId: Int) extends ProximityTerminalDefinition(objectId) {
|
||||
private var interval: FiniteDuration = Duration(0, "seconds")
|
||||
private var healAmount: Int = 0
|
||||
private var armorAmount: Int = 0
|
||||
|
||||
def Interval: FiniteDuration = interval
|
||||
|
||||
def Interval_=(amount: Int): FiniteDuration = {
|
||||
Interval_=(Duration(amount, "milliseconds"))
|
||||
}
|
||||
|
||||
def Interval_=(amount: FiniteDuration): FiniteDuration = {
|
||||
interval = amount
|
||||
Interval
|
||||
}
|
||||
class MedicalTerminalDefinition(objectId: Int)
|
||||
extends ProximityTerminalDefinition(objectId) {
|
||||
private var healAmount: Int = 0
|
||||
private var armorAmount: Int = 0
|
||||
|
||||
def HealAmount: Int = healAmount
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import net.psforever.objects.definition.ObjectDefinition
|
|||
import net.psforever.objects.equipment.EffectTarget
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.duration.{Duration, FiniteDuration}
|
||||
|
||||
/**
|
||||
* The definition mix-in for any game object that possesses a proximity-based effect.
|
||||
|
|
@ -17,10 +18,22 @@ import scala.collection.mutable
|
|||
trait ProximityDefinition {
|
||||
this: ObjectDefinition =>
|
||||
|
||||
private var interval: FiniteDuration = Duration(0, "seconds")
|
||||
private var useRadius: Float = 0f //TODO belongs on a wider range of object definitions
|
||||
private val targetValidation: mutable.HashMap[EffectTarget.Category.Value, PlanetSideGameObject => Boolean] =
|
||||
new mutable.HashMap[EffectTarget.Category.Value, PlanetSideGameObject => Boolean]()
|
||||
|
||||
def Interval: FiniteDuration = interval
|
||||
|
||||
def Interval_=(amount: Int): FiniteDuration = {
|
||||
Interval_=(Duration(amount, "milliseconds"))
|
||||
}
|
||||
|
||||
def Interval_=(amount: FiniteDuration): FiniteDuration = {
|
||||
interval = amount
|
||||
Interval
|
||||
}
|
||||
|
||||
def UseRadius: Float = useRadius
|
||||
|
||||
def UseRadius_=(radius: Float): Float = {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package net.psforever.objects.serverobject.terminals
|
|||
|
||||
import akka.actor.{ActorRef, Cancellable}
|
||||
import net.psforever.objects._
|
||||
import net.psforever.objects.ballistics.{PlayerSource, VehicleSource}
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
import net.psforever.objects.serverobject.CommonMessages
|
||||
import net.psforever.objects.serverobject.affinity.FactionAffinityBehavior
|
||||
import net.psforever.objects.serverobject.damage.Damageable.Target
|
||||
|
|
@ -10,8 +12,12 @@ import net.psforever.objects.serverobject.damage.DamageableAmenity
|
|||
import net.psforever.objects.serverobject.hackable.{GenericHackables, HackableBehavior}
|
||||
import net.psforever.objects.serverobject.repair.{AmenityAutoRepair, RepairableAmenity}
|
||||
import net.psforever.objects.serverobject.structures.{Building, PoweredAmenityControl}
|
||||
import net.psforever.objects.vital.{HealFromTerm, RepairFromTerm}
|
||||
import net.psforever.packet.game.InventoryStateMessage
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.services.local.{LocalAction, LocalServiceMessage}
|
||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.duration._
|
||||
|
|
@ -92,6 +98,9 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
|||
callbackList.lift(index) match {
|
||||
case Some(cback) =>
|
||||
cback ! ProximityUnit.Action(term, target)
|
||||
if (ProximityTerminalControl.selectAndTryProximityUnitBehavior(cback, term, target)) {
|
||||
Unuse(target, term.Zone.id)
|
||||
}
|
||||
case None =>
|
||||
log.error(
|
||||
s"improper callback registered for $target on $term in zone ${term.Owner.Continent}; this may be recoverable"
|
||||
|
|
@ -141,12 +150,12 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
|||
callbacks += callback
|
||||
//activation
|
||||
if (term.NumberUsers == 1 && hadNoUsers) {
|
||||
val medDef = term.Definition.asInstanceOf[MedicalTerminalDefinition]
|
||||
val tdef = term.Definition.asInstanceOf[ProximityDefinition]
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
terminalAction.cancel()
|
||||
terminalAction = context.system.scheduler.scheduleWithFixedDelay(
|
||||
500 milliseconds,
|
||||
medDef.Interval,
|
||||
tdef.Interval,
|
||||
self,
|
||||
ProximityTerminalControl.TerminalAction()
|
||||
)
|
||||
|
|
@ -166,7 +175,7 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
|||
s"ProximityTerminal.Unuse: unit ${term.Definition.Name}@${term.GUID.guid} will cease operation on $target"
|
||||
)
|
||||
//remove callback
|
||||
callbacks.remove(whereTarget)
|
||||
callbacks.remove(whereTarget) ! ProximityUnit.StopAction(term, target)
|
||||
//de-activation (global / local)
|
||||
if (term.NumberUsers == 0 && hadUsers) {
|
||||
terminalAction.cancel()
|
||||
|
|
@ -203,4 +212,209 @@ class ProximityTerminalControl(term: Terminal with ProximityUnit)
|
|||
|
||||
object ProximityTerminalControl {
|
||||
private case class TerminalAction()
|
||||
|
||||
/**
|
||||
* Determine which functionality to pursue by a generic proximity-functional unit given the target for its activity.
|
||||
* @see `VehicleService:receive, ProximityUnit.Action`
|
||||
* @param terminal the proximity-based unit
|
||||
* @param target the object being affected by the unit
|
||||
*/
|
||||
def selectAndTryProximityUnitBehavior(
|
||||
callback: ActorRef,
|
||||
terminal: Terminal with ProximityUnit,
|
||||
target: PlanetSideGameObject
|
||||
): Boolean = {
|
||||
(terminal.Definition, target) match {
|
||||
case (_: MedicalTerminalDefinition, p: Player) => HealthAndArmorTerminal(terminal, p)
|
||||
case (_: WeaponRechargeTerminalDefinition, p: Player) => WeaponRechargeTerminal(terminal, p)
|
||||
case (_: MedicalTerminalDefinition, v: Vehicle) => VehicleRepairTerminal(terminal, v)
|
||||
case (_: WeaponRechargeTerminalDefinition, v: Vehicle) => WeaponRechargeTerminal(terminal, v)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When standing on the platform of a(n advanced) medical terminal,
|
||||
* restore the player's health and armor points (when they need their health and armor points restored).
|
||||
* If the player is both fully healed and fully repaired, stop using the terminal.
|
||||
* @param unit the medical terminal
|
||||
* @param target the player being healed
|
||||
*/
|
||||
def HealthAndArmorTerminal(unit: Terminal with ProximityUnit, target: Player): Boolean = {
|
||||
val medDef = unit.Definition.asInstanceOf[MedicalTerminalDefinition]
|
||||
val healAmount = medDef.HealAmount
|
||||
val healthFull: Boolean = if (healAmount != 0 && target.Health < target.MaxHealth) {
|
||||
target.History(HealFromTerm(PlayerSource(target), healAmount, 0, medDef))
|
||||
HealAction(target, healAmount)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
val repairAmount = medDef.ArmorAmount
|
||||
val armorFull: Boolean = if (repairAmount != 0 && target.Armor < target.MaxArmor) {
|
||||
target.History(HealFromTerm(PlayerSource(target), 0, repairAmount, medDef))
|
||||
ArmorRepairAction(target, repairAmount)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
healthFull && armorFull
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore, at most, a specific amount of health points on a player.
|
||||
* Send messages to connected client and to events system.
|
||||
* @param tplayer the player
|
||||
* @param healValue the amount to heal;
|
||||
* 10 by default
|
||||
* @return whether the player can be repaired for any more health points
|
||||
*/
|
||||
def HealAction(tplayer: Player, healValue: Int = 10): Boolean = {
|
||||
tplayer.Health = tplayer.Health + healValue
|
||||
val zone = tplayer.Zone
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
zone.id,
|
||||
AvatarAction.PlanetsideAttributeToAll(tplayer.GUID, 0, tplayer.Health)
|
||||
)
|
||||
tplayer.Health == tplayer.MaxHealth
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore, at most, a specific amount of personal armor points on a player.
|
||||
* Send messages to connected client and to events system.
|
||||
* @param tplayer the player
|
||||
* @param repairValue the amount to repair;
|
||||
* 10 by default
|
||||
* @return whether the player can be repaired for any more armor points
|
||||
*/
|
||||
def ArmorRepairAction(tplayer: Player, repairValue: Int = 10): Boolean = {
|
||||
tplayer.Armor = tplayer.Armor + repairValue
|
||||
val zone = tplayer.Zone
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
zone.id,
|
||||
AvatarAction.PlanetsideAttributeToAll(tplayer.GUID, 4, tplayer.Armor)
|
||||
)
|
||||
tplayer.Armor == tplayer.MaxArmor
|
||||
}
|
||||
|
||||
/**
|
||||
* When driving a vehicle close to a rearm/repair silo,
|
||||
* restore the vehicle's health points.
|
||||
* If the vehicle is fully repaired, stop using the terminal.
|
||||
* @param unit the terminal
|
||||
* @param target the vehicle being repaired
|
||||
*/
|
||||
def VehicleRepairTerminal(unit: Terminal with ProximityUnit, target: Vehicle): Boolean = {
|
||||
val medDef = unit.Definition.asInstanceOf[MedicalTerminalDefinition]
|
||||
val healAmount = medDef.HealAmount
|
||||
val maxHealth = target.MaxHealth
|
||||
val noMoreHeal = if (!target.Destroyed && unit.Validate(target)) {
|
||||
//repair vehicle
|
||||
if (healAmount > 0 && target.Health < maxHealth) {
|
||||
target.Health = target.Health + healAmount
|
||||
target.History(RepairFromTerm(VehicleSource(target), healAmount, medDef))
|
||||
val zone = target.Zone
|
||||
zone.VehicleEvents ! VehicleServiceMessage(
|
||||
zone.id,
|
||||
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 0, target.Health)
|
||||
)
|
||||
target.Health == maxHealth
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
noMoreHeal
|
||||
}
|
||||
|
||||
/**
|
||||
* When standing in a friendly SOI whose facility is under the influence of an Ancient Weapon Module benefit,
|
||||
* and the player is in possession of Ancient weaponnry whose magazine is not full,
|
||||
* restore some ammunition to its magazine.
|
||||
* If no valid weapons are discovered or the discovered valid weapons have full magazines, stop using the terminal.
|
||||
* @param unit the terminal
|
||||
* @param target the player with weapons being recharged
|
||||
*/
|
||||
def WeaponRechargeTerminal(unit: Terminal with ProximityUnit, target: Player): Boolean = {
|
||||
val result = WeaponsBeingRechargedWithSomeAmmunition(
|
||||
unit.Definition.asInstanceOf[WeaponRechargeTerminalDefinition].AmmoAmount,
|
||||
target.Holsters().map { _.Equipment }.flatten.toIterable ++ target.Inventory.Items.map { _.obj }
|
||||
)
|
||||
val events = unit.Zone.AvatarEvents
|
||||
val channel = target.Name
|
||||
result.foreach { case (weapon, slots) =>
|
||||
slots.foreach { slot =>
|
||||
events ! AvatarServiceMessage(
|
||||
channel,
|
||||
AvatarAction.SendResponse(Service.defaultPlayerGUID, InventoryStateMessage(slot.Box.GUID, weapon.GUID, slot.Box.Capacity))
|
||||
)
|
||||
}
|
||||
}
|
||||
!result.unzip._2.flatten.exists { slot => slot.Magazine < slot.MaxMagazine() }
|
||||
}
|
||||
|
||||
/**
|
||||
* When driving close to a rearm/repair silo whose facility is under the influence of an Ancient Weapon Module benefit,
|
||||
* and the vehicle is an Ancient vehicle with mounted weaponry whose magazine(s) is not full,
|
||||
* restore some ammunition to the magazine(s).
|
||||
* If no valid weapons are discovered or the discovered valid weapons have full magazines, stop using the terminal.
|
||||
* @param unit the terminal
|
||||
* @param target the vehicle with weapons being recharged
|
||||
*/
|
||||
def WeaponRechargeTerminal(unit: Terminal with ProximityUnit, target: Vehicle): Boolean = {
|
||||
val result = WeaponsBeingRechargedWithSomeAmmunition(
|
||||
unit.Definition.asInstanceOf[WeaponRechargeTerminalDefinition].AmmoAmount,
|
||||
target.Weapons.values.collect { case e if e.Equipment.nonEmpty => e.Equipment.get }
|
||||
)
|
||||
val events = unit.Zone.VehicleEvents
|
||||
val channel = target.Actor.toString
|
||||
result.foreach { case (weapon, slots) =>
|
||||
slots.foreach { slot =>
|
||||
events ! VehicleServiceMessage(
|
||||
channel,
|
||||
VehicleAction.SendResponse(Service.defaultPlayerGUID, InventoryStateMessage(slot.Box.GUID, weapon.GUID, slot.Box.Capacity))
|
||||
)
|
||||
}
|
||||
}
|
||||
!result.unzip._2.flatten.exists { slot => slot.Magazine < slot.MaxMagazine() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect all weapons with magazines that need to have ammunition reloaded,
|
||||
* and reload some ammunition into them.
|
||||
* @param ammoAdded the amount of ammo to be added to a weapon
|
||||
* @param equipment the equipment being considered;
|
||||
* weapons whose ammo will be increased will be isolated
|
||||
* @return na
|
||||
*/
|
||||
def WeaponsBeingRechargedWithSomeAmmunition(
|
||||
ammoAdded: Int,
|
||||
equipment: Iterable[Equipment]
|
||||
): Iterable[(Tool, Iterable[Tool.FireModeSlot])] = {
|
||||
equipment
|
||||
.collect {
|
||||
case weapon: Tool
|
||||
if weapon.AmmoSlots.exists(slot => slot.Box.Capacity < slot.Definition.Magazine) =>
|
||||
(weapon, WeaponAmmoRecharge(ammoAdded, weapon.AmmoSlots))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect all magazines from this weapon that need to have ammunition reloaded,
|
||||
* and reload some ammunition into them.
|
||||
* @param ammoAdded the amount of ammo to be added to a weapon
|
||||
* @param slots the vehicle with weapons being recharged
|
||||
* @return ammunition slots that were affected
|
||||
*/
|
||||
def WeaponAmmoRecharge(
|
||||
ammoAdded: Int,
|
||||
slots: List[Tool.FireModeSlot]
|
||||
): List[Tool.FireModeSlot] = {
|
||||
val unfilledSlots = slots.filter { slot => slot.Magazine < slot.MaxMagazine() }
|
||||
if (unfilledSlots.nonEmpty) {
|
||||
unfilledSlots.foreach { slot => slot.Box.Capacity = slot.Box.Capacity + ammoAdded }
|
||||
unfilledSlots
|
||||
} else {
|
||||
Nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import net.psforever.objects.Player
|
|||
*
|
||||
* @param objectId the object's identifier number
|
||||
*/
|
||||
class ProximityTerminalDefinition(objectId: Int) extends TerminalDefinition(objectId) with ProximityDefinition {
|
||||
class ProximityTerminalDefinition(objectId: Int)
|
||||
extends TerminalDefinition(objectId)
|
||||
with ProximityDefinition {
|
||||
def Request(player: Player, msg: Any): Terminal.Exchange = Terminal.NoDeal()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ trait ProximityUnit {
|
|||
* @return `true`, if the entity passes the validation tests;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def Validate(radius: Float, validations: Seq[(PlanetSideGameObject) => Boolean])(
|
||||
def Validate(radius: Float, validations: Seq[PlanetSideGameObject => Boolean])(
|
||||
target: PlanetSideGameObject
|
||||
): Boolean = {
|
||||
//org.log4s.getLogger("ProximityUnit").info(s"vehicle: ${Owner.Position}, terminal: $Position, target: ${target.Position}, toOwner: ${Vector3.Distance(Position, Owner.Position)}, toTarget: ${Vector3.Distance(Position, target.Position)}")
|
||||
|
|
@ -93,4 +93,6 @@ trait ProximityUnit {
|
|||
|
||||
object ProximityUnit {
|
||||
final case class Action(terminal: Terminal with ProximityUnit, target: PlanetSideGameObject)
|
||||
|
||||
final case class StopAction(terminal: Terminal with ProximityUnit, target: PlanetSideGameObject)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2022 PSForever
|
||||
package net.psforever.objects.serverobject.terminals
|
||||
|
||||
import net.psforever.objects.Player
|
||||
|
||||
/**
|
||||
* na
|
||||
*/
|
||||
class WeaponRechargeTerminalDefinition(objectId: Int)
|
||||
extends ProximityTerminalDefinition(objectId) {
|
||||
private var ammoAmount: Int = 1
|
||||
|
||||
def AmmoAmount: Int = ammoAmount
|
||||
|
||||
def AmmoAmount_=(amount: Int): Int = {
|
||||
ammoAmount = amount
|
||||
AmmoAmount
|
||||
}
|
||||
|
||||
override def Request(player: Player, msg: Any): Terminal.Exchange = Terminal.NoDeal()
|
||||
}
|
||||
|
|
@ -162,11 +162,13 @@ trait VitalityDefinition extends DamageModifiers {
|
|||
/**
|
||||
* damage that is inherent to the object, used for explosions, mainly
|
||||
*/
|
||||
var innateDamage: Option[DamageWithPosition] = None
|
||||
private var _innateDamage: Option[DamageWithPosition] = None
|
||||
|
||||
def innateDamage: Option[DamageWithPosition] = _innateDamage
|
||||
|
||||
def innateDamage_=(combustion: DamageWithPosition): Option[DamageWithPosition] = {
|
||||
innateDamage = Some(combustion)
|
||||
innateDamage
|
||||
_innateDamage = Some(combustion)
|
||||
_innateDamage
|
||||
}
|
||||
|
||||
val collision: CollisionData = new CollisionData()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ package net.psforever.objects.vital.base
|
|||
object DamageType extends Enumeration(1) {
|
||||
type Type = Value
|
||||
|
||||
//"one" (numerical 1 in the ADB) corresponds to objects that explode
|
||||
//"one" (numerical 1 in the ADB) corresponds to objects that explode and kill fields
|
||||
final val Direct, Splash, Lash, Radiation, Aggravated, One, Siphon, None = Value
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,3 +109,13 @@ case object ExplodingRadialDegrade extends ExplodingDamageModifiers.Mod {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
case object ExplosionDamagesOnlyAbove extends ExplodingDamageModifiers.Mod {
|
||||
def calculate(damage: Int, data: DamageInteraction, cause: ExplodingEntityReason): Int = {
|
||||
if (data.target.Position.z <= data.hitPos.z) {
|
||||
damage
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import net.psforever.objects.vital.resolution.{DamageAndResistance, DamageResist
|
|||
|
||||
final case class PainboxReason(entity: Painbox) extends DamageReason {
|
||||
private val definition = entity.Definition
|
||||
assert(definition.innateDamage.nonEmpty, "causal entity does not emit pain field")
|
||||
assert(definition.innateDamage.nonEmpty, s"causal entity '${definition.Name}' does not emit pain field")
|
||||
|
||||
def source: DamageWithPosition = definition.innateDamage.get
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import net.psforever.objects.vital.resolution.DamageAndResistance
|
|||
/**
|
||||
* A wrapper for a "damage source" in damage calculations
|
||||
* that parameterizes information necessary to explain a radiation cloud.
|
||||
* @param resolution how the damage is processed
|
||||
* @param projectile the projectile that caused the damage
|
||||
* @param damageModel the model to be utilized in these calculations;
|
||||
* typically, but not always, defined by the target
|
||||
|
|
@ -55,9 +54,8 @@ object RadiationDamageModifiers {
|
|||
}
|
||||
|
||||
/**
|
||||
* If the damge is caused by a projectile that emits a field that permeates vehicle armor,
|
||||
* If the damage is caused by a projectile that emits a field that permeates vehicle armor,
|
||||
* determine by how much the traversed armor's shielding reduces the damage.
|
||||
* Infantry take damage, reduced only if one is equipped with a mechanized assault exo-suit.
|
||||
*/
|
||||
case object ShieldAgainstRadiation extends RadiationDamageModifiers.Mod {
|
||||
def calculate(damage: Int, data: DamageInteraction, cause: RadiationReason): Int = {
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ case object FlailDistanceDamageBoost extends ProjectileDamageModifiers.Mod {
|
|||
}
|
||||
|
||||
/**
|
||||
* If the damge is caused by a projectile that emits a field that permeates vehicle armor,
|
||||
* If the damge is caused by a projectile that emits a field that permeates armor,
|
||||
* determine by how much the traversed armor's shielding reduces the damage.
|
||||
* Infantry take damage, reduced only if one is equipped with a mechanized assault exo-suit.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -30,8 +30,9 @@ trait DamageProperties
|
|||
private var useDamage1Subtract: Boolean = false
|
||||
/** some other entity confers damage;
|
||||
* a set value should be the damager's object uid
|
||||
* usually corresponding to a projectile */
|
||||
private var damageProxy: Option[Int] = None
|
||||
* usually corresponding to a projectile;
|
||||
* also used to produce staged projectiles */
|
||||
private var damageProxy: List[Int] = Nil
|
||||
/** na;
|
||||
* currently used with jammer properties only */
|
||||
private var additionalEffect: Boolean = false
|
||||
|
|
@ -88,11 +89,14 @@ trait DamageProperties
|
|||
DamageToBattleframeOnly
|
||||
}
|
||||
|
||||
def DamageProxy : Option[Int] = damageProxy
|
||||
def DamageProxy : List[Int] = damageProxy
|
||||
|
||||
def DamageProxy_=(proxyObjectId : Int) : Option[Int] = DamageProxy_=(Some(proxyObjectId))
|
||||
def DamageProxy_=(proxyObjectId: Int): List[Int] = {
|
||||
damageProxy = damageProxy :+ proxyObjectId
|
||||
DamageProxy
|
||||
}
|
||||
|
||||
def DamageProxy_=(proxyObjectId : Option[Int]) : Option[Int] = {
|
||||
def DamageProxy_=(proxyObjectId: List[Int]): List[Int] = {
|
||||
damageProxy = proxyObjectId
|
||||
DamageProxy
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1257,10 +1257,27 @@ object Zone {
|
|||
source: PlanetSideGameObject with FactionAffinity with Vitality,
|
||||
target: PlanetSideGameObject with FactionAffinity with Vitality
|
||||
): DamageInteraction = {
|
||||
explosionDamage(instigation, target.Position)(source, target)
|
||||
}/**
|
||||
* na
|
||||
* @param instigation what previous event happened, if any, that caused this explosion
|
||||
* @param explosionPosition the coordinates of the detected explosion
|
||||
* @param source a game object that represents the source of the explosion
|
||||
* @param target a game object that is affected by the explosion
|
||||
* @return a `DamageInteraction` object
|
||||
*/
|
||||
def explosionDamage(
|
||||
instigation: Option[DamageResult],
|
||||
explosionPosition: Vector3
|
||||
)
|
||||
(
|
||||
source: PlanetSideGameObject with FactionAffinity with Vitality,
|
||||
target: PlanetSideGameObject with FactionAffinity with Vitality
|
||||
): DamageInteraction = {
|
||||
DamageInteraction(
|
||||
SourceEntry(target),
|
||||
ExplodingEntityReason(source, target.DamageModel, instigation),
|
||||
target.Position
|
||||
explosionPosition
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,6 +143,10 @@ class ZoneProjectileActor(
|
|||
val (clarifiedFilterGuid, duration) = if (definition.radiation_cloud) {
|
||||
zone.blockMap.addTo(projectile)
|
||||
(Service.defaultPlayerGUID, projectile.profile.Lifespan seconds)
|
||||
} else if (definition.RemoteClientData == (0,0)) {
|
||||
//remote projectiles that are not radiation clouds have lifespans controlled by the controller (user)
|
||||
//this projectile has defaulted remote client data
|
||||
(Service.defaultPlayerGUID, projectile.profile.Lifespan * 1.5f seconds)
|
||||
} else {
|
||||
//remote projectiles that are not radiation clouds have lifespans controlled by the controller (user)
|
||||
//if the controller fails, the projectile has a bit more than its normal lifespan before automatic clean up
|
||||
|
|
@ -188,6 +192,11 @@ class ZoneProjectileActor(
|
|||
zone.id,
|
||||
AvatarAction.ObjectDelete(PlanetSideGUID(0), projectile_guid, 2)
|
||||
)
|
||||
} else if (projectile.Definition.RemoteClientData == (0,0)) {
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
zone.id,
|
||||
AvatarAction.ObjectDelete(PlanetSideGUID(0), projectile_guid, 2)
|
||||
)
|
||||
} else {
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
zone.id,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) 2022 PSForever
|
||||
package net.psforever.packet.game.objectcreate
|
||||
|
||||
import net.psforever.packet.Marshallable
|
||||
import scodec.{Attempt, Codec}
|
||||
import scodec.codecs._
|
||||
import shapeless.{::, HNil}
|
||||
|
||||
final case class LittleBuddyProjectileData(
|
||||
data: CommonFieldDataWithPlacement,
|
||||
u2: Int,
|
||||
u4: Boolean
|
||||
) extends ConstructorData {
|
||||
assert(data.pos.vel.nonEmpty, "oicw little buddy object always requires velocity to be defined")
|
||||
/**
|
||||
* The length of the little buddy data is functionally `32u`
|
||||
* after all other fields are accounted for
|
||||
* but the packet decode demands an additional bit be accounted for.
|
||||
* @return the number of bits necessary to measure an object of this class
|
||||
*/
|
||||
override def bitsize: Long = 33L + data.bitsize
|
||||
}
|
||||
|
||||
object LittleBuddyProjectileData extends Marshallable[LittleBuddyProjectileData] {
|
||||
implicit val codec: Codec[LittleBuddyProjectileData] = (
|
||||
("data" | CommonFieldDataWithPlacement.codec) ::
|
||||
("unk2" | uint24L) ::
|
||||
uint(bits = 7) ::
|
||||
("unk4" | bool)
|
||||
).exmap[LittleBuddyProjectileData](
|
||||
{
|
||||
case data :: u2 :: 31 :: u4 :: HNil =>
|
||||
Attempt.successful(LittleBuddyProjectileData(data, u2, u4))
|
||||
},
|
||||
{
|
||||
case LittleBuddyProjectileData(data, u2, u4) =>
|
||||
Attempt.successful(data :: u2 :: 31 :: u4 :: HNil)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -669,7 +669,8 @@ object ObjectClass {
|
|||
def selectDataDroppedDetailedCodec(objClass: Int): Codec[ConstructorData] =
|
||||
(objClass: @switch) match {
|
||||
//special cases
|
||||
case ObjectClass.avatar => ConstructorData(DetailedPlayerData.codec(true), "avatar")
|
||||
case ObjectClass.avatar => ConstructorData(DetailedPlayerData.codec(position_defined = true), "avatar")
|
||||
case ObjectClass.oicw_little_buddy => ConstructorData(LittleBuddyProjectileData.codec, "projectile")
|
||||
//defer to other codec selection
|
||||
case _ => selectDataDetailedCodec(objClass)
|
||||
}
|
||||
|
|
@ -1240,7 +1241,7 @@ object ObjectClass {
|
|||
case ObjectClass.meteor_projectile_small => ConstructorData(RemoteProjectileData.codec, "meteor")
|
||||
case ObjectClass.peregrine_particle_cannon_radiation_cloud => ConstructorData(RadiationCloudData.codec, "radiation cloud")
|
||||
case ObjectClass.phoenix_missile_guided_projectile => ConstructorData(RemoteProjectileData.codec, "projectile")
|
||||
case ObjectClass.oicw_little_buddy => ConstructorData(RemoteProjectileData.codec, "projectile")
|
||||
case ObjectClass.oicw_little_buddy => ConstructorData(LittleBuddyProjectileData.codec, "projectile")
|
||||
case ObjectClass.oicw_projectile => ConstructorData(RemoteProjectileData.codec, "projectile")
|
||||
case ObjectClass.radiator_cloud => ConstructorData(RadiationCloudData.codec, "radiation cloud")
|
||||
case ObjectClass.sparrow_projectile => ConstructorData(RemoteProjectileData.codec, "projectile")
|
||||
|
|
|
|||
|
|
@ -9,14 +9,15 @@ import shapeless.{::, HNil}
|
|||
object RemoteProjectiles {
|
||||
abstract class Data(val a: Int, val b: Int)
|
||||
|
||||
final case object Meteor extends Data(0, 32)
|
||||
final case object Wasp extends Data(0, 208)
|
||||
final case object Sparrow extends Data(13107, 187)
|
||||
final case object OICW extends Data(13107, 195)
|
||||
final case object Striker extends Data(26214, 134)
|
||||
final case object HunterSeeker extends Data(39577, 201)
|
||||
final case object Starfire extends Data(39577, 249)
|
||||
class OICWLittleBuddy(x: Int, y: Int) extends Data(x, y)
|
||||
final case object Meteor extends Data(0, 32)
|
||||
final case object Wasp extends Data(0, 208)
|
||||
final case object Sparrow extends Data(13107, 187)
|
||||
final case object OICW extends Data(13107, 195)
|
||||
final case object Striker extends Data(26214, 134)
|
||||
final case object HunterSeeker extends Data(39577, 201)
|
||||
final case object Starfire extends Data(39577, 249)
|
||||
|
||||
//the oicw_little_buddy is handled by its own transcoder
|
||||
}
|
||||
|
||||
object FlightPhysics extends Enumeration {
|
||||
|
|
@ -67,7 +68,7 @@ object RemoteProjectileData extends Marshallable[RemoteProjectileData] {
|
|||
("u1" | uint16) ::
|
||||
("u2" | uint8) ::
|
||||
("unk3" | FlightPhysics.codec) ::
|
||||
("unk4" | uint(3)) ::
|
||||
("unk4" | uint(bits = 3)) ::
|
||||
("unk5" | uint2)
|
||||
).exmap[RemoteProjectileData](
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@
|
|||
package net.psforever.services.vehicle
|
||||
|
||||
import akka.actor.{Actor, ActorRef, Props}
|
||||
import net.psforever.objects.{GlobalDefinitions, Tool, Vehicle}
|
||||
import net.psforever.objects.ballistics.VehicleSource
|
||||
import net.psforever.objects.serverobject.pad.VehicleSpawnPad
|
||||
import net.psforever.objects.serverobject.terminals.{MedicalTerminalDefinition, ProximityUnit}
|
||||
import net.psforever.objects.vital.RepairFromTerm
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.packet.game.ObjectCreateMessage
|
||||
import net.psforever.packet.game.objectcreate.ObjectCreateMessageParent
|
||||
import net.psforever.services.vehicle.support.TurretUpgrader
|
||||
import net.psforever.types.{DriveState, PlanetSideGUID}
|
||||
import net.psforever.types.DriveState
|
||||
import net.psforever.services.{GenericEventBus, Service}
|
||||
|
||||
class VehicleService(zone: Zone) extends Actor {
|
||||
|
|
@ -395,51 +391,6 @@ class VehicleService(zone: Zone) extends Actor {
|
|||
)
|
||||
)
|
||||
|
||||
//from ProximityTerminalControl (?)
|
||||
case ProximityUnit.Action(term, target: Vehicle) =>
|
||||
val medDef = term.Definition.asInstanceOf[MedicalTerminalDefinition]
|
||||
val healAmount = medDef.HealAmount
|
||||
if (!target.Destroyed && term.Validate(target)) {
|
||||
//repair vehicle
|
||||
if (healAmount > 0 && target.Health < target.MaxHealth) {
|
||||
val healAmount = medDef.HealAmount
|
||||
target.Health = target.Health + healAmount
|
||||
target.History(RepairFromTerm(VehicleSource(target), healAmount, medDef))
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(
|
||||
s"/${term.Continent}/Vehicle",
|
||||
PlanetSideGUID(0),
|
||||
VehicleResponse.PlanetsideAttribute(target.GUID, 0, target.Health)
|
||||
)
|
||||
)
|
||||
}
|
||||
//recharge ammunition of cavern vehicles
|
||||
if (GlobalDefinitions.isCavernVehicle(target.Definition) && term.Definition == GlobalDefinitions.recharge_terminal) {
|
||||
//TODO check cavern module benefits on facility; unlike facility benefits, it's faked for now
|
||||
val channel = s"/${target.Actor.toString}/Vehicle"
|
||||
val parent = target.GUID
|
||||
val excludeNone = Service.defaultPlayerGUID
|
||||
target.Weapons.values
|
||||
.map { _.Equipment }
|
||||
.collect { case Some(weapon: Tool) =>
|
||||
weapon.AmmoSlots
|
||||
.foreach { slot =>
|
||||
val box = slot.Box
|
||||
if (box.Capacity < slot.Definition.Magazine) {
|
||||
val capacity = box.Capacity += 1
|
||||
VehicleEvents.publish(
|
||||
VehicleServiceResponse(
|
||||
channel,
|
||||
excludeNone,
|
||||
VehicleResponse.InventoryState2(box.GUID, parent, capacity)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case msg =>
|
||||
log.warn(s"Unhandled message $msg from ${sender()}")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,6 +295,19 @@ object Zones {
|
|||
)
|
||||
)
|
||||
)
|
||||
if (facilityTypes.contains(structure.objectType)) {
|
||||
//major overworld facilities have an intrinsic terminal that occasionally recharges ancient weapons
|
||||
val buildingGuid = structure.guid
|
||||
val terminalGuid = buildingGuid + 1
|
||||
zoneMap.addLocalObject(
|
||||
buildingGuid + 1,
|
||||
ProximityTerminal.Constructor(
|
||||
structure.position,
|
||||
GlobalDefinitions.recharge_terminal_weapon_module
|
||||
),
|
||||
owningBuildingGuid = buildingGuid
|
||||
)
|
||||
}
|
||||
}
|
||||
val filteredZoneEntities =
|
||||
data.filter { _.owner.contains(structure.id) } ++
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
package game.objectcreate
|
||||
|
||||
import net.psforever.packet.PacketCoding
|
||||
import net.psforever.packet.game.ObjectCreateMessage
|
||||
import net.psforever.packet.game.{ObjectCreateDetailedMessage, ObjectCreateMessage}
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||
import org.specs2.mutable._
|
||||
|
|
@ -11,6 +11,7 @@ import scodec.bits._
|
|||
class RemoteProjectileDataTest extends Specification {
|
||||
val string_striker_projectile = hex"17 C5000000 A4B 009D 4C129 0CB0A 9814 00 F5 E3 040000666686400"
|
||||
val string_hunter_seeker_missile_projectile = hex"17 c5000000 ca9 ab9e af127 ec465 3723 00 15 c4 2400009a99c9400"
|
||||
val string_oicw_little_buddy = hex"18 ef000000 aca 3d0e 1ef35 d9417 2511 00 0f 21 d3bf0d1bc38900000000000fc"
|
||||
|
||||
"RemoteProjectileData" should {
|
||||
"decode (striker_missile_targeting_projectile)" in {
|
||||
|
|
@ -33,7 +34,6 @@ class RemoteProjectileDataTest extends Specification {
|
|||
deploy.v4.isEmpty mustEqual true
|
||||
deploy.v5.isEmpty mustEqual true
|
||||
deploy.guid mustEqual PlanetSideGUID(0)
|
||||
|
||||
unk2 mustEqual 26214
|
||||
lim mustEqual 134
|
||||
unk3 mustEqual FlightPhysics.State4
|
||||
|
|
@ -67,7 +67,6 @@ class RemoteProjectileDataTest extends Specification {
|
|||
deploy.v4.isEmpty mustEqual true
|
||||
deploy.v5.isEmpty mustEqual true
|
||||
deploy.guid mustEqual PlanetSideGUID(0)
|
||||
|
||||
unk2 mustEqual 39577
|
||||
lim mustEqual 201
|
||||
unk3 mustEqual FlightPhysics.State4
|
||||
|
|
@ -81,6 +80,37 @@ class RemoteProjectileDataTest extends Specification {
|
|||
}
|
||||
}
|
||||
|
||||
"decode (oicw_little_buddy)" in {
|
||||
PacketCoding.decodePacket(string_oicw_little_buddy).require match {
|
||||
case ObjectCreateDetailedMessage(len, cls, guid, parent, data) =>
|
||||
len mustEqual 239
|
||||
cls mustEqual ObjectClass.oicw_little_buddy
|
||||
guid mustEqual PlanetSideGUID(3645)
|
||||
parent.isDefined mustEqual false
|
||||
data match {
|
||||
case LittleBuddyProjectileData(dat, u2, u4) =>
|
||||
dat.pos.coord mustEqual Vector3(3046.2344f, 3715.6953f, 68.578125f)
|
||||
dat.pos.orient mustEqual Vector3(0, 317.8125f, 357.1875f)
|
||||
dat.pos.vel.contains(Vector3(-10.0125f, 101.475f, -101.7f)) mustEqual true
|
||||
dat.data.faction mustEqual PlanetSideEmpire.NC
|
||||
dat.data.bops mustEqual false
|
||||
dat.data.alternate mustEqual false
|
||||
dat.data.v1 mustEqual true
|
||||
dat.data.v2.isEmpty mustEqual true
|
||||
dat.data.jammered mustEqual false
|
||||
dat.data.v4.isEmpty mustEqual true
|
||||
dat.data.v5.isEmpty mustEqual true
|
||||
dat.data.guid mustEqual PlanetSideGUID(0)
|
||||
u2 mustEqual 0
|
||||
u4 mustEqual true
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
case _ =>
|
||||
ko
|
||||
}
|
||||
}
|
||||
|
||||
"encode (striker_missile_targeting_projectile)" in {
|
||||
val obj = RemoteProjectileData(
|
||||
CommonFieldDataWithPlacement(
|
||||
|
|
@ -101,26 +131,53 @@ class RemoteProjectileDataTest extends Specification {
|
|||
pkt.toBitVector.drop(133).take(7) mustEqual string_striker_projectile.toBitVector.drop(133).take(7)
|
||||
pkt.toBitVector.drop(141) mustEqual string_striker_projectile.toBitVector.drop(141)
|
||||
}
|
||||
}
|
||||
|
||||
"encode (hunter_seeker_missile_projectile)" in {
|
||||
val obj = RemoteProjectileData(
|
||||
CommonFieldDataWithPlacement(
|
||||
PlacementData(3621.3672f, 2701.8438f, 140.85938f, 0, 300.9375f, 258.75f),
|
||||
CommonFieldData(PlanetSideEmpire.NC, false, false, true, None, false, None, None, PlanetSideGUID(0))
|
||||
),
|
||||
39577,
|
||||
201,
|
||||
FlightPhysics.State4,
|
||||
0,
|
||||
0
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.hunter_seeker_missile_projectile, PlanetSideGUID(40619), obj)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
//pkt mustEqual string_hunter_seeker_missile_projectile
|
||||
"encode (hunter_seeker_missile_projectile)" in {
|
||||
val obj = RemoteProjectileData(
|
||||
CommonFieldDataWithPlacement(
|
||||
PlacementData(3621.3672f, 2701.8438f, 140.85938f, 0, 300.9375f, 258.75f),
|
||||
CommonFieldData(PlanetSideEmpire.NC, false, false, true, None, false, None, None, PlanetSideGUID(0))
|
||||
),
|
||||
39577,
|
||||
201,
|
||||
FlightPhysics.State4,
|
||||
0,
|
||||
0
|
||||
)
|
||||
val msg = ObjectCreateMessage(ObjectClass.hunter_seeker_missile_projectile, PlanetSideGUID(40619), obj)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
//pkt mustEqual string_hunter_seeker_missile_projectile
|
||||
|
||||
pkt.toBitVector.take(132) mustEqual string_hunter_seeker_missile_projectile.toBitVector.take(132)
|
||||
pkt.toBitVector.drop(133).take(7) mustEqual string_hunter_seeker_missile_projectile.toBitVector.drop(133).take(7)
|
||||
pkt.toBitVector.drop(141) mustEqual string_hunter_seeker_missile_projectile.toBitVector.drop(141)
|
||||
pkt.toBitVector.take(132) mustEqual string_hunter_seeker_missile_projectile.toBitVector.take(132)
|
||||
pkt.toBitVector.drop(133).take(7) mustEqual string_hunter_seeker_missile_projectile.toBitVector.drop(133).take(7)
|
||||
pkt.toBitVector.drop(141) mustEqual string_hunter_seeker_missile_projectile.toBitVector.drop(141)
|
||||
}
|
||||
|
||||
"encode (oicw_little_buddy)" in {
|
||||
val obj = LittleBuddyProjectileData(
|
||||
CommonFieldDataWithPlacement(
|
||||
PlacementData(Vector3(3046.2344f, 3715.6953f, 68.578125f),
|
||||
Vector3(0, 317.8125f, 357.1875f),
|
||||
Some(Vector3(-10.0125f, 101.475f, -101.7f))
|
||||
),
|
||||
CommonFieldData(
|
||||
PlanetSideEmpire.NC,
|
||||
bops = false,
|
||||
alternate = false,
|
||||
v1 = true,
|
||||
v2 = None,
|
||||
jammered = false,
|
||||
v4 = None,
|
||||
v5 = None,
|
||||
guid = PlanetSideGUID(0)
|
||||
)
|
||||
),
|
||||
u2 = 0,
|
||||
u4 = true
|
||||
)
|
||||
val msg = ObjectCreateDetailedMessage(ObjectClass.oicw_little_buddy, PlanetSideGUID(3645), obj)
|
||||
val pkt = PacketCoding.encodePacket(msg).require.toByteVector
|
||||
pkt mustEqual string_oicw_little_buddy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -921,7 +921,7 @@ class DamageModelTests extends Specification {
|
|||
}
|
||||
|
||||
object DamageModelTests {
|
||||
final val projectile = new ProjectileDefinition(Projectiles.heavy_grenade_projectile.id) {
|
||||
final val projectile = new ProjectileDefinition(Projectiles.Types.heavy_grenade_projectile.id) {
|
||||
Damage0 = 50
|
||||
Damage1 = 82
|
||||
Damage2 = 82
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class ProjectileTest extends Specification {
|
|||
"define (default)" in {
|
||||
val obj = new ProjectileDefinition(31) //9mmbullet_projectile
|
||||
|
||||
obj.ProjectileType mustEqual Projectiles.bullet_9mm_projectile
|
||||
obj.ProjectileType mustEqual Projectiles.Types.bullet_9mm_projectile
|
||||
obj.ObjectId mustEqual 31
|
||||
obj.Damage0 mustEqual 0
|
||||
obj.Damage1 mustEqual 0
|
||||
|
|
@ -84,9 +84,9 @@ class ProjectileTest extends Specification {
|
|||
}
|
||||
|
||||
"define (failure)" in {
|
||||
Projectiles(31) mustEqual Projectiles.bullet_9mm_projectile
|
||||
Projectiles.Types(31) mustEqual Projectiles.Types.bullet_9mm_projectile
|
||||
try {
|
||||
ProjectileDefinition(Projectiles.bullet_9mm_projectile) //passes
|
||||
ProjectileDefinition(Projectiles.Types.bullet_9mm_projectile) //passes
|
||||
} catch {
|
||||
case _: NoSuchElementException =>
|
||||
ko
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import net.psforever.objects.guid.source.MaxNumberSource
|
|||
import net.psforever.objects.serverobject.environment._
|
||||
import net.psforever.objects.serverobject.mount.Mountable
|
||||
import net.psforever.objects.vehicles.VehicleLockState
|
||||
import net.psforever.objects.vehicles.control.{CargoCarrierControl, VehicleControl}
|
||||
import net.psforever.objects.vehicles.control.{/*CargoCarrierControl, */VehicleControl}
|
||||
import net.psforever.objects.vital.{VehicleShieldCharge, Vitality}
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.packet.game._
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ class ProximityTerminalControlTwoUsersTest extends ActorTest {
|
|||
)
|
||||
)
|
||||
avatar.Continent = "test"
|
||||
avatar.Zone = zone
|
||||
avatar.Spawn()
|
||||
avatar.Health = 50
|
||||
val avatar2 =
|
||||
|
|
@ -249,12 +250,13 @@ class ProximityTerminalControlTwoUsersTest extends ActorTest {
|
|||
ProximityTest.avatarId.getAndIncrement(),
|
||||
"TestCharacter2",
|
||||
PlanetSideEmpire.VS,
|
||||
CharacterSex.Female,
|
||||
CharacterSex.Male,
|
||||
1,
|
||||
CharacterVoice.Voice1
|
||||
)
|
||||
)
|
||||
avatar2.Continent = "test"
|
||||
avatar2.Zone = zone
|
||||
avatar2.Spawn()
|
||||
avatar2.Health = 50
|
||||
|
||||
|
|
@ -266,6 +268,7 @@ class ProximityTerminalControlTwoUsersTest extends ActorTest {
|
|||
val probe1 = new TestProbe(system, "local-events")
|
||||
val probe2 = new TestProbe(system, "target-callback-1")
|
||||
val probe3 = new TestProbe(system, "target-callback-2")
|
||||
zone.AvatarEvents = new TestProbe(system, "avatar-events-throwaway").ref
|
||||
zone.LocalEvents = probe1.ref
|
||||
|
||||
"not send out a start message if not the first user" in {
|
||||
|
|
@ -274,7 +277,7 @@ class ProximityTerminalControlTwoUsersTest extends ActorTest {
|
|||
|
||||
terminal.Actor.tell(CommonMessages.Use(avatar, Some(avatar)), probe2.ref)
|
||||
probe1.expectMsgClass(1 second, classOf[Terminal.StartProximityEffect])
|
||||
probe2.expectMsgClass(1 second, classOf[ProximityUnit.Action])
|
||||
probe2.expectMsgClass(5 second, classOf[ProximityUnit.Action])
|
||||
|
||||
terminal.Actor.tell(CommonMessages.Use(avatar2, Some(avatar2)), probe3.ref)
|
||||
probe1.expectNoMessage(1 second)
|
||||
|
|
@ -313,15 +316,17 @@ class ProximityTerminalControlStopTest extends ActorTest {
|
|||
)
|
||||
)
|
||||
avatar.Continent = "test"
|
||||
avatar.Zone = zone
|
||||
avatar.Spawn()
|
||||
avatar.Health = 50
|
||||
avatar.Health = 1
|
||||
|
||||
avatar.GUID = PlanetSideGUID(1)
|
||||
terminal.GUID = PlanetSideGUID(2)
|
||||
terminal.Actor ! Service.Startup()
|
||||
expectNoMessage(500 milliseconds) //spacer
|
||||
val probe1 = new TestProbe(system, "local-events")
|
||||
val probe2 = new TestProbe(system, "target-callback-1")
|
||||
val probe2 = new TestProbe(system, "target-callback")
|
||||
zone.AvatarEvents = new TestProbe(system, "avatar-events-throwaway").ref
|
||||
zone.LocalEvents = probe1.ref
|
||||
|
||||
"send out a stop message" in {
|
||||
|
|
@ -333,6 +338,14 @@ class ProximityTerminalControlStopTest extends ActorTest {
|
|||
probe2.expectMsgClass(1 second, classOf[ProximityUnit.Action])
|
||||
|
||||
terminal.Actor ! CommonMessages.Unuse(avatar, Some(avatar))
|
||||
probe2.fishForMessage(2.seconds, hint = "could not find StopAction") {
|
||||
case _ : ProximityUnit.Action => false
|
||||
case _ => true
|
||||
} match {
|
||||
case _ : ProximityUnit.StopAction => ;
|
||||
case out => assert(false, s"last message $out is not StopAction")
|
||||
}
|
||||
//probe2.expectMsgClass(1 second, classOf[ProximityUnit.StopAction])
|
||||
probe1.expectMsgClass(1 second, classOf[Terminal.StopProximityEffect])
|
||||
assert(terminal.NumberUsers == 0)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue