diff --git a/src/Classes/ModDB.lua b/src/Classes/ModDB.lua index 3ff5c16a37..ca864aaa9c 100644 --- a/src/Classes/ModDB.lua +++ b/src/Classes/ModDB.lua @@ -7,6 +7,7 @@ local ipairs = ipairs local pairs = pairs local select = select local t_insert = table.insert +local t_remove = table.remove local m_floor = math.floor local m_min = math.min local m_max = math.max @@ -64,6 +65,45 @@ function ModDBClass:ReplaceModInternal(mod) return false end +---ConvertModInternal +--- Converts an existing mod with oldName to a new mod with a different name. +--- Moves the mod from the old name's bucket to the new name's bucket. +--- If no matching mod exists, then the function returns false +---@param oldName string @The name of the existing mod to find +---@param mod table @The new mod to replace it with +---@return boolean @Whether any mod was converted +function ModDBClass:ConvertModInternal(oldName, mod) + if not self.mods[oldName] then + if self.parent then + return self.parent:ConvertModInternal(oldName, mod) + end + return false + end + + local oldList = self.mods[oldName] + for i = 1, #oldList do + local curMod = oldList[i] + if oldName == curMod.name and mod.type == curMod.type and mod.flags == curMod.flags and mod.keywordFlags == curMod.keywordFlags and mod.source == curMod.source and not curMod.converted then + -- Remove from old name's bucket + t_remove(oldList, i) + -- Add to new name's bucket + local newName = mod.name + if not self.mods[newName] then + self.mods[newName] = { } + end + mod.converted = true + t_insert(self.mods[newName], mod) + return true + end + end + + if self.parent then + return self.parent:ConvertModInternal(oldName, mod) + end + + return false +end + function ModDBClass:AddList(modList) local mods = self.mods for i, mod in ipairs(modList) do diff --git a/src/Classes/ModList.lua b/src/Classes/ModList.lua index 00ae37856b..7bbadba7d6 100644 --- a/src/Classes/ModList.lua +++ b/src/Classes/ModList.lua @@ -45,6 +45,27 @@ function ModListClass:ReplaceModInternal(mod) return false end +---ConvertModInternal +--- Converts an existing mod with oldName to a new mod with a different name. +--- If no matching mod exists, then the function returns false +---@param oldName string @The name of the existing mod to find +---@param mod table @The new mod to replace it with +---@return boolean @Whether any mod was converted +function ModListClass:ConvertModInternal(oldName, mod) + for i, curMod in ipairs(self) do + if oldName == curMod.name and mod.type == curMod.type and mod.flags == curMod.flags and mod.keywordFlags == curMod.keywordFlags and mod.source == curMod.source then + self[i] = mod + return true + end + end + + if self.parent then + return self.parent:ConvertModInternal(oldName, mod) + end + + return false +end + function ModListClass:MergeMod(mod, skipNonAdditive) if mod.type == "BASE" or mod.type == "INC" or mod.type == "MORE" then for i = 1, #self do diff --git a/src/Classes/ModStore.lua b/src/Classes/ModStore.lua index 6470f1b219..7e665e923d 100644 --- a/src/Classes/ModStore.lua +++ b/src/Classes/ModStore.lua @@ -110,6 +110,19 @@ function ModStoreClass:ReplaceMod(...) end end +---ConvertMod +--- Converts an existing mod to a new name, replacing it in the store. +--- Finds a mod matching oldName with the same type, flags, keywordFlags, and source as the new mod. +--- If no matching mod exists, the new mod is added instead. +---@param oldName string @The name of the existing mod to convert +---@param ... any @Parameters to be passed along to the modLib.createMod function (new name, type, value, source, ...) +function ModStoreClass:ConvertMod(oldName, ...) + local mod = mod_createMod(...) + if not self:ConvertModInternal(oldName, mod) then + self:AddMod(mod) + end +end + function ModStoreClass:Combine(modType, cfg, ...) if modType == "MORE" then return self:More(cfg, ...) diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index cd5a2bc12d..ba8b6a0944 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -376,6 +376,8 @@ local function doActorAttribsConditions(env, actor) condList["StrHighestAttribute"] = output.Str >= output.Dex and output.Str >= output.Int condList["IntHighestAttribute"] = output.Int >= output.Str and output.Int >= output.Dex condList["DexHighestAttribute"] = output.Dex >= output.Str and output.Dex >= output.Int + condList["IntSingleHighestAttribute"] = output.Int > output.Str and output.Int > output.Dex + condList["DexSingleHighestAttribute"] = output.Dex > output.Str and output.Dex > output.Int end end