Skip to content

Commit

Permalink
Implement the new projectile functions (FAForever#5846)
Browse files Browse the repository at this point in the history
  • Loading branch information
Garanas authored Feb 2, 2024
1 parent c723047 commit 39672ba
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 71 deletions.
33 changes: 32 additions & 1 deletion engine/Sim/Projectile.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@ function Projectile:ChangeDetonateBelowHeight(height)
end

--- Change the amount of zig-zag in degrees per second
---
--- You can use `Projectile:GetMaxZigZag()` to retrieve the current zig zag distance.
---@param max number
function Projectile:ChangeMaxZigZag(max)
end

--- Change the frequency of the zig-zag
---
--- You can use `Projectile:GetZigZagFrequency()` to retrieve the current zig zag frequency.
---@param freq number
function Projectile:ChangeZigZagFrequency(freq)
end
Expand All @@ -34,7 +38,7 @@ function Projectile:CreateChildProjectile(blueprint)
end

--- Returns the speed over ticks instead of over seconds. Multiply by 10 to get the (usually) expected speed value
---@return number
---@return number
function Projectile:GetCurrentSpeed()
end

Expand All @@ -43,6 +47,27 @@ end
function Projectile:GetCurrentTargetPosition()
end

--- Returns the position of the current target as separate coordinates.
---@return number # x
---@return number # y
---@return number # z
function Projectile:GetCurrentTargetPositionXYZ()
end

--- Returns the zig zag frequency.
---
--- You can use `Projectile:ChangeMaxZigZag(value)` to change the zig zag frequency.
---@return number
function Projectile:GetZigZagFrequency()
end

--- Returns the zig zag distance.
---
--- You can use `Projectile:ChangeMaxZigZag(value)` to change the zig zag distance.
---@return number
function Projectile:GetMaxZigZag()
end

--- Returns the entity that is responsible for creating this projectile.
---@return Entity | Unit | nil
function Projectile:GetLauncher()
Expand Down Expand Up @@ -118,6 +143,12 @@ end
function Projectile:SetNewTargetGround(location)
end

---@param x number
---@param y number
---@param z number
function Projectile:SetNewTargetGroundXYZ(x, y, z)
end

---
---@param svx number
---@param svy number
Expand Down
164 changes: 94 additions & 70 deletions lua/sim/Projectile.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,46 @@
-- Copyright © 2005 Gas Powered Games, Inc. All rights reserved.
------------------------------------------------------------------

local ProjectileMethods = moho.projectile_methods
local DefaultDamage = import("/lua/sim/defaultdamage.lua")
local Flare = import("/lua/defaultantiprojectile.lua").Flare
local DepthCharge = import("/lua/defaultantiprojectile.lua").DepthCharge

-- upvalue scope for performance
local unpack = unpack
local Damage = Damage
local Random = Random
local IsAlly = IsAlly
local ForkThread = ForkThread
local DamageArea = DamageArea
local IsDestroyed = IsDestroyed
local CreateSplat = CreateSplat
local CreateEmitterAtBone = CreateEmitterAtBone
local CreateEmitterAtEntity = CreateEmitterAtEntity
local EntityCategoryContains = EntityCategoryContains

local ProjectileMethods = moho.projectile_methods
local ProjectileMethodsCreateChildProjectile = ProjectileMethods.CreateChildProjectile
local ProjectileMethodsGetMaxZigZag = ProjectileMethods.GetMaxZigZag
local ProjectileMethodsGetZigZagFrequency = ProjectileMethods.GetZigZagFrequency

local EntityMethods = _G.moho.entity_methods
local EntityGetBlueprint = EntityMethods.GetBlueprint
local EntityGetArmy = EntityMethods.GetArmy
local EntitySetMaxHealth = EntityMethods.SetMaxHealth
local EntitySetHealth = EntityMethods.SetHealth
local EntityGetPositionXYZ = EntityMethods.GetPositionXYZ
local EntityDestroy = EntityMethods.Destroy
local EntityGetOrientation = EntityMethods.GetOrientation

local TrashBag = TrashBag
local TrashBagAdd = TrashBag.Add
local TrashBagDestroy = TrashBag.Destroy

local TableEmpty = table.empty
local TableGetn = table.getn

local MathCos = math.cos
local MathSin = math.sin
-- cache categories computations
local OnImpactDestroyCategories = categories.ANTIMISSILE * categories.ALLPROJECTILES

-- scorch mark interaction
local ScorchSplatTextures = {
Expand Down Expand Up @@ -49,31 +80,6 @@ local OnImpactPreviousZ = 0

local VectorCached = Vector(0, 0, 0)

-- upvalue for performance
local EntityGetBlueprint = _G.moho.entity_methods.GetBlueprint
local EntityGetArmy = _G.moho.entity_methods.GetArmy
local EntitySetMaxHealth = _G.moho.entity_methods.SetMaxHealth
local EntitySetHealth = _G.moho.entity_methods.SetHealth
local EntityGetPositionXYZ = _G.moho.entity_methods.GetPositionXYZ
local EntityDestroy = _G.moho.entity_methods.Destroy

local TrashBag = TrashBag

local TableEmpty = table.empty

local EntityCategoryContains = EntityCategoryContains
local CreateEmitterAtBone = CreateEmitterAtBone
local CreateEmitterAtEntity = CreateEmitterAtEntity
local CreateSplat = CreateSplat
local DamageArea = DamageArea
local Damage = Damage
local Random = Random
local IsAlly = IsAlly
local ForkThread = ForkThread

-- cache categories computations
local OnImpactDestroyCategories = categories.ANTIMISSILE * categories.ALLPROJECTILES

---@class Projectile : moho.projectile_methods, InternalObject
---@field Blueprint ProjectileBlueprint
---@field Army number
Expand Down Expand Up @@ -122,12 +128,13 @@ Projectile = ClassProjectile(ProjectileMethods) {
---@param self Projectile The projectile that we're creating
---@param inWater? boolean Flag to indicate the projectile is in water or not
OnCreate = function(self, inWater)
local blueprint = self:GetBlueprint() --[[@as ProjectileBlueprint]]
local blueprint = EntityGetBlueprint(self) --[[@as ProjectileBlueprint]]
local trash = TrashBag() --[[@as TrashBag]]

self.Blueprint = blueprint
self.Army = self:GetArmy() --[[@as number]]
self.Trash = trash
self.Army = EntityGetArmy(self) --[[@as number]]
self.Launcher = self:GetLauncher() --[[@as Unit]]
self.Trash = TrashBag() --[[@as TrashBag]]

-- set some health, if we have some
local maxHealth = blueprint.Defense.MaxHealth
Expand All @@ -138,7 +145,7 @@ Projectile = ClassProjectile(ProjectileMethods) {

-- do not track target, but track where the target was
if blueprint.Physics.TrackTargetGround then
self.Trash:Add(ForkThread(self.OnTrackTargetGround, self))
TrashBagAdd(trash, ForkThread(self.OnTrackTargetGround, self))
end
end,

Expand Down Expand Up @@ -169,45 +176,37 @@ Projectile = ClassProjectile(ProjectileMethods) {
sz = sz + offset

local dx = sx * (Random() - 0.5) * fuzziness
local dy = (sy + offset) * (Random() - 0.5) * fuzziness + sy/2 + cy
local dy = (sy + offset) * (Random() - 0.5) * fuzziness + sy / 2 + cy
local dz = sz * (Random() - 0.5) * fuzziness + cz
local dw

-- Rotate a vector by a quaternion: q * v * conjugate(q)
-- Supreme Commander quaternions use y,z,x,w!
local ty, tz, tx, tw = unpack(target:GetOrientation())
local ty, tz, tx, tw = unpack(EntityGetOrientation(target))

-- compute the product in a single assignment to not have to use temporary, single-use variables.
dw, dx, dy, dz =
-tx * dx - tz * dy - ty * dz,
tw * dx + tz * dz - ty * dy,
tw * dy + ty * dx - tx * dz,
tw * dz + tx * dy - tz * dx
dw, dx, dy, dz = -tx * dx - tz * dy - ty * dz,
tw * dx + tz * dz - ty * dy,
tw * dy + ty * dx - tx * dz,
tw * dz + tx * dy - tz * dx

tx, tz, ty = -tx, -tz, -ty

-- compute the product in a single assignment to not have to use temporary, single-use variables.
dx, dy, dz =
dw * tx + dx * tw + dy * ty - dz * tz,
dw * tz + dy * tw + dz * tx - dx * ty,
dw * ty + dz * tw + dx * tz - dy * tx
dx, dy, dz = dw * tx + dx * tw + dy * ty - dz * tz,
dw * tz + dy * tw + dz * tx - dx * ty,
dw * ty + dz * tw + dx * tz - dy * tx

local pos = { px + dx, py + dy, pz + dz }
self:SetNewTargetGround(pos)
self:SetNewTargetGroundXYZ(px + dx, py + dy, pz + dz)
else
local pos = self:GetCurrentTargetPosition()
local px, _, pz = self:GetCurrentTargetPositionXYZ()

local physics = self.Blueprint.Physics
local fuzziness = physics.TrackTargetGroundFuzziness or 0.8
local offset = physics.TrackTargetGroundOffset or 0
local dx = (Random() - 0.5) * fuzziness * (1 + offset)
local dz = (Random() - 0.5) * fuzziness * (1 + offset)

pos[1] = pos[1] + dx
pos[3] = pos[3] + dz

pos[2] = GetSurfaceHeight(pos[1], pos[3])
self:SetNewTargetGround(pos)
local tx = px + (Random() - 0.5) * fuzziness * (1 + offset)
local tz = pz + (Random() - 0.5) * fuzziness * (1 + offset)
self:SetNewTargetGroundXYZ(tx, GetSurfaceHeight(tx, tz), tz)
end
end,

Expand Down Expand Up @@ -298,7 +297,7 @@ Projectile = ClassProjectile(ProjectileMethods) {
OnDestroy = function(self)
local trash = self.Trash
if trash then
trash:Destroy()
TrashBagDestroy(trash)
end
end,

Expand Down Expand Up @@ -571,7 +570,7 @@ Projectile = ClassProjectile(ProjectileMethods) {
local trackTarget = bp.TrackTarget
local trackTargetGround = bp.TrackTargetGround
if trackTarget and (not trackTargetGround) then
self.Trash:Add(ForkThread(self.RetargetThread, self))
TrashBagAdd(self.Trash, ForkThread(self.RetargetThread, self))
end
end,

Expand Down Expand Up @@ -935,7 +934,44 @@ Projectile = ClassProjectile(ProjectileMethods) {
end
end,

-- Deprecated functionality
---------------------------------------------------------------------------
--#region C hooks

--- Creates a child projectile that inherits the speed, orientation and launcher of its parent
---@param blueprint BlueprintId
---@return Projectile
CreateChildProjectile = function(self, blueprint)
local childProjectile = ProjectileMethodsCreateChildProjectile(self, blueprint)
childProjectile.Launcher = self.Launcher
return childProjectile
end,

--- Returns the zig zag distance of the projectile.
---@param self Projectile
---@return number
GetMaxZigZag = function(self)
local distance = ProjectileMethodsGetMaxZigZag(self)
if distance == -1 then
distance = self.Blueprint.Physics.MaxZigZag or 0
end

return distance
end,

--- Returns the zig zag frequency of the projectile.
---@param self Projectile
---@return number
GetZigZagFrequency = function(self)
local frequency = ProjectileMethodsGetZigZagFrequency(self)
if frequency == -1 then
frequency = self.Blueprint.Physics.ZigZagFrequency or 0
end

return frequency
end,

---------------------------------------------------------------------------
--#region Deprecated functionality

---@deprecated
---@param self Projectile
Expand Down Expand Up @@ -991,18 +1027,6 @@ Projectile = ClassProjectile(ProjectileMethods) {
return nil
end
end,

---------------------------------------------------------------------------
--#region C hooks

--- Creates a child projectile that inherits the speed, orientation and launcher of its parent
---@param blueprint BlueprintId
---@return Projectile
CreateChildProjectile = function(self, blueprint)
local projectile = ProjectileMethods.CreateChildProjectile(self, blueprint)
projectile.Launcher = self.Launcher
return projectile
end,
}

--- A dummy projectile that solely inherits what it needs. Useful for
Expand Down

0 comments on commit 39672ba

Please sign in to comment.