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

Add a flat threshold for the brain energy manager #6514

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading