mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-04-29 16:25:30 +00:00
merge rebase; accommodation for suppressing aura where no aura should be displayed; new radial degrade calculations
This commit is contained in:
parent
ac5e26f37a
commit
e27e827552
7 changed files with 98 additions and 125 deletions
|
|
@ -156,4 +156,23 @@ object AggravatedDamage {
|
||||||
vanu_aggravated,
|
vanu_aggravated,
|
||||||
targets
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ object AuraEffectBehavior {
|
||||||
|
|
||||||
override def isCancelled : Boolean = timer.isCancelled
|
override def isCancelled : Boolean = timer.isCancelled
|
||||||
|
|
||||||
override def cancel: Boolean = timer.cancel
|
override def cancel(): Boolean = timer.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
object Entry {
|
object Entry {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ trait AggravatedBehavior {
|
||||||
projectile.profile.Aggravated match {
|
projectile.profile.Aggravated match {
|
||||||
case Some(damage)
|
case Some(damage)
|
||||||
if projectile.profile.ProjectileDamageTypes.contains(DamageType.Aggravated) &&
|
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 ||
|
(projectile.quality == ProjectileQuality.AggravatesTarget ||
|
||||||
damage.targets.exists(validation => validation.test(AggravatedObject))) =>
|
damage.targets.exists(validation => validation.test(AggravatedObject))) =>
|
||||||
TryAggravationEffectActivate(damage, data)
|
TryAggravationEffectActivate(damage, data)
|
||||||
|
|
@ -61,7 +62,7 @@ trait AggravatedBehavior {
|
||||||
|
|
||||||
private def SetupAggravationEntry(aggravation: AggravatedDamage, data: ResolvedProjectile): Boolean = {
|
private def SetupAggravationEntry(aggravation: AggravatedDamage, data: ResolvedProjectile): Boolean = {
|
||||||
val effect = aggravation.effect_type
|
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) =>
|
case Some(info) =>
|
||||||
val timing = aggravation.timing
|
val timing = aggravation.timing
|
||||||
val duration = timing.duration
|
val duration = timing.duration
|
||||||
|
|
@ -77,7 +78,6 @@ trait AggravatedBehavior {
|
||||||
case None =>
|
case None =>
|
||||||
(1000L, (duration / 1000).toInt)
|
(1000L, (duration / 1000).toInt)
|
||||||
}
|
}
|
||||||
//val leftoverTime = duration - (tick * iterations)
|
|
||||||
//quality per tick
|
//quality per tick
|
||||||
val totalPower = (duration.toFloat / info.infliction_rate).toInt - 1
|
val totalPower = (duration.toFloat / info.infliction_rate).toInt - 1
|
||||||
val averagePowerPerTick = totalPower.toFloat / iterations
|
val averagePowerPerTick = totalPower.toFloat / iterations
|
||||||
|
|
@ -108,7 +108,7 @@ trait AggravatedBehavior {
|
||||||
powerOffset: List[Float]
|
powerOffset: List[Float]
|
||||||
): AggravatedBehavior.Entry = {
|
): AggravatedBehavior.Entry = {
|
||||||
val aggravatedDamageInfo = ResolvedProjectile(
|
val aggravatedDamageInfo = ResolvedProjectile(
|
||||||
AggravatedBehavior.burning(data.resolution),
|
AggravatedDamage.burning(data.resolution),
|
||||||
data.projectile,
|
data.projectile,
|
||||||
target,
|
target,
|
||||||
data.damage_model,
|
data.damage_model,
|
||||||
|
|
@ -168,7 +168,7 @@ trait AggravatedBehavior {
|
||||||
def CleanupAggravationTimer(id: Long): Unit = {
|
def CleanupAggravationTimer(id: Long): Unit = {
|
||||||
//remove and cancel timer
|
//remove and cancel timer
|
||||||
aggravationToTimer.remove(id) match {
|
aggravationToTimer.remove(id) match {
|
||||||
case Some(timer) => timer.cancel
|
case Some(timer) => timer.cancel()
|
||||||
case _ => ;
|
case _ => ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,9 +179,9 @@ trait AggravatedBehavior {
|
||||||
}
|
}
|
||||||
|
|
||||||
def EndAllAggravation(): Unit = {
|
def EndAllAggravation(): Unit = {
|
||||||
entryIdToEntry.clear
|
entryIdToEntry.clear()
|
||||||
aggravationToTimer.values.foreach { _.cancel }
|
aggravationToTimer.values.foreach { _.cancel() }
|
||||||
aggravationToTimer.clear
|
aggravationToTimer.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
def AggravatedReaction: Boolean = ongoingAggravated
|
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 Entry(id: Long, effect: Aura, retime: Long, data: ResolvedProjectile, qualityPerTick: List[Float])
|
||||||
|
|
||||||
private case class Aggravate(id: Long, iterations: Int)
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,26 @@
|
||||||
package net.psforever.actors.session
|
package net.psforever.actors.session
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit
|
//language imports
|
||||||
import akka.actor.MDCContextAware.Implicits._
|
|
||||||
import akka.actor.typed
|
import akka.actor.typed
|
||||||
import akka.actor.typed.receptionist.Receptionist
|
import akka.actor.typed.receptionist.Receptionist
|
||||||
|
import akka.actor.typed.scaladsl.adapter._
|
||||||
import akka.actor.{Actor, ActorRef, Cancellable, MDCContextAware}
|
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 org.log4s.MDC
|
||||||
import scala.collection.mutable.LongMap
|
import scala.collection.mutable
|
||||||
import scala.concurrent.{Await, Future}
|
import scala.concurrent.{Await, Future}
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
import scala.util.{Failure, Success}
|
import scala.util.Success
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
import services.properties.PropertyOverrideManager
|
//project imports
|
||||||
import org.joda.time.{LocalDateTime, Period}
|
import net.psforever.login.{DropCryptoSession, DropSession, HelloFriend, RawPacket}
|
||||||
import csr.{CSRWarp, CSRZone, Traveler}
|
import net.psforever.login.WorldSession._
|
||||||
import MDCContextAware.Implicits._
|
|
||||||
import net.psforever.objects.{GlobalDefinitions, _}
|
|
||||||
import net.psforever.objects.avatar.{Avatar, Certification, DeployableToolbox}
|
|
||||||
import net.psforever.objects._
|
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.ballistics._
|
||||||
import net.psforever.objects.ce._
|
import net.psforever.objects.ce._
|
||||||
import net.psforever.objects.definition._
|
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.equipment.{EffectTarget, Equipment, FireModeSwitch, JammableUnit}
|
||||||
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
|
import net.psforever.objects.guid.{GUIDTask, Task, TaskResolver}
|
||||||
import net.psforever.objects.inventory.{Container, InventoryItem}
|
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.affinity.FactionAffinity
|
||||||
import net.psforever.objects.serverobject.containable.Containable
|
import net.psforever.objects.serverobject.containable.Containable
|
||||||
import net.psforever.objects.serverobject.damage.Damageable
|
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.tube.SpawnTube
|
||||||
import net.psforever.objects.serverobject.turret.{FacilityTurret, WeaponTurret}
|
import net.psforever.objects.serverobject.turret.{FacilityTurret, WeaponTurret}
|
||||||
import net.psforever.objects.serverobject.zipline.ZipLinePath
|
import net.psforever.objects.serverobject.zipline.ZipLinePath
|
||||||
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
|
||||||
import net.psforever.objects.teamwork.Squad
|
import net.psforever.objects.teamwork.Squad
|
||||||
import net.psforever.objects.vehicles._
|
import net.psforever.objects.vehicles._
|
||||||
import net.psforever.objects.vehicles.Utility.InternalTelepad
|
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.objects.zones.{Zone, ZoneHotSpotProjector, Zoning}
|
||||||
import net.psforever.packet._
|
import net.psforever.packet._
|
||||||
import net.psforever.packet.control._
|
import net.psforever.packet.control._
|
||||||
import net.psforever.packet.game.objectcreate._
|
|
||||||
import net.psforever.packet.game.{HotSpotInfo => PacketHotSpotInfo, _}
|
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.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.ServiceManager.LookupResult
|
||||||
import net.psforever.services.account.{AccountPersistenceService, PlayerToken, ReceiveAccountData, RetrieveAccountData}
|
import net.psforever.services.account.{AccountPersistenceService, PlayerToken, ReceiveAccountData, RetrieveAccountData}
|
||||||
import net.psforever.services.avatar.{AvatarAction, AvatarResponse, AvatarServiceMessage, AvatarServiceResponse}
|
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.galaxy.{GalaxyAction, GalaxyResponse, GalaxyServiceMessage, GalaxyServiceResponse}
|
||||||
import net.psforever.services.local.support.RouterTelepadActivation
|
import net.psforever.services.local.support.RouterTelepadActivation
|
||||||
import net.psforever.services.local.{LocalAction, LocalResponse, LocalServiceMessage, LocalServiceResponse}
|
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.vehicle.{VehicleAction, VehicleResponse, VehicleServiceMessage, VehicleServiceResponse}
|
||||||
import net.psforever.services.{InterstellarClusterService, RemoverActor, Service, ServiceManager}
|
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.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 {
|
object SessionActor {
|
||||||
|
|
||||||
|
|
@ -1301,49 +1280,6 @@ class SessionActor extends Actor with MDCContextAware {
|
||||||
taskResolver ! RegisterNewAvatar(player)
|
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) =>
|
case NewPlayerLoaded(tplayer) =>
|
||||||
//new zone
|
//new zone
|
||||||
log.info(s"Player ${tplayer.Name} has been loaded")
|
log.info(s"Player ${tplayer.Name} has been loaded")
|
||||||
|
|
@ -3792,7 +3728,7 @@ class SessionActor extends Actor with MDCContextAware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continent.VehicleEvents ! VehicleServiceMessage(
|
continent.VehicleEvents ! VehicleServiceMessage(
|
||||||
continent.Id,
|
continent.id,
|
||||||
VehicleAction.UpdateAmsSpawnPoint(continent)
|
VehicleAction.UpdateAmsSpawnPoint(continent)
|
||||||
)
|
)
|
||||||
upstreamMessageCount = 0
|
upstreamMessageCount = 0
|
||||||
|
|
@ -7753,7 +7689,8 @@ class SessionActor extends Actor with MDCContextAware {
|
||||||
val outProjectile = if(projectile.profile.ProjectileDamageTypes.contains(DamageType.Aggravated)) {
|
val outProjectile = if(projectile.profile.ProjectileDamageTypes.contains(DamageType.Aggravated)) {
|
||||||
val quality = projectile.profile.Aggravated match {
|
val quality = projectile.profile.Aggravated match {
|
||||||
case Some(aggravation)
|
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
|
ProjectileQuality.AggravatesTarget
|
||||||
case _ =>
|
case _ =>
|
||||||
ProjectileQuality.Normal
|
ProjectileQuality.Normal
|
||||||
|
|
@ -8013,12 +7950,12 @@ class SessionActor extends Actor with MDCContextAware {
|
||||||
* @return `true`, if the desired certification requirements are met; `false`, otherwise
|
* @return `true`, if the desired certification requirements are met; `false`, otherwise
|
||||||
*/
|
*/
|
||||||
def ConstructionItemPermissionComparison(
|
def ConstructionItemPermissionComparison(
|
||||||
sample: Set[CertificationType.Value],
|
sample: Set[Certification],
|
||||||
test: Set[CertificationType.Value]
|
test: Set[Certification]
|
||||||
): Boolean = {
|
): Boolean = {
|
||||||
import CertificationType._
|
import Certification._
|
||||||
val engineeringCerts: Set[CertificationType.Value] = Set(AssaultEngineering, FortificationEngineering)
|
val engineeringCerts: Set[Certification] = Set(AssaultEngineering, FortificationEngineering)
|
||||||
val testDiff: Set[CertificationType.Value] = test diff (engineeringCerts ++ Set(AdvancedEngineering))
|
val testDiff: Set[Certification] = test diff (engineeringCerts ++ Set(AdvancedEngineering))
|
||||||
//substitute `AssaultEngineering` and `FortificationEngineering` for `AdvancedEngineering`
|
//substitute `AssaultEngineering` and `FortificationEngineering` for `AdvancedEngineering`
|
||||||
val sampleIntersect = if (sample contains AdvancedEngineering) {
|
val sampleIntersect = if (sample contains AdvancedEngineering) {
|
||||||
engineeringCerts
|
engineeringCerts
|
||||||
|
|
@ -8602,7 +8539,7 @@ class SessionActor extends Actor with MDCContextAware {
|
||||||
) {
|
) {
|
||||||
//do not delete if vehicle has passengers or cargo
|
//do not delete if vehicle has passengers or cargo
|
||||||
continent.VehicleEvents ! VehicleServiceMessage(
|
continent.VehicleEvents ! VehicleServiceMessage(
|
||||||
continent.Id,
|
continent.id,
|
||||||
VehicleAction.UnloadVehicle(pguid, continent, vehicle, topLevel)
|
VehicleAction.UnloadVehicle(pguid, continent, vehicle, topLevel)
|
||||||
)
|
)
|
||||||
None
|
None
|
||||||
|
|
@ -9438,7 +9375,7 @@ class SessionActor extends Actor with MDCContextAware {
|
||||||
)
|
)
|
||||||
taskResolver ! (if (projectile.HasGUID) {
|
taskResolver ! (if (projectile.HasGUID) {
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
continent.Id,
|
continent.id,
|
||||||
AvatarAction.ProjectileExplodes(
|
AvatarAction.ProjectileExplodes(
|
||||||
player.GUID,
|
player.GUID,
|
||||||
projectile.GUID,
|
projectile.GUID,
|
||||||
|
|
|
||||||
|
|
@ -3918,7 +3918,11 @@ object GlobalDefinitions {
|
||||||
2000,
|
2000,
|
||||||
0f,
|
0f,
|
||||||
true,
|
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.InitialVelocity = 45
|
||||||
starfire_projectile.Lifespan = 7.8f
|
starfire_projectile.Lifespan = 7.8f
|
||||||
|
|
|
||||||
|
|
@ -16,33 +16,68 @@ class ProjectileDefinition(objectId: Int)
|
||||||
with JammingUnit
|
with JammingUnit
|
||||||
with StandardDamageProfile
|
with StandardDamageProfile
|
||||||
with DamageModifiers {
|
with DamageModifiers {
|
||||||
|
/** ascertain that this object is a valid projectile type */
|
||||||
private val projectileType: Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException
|
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
|
private var acceleration: Int = 0
|
||||||
|
/** when the acceleration stops being applied (s) */
|
||||||
private var accelerationUntil: Float = 0f
|
private var accelerationUntil: Float = 0f
|
||||||
|
/** the type of damage that the projectile causes */
|
||||||
private var damageType: DamageType.Value = DamageType.None
|
private var damageType: DamageType.Value = DamageType.None
|
||||||
|
/** an auxillary type of damage that the projectile causes */
|
||||||
private var damageTypeSecondary: DamageType.Value = DamageType.None
|
private var damageTypeSecondary: DamageType.Value = DamageType.None
|
||||||
|
/** against Infantry targets, this projectile does not do armor damage */
|
||||||
private var damageToHealthOnly: Boolean = false
|
private var damageToHealthOnly: Boolean = false
|
||||||
|
/** number of seconds before an airborne projectile's damage begins to degrade (s) */
|
||||||
private var degradeDelay: Float = 1f
|
private var degradeDelay: Float = 1f
|
||||||
|
/** the rate of degrade of projectile damage after the degrade delay */
|
||||||
private var degradeMultiplier: Float = 1f
|
private var degradeMultiplier: Float = 1f
|
||||||
|
/** the out-of-the-muzzle speed of a projectile (m/s) */
|
||||||
private var initialVelocity: Int = 1
|
private var initialVelocity: Int = 1
|
||||||
|
/** for how long the projectile exists (s) */
|
||||||
private var lifespan: Float = 1f
|
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
|
private var damageAtEdge: Float = 1f
|
||||||
|
/** for radial damage, the radial distance of the explosion effect (m) */
|
||||||
private var damageRadius: Float = 1f
|
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
|
private var lashRadius : Float = 0f
|
||||||
|
/** use a specific modifier as a part of damage calculations */
|
||||||
private var useDamage1Subtract: Boolean = false
|
private var useDamage1Subtract: Boolean = false
|
||||||
private var existsOnRemoteClients: Boolean = false //`true` spawns a server-managed object
|
/** the projectile is represented by a server-side entity
|
||||||
private var remoteClientData: (Int, Int) =
|
* that is updated by the projectile owner
|
||||||
(0, 0) //artificial values; for ObjectCreateMessage packet (oicw_little_buddy is undefined)
|
* 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
|
private var damageProxy: Option[Int] = None
|
||||||
|
/** this projectile follows its target, after a fashion */
|
||||||
private var autoLock: Boolean = false
|
private var autoLock: Boolean = false
|
||||||
|
/** na;
|
||||||
|
* currently used with jammer properties only */
|
||||||
private var additionalEffect: Boolean = false
|
private var additionalEffect: Boolean = false
|
||||||
|
/** the projectile tries to confer the jammered status effect to its target(s) */
|
||||||
private var jammerProjectile: Boolean = false
|
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
|
private var grenade_projectile : Boolean = false
|
||||||
|
/** projectile tries to confers aggravated damage burn to its target */
|
||||||
private var aggravated_damage : Option[AggravatedDamage] = None
|
private var aggravated_damage : Option[AggravatedDamage] = None
|
||||||
//derived calculations
|
//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
|
private var distanceMax: Float = 0f
|
||||||
|
/** how far the projectile will travel while accelerating (m) */
|
||||||
private var distanceFromAcceleration: Float = 0f
|
private var distanceFromAcceleration: Float = 0f
|
||||||
|
/** how far the projectile will travel while no degrading (m) */
|
||||||
private var distanceNoDegrade: Float = 0f
|
private var distanceNoDegrade: Float = 0f
|
||||||
|
/** after acceleration, if any, what is the final speed of the projectile (m/s) */
|
||||||
private var finalVelocity: Float = 0f
|
private var finalVelocity: Float = 0f
|
||||||
Name = "projectile"
|
Name = "projectile"
|
||||||
Modifiers = DamageModifiers.DistanceDegrade
|
Modifiers = DamageModifiers.DistanceDegrade
|
||||||
|
|
|
||||||
|
|
@ -97,14 +97,11 @@ object DamageModifiers {
|
||||||
def Calculate: DamageModifiers.Format = function
|
def Calculate: DamageModifiers.Format = function
|
||||||
|
|
||||||
private def function(damage: Int, data: ResolvedProjectile): Int = {
|
private def function(damage: Int, data: ResolvedProjectile): Int = {
|
||||||
val projectile = data.projectile
|
val profile = data.projectile.profile
|
||||||
val profile = projectile.profile
|
|
||||||
val distance = Vector3.Distance(data.hit_pos, data.target.Position)
|
val distance = Vector3.Distance(data.hit_pos, data.target.Position)
|
||||||
val radius = profile.DamageRadius
|
val radius = profile.DamageRadius
|
||||||
if (distance <= radius) {
|
if (distance <= radius) {
|
||||||
val base: Float = profile.DamageAtEdge
|
damage * (1f - (profile.DamageAtEdge * distance / radius)).toInt
|
||||||
val degrade: Float = (1 - base) * ((radius - distance) / radius) + base
|
|
||||||
(damage * degrade).toInt
|
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue