Skip to content
Open
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
97 changes: 97 additions & 0 deletions spec/System/TestConfigPersistence_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
describe("Configuration persistence", function()
before_each(function()
newBuild()
end)

it("omits untouched defaults while retaining existing non-default settings", function()
local configTab = build.configTab
local function savedInputs()
local xml = { }
configTab:Save(xml)
local inputs = { }
for _, node in ipairs(xml[1]) do
if node.elem == "Input" then
inputs[node.attrib.name] = node.attrib
end
end
return inputs
end
local defaults = {
"resistancePenalty", "GamblesprintMovementSpeed", "bloodsoakedBannerStages",
"conditionCorruptingCryStages", "touchedDebuffsCount", "maniaDebuffsCount",
}
local inputs = savedInputs()
for _, var in ipairs(defaults) do
assert.is_not_nil(configTab.input[var])
assert.is_nil(inputs[var])
end
assert.is_nil(inputs.overridePowerCharges)
-- Selecting a numeric dropdown's default must not create a saved override.
configTab.input.EHPUnluckyWorstOf = 1
assert.is_nil(savedInputs().EHPUnluckyWorstOf)

configTab.input.resistancePenalty = 0
configTab.input.EHPUnluckyWorstOf = 2
configTab.varControls.maniaDebuffsCount:SetText("2", true)
inputs = savedInputs()
assert.are.equal("0", inputs.resistancePenalty.number)
assert.are.equal("2", inputs.EHPUnluckyWorstOf.number)
assert.are.equal("2", inputs.maniaDebuffsCount.number)
loadBuildFromXML(build:SaveDB("code"))
assert.are.equal(0, build.configTab.input.resistancePenalty)
assert.are.equal(2, build.configTab.input.EHPUnluckyWorstOf)
assert.are.equal(2, build.configTab.input.maniaDebuffsCount)
end)

it("preserves explicit numeric inputs separately from blank fields in every config set", function()
local configTab = build.configTab
local vars = { "overrideEnduranceCharges", "overrideCrabBarriers", "conditionStationary" }
for id = 1, 3 do
if id > 1 then
configTab:NewConfigSet(id, "Config " .. id)
table.insert(configTab.configSetOrderList, id)
end
configTab:SetActiveConfigSet(id)
for _, var in ipairs(vars) do
configTab.varControls[var]:SetText(id == 1 and "0" or id == 2 and "2" or "", true)
configTab.placeholder[var] = 0
end
end

loadBuildFromXML(build:SaveDB("code"))

configTab = build.configTab
for id = 1, 3 do
configTab:SetActiveConfigSet(id)
for _, var in ipairs(vars) do
assert.are.equal(id == 1 and "0" or id == 2 and "2" or "", configTab.varControls[var].buf)
if id == 3 then
assert.is_nil(configTab.input[var])
else
assert.are.equal(id == 1 and 0 or 2, configTab.input[var])
end
assert.are.equal(0, configTab.placeholder[var])
end
end
end)

for _, minion in ipairs({ false, true }) do
it("calculates saved charge overrides for " .. (minion and "minions" or "the player"), function()
build.skillsTab:PasteSocketGroup("Raise Zombie 20/0 1")
for _, text in ipairs({ "0", "2", "" }) do
local configTab = build.configTab
for _, charge in ipairs({ "Power", "Frenzy", "Endurance" }) do
configTab.input[(minion and "minionsUse" or "use") .. charge .. "Charges"] = true
configTab.varControls[(minion and "minionsOverride" or "override") .. charge .. "Charges"]:SetText(text, true)
end
loadBuildFromXML(build:SaveDB("code"))
runCallback("OnFrame")
local output = minion and build.calcsTab.mainEnv.minion.output or build.calcsTab.mainOutput
for _, charge in ipairs({ "Power", "Frenzy", "Endurance" }) do
assert.are.equal(3, output[charge .. "ChargesMax"])
assert.are.equal(tonumber(text) or 3, output[charge .. "Charges"])
end
end
end)
end
end)
11 changes: 10 additions & 1 deletion src/Classes/ConfigTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ local varList = require("Modules.ConfigOptions")
local configVisibility = require("Modules.ConfigVisibility")
local configModBrowser = require("Modules.ConfigModBrowser")

local numericOptions = { }
for _, varData in ipairs(varList) do
if varData.type == "count" or varData.type == "integer" or varData.type == "countAllowZero" or varData.type == "float" then
numericOptions[varData.var] = varData
end
end

---@class CustomModBlockControl: ControlHost, Control
local CustomModBlockClass = newClass("CustomModBlockControl", "ControlHost", "Control")

Expand Down Expand Up @@ -968,7 +975,9 @@ function ConfigTabClass:Save(xml)
t_insert(xml, child)

