Skip to content

Commit

Permalink
rebased
Browse files Browse the repository at this point in the history
Finally this patch will fix the game slowdown on long AI games.
Reason for the slowdown was the engineermanger while ping pong forking functions.
This was causing in the end a engine slowdown a finally a stack buffer overrun.

This patch also stores almost every forked thread to the corresponding unit/weapon,
so it can be destroyed on unit dead to prevent parentless threads.

The transport function is now using surfaceghight for the transportation target
for faster unit drops.

Also fixed an issue where the ACU is not moving on gamestart.
This was caused by the `BlockCommandQueue` from the ACU WarpInAnimation

Changelog:

------------------------------------------------------------------------------------

aiarchetype-managerloader.lua

function ExecutePlan()
-Opt: Storing Forked Thread inside the aiBrain Trashbag for better performance

------------------------------------------------------------------------------------

AIBehaviors.lua

function CommanderThread()
-Opt: Added check for 'BlockCommandQueue' to prevent stucked ACU after WarpInAnimation

function CommanderThreadImproved()
-Opt: Added check for 'BlockCommandQueue' to prevent stucked ACU after WarpInAnimation

function GetClosestShieldProtectingTarget()
-Opt: Added safeguard for dead attacker or target

function CommanderThreadSorian()
-Opt: Added check for 'BlockCommandQueue' to prevent stucked ACU after WarpInAnimation

------------------------------------------------------------------------------------

SorianStrategyBuilders.lua

BuilderGroup 'Sorian Excess Mass Strategy'
-Opt: Storing Forked Thread inside the aiBrain Trashbag for better performance

------------------------------------------------------------------------------------

AttackManager.lua

function FormAttackPlatoon()
-Opt: Storing Forked Thread inside the aiBrain Trashbag for better performance

------------------------------------------------------------------------------------

aiutilities.lua

function UseTransports()
-Opt: Changed command WaitTicks() to coroutine.yield() for better performance
-Opt: Added surfacehight to trasnport location for faster unit unloading

function EngineerTryReclaimCaptureArea()
-Fix: Function now only returns true if we have valid unit for capture

function UseTransports
-Fix: Added IssueClearCommands for transports to prevent flightloops

------------------------------------------------------------------------------------

sorianutilities.lua

function Nuke()
-Opt: Storing Forked Thread inside the aiBrain Trashbag for better performance

------------------------------------------------------------------------------------

aibrain.lua

function AddBuilderManagers()
-Opt: Added a baseType to every expansion for faster expansion count

function GetManagerCount()
-Opt: To count expansions we are now searching for a baseType not 8 x name search

function InitialAIThread
-Fix: Delaying the AI so it can't reclaim the start area before it's cleared from the ACU landing blast.

------------------------------------------------------------------------------------

cybranunits.lua

Class CConstructionEggUnit()
-Opt: Storing Forked Thread inside the Unit Trashbag for better performance

------------------------------------------------------------------------------------

aiattackutilities.lua

function GetBestThreatTarget()
-Fix: changed missplaced variables in GetThreatAtPosition call

------------------------------------------------------------------------------------
defaultunits.lua

function OnPrepareArmToBuild() (ConstructionUnit Class)
-Opt: Storing Forked Thread inside the Unit Trashbag for better performance

function OnPrepareArmToBuild() (CommandUnit Class)
-Opt: Storing Forked Thread inside the Unit Trashbag for better performance

------------------------------------------------------------------------------------

platoon.lua

several functions()
-Opt: Changed command WaitTicks() to coroutine.yield() for better performance

function AssistBody()
-Opt: Moved safeguard for nonexisting platoons at the start of the function

function EngineerBuildAI()
-Opt: Removed old sorianfunction for delaying platoonbuilder
-Fix: Excluded StationAssitPods from building tasks
-Opt: Using now .Location instead of the functioncall :GetLocationCoords()
-Fix: The safeguard at the end of the function is now working

function WatchForNotBuilding()
-Opt: Removed unused unitstate checks

function ProcessBuildCommand()
-Opt: replaced BuildToNormalLocation and NormalToBuildLocation and used numbers directly
-Fix: Units now get capture/reclaim and buildcommands queued instead of looping the ProcessBuildCommand
-Fix: Prevent disbanding a platoon while on a transport

