Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve memory management of treads #4640

Merged
merged 7 commits into from
Jan 29, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lua/AI/AIBuilders/AIAirAttackBuilders.lua
Original file line number Diff line number Diff line change
Expand Up @@ -428,10 +428,10 @@ BuilderGroup {
{ IBC, 'BrainNotLowPowerMode', {} },
{ MIBC, 'ArmyNeedsTransports', {} },
{ EBC, 'GreaterThanEconEfficiencyOverTime', { 0.8, 1.05 }}, --DUNCAN - was 0.9
{ UCBC, 'LocationFactoriesBuildingLess', { 'LocationType', 1, categories.TRANSPORTFOCUS } },
{ UCBC, 'HaveGreaterThanUnitsWithCategory', { 5, categories.AIR * categories.ANTIAIR } }, --DUNCAN - added
{ UCBC, 'HaveGreaterThanUnitsWithCategory', { 8, categories.LAND * (categories.TECH2 + categories.TECH3) } }, --DUNCAN - added
{ UCBC, 'HaveLessThanUnitsWithCategory', { 3 , categories.TRANSPORTFOCUS * categories.TECH2} },
{ UCBC, 'LocationFactoriesBuildingLess', { 'LocationType', 1, categories.TRANSPORTFOCUS } },
},
BuilderType = 'Air',
},
Expand Down
115 changes: 111 additions & 4 deletions lua/defaultcomponents.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@

---@class ShieldEffectsComponent : Unit
---@field Trash TrashBag
---@field ShieldEffectsBag TrashBag
---@field ShieldEffectsBone Bone
---@field ShieldEffectsScale number
ShieldEffectsComponent = ClassSimple {

ShieldEffects = { },
ShieldEffects = {},
ShieldEffectsBone = 0,
ShieldEffectsScale = 1,

Expand All @@ -20,12 +19,120 @@ ShieldEffectsComponent = ClassSimple {
OnShieldEnabled = function(self)
self.ShieldEffectsBag:Destroy()
for _, v in self.ShieldEffects do
self.ShieldEffectsBag:Add(CreateAttachedEmitter(self, self.ShieldEffectsBone, self.Army, v):ScaleEmitter(self.ShieldEffectsScale))
self.ShieldEffectsBag:Add(CreateAttachedEmitter(self, self.ShieldEffectsBone, self.Army, v):ScaleEmitter(self
.ShieldEffectsScale))
end
end,

---@param self ShieldEffectsComponent
OnShieldDisabled = function(self)
self.ShieldEffectsBag:Destroy()
end,
}
}


---@type table<string, number>
local TechToDuration = {
TECH1 = 1,
TECH2 = 2,
TECH3 = 4,
EXPERIMENTAL = 16,
}
local TechToLOD = {
TECH1 = 120,
TECH2 = 180,
TECH3 = 240,
EXPERIMENTAL = 320,
}

---@class TreadComponent
---@field TreadBlueprint UnitBlueprintTreads
---@field TreadSuspend? boolean
---@field TreadThreads? table<number, thread>
TreadComponent = ClassSimple {

---@param self Unit | TreadComponent
OnCreate = function(self)
self.TreadBlueprint = self.Blueprint.Display.MovementEffects.Land.Treads
end,

---@param self Unit | TreadComponent
CreateMovementEffects = function(self)
local treads = self.TreadBlueprint
if treads then
self:AddThreadScroller(1.0, treads.ScrollMultiplier or 0.2)

local treadMarks = treads.TreadMarks
if treadMarks then
self:CreateTreads(treadMarks)
end
end
end,

---@param self Unit | TreadComponent
DestroyMovementEffects = function(self)
local treads = self.TreadBlueprint
if treads then
self:RemoveScroller()

if self.TreadThreads then
self.TreadSuspend = true
end
end
end,

---@param self Unit | TreadComponent
---@param treadsBlueprint UnitBlueprintTreadMarks
CreateTreads = function(self, treadsBlueprint)
local treadThreads = self.TreadThreads
if not treadThreads then
treadThreads = { }

for k, treadBlueprint in treadsBlueprint do
local thread = ForkThread(self.CreateTreadsThread, self, treadBlueprint)
treadThreads[k] = thread
self.Trash:Add(thread)
end

self.TreadThreads = treadThreads
else
self.TreadSuspend = nil
for k, thread in treadThreads do
ResumeThread(thread)
end
end
end,

---@param self Unit | TreadComponent
---@param treads UnitBlueprintTreadMarks
CreateTreadsThread = function(self, treads)

-- to local scope for performance
local WaitTicks = WaitTicks
local CreateSplatOnBone = CreateSplatOnBone
local SuspendCurrentThread = SuspendCurrentThread

local tech = self.Blueprint.TechCategory
local sizeX = treads.TreadMarksSizeX
local sizeZ = treads.TreadMarksSizeZ
local interval = 10 * treads.TreadMarksInterval
local treadOffset = treads.TreadOffset
local treadBone = treads.BoneName or 0
local treadTexture = treads.TreadMarks

local duration = treads.TreadLifeTime or TechToDuration[tech] or 1
local lod = TechToLOD[tech] or 120
local army = self.Army

while true do
while not self.TreadSuspend do
CreateSplatOnBone(self, treadOffset, treadBone, treadTexture, sizeX, sizeZ, lod, duration, army)
WaitTicks(interval)
end

SuspendCurrentThread()
self.TreadSuspend = nil
WaitTicks(interval)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This delays tread creation by one interval any time the unit moves again

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visually that is fine - during the first interval the unit barely moves.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can notice it--it's logically an error, just remove it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adjusted it to waiting just a single tick

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you think you need it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having an infinite loop with no wait statement is asking for trouble.

end
end,
}
42 changes: 37 additions & 5 deletions lua/defaultunits.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ local AdjacencyBuffs = import("/lua/sim/adjacencybuffs.lua")
local FireState = import("/lua/game.lua").FireState
local ScenarioFramework = import("/lua/scenarioframework.lua")

