|
6 | 6 | local ipairs = ipairs |
7 | 7 | local t_insert = table.insert |
8 | 8 | local t_remove = table.remove |
| 9 | +local m_abs = math.abs |
9 | 10 | local m_min = math.min |
10 | 11 | local m_max = math.max |
11 | 12 | local m_floor = math.floor |
@@ -962,6 +963,175 @@ function ItemClass:NormaliseQuality() |
962 | 963 | end |
963 | 964 | end |
964 | 965 |
|
| 966 | +local tinctureLocalModNames = { |
| 967 | + CooldownRecovery = true, |
| 968 | + LocalEffect = true, |
| 969 | + TinctureCooldownRecovery = true, |
| 970 | + TinctureEffect = true, |
| 971 | + TinctureManaBurnRate = true, |
| 972 | +} |
| 973 | + |
| 974 | +local function getTinctureModLineParse(line) |
| 975 | + if not line then |
| 976 | + return |
| 977 | + end |
| 978 | + return modLib.parseMod(line:gsub("\n", " ")) |
| 979 | +end |
| 980 | + |
| 981 | +local function getTinctureModLineSignature(modList) |
| 982 | + local signature = { } |
| 983 | + for _, mod in ipairs(modList or { }) do |
| 984 | + t_insert(signature, modLib.formatMod(mod)) |
| 985 | + end |
| 986 | + table.sort(signature) |
| 987 | + return table.concat(signature, "\n") |
| 988 | +end |
| 989 | + |
| 990 | +local function tinctureModLineShouldScale(modList) |
| 991 | + for _, mod in ipairs(modList or { }) do |
| 992 | + local scaledMod = (type(mod.value) == "table" and mod.value.mod) or mod |
| 993 | + if tinctureLocalModNames[scaledMod.name] then |
| 994 | + return false |
| 995 | + end |
| 996 | + end |
| 997 | + return true |
| 998 | +end |
| 999 | + |
| 1000 | +local function tinctureModLineHasLocalEffect(modList) |
| 1001 | + for _, mod in ipairs(modList or { }) do |
| 1002 | + local scaledMod = (type(mod.value) == "table" and mod.value.mod) or mod |
| 1003 | + if scaledMod.name == "LocalEffect" or scaledMod.name == "TinctureEffect" then |
| 1004 | + return true |
| 1005 | + end |
| 1006 | + end |
| 1007 | + return false |
| 1008 | +end |
| 1009 | + |
| 1010 | +local function getTinctureRangeSteps(templateLine) |
| 1011 | + local maxSteps = 0 |
| 1012 | + for min, max in templateLine:gmatch("%((%-?%d+%.?%d*)%-(%-?%d+%.?%d*)%)") do |
| 1013 | + local minStr, maxStr = tostring(min), tostring(max) |
| 1014 | + local minPrecision = minStr:match("%.(%d+)") and #minStr:match("%.(%d+)") or 0 |
| 1015 | + local maxPrecision = maxStr:match("%.(%d+)") and #maxStr:match("%.(%d+)") or 0 |
| 1016 | + local power = 10 ^ m_max(minPrecision, maxPrecision) |
| 1017 | + local steps = m_floor(m_abs((tonumber(max) - tonumber(min)) * power) + 0.5) |
| 1018 | + maxSteps = m_max(maxSteps, steps) |
| 1019 | + end |
| 1020 | + return maxSteps |
| 1021 | +end |
| 1022 | + |
| 1023 | +local function getTinctureScaledModList(modList, scale) |
| 1024 | + if scale == 1 then |
| 1025 | + return modList |
| 1026 | + end |
| 1027 | + local scaledList = new("ModList") |
| 1028 | + scaledList:ScaleAddList(modList, scale) |
| 1029 | + return { unpack(scaledList) } |
| 1030 | +end |
| 1031 | + |
| 1032 | +local function matchTinctureModLine(targetLine, templateLines, scale, forceScale) |
| 1033 | + local targetModList, targetExtra = getTinctureModLineParse(targetLine) |
| 1034 | + if not targetModList or targetExtra or not templateLines then |
| 1035 | + return |
| 1036 | + end |
| 1037 | + local targetShouldScale = forceScale or tinctureModLineShouldScale(targetModList) |
| 1038 | + local targetSignature = getTinctureModLineSignature(targetModList) |
| 1039 | + for _, templateLine in ipairs(templateLines) do |
| 1040 | + local steps = getTinctureRangeSteps(templateLine) |
| 1041 | + local seen = { } |
| 1042 | + for step = 0, m_max(steps, 0) do |
| 1043 | + local candidateLine = steps > 0 and itemLib.applyRange(templateLine, step / steps) or templateLine |
| 1044 | + if not seen[candidateLine] then |
| 1045 | + seen[candidateLine] = true |
| 1046 | + local candidateModList, candidateExtra = getTinctureModLineParse(candidateLine) |
| 1047 | + if candidateModList and not candidateExtra then |
| 1048 | + if targetShouldScale and scale ~= 1 then |
| 1049 | + candidateModList = getTinctureScaledModList(candidateModList, scale) |
| 1050 | + end |
| 1051 | + if getTinctureModLineSignature(candidateModList) == targetSignature then |
| 1052 | + return candidateLine |
| 1053 | + end |
| 1054 | + end |
| 1055 | + end |
| 1056 | + end |
| 1057 | + end |
| 1058 | +end |
| 1059 | + |
| 1060 | +function ItemClass:NormaliseImportedTinctureModLines() |
| 1061 | + if not self.base or not self.base.tincture then |
| 1062 | + return |
| 1063 | + end |
| 1064 | + |
| 1065 | + local explicitTemplateLines = { } |
| 1066 | + if self.rarity == "UNIQUE" or self.rarity == "RELIC" then |
| 1067 | + local uniqueItem = main and main.uniqueDB and main.uniqueDB.list and main.uniqueDB.list[self.name] |
| 1068 | + if uniqueItem then |
| 1069 | + for _, modLine in ipairs(uniqueItem.explicitModLines) do |
| 1070 | + t_insert(explicitTemplateLines, modLine.line) |
| 1071 | + end |
| 1072 | + end |
| 1073 | + else |
| 1074 | + local affixes = self.affixes |
| 1075 | + or (self.base.subType and data.itemMods[self.base.type .. self.base.subType]) |
| 1076 | + or data.itemMods[self.base.type] |
| 1077 | + or data.itemMods.Item |
| 1078 | + for _, affix in pairs(affixes or { }) do |
| 1079 | + for _, line in ipairs(affix) do |
| 1080 | + t_insert(explicitTemplateLines, line) |
| 1081 | + end |
| 1082 | + end |
| 1083 | + end |
| 1084 | + |
| 1085 | + local localEffectInc = 0 |
| 1086 | + for _, modLine in ipairs(self.explicitModLines) do |
| 1087 | + local modList = getTinctureModLineParse(modLine.line) |
| 1088 | + local matchedLine |
| 1089 | + if tinctureModLineHasLocalEffect(modList) then |
| 1090 | + matchedLine = matchTinctureModLine(modLine.line, explicitTemplateLines, 1) |
| 1091 | + if not matchedLine and (self.quality or 0) > 0 then |
| 1092 | + matchedLine = matchTinctureModLine(modLine.line, explicitTemplateLines, 1 + (self.quality or 0) / 100, true) |
| 1093 | + end |
| 1094 | + end |
| 1095 | + if matchedLine then |
| 1096 | + modLine.line = matchedLine |
| 1097 | + end |
| 1098 | + modList = getTinctureModLineParse(modLine.line) |
| 1099 | + for _, mod in ipairs(modList or { }) do |
| 1100 | + local scaledMod = (type(mod.value) == "table" and mod.value.mod) or mod |
| 1101 | + if scaledMod.type == "INC" and (scaledMod.name == "LocalEffect" or scaledMod.name == "TinctureEffect") then |
| 1102 | + localEffectInc = localEffectInc + scaledMod.value |
| 1103 | + end |
| 1104 | + end |
| 1105 | + end |
| 1106 | + |
| 1107 | + local effectMod = m_floor((1 + localEffectInc / 100) * (1 + (self.quality or 0) / 100) * 100 + 0.0001) / 100 |
| 1108 | + if effectMod == 1 then |
| 1109 | + return |
| 1110 | + end |
| 1111 | + |
| 1112 | + local implicitTemplateLines = { } |
| 1113 | + if self.base.implicit then |
| 1114 | + for line in self.base.implicit:gmatch("[^\n]+") do |
| 1115 | + t_insert(implicitTemplateLines, line) |
| 1116 | + end |
| 1117 | + end |
| 1118 | + |
| 1119 | + for index, modLine in ipairs(self.implicitModLines) do |
| 1120 | + local templateLines = implicitTemplateLines[index] and { implicitTemplateLines[index] } or implicitTemplateLines |
| 1121 | + local matchedLine = matchTinctureModLine(modLine.line, templateLines, effectMod) |
| 1122 | + if matchedLine then |
| 1123 | + modLine.line = matchedLine |
| 1124 | + end |
| 1125 | + end |
| 1126 | + |
| 1127 | + for _, modLine in ipairs(self.explicitModLines) do |
| 1128 | + local matchedLine = matchTinctureModLine(modLine.line, explicitTemplateLines, effectMod) |
| 1129 | + if matchedLine then |
| 1130 | + modLine.line = matchedLine |
| 1131 | + end |
| 1132 | + end |
| 1133 | +end |
| 1134 | + |
965 | 1135 | function ItemClass:GetModSpawnWeight(mod, includeTags, excludeTags) |
966 | 1136 | local weight = 0 |
967 | 1137 | if self.base then |
|
0 commit comments