function EngineerBuildAISorian
-Opt: Removed old sorianfunction for delaying platoonbuilder
-Opt: Using now .Location instead of the functioncall :GetLocationCoords()

------------------------------------------------------------------------------------

ScenarioUtilities.lua

function CommanderWarpDelay()
-Opt: Removed BlockCommandQueue for AI brains

------------------------------------------------------------------------------------

EngineerManager.lua

several functions()
-Opt: Changed command WaitTicks() to coroutine.yield() for better performance

function AddUnit()
-Fix: Excluded StationAssitPods from building tasks
-Fix: Changed the logic of forking threads to prevent gameslowdown at +1 hour

function GetNumCategoryBeingBuilt()
-Opt: returning a value directly without defining it local

function TaskFinished()
-Fix: Changed the logic of forking threads to prevent gameslowdown at +1 hour

Removed functions:
EngineerWaiting, InitialWait, DelayAssign, DelayAssignBody
-Fix: Changed the logic of forking threads to prevent gameslowdown at +1 hour

Replaced removed functiosn with new functions:
ForkEngineerTask, DelayAssign, Wait, EngineerWaiting
-Fix: Changed the logic of forking threads to prevent gameslowdown at +1 hour

------------------------------------------------------------------------------------

Unit.lua

function DeathThread()
-Opt: Destroy trashbags only if not already done

function DestroyAllTrashBags()
-New: This function clears all trashbags and unit effects

function OnDestroy()
-New: Destroy trashbags only if not already done inside DeathThread()

function StopRocking()
-Opt: Only kill a thread when it actual exist.

------------------------------------------------------------------------------------

Blueprints.lua

function HandleUnitWithBuildPresets()
-New: Adding SACU presets as unit category for AI builders

------------------------------------------------------------------------------------

CIFArtilleryProton01_script.lua

function OnImpact()
-Opt: Storing Forked Thread inside the Projectile Trashbag for better performance

------------------------------------------------------------------------------------

UEL0001_script.lua

function CreateEnhancement()
-Opt: Storing Forked Thread inside the Unit Trashbag for better performance

------------------------------------------------------------------------------------

UEL0301_script.lua

function CreateEnhancement()
-Opt: Storing Forked Thread inside the Unit Trashbag for better performance

------------------------------------------------------------------------------------

XRB2308_script.lua

function OnStopBeingBuilt()
-Opt: Storing Forked Thread inside the Unit Trashbag for better performance

function StartSinking()
-Opt: Storing Forked Thread inside the Unit Trashbag for better performance

------------------------------------------------------------------------------------

XRB2309_script.lua

function StartSinking()
-Opt: Storing Forked Thread inside the Unit Trashbag for better performance
  • Loading branch information
Uveso authored and shalkya committed Aug 10, 2020
1 parent 37dce80 commit 5c7a7ec
Show file tree
Hide file tree
Showing 19 changed files with 220 additions and 198 deletions.
12 changes: 9 additions & 3 deletions lua/AI/AIBehaviors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ function CommanderThread(cdr, platoon)

