local L = ww_localization local function stringsToFuncs(strTable) local funcTable = {} if not strTable then return funcTable end for major, tbl in pairs(strTable) do funcTable[major] = {} for minor, funcStr in pairs(tbl) do funcTable[major][minor] = loadstring(funcStr)() end end return funcTable end local function noop_up(vars) vars.dataMinorVersion = vars.dataMinorVersion + 1 return vars end local noop_down = [[ return function(vars) vars.dataMinorVersion = vars.dataMinorVersion - 1 return vars end ]] local function noop_major_up(vars) vars.dataMajorVersion = vars.dataMajorVersion + 1 vars.dataMinorVersion = 0 return vars end local function replaceStats(vars, conversions) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight] then for oldStat, newStat in pairs(conversions) do if vars.weightsList[class][weight][newStat] == nil then vars.weightsList[class][weight][newStat] = vars.weightsList[class][weight][oldStat] end vars.weightsList[class][weight][oldStat] = nil end end end end end local replaceStatsStr = [[ local function replaceStats(vars, conversions) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight] then for oldStat, newStat in pairs(conversions) do if vars.weightsList[class][weight][newStat] == nil then vars.weightsList[class][weight][newStat] = vars.weightsList[class][weight][oldStat] end vars.weightsList[class][weight][oldStat] = nil end end end end end ]] local function upgradeAccountToNewMetaEffects(vars) local conversions = { ["chance on being hit to gain 20% reduction to physical damage taken"] = "chance on being hit to gain 20% reduction to damage taken", } replaceStats(vars, conversions) vars.dataMinorVersion = 7 return vars end local downgradeAccountFromNewMetaEffects = replaceStatsStr .. [[ return function(vars) local conversions = { ["chance on being hit to gain 20% reduction to damage taken"] = "chance on being hit to gain 20% reduction to physical damage taken", } replaceStats(vars, conversions) vars.dataMinorVersion = 6 return vars end ]] local function upgradeAccountToReplaceEmptyOptions(vars) if not vars.options then vars.options = ww_deepTableCopy(ww_defaultVars.options) end vars.dataMinorVersion = 6 return vars end local function upgradeAccountToMonks(vars) if vars.weightsList["MONK"] == nil then vars.weightsList["MONK"] = ww_deepTableCopy(ww_defaultVars.weightsList["MONK"]) table.insert(vars.weightsList, 5, "MONK") end vars.dataMinorVersion = 5 return vars end local function upgradeAccountToMoPEnhancements(vars) local limit = vars.options.gems.qualityLimit if limit <= 10 and limit >= 8 then vars.options.gems.qualityLimit = limit + 3 end vars.dataMinorVersion = 4 return vars end local downgradeAccountFromMoPEnhancements = [[ return function(vars) local limit = vars.options.gems.qualityLimit if limit <= 13 and limit >= 11 then vars.options.gems.qualityLimit = limit - 3 elseif limit == 14 then vars.options.gems.qualityLimit = 10 end vars.dataMinorVersion = 3 return vars end ]] local function upgradeAccountToPVPResilience(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["pvp resilience"] == nil then vars.weightsList[class][weight]["pvp resilience"] = vars.weightsList[class][weight]["resilience"] end vars.weightsList[class][weight]["resilience"] = nil end end vars.dataMinorVersion = 3 return vars end local downgradeAccountFromPVPResilience = [[ return function(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["resilience"] == nil then vars.weightsList[class][weight]["resilience"] = vars.weightsList[class][weight]["pvp resilience"] end vars.weightsList[class][weight]["pvp resilience"] = nil end end vars.dataMinorVersion = 2 return vars end ]] local function upgradeAccountToMoPStats(vars) local stats = { "critical strike", "dodge", "expertise", "haste", "hit", "mastery", "parry", "ranged critical strike", "ranged haste", "ranged hit", "resilience", "spell critical strike", "spell hit" } for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do for _, stat in ipairs(stats) do if vars.weightsList[class][weight][stat] == nil then vars.weightsList[class][weight][stat] = vars.weightsList[class][weight][stat .. " rating"] end vars.weightsList[class][weight][stat .. " rating"] = nil end end end vars.dataMinorVersion = 2 return vars end local downgradeAccountFromMoPStats = [[ return function(vars) local stats = { "critical strike", "dodge", "expertise", "haste", "hit", "mastery", "parry", "ranged critical strike", "ranged haste", "ranged hit", "resilience", "spell critical strike", "spell hit" } for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do for _, stat in ipairs(stats) do if vars.weightsList[class][weight][stat .. " rating"] == nil then vars.weightsList[class][weight][stat .. " rating"] = vars.weightsList[class][weight][stat] end vars.weightsList[class][weight][stat] = nil end end end vars.dataMinorVersion = 1 return vars end ]] local function upgradeAccountToCriticalEffect(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["critical effect (percent)"] == nil then local value = (vars.weightsList[class][weight]["critical damage (percent)"] or 0) + (vars.weightsList[class][weight]["critical healing (percent)"] or 0) if value ~= 0 then vars.weightsList[class][weight]["critical effect (percent)"] = value end end end end vars.dataMinorVersion = 1 return vars end local function upgradeAccountToEnchants(vars) if not vars.options.calculation then vars.options.calculation = {} end if not vars.options.calculation.useEffectUptimeRatio then vars.options.calculation.useEffectUptimeRatio = vars.options.useEffects.uptimeRatio or ww_defaultVars.options.calculation.useEffectUptimeRatio end vars.options.useEffects = nil if vars.options.tooltip.showAlternateEnhancements == nil then vars.options.tooltip.showAlternateEnhancements = vars.options.tooltip.showAlternateGems or ww_defaultVars.options.tooltip.showAlternateEnhancements end vars.options.tooltip.showAlternateGems = nil if vars.options.tooltip.showEnhancements == nil then vars.options.tooltip.showEnhancements = vars.options.tooltip.showIdealGems or ww_defaultVars.options.tooltip.showEnhancements end vars.options.tooltip.showIdealGems = nil if vars.options.tooltip.showEnhancementStats == nil then vars.options.tooltip.showEnhancementStats = vars.options.tooltip.showIdealGemStats or ww_defaultVars.options.tooltip.showEnhancementStats end vars.options.tooltip.showIdealGemStats = nil if vars.options.tooltip.showEnhancementsWhen == nil then vars.options.tooltip.showEnhancementsWhen = ww_defaultVars.options.tooltip.showEnhancementsWhen end if not vars.options.enchants then vars.options.enchants = ww_deepTableCopy(ww_defaultVars.options.enchants) end vars.dataMajorVersion = 2 vars.dataMinorVersion = 0 return vars end local downgradeAccountFromEnchants = [[ return function(vars) if not vars.options.useEffects then vars.options.useEffects = {} end if not vars.options.useEffects.uptimeRatio then vars.options.useEffects.uptimeRatio = vars.options.calculation.useEffectUptimeRatio or ww_defaultVars.options.useEffects.uptimeRatio end if vars.options.tooltip.showAlternateGems == nil then vars.options.tooltip.showAlternateGems = vars.options.tooltip.showAlternateEnhancements or ww_defaultVars.options.tooltip.showAlternateGems end vars.options.tooltip.showAlternateEnhancements = nil if vars.options.tooltip.showIdealGems == nil then vars.options.tooltip.showIdealGems = vars.options.tooltip.showEnhancements or ww_defaultVars.options.tooltip.showIdealGems end vars.options.tooltip.showEnhancements = nil if vars.options.tooltip.showIdealGemStats == nil then vars.options.tooltip.showIdealGemStats = vars.options.tooltip.showEnhancementStats or ww_defaultVars.options.tooltip.showIdealGemStats end vars.options.tooltip.showEnhancementStats = nil vars.dataMajorVersion = 1 vars.dataMinorVersion = 25 return vars end ]] local function UpgradeAccountToShowZeroScores(vars) if vars.options.tooltip.showZeroScores == nil then vars.options.tooltip.showZeroScores = false end vars.dataMinorVersion = 25 return vars end local function upgradeAccountToCataclysmGems(vars) if vars.options.gems.qualityLimit == 7 then vars.options.gems.qualityLimit = 10 end vars.dataMinorVersion = 24 return vars end local function upgradeAccountToMeleeCrit(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["melee dps"] or vars.weightsList[class][weight]["feral attack power"] or vars.weightsList[class][weight]["expertise rating"] then if vars.weightsList[class][weight]["melee critical strike rating"] == nil then vars.weightsList[class][weight]["melee critical strike rating"] = vars.weightsList[class][weight]["critical strike rating"] end end end end vars.dataMinorVersion = 23 return vars end local function upgradeAccountToMastery(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["mastery rating"] == nil then if ww_defaultVars.weightsList[class][weight] then vars.weightsList[class][weight]["mastery rating"] = ww_defaultVars.weightsList[class][weight]["mastery rating"] or 100 else vars.weightsList[class][weight]["mastery rating"] = 100 end end end end vars.dataMinorVersion = 22 return vars end local function upgradeAccountToNewClassNameDisplayOptions(vars) if vars.options.tooltip.showClassNames == "Others" then vars.options.tooltip.showClassNames = "Other Classes" end vars.dataMinorVersion = 21 return vars end local downgradeAccountFromNewClassNameDisplayOptions = [[ return function(vars) if vars.options.tooltip.showClassNames == "Other Classes" then vars.options.tooltip.showClassNames = "Others" end vars.dataMinorVersion = 20 return vars end ]] local function upgradeAccountToRangedCritHasteAndHit(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["ranged attack power"] ~= nil or vars.weightsList[class][weight]["ranged dps"] ~= nil then if vars.weightsList[class][weight]["ranged critical strike rating"] == nil then vars.weightsList[class][weight]["ranged critical strike rating"] = vars.weightsList[class][weight]["critical strike rating"] end if vars.weightsList[class][weight]["ranged haste rating"] == nil then vars.weightsList[class][weight]["ranged haste rating"] = vars.weightsList[class][weight]["haste rating"] end if vars.weightsList[class][weight]["ranged hit rating"] == nil then vars.weightsList[class][weight]["ranged hit rating"] = vars.weightsList[class][weight]["hit rating"] end end end end vars.dataMinorVersion = 20 return vars end local function upgradeAccountToSpellHitAndCrit(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["spell power"] ~= nil and vars.weightsList[class][weight]["attack power"] == nil then if vars.weightsList[class][weight]["spell critical strike rating"] == nil then vars.weightsList[class][weight]["spell critical strike rating"] = vars.weightsList[class][weight]["critical strike rating"] end if vars.weightsList[class][weight]["spell hit rating"] == nil then vars.weightsList[class][weight]["spell hit rating"] = vars.weightsList[class][weight]["hit rating"] end end end end vars.dataMinorVersion = 19 return vars end local function upgradeAccountToNoMeleeDamage(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["average melee weapon damage"] == nil then vars.weightsList[class][weight]["average melee weapon damage"] = vars.weightsList[class][weight]["melee damage"] end if vars.weightsList[class][weight]["maximum melee weapon damage"] == nil then vars.weightsList[class][weight]["maximum melee weapon damage"] = vars.weightsList[class][weight]["melee damage"] end vars.weightsList[class][weight]["melee damage"] = nil end end vars.dataMinorVersion = 18 return vars end local function upgradeAccountToAverageWeaponDamage(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["average melee weapon damage"] == nil then vars.weightsList[class][weight]["average melee weapon damage"] = vars.weightsList[class][weight]["minimum melee weapon damage"] end vars.weightsList[class][weight]["minimum melee weapon damage"] = nil if vars.weightsList[class][weight]["average ranged weapon damage"] == nil then vars.weightsList[class][weight]["average ranged weapon damage"] = vars.weightsList[class][weight]["minimum ranged weapon damage"] end vars.weightsList[class][weight]["minimum ranged weapon damage"] = nil end end vars.dataMinorVersion = 17 return vars end local downgradeAccountFromAverageWeaponDamage = [[ return function(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["minimum melee weapon damage"] == nil then vars.weightsList[class][weight]["minimum melee weapon damage"] = vars.weightsList[class][weight]["average melee weapon damage"] end if vars.weightsList[class][weight]["minimum ranged weapon damage"] == nil then vars.weightsList[class][weight]["minimum ranged weapon damage"] = vars.weightsList[class][weight]["average ranged weapon damage"] end end end vars.dataMinorVersion = 16 return vars end ]] local function upgradeAccountToMeleeStatsAndRangedWeaponDamage(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["ranged attack power"] ~= nil or vars.weightsList[class][weight]["ranged dps"] ~= nil then if vars.weightsList[class][weight]["maximum ranged weapon damage"] == nil then vars.weightsList[class][weight]["maximum ranged weapon damage"] = vars.weightsList[class][weight]["maximum weapon damage"] end vars.weightsList[class][weight]["maximum weapon damage"] = nil if vars.weightsList[class][weight]["minimum ranged weapon damage"] == nil then vars.weightsList[class][weight]["minimum ranged weapon damage"] = vars.weightsList[class][weight]["minimum weapon damage"] end vars.weightsList[class][weight]["minimum weapon damage"] = nil end if vars.weightsList[class][weight]["melee dps"] == nil then vars.weightsList[class][weight]["melee dps"] = vars.weightsList[class][weight]["dps"] end vars.weightsList[class][weight]["dps"] = nil if vars.weightsList[class][weight]["minimum melee weapon damage"] == nil then vars.weightsList[class][weight]["minimum melee weapon damage"] = vars.weightsList[class][weight]["minimum weapon damage"] end vars.weightsList[class][weight]["minimum weapon damage"] = nil if vars.weightsList[class][weight]["maximum melee weapon damage"] == nil then vars.weightsList[class][weight]["maximum melee weapon damage"] = vars.weightsList[class][weight]["maximum weapon damage"] end vars.weightsList[class][weight]["maximum weapon damage"] = nil end end vars.dataMinorVersion = 16 return vars end local downgradeAccountFromMeleeStatsAndRangedWeaponDamage = [[ return function(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["maximum weapon damage"] == nil then vars.weightsList[class][weight]["maximum weapon damage"] = vars.weightsList[class][weight]["maximum ranged weapon damage"] end if vars.weightsList[class][weight]["minimum weapon damage"] == nil then vars.weightsList[class][weight]["minimum weapon damage"] = vars.weightsList[class][weight]["minimum ranged weapon damage"] end if vars.weightsList[class][weight]["dps"] == nil then vars.weightsList[class][weight]["dps"] = vars.weightsList[class][weight]["melee dps"] end if vars.weightsList[class][weight]["minimum weapon damage"] == nil then vars.weightsList[class][weight]["minimum weapon damage"] = vars.weightsList[class][weight]["minimum melee weapon damage"] end if vars.weightsList[class][weight]["maximum weapon damage"] == nil then vars.weightsList[class][weight]["maximum weapon damage"] = vars.weightsList[class][weight]["maximum melee weapon damage"] end end end vars.dataMinorVersion = 15 return vars end ]] local function upgradeAccountToFixStunResistChance(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["stun resist chance (percent)"] == nil then vars.weightsList[class][weight]["stun resist chance (percent)"] = vars.weightsList[class][weight]["stun resistance (percent)"] vars.weightsList[class][weight]["stun resistance (percent)"] = nil end end end vars.dataMinorVersion = 14 return vars end local function FixStunResistChance(vars) vars = upgradeAccountToFixStunResistChance(vars) vars.dataMinorVersion = 15 return vars end local downgradeAccountFromFixStunResistChance = [[ return function(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if vars.weightsList[class][weight]["stun resistance (percent)"] == nil then vars.weightsList[class][weight]["stun resistance (percent)"] = vars.weightsList[class][weight]["stun resist chance (percent)"] vars.weightsList[class][weight]["stun resist chance (percent)"] = nil end end end vars.dataMinorVersion = 13 return vars end ]] local function upgradeAccountToDebugKey(vars) if vars.options.tooltip.showDebugInfo == nil then vars.options.tooltip.showDebugInfo = "Never" end vars.dataMinorVersion = 13 return vars end local function upgradeAccountToTriggers(vars) if vars.savedTriggers then for _, class in ipairs(vars.savedTriggers) do for _, weight in ipairs(vars.savedTriggers[class]) do if vars.weightsList[class] and vars.weightsList[class][weight] then vars.weightsList[class][weight].triggers = vars.savedTriggers[class][weight] end end end end vars.savedTriggers = nil for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do if not vars.weightsList[class][weight].triggers then vars.weightsList[class][weight].triggers = {} if vars.weightsList[class][weight]["dps"] or (vars.weightsList[class][weight]["attack power"] and not vars.weightsList[class][weight]["ranged attack power"]) then vars.weightsList[class][weight].triggers.meleeDamage = true end if vars.weightsList[class][weight]["ranged dps"] or vars.weightsList[class][weight]["ranged attack power"] then vars.weightsList[class][weight].triggers.rangedDamage = true end if vars.weightsList[class][weight]["spell power"] and vars.weightsList[class][weight]["hit rating"] then vars.weightsList[class][weight].triggers.harmfulSpell = true end if vars.weightsList[class][weight]["spell power"] and not vars.weightsList[class][weight]["hit rating"] then vars.weightsList[class][weight].triggers.helpfulSpell = true end end end end vars.dataMinorVersion = 12 return vars end local downgradeAccountFromTriggers = [[ return function(vars) vars.savedTriggers = {} for i, class in ipairs(vars.weightsList) do vars.savedTriggers[i] = class vars.savedTriggers[class] = {} for j, weight in ipairs(vars.weightsList[class]) do vars.savedTriggers[class][j] = weight vars.savedTriggers[class][weight] = vars.weightsList[class][weight].triggers vars.weightsList[class][weight].triggers = nil end end vars.dataMinorVersion = 11 return vars end ]] local function upgradeAccountToUseEffectRatio(vars) if not vars.options.useEffects then vars.options.useEffects = {} end if not vars.options.useEffects.uptimeRatio then vars.options.useEffects.uptimeRatio = 0.8 end vars.dataMinorVersion = 11 return vars end local function upgradeAccountToWorkingMeleeDamage(vars) for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do vars.weightsList[class][weight]["melee damage"] = vars.weightsList[class][weight]["weapon damage"] vars.weightsList[class][weight]["weapon damage"] = nil end end vars.dataMinorVersion = 10 return vars end local function upgradeAccountToWorkingResistances(vars) local resistances = { "arcane", "fire", "frost", "holy", "nature", "shadow", } for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do for _, resistance in ipairs(resistances) do vars.weightsList[class][weight][resistance .. " resistance"] = vars.weightsList[class][weight][resistance] vars.weightsList[class][weight][resistance] = nil end end end vars.dataMinorVersion = 9 return vars end local function upgradeAccountToShowAlternateGemsTypoFix(vars) if vars.options.tooltip.showAlternateGems == nil then vars.options.tooltip.showAlternateGems = "Alt" end vars.options.tooltip.showAlternativeGems = nil vars.dataMinorVersion = 8 return vars end local function upgradeAccountToShowAlternateGems(vars) if vars.options.tooltip.showAlternateGems == nil then vars.options.tooltip.showAlternateGems = "Alt" end vars.dataMinorVersion = 7 return vars end local function upgradeAccountToGemSources(vars) if not vars.options.gems.types then vars.options.gems.types = {} end if not vars.options.gems.sources then vars.options.gems.sources = {} end if vars.options.gems.usedTypes then if vars.options.gems.types["Normal"] == nil then vars.options.gems.types["Normal"] = vars.options.gems.usedTypes["Normal"] end if vars.options.gems.types["Unique-Equipped"] == nil then vars.options.gems.types["Unique-Equipped"] = vars.options.gems.usedTypes["Unique-Equipped"] end if vars.options.gems.types["Jewelcrafter-Only"] == nil then vars.options.gems.types["Jewelcrafter-Only"] = vars.options.gems.usedTypes["Jewelcrafter-Only"] end if vars.options.gems.sources["Procced"] == nil then vars.options.gems.sources["Procced"] = vars.options.gems.usedTypes["Procced"] end end if vars.options.gems.types["Normal"] == nil then vars.options.gems.types["Normal"] = true end if vars.options.gems.types["Unique-Equipped"] == nil then vars.options.gems.types["Unique-Equipped"] = false end if vars.options.gems.types["Jewelcrafter-Only"] == nil then vars.options.gems.types["Jewelcrafter-Only"] = false end if vars.options.gems.sources["Vendor"] == nil then vars.options.gems.sources["Vendor"] = true end if vars.options.gems.sources["PVP-Vendor"] == nil then vars.options.gems.sources["PVP-Vendor"] = false end if vars.options.gems.sources["Crafted"] == nil then vars.options.gems.sources["Crafted"] = true end if vars.options.gems.sources["Procced"] == nil then vars.options.gems.sources["Procced"] = true end if vars.options.gems.sources["Drop"] == nil then vars.options.gems.sources["Drop"] = false end if vars.options.gems.sources["Quest"] == nil then vars.options.gems.sources["Quest"] = false end vars.options.gems.usedTypes = nil vars.dataMinorVersion = 6 return vars end local downgradeAccountFromGemSources = [[ return function(vars) if not vars.options.gems.usedTypes then vars.options.gems.usedTypes = {} end if vars.options.gems.types then if vars.options.gems.usedTypes["Normal"] == nil then vars.options.gems.usedTypes["Normal"] = vars.options.gems.types["Normal"] end if vars.options.gems.usedTypes["Unique-Equipped"] == nil then vars.options.gems.usedTypes["Unique-Equipped"] = vars.options.gems.types["Unique-Equipped"] end if vars.options.gems.usedTypes["Jewelcrafter-Only"] == nil then vars.options.gems.usedTypes["Jewelcrafter-Only"] = vars.options.gems.types["Jewelcrafter-Only"] end end if vars.options.gems.sources then if vars.options.gems.usedTypes["Procced"] == nil then vars.options.gems.usedTypes["Procced"] = vars.options.gems.sources["Procced"] end end if vars.options.gems.usedTypes["Normal"] == nil then vars.options.gems.usedTypes["Normal"] = true end if vars.options.gems.usedTypes["Unique-Equipped"] == nil then vars.options.gems.usedTypes["Unique-Equipped"] = false end if vars.options.gems.usedTypes["Jewelcrafter-Only"] == nil then vars.options.gems.usedTypes["Jewelcrafter-Only"] = false end if vars.options.gems.usedTypes["Procced"] == nil then vars.options.gems.usedTypes["Procced"] = true end vars.dataMinorVersion = 5 return vars end ]] local function upgradeAccountToFixedConfigOptions(vars) if vars.options.breakSocketColors ~= nil then vars.options.gems.breakSocketColors = vars.options.breakSocketColors vars.options.breakSocketColors = nil else vars.options.gems.breakSocketColors = true end if vars.options.neverBreakSocketColors ~= nil then vars.options.gems.neverBreakSocketColors = vars.options.neverBreakSocketColors vars.options.neverBreakSocketColors = nil else vars.options.gems.neverBreakSocketColors = false end if vars.options.normalizeWeights ~= nil then vars.options.tooltip.normalizeWeights = vars.options.normalizeWeights vars.options.normalizeWeights = nil else vars.options.tooltip.normalizeWeights = true end vars.dataMinorVersion = 5 return vars end local downgradeAccountFromFixedConfigOptions = [[ return function(vars) if vars.options.tooltip.normalizeWeights ~= nil then vars.options.normalizeWeights = vars.options.tooltip.normalizeWeights vars.options.tooltip.normalizeWeights = nil else vars.options.normalizeWeights = true end vars.dataMinorVersion = 4 return vars end ]] local function upgradeAccountToPartitionedGems(vars) local qualityConversion = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 4, [6] = 5, [7] = 5, [8] = 6, [9] = 7, [10] = 7, [11] = 7, } if not vars.options.gems then vars.options.gems = {} end if not vars.options.gems.usedTypes then vars.options.gems.usedTypes = {} end vars.options.gems.usedTypes["Normal"] = true vars.options.gems.usedTypes["Unique-Equipped"] = vars.options.gemQualityLimit == 5 or vars.options.gemQualityLimit == 10 vars.options.gems.usedTypes["Jewelcrafter-Only"] = vars.options.gemQualityLimit == 11 vars.options.gems.usedTypes["Procced"] = vars.options.gemQualityLimit == 7 vars.options.gems.qualityLimit = qualityConversion[vars.options.gemQualityLimit] vars.options.gems.breakSocketColors = vars.options.breakSocketColors vars.options.gems.neverBreakSocketColors = vars.options.neverBreakSocketColors vars.options.gemQualityLimit = nil vars.options.breakSocketColors = nil vars.options.neverBreakSocketColors = nil vars.dataMinorVersion = 4 return vars end local downgradeAccountFromPartitionedGems = [[ return function(vars) local qualityConversion = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, [6] = 8, [7] = 9, } vars.options.gemQualityLimit = qualityConversion[vars.options.gems.qualityLimit] if vars.options.gems.usedTypes["Unique-Equipped"] and (vars.options.gems.qualityLimit == 4 or vars.options.gems.qualityLimit == 7) then vars.options.gemQualityLimit = vars.options.gemQualityLimit + 1 end if vars.options.gems.usedTypes["Procced"] and vars.options.gems.qualityLimit == 5 then vars.options.gemQualityLimit = 7 end if vars.options.gems.usedTypes["Jewelcrafter-Only"] and vars.options.gems.qualityLimit == 7 then vars.options.gemQualityLimit = 11 end vars.options.breakSocketColors = vars.options.gems.breakSocketColors vars.options.neverBreakSocketColors = vars.options.gems.neverBreakSocketColors vars.options.gems = nil vars.dataMinorVersion = 3 return vars end ]] local function upgradeAccountToShowDifferences(vars) if vars.options.tooltip.showDifferences == nil then vars.options.tooltip.showDifferences = true end vars.dataMinorVersion = 3 return vars end local function upgradeAccountToCorrectShowClassNames(vars) if vars.options.tooltip.showClassNames == nil then if vars.options.showClassNames == nil then vars.options.tooltip.showClassNames = "Others" else vars.options.tooltip.showClassNames = vars.options.showClassNames end end vars.options.showClassNames = nil vars.dataMinorVersion = 2 return vars end local function upgradeAccountToBetterMetaEffectNames(vars) local newName local conversion = { ["armor from items percent"] = "armor from items (percent)", ["block value percent"] = "block value (percent)", ["chance to increase melee/ranged attack speed"] = "chance to increase physical haste", ["chance to increase spell cast speed"] = "chance to increase spell haste", ["critical damage percent"] = "critical damage (percent)", ["critical healing percent"] = "critical healing (percent)", ["fear duration reduction percent"] = "fear duration reduction (percent)", ["silence duration reduction percent"] = "silence duration reduction (percent)", ["snare/root duration reduction percent"] = "snare/root duration reduction (percent)", ["spell damage taken reduction percent"] = "spell damage taken reduction (percent)", ["spell reflect percent"] = "spell reflect (percent)", ["stun duration reduction percent"] = "stun duration reduction (percent)", ["stun resistance percent"] = "stun resistance (percent)", ["threat percent"] = false, ["threat reduction percent"] = "threat reduction (percent)", } for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do for stat, value in pairs(vars.weightsList[class][weight]) do newName = conversion[stat] -- Don't touch unchanged stat names, clear deleted stat names if newName ~= nil then vars.weightsList[class][weight][stat] = nil end -- move the value to the new stat name if newName then vars.weightsList[class][weight][newName] = value end end end end vars.dataMinorVersion = 1 return vars end local downgradeAccountFromBetterMetaEffectNames = [[ return function (vars) local newName local conversion = { ["armor from items (percent)"] = "armor from items percent", ["block value (percent)"] = "block value percent", ["chance to increase physical haste"] = "chance to increase melee/ranged attack speed", ["chance to increase spell haste"] = "chance to increase spell cast speed", ["critical damage (percent)"] = "critical damage percent", ["critical healing (percent)"] = "critical healing percent", ["fear duration reduction (percent)"] = "fear duration reduction percent", ["silence duration reduction (percent)"] = "silence duration reduction percent", ["snare/root duration reduction (percent)"] = "snare/root duration reduction percent", ["spell damage taken reduction (percent)"] = "spell damage taken reduction percent", ["spell reflect (percent)"] = "spell reflect percent", ["stun duration reduction (percent)"] = "stun duration reduction percent", ["stun resistance (percent)"] = "stun resistance percent", ["threat reduction (percent)"] = "threat reduction percent", } for _, class in ipairs(vars.weightsList) do for _, weight in ipairs(vars.weightsList[class]) do for stat, value in pairs(vars.weightsList[class][weight]) do newName = conversion[stat] -- move the value to the new stat name if newName then vars.weightsList[class][weight][stat] = nil vars.weightsList[class][weight][newName] = value end end end end vars.dataMinorVersion = 0 return vars end ]] local downgradeAccountToDevelopment = [[ return function(vars) vars.dataMajorVersion = 0 vars.dataMinorVersion = 10 return vars end ]] local downgradeCharToDevelopment = [[ return function(vars) vars.dataMajorVersion = 0 vars.dataMinorVersion = 2 return vars end ]] local function upgradeAccountToConfig(vars) local table = vars.options.tooltip local conversion = { [true] = "Always", [false] = "Never", ["LSHIFT"] = "Left Shift", ["RSHIFT"] = "Right Shift", ["SHIFT"] = "Shift", ["LALT"] = "Left Alt", ["RALT"] = "Right Alt", ["ALT"] = "Alt", ["LCTRL"] = "Left Control", ["RCTRL"] = "Right Control", ["CTRL"] = "Control", } local keys = { ["showIdealGemStats"] = true, ["showIdealWeights"] = true, ["showWeights"] = true, ["showIdealGems"] = true, } for key, value in pairs(table) do if keys[key] then if conversion[value] == nil then return nil end table[key] = conversion[value] end end vars.dataMinorVersion = 10 return vars end local downgradeAccountFromConfig = [[ return function(vars) local table = vars.options.tooltip local conversion = { ["Always"] = true, ["Never"] = false, ["Left Shift"] = "LSHIFT", ["Right Shift"] = "RSHIFT", ["Shift"] = "SHIFT", ["Left Alt"] = "LALT", ["Right Alt"] = "RALT", ["Alt"] = "ALT", ["Left Control"] = "LCTRL", ["Right Control"] = "RCTRL", ["Control"] = "CTRL", } local keys = { ["showIdealGemStats"] = true, ["showIdealWeights"] = true, ["showWeights"] = true, ["showIdealGems"] = true, } for key, value in pairs(table) do if keys[key] then if conversion[value] == nil then return nil end table[key] = conversion[value] end end vars.dataMinorVersion = 9 return vars end ]] local function upgradeAccountForceGemColors(vars) if vars.options.breakSocketColors == nil then vars.options.breakSocketColors = true end if vars.options.neverBreakSocketColors == nil then vars.options.neverBreakSocketColors = false end vars.dataMinorVersion = 9 return vars end local function upgradeAccountHideModKeyHints(vars) if vars.options.tooltip.hideHints == nil then vars.options.tooltip.hideHints = false end vars.dataMinorVersion = 8 return vars end local function upgradeAccountShowClassNames(vars) if not vars.options.tooltip.showClassNames then vars.options.tooltip.showClassNames = "Others" end vars.dataMinorVersion = 7 return vars end local function upgradeAccountToHandleModifierKeys(vars) if not vars.options.tooltip then vars.options.tooltip = ww_deepTableCopy(ww_defaultVars.options.tooltip) end vars.dataMinorVersion = 5 return vars end local function upgradeAccountToOrderedLists(vars) local i, j = 1 local weightsListCopy = {} for class, weights in pairs(vars.weightsList) do if type(class) ~= "string" then return nil end weightsListCopy[i] = class weightsListCopy[class] = {} j = 1 for weight, stats in pairs(weights) do if type(weight) ~= "string" then return nil end weightsListCopy[class][j] = weight weightsListCopy[class][weight] = stats j = j + 1 end i = i + 1 end vars.weightsList = weightsListCopy vars.dataMinorVersion = 4 return vars end local downgradeAccountFromOrderedLists = [[ return function(vars) local weightsListCopy = {} for i, class in ipairs(vars.weightsList) do weightsListCopy[class] = {} for j, weight in ipairs(vars.weightsList[class]) do weightsListCopy[class][weight] = class[weight] end end vars.weightsList = weightsListCopy vars.dataMinorVersion = 3 return vars end ]] local function upgradeCharToOrderedLists(vars) local i = 1 local activeWeightsCopy = {} for class, weights in pairs(vars.activeWeights) do if type(class) ~= "string" then return nil end activeWeightsCopy[i] = class activeWeightsCopy[class] = {} for j, weight in pairs(weights) do if type(weight) ~= "string" then return nil end activeWeightsCopy[class][j] = weight end i = i + 1 end vars.activeWeights = activeWeightsCopy vars.dataMinorVersion = 2 return vars end local downgradeCharFromOrderedLists = [[ return function(vars) local activeWeightsCopy = {} for i, class in ipairs(vars.activeWeights) do activeWeightsCopy[class] = {} for j, weight in ipairs(vars.activeWeights[class]) do activeWeightsCopy[class][j] = weight end end vars.activeWeights = activeWeightsCopy vars.dataMinorVersion = 1 return vars end ]] local function upgradeAccountToGemQuality(vars) if not vars.options.gemQualityLimit then vars.options.gemQualityLimit = 9 end vars.dataMinorVersion = 3 return vars end local function upgradeAccountToNormalization(vars) if not vars.options then vars.options = {} end if vars.options.normalizeWeights == nil then vars.options.normalizeWeights = true end vars.dataMinorVersion = 2 return vars end function ww_copyDefaultAccountVars() return ww_deepTableCopy(ww_defaultVars) end local function createActiveWeights(class) local activeWeights = {class} activeWeights[class] = {} for i, name in ipairs(ww_vars.weightsList[class]) do activeWeights[class][i] = name end return activeWeights end local function ww_copyDefaultCharVars() local charVars charVars = ww_deepTableCopy(ww_defaultCharVars) charVars.activeWeights = createActiveWeights(WeightsWatcher.player.class) return charVars end local upgradeAccountFunctions = { [0] = { [0] = ww_copyDefaultAccountVars, [1] = upgradeAccountToNormalization, [2] = upgradeAccountToGemQuality, [3] = upgradeAccountToOrderedLists, [4] = upgradeAccountToHandleModifierKeys, [5] = noop_up, [6] = upgradeAccountShowClassNames, [7] = upgradeAccountHideModKeyHints, [8] = upgradeAccountForceGemColors, [9] = upgradeAccountToConfig, [10] = noop_major_up, }, [1] = { [0] = upgradeAccountToBetterMetaEffectNames, [1] = upgradeAccountToCorrectShowClassNames, [2] = upgradeAccountToShowDifferences, [3] = upgradeAccountToPartitionedGems, [4] = upgradeAccountToFixedConfigOptions, [5] = upgradeAccountToGemSources, [6] = upgradeAccountToShowAlternateGems, [7] = upgradeAccountToShowAlternateGemsTypoFix, [8] = upgradeAccountToWorkingResistances, [9] = upgradeAccountToWorkingMeleeDamage, [10] = upgradeAccountToUseEffectRatio, [11] = upgradeAccountToTriggers, [12] = upgradeAccountToDebugKey, [13] = upgradeAccountToFixStunResistChance, [14] = FixStunResistChance, [15] = upgradeAccountToMeleeStatsAndRangedWeaponDamage, [16] = upgradeAccountToAverageWeaponDamage, [17] = upgradeAccountToNoMeleeDamage, [18] = upgradeAccountToSpellHitAndCrit, [19] = upgradeAccountToRangedCritHasteAndHit, [20] = upgradeAccountToNewClassNameDisplayOptions, [21] = upgradeAccountToMastery, [22] = upgradeAccountToMeleeCrit, [23] = upgradeAccountToCataclysmGems, [24] = UpgradeAccountToShowZeroScores, [25] = upgradeAccountToEnchants, }, [2] = { [0] = upgradeAccountToCriticalEffect, [1] = upgradeAccountToMoPStats, [2] = upgradeAccountToPVPResilience, [3] = upgradeAccountToMoPEnhancements, [4] = upgradeAccountToMonks, [5] = upgradeAccountToReplaceEmptyOptions, [6] = upgradeAccountToNewMetaEffects, }, } local downgradeAccountFunctions = { [0] = { [2] = noop_down, [3] = noop_down, [4] = downgradeAccountFromOrderedLists, [5] = noop_down, [6] = noop_down, [7] = noop_down, [8] = noop_down, [9] = noop_down, [10] = downgradeAccountFromConfig, }, [1] = { [0] = downgradeAccountToDevelopment, [1] = downgradeAccountFromBetterMetaEffectNames, [2] = noop_down, [3] = noop_down, [4] = downgradeAccountFromPartitionedGems, [5] = downgradeAccountFromFixedConfigOptions, [6] = downgradeAccountFromGemSources, [7] = noop_down, [8] = noop_down, [9] = noop_down, [10] = noop_down, [11] = noop_down, [12] = downgradeAccountFromTriggers, [13] = noop_down, [14] = downgradeAccountFromFixStunResistChance, [15] = noop_down, [16] = downgradeAccountFromMeleeStatsAndRangedWeaponDamage, [17] = downgradeAccountFromAverageWeaponDamage, [18] = noop_down, [19] = noop_down, [20] = noop_down, [21] = downgradeAccountFromNewClassNameDisplayOptions, [22] = noop_down, [23] = noop_down, [24] = noop_down, [25] = noop_down, }, [2] = { [0] = downgradeAccountFromEnchants, [1] = noop_down, [2] = downgradeAccountFromMoPStats, [3] = downgradeAccountFromPVPResilience, [4] = downgradeAccountFromMoPEnhancements, [5] = noop_down, [6] = noop_down, [7] = downgradeAccountFromNewMetaEffects, }, } local upgradeCharFunctions = { [0] = { [0] = ww_copyDefaultCharVars, [1] = upgradeCharToOrderedLists, [2] = noop_major_up, }, } local downgradeCharFunctions = { [0] = { [2] = downgradeCharFromOrderedLists, }, [1] = { [0] = downgradeCharToDevelopment, }, } function WeightsWatcher.Upgrade(dataType) local oldMinorVersion, oldMajorVersion, newMinorVersion, newMajorVersion, vars, funcTable, direction, downgradeFunctions if dataType == "account" then vars = ww_vars newMinorVersion = ww_defaultVars.dataMinorVersion newMajorVersion = ww_defaultVars.dataMajorVersion funcTable = upgradeAccountFunctions downgradeFunctions = downgradeAccountFunctions elseif dataType == "character" then vars = ww_charVars newMinorVersion = ww_defaultCharVars.dataMinorVersion newMajorVersion = ww_defaultCharVars.dataMajorVersion funcTable = upgradeCharFunctions downgradeFunctions = downgradeCharFunctions else print(string.format(L["UPGRADE_ERR_INV_DATA_TYPE"], dataType)) return nil end dataType = L[dataType] if vars then oldMinorVersion = vars.dataMinorVersion oldMajorVersion = vars.dataMajorVersion end if not oldMinorVersion then oldMinorVersion = 0 end if not oldMajorVersion then oldMajorVersion = 0 end if newMajorVersion == oldMajorVersion and newMinorVersion == oldMinorVersion then return vars end if newMajorVersion > oldMajorVersion or (newMajorVersion == oldMajorVersion and newMinorVersion > oldMinorVersion) then direction = L["upgrade"] else direction = L["downgrade"] funcTable = stringsToFuncs(vars.downgradeFunctions) end if funcTable == nil then print(string.format(L["UPGRADE_ERR_NO_FUNC_TBL"], direction)) return nil end if oldMajorVersion == 0 and oldMinorVersion == 0 then print(string.format(L["LOADING_DEFAULTS"], dataType)) else print(string.format(L["UPGRADE_ATTEMPT"], direction, dataType, oldMajorVersion, oldMinorVersion, newMajorVersion, newMinorVersion)) end local newVars = ww_deepTableCopy(vars) while oldMajorVersion ~= newMajorVersion or oldMinorVersion ~= newMinorVersion do if not funcTable[oldMajorVersion] or not funcTable[oldMajorVersion][oldMinorVersion] then print(string.format(L["UPGRADE_ERR_NO_PATH"], dataType, direction)) return nil end newVars = funcTable[oldMajorVersion][oldMinorVersion](newVars) if not newVars or not newVars.dataMinorVersion then print(string.format(L["UPGRADE_ERR_GENERIC"], dataType, direction)) return nil elseif oldMinorVersion == newVars.dataMinorVersion and oldMajorVersion == newVars.dataMajorVersion then print(string.format(L["UPGRADE_ERR_INF_LOOP"], dataType, direction)) return nil end oldMinorVersion = newVars.dataMinorVersion if newVars.dataMajorVersion then oldMajorVersion = newVars.dataMajorVersion else oldMajorVersion = 0 end end newVars.downgradeFunctions = downgradeFunctions print(string.format(L["UPGRADE_SUCCESS"], dataType, direction)) return newVars end