mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
Restoring Proxy Damage (#1323)
* adjusted target selection to account for volumetric geometry, hopefully collecting more targets than before; additionally, utilize previously allocated local sector to reduce the target scope; combined mappings to reduce passing over those same results * reactivating maelstrom availability; restore damage dealing potential to the maelstrom grenades; changing damage profile to 'no radial degrade' * reactivating oicw availability; no more discrepancy checks on secondary projectiles; code for maelstrom chain lashing * might have actually fixed oicw little buddies
This commit is contained in:
parent
4d2639b54d
commit
d00fa6a6bf
|
|
@ -55,7 +55,7 @@ add_property lasher holstertime 750
|
||||||
add_property lasher_projectile_ap lasher_projectile_ap false
|
add_property lasher_projectile_ap lasher_projectile_ap false
|
||||||
add_property lasher_projectile_ap lasher_projectile true
|
add_property lasher_projectile_ap lasher_projectile true
|
||||||
add_property lightgunship maxhealth 855
|
add_property lightgunship maxhealth 855
|
||||||
add_property maelstrom allowed false
|
add_property maelstrom allowed true
|
||||||
add_property maelstrom equiptime 1000
|
add_property maelstrom equiptime 1000
|
||||||
add_property maelstrom holstertime 1000
|
add_property maelstrom holstertime 1000
|
||||||
add_property magcutter equiptime 250
|
add_property magcutter equiptime 250
|
||||||
|
|
@ -68,7 +68,7 @@ add_property mini_chaingun equiptime 750
|
||||||
add_property mini_chaingun holstertime 750
|
add_property mini_chaingun holstertime 750
|
||||||
add_property nano_dispenser equiptime 750
|
add_property nano_dispenser equiptime 750
|
||||||
add_property nano_dispenser holstertime 750
|
add_property nano_dispenser holstertime 750
|
||||||
add_property oicw allowed false
|
add_property oicw allowed true
|
||||||
add_property pellet_gun equiptime 600
|
add_property pellet_gun equiptime 600
|
||||||
add_property pellet_gun holstertime 600
|
add_property pellet_gun holstertime 600
|
||||||
add_property peregrine_flight requirement_award0 false
|
add_property peregrine_flight requirement_award0 false
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,10 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
if (list.isEmpty) {
|
if (list.isEmpty) {
|
||||||
ops.handleProxyDamage(pkt.projectile_guid, pkt.hit_info.map(_.hit_pos).getOrElse(Vector3.Zero))
|
ops.handleProxyDamage(pkt.projectile_guid, pkt.hit_info.map(_.hit_pos).getOrElse(Vector3.Zero)).foreach {
|
||||||
|
case (target, proxy, hitPos, _) =>
|
||||||
|
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Hit, hitPos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -182,7 +185,10 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
ops.handleProxyDamage(pkt.projectile_uid, pkt.projectile_pos)
|
ops.handleProxyDamage(pkt.projectile_uid, pkt.projectile_pos).foreach {
|
||||||
|
case (target, proxy, hitPos, _) =>
|
||||||
|
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Splash, hitPos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObjec
|
||||||
import net.psforever.objects.{BoomerDeployable, BoomerTrigger, Player, SpecialEmp, Tool, Vehicle}
|
import net.psforever.objects.{BoomerDeployable, BoomerTrigger, Player, SpecialEmp, Tool, Vehicle}
|
||||||
import net.psforever.objects.vital.base.{DamageResolution, DamageType}
|
import net.psforever.objects.vital.base.{DamageResolution, DamageType}
|
||||||
import net.psforever.objects.zones.{Zone, ZoneProjectile}
|
import net.psforever.objects.zones.{Zone, ZoneProjectile}
|
||||||
import net.psforever.packet.game.{AIDamage, AvatarGrenadeStateMessage, ChangeAmmoMessage, ChangeFireModeMessage, ChangeFireStateMessage_Start, ChangeFireStateMessage_Stop, HitMessage, LashMessage, LongRangeProjectileInfoMessage, OrbitalStrikeWaypointMessage, ProjectileStateMessage, ReloadMessage, SplashHitMessage, TriggerEffectMessage, TriggeredEffectLocation, UplinkRequest, UplinkRequestType, UplinkResponse, WeaponDelayFireMessage, WeaponDryFireMessage, WeaponFireMessage, WeaponLazeTargetPositionMessage}
|
import net.psforever.packet.game.{AIDamage, AvatarGrenadeStateMessage, ChangeAmmoMessage, ChangeFireModeMessage, ChangeFireStateMessage_Start, ChangeFireStateMessage_Stop, HitMessage, LashMessage, LongRangeProjectileInfoMessage, ProjectileStateMessage, ReloadMessage, SplashHitMessage, UplinkRequest, WeaponDelayFireMessage, WeaponDryFireMessage, WeaponFireMessage, WeaponLazeTargetPositionMessage}
|
||||||
import net.psforever.types.{ValidPlanetSideGUID, Vector3}
|
import net.psforever.types.Vector3
|
||||||
|
|
||||||
object WeaponAndProjectileLogic {
|
object WeaponAndProjectileLogic {
|
||||||
def apply(ops: WeaponAndProjectileOperations): WeaponAndProjectileLogic = {
|
def apply(ops: WeaponAndProjectileOperations): WeaponAndProjectileLogic = {
|
||||||
|
|
@ -141,18 +141,19 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
}
|
}
|
||||||
|
|
||||||
def handleDirectHit(pkt: HitMessage): Unit = {
|
def handleDirectHit(pkt: HitMessage): Unit = {
|
||||||
|
val projectileGuid = pkt.projectile_guid
|
||||||
val list = ops.composeDirectDamageInformation(pkt)
|
val list = ops.composeDirectDamageInformation(pkt)
|
||||||
.collect {
|
.collect {
|
||||||
case (target, projectile, hitPos, _) =>
|
case (target, projectile, hitPos, _) =>
|
||||||
ops.checkForHitPositionDiscrepancy(projectile.GUID, hitPos, target)
|
ops.checkForHitPositionDiscrepancy(projectileGuid, hitPos, target)
|
||||||
ops.resolveProjectileInteraction(target, projectile, DamageResolution.Hit, hitPos)
|
ops.resolveProjectileInteraction(target, projectile, DamageResolution.Hit, hitPos)
|
||||||
projectile
|
projectile
|
||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
if (list.isEmpty) {
|
if (list.isEmpty) {
|
||||||
ops.handleProxyDamage(pkt.projectile_guid, pkt.hit_info.map(_.hit_pos).getOrElse(Vector3.Zero)).foreach {
|
ops.handleProxyDamage(projectileGuid, pkt.hit_info.map(_.hit_pos).getOrElse(Vector3.Zero)).foreach {
|
||||||
case (target, proxy, hitPos, _) =>
|
case (target, proxy, hitPos, _) =>
|
||||||
ops.checkForHitPositionDiscrepancy(proxy.GUID, hitPos, target)
|
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Hit, hitPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +180,6 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
}
|
}
|
||||||
others.foreach {
|
others.foreach {
|
||||||
case (target, _, hitPos, _) =>
|
case (target, _, hitPos, _) =>
|
||||||
ops.checkForHitPositionDiscrepancy(projectileGuid, hitPos, target)
|
|
||||||
ops.resolveProjectileInteraction(target, projectile, resolution2, hitPos)
|
ops.resolveProjectileInteraction(target, projectile, resolution2, hitPos)
|
||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
|
|
@ -206,7 +206,7 @@ class WeaponAndProjectileLogic(val ops: WeaponAndProjectileOperations, implicit
|
||||||
//...
|
//...
|
||||||
ops.handleProxyDamage(pkt.projectile_uid, pkt.projectile_pos).foreach {
|
ops.handleProxyDamage(pkt.projectile_uid, pkt.projectile_pos).foreach {
|
||||||
case (target, proxy, hitPos, _) =>
|
case (target, proxy, hitPos, _) =>
|
||||||
ops.checkForHitPositionDiscrepancy(proxy.GUID, hitPos, target)
|
ops.resolveProjectileInteraction(target, proxy, DamageResolution.Splash, hitPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import net.psforever.objects.ballistics.ProjectileQuality
|
||||||
import net.psforever.objects.definition.{ProjectileDefinition, SpecialExoSuitDefinition}
|
import net.psforever.objects.definition.{ProjectileDefinition, SpecialExoSuitDefinition}
|
||||||
import net.psforever.objects.entity.SimpleWorldEntity
|
import net.psforever.objects.entity.SimpleWorldEntity
|
||||||
import net.psforever.objects.equipment.{ChargeFireModeDefinition, Equipment, FireModeSwitch}
|
import net.psforever.objects.equipment.{ChargeFireModeDefinition, Equipment, FireModeSwitch}
|
||||||
|
import net.psforever.objects.geometry.d3.{Point, VolumetricGeometry}
|
||||||
import net.psforever.objects.guid.{GUIDTask, TaskBundle, TaskWorkflow}
|
import net.psforever.objects.guid.{GUIDTask, TaskBundle, TaskWorkflow}
|
||||||
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
import net.psforever.objects.serverobject.{CommonMessages, PlanetSideServerObject}
|
||||||
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
import net.psforever.objects.serverobject.affinity.FactionAffinity
|
||||||
|
|
@ -662,14 +663,9 @@ class WeaponAndProjectileOperations(
|
||||||
projectileGuid: PlanetSideGUID,
|
projectileGuid: PlanetSideGUID,
|
||||||
explosionPosition: Vector3
|
explosionPosition: Vector3
|
||||||
): List[(PlanetSideGameObject with FactionAffinity with Vitality, Projectile, Vector3, Vector3)] = {
|
): List[(PlanetSideGameObject with FactionAffinity with Vitality, Projectile, Vector3, Vector3)] = {
|
||||||
val proxyList = FindProjectileEntry(projectileGuid)
|
FindProjectileEntry(projectileGuid)
|
||||||
.map(projectile => resolveDamageProxy(projectile, projectile.GUID, explosionPosition))
|
.map(projectile => resolveDamageProxy(projectile, projectile.GUID, explosionPosition))
|
||||||
.getOrElse(Nil)
|
.getOrElse(Nil)
|
||||||
proxyList.collectFirst {
|
|
||||||
case (_, proxy, _, _) if proxy.profile == GlobalDefinitions.oicw_little_buddy =>
|
|
||||||
performLittleBuddyExplosion(proxyList.map(_._2))
|
|
||||||
}
|
|
||||||
proxyList
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -695,35 +691,47 @@ class WeaponAndProjectileOperations(
|
||||||
case list =>
|
case list =>
|
||||||
setupDamageProxyLittleBuddy(list, hitPos)
|
setupDamageProxyLittleBuddy(list, hitPos)
|
||||||
WeaponAndProjectileOperations.updateProjectileSidednessAfterHit(continent, projectile, hitPos)
|
WeaponAndProjectileOperations.updateProjectileSidednessAfterHit(continent, projectile, hitPos)
|
||||||
val projectileSide = projectile.WhichSide
|
|
||||||
list.flatMap { proxy =>
|
list.flatMap { proxy =>
|
||||||
if (proxy.profile.ExistsOnRemoteClients) {
|
if (proxy.profile == GlobalDefinitions.oicw_little_buddy) {
|
||||||
proxy.Position = hitPos
|
proxy.WhichSide = projectile.WhichSide
|
||||||
proxy.WhichSide = projectileSide
|
continent.Projectile ! ZoneProjectile.Add(player.GUID, proxy)
|
||||||
|
queueLittleBuddyExplosion(proxy)
|
||||||
|
Nil
|
||||||
|
} else if (proxy.profile.ExistsOnRemoteClients) {
|
||||||
|
proxy.WhichSide = projectile.WhichSide
|
||||||
continent.Projectile ! ZoneProjectile.Add(player.GUID, proxy)
|
continent.Projectile ! ZoneProjectile.Add(player.GUID, proxy)
|
||||||
Nil
|
Nil
|
||||||
} else if (proxy.tool_def == GlobalDefinitions.maelstrom) {
|
} else if (proxy.tool_def == GlobalDefinitions.maelstrom) {
|
||||||
//server-side maelstrom grenade target selection
|
//server-side maelstrom grenade target selection
|
||||||
val radius = proxy.profile.LashRadius * proxy.profile.LashRadius
|
//for convenience purposes, all resulting chain lashing is handled here and resolves in one pass
|
||||||
val targets = Zone.findAllTargets(continent, hitPos, proxy.profile.LashRadius, { _.livePlayerList })
|
proxy.WhichSide = Sidedness.StrictlyBetweenSides
|
||||||
.filter { target =>
|
val radiusSquared = proxy.profile.LashRadius * proxy.profile.LashRadius
|
||||||
Vector3.DistanceSquared(target.Position, hitPos) <= radius
|
var availableTargets = sessionLogic.localSector.livePlayerList
|
||||||
|
var unresolvedChainLashHits: Seq[VolumetricGeometry] = Seq(Point(hitPos))
|
||||||
|
var uniqueChainLashTargets: Seq[(PlanetSideGameObject with FactionAffinity with Vitality, Projectile)] = Seq()
|
||||||
|
while (unresolvedChainLashHits.nonEmpty) {
|
||||||
|
val newChainLashTargets = unresolvedChainLashHits.flatMap { availableCarrier =>
|
||||||
|
val proxyCopy = proxy.copy(shot_origin = availableCarrier.center.asVector3)
|
||||||
|
val (hits, misses) = availableTargets.partition { target => Zone.distanceCheck(availableCarrier, target, radiusSquared) }
|
||||||
|
availableTargets = misses
|
||||||
|
hits.map(t => (t, proxyCopy))
|
||||||
}
|
}
|
||||||
//chainlash is separated from the actual damage application for convenience
|
uniqueChainLashTargets = uniqueChainLashTargets ++ newChainLashTargets
|
||||||
|
unresolvedChainLashHits = newChainLashTargets.map { case (t, _) => t.Definition.Geometry(t) }
|
||||||
|
}
|
||||||
|
val (guidRefs, outputRefs) = uniqueChainLashTargets.map { case (target, proxyCopy) =>
|
||||||
|
(target.GUID, (target, proxyCopy, proxyCopy.shot_origin, target.Position))
|
||||||
|
}.unzip
|
||||||
|
//chain lash effect
|
||||||
continent.AvatarEvents ! AvatarServiceMessage(
|
continent.AvatarEvents ! AvatarServiceMessage(
|
||||||
continent.id,
|
continent.id,
|
||||||
AvatarAction.SendResponse(
|
AvatarAction.SendResponse(
|
||||||
PlanetSideGUID(0),
|
PlanetSideGUID(0),
|
||||||
ChainLashMessage(
|
ChainLashMessage(hitPos, projectile.profile.ObjectId, guidRefs.toList)
|
||||||
hitPos,
|
|
||||||
projectile.profile.ObjectId,
|
|
||||||
targets.map { _.GUID }
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
targets.map { target =>
|
//chain lash target output
|
||||||
(target, proxy, hitPos, target.Position)
|
outputRefs.toList
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
|
|
@ -784,28 +792,12 @@ class WeaponAndProjectileOperations(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def performLittleBuddyExplosion(listOfProjectiles: List[Projectile]): Boolean = {
|
private def queueLittleBuddyExplosion(proxy: Projectile): Boolean = {
|
||||||
val listOfLittleBuddies: List[Projectile] = listOfProjectiles.filter { _.tool_def == GlobalDefinitions.oicw }
|
if (proxy.profile == GlobalDefinitions.oicw_little_buddy) {
|
||||||
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 speed: Float = 144f //speed (packet discovered)
|
val speed: Float = 144f //speed (packet discovered)
|
||||||
val dist: Float = 25 //distance (client defined)
|
val dist: Float = 25 //distance (client defined)
|
||||||
//downwards projectiles
|
val dir = proxy.Velocity.map(_ / speed).getOrElse(Vector3.Zero)
|
||||||
var i: Int = 0
|
queueLittleBuddyDamage(proxy, dir, dist)
|
||||||
listOfLittleBuddies.take(firstHalf).foreach { proxy =>
|
|
||||||
val dir = proxy.Velocity.map(_ / speed).getOrElse(Vector3.Zero)
|
|
||||||
queueLittleBuddyDamage(proxy, dir, dist)
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
//flared out projectiles
|
|
||||||
i = 0
|
|
||||||
listOfLittleBuddies.drop(firstHalf).foreach { proxy =>
|
|
||||||
val dir = proxy.Velocity.map(_ / speed).getOrElse(Vector3.Zero)
|
|
||||||
queueLittleBuddyDamage(proxy, dir, dist)
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|
@ -1569,7 +1561,8 @@ object WeaponAndProjectileOperations {
|
||||||
def updateProjectileSidednessAfterHit(zone: Zone, projectile: Projectile, hitPosition: Vector3): Unit = {
|
def updateProjectileSidednessAfterHit(zone: Zone, projectile: Projectile, hitPosition: Vector3): Unit = {
|
||||||
val origin = projectile.Position
|
val origin = projectile.Position
|
||||||
val distance = Vector3.Magnitude(hitPosition - origin)
|
val distance = Vector3.Magnitude(hitPosition - origin)
|
||||||
zone.blockMap
|
zone
|
||||||
|
.blockMap
|
||||||
.sector(hitPosition, distance)
|
.sector(hitPosition, distance)
|
||||||
.environmentList
|
.environmentList
|
||||||
.collect { case o: InteriorDoorPassage =>
|
.collect { case o: InteriorDoorPassage =>
|
||||||
|
|
@ -1658,13 +1651,15 @@ object WeaponAndProjectileOperations {
|
||||||
* @param source a game object that represents the source of the explosion
|
* @param source a game object that represents the source of the explosion
|
||||||
* @param owner who or what to accredit damage from the explosion to;
|
* @param owner who or what to accredit damage from the explosion to;
|
||||||
* clarifies a normal `SourceEntry(source)` accreditation
|
* clarifies a normal `SourceEntry(source)` accreditation
|
||||||
|
* @return a list of affected entities
|
||||||
|
|
||||||
*/
|
*/
|
||||||
def detonateLittleBuddy(
|
def detonateLittleBuddy(
|
||||||
zone: Zone,
|
zone: Zone,
|
||||||
source: PlanetSideGameObject with FactionAffinity with Vitality,
|
source: PlanetSideGameObject with FactionAffinity with Vitality,
|
||||||
proxy: Projectile,
|
proxy: Projectile,
|
||||||
owner: SourceEntry
|
owner: SourceEntry
|
||||||
)(): Unit = {
|
)(): List[PlanetSideServerObject] = {
|
||||||
Zone.serverSideDamage(zone, source, littleBuddyExplosionDamage(owner, proxy.id, source.Position))
|
Zone.serverSideDamage(zone, source, littleBuddyExplosionDamage(owner, proxy.id, source.Position))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import net.psforever.objects.definition.converter.{
|
||||||
import net.psforever.objects.equipment.{ArmorSiphonRepairHost, EffectTarget, TargetValidation}
|
import net.psforever.objects.equipment.{ArmorSiphonRepairHost, EffectTarget, TargetValidation}
|
||||||
import net.psforever.objects.serverobject.aura.Aura
|
import net.psforever.objects.serverobject.aura.Aura
|
||||||
import net.psforever.objects.vital.base.DamageType
|
import net.psforever.objects.vital.base.DamageType
|
||||||
import net.psforever.objects.vital.damage.{RadialDegrade, StandardDamageProfile}
|
import net.psforever.objects.vital.damage.{RadialDegrade, SameHit, StandardDamageProfile}
|
||||||
import net.psforever.objects.vital.etc.{
|
import net.psforever.objects.vital.etc.{
|
||||||
ArmorSiphonMaxDistanceCutoff,
|
ArmorSiphonMaxDistanceCutoff,
|
||||||
ExplosionDamagesOnlyAbove,
|
ExplosionDamagesOnlyAbove,
|
||||||
|
|
@ -1054,7 +1054,7 @@ object GlobalDefinitionsProjectile {
|
||||||
maelstrom_grenade_projectile.Lifespan = 2f
|
maelstrom_grenade_projectile.Lifespan = 2f
|
||||||
maelstrom_grenade_projectile.DamageProxy = 464 //maelstrom_grenade_damager
|
maelstrom_grenade_projectile.DamageProxy = 464 //maelstrom_grenade_damager
|
||||||
ProjectileDefinition.CalculateDerivedFields(maelstrom_grenade_projectile)
|
ProjectileDefinition.CalculateDerivedFields(maelstrom_grenade_projectile)
|
||||||
maelstrom_grenade_projectile.Modifiers = RadialDegrade
|
maelstrom_grenade_projectile.Modifiers = SameHit
|
||||||
|
|
||||||
maelstrom_grenade_projectile_contact.Name = "maelstrom_grenade_projectile_contact"
|
maelstrom_grenade_projectile_contact.Name = "maelstrom_grenade_projectile_contact"
|
||||||
// TODO for later, maybe : set_resource_parent maelstrom_grenade_projectile_contact game_objects maelstrom_grenade_projectile
|
// TODO for later, maybe : set_resource_parent maelstrom_grenade_projectile_contact game_objects maelstrom_grenade_projectile
|
||||||
|
|
@ -1069,7 +1069,7 @@ object GlobalDefinitionsProjectile {
|
||||||
maelstrom_grenade_projectile_contact.Lifespan = 15f
|
maelstrom_grenade_projectile_contact.Lifespan = 15f
|
||||||
maelstrom_grenade_projectile_contact.DamageProxy = 464 //maelstrom_grenade_damager
|
maelstrom_grenade_projectile_contact.DamageProxy = 464 //maelstrom_grenade_damager
|
||||||
ProjectileDefinition.CalculateDerivedFields(maelstrom_grenade_projectile_contact)
|
ProjectileDefinition.CalculateDerivedFields(maelstrom_grenade_projectile_contact)
|
||||||
maelstrom_grenade_projectile_contact.Modifiers = RadialDegrade
|
maelstrom_grenade_projectile_contact.Modifiers = SameHit
|
||||||
|
|
||||||
maelstrom_stream_projectile.Name = "maelstrom_stream_projectile"
|
maelstrom_stream_projectile.Name = "maelstrom_stream_projectile"
|
||||||
maelstrom_stream_projectile.Damage0 = 15
|
maelstrom_stream_projectile.Damage0 = 15
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue