merge rebase; accommodation for suppressing aura where no aura should be displayed; new radial degrade calculations

This commit is contained in:
FateJH 2020-08-25 01:12:53 -04:00
parent ac5e26f37a
commit e27e827552
7 changed files with 98 additions and 125 deletions

View file

@ -156,4 +156,23 @@ object AggravatedDamage {
vanu_aggravated,
targets
)
def burning(resolution: ProjectileResolution.Value): ProjectileResolution.Value = {
resolution match {
case ProjectileResolution.AggravatedDirect => ProjectileResolution.AggravatedDirectBurn
case ProjectileResolution.AggravatedSplash => ProjectileResolution.AggravatedSplashBurn
case _ => resolution
}
}
def basicDamageType(resolution: ProjectileResolution.Value): DamageType.Value = {
resolution match {
case ProjectileResolution.AggravatedDirect | ProjectileResolution.AggravatedDirectBurn =>
DamageType.Direct
case ProjectileResolution.AggravatedSplash | ProjectileResolution.AggravatedSplashBurn =>
DamageType.Splash
case _ =>
DamageType.None
}
}
}

View file

@ -171,7 +171,7 @@ object AuraEffectBehavior {
override def isCancelled : Boolean = timer.isCancelled
override def cancel: Boolean = timer.cancel
override def cancel(): Boolean = timer.cancel()
}
object Entry {

View file

@ -26,7 +26,8 @@ trait AggravatedBehavior {
projectile.profile.Aggravated match {
case Some(damage)
if projectile.profile.ProjectileDamageTypes.contains(DamageType.Aggravated) &&
damage.effect_type != Aura.Nothing &&
damage.info.exists(_.damage_type == AggravatedDamage.basicDamageType(data.resolution)) &&
damage.effect_type != Aura.Nothing &&
(projectile.quality == ProjectileQuality.AggravatesTarget ||
damage.targets.exists(validation => validation.test(AggravatedObject))) =>
TryAggravationEffectActivate(damage, data)
@ -61,7 +62,7 @@ trait AggravatedBehavior {
private def SetupAggravationEntry(aggravation: AggravatedDamage, data: ResolvedProjectile): Boolean = {
val effect = aggravation.effect_type
aggravation.info.find(_.damage_type == AggravatedBehavior.basicDamageType(data.resolution)) match {
aggravation.info.find(_.damage_type == AggravatedDamage.basicDamageType(data.resolution)) match {
case Some(info) =>
val timing = aggravation.timing
val duration = timing.duration
@ -77,7 +78,6 @@ trait AggravatedBehavior {
case None =>
(1000L, (duration / 1000).toInt)
}
//val leftoverTime = duration - (tick * iterations)
//quality per tick
val totalPower = (duration.toFloat / info.infliction_rate).toInt - 1
val averagePowerPerTick = totalPower.toFloat / iterations
@ -108,7 +108,7 @@ trait AggravatedBehavior {
powerOffset: List[Float]
): AggravatedBehavior.Entry = {
val aggravatedDamageInfo = ResolvedProjectile(
AggravatedBehavior.burning(data.resolution),
AggravatedDamage.burning(data.resolution),
data.projectile,
target,
data.damage_model,
@ -168,7 +168,7 @@ trait AggravatedBehavior {
def CleanupAggravationTimer(id: Long): Unit = {
//remove and cancel timer
aggravationToTimer.remove(id) match {
case Some(timer) => timer.cancel
case Some(timer) => timer.cancel()
case _ => ;
}
}
@ -179,9 +179,9 @@ trait AggravatedBehavior {
}
def EndAllAggravation(): Unit = {
entryIdToEntry.clear
aggravationToTimer.values.foreach { _.cancel }
aggravationToTimer.clear
entryIdToEntry.clear()
aggravationToTimer.values.foreach { _.cancel() }
aggravationToTimer.clear()
}
def AggravatedReaction: Boolean = ongoingAggravated
@ -206,23 +206,4 @@ object AggravatedBehavior {
private case class Entry(id: Long, effect: Aura, retime: Long, data: ResolvedProjectile, qualityPerTick: List[Float])
private case class Aggravate(id: Long, iterations: Int)
private def burning(resolution: ProjectileResolution.Value): ProjectileResolution.Value = {
resolution match {
case ProjectileResolution.AggravatedDirect => ProjectileResolution.AggravatedDirectBurn
case ProjectileResolution.AggravatedSplash => ProjectileResolution.AggravatedSplashBurn
case _ => resolution
}
}
private def basicDamageType(resolution: ProjectileResolution.Value): DamageType.Value = {
resolution match {
case ProjectileResolution.AggravatedDirect | ProjectileResolution.AggravatedDirectBurn =>
DamageType.Direct
case ProjectileResolution.AggravatedSplash | ProjectileResolution.AggravatedSplashBurn =>
DamageType.Splash
case _ =>
DamageType.None
}
}
}

View file

@ -1,26 +1,26 @@
package net.psforever.actors.session
import java.util.concurrent.TimeUnit
import akka.actor.MDCContextAware.Implicits._
//language imports
import akka.actor.typed
import akka.actor.typed.receptionist.Receptionist
import akka.actor.typed.scaladsl.adapter._
import akka.actor.{Actor, ActorRef, Cancellable, MDCContextAware}
import java.util.concurrent.atomic.AtomicInteger
import akka.pattern.ask
import akka.util.Timeout
import java.util.concurrent.TimeUnit
import MDCContextAware.Implicits._
import org.log4s.MDC
import scala.collection.mutable.LongMap
import scala.collection.mutable
import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import scala.util.Success
import scodec.bits.ByteVector
import services.properties.PropertyOverrideManager
import org.joda.time.{LocalDateTime, Period}
import csr.{CSRWarp, CSRZone, Traveler}
import MDCContextAware.Implicits._
import net.psforever.objects.{GlobalDefinitions, _}
import net.psforever.objects.avatar.{Avatar, Certification, DeployableToolbox}
//project imports
import net.psforever.login.{DropCryptoSession, DropSession, HelloFriend, RawPacket}
import net.psforever.login.WorldSession._
import net.psforever.objects._
import net.psforever.objects.avatar.{Certification, DeployableToolbox, FirstTimeEvents}
import net.psforever.objects.avatar.{Avatar, Certification, Cosmetic, DeployableToolbox}
import net.psforever.objects.ballistics._
import net.psforever.objects.ce._
import net.psforever.objects.definition._
@ -29,6 +29,7 @@ import net.psforever.objects.entity.{SimpleWorldEntity, WorldEntity}
import net.psforever.objects.equipment.{EffectTarget, Equipment, FireModeSwitch, JammableUnit}
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
import net.psforever.objects.inventory.{Container, InventoryItem}
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.serverobject.containable.Containable
import net.psforever.objects.serverobject.damage.Damageable
@ -48,7 +49,6 @@ import net.psforever.objects.serverobject.terminals._
import net.psforever.objects.serverobject.tube.SpawnTube
import net.psforever.objects.serverobject.turret.{FacilityTurret, WeaponTurret}
import net.psforever.objects.serverobject.zipline.ZipLinePath
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
import net.psforever.objects.teamwork.Squad
import net.psforever.objects.vehicles._
import net.psforever.objects.vehicles.Utility.InternalTelepad
@ -56,21 +56,12 @@ import net.psforever.objects.vital._
import net.psforever.objects.zones.{Zone, ZoneHotSpotProjector, Zoning}
import net.psforever.packet._
import net.psforever.packet.control._
import net.psforever.packet.game.objectcreate._
import net.psforever.packet.game.{HotSpotInfo => PacketHotSpotInfo, _}
import net.psforever.objects.zones.{InterstellarCluster, Zone, ZoneHotSpotProjector, Zoning}
import net.psforever.packet._
import net.psforever.packet.control._
import net.psforever.packet.game._
import net.psforever.packet.game.objectcreate._
import net.psforever.packet.game.{HotSpotInfo => PacketHotSpotInfo}
import net.psforever.persistence
import net.psforever.types._
import org.log4s.MDC
import scodec.bits.ByteVector
import net.psforever.services.ServiceManager.LookupResult
import net.psforever.services.account.{AccountPersistenceService, PlayerToken, ReceiveAccountData, RetrieveAccountData}
import net.psforever.services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
import net.psforever.services.chat.ChatService
import net.psforever.services.galaxy.{GalaxyAction, GalaxyResponse, GalaxyServiceMessage, GalaxyServiceResponse}
import net.psforever.services.local.support.RouterTelepadActivation
import net.psforever.services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
@ -84,20 +75,8 @@ import net.psforever.services.teamwork.{
}
import net.psforever.services.vehicle.{VehicleAction, VehicleResponse, VehicleServiceMessage, VehicleServiceResponse}
import net.psforever.services.{InterstellarClusterService, RemoverActor, Service, ServiceManager}
import net.psforever.login.{DropCryptoSession, DropSession, HelloFriend, RawPacket}
import net.psforever.types._
import net.psforever.util.{Config, DefinitionUtil}
import net.psforever.login.WorldSession._
import net.psforever.zones.Zones
import net.psforever.services.chat.ChatService
import net.psforever.objects.avatar.Cosmetic
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.util.Success
import akka.actor.typed.scaladsl.adapter._
import akka.pattern.ask
import akka.util.Timeout
import scala.collection.mutable
object SessionActor {
@ -1301,49 +1280,6 @@ class SessionActor extends Actor with MDCContextAware {
taskResolver ! RegisterNewAvatar(player)
}
case msg @ Zoning.InstantAction.Located(zone, _, spawn_point) =>
//in between subsequent reply messages, it does not matter if the destination changes
//so long as there is at least one destination at all (including the fallback)
if (ContemplateZoningResponse(Zoning.InstantAction.Request(player.Faction), cluster)) {
val (pos, ori) = spawn_point.SpecificPoint(player)
SpawnThroughZoningProcess(zone, pos, ori)
} else if (zoningStatus != Zoning.Status.None) {
instantActionFallbackDestination = Some(msg)
}
case Zoning.InstantAction.NotLocated() =>
instantActionFallbackDestination match {
case Some(Zoning.InstantAction.Located(zone, _, spawn_point))
if spawn_point.Owner.Faction == player.Faction && !spawn_point.Offline =>
if (ContemplateZoningResponse(Zoning.InstantAction.Request(player.Faction), cluster)) {
val (pos, ori) = spawn_point.SpecificPoint(player)
SpawnThroughZoningProcess(zone, pos, ori)
} else if (zoningCounter == 0) {
CancelZoningProcessWithReason("@InstantActionNoHotspotsAvailable")
}
case _ =>
//no instant action available
CancelZoningProcessWithReason("@InstantActionNoHotspotsAvailable")
}
case Zoning.Recall.Located(zone, spawn_point) =>
if (ContemplateZoningResponse(Zoning.Recall.Request(player.Faction, zone.Id), cluster)) {
val (pos, ori) = spawn_point.SpecificPoint(player)
SpawnThroughZoningProcess(zone, pos, ori)
}
case Zoning.Recall.Denied(reason) =>
CancelZoningProcessWithReason(s"@norecall_sanctuary_$reason", Some(ChatMessageType.CMT_QUIT))
case Zoning.Quit() =>
if (ContemplateZoningResponse(Zoning.Quit(), self)) {
log.info("Good-bye")
ImmediateDisconnect()
}
case ZoningReset() =>
CancelZoningProcess()
case NewPlayerLoaded(tplayer) =>
//new zone
log.info(s"Player ${tplayer.Name} has been loaded")
@ -3792,7 +3728,7 @@ class SessionActor extends Actor with MDCContextAware {
}
}
continent.VehicleEvents ! VehicleServiceMessage(
continent.Id,
continent.id,
VehicleAction.UpdateAmsSpawnPoint(continent)
)
upstreamMessageCount = 0
@ -7753,7 +7689,8 @@ class SessionActor extends Actor with MDCContextAware {
val outProjectile = if(projectile.profile.ProjectileDamageTypes.contains(DamageType.Aggravated)) {
val quality = projectile.profile.Aggravated match {
case Some(aggravation)
if aggravation.targets.exists(validation => validation.test(target)) =>
if aggravation.targets.exists(validation => validation.test(target)) &&
aggravation.info.exists(_.damage_type == AggravatedDamage.basicDamageType(resolution)) =>
ProjectileQuality.AggravatesTarget
case _ =>
ProjectileQuality.Normal
@ -8013,12 +7950,12 @@ class SessionActor extends Actor with MDCContextAware {
* @return `true`, if the desired certification requirements are met; `false`, otherwise
*/
def ConstructionItemPermissionComparison(
sample: Set[CertificationType.Value],
test: Set[CertificationType.Value]
sample: Set[Certification],
test: Set[Certification]
): Boolean = {
import CertificationType._
val engineeringCerts: Set[CertificationType.Value] = Set(AssaultEngineering, FortificationEngineering)
val testDiff: Set[CertificationType.Value] = test diff (engineeringCerts ++ Set(AdvancedEngineering))
import Certification._
val engineeringCerts: Set[Certification] = Set(AssaultEngineering, FortificationEngineering)
val testDiff: Set[Certification] = test diff (engineeringCerts ++ Set(AdvancedEngineering))
//substitute `AssaultEngineering` and `FortificationEngineering` for `AdvancedEngineering`
val sampleIntersect = if (sample contains AdvancedEngineering) {
engineeringCerts
@ -8602,7 +8539,7 @@ class SessionActor extends Actor with MDCContextAware {
) {
//do not delete if vehicle has passengers or cargo
continent.VehicleEvents ! VehicleServiceMessage(
continent.Id,
continent.id,
VehicleAction.UnloadVehicle(pguid, continent, vehicle, topLevel)
)
None
@ -9438,7 +9375,7 @@ class SessionActor extends Actor with MDCContextAware {
)
taskResolver ! (if (projectile.HasGUID) {
continent.AvatarEvents ! AvatarServiceMessage(
continent.Id,
continent.id,
AvatarAction.ProjectileExplodes(
player.GUID,
projectile.GUID,

View file

@ -3918,7 +3918,11 @@ object GlobalDefinitions {
2000,
0f,
true,
List(TargetValidation(EffectTarget.Category.Aircraft, EffectTarget.Validation.Aircraft))
List(
TargetValidation(EffectTarget.Category.Player, EffectTarget.Validation.Player),
TargetValidation(EffectTarget.Category.Vehicle, EffectTarget.Validation.Vehicle),
TargetValidation(EffectTarget.Category.Turret, EffectTarget.Validation.Turret)
)
)
starfire_projectile.InitialVelocity = 45
starfire_projectile.Lifespan = 7.8f

View file

@ -16,33 +16,68 @@ class ProjectileDefinition(objectId: Int)
with JammingUnit
with StandardDamageProfile
with DamageModifiers {
/** ascertain that this object is a valid projectile type */
private val projectileType: Projectiles.Value = Projectiles(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) */
private var accelerationUntil: Float = 0f
/** the type of damage that the projectile causes */
private var damageType: DamageType.Value = DamageType.None
/** an auxillary type of damage that the projectile causes */
private var damageTypeSecondary: DamageType.Value = DamageType.None
/** against Infantry targets, this projectile does not do armor damage */
private var damageToHealthOnly: Boolean = false
/** number of seconds before an airborne projectile's damage begins to degrade (s) */
private var degradeDelay: Float = 1f
/** the rate of degrade of projectile damage after the degrade delay */
private var degradeMultiplier: Float = 1f
/** the out-of-the-muzzle speed of a projectile (m/s) */
private var initialVelocity: Int = 1
/** for how long the projectile exists (s) */
private var lifespan: Float = 1f
/** for radial damage, how much damage has been lost the further away from the impact point (m) */
private var damageAtEdge: Float = 1f
/** for radial damage, the radial distance of the explosion effect (m) */
private var damageRadius: Float = 1f
/** for lashing damage, how far away a target will be affected by the projectile (m) */
private var lashRadius : Float = 0f
/** use a specific modifier as a part of damage calculations */
private var useDamage1Subtract: Boolean = false
private var existsOnRemoteClients: Boolean = false //`true` spawns a server-managed object
private var remoteClientData: (Int, Int) =
(0, 0) //artificial values; for ObjectCreateMessage packet (oicw_little_buddy is undefined)
/** the projectile is represented by a server-side entity
* that is updated by the projectile owner
* and transmitted to all projectile observers;
* `true` spawns a server-managed object */
private var existsOnRemoteClients: Boolean = false
/** the values used by the `ObjectCreateMessage` packet for construction of the server-managed projectile
* `0, 0` are artificial values;
* the oicw_little_buddy is undefined for these values */
private var remoteClientData: (Int, Int) = (0, 0)
/** some other entity confers projectile damage;
* a set value should not `None` and not `0` but is preferred to be the damager's uid */
private var damageProxy: Option[Int] = None
/** this projectile follows its target, after a fashion */
private var autoLock: Boolean = false
/** na;
* currently used with jammer properties only */
private var additionalEffect: Boolean = false
/** the projectile tries to confer the jammered status effect to its target(s) */
private var jammerProjectile: Boolean = false
/** projectile takes the form of a type of "grenade";
* grenades arc with gravity rather than travel in a relatively straight path */
private var grenade_projectile : Boolean = false
/** projectile tries to confers aggravated damage burn to its target */
private var aggravated_damage : Option[AggravatedDamage] = None
//derived calculations
/** the calculated distance at which the projectile have traveled far enough to despawn (m);
* typically handled as the projectile no longer performing damage;
* occasionally, this value is purely mathematical as opposed to realistic, e.g., the melee weapons */
private var distanceMax: Float = 0f
/** how far the projectile will travel while accelerating (m) */
private var distanceFromAcceleration: Float = 0f
/** how far the projectile will travel while no degrading (m) */
private var distanceNoDegrade: Float = 0f
/** after acceleration, if any, what is the final speed of the projectile (m/s) */
private var finalVelocity: Float = 0f
Name = "projectile"
Modifiers = DamageModifiers.DistanceDegrade

View file

@ -97,14 +97,11 @@ object DamageModifiers {
def Calculate: DamageModifiers.Format = function
private def function(damage: Int, data: ResolvedProjectile): Int = {
val projectile = data.projectile
val profile = projectile.profile
val profile = data.projectile.profile
val distance = Vector3.Distance(data.hit_pos, data.target.Position)
val radius = profile.DamageRadius
if (distance <= radius) {
val base: Float = profile.DamageAtEdge
val degrade: Float = (1 - base) * ((radius - distance) / radius) + base
(damage * degrade).toInt
damage * (1f - (profile.DamageAtEdge * distance / radius)).toInt
} else {
0
}