local TreadComponent = import("/lua/defaultcomponents.lua").TreadComponent


local RolloffUnitTable = { nil }
local RolloffPositionTable = { 0, 0, 0 }

Expand Down Expand Up @@ -2213,9 +2216,23 @@ AirTransport = ClassUnit(AirUnit, BaseTransport) {
end,
}

-- LAND UNITS
---@class LandUnit : MobileUnit
LandUnit = ClassUnit(MobileUnit) {}
---@class LandUnit : MobileUnit, TreadComponent
LandUnit = ClassUnit(MobileUnit, TreadComponent) {
OnCreate = function(self)
MobileUnit.OnCreate(self)
TreadComponent.OnCreate(self)
end,

CreateMovementEffects = function(self, effectsBag, typeSuffix, terrainType)
MobileUnit.CreateMovementEffects(self, effectsBag, typeSuffix, terrainType)
TreadComponent.CreateMovementEffects(self)
end,

DestroyMovementEffects = function(self)
MobileUnit.DestroyMovementEffects(self)
TreadComponent.DestroyMovementEffects(self)
end,
}

-- CONSTRUCTION UNITS
---@class ConstructionUnit : MobileUnit
Expand Down Expand Up @@ -2424,8 +2441,23 @@ SlowHoverLandUnit = ClassUnit(HoverLandUnit) {
}

-- AMPHIBIOUS LAND UNITS
---@class AmphibiousLandUnit : MobileUnit
AmphibiousLandUnit = ClassUnit(MobileUnit) { }
---@class AmphibiousLandUnit : MobileUnit, TreadComponent
AmphibiousLandUnit = ClassUnit(MobileUnit, TreadComponent) {
OnCreate = function(self)
MobileUnit.OnCreate(self)
TreadComponent.OnCreate(self)
end,

CreateMovementEffects = function(self, effectsBag, typeSuffix, terrainType)
MobileUnit.CreateMovementEffects(self, effectsBag, typeSuffix, terrainType)
TreadComponent.CreateMovementEffects(self)
end,

DestroyMovementEffects = function(self)
MobileUnit.DestroyMovementEffects(self)
TreadComponent.DestroyMovementEffects(self)
end,
}

