Skip to content

Commit

Permalink
Salvation Undershoot Fix (FAForever#6185)
Browse files Browse the repository at this point in the history
  • Loading branch information
clyfordv authored May 15, 2024
1 parent ca92d0e commit 3bf055f
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 39 deletions.
1 change: 1 addition & 0 deletions changelog/snippets/fix.6185.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(#6185) Fix Salvation Undershooting - reworks Salvation projectile code to not drop short and use blueprint values for speed and fragment spread
2 changes: 2 additions & 0 deletions engine/Core/Blueprints/ProjectileBlueprint.lua
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,6 @@
---@field RealisticOrdinance boolean
--- bombs that always drop stright down
---@field StraightDownOrdinance boolean
--- for projectiles that spawn spreads of sub-projectiles, how large the impact radius should be
---@field FragmentRadius number
---@field OnLostTargetLifetime? number
1 change: 1 addition & 0 deletions engine/Sim/Projectile.lua
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ end
---@param velX number
---@param velY? number
---@param velZ? number
---@return Projectile
function Projectile:SetVelocity(velX, velY, velZ)
end

Expand Down
2 changes: 1 addition & 1 deletion lua/sim/weapons/DefaultProjectileWeapon.lua
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ DefaultProjectileWeapon = ClassWeapon(Weapon) {
end
self.EconDrain = CreateEconomyEvent(self.unit, nrgReq, 0, time)
self.FirstShot = true
self.unit:ForkThread(self.EconomyDrainThread)
ForkThread(self.EconomyDrainThread, self)
end
end
end,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ ProjectileBlueprint {
Physics = {
DestroyOnWater = true,
DetonateBelowHeight = 45,
InitialSpeed = 14.6,
InitialSpeed = 16,
InitialSpeedRange = 3,
InitialSpeedReduceDistance = 30,
LeadTarget = false,
TurnRate = 360,
VelocityAlign = true,
Fragments = 6,
FragmentId = '/projectiles/AIFFragmentationSensorShell02/AIFFragmentationSensorShell02_proj.bp'
FragmentId = '/projectiles/AIFFragmentationSensorShell02/AIFFragmentationSensorShell02_proj.bp',
FragmentRadius = 7,
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ local EffectTemplate = import("/lua/effecttemplates.lua")
local AArtilleryFragmentationSensorShellProjectile = import("/lua/aeonprojectiles.lua").AArtilleryFragmentationSensorShellProjectile
local RandomFloat = import("/lua/utilities.lua").GetRandomFloat

local MathSqrt = math.sqrt
local MathPow = math.pow
local MathPi = math.pi
local MathSin = math.sin
local MathCos = math.cos

-- Gravitational constant
local g = -4.9

---@class AIFFragmentationSensorShell01 : AArtilleryFragmentationSensorShellProjectile
AIFFragmentationSensorShell01 = ClassProjectile(AArtilleryFragmentationSensorShellProjectile) {

Expand All @@ -23,33 +32,50 @@ AIFFragmentationSensorShell01 = ClassProjectile(AArtilleryFragmentationSensorShe
CreateEmitterAtBone( self, -1, self.Army, v )
end

local detonationHeight = bp.DetonateBelowHeight
local vx, vy, vz = self:GetVelocity()
local velocity = 16
-- Normalize our velocity to ogrids/second
vx, vy, vz = vx*10, vy*10, vz*10
local vMult = bp.InitialSpeed/(10 * self:GetCurrentSpeed())

-- Time to impact (with our reduced speed) is calculated using the quadratic formula and vMult.
local timeToImpact = ((-vy - MathSqrt(MathPow(vy,2) - 2*g*detonationHeight))/g) / vMult

-- Calculate the new ballistic acceleration
local ballisticAcceleration = -2 * (detonationHeight + vy*vMult * timeToImpact) / MathPow(timeToImpact, 2)

-- Update our velocity values to their new lower values
vx, vy, vz = vx*vMult, vy*vMult, vz*vMult

-- One initial projectile following same directional path as the original
self:CreateChildProjectile(bp.FragmentId):SetVelocity(vx,0.8*vy, vz):SetVelocity(velocity):PassDamageData(self.DamageData)
self:CreateChildProjectile(bp.FragmentId)
:SetVelocity(vx, vy, vz)
:SetBallisticAcceleration(ballisticAcceleration).DamageData = self.DamageData

-- Create several other projectiles in a dispersal pattern
local numProjectiles = bp.Fragments - 1
local angle = (2 * math.pi) / numProjectiles
local angle = (2 * MathPi) / numProjectiles
local angleInitial = RandomFloat( 0, angle )

-- Randomization of the spread
local angleVariation = angle * 8 -- Adjusts angle variance spread
local spreadMul = 0.8 -- Adjusts the width of the dispersal

local xVec = 0
local yVec = vy*0.8
local zVec = 0
local spreadMagnitude = bp.FragmentRadius / timeToImpact -- Adjusts the width of the dispersal

local xVec
local zVec
local offsetAngle
local magnitudeVariation

-- Launch projectiles at semi-random angles away from split location
for i = 0, numProjectiles - 1 do
xVec = vx + (math.sin(angleInitial + (i*angle) + RandomFloat(-angleVariation, angleVariation))) * spreadMul
zVec = vz + (math.cos(angleInitial + (i*angle) + RandomFloat(-angleVariation, angleVariation))) * spreadMul
local proj = self:CreateChildProjectile(bp.FragmentId)
proj:SetVelocity(xVec,yVec,zVec)
proj:SetVelocity(velocity)
proj.DamageData = self.DamageData
offsetAngle = angleInitial + (i*angle) + RandomFloat(-angleVariation, angleVariation)
magnitudeVariation = RandomFloat(0.9, 1.1)
xVec = vx + MathSin(offsetAngle) * spreadMagnitude * magnitudeVariation
zVec = vz + MathCos(offsetAngle) * spreadMagnitude * magnitudeVariation
self:CreateChildProjectile(bp.FragmentId)
:SetVelocity(xVec, vy, zVec)
:SetVelocity(bp.InitialSpeed + RandomFloat(-bp.InitialSpeedRange, bp.InitialSpeedRange))
:SetBallisticAcceleration(ballisticAcceleration).DamageData = self.DamageData
end

self:Destroy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,14 @@ ProjectileBlueprint {
Physics = {
DestroyOnWater = true,
DetonateBelowHeight = 24,
InitialSpeed = 14.6,
InitialSpeed = 12,
InitialSpeedRange = 3,
InitialSpeedReduceDistance = 30,
LeadTarget = false,
MaxZigZag = 0,
TurnRate = 360,
VelocityAlign = true,
ZigZagFrequency = 0,
Fragments = 6,
FragmentId = '/projectiles/AIFFragmentationSensorShell03/AIFFragmentationSensorShell03_proj.bp'
FragmentId = '/projectiles/AIFFragmentationSensorShell03/AIFFragmentationSensorShell03_proj.bp',
FragmentRadius = 4,
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@ local EffectTemplate = import("/lua/effecttemplates.lua")
local AArtilleryFragmentationSensorShellProjectile = import("/lua/aeonprojectiles.lua").AArtilleryFragmentationSensorShellProjectile02
local RandomFloat = import("/lua/utilities.lua").GetRandomFloat

local MathSqrt = math.sqrt
local MathPow = math.pow
local MathPi = math.pi
local MathSin = math.sin
local MathCos = math.cos

-- We'll update our ballistic parameters so we still hit the target, but only need
-- to do it once for the subprojectiles, because the velocity delta will be very similar
-- and these won't change much/at all.
local ballisticAcceleration
local vMult
local spreadMagnitude

-- Gravitational constant
local g = -4.9

--- Aeon Quantic Cluster Fragmentation Sensor shell script , Child Projectile after 1st split - XAB2307
---@class AIFFragmentationSensorShell02 : AArtilleryFragmentationSensorShellProjectile02
AIFFragmentationSensorShell02 = ClassProjectile(AArtilleryFragmentationSensorShellProjectile) {
Expand All @@ -25,35 +41,59 @@ AIFFragmentationSensorShell02 = ClassProjectile(AArtilleryFragmentationSensorShe
end

local vx, vy, vz = self:GetVelocity()
local velocity = 12
-- Normalize our velocity to ogrids/second
vx, vy, vz = vx*10, vy*10, vz*10

-- If we haven't already calculated our ballistic acceleration, do so now
-- This shouldn't change much between subprojectiles, so we only need to do it once
if not ballisticAcceleration then
local detonationHeight = bp.DetonateBelowHeight
vMult = bp.InitialSpeed/(10 * self:GetCurrentSpeed())

-- Time to impact (with our reduced speed) is calculated using the quadratic formula and vMult.
local timeToImpact = ((-vy - MathSqrt(MathPow(vy,2) - 2*g*detonationHeight))/g) / vMult

-- Calculate the new ballistic acceleration
ballisticAcceleration = -2 * (detonationHeight + vy*vMult * timeToImpact) / MathPow(timeToImpact, 2)
spreadMagnitude = bp.FragmentRadius / timeToImpact
end

-- Update our velocity values
-- There appears to be inevitable decay with child projectiles, so we give a slight vertical lift to compensate
vx, vy, vz = vx*vMult, vy*vMult + 2, vz*vMult

-- One initial projectile following same directional path as the original
self:CreateChildProjectile(bp.FragmentId):SetVelocity(vx,0.8*vy, vz):SetVelocity(velocity):PassDamageData(self.DamageData)
self:CreateChildProjectile(bp.FragmentId)
:SetVelocity(vx, vy, vz)
:SetVelocity(bp.InitialSpeed)
:SetBallisticAcceleration(ballisticAcceleration).DamageData = self.DamageData

-- Create several other projectiles in a dispersal pattern
local numProjectiles = bp.Fragments - 1
local angle = (2 * math.pi) / numProjectiles
local angle = (2 * MathPi) / numProjectiles
local angleInitial = RandomFloat( 0, angle )

-- Randomization of the spread
local angleVariation = angle * 13 -- Adjusts angle variance spread
local spreadMul = 0.4 -- Adjusts the width of the dispersal
local xVec = 0
local yVec = vy*0.8
local zVec = 0

-- Launch projectiles at semi-random angles away from split location
for i = 0, numProjectiles - 1 do
xVec = vx + (math.sin(angleInitial + (i*angle) + RandomFloat(-angleVariation, angleVariation))) * spreadMul
zVec = vz + (math.cos(angleInitial + (i*angle) + RandomFloat(-angleVariation, angleVariation))) * spreadMul
local proj = self:CreateChildProjectile(bp.FragmentId)
proj:SetVelocity(xVec,yVec,zVec)
proj:SetVelocity(velocity)
proj.DamageData = self.DamageData
end
local xVec
local zVec
local offsetAngle
local magnitudeVariation

-- Launch projectiles at semi-random angles away from split location
for i = 0, numProjectiles - 1 do
offsetAngle = angleInitial + (i*angle) + RandomFloat(-angleVariation, angleVariation)
magnitudeVariation = RandomFloat(0.9, 1.1)
xVec = vx + MathSin(offsetAngle) * spreadMagnitude * magnitudeVariation
zVec = vz + MathCos(offsetAngle) * spreadMagnitude * magnitudeVariation
self:CreateChildProjectile(bp.FragmentId)
:SetVelocity(xVec, vy, zVec)
:SetVelocity(bp.InitialSpeed + RandomFloat(-bp.InitialSpeedRange, bp.InitialSpeedRange))
:SetBallisticAcceleration(ballisticAcceleration).DamageData = self.DamageData
end
self:Destroy()
else
self:DoDamage( self, self.DamageData, TargetEntity)
self:DoDamage(self, self.DamageData, TargetEntity)
self:OnImpactDestroy(TargetType, TargetEntity)
end
end,
Expand Down

0 comments on commit 3bf055f

Please sign in to comment.