for k, v in pairs(configSet.input) do
if v ~= self:GetDefaultState(k, type(v)) then
local varData = numericOptions[k]
-- Preserve numeric entries that would not be restored by the field's declared default.
if (type(v) == "number" and varData and v ~= varData.defaultState) or v ~= self:GetDefaultState(k, type(v)) then
local node = { elem = "Input", attrib = { name = k } }
if type(v) == "number" then
node.attrib.number = tostring(v)
Expand Down
12 changes: 6 additions & 6 deletions src/Modules/ConfigOptions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -900,19 +900,19 @@ Huge sets the radius to 11.
{ var = "usePowerCharges", type = "check", label = "Do you use Power Charges?", apply = function(val, modList, enemyModList)
modList:NewMod("UsePowerCharges", "FLAG", true, "Config", { type = "Condition", var = "Combat" })
end },
{ var = "overridePowerCharges", type = "count", label = "# of Power Charges (if not maximum):", ifOption = "usePowerCharges", apply = function(val, modList, enemyModList)
{ var = "overridePowerCharges", type = "countAllowZero", label = "# of Power Charges (if not maximum):", ifOption = "usePowerCharges", apply = function(val, modList, enemyModList)
modList:NewMod("PowerCharges", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" })
end },
{ var = "useFrenzyCharges", type = "check", label = "Do you use Frenzy Charges?", apply = function(val, modList, enemyModList)
modList:NewMod("UseFrenzyCharges", "FLAG", true, "Config", { type = "Condition", var = "Combat" })
end },
{ var = "overrideFrenzyCharges", type = "count", label = "# of Frenzy Charges (if not maximum):", ifOption = "useFrenzyCharges", apply = function(val, modList, enemyModList)
{ var = "overrideFrenzyCharges", type = "countAllowZero", label = "# of Frenzy Charges (if not maximum):", ifOption = "useFrenzyCharges", apply = function(val, modList, enemyModList)
modList:NewMod("FrenzyCharges", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" })
end },
{ var = "useEnduranceCharges", type = "check", label = "Do you use Endurance Charges?", apply = function(val, modList, enemyModList)
modList:NewMod("UseEnduranceCharges", "FLAG", true, "Config", { type = "Condition", var = "Combat" })
end },
{ var = "overrideEnduranceCharges", type = "count", label = "# of Endurance Charges (if not maximum):", ifOption = "useEnduranceCharges", apply = function(val, modList, enemyModList)
{ var = "overrideEnduranceCharges", type = "countAllowZero", label = "# of Endurance Charges (if not maximum):", ifOption = "useEnduranceCharges", apply = function(val, modList, enemyModList)
modList:NewMod("EnduranceCharges", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" })
end },
{ var = "useSiphoningCharges", type = "check", label = "Do you use Siphoning Charges?", ifMult = "SiphoningCharge", apply = function(val, modList, enemyModList)
Expand Down Expand Up @@ -982,13 +982,13 @@ Huge sets the radius to 11.
{ var = "minionsUseEnduranceCharges", type = "check", label = "Do your Minions use Endur. Charges?", ifFlag = "haveMinion", apply = function(val, modList, enemyModList)
modList:NewMod("MinionModifier", "LIST", { mod = modLib.createMod("UseEnduranceCharges", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) }, "Config")
end },
{ var = "minionsOverridePowerCharges", type = "count", label = "# of Power Charges (if not maximum):", ifFlag = "haveMinion", ifOption = "minionsUsePowerCharges", apply = function(val, modList, enemyModList)
{ var = "minionsOverridePowerCharges", type = "countAllowZero", label = "# of Power Charges (if not maximum):", ifFlag = "haveMinion", ifOption = "minionsUsePowerCharges", apply = function(val, modList, enemyModList)
modList:NewMod("MinionModifier", "LIST", { mod = modLib.createMod("PowerCharges", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" }) }, "Config")
end },
{ var = "minionsOverrideFrenzyCharges", type = "count", label = "# of Frenzy Charges (if not maximum):", ifFlag = "haveMinion", ifOption = "minionsUseFrenzyCharges", apply = function(val, modList, enemyModList)
{ var = "minionsOverrideFrenzyCharges", type = "countAllowZero", label = "# of Frenzy Charges (if not maximum):", ifFlag = "haveMinion", ifOption = "minionsUseFrenzyCharges", apply = function(val, modList, enemyModList)
modList:NewMod("MinionModifier", "LIST", { mod = modLib.createMod("FrenzyCharges", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" }) }, "Config")
end },
{ var = "minionsOverrideEnduranceCharges", type = "count", label = "# of Endurance Charges (if not maximum):", ifFlag = "haveMinion", ifOption = "minionsUseEnduranceCharges", apply = function(val, modList, enemyModList)
{ var = "minionsOverrideEnduranceCharges", type = "countAllowZero", label = "# of Endurance Charges (if not maximum):", ifFlag = "haveMinion", ifOption = "minionsUseEnduranceCharges", apply = function(val, modList, enemyModList)
modList:NewMod("MinionModifier", "LIST", { mod = modLib.createMod("EnduranceCharges", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" }) }, "Config")
end },
{ var = "multiplierRampage", type = "count", label = "# of Rampage Kills:", ifFlag = "Condition:Rampage", tooltip = "Rampage grants the following, up to 1000 stacks:\n\t1% increased Movement Speed per 20 Rampage\n\t2% increased Damage per 20 Rampage\nYou lose Rampage if you do not get a Kill within 5 seconds.", apply = function(val, modList, enemyModList)
Expand Down
Loading