---@class SlowAmphibiousLandUnit : AmphibiousLandUnit
SlowAmphibiousLandUnit = ClassUnit(AmphibiousLandUnit) {
Expand Down
1 change: 0 additions & 1 deletion lua/proptree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ Tree = Class(Prop) {
---@param dz number
---@param depth number
FallThread = function(self, dx, dy, dz, depth)

-- make it fall down
local motor = self:FallDown()
motor:Whack(dx, dy, dz, depth, true)
Expand Down
68 changes: 4 additions & 64 deletions lua/sim/Unit.lua
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ local cUnit = moho.unit_methods
---@field EventCallbacks table<string, function[]>
---@field Blueprint UnitBlueprint
---@field EngineFlags any
---@field TerrainType TerrainType
---@field EngineCommandCap? table<string, boolean>
---@field UnitBeingBuilt Unit?
Unit = ClassUnit(moho.unit_methods) {
Expand Down Expand Up @@ -1692,6 +1693,8 @@ Unit = ClassUnit(moho.unit_methods) {
end
end,



--- Called when a unit collides with a projectile to check if the collision is valid
---@param self Unit The unit we're checking the collision for
---@param other Projectile The projectile we're checking the collision with
Expand Down Expand Up @@ -3693,6 +3696,7 @@ Unit = ClassUnit(moho.unit_methods) {
---@param new string
---@param old string
OnTerrainTypeChange = function(self, new, old)
self.TerrainType = new
if self.MovementEffectsExist then
self:DestroyMovementEffects()
self:CreateMovementEffects(self.MovementEffectsBag, nil, new)
Expand Down Expand Up @@ -3814,14 +3818,6 @@ Unit = ClassUnit(moho.unit_methods) {
end
end,

---@param self Unit
---@param pos Vector
---@return TerrainTreadType
GetTTTreadType = function(self, pos)
Garanas marked this conversation as resolved.
Show resolved Hide resolved
local terrainType = GetTerrainType(pos[1], pos[3])
return terrainType.Treads or 'None'
end,

---@param fxType TerrainEffectType
---@param layer Layer
---@param pos Vector
Expand Down Expand Up @@ -3940,12 +3936,6 @@ Unit = ClassUnit(moho.unit_methods) {
bpTable = bpTable[layer]
local effectTypeGroups = bpTable.Effects

if bpTable.Treads then
self:CreateTreads(bpTable.Treads)
else
self:RemoveScroller()
end

if not effectTypeGroups or (effectTypeGroups and (table.empty(effectTypeGroups))) then
if not self.Footfalls and bpTable.Footfall then
WARN('*WARNING: No movement effect groups defined for unit ', repr(self.UnitId), ', Effect groups with bone lists must be defined to play movement effects. Add these to the Display.MovementEffects', layer, '.Effects table in unit blueprint. ')
Expand Down Expand Up @@ -4001,18 +3991,6 @@ Unit = ClassUnit(moho.unit_methods) {
self:ShakeCamera(shake.Radius, shake.MaxShakeEpicenter * 0.25, shake.MinShakeAtRadius * 0.25, 1)
end
end

-- Clean up treads
if self.TreadThreads then
for k, v in self.TreadThreads do
KillThread(v)
end
self.TreadThreads = {}
end

if bpTable[layer].Treads.ScrollTreads then
self:RemoveScroller()
end
end,

---@param self Unit
Expand Down Expand Up @@ -4108,44 +4086,6 @@ Unit = ClassUnit(moho.unit_methods) {
end
end,

---@param self Unit
---@param treads UnitBlueprintTreads
CreateTreads = function(self, treads)
if treads.ScrollTreads then
self:AddThreadScroller(1.0, treads.ScrollMultiplier or 0.2)
end

self.TreadThreads = {}
if treads.TreadMarks then
local type = self:GetTTTreadType(self:GetPosition())
if type ~= 'None' then
for k, v in treads.TreadMarks do
table.insert(self.TreadThreads, self:ForkThread(self.CreateTreadsThread, v, type))
end
end
end
end,

---@param self Unit
---@param treads UnitBlueprintTreadMarks
---@param type string
CreateTreadsThread = function(self, treads, type)
local sizeX = treads.TreadMarksSizeX
local sizeZ = treads.TreadMarksSizeZ
local interval = treads.TreadMarksInterval
local treadOffset = treads.TreadOffset
local treadBone = treads.BoneName or 0
local treadTexture = treads.TreadMarks
local duration = treads.TreadLifeTime or 10

while true do
-- Syntactic reference
-- CreateSplatOnBone(entity, offset, boneName, textureName, sizeX, sizeZ, lodParam, duration, army)
CreateSplatOnBone(self, treadOffset, treadBone, treadTexture, sizeX, sizeZ, 130, duration, self.Army)
WaitSeconds(interval)
end
end,

---@param self Unit
---@param footfall boolean
---@return boolean
Expand Down
4 changes: 2 additions & 2 deletions units/UEL0401/UEL0401_unit.bp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ UnitBlueprint {
TreadMarks = {
{
TreadMarks = 'tank_treads06_albedo',
TreadMarksInterval = 0.6,
TreadMarksInterval = 0.3,
TreadMarksSizeX = 5,
TreadMarksSizeZ = 5.5,
TreadOffset = {
Expand All @@ -249,7 +249,7 @@ UnitBlueprint {
},
{
TreadMarks = 'tank_treads06_albedo',
TreadMarksInterval = 0.6,
TreadMarksInterval = 0.3,
TreadMarksSizeX = 5.5,
TreadMarksSizeZ = 5.5,
TreadOffset = {
Expand Down