140 lines
4.1 KiB
Plaintext
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
|