Skip to content

Commit

Permalink
Add a flat threshold for the brain energy manager (#6514)
Browse files Browse the repository at this point in the history
Places an upper limit on the energy requirement to turn energy-consuming units back on after an energy stall
  • Loading branch information
lL1l1 authored Nov 10, 2024
1 parent d1d28f7 commit 128f7d7
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 18 deletions.
1 change: 1 addition & 0 deletions changelog/snippets/fix.6514.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- (#6514) Fix extremely large amounts of energy storage preventing structures from re-enabling themselves after an energy stall due to requiring 0.1% of storage to be full. Now there is an upper limit of 10k on the energy requirement, which is reached at 100k storage.
32 changes: 22 additions & 10 deletions engine/Sim/CAiBrain.lua
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,19 @@ end
--- | 'Economy_Output_Energy'
--- | 'Economy_Stored_Energy'
--- | 'Economy_Reclaimed_Energy'
--- | 'Economy_Ratio_Energy'
--- | 'Economy_MaxStorage_Energy'
--- | 'Economy_Trend_Energy'
--- | 'Economy_PeakStorage_Energy'
--- | 'Economy_TotalProduced_Mass'
--- | 'Economy_TotalConsumed_Mass'
--- | 'Economy_Income_Mass'
--- | 'Economy_Output_Mass'
--- | 'Economy_Stored_Mass'
--- | 'Economy_Reclaimed_Mass'
--- | 'Economy_Ratio_Mass'
--- | 'Economy_MaxStorage_Mass'
--- | 'Economy_Trend_Mass'
--- | 'Economy_PeakStorage_Mass'

--- Returns the statistic of the army, if it doesn't exist it creates it and returns the default value
Expand Down Expand Up @@ -484,23 +488,31 @@ function CAiBrain:PlatoonExists(platoon)
end

--- Remove an army stats trigger.
-- @param statName String, army's stat, example: "Economy_Ratio_Mass".
-- @param triggerName String, unique name of the trigger.
---@param statName AIBrainBlueprintStatUnits | AIBrainBlueprintStatEnemies | AIBrainBlueprintStatEconomy | AIBrainBlueprintStatDamage
---@param triggerName string # unique name of the trigger.
function CAiBrain:RemoveArmyStatsTrigger(statName, triggerName)
end

--- Sets army's stat to value.
-- @param statName String, army's stat, example: "Economy_Ratio_Mass".
-- @param value Number.
---@param statName AIBrainBlueprintStatUnits | AIBrainBlueprintStatEnemies | AIBrainBlueprintStatEconomy | AIBrainBlueprintStatDamage # army's stat, example: "Economy_Ratio_Mass".
---@param value number
function CAiBrain:SetArmyStat(statName, value)
end

---@alias ComparatorString
---| "LessThan"
---| "LessThanOrEqual"
---| "GreaterThan"
---| "GreaterThanOrEqual"
---| "Equal"

--- Creates a new stat trigger.
-- @param statName String, army's stat, example: "Economy_Ratio_Mass".
-- @param triggerName String, unique name of the trigger.
-- @param compareType String, available types: 'LessThan', 'LessThanOrEqual', 'GreaterThan', 'GreaterThanOrEqual', 'Equal'.
-- @param value Number.
function CAiBrain:SetArmyStatsTrigger(statName, triggerName, compareType, value)
---@param statName AIBrainBlueprintStatUnits | AIBrainBlueprintStatEnemies | AIBrainBlueprintStatEconomy | AIBrainBlueprintStatDamage # army's stat
---@param triggerName string # unique name of the trigger. See `RemoveArmyStatsTrigger` to remove occupied names.
---@param compareType ComparatorString # available types: `LessThan`, `LessThanOrEqual`, `GreaterThan`, `GreaterThanOrEqual`, `Equal`
---@param value number #
---@param category EntityCategory? #
function CAiBrain:SetArmyStatsTrigger(statName, triggerName, compareType, value, category)
end

--- Set the current enemy for this brain to attack.
Expand All @@ -518,7 +530,7 @@ function CAiBrain:SetGreaterOf(statname, val)
end

--- Set if the brain should share resources to the allies.
-- @param bool ture/false
---@param bool boolean
function CAiBrain:SetResourceSharing(bool)
end

Expand Down
14 changes: 14 additions & 0 deletions lua/TriggerManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,20 @@ Manager = {
return true
end,

---@class EconStatsTriggerSpec
---@field Name string
---@field Parameters EconStatsTriggerParams

---@class EconStatsTriggerParams
---@field Brain AIBrain
---@field ResourceType 'Mass' | 'Energy'
---@field EconType 'TotalProduced' | 'TotalConsumed' | 'Income' | 'Output' | 'Stored' | 'Reclaimed' | 'Ratio' | 'MaxStorage' | 'PeakStorage' | 'Trend'
---@field CompareType ComparatorString?
---@field Number number # Value to compare against

---@param self TriggerManager
---@param spec EconStatsTriggerSpec
---@return boolean
EconStats = function(self, spec)
local params = spec.Parameters
if not params.ResourceType then
Expand Down
39 changes: 31 additions & 8 deletions lua/aibrains/components/EnergyManagerBrainComponent.lua
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ EnergyManagerBrainComponent = ClassSimple {
end,

OnStatsTrigger = function(self, triggerName)
if triggerName == "EnergyDepleted" or triggerName == "EnergyViable" then
if triggerName == "EnergyDepleted" or triggerName == "EnergyViable" or triggerName == "SwitchEnergyViableTrigger" then
self:OnEnergyTrigger(triggerName)
end
end,
Expand All @@ -250,18 +250,41 @@ EnergyManagerBrainComponent = ClassSimple {
---@param self AIBrain
---@param triggerName string
OnEnergyTrigger = function(self, triggerName)
if triggerName == "EnergyDepleted" then
if triggerName == "EnergyDepleted" or triggerName == "SwitchEnergyViableTrigger" then
-- add trigger when we can recover units
self:SetArmyStatsTrigger('Economy_Ratio_Energy', 'EnergyViable', 'GreaterThanOrEqual', 0.1)
self.EnergyDepleted = true
local energyStorageThreshold = 100000
local storageRatio = 0.1

if self:GetArmyStat('Economy_MaxStorage_Energy', 0).Value < energyStorageThreshold then
-- When we have little storage, turn back on above the ratio, or switch trigger after building enough storage.
self:RemoveArmyStatsTrigger("Economy_Stored_Energy", "EnergyViable")
self:SetArmyStatsTrigger('Economy_Ratio_Energy', 'EnergyViable', 'GreaterThanOrEqual', storageRatio)

self:RemoveArmyStatsTrigger("Economy_Stored_Energy", "SwitchEnergyViableTrigger")
self:SetArmyStatsTrigger("Economy_MaxStorage_Energy", "SwitchEnergyViableTrigger", "GreaterThanOrEqual", energyStorageThreshold)
else
-- When we have a lot of storage, turn back on above the ratio of the threshold, or switch trigger after losing enough storage.
self:RemoveArmyStatsTrigger("Economy_Ratio_Energy", "EnergyViable")
self:SetArmyStatsTrigger("Economy_Stored_Energy", "EnergyViable", "GreaterThanOrEqual", energyStorageThreshold * storageRatio)

self:RemoveArmyStatsTrigger("Economy_MaxStorage_Energy", "SwitchEnergyViableTrigger")
self:SetArmyStatsTrigger("Economy_MaxStorage_Energy", "SwitchEnergyViableTrigger", "LessThan", energyStorageThreshold)
end

-- recurse over the list of units and do callbacks accordingly
for id, entity in self.EnergyDependingUnits do
if not IsDestroyed(entity) then
entity:OnEnergyDepleted()
if triggerName == "EnergyDepleted" then
self.EnergyDepleted = true

-- recurse over the list of units and do callbacks accordingly
for id, entity in self.EnergyDependingUnits do
if not IsDestroyed(entity) then
entity:OnEnergyDepleted()
end
end
end
else
-- clean up the trigger switcher
self:RemoveArmyStatsTrigger("Economy_MaxStorage_Energy", "SwitchEnergyViableTrigger")

-- add trigger when we're depleted
self:SetArmyStatsTrigger('Economy_Ratio_Energy', 'EnergyDepleted', 'LessThanOrEqual', 0.0)
self.EnergyDepleted = false
Expand Down

0 comments on commit 128f7d7

Please sign in to comment.