Divergent/mods/Anomaly Magazines Redux/gamedata/scripts/rax_stacking_control.script

140 lines
4.1 KiB
Plaintext

--[[
Stacking control
Fixes a bug in utils_ui that allowed things to stack incorectly when the full stacking rules are applied.
Provides a mechanisiam to invoke the full stacking rules on specified items under specified conditions
06Jun2021
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
Author: RavenAscendant
--]]
local registered_rules = {}
local expanded_rules = {}
-- section_func is a function that when passed a section returns true, if that section should be exempted from the normal forced stack all and have more complex stacking rules applied including custom rules included in the functor
--obj_functor should take an object return true if that particualr object should have the complex staking rules applied, false if that object should not stack with other objects of the same section regardless of other stacking rules.
-- if multiple rules for same
function register(section_func, obj_functor )
if not section_func then return end
registered_rules[section_func] = obj_functor
expanded_rules = {} --clear caching on new rule
end
local function get_rules(section)
--printf("get_rules1:%s %s", section, type(expanded_rules[section]) )
if expanded_rules[section] or expanded_rules[section] == false then return expanded_rules[section] end --false indicates no rules for section, nil is section has not been evaluated
expanded_rules[section] = {}
for k,v in pairs(registered_rules) do
--printf("get_rules2:%s %s", section, k(section) )
if k(section) then
expanded_rules[section][#expanded_rules[section]+1] = v or false --nil is not the same as false
end
end
if #expanded_rules[section]<1 then expanded_rules[section] = false end --don't want to keep an empty list, as empty list is not false
return expanded_rules[section]
end
local function check_rules(obj)
--
local rules = get_rules(obj:section())
if not rules then return false end
local stack = true
for _,v in ipairs(rules) do
stack = stack and (v and v(obj)) --any rule says don't stack it doesn't stack.
end
return not stack
end
function utils_ui.UICellContainer:ValidateSimilar(obj, sec)
if not (obj or sec) then
printe("!ERROR UICellContainer:ValidateSimilar | no data recieved!")
return false
end
local sec = obj:section()
if get_rules(sec) and check_rules(obj) then
return false
end
-- Ignore search if multiuse item is used
local max_uses = IsItem("multiuse",sec)
if max_uses and obj:get_remaining_uses() ~= max_uses then
return false
end
-- Ignore search if item has upgrades
if utils_item.has_upgrades(obj) then
return false
end
return true -- no opbjections let it go
end
function utils_ui.UICellContainer:FindSimilar(obj, sec)
--printf("find similar")
if not (obj or sec) then
printe("!ERROR UICellContainer:FindSimilar | no data recieved!")
return false
end
-- Ignore search if item isn't meant to stack
if SYS_GetParam(1,sec,"dont_stack") then
return false
end
if self.disable_stack then
return false
end
if self.showcase or self.stack_all and (not get_rules(sec)) then
return self:GetCell_SEC(sec)
end
local sec = obj:section() --not sure the importance of this, but tronex had it so make sure it fits.
if not self:ValidateSimilar(obj, sec) then
return false
end
-- items with no condition can stack, return a cell with same section
local clsid = obj:clsid()
local use_cond = SYS_GetParam(1,sec,"use_condition") or IsWeapon(nil,clsid) or IsOutfit(nil,clsid) or IsHeadgear(nil,clsid)
if (not use_cond) and (not get_rules(sec)) then
return self:GetCell_SEC(sec)
end
-- items with condition, full search
for idx,ci in pairs(self.cell) do
local obj_2 = ci.ID and level.object_by_id(ci.ID)
if (ci.section == sec and obj_2 and self:ValidateSimilar(obj_2, ci.section)) then
-- full multiuse item can stack
if max_uses then
return ci
-- item with similar condition can stack
else
local cond = obj:condition()
if obj_2 and math.abs(obj_2:condition() - cond) < 0.1 then
return ci
end
end
end
end
-- no similar item found
return false
end