diff --git a/src/Classes/ModDB.lua b/src/Classes/ModDB.lua index 0fdba90fef..015ff04a3e 100644 --- a/src/Classes/ModDB.lua +++ b/src/Classes/ModDB.lua @@ -130,7 +130,7 @@ end function ModDBClass:SumInternal(context, modType, cfg, flags, keywordFlags, source, ...) local result = 0 - local globalLimits = { } + local globalLimits for i = 1, select('#', ...) do local modList = self.mods[select(i, ...)] if modList then @@ -156,7 +156,7 @@ end function ModDBClass:MoreInternal(context, cfg, flags, keywordFlags, source, ...) local result = 1 local modPrecision = nil - local globalLimits = { } + local globalLimits for i = 1, select('#', ...) do local modList = self.mods[select(i, ...)] local modResult = 1 --The more multipliers for each mod are computed to the nearest percent then applied. @@ -166,6 +166,9 @@ function ModDBClass:MoreInternal(context, cfg, flags, keywordFlags, source, ...) if mod.type == "MORE" and band(flags, mod.flags) == mod.flags and MatchKeywordFlags(keywordFlags, mod.keywordFlags) and (not source or mod.source:match("[^:]+") == source) then local value if mod[1] then + if not globalLimits then + globalLimits = {} + end value = context:EvalMod(mod, cfg, globalLimits) or 0 else value = mod.value or 0 @@ -266,7 +269,7 @@ function ModDBClass:ListInternal(context, result, cfg, flags, keywordFlags, sour end function ModDBClass:TabulateInternal(context, result, modType, cfg, flags, keywordFlags, source, ...) - local globalLimits = { } + local globalLimits for i = 1, select('#', ...) do local modName = select(i, ...) local modList = self.mods[modName] @@ -276,6 +279,9 @@ function ModDBClass:TabulateInternal(context, result, modType, cfg, flags, keywo if (mod.type == modType or not modType) and band(flags, mod.flags) == mod.flags and MatchKeywordFlags(keywordFlags, mod.keywordFlags) and (not source or mod.source:match("[^:]+") == source) then local value if mod[1] then + if not globalLimits then + globalLimits = {} + end value = context:EvalMod(mod, cfg, globalLimits) else value = mod.value diff --git a/src/Classes/ModDB.lua.rej b/src/Classes/ModDB.lua.rej new file mode 100644 index 0000000000..106e51cf41 --- /dev/null +++ b/src/Classes/ModDB.lua.rej @@ -0,0 +1,11 @@ +diff a/src/Classes/ModDB.lua b/src/Classes/ModDB.lua (rejected hunks) +@@ -143,6 +143,9 @@ function ModDBClass:SumInternal(context, modType, cfg, flags, keywordFlags, sour + local mod = modList[i] + if mod.type == modType and band(flags, mod.flags) == mod.flags and MatchKeywordFlags(keywordFlags, mod.keywordFlags) and (not source or ( mod.source and mod.source:match("[^:]+") == source )) then + if mod[1] then ++ if not globalLimits then ++ globalLimits = {} ++ end + local value = context:EvalMod(mod, cfg, globalLimits) or 0 + result = result + value + else diff --git a/src/Modules/CalcSetup.lua.rej b/src/Modules/CalcSetup.lua.rej new file mode 100644 index 0000000000..7cc52ed486 --- /dev/null +++ b/src/Modules/CalcSetup.lua.rej @@ -0,0 +1,19 @@ +diff a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua (rejected hunks) +@@ -212,7 +212,7 @@ function calcs.buildModListForNode(env, node, reuse) + if hasOtherEffect and modList:Flag(nil, "PassiveSkillHasOtherEffect") then + local newMods = modList:List(nil, "NodeModifier") + for i = 1, #newMods do +- local mod = newMods[i] ++ local mod = newMods[i].mod + if i == 1 then + wipeTable(modList) + hasExtraSkill = nil +@@ -223,7 +223,7 @@ function calcs.buildModListForNode(env, node, reuse) + elseif mod.name == "CanExplode" then + hasExplode = true + end +- modList:AddMod(mod.mod) ++ modList:AddMod(mod) + end + end + diff --git a/src/Modules/Common.lua.rej b/src/Modules/Common.lua.rej new file mode 100644 index 0000000000..8b8186a2b3 --- /dev/null +++ b/src/Modules/Common.lua.rej @@ -0,0 +1,208 @@ +diff a/src/Modules/Common.lua b/src/Modules/Common.lua (rejected hunks) +@@ -76,6 +76,25 @@ local function getClass(className) + return class + end + ++-- wrap constructor to check that the constructors for all parent and superparent classes have been called ++local function wrapConstructor(class, className, originalFunc) ++ return function(self, ...) ++ local ret = originalFunc(self, ...) ++ if class._parents then ++ for parent in pairs(class._superParents) do ++ if parent[parent._className] and not self._parentInit[parent] then ++ error("Parent class '" .. ++ parent._className .. "' of class '" .. className .. "' must be initialised") ++ end ++ end ++ end ++ if not ret then ++ error(string.format("Class %s constructor did not return a value", className)) ++ end ++ return ret ++ end ++end ++ + ---@generic T + ---@param className `T` + ---@param ... string parent class names +@@ -90,8 +109,11 @@ function newClass(className, ...) + end + return obj + end ++ -- a list of metatables. one for each parent ++ class._metaList = {} + class._className = className + local numVarArg = select("#", ...) ++ local parentIndex + if numVarArg > 0 then + -- Build list of parent classes + class._parents = { } +@@ -102,21 +124,79 @@ function newClass(className, ...) + class._superParents = { } + addSuperParents(class, class) + -- Set up inheritance +- setmetatable(class, { +- __index = function(self, key) +- for _, parent in ipairs(class._parents) do +- local val = parent[key] +- if val ~= nil then +- self[key] = val +- return val +- end ++ function parentIndex(self, key) ++ for _, parent in ipairs(class._parents) do ++ local val = parent[key] ++ if val ~= nil then ++ rawset(self, key, val) ++ return val + end + end +- }) ++ end + end ++ setmetatable(class, { ++ __index = parentIndex, ++ __newindex = function(self, k, v) ++ if k == className then ++ -- Check that the constructors for all parent and superparent classes have been called ++ v = wrapConstructor(class, className, v) ++ end ++ rawset(self, k, v) ++ end ++ }) ++ class._unconstructedMeta = { ++ __index = function(obj, key) ++ if key == className then ++ setmetatable(obj, class) ++ return class[className] ++ end ++ error(s_format( ++ "Object of class '%s' was used before it was constructed (accessed '%s'). Did you forget to call new(\"%s\"):%s()?", ++ className, tostring(key), className, className)) ++ end, ++ } + return class + end + ++-- avoid rebuilding metatables constantly. this is done by caching class-parent pair metatables ++local function getMeta(class, parent) ++ local metaList = rawget(class, "_metaList") ++ local meta = metaList[parent] ++ if not meta then ++ local parentName = parent._className ++ meta = { ++ __index = function(proxy, key) ++ local object = rawget(proxy, "_object") ++ local v = rawget(object, key) ++ if v ~= nil then ++ return v ++ else ++ return parent[key] ++ end ++ end, ++ __newindex = function(proxy, k, v) ++ local object = rawget(proxy, "_object") ++ object[k] = v ++ end, ++ __call = function(proxy, self, ...) ++ local object = rawget(proxy, "_object") ++ if not parent[parentName] then ++ error("Parent class '" .. parentName .. "' of class '" .. class._className .. "' has no constructor") ++ end ++ if object._parentInit[parent] then ++ error("Parent class '" .. parentName .. "' of class '" .. class._className .. "' has already been initialised") ++ end ++ if self ~= object then ++ error(string.format("Parent class %s constructor of class %s was not provided self. Are you perhaps calling it with self.%s instead of self:%s?", parentName, class._className, parentName, parentName)) ++ end ++ parent[parent._className](self, ...) ++ object._parentInit[parent] = true ++ end, ++ } ++ metaList[parent] = meta ++ end ++ return meta ++end + ---@generic T + ---@param className `T` + ---@param extraArg nil Never pass extra parameters. Defined purely to guard against old syntax. +@@ -130,77 +210,14 @@ function new(className, extraArg) + end + local class = getClass(className) + -- protect against calling new("Foo") without calling :Foo() +- local object +- if class[className] then +- if not rawget(class, "_unconstructedMeta") then +- class._unconstructedMeta = { +- __index = function(obj, key) +- if key == className then +- setmetatable(obj, class) +- return class[className] +- end +- error(s_format( +- "Object of class '%s' was used before it was constructed (accessed '%s'). Did you forget to call new(\"%s\"):%s()?", +- className, tostring(key), className, className)) +- end, +- } +- end +- object = setmetatable({}, class._unconstructedMeta) +- else +- object = setmetatable({}, class) +- end ++ local object = setmetatable({}, class._unconstructedMeta or class) + object.Object = object + if class._parents then + -- Add parent and superparent class proxies + object._parentInit = { } + for parent in pairs(class._superParents) do +- local proxyMeta = { +- __index = function(self, key) +- local v = rawget(object, key) +- if v ~= nil then +- return v +- else +- return parent[key] +- end +- end, +- __newindex = object, +- __call = function(_, self, ...) +- if not parent[parent._className] then +- error("Parent class '"..parent._className.."' of class '"..class._className.."' has no constructor") +- end +- if object._parentInit[parent] then +- error("Parent class '"..parent._className.."' of class '"..class._className.."' has already been initialised") +- end +- if self ~= object then +- error(string.format("Parent class %s constructor of class %s was not provided self. Are you perhaps calling it with self.%s instead of self:%s?", parent._className, className, parent._className, parent._className)) +- end +- parent[parent._className](self, ...) +- object._parentInit[parent] = true +- end, +- } +- object[parent._className] = setmetatable(proxyMeta, proxyMeta) +- end +- end +- +- if class[className] and not rawget(class, "_constructorInitialised") then +- local originalFunc = class[className] +- class[className] = function(self, ...) +- local ret = originalFunc(self, ...) +- if class._parents then +- -- Check that the constructors for all parent and superparent classes have been called +- for parent in pairs(class._superParents) do +- if parent[parent._className] and not self._parentInit[parent] then +- error("Parent class '" .. +- parent._className .. "' of class '" .. className .. "' must be initialised") +- end +- end +- end +- if not ret then +- error(string.format("Class %s constructor did not return a value", className)) +- end +- return ret ++ object[parent._className] = setmetatable({ _object = object }, getMeta(class, parent)) + end +- class._constructorInitialised = true + end + return object + end