mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
raestored radiator availability; radiator damage restored to value on file (2) rather than makeshift (1); radiator damage (and other cloud-based damage) should not stack; radiator should damage MAX again; vehicle occupant damage may be fixed, but have not tested; most file changes are accounting for two classes moved into their own package
This commit is contained in:
parent
73c9c5a4a0
commit
c8ab08b2f5
|
|
@ -78,7 +78,7 @@ add_property pulsar equiptime 600
|
|||
add_property pulsar holstertime 600
|
||||
add_property punisher equiptime 600
|
||||
add_property punisher holstertime 600
|
||||
add_property radiator allowed false
|
||||
add_property radiator allowed true
|
||||
add_property r_shotgun equiptime 750
|
||||
add_property r_shotgun holstertime 750
|
||||
add_property remote_electronics_kit equiptime 500
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ import net.psforever.objects.vital.damage.DamageProfile
|
|||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.vital.resolution.DamageResistanceModel
|
||||
import net.psforever.objects.zones.blockmap.BlockMapEntity
|
||||
import net.psforever.objects.zones.{InteractsWithZone, ZoneAware, Zoning}
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.objects.zones.{ZoneAware, Zoning}
|
||||
import net.psforever.types._
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import net.psforever.objects.vital.damage.DamageCalculations
|
|||
import net.psforever.objects.vital.interaction.DamageResult
|
||||
import net.psforever.objects.vital.resistance.StandardResistanceProfile
|
||||
import net.psforever.objects.vital.{SimpleResolutions, StandardVehicleResistance}
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.packet.game.TriggeredSound
|
||||
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import net.psforever.objects.vehicles.interaction.{TriggerOnVehicleRule, WithLav
|
|||
import net.psforever.objects.vital.resistance.StandardResistanceProfile
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.vital.resolution.DamageResistanceModel
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.blockmap.BlockMapEntity
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.packet.PlanetSideGamePacket
|
||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import net.psforever.objects.serverobject.doors.{Door, InteriorDoorPassage}
|
|||
import net.psforever.objects.serverobject.environment.{EnvironmentAttribute, EnvironmentTrait, PieceOfEnvironment, interaction}
|
||||
import net.psforever.objects.serverobject.environment.interaction.{InteractionWith, RespondsToZoneEnvironment}
|
||||
import net.psforever.objects.serverobject.interior.{Sidedness, TraditionalInteriorAware}
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
import scala.annotation.unused
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import net.psforever.objects.serverobject.environment.interaction.{InteractionWi
|
|||
import net.psforever.objects.{Player, Vehicle, Vehicles}
|
||||
import net.psforever.objects.serverobject.environment.{EnvironmentAttribute, EnvironmentTrait, GantryDenialField, PieceOfEnvironment, interaction}
|
||||
import net.psforever.objects.serverobject.shuttle.OrbitalShuttlePad
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.packet.game.{ChatMsg, PlayerStateShiftMessage, ShiftState}
|
||||
import net.psforever.services.Service
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import net.psforever.objects.sourcing.SourceEntry
|
|||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.vital.environment.EnvironmentReason
|
||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import net.psforever.objects.serverobject.environment.interaction.{InteractionWi
|
|||
import net.psforever.objects.serverobject.environment.interaction.common.Watery
|
||||
import net.psforever.objects.serverobject.environment.interaction.common.Watery.OxygenStateTarget
|
||||
import net.psforever.objects.serverobject.environment.{EnvironmentTrait, PieceOfEnvironment, interaction}
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
import net.psforever.types.OxygenState
|
||||
|
||||
|
|
|
|||
|
|
@ -7,83 +7,38 @@ import net.psforever.objects.vital.Vitality
|
|||
import net.psforever.objects.vital.base.DamageResolution
|
||||
import net.psforever.objects.vital.etc.RadiationReason
|
||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.zones.blockmap.SectorPopulation
|
||||
import net.psforever.objects.zones.{InteractsWithZone, Zone, ZoneInteraction, ZoneInteractionType}
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import net.psforever.objects.zones.interaction.{InteractsWithZone, RadiationCloudInteraction, ZoneInteractionType}
|
||||
|
||||
case object RadiationInteraction extends ZoneInteractionType
|
||||
|
||||
/**
|
||||
* This game entity may infrequently test whether it may interact with radiation cloud projectiles
|
||||
* that may be emitted in the game environment for a limited amount of time.
|
||||
*/
|
||||
* This game entity may infrequently test whether it may interact with radiation cloud projectiles
|
||||
* that may be emitted in the game environment for a limited amount of time.
|
||||
* Since the target entity is a player character, it gets tested for its interaction
|
||||
*/
|
||||
class InteractWithRadiationClouds(
|
||||
val range: Float,
|
||||
private val user: Option[Player]
|
||||
) extends ZoneInteraction {
|
||||
/**
|
||||
* radiation clouds that, though detected, are skipped from affecting the target;
|
||||
* in between interaction tests, a memory of the clouds that were tested last are retained and
|
||||
* are excluded from being tested this next time;
|
||||
* clouds that are detected a second time are cleared from the list and are available to be tested next time
|
||||
*/
|
||||
private var skipTargets: List[PlanetSideGUID] = List()
|
||||
|
||||
) extends RadiationCloudInteraction {
|
||||
def Type: ZoneInteractionType = RadiationInteraction
|
||||
|
||||
/**
|
||||
* Wander into a radiation cloud and suffer the consequences.
|
||||
* @param sector the portion of the block map being tested
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit = {
|
||||
target match {
|
||||
case t: Vitality =>
|
||||
val position = target.Position
|
||||
val targetList = List(target)
|
||||
//collect all projectiles in sector/range
|
||||
val projectiles = sector
|
||||
.projectileList
|
||||
.filter { cloud =>
|
||||
val definition = cloud.Definition
|
||||
val radius = definition.DamageRadius
|
||||
definition.radiation_cloud &&
|
||||
Zone.allOnSameSide(cloud, definition, targetList).nonEmpty &&
|
||||
Zone.distanceCheck(target, cloud, radius * radius)
|
||||
}
|
||||
.distinct
|
||||
val notSkipped = projectiles.filterNot { t => skipTargets.contains(t.GUID) }
|
||||
skipTargets = notSkipped.map { _.GUID }
|
||||
if (notSkipped.nonEmpty) {
|
||||
//isolate one of each type of projectile
|
||||
notSkipped
|
||||
.foldLeft(Nil: List[Projectile]) {
|
||||
(acc, next) => if (acc.exists { _.profile == next.profile }) acc else next :: acc
|
||||
}
|
||||
.foreach { projectile =>
|
||||
t.Actor ! Vitality.Damage(
|
||||
DamageInteraction(
|
||||
SourceEntry(target),
|
||||
RadiationReason(
|
||||
ProjectileQuality.modifiers(projectile, DamageResolution.Radiation, t, t.Position, user),
|
||||
t.DamageModel,
|
||||
0f
|
||||
),
|
||||
position
|
||||
).calculate()
|
||||
)
|
||||
}
|
||||
def performInteractionWithTarget(projectiles: List[Projectile], target: InteractsWithZone): Unit = {
|
||||
if (projectiles.nonEmpty) {
|
||||
val position = target.Position
|
||||
projectiles
|
||||
.foreach { projectile =>
|
||||
target.Actor ! Vitality.Damage(
|
||||
DamageInteraction(
|
||||
SourceEntry(target),
|
||||
RadiationReason(
|
||||
ProjectileQuality.modifiers(projectile, DamageResolution.Radiation, target, target.Position, user),
|
||||
target.DamageModel,
|
||||
RadiationCloudInteraction.RadiationShieldingFrom(target)
|
||||
),
|
||||
position
|
||||
).calculate()
|
||||
)
|
||||
}
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Any radiation clouds blocked from being tested should be cleared.
|
||||
* All that can be done is blanking our retained previous effect targets.
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
def resetInteraction(target: InteractsWithZone): Unit = {
|
||||
skipTargets = List()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package net.psforever.objects.ce
|
|||
|
||||
import net.psforever.objects.geometry.d3.VolumetricGeometry
|
||||
import net.psforever.objects.zones.blockmap.SectorPopulation
|
||||
import net.psforever.objects.zones.{InteractsWithZone, ZoneInteraction, ZoneInteractionType}
|
||||
import net.psforever.objects.zones.interaction.{InteractsWithZone, ZoneInteraction, ZoneInteractionType}
|
||||
import net.psforever.objects.{BoomerDeployable, ExplosiveDeployable}
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import net.psforever.objects.GlobalDefinitions
|
|||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.serverobject.turret.auto.{AutomatedTurret, AutomatedTurretBehavior}
|
||||
import net.psforever.objects.zones.blockmap.SectorPopulation
|
||||
import net.psforever.objects.zones.{InteractsWithZone, ZoneInteraction, ZoneInteractionType}
|
||||
import net.psforever.objects.sourcing.SourceUniqueness
|
||||
import net.psforever.objects.zones.interaction.{InteractsWithZone, ZoneInteraction, ZoneInteractionType}
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
case object TurretInteraction extends ZoneInteractionType
|
||||
|
|
|
|||
|
|
@ -4,20 +4,14 @@ package net.psforever.objects.global
|
|||
import net.psforever.objects.GlobalDefinitions
|
||||
import net.psforever.objects.ballistics.{AggravatedDamage, AggravatedInfo, AggravatedTiming, ChargeDamage}
|
||||
import net.psforever.objects.definition.ProjectileDefinition
|
||||
import net.psforever.objects.definition.converter.{
|
||||
LittleBuddyProjectileConverter,
|
||||
ProjectileConverter,
|
||||
RadiationCloudConverter
|
||||
}
|
||||
import net.psforever.objects.definition.converter.{LittleBuddyProjectileConverter, ProjectileConverter, RadiationCloudConverter}
|
||||
import net.psforever.objects.equipment.{ArmorSiphonRepairHost, EffectTarget, TargetValidation}
|
||||
import net.psforever.objects.serverobject.aura.Aura
|
||||
import net.psforever.objects.vital.base.DamageType
|
||||
import net.psforever.objects.vital.damage.{RadialDegrade, SameHit, StandardDamageProfile}
|
||||
import net.psforever.objects.vital.etc.{
|
||||
ArmorSiphonMaxDistanceCutoff,
|
||||
ExplosionDamagesOnlyAbove,
|
||||
InfantryAggravatedRadiation,
|
||||
InfantryAggravatedRadiationBurn
|
||||
ExplosionDamagesOnlyAbove
|
||||
}
|
||||
import net.psforever.objects.vital.projectile._
|
||||
|
||||
|
|
@ -1529,7 +1523,7 @@ object GlobalDefinitionsProjectile {
|
|||
ProjectileDefinition.CalculateDerivedFields(quasar_projectile)
|
||||
|
||||
radiator_cloud.Name = "radiator_cloud"
|
||||
radiator_cloud.Damage0 = 1 //2
|
||||
radiator_cloud.Damage0 = 2
|
||||
radiator_cloud.DamageAtEdge = 1.0f
|
||||
radiator_cloud.DamageRadius = 5f
|
||||
radiator_cloud.DamageToHealthOnly = true
|
||||
|
|
@ -1539,7 +1533,7 @@ object GlobalDefinitionsProjectile {
|
|||
//custom aggravated information
|
||||
radiator_cloud.ProjectileDamageTypeSecondary = DamageType.Aggravated
|
||||
radiator_cloud.Aggravated = AggravatedDamage(
|
||||
AggravatedInfo(DamageType.Splash, 1f, 80),
|
||||
AggravatedInfo(DamageType.Splash, 0f, 80),
|
||||
Aura.None,
|
||||
AggravatedTiming(250, 2),
|
||||
0f,
|
||||
|
|
@ -1552,12 +1546,7 @@ object GlobalDefinitionsProjectile {
|
|||
radiator_cloud.ExistsOnRemoteClients = true
|
||||
radiator_cloud.Packet = radCloudConverter
|
||||
//radiator_cloud.Geometry = GeometryForm.representProjectileBySphere()
|
||||
radiator_cloud.Modifiers = List(
|
||||
MaxDistanceCutoff,
|
||||
InfantryAggravatedRadiation,
|
||||
InfantryAggravatedRadiationBurn,
|
||||
ShieldAgainstRadiation
|
||||
)
|
||||
radiator_cloud.Modifiers = MaxDistanceCutoff
|
||||
|
||||
radiator_grenade_projectile.Name = "radiator_grenade_projectile" // Todo : Radiator damages ?
|
||||
radiator_grenade_projectile.GrenadeProjectile = true //not really, but technically yes
|
||||
|
|
@ -2037,12 +2026,7 @@ object GlobalDefinitionsProjectile {
|
|||
aphelion_plasma_cloud.ExistsOnRemoteClients = true
|
||||
aphelion_plasma_cloud.Packet = radCloudConverter
|
||||
//aphelion_plasma_cloud.Geometry = GeometryForm.representProjectileBySphere()
|
||||
aphelion_plasma_cloud.Modifiers = List( //TODO placeholder values
|
||||
MaxDistanceCutoff,
|
||||
InfantryAggravatedRadiation,
|
||||
InfantryAggravatedRadiationBurn,
|
||||
ShieldAgainstRadiation
|
||||
)
|
||||
aphelion_plasma_cloud.Modifiers = MaxDistanceCutoff
|
||||
|
||||
aphelion_plasma_rocket_projectile.Name = "aphelion_plasma_rocket_projectile"
|
||||
//has property aggravated_damage_max_factor, but it's the aphelion_plasma_cloud that performs aggravated damage
|
||||
|
|
@ -2240,10 +2224,7 @@ object GlobalDefinitionsProjectile {
|
|||
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.Modifiers = List(
|
||||
MaxDistanceCutoff,
|
||||
ShieldAgainstRadiation
|
||||
)
|
||||
peregrine_particle_cannon_radiation_cloud.Modifiers = MaxDistanceCutoff
|
||||
|
||||
peregrine_rocket_pod_projectile.Name = "peregrine_rocket_pod_projectile"
|
||||
peregrine_rocket_pod_projectile.Damage0 = 30
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import net.psforever.objects.serverobject.PlanetSideServerObject
|
|||
import net.psforever.objects.serverobject.environment.{EnvironmentTrait, PieceOfEnvironment}
|
||||
import net.psforever.objects.zones._
|
||||
import net.psforever.objects.zones.blockmap.{BlockMapEntity, SectorGroup, SectorPopulation}
|
||||
import net.psforever.objects.zones.interaction.{InteractsWithZone, ZoneInteraction, ZoneInteractionType}
|
||||
import net.psforever.types.Vector3
|
||||
|
||||
import scala.collection.mutable
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package net.psforever.objects.serverobject.environment.interaction
|
||||
|
||||
import net.psforever.objects.serverobject.environment.{EnvironmentTrait, PieceOfEnvironment}
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
trait InteractionWith {
|
||||
def attribute: EnvironmentTrait
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ package net.psforever.objects.serverobject.environment.interaction
|
|||
import akka.actor.{Actor, ActorRef, Cancellable}
|
||||
import net.psforever.objects.Default
|
||||
import net.psforever.objects.serverobject.environment.EnvironmentTrait
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import net.psforever.objects.serverobject.PlanetSideServerObject
|
|||
import net.psforever.objects.serverobject.environment.interaction.InteractWithEnvironment
|
||||
import net.psforever.objects.serverobject.environment.interaction.common.Watery.OxygenStateTarget
|
||||
import net.psforever.objects.serverobject.environment.{EnvironmentAttribute, EnvironmentTrait, PieceOfEnvironment}
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.types.{OxygenState, PlanetSideGUID}
|
||||
|
||||
trait Watery {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import net.psforever.objects.sourcing.SourceEntry
|
|||
import net.psforever.objects.vital.etc.SuicideReason
|
||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.vital.{IncarnationActivity, Vitality}
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
import scala.annotation.unused
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package net.psforever.objects.serverobject.environment.interaction.common
|
|||
|
||||
import net.psforever.objects.serverobject.environment._
|
||||
import net.psforever.objects.serverobject.environment.interaction.InteractionWith
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
import scala.annotation.unused
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package net.psforever.objects.serverobject.interior
|
|||
|
||||
import net.psforever.objects.avatar.interaction.WithEntrance
|
||||
import net.psforever.objects.serverobject.environment.interaction.InteractWithEnvironment
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
import scala.annotation.unused
|
||||
|
||||
|
|
|
|||
|
|
@ -8,91 +8,43 @@ import net.psforever.objects.vital.base.DamageResolution
|
|||
import net.psforever.objects.vital.etc.RadiationReason
|
||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.vital.resistance.StandardResistanceProfile
|
||||
import net.psforever.objects.zones.blockmap.SectorPopulation
|
||||
import net.psforever.objects.zones.{InteractsWithZone, Zone, ZoneInteraction}
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
import net.psforever.objects.zones.interaction.{InteractsWithZone, RadiationCloudInteraction, ZoneInteractionType}
|
||||
|
||||
/**
|
||||
* This game entity may infrequently test whether it may interact with radiation cloud projectiles
|
||||
* that may be emitted in the game environment for a limited amount of time.
|
||||
* Since the entity in question is a vehicle, the occupants of the vehicle get tested their interaction.
|
||||
* Since the entity in question is mountable, its occupants get tested for their interaction.
|
||||
*/
|
||||
class InteractWithRadiationCloudsSeatedInEntity(
|
||||
private val obj: Mountable with StandardResistanceProfile,
|
||||
val range: Float
|
||||
) extends ZoneInteraction {
|
||||
/**
|
||||
* radiation clouds that, though detected, are skipped from affecting the target;
|
||||
* in between interaction tests, a memory of the clouds that were tested last are retained and
|
||||
* are excluded from being tested this next time;
|
||||
* clouds that are detected a second time are cleared from the list and are available to be tested next time
|
||||
*/
|
||||
private var skipTargets: List[PlanetSideGUID] = List()
|
||||
) extends RadiationCloudInteraction {
|
||||
def Type: ZoneInteractionType = RadiationInMountableInteraction
|
||||
|
||||
def Type: RadiationInMountableInteraction.type = RadiationInMountableInteraction
|
||||
|
||||
/**
|
||||
* Drive into a radiation cloud and all the vehicle's occupants suffer the consequences.
|
||||
* @param sector the portion of the block map being tested
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
override def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit = {
|
||||
val position = target.Position
|
||||
val targetList = List(target)
|
||||
//collect all projectiles in sector/range
|
||||
val projectiles = sector
|
||||
.projectileList
|
||||
.filter { cloud =>
|
||||
val definition = cloud.Definition
|
||||
val radius = definition.DamageRadius
|
||||
definition.radiation_cloud &&
|
||||
Zone.allOnSameSide(cloud, definition, targetList).nonEmpty &&
|
||||
Zone.distanceCheck(target, cloud, radius * radius)
|
||||
}
|
||||
.distinct
|
||||
val notSkipped = projectiles.filterNot { t => skipTargets.contains(t.GUID) }
|
||||
skipTargets = notSkipped.map { _.GUID }
|
||||
if (notSkipped.nonEmpty) {
|
||||
(
|
||||
//isolate one of each type of projectile
|
||||
notSkipped
|
||||
.foldLeft(Nil: List[Projectile]) {
|
||||
(acc, next) => if (acc.exists { _.profile == next.profile }) acc else next :: acc
|
||||
},
|
||||
obj.Seats
|
||||
.values
|
||||
.collect { case seat => seat.occupant }
|
||||
.flatten
|
||||
) match {
|
||||
case (uniqueProjectiles, targets) if uniqueProjectiles.nonEmpty && targets.nonEmpty =>
|
||||
val shielding = obj.RadiationShielding
|
||||
targets.foreach { t =>
|
||||
uniqueProjectiles.foreach { p =>
|
||||
t.Actor ! Vitality.Damage(
|
||||
DamageInteraction(
|
||||
SourceEntry(t),
|
||||
RadiationReason(
|
||||
ProjectileQuality.modifiers(p, DamageResolution.Radiation, t, t.Position, None),
|
||||
t.DamageModel,
|
||||
shielding
|
||||
),
|
||||
position
|
||||
).calculate()
|
||||
)
|
||||
}
|
||||
}
|
||||
case _ => ()
|
||||
def performInteractionWithTarget(projectiles: List[Projectile], target: InteractsWithZone): Unit = {
|
||||
val mountedTargets = obj.Seats
|
||||
.values
|
||||
.collect { case seat => seat.occupant }
|
||||
.flatten
|
||||
if (projectiles.nonEmpty && mountedTargets.nonEmpty) {
|
||||
val position = target.Position
|
||||
val shielding = RadiationCloudInteraction.RadiationShieldingFrom(target)
|
||||
mountedTargets
|
||||
.flatMap(t => projectiles.map(p => (t, p)))
|
||||
.foreach { case (t, p) =>
|
||||
t.Actor ! Vitality.Damage(
|
||||
DamageInteraction(
|
||||
SourceEntry(t),
|
||||
RadiationReason(
|
||||
ProjectileQuality.modifiers(p, DamageResolution.Radiation, t, t.Position, None),
|
||||
t.DamageModel,
|
||||
shielding
|
||||
),
|
||||
position
|
||||
).calculate()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Any radiation clouds blocked from being tested should be cleared.
|
||||
* All that can be done is blanking our retained previous effect targets.
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
def resetInteraction(target: InteractsWithZone): Unit = {
|
||||
skipTargets = List()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
package net.psforever.objects.serverobject.mount
|
||||
|
||||
import net.psforever.objects.zones.ZoneInteractionType
|
||||
import net.psforever.objects.zones.interaction.ZoneInteractionType
|
||||
|
||||
case object RadiationInMountableInteraction extends ZoneInteractionType
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ import net.psforever.objects.sourcing.{PlayerSource, SourceEntry, SourceUniquene
|
|||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.vital.interaction.DamageResult
|
||||
import net.psforever.objects.zones.exp.ToDatabase
|
||||
import net.psforever.objects.zones.{InteractsWithZone, Zone}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.objects.{Default, PlanetSideGameObject, Player}
|
||||
import net.psforever.packet.game.{ChangeFireStateMessage_Start, ChangeFireStateMessage_Stop, ObjectDetectedMessage}
|
||||
import net.psforever.services.Service
|
||||
|
|
|
|||
|
|
@ -4,24 +4,24 @@ package net.psforever.objects.vehicles
|
|||
import net.psforever.objects.Vehicle
|
||||
import net.psforever.objects.serverobject.mount.{InteractWithRadiationCloudsSeatedInEntity, RadiationInMountableInteraction}
|
||||
import net.psforever.objects.zones.blockmap.SectorPopulation
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
/**
|
||||
* This game entity may infrequently test whether it may interact with radiation cloud projectiles
|
||||
* that may be emitted in the game environment for a limited amount of time.
|
||||
* Since the entity in question is a vehicle, the occupants of the vehicle get tested their interaction.
|
||||
*/
|
||||
* This game entity may infrequently test whether it may interact with radiation cloud projectiles
|
||||
* that may be emitted in the game environment for a limited amount of time.
|
||||
* Since the entity in question is a vehicle, the occupants of the vehicle's mounted vehicles get tested for their interaction.
|
||||
*/
|
||||
class InteractWithRadiationCloudsSeatedInVehicle(
|
||||
private val obj: Vehicle,
|
||||
override val range: Float
|
||||
) extends InteractWithRadiationCloudsSeatedInEntity(obj, range) {
|
||||
/**
|
||||
* Drive into a radiation cloud and all the vehicle's occupants suffer the consequences.
|
||||
* @param sector the portion of the block map being tested
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
* Drive into a radiation cloud and all the vehicle's occupants suffer the consequences.
|
||||
* @param sector the portion of the block map being tested
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
override def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit = {
|
||||
super.interaction(sector, target)
|
||||
super.interaction(sector, target) //vehicle is a mountable entity and must call down
|
||||
obj.CargoHolds
|
||||
.values
|
||||
.collect {
|
||||
|
|
@ -30,7 +30,7 @@ class InteractWithRadiationCloudsSeatedInVehicle(
|
|||
target
|
||||
.interaction()
|
||||
.find(_.Type == RadiationInMountableInteraction)
|
||||
.foreach(func => func.interaction(sector, target))
|
||||
.foreach(func => func.interaction(sector, obj))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import net.psforever.objects.Vehicle
|
|||
import net.psforever.objects.avatar.interaction.WithEntrance
|
||||
import net.psforever.objects.serverobject.doors.InteriorDoorPassage
|
||||
import net.psforever.objects.serverobject.environment.PieceOfEnvironment
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
class WithEntranceInVehicle
|
||||
extends WithEntrance() {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import net.psforever.objects.sourcing.SourceEntry
|
|||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.vital.environment.EnvironmentReason
|
||||
import net.psforever.objects.vital.interaction.DamageInteraction
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import net.psforever.objects.serverobject.environment.interaction.common.Watery
|
|||
import net.psforever.objects.serverobject.environment.interaction.common.Watery.OxygenStateTarget
|
||||
import net.psforever.objects.serverobject.environment.{EnvironmentTrait, PieceOfEnvironment, interaction}
|
||||
import net.psforever.objects.vehicles.control.VehicleControl
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.types.OxygenState
|
||||
|
||||
import scala.annotation.unused
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@ import net.psforever.objects.vital.damage.DamageCalculations
|
|||
import net.psforever.objects.vital.prop.DamageProperties
|
||||
import net.psforever.objects.vital.resolution.{DamageAndResistance, DamageResistanceModel}
|
||||
import net.psforever.objects.vital.{NoResistanceSelection, SimpleResolutions}
|
||||
import net.psforever.objects.zones.InteractsWithZone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
|
||||
/**
|
||||
* A wrapper for a "damage source" in damage calculations
|
||||
* that parameterizes information necessary to explain the environment being antagonistic.
|
||||
*
|
||||
* @see `DamageCalculations`
|
||||
* @param body a representative of an element of the environment
|
||||
* @param against for the purposes of damage, what kind of target is being acted upon
|
||||
|
|
|
|||
|
|
@ -333,28 +333,6 @@ case object FlailDistanceDamageBoost extends ProjectileDamageModifiers.Mod {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
case object ShieldAgainstRadiation extends ProjectileDamageModifiers.Mod {
|
||||
def calculate(damage: Int, data: DamageInteraction, cause: ProjectileReason): Int = {
|
||||
if (data.resolution == DamageResolution.Radiation) {
|
||||
data.target match {
|
||||
case p: PlayerSource if p.ExoSuit == ExoSuitType.MAX =>
|
||||
damage - (damage * p.Modifiers.RadiationShielding).toInt
|
||||
case _: PlayerSource =>
|
||||
damage
|
||||
case _ =>
|
||||
0
|
||||
}
|
||||
} else {
|
||||
damage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The Cerberus turret can not target any entities besides flying vehicles.
|
||||
* An exception to this rule, however, happens when retaliating against something that damaged it first. */
|
||||
case object CerberusTurretWrongTarget extends ProjectileDamageModifiers.Mod {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2021 PSForever
|
||||
package net.psforever.objects.zones
|
||||
package net.psforever.objects.zones.interaction
|
||||
|
||||
import net.psforever.objects.definition.ObjectDefinition
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
|
|
@ -72,39 +72,3 @@ trait InteractsWithZone
|
|||
|
||||
override def Definition: ObjectDefinition with VitalityDefinition
|
||||
}
|
||||
|
||||
trait ZoneInteractionType
|
||||
|
||||
/**
|
||||
* The basic behavior of an entity in a zone.
|
||||
* @see `InteractsWithZone`
|
||||
* @see `Zone`
|
||||
*/
|
||||
trait ZoneInteraction {
|
||||
/**
|
||||
* A categorical descriptor for this interaction.
|
||||
*/
|
||||
def Type: ZoneInteractionType
|
||||
|
||||
/**
|
||||
* The anticipated (radial?) distance across which this interaction affects the zone's blockmap.
|
||||
*/
|
||||
def range: Float
|
||||
|
||||
/**
|
||||
* The method by which zone interactions are tested.
|
||||
* How a target tests this interaction with elements of the target's zone.
|
||||
* @param sector the portion of the block map being tested
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit
|
||||
|
||||
/**
|
||||
* Suspend any current interaction procedures.
|
||||
* How the interactions are undone and stability restored to elements engaged with this target,
|
||||
* even if only possible by small measure.
|
||||
* Not all interactions can be reversed.
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
def resetInteraction(target: InteractsWithZone): Unit
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) 2021-2025 PSForever
|
||||
package net.psforever.objects.zones.interaction
|
||||
|
||||
import net.psforever.objects.ballistics.Projectile
|
||||
import net.psforever.objects.definition.ProjectileDefinition
|
||||
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.zones.blockmap.SectorPopulation
|
||||
|
||||
/**
|
||||
* This game entity may infrequently test whether it may interact with radiation cloud projectiles
|
||||
* that may be emitted in the game environment for a limited amount of time.
|
||||
*/
|
||||
trait RadiationCloudInteraction extends ZoneInteraction {
|
||||
/**
|
||||
* radiation clouds that, though detected, are skipped from affecting the target;
|
||||
* in between interaction tests, a memory of the clouds that were tested last are retained and
|
||||
* are excluded from being tested this next time;
|
||||
* clouds that are detected a second time are cleared from the list and are available to be tested next time
|
||||
*/
|
||||
private var damageTypesToSkip: List[ProjectileDefinition] = List()
|
||||
|
||||
/**
|
||||
* Wander into a radiation cloud and suffer the consequences.
|
||||
* @param sector the portion of the block map being tested
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit = {
|
||||
performInteractionWithTarget(uniqueProjectileDamageToTargetInSector(sector, target), target)
|
||||
}
|
||||
|
||||
/**
|
||||
* Any radiation clouds blocked from being tested should be cleared.
|
||||
* All that can be done is blanking our retained previous effect targets.
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
def resetInteraction(target: InteractsWithZone): Unit = {
|
||||
damageTypesToSkip = List()
|
||||
}
|
||||
|
||||
private def uniqueProjectileDamageToTargetInSector(sector: SectorPopulation, target: InteractsWithZone): List[Projectile] = {
|
||||
lazy val targetList = List(target)
|
||||
val projectiles = sector
|
||||
.projectileList
|
||||
.filter { cloud =>
|
||||
val definition = cloud.Definition
|
||||
val radius = definition.DamageRadius
|
||||
definition.radiation_cloud &&
|
||||
Zone.allOnSameSide(cloud, definition, targetList).nonEmpty &&
|
||||
Zone.distanceCheck(target, cloud, radius * radius)
|
||||
}
|
||||
val projectilesToUse = projectiles.filterNot(p => damageTypesToSkip.contains(p.profile)).distinctBy(_.profile)
|
||||
damageTypesToSkip = projectilesToUse.map(_.profile)
|
||||
projectilesToUse
|
||||
}
|
||||
|
||||
def performInteractionWithTarget(projectiles: List[Projectile], target: InteractsWithZone): Unit
|
||||
}
|
||||
|
||||
object RadiationCloudInteraction {
|
||||
def RadiationShieldingFrom(target: InteractsWithZone): Float = {
|
||||
target match {
|
||||
case profile: ResistanceProfile => profile.RadiationShielding
|
||||
case _ => 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) 2021 PSForever
|
||||
package net.psforever.objects.zones.interaction
|
||||
|
||||
import net.psforever.objects.zones.blockmap.SectorPopulation
|
||||
|
||||
trait ZoneInteractionType
|
||||
|
||||
/**
|
||||
* The basic behavior of an entity in a zone.
|
||||
* @see `InteractsWithZone`
|
||||
* @see `Zone`
|
||||
*/
|
||||
trait ZoneInteraction {
|
||||
/**
|
||||
* A categorical descriptor for this interaction.
|
||||
*/
|
||||
def Type: ZoneInteractionType
|
||||
|
||||
/**
|
||||
* The anticipated (radial?) distance across which this interaction affects the zone's blockmap.
|
||||
*/
|
||||
def range: Float
|
||||
|
||||
/**
|
||||
* The method by which zone interactions are tested.
|
||||
* How a target tests this interaction with elements of the target's zone.
|
||||
* @param sector the portion of the block map being tested
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
def interaction(sector: SectorPopulation, target: InteractsWithZone): Unit
|
||||
|
||||
/**
|
||||
* Suspend any current interaction procedures.
|
||||
* How the interactions are undone and stability restored to elements engaged with this target,
|
||||
* even if only possible by small measure.
|
||||
* Not all interactions can be reversed.
|
||||
* @param target the fixed element in this test
|
||||
*/
|
||||
def resetInteraction(target: InteractsWithZone): Unit
|
||||
}
|
||||
|
|
@ -10,7 +10,8 @@ import net.psforever.objects.serverobject.environment.interaction.InteractWithEn
|
|||
import net.psforever.objects.serverobject.llu.CaptureFlag
|
||||
import net.psforever.objects.serverobject.structures.{Building, WarpGate}
|
||||
import net.psforever.objects.serverobject.terminals.capture.CaptureTerminal
|
||||
import net.psforever.objects.zones.{InteractsWithZone, Zone}
|
||||
import net.psforever.objects.zones.Zone
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.packet.game._
|
||||
import net.psforever.services.{Service, ServiceManager}
|
||||
import net.psforever.services.ServiceManager.{Lookup, LookupResult}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ import net.psforever.objects.serverobject.aura.{Aura, AuraEffectBehavior}
|
|||
import net.psforever.objects.serverobject.environment._
|
||||
import net.psforever.objects.serverobject.environment.interaction.RespondsToZoneEnvironment
|
||||
import net.psforever.objects.vital.Vitality
|
||||
import net.psforever.objects.zones.{InteractsWithZone, Zone, ZoneMap}
|
||||
import net.psforever.objects.zones.interaction.InteractsWithZone
|
||||
import net.psforever.objects.zones.{Zone, ZoneMap}
|
||||
import net.psforever.types.{CharacterSex, CharacterVoice, PlanetSideEmpire, PlanetSideGUID, Vector3}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
|
|
|||
Loading…
Reference in a new issue