From edd672e9234a02d5e068351b26899061223054f6 Mon Sep 17 00:00:00 2001 From: Regisle Date: Thu, 9 Feb 2023 22:32:05 +1030 Subject: [PATCH 1/7] Initial Implementation of item Disablers --- src/Modules/CalcSetup.lua | 88 ++++++++++++++++++++++++++++++++++- src/Modules/ConfigOptions.lua | 1 + src/Modules/ModParser.lua | 6 +++ 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index e900d845cd..19895c3582 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -570,9 +570,10 @@ function calcs.initEnv(build, mode, override, specEnv) modDB:NewMod("Multiplier:AllocatedNotable", "BASE", allocatedNotableCount, "") modDB:NewMod("Multiplier:AllocatedMastery", "BASE", allocatedMasteryCount, "") modDB:NewMod("Multiplier:AllocatedMasteryType", "BASE", allocatedMasteryTypeCount, "") - + -- Build and merge item modifiers, and create list of radius jewels if not accelerate.requirementsItems then + local items = {} for _, slot in pairs(build.itemsTab.orderedSlots) do local slotName = slot.slotName local item @@ -638,6 +639,91 @@ function calcs.initEnv(build, mode, override, specEnv) end end end + items[slotName] = item + end + + if not env.configInput.ignoreItemDisablers then + local itemDisabled = {} + local unhandeledItemDisablers = { size = 1} + if modDB:Flag(nil, "CantUseHelm") then + itemDisabled["Helmet"] = { disabled = true, size = 1 } + end + for _, slot in pairs(build.itemsTab.orderedSlots) do + local slotName = slot.slotName + if items[slotName] then + local srcList = items[slotName].modList or items[slotName].slotModList[slot.slotNum] + for _, mod in ipairs(srcList) do + -- checks if it disables another slot + for _, tag in ipairs(mod) do + if tag.type == "DisablesItem" then + unhandeledItemDisablers[slotName] = unhandeledItemDisablers[slotName] and unhandeledItemDisablers[slotName] or {} + t_insert(unhandeledItemDisablers[slotName], tag.slotName) + unhandeledItemDisablers.size = unhandeledItemDisablers.size + 1 + itemDisabled[tag.slotName] = itemDisabled[tag.slotName] and itemDisabled[tag.slotName] or { size = 0} + itemDisabled[tag.slotName][slotName] = true + itemDisabled[tag.slotName].size = itemDisabled[tag.slotName].size + 1 + break + end + end + end + end + end + while unhandeledItemDisablers.size > 0 do + local stalemateBreaker = true + for slot, itemData in pairs(unhandeledItemDisablers) do + if slot ~= "size" then + if not itemDisabled[slot] then + for _, slot2 in ipairs(unhandeledItemDisablers[slot]) do + if unhandeledItemDisablers[slot2] then + for _, slot3 in ipairs(unhandeledItemDisablers[slot2]) do + itemDisabled[slot3][slot2] = nil + itemDisabled[slot3].size = itemDisabled[slot3].size - 1 + if itemDisabled[slot3].size == 0 then + itemDisabled[slot3] = nil + end + end + unhandeledItemDisablers[slot2] = nil + unhandeledItemDisablers.size = unhandeledItemDisablers.size - 1 + end + end + unhandeledItemDisablers[slot] = nil + unhandeledItemDisablers.size = unhandeledItemDisablers.size - 1 + stalemateBreaker = false + end + end + end + -- if goes through an entire itteration without handeling an unhandeled Item Disabler, just take the first one + if stalemateBreaker then + for slot, itemData in pairs(unhandeledItemDisablers) do + if slot ~= "size" then + for _, slot2 in ipairs(unhandeledItemDisablers[slot]) do + if unhandeledItemDisablers[slot2] then + for _, slot3 in ipairs(unhandeledItemDisablers[slot2]) do + itemDisabled[slot3][slot2] = nil + itemDisabled[slot3].size = itemDisabled[slot3].size - 1 + if itemDisabled[slot3].size == 0 then + itemDisabled[slot3] = nil + end + end + unhandeledItemDisablers[slot2] = nil + unhandeledItemDisablers.size = unhandeledItemDisablers.size - 1 + end + end + unhandeledItemDisablers[slot] = nil + break + end + end + unhandeledItemDisablers.size = unhandeledItemDisablers.size - 1 + end + end + for slot, _ in pairs(itemDisabled) do + items[slot] = nil + end + end + + for _, slot in pairs(build.itemsTab.orderedSlots) do + local slotName = slot.slotName + local item = items[slotName] if item and item.type == "Flask" then if slot.active then env.flasks[item] = true diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index c434993884..12bddf101d 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -140,6 +140,7 @@ return { { var = "EVBypass", type = "check", label = "Disable Emperor's Vigilance Bypass", ifCond = "EVBypass", apply = function(val, modList, enemyModList) modList:NewMod("Condition:EVBypass", "FLAG", true, "Config") end }, + { var = "ignoreItemDisablers", type = "check", label = "Ignore Item Disablers" }, -- Section: Skill-specific options { section = "Skill Options", col = 2 }, diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 70858e38de..68d87c6b77 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -3521,6 +3521,12 @@ local specialModList = { ["added small passive skills have (%d+)%% increased effect"] = function(num) return { mod("JewelData", "LIST", { key = "clusterJewelIncEffect", value = num }) } end, ["this jewel's socket has (%d+)%% increased effect per allocated passive skill between it and your class' starting location"] = function(num) return { mod("JewelData", "LIST", { key = "jewelIncEffectFromClassStart", value = num }) } end, -- Misc + ["can't use chest armour"] = { mod("CantUseBody", "Flag", 1, { type = "DisablesItem", slotName = "Body Armour" }) }, + --["can't use helmets"] = { mod("CantUseHelmet", "Flag", 1, { type = "DisablesItem", slotName = "Helmet" }) }, -- this one doesnt work due to being on a passive? + ["can't use helmet"] = { mod("CantUseHelmet", "Flag", 1, { type = "DisablesItem", slotName = "Helmet" }) }, -- this is to allow for custom mod without saying the other is parsed + ["can't use other rings"] = { mod("CantUseRightRing", "Flag", 1, { type = "DisablesItem", slotName = "Ring 2" }, { type = "SlotNumber", num = 1 }), mod("CantUseLeftRing", "Flag", 1, { type = "DisablesItem", slotName = "Ring 1" }, { type = "SlotNumber", num = 2 }) }, + ["uses both hand slots"] = { mod("CantUseRightWeapon", "Flag", 1, { type = "DisablesItem", slotName = "Weapon 2" }, { type = "SlotNumber", num = 1 }), mod("CantUseLeftWeapon", "Flag", 1, { type = "DisablesItem", slotName = "Weapon 1" }, { type = "SlotNumber", num = 2 }) }, + ["can't use flask in fifth slot"] = { mod("CantUseFifthFlask", "Flag", 1, { type = "DisablesItem", slotName = "Flask 5" }) }, ["boneshatter has (%d+)%% chance to grant %+1 trauma"] = function(num) return { mod("ExtraTrauma", "BASE", num, { type = "SkillName", skillName = "Boneshatter" }) } end, ["your minimum frenzy, endurance and power charges are equal to your maximum while you are stationary"] = { flag("MinimumFrenzyChargesIsMaximumFrenzyCharges", {type = "Condition", var = "Stationary" }), From b2b4866fd68600909e104d9772f8c314b6f8cf57 Mon Sep 17 00:00:00 2001 From: Regisle Date: Thu, 9 Feb 2023 22:41:19 +1030 Subject: [PATCH 2/7] fix spelling --- src/Modules/CalcSetup.lua | 46 +++++++++++++++++++-------------------- src/Modules/ModParser.lua | 12 +++++----- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 19895c3582..07a0e32047 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -644,8 +644,8 @@ function calcs.initEnv(build, mode, override, specEnv) if not env.configInput.ignoreItemDisablers then local itemDisabled = {} - local unhandeledItemDisablers = { size = 1} - if modDB:Flag(nil, "CantUseHelm") then + local unhandledItemDisablers = { size = 1} + if modDB:Flag(nil, "CanNotUseHelm") then itemDisabled["Helmet"] = { disabled = true, size = 1 } end for _, slot in pairs(build.itemsTab.orderedSlots) do @@ -656,9 +656,9 @@ function calcs.initEnv(build, mode, override, specEnv) -- checks if it disables another slot for _, tag in ipairs(mod) do if tag.type == "DisablesItem" then - unhandeledItemDisablers[slotName] = unhandeledItemDisablers[slotName] and unhandeledItemDisablers[slotName] or {} - t_insert(unhandeledItemDisablers[slotName], tag.slotName) - unhandeledItemDisablers.size = unhandeledItemDisablers.size + 1 + unhandledItemDisablers[slotName] = unhandledItemDisablers[slotName] and unhandledItemDisablers[slotName] or {} + t_insert(unhandledItemDisablers[slotName], tag.slotName) + unhandledItemDisablers.size = unhandledItemDisablers.size + 1 itemDisabled[tag.slotName] = itemDisabled[tag.slotName] and itemDisabled[tag.slotName] or { size = 0} itemDisabled[tag.slotName][slotName] = true itemDisabled[tag.slotName].size = itemDisabled[tag.slotName].size + 1 @@ -668,52 +668,52 @@ function calcs.initEnv(build, mode, override, specEnv) end end end - while unhandeledItemDisablers.size > 0 do + while unhandledItemDisablers.size > 0 do local stalemateBreaker = true - for slot, itemData in pairs(unhandeledItemDisablers) do + for slot, itemData in pairs(unhandledItemDisablers) do if slot ~= "size" then if not itemDisabled[slot] then - for _, slot2 in ipairs(unhandeledItemDisablers[slot]) do - if unhandeledItemDisablers[slot2] then - for _, slot3 in ipairs(unhandeledItemDisablers[slot2]) do + for _, slot2 in ipairs(unhandledItemDisablers[slot]) do + if unhandledItemDisablers[slot2] then + for _, slot3 in ipairs(unhandledItemDisablers[slot2]) do itemDisabled[slot3][slot2] = nil itemDisabled[slot3].size = itemDisabled[slot3].size - 1 if itemDisabled[slot3].size == 0 then itemDisabled[slot3] = nil end end - unhandeledItemDisablers[slot2] = nil - unhandeledItemDisablers.size = unhandeledItemDisablers.size - 1 + unhandledItemDisablers[slot2] = nil + unhandledItemDisablers.size = unhandledItemDisablers.size - 1 end end - unhandeledItemDisablers[slot] = nil - unhandeledItemDisablers.size = unhandeledItemDisablers.size - 1 + unhandledItemDisablers[slot] = nil + unhandledItemDisablers.size = unhandledItemDisablers.size - 1 stalemateBreaker = false end end end - -- if goes through an entire itteration without handeling an unhandeled Item Disabler, just take the first one + -- if goes through an entire iteration without handeling an unhandled Item Disabler, just take the first one if stalemateBreaker then - for slot, itemData in pairs(unhandeledItemDisablers) do + for slot, itemData in pairs(unhandledItemDisablers) do if slot ~= "size" then - for _, slot2 in ipairs(unhandeledItemDisablers[slot]) do - if unhandeledItemDisablers[slot2] then - for _, slot3 in ipairs(unhandeledItemDisablers[slot2]) do + for _, slot2 in ipairs(unhandledItemDisablers[slot]) do + if unhandledItemDisablers[slot2] then + for _, slot3 in ipairs(unhandledItemDisablers[slot2]) do itemDisabled[slot3][slot2] = nil itemDisabled[slot3].size = itemDisabled[slot3].size - 1 if itemDisabled[slot3].size == 0 then itemDisabled[slot3] = nil end end - unhandeledItemDisablers[slot2] = nil - unhandeledItemDisablers.size = unhandeledItemDisablers.size - 1 + unhandledItemDisablers[slot2] = nil + unhandledItemDisablers.size = unhandledItemDisablers.size - 1 end end - unhandeledItemDisablers[slot] = nil + unhandledItemDisablers[slot] = nil break end end - unhandeledItemDisablers.size = unhandeledItemDisablers.size - 1 + unhandledItemDisablers.size = unhandledItemDisablers.size - 1 end end for slot, _ in pairs(itemDisabled) do diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 68d87c6b77..93d59e6509 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -3521,12 +3521,12 @@ local specialModList = { ["added small passive skills have (%d+)%% increased effect"] = function(num) return { mod("JewelData", "LIST", { key = "clusterJewelIncEffect", value = num }) } end, ["this jewel's socket has (%d+)%% increased effect per allocated passive skill between it and your class' starting location"] = function(num) return { mod("JewelData", "LIST", { key = "jewelIncEffectFromClassStart", value = num }) } end, -- Misc - ["can't use chest armour"] = { mod("CantUseBody", "Flag", 1, { type = "DisablesItem", slotName = "Body Armour" }) }, - --["can't use helmets"] = { mod("CantUseHelmet", "Flag", 1, { type = "DisablesItem", slotName = "Helmet" }) }, -- this one doesnt work due to being on a passive? - ["can't use helmet"] = { mod("CantUseHelmet", "Flag", 1, { type = "DisablesItem", slotName = "Helmet" }) }, -- this is to allow for custom mod without saying the other is parsed - ["can't use other rings"] = { mod("CantUseRightRing", "Flag", 1, { type = "DisablesItem", slotName = "Ring 2" }, { type = "SlotNumber", num = 1 }), mod("CantUseLeftRing", "Flag", 1, { type = "DisablesItem", slotName = "Ring 1" }, { type = "SlotNumber", num = 2 }) }, - ["uses both hand slots"] = { mod("CantUseRightWeapon", "Flag", 1, { type = "DisablesItem", slotName = "Weapon 2" }, { type = "SlotNumber", num = 1 }), mod("CantUseLeftWeapon", "Flag", 1, { type = "DisablesItem", slotName = "Weapon 1" }, { type = "SlotNumber", num = 2 }) }, - ["can't use flask in fifth slot"] = { mod("CantUseFifthFlask", "Flag", 1, { type = "DisablesItem", slotName = "Flask 5" }) }, + ["can't use chest armour"] = { mod("CanNotUseBody", "Flag", 1, { type = "DisablesItem", slotName = "Body Armour" }) }, + --["can't use helmets"] = { mod("CanNotUseHelmet", "Flag", 1, { type = "DisablesItem", slotName = "Helmet" }) }, -- this one doesnt work due to being on a passive? + ["can't use helmet"] = { mod("CanNotUseHelmet", "Flag", 1, { type = "DisablesItem", slotName = "Helmet" }) }, -- this is to allow for custom mod without saying the other is parsed + ["can't use other rings"] = { mod("CanNotUseRightRing", "Flag", 1, { type = "DisablesItem", slotName = "Ring 2" }, { type = "SlotNumber", num = 1 }), mod("CanNotUseLeftRing", "Flag", 1, { type = "DisablesItem", slotName = "Ring 1" }, { type = "SlotNumber", num = 2 }) }, + ["uses both hand slots"] = { mod("CanNotUseRightWeapon", "Flag", 1, { type = "DisablesItem", slotName = "Weapon 2" }, { type = "SlotNumber", num = 1 }), mod("CanNotUseLeftWeapon", "Flag", 1, { type = "DisablesItem", slotName = "Weapon 1" }, { type = "SlotNumber", num = 2 }) }, + ["can't use flask in fifth slot"] = { mod("CanNotUseFifthFlask", "Flag", 1, { type = "DisablesItem", slotName = "Flask 5" }) }, ["boneshatter has (%d+)%% chance to grant %+1 trauma"] = function(num) return { mod("ExtraTrauma", "BASE", num, { type = "SkillName", skillName = "Boneshatter" }) } end, ["your minimum frenzy, endurance and power charges are equal to your maximum while you are stationary"] = { flag("MinimumFrenzyChargesIsMaximumFrenzyCharges", {type = "Condition", var = "Stationary" }), From 19511187110e50e0c9bb20f1655e58bd89003287 Mon Sep 17 00:00:00 2001 From: Regisle Date: Thu, 9 Feb 2023 22:43:52 +1030 Subject: [PATCH 3/7] fix spelling --- src/Modules/CalcSetup.lua | 2 +- src/Modules/ModParser.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 07a0e32047..c2575b4758 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -692,7 +692,7 @@ function calcs.initEnv(build, mode, override, specEnv) end end end - -- if goes through an entire iteration without handeling an unhandled Item Disabler, just take the first one + -- if goes through an entire iteration without handling an unhandled Item Disabler, just take the first one if stalemateBreaker then for slot, itemData in pairs(unhandledItemDisablers) do if slot ~= "size" then diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 93d59e6509..3ba72b880b 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -3522,7 +3522,7 @@ local specialModList = { ["this jewel's socket has (%d+)%% increased effect per allocated passive skill between it and your class' starting location"] = function(num) return { mod("JewelData", "LIST", { key = "jewelIncEffectFromClassStart", value = num }) } end, -- Misc ["can't use chest armour"] = { mod("CanNotUseBody", "Flag", 1, { type = "DisablesItem", slotName = "Body Armour" }) }, - --["can't use helmets"] = { mod("CanNotUseHelmet", "Flag", 1, { type = "DisablesItem", slotName = "Helmet" }) }, -- this one doesnt work due to being on a passive? + --["can't use helmets"] = { mod("CanNotUseHelmet", "Flag", 1, { type = "DisablesItem", slotName = "Helmet" }) }, -- this one does not work due to being on a passive? ["can't use helmet"] = { mod("CanNotUseHelmet", "Flag", 1, { type = "DisablesItem", slotName = "Helmet" }) }, -- this is to allow for custom mod without saying the other is parsed ["can't use other rings"] = { mod("CanNotUseRightRing", "Flag", 1, { type = "DisablesItem", slotName = "Ring 2" }, { type = "SlotNumber", num = 1 }), mod("CanNotUseLeftRing", "Flag", 1, { type = "DisablesItem", slotName = "Ring 1" }, { type = "SlotNumber", num = 2 }) }, ["uses both hand slots"] = { mod("CanNotUseRightWeapon", "Flag", 1, { type = "DisablesItem", slotName = "Weapon 2" }, { type = "SlotNumber", num = 1 }), mod("CanNotUseLeftWeapon", "Flag", 1, { type = "DisablesItem", slotName = "Weapon 1" }, { type = "SlotNumber", num = 2 }) }, From 7915b2ad59502f607cfa91a97a314563b9ca95c6 Mon Sep 17 00:00:00 2001 From: Regisle Date: Fri, 10 Feb 2023 15:31:31 +1030 Subject: [PATCH 4/7] update tooltip --- src/Modules/ConfigOptions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index 12bddf101d..c055e32e5c 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -140,7 +140,7 @@ return { { var = "EVBypass", type = "check", label = "Disable Emperor's Vigilance Bypass", ifCond = "EVBypass", apply = function(val, modList, enemyModList) modList:NewMod("Condition:EVBypass", "FLAG", true, "Config") end }, - { var = "ignoreItemDisablers", type = "check", label = "Ignore Item Disablers" }, + { var = "ignoreItemDisablers", type = "check", label = "Ignore Item Disablers", tooltip = "Ignore the effects of things which disable items, like bringer of rain" }, -- Section: Skill-specific options { section = "Skill Options", col = 2 }, From 31bfb51db15ddc11ce147c9fb920e2f7bd809328 Mon Sep 17 00:00:00 2001 From: Regisle <49933620+Regisle@users.noreply.github.com> Date: Fri, 31 Mar 2023 15:28:18 +1030 Subject: [PATCH 5/7] Apply suggestions from code review Co-authored-by: Wires77 --- src/Modules/CalcSetup.lua | 6 +++--- src/Modules/ConfigOptions.lua | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index c2575b4758..4a5f01b09d 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -656,10 +656,10 @@ function calcs.initEnv(build, mode, override, specEnv) -- checks if it disables another slot for _, tag in ipairs(mod) do if tag.type == "DisablesItem" then - unhandledItemDisablers[slotName] = unhandledItemDisablers[slotName] and unhandledItemDisablers[slotName] or {} + unhandledItemDisablers[slotName] = unhandledItemDisablers[slotName] or {} t_insert(unhandledItemDisablers[slotName], tag.slotName) unhandledItemDisablers.size = unhandledItemDisablers.size + 1 - itemDisabled[tag.slotName] = itemDisabled[tag.slotName] and itemDisabled[tag.slotName] or { size = 0} + itemDisabled[tag.slotName] = itemDisabled[tag.slotName] or { size = 0 } itemDisabled[tag.slotName][slotName] = true itemDisabled[tag.slotName].size = itemDisabled[tag.slotName].size + 1 break @@ -668,7 +668,7 @@ function calcs.initEnv(build, mode, override, specEnv) end end end - while unhandledItemDisablers.size > 0 do + while next(nilunhandledItemDisablers) != nil do local stalemateBreaker = true for slot, itemData in pairs(unhandledItemDisablers) do if slot ~= "size" then diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index c055e32e5c..f47194fb63 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -140,7 +140,7 @@ return { { var = "EVBypass", type = "check", label = "Disable Emperor's Vigilance Bypass", ifCond = "EVBypass", apply = function(val, modList, enemyModList) modList:NewMod("Condition:EVBypass", "FLAG", true, "Config") end }, - { var = "ignoreItemDisablers", type = "check", label = "Ignore Item Disablers", tooltip = "Ignore the effects of things which disable items, like bringer of rain" }, + { var = "ignoreItemDisablers", type = "check", label = "Don't disable items", tooltip = "Ignore the effects of things which disable items, like Bringer of Rain" }, -- Section: Skill-specific options { section = "Skill Options", col = 2 }, From d0cad4070148a2b040e64bc99ef6a62d4246c066 Mon Sep 17 00:00:00 2001 From: Regisle Date: Fri, 31 Mar 2023 15:44:46 +1030 Subject: [PATCH 6/7] cleanup merge issues --- src/Modules/CalcSetup.lua | 63 +++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 4a5f01b09d..a985d4896d 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -644,7 +644,7 @@ function calcs.initEnv(build, mode, override, specEnv) if not env.configInput.ignoreItemDisablers then local itemDisabled = {} - local unhandledItemDisablers = { size = 1} + local unhandledItemDisablers = { } if modDB:Flag(nil, "CanNotUseHelm") then itemDisabled["Helmet"] = { disabled = true, size = 1 } end @@ -658,7 +658,6 @@ function calcs.initEnv(build, mode, override, specEnv) if tag.type == "DisablesItem" then unhandledItemDisablers[slotName] = unhandledItemDisablers[slotName] or {} t_insert(unhandledItemDisablers[slotName], tag.slotName) - unhandledItemDisablers.size = unhandledItemDisablers.size + 1 itemDisabled[tag.slotName] = itemDisabled[tag.slotName] or { size = 0 } itemDisabled[tag.slotName][slotName] = true itemDisabled[tag.slotName].size = itemDisabled[tag.slotName].size + 1 @@ -668,52 +667,44 @@ function calcs.initEnv(build, mode, override, specEnv) end end end - while next(nilunhandledItemDisablers) != nil do + while next(unhandledItemDisablers) ~= nil do local stalemateBreaker = true for slot, itemData in pairs(unhandledItemDisablers) do - if slot ~= "size" then - if not itemDisabled[slot] then - for _, slot2 in ipairs(unhandledItemDisablers[slot]) do - if unhandledItemDisablers[slot2] then - for _, slot3 in ipairs(unhandledItemDisablers[slot2]) do - itemDisabled[slot3][slot2] = nil - itemDisabled[slot3].size = itemDisabled[slot3].size - 1 - if itemDisabled[slot3].size == 0 then - itemDisabled[slot3] = nil - end + if not itemDisabled[slot] then + for _, slot2 in ipairs(unhandledItemDisablers[slot]) do + if unhandledItemDisablers[slot2] then + for _, slot3 in ipairs(unhandledItemDisablers[slot2]) do + itemDisabled[slot3][slot2] = nil + itemDisabled[slot3].size = itemDisabled[slot3].size - 1 + if itemDisabled[slot3].size == 0 then + itemDisabled[slot3] = nil end - unhandledItemDisablers[slot2] = nil - unhandledItemDisablers.size = unhandledItemDisablers.size - 1 end - end - unhandledItemDisablers[slot] = nil - unhandledItemDisablers.size = unhandledItemDisablers.size - 1 - stalemateBreaker = false - end + unhandledItemDisablers[slot2] = nil + end + end + unhandledItemDisablers[slot] = nil + stalemateBreaker = false end end -- if goes through an entire iteration without handling an unhandled Item Disabler, just take the first one if stalemateBreaker then for slot, itemData in pairs(unhandledItemDisablers) do - if slot ~= "size" then - for _, slot2 in ipairs(unhandledItemDisablers[slot]) do - if unhandledItemDisablers[slot2] then - for _, slot3 in ipairs(unhandledItemDisablers[slot2]) do - itemDisabled[slot3][slot2] = nil - itemDisabled[slot3].size = itemDisabled[slot3].size - 1 - if itemDisabled[slot3].size == 0 then - itemDisabled[slot3] = nil - end + for _, slot2 in ipairs(unhandledItemDisablers[slot]) do + if unhandledItemDisablers[slot2] then + for _, slot3 in ipairs(unhandledItemDisablers[slot2]) do + itemDisabled[slot3][slot2] = nil + itemDisabled[slot3].size = itemDisabled[slot3].size - 1 + if itemDisabled[slot3].size == 0 then + itemDisabled[slot3] = nil end - unhandledItemDisablers[slot2] = nil - unhandledItemDisablers.size = unhandledItemDisablers.size - 1 end - end - unhandledItemDisablers[slot] = nil - break - end + unhandledItemDisablers[slot2] = nil + end + end + unhandledItemDisablers[slot] = nil + break end - unhandledItemDisablers.size = unhandledItemDisablers.size - 1 end end for slot, _ in pairs(itemDisabled) do From aa6378e0243ab61bf753feaba63683e218893227 Mon Sep 17 00:00:00 2001 From: Wires77 Date: Sat, 1 Apr 2023 01:14:17 -0500 Subject: [PATCH 7/7] Refactored algorithm for determining disabled items --- src/Modules/CalcSetup.lua | 70 ++++++++++++++------------------------- 1 file changed, 25 insertions(+), 45 deletions(-) diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index a985d4896d..6f1da057f0 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -641,10 +641,10 @@ function calcs.initEnv(build, mode, override, specEnv) end items[slotName] = item end - + if not env.configInput.ignoreItemDisablers then local itemDisabled = {} - local unhandledItemDisablers = { } + local itemDisablers = {} if modDB:Flag(nil, "CanNotUseHelm") then itemDisabled["Helmet"] = { disabled = true, size = 1 } end @@ -656,58 +656,38 @@ function calcs.initEnv(build, mode, override, specEnv) -- checks if it disables another slot for _, tag in ipairs(mod) do if tag.type == "DisablesItem" then - unhandledItemDisablers[slotName] = unhandledItemDisablers[slotName] or {} - t_insert(unhandledItemDisablers[slotName], tag.slotName) - itemDisabled[tag.slotName] = itemDisabled[tag.slotName] or { size = 0 } - itemDisabled[tag.slotName][slotName] = true - itemDisabled[tag.slotName].size = itemDisabled[tag.slotName].size + 1 + itemDisablers[slotName] = tag.slotName + itemDisabled[tag.slotName] = slotName break end end end end end - while next(unhandledItemDisablers) ~= nil do - local stalemateBreaker = true - for slot, itemData in pairs(unhandledItemDisablers) do - if not itemDisabled[slot] then - for _, slot2 in ipairs(unhandledItemDisablers[slot]) do - if unhandledItemDisablers[slot2] then - for _, slot3 in ipairs(unhandledItemDisablers[slot2]) do - itemDisabled[slot3][slot2] = nil - itemDisabled[slot3].size = itemDisabled[slot3].size - 1 - if itemDisabled[slot3].size == 0 then - itemDisabled[slot3] = nil - end - end - unhandledItemDisablers[slot2] = nil - end - end - unhandledItemDisablers[slot] = nil - stalemateBreaker = false - end - end - -- if goes through an entire iteration without handling an unhandled Item Disabler, just take the first one - if stalemateBreaker then - for slot, itemData in pairs(unhandledItemDisablers) do - for _, slot2 in ipairs(unhandledItemDisablers[slot]) do - if unhandledItemDisablers[slot2] then - for _, slot3 in ipairs(unhandledItemDisablers[slot2]) do - itemDisabled[slot3][slot2] = nil - itemDisabled[slot3].size = itemDisabled[slot3].size - 1 - if itemDisabled[slot3].size == 0 then - itemDisabled[slot3] = nil - end - end - unhandledItemDisablers[slot2] = nil - end - end - unhandledItemDisablers[slot] = nil - break + local visited = {} + local trueDisabled = {} + for slot in pairs(itemDisablers) do + if not visited[slot] then + -- find chain start + local curChain = { slot = true } + while itemDisabled[slot] do + slot = itemDisabled[slot] + if curChain[slot] then break end -- detect cycles + curChain[slot] = true end + + -- step through the chain of disabled items, disabling every other one + repeat + visited[slot] = true + slot = itemDisablers[slot] + if not slot then break end + visited[slot] = true + trueDisabled[slot] = true + slot = itemDisablers[slot] + until(not slot or visited[slot]) end end - for slot, _ in pairs(itemDisabled) do + for slot in pairs(trueDisabled) do items[slot] = nil end end