-- Call platoon resume building deal...
if not cdr.Dead and cdr:IsIdleState() and not cdr.GoingHome and not cdr:IsUnitState("Building")
and not cdr:IsUnitState("Attacking") and not cdr:IsUnitState("Repairing") and not cdr:IsUnitState("Upgrading") then
and not cdr:IsUnitState("Attacking") and not cdr:IsUnitState("Repairing")
and not cdr:IsUnitState("Upgrading") and not cdr:IsUnitState('BlockCommandQueue') then
if not cdr.EngineerBuildQueue or table.getn(cdr.EngineerBuildQueue) == 0 then
local pool = aiBrain:GetPlatoonUniquelyNamed('ArmyPool')
aiBrain:AssignUnitsToPlatoon(pool, {cdr}, 'Unassigned', 'None')
Expand Down Expand Up @@ -342,7 +343,8 @@ function CommanderThreadImproved(cdr, platoon)
if not cdr.Dead and cdr:IsIdleState() and not cdr.GoingHome and not cdr:IsUnitState("Moving")
and not cdr:IsUnitState("Building") and not cdr:IsUnitState("Guarding")
and not cdr:IsUnitState("Attacking") and not cdr:IsUnitState("Repairing")
and not cdr:IsUnitState("Upgrading") and not cdr:IsUnitState("Enhancing") then
and not cdr:IsUnitState("Upgrading") and not cdr:IsUnitState("Enhancing")
and not cdr:IsUnitState('BlockCommandQueue') then
-- if we have nothing to build...
if not cdr.EngineerBuildQueue or table.getn(cdr.EngineerBuildQueue) == 0 then
-- check if the we have still a platton assigned to the CDR
Expand Down Expand Up @@ -834,6 +836,9 @@ end
-- The shield, else false
-------------------------------------------------------
function GetClosestShieldProtectingTarget(attackingUnit, targetUnit)
if attackingUnit.Dead or targetUnit.Dead then
return false
end
local aiBrain = attackingUnit:GetAIBrain()
local tPos = targetUnit:GetPosition()
local aPos = attackingUnit:GetPosition()
Expand Down Expand Up @@ -2025,7 +2030,8 @@ function CommanderThreadSorian(cdr, platoon)
-- Call platoon resume building deal...
if not cdr.Dead and cdr:IsIdleState() and not cdr.GoingHome and not cdr.Fighting and not cdr.Upgrading and not cdr:IsUnitState("Building")
and not cdr:IsUnitState("Attacking") and not cdr:IsUnitState("Repairing") and not cdr.UnitBeingBuiltBehavior and not cdr:IsUnitState("Upgrading")
and not cdr:IsUnitState("Enhancing") and not (SUtils.XZDistanceTwoVectorsSq(cdr.CDRHome, cdr:GetPosition()) > 100) then
and not cdr:IsUnitState("Enhancing") and not (SUtils.XZDistanceTwoVectorsSq(cdr.CDRHome, cdr:GetPosition()) > 100)
and not cdr:IsUnitState('BlockCommandQueue') then
if not cdr.EngineerBuildQueue or table.getn(cdr.EngineerBuildQueue) == 0 then
local pool = aiBrain:GetPlatoonUniquelyNamed('ArmyPool')
aiBrain:AssignUnitsToPlatoon(pool, {cdr}, 'Unassigned', 'None')
Expand Down
2 changes: 1 addition & 1 deletion lua/AI/AIBuilders/SorianStrategyBuilders.lua
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ BuilderGroup {
if econThread then
KillThread(econThread)
end
econThread = ForkThread(EconWatch, aiBrain)
econThread = aiBrain:ForkThread(EconWatch)
end,
OnStrategyDeactivate = function(self, aiBrain)
Builders[self.BuilderName].Running = false
Expand Down
4 changes: 2 additions & 2 deletions lua/AI/AttackManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ AttackManager = Class({
if v.FormCallbacks then
for cbNum, callback in v.FormCallbacks do
if type(callback) == 'function' then
ForkThread(callback, tempPlatoon)
self.Trash:Add(ForkThread(callback, tempPlatoon))
else
ForkThread(import(callback[1])[callback[2]], tempPlatoon)
self.Trash:Add(ForkThread(import(callback[1])[callback[2]], tempPlatoon))
end
--LOG('*AM DEBUG: AM Master Platoon Form callback: ', repr(callback[2]), ' Builder Named: ', repr(v.BuilderName))
end
Expand Down
6 changes: 3 additions & 3 deletions lua/AI/aiarchetype-managerloader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ function ExecutePlan(aiBrain)
end

if aiBrain.Sorian then
ForkThread(UnitCapWatchThreadSorian, aiBrain)
ForkThread(behaviors.NukeCheck, aiBrain)
aiBrain:ForkThread(UnitCapWatchThreadSorian)
aiBrain:ForkThread(behaviors.NukeCheck)
else
ForkThread(UnitCapWatchThread, aiBrain)
aiBrain:ForkThread(UnitCapWatchThread)
end
end
if aiBrain.PBM then
Expand Down
2 changes: 1 addition & 1 deletion lua/AI/aiattackutilities.lua
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ function GetBestThreatTarget(aiBrain, platoon, bSkipPathability)
# Determine relative strength of platoon compared to enemy threat
local enemyThreat = aiBrain:GetThreatAtPosition({threat[1], 0, threat[2]}, EnemyThreatRings, true, ThreatTable[platoon.MovementLayer] or 'AntiSurface')
if IgnoreCommanderStrength then
enemyThreat = enemyThreat - aiBrain:GetThreatAtPosition({threat[1], EnemyThreatRings, threat[2]}, 1, true, 'Commander')
enemyThreat = enemyThreat - aiBrain:GetThreatAtPosition({threat[1], 0, threat[2]}, EnemyThreatRings, true, 'Commander')
end
#defaults to no threat (threat difference is opposite of platoon threat)
local threatDiff = myThreat - enemyThreat
Expand Down
21 changes: 14 additions & 7 deletions lua/AI/aiutilities.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,8 @@ function UseTransports(units, transports, location, transportPlatoon)
return false
end

IssueClearCommands(transports)

for num, unit in transports do
local id = unit.UnitId
if not transSlotTable[id] then
Expand Down Expand Up @@ -1524,7 +1526,7 @@ function UseTransports(units, transports, location, transportPlatoon)

local attached = true
repeat
WaitSeconds(2)
coroutine.yield(20)
local allDead = true
local transDead = true
for k, v in units do
Expand Down Expand Up @@ -1572,11 +1574,18 @@ function UseTransports(units, transports, location, transportPlatoon)
if table.getn(transports) ~= 0 then
-- If no location then we have loaded transports then return true
if location then
-- Adding Surface Height, so the transporter get not confused, because the target is under the map (reduces unload time)
location = {location[1], GetSurfaceHeight(location[1],location[3]), location[3]}
local safePath = AIAttackUtils.PlatoonGenerateSafePathTo(aiBrain, 'Air', transports[1]:GetPosition(), location, 200)
if safePath then
for _, p in safePath do
IssueMove(transports, p)
end
IssueMove(transports, location)
IssueTransportUnload(transports, location)
else
IssueMove(transports, location)
IssueTransportUnload(transports, location)
end
else
return true
Expand All @@ -1586,12 +1595,9 @@ function UseTransports(units, transports, location, transportPlatoon)
return false
end

-- Adding Surface Height, so thetransporter get not confused, because the target is under the map (reduces unload time)
location = {location[1], GetSurfaceHeight(location[1],location[3]), location[3]}
IssueTransportUnload(transports, location)
local attached = true
while attached do
WaitSeconds(2)
coroutine.yield(20)
local allDead = true
for _, v in transports do
if not v.Dead then
Expand Down Expand Up @@ -1833,15 +1839,16 @@ function EngineerTryReclaimCaptureArea(aiBrain, eng, pos)
unit.ReclaimInProgress = true
IssueReclaim({eng}, unit)
end
Reclaiming = true
end
Reclaiming = true
end
-- reclaim rocks etc or we can't build mexes or hydros
local Reclaimables = GetReclaimablesInRect(Rect(pos[1], pos[3], pos[1], pos[3]))
if Reclaimables and table.getn( Reclaimables ) > 0 then
for k,v in Reclaimables do
if v.MaxMassReclaim and v.MaxMassReclaim > 0 or v.MaxEnergyReclaim and v.MaxEnergyReclaim > 0 then
if v.MaxMassReclaim > 0 or v.MaxEnergyReclaim > 0 then
IssueReclaim({eng}, v)
Reclaiming = true
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lua/AI/sorianutilities.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ function Nuke(aiBrain)
break
end
end
ForkThread(LaunchNukesTimed, nukesToFire, tarPosition)
aiBrain:ForkThread(LaunchNukesTimed, nukesToFire, tarPosition)
end
-- Keep track of old targets
table.insert(oldTarget, target)
Expand Down Expand Up @@ -1189,7 +1189,7 @@ end
-- Returns:
-- nil
-- -----------------------------------------------------
function LaunchNukesTimed(nukesToFire, target)
function LaunchNukesTimed(aiBrain, nukesToFire, target)
local nukes = {}
for k,v in nukesToFire do
local pos = v:GetPosition()
Expand Down
20 changes: 15 additions & 5 deletions lua/aibrain.lua
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ AIBrain = Class(moho.aibrain_methods) {
end

self.CurrentPlan = self.AIPlansList[self:GetFactionIndex()][1]
self.EvaluateThread = self:ForkThread(self.EvaluateAIThread)
self.ExecuteThread = self:ForkThread(self.ExecuteAIThread)
self:ForkThread(self.InitialAIThread)

self.PlatoonNameCounter = {}
self.PlatoonNameCounter['AttackForce'] = 0
Expand Down Expand Up @@ -760,6 +759,13 @@ AIBrain = Class(moho.aibrain_methods) {
self.ConstantEval = eval
end,

InitialAIThread = function(self)
-- delay the AI so it can't reclaim the start area before it's cleared from the ACU landing blast.
WaitTicks(30)
self.EvaluateThread = self:ForkThread(self.EvaluateAIThread)
self.ExecuteThread = self:ForkThread(self.ExecuteAIThread)
end,

EvaluateAIThread = function(self)
local personality = self:GetPersonality()
local factionIndex = self:GetFactionIndex()
Expand Down Expand Up @@ -1092,12 +1098,15 @@ AIBrain = Class(moho.aibrain_methods) {
GetManagerCount = function(self, type)
local count = 0
for k, v in self.BuilderManagers do
if not v.BaseType then
continue
end
if type then
if type == 'Start Location' and not (string.find(k, 'ARMY_') or string.find(k, 'Large Expansion')) then
if type == 'Start Location' and v.BaseType ~= 'MAIN' and v.BaseType ~= 'Blank Marker' then
continue
elseif type == 'Naval Area' and not (string.find(k, 'Naval Area')) then
elseif type == 'Naval Area' and v.BaseType ~= 'Naval Area' then
continue
elseif type == 'Expansion Area' and (not (string.find(k, 'Expansion Area') or string.find(k, 'EXPANSION_AREA')) or string.find(k, 'Large Expansion')) then
elseif type == 'Expansion Area' and v.BaseType ~= 'Expansion Area' and v.BaseType ~= 'Large Expansion Area' then
continue
end
end
Expand Down Expand Up @@ -1243,6 +1252,7 @@ AIBrain = Class(moho.aibrain_methods) {
},
BuilderHandles = {},
Position = position,
BaseType = Scenario.MasterChain._MASTERCHAIN_.Markers[baseName].type or 'MAIN',
}
self.NumBases = self.NumBases + 1
end,
Expand Down
2 changes: 1 addition & 1 deletion lua/cybranunits.lua
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ CConstructionEggUnit = Class(CStructureUnit) {
pos[1], pos[2], pos[3],
0, 0, 0
)
ForkThread(function()
self:ForkThread(function()
self.OpenAnimManip = CreateAnimator(self)
self.Trash:Add(self.OpenAnimManip)
self.OpenAnimManip:PlayAnim(self:GetBlueprint().Display.AnimationOpen, false):SetRate(0.1)
Expand Down
6 changes: 3 additions & 3 deletions lua/defaultunits.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2067,7 +2067,7 @@ ConstructionUnit = Class(MobileUnit) {
self.BuildingOpenAnimManip:SetRate(self:GetBlueprint().Display.AnimationBuildRate or 1)
if self.BuildArmManipulator then
self.StoppedBuilding = false
ForkThread(self.WaitForBuildAnimation, self, true)
self:ForkThread(self.WaitForBuildAnimation, true)
end
end

Expand All @@ -2077,7 +2077,7 @@ ConstructionUnit = Class(MobileUnit) {
-- as it doesn't know it's doing something bad. To fix it, we temporarily make the unit immobile when it starts construction.
if self:IsMoving() then
self:SetImmobile(true)
ForkThread(function() WaitTicks(1) if not self:BeenDestroyed() then self:SetImmobile(false) end end)
self:ForkThread(function() WaitTicks(1) if not self:BeenDestroyed() then self:SetImmobile(false) end end)
end
end,

Expand Down Expand Up @@ -2211,7 +2211,7 @@ CommandUnit = Class(WalkingLandUnit) {
-- as it doesn't know it's doing something bad. To fix it, we temporarily make the unit immobile when it starts construction.
if self:IsMoving() then
self:SetImmobile(true)
ForkThread(function() WaitTicks(1) if not self:BeenDestroyed() then self:SetImmobile(false) end end)
self:ForkThread(function() WaitTicks(1) if not self:BeenDestroyed() then self:SetImmobile(false) end end)
end
end,

Expand Down
Loading

0 comments on commit 5c7a7ec

Please sign in to comment.