diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 7b226410d8410a1a7af3b0014d4b067f60fe7952..bdb43e538a39e257273eea34861dde5274274752 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -4882,6 +4882,21 @@ local sustainCallbackCheck = { } _M.sustainCallbackCheck = sustainCallbackCheck +local function convertToString(id) + if _G.type(id) == "table" then return id.name or tostring(id) end + return tostring(id) +end + +local function callbackKeyLess(x, y) + local ap, bp = x[1], y[1] + -- edge case: equal priorities + if ap == bp then + if x[2] < y[2] or + (x[2] == y[2] and x[3] < y[3]) then return true end + return false + else return ap < bp end +end + -- Upgrade from pre- local function upgradeStore(store, storename) if store.__priorities then return end @@ -4889,18 +4904,34 @@ local function upgradeStore(store, storename) local priorities = {} for k,_ in pairs(store) do priorities[k] = 0 end store.__priorities = priorities + local sorted = {} + for id, _ in pairs(self[store].__priorities) do + sorted[#sorted + 1] = {self[store].__priorities[id], self[store][id], convertToString(id), id} + end + table.sort(sorted, callbackKeyLess) + store.__sorted = sorted end + function _M:registerCallbacks(objdef, objid, objtype) for event, store in pairs(sustainCallbackCheck) do if objdef[event] then local cb = self[store] or {} upgradeStore(cb, store) - cb.__sorted = nil cb[objid] = objtype -- extract a priority, 0 by default cb.__priorities[objid] = (objdef.callbackPriorities and objdef.callbackPriorities[event]) or 0 self[store] = cb + -- insert into priorities + local sortedkey = {cb.__priorities[objid], objtype, convertToString(id), id} + local idx = #cb.__sorted + 1 + for i, key in ipairs(cb.__sorted) do + if callbackKeyLess(sortedkey, key) then + idx = i + break + end + end + table.insert(cb.__sorted, idx, sortedkey) -- may be nil, which means to the end end end @@ -4911,42 +4942,25 @@ function _M:unregisterCallbacks(objdef, objid) upgradeStore(self[store], store) self[store][objid] = nil self[store].__priorities[objid] = nil - self[store].__sorted = nil + local idx = nil + for i, key in ipairs(self[store].__sorted) do + if key[4] == objid then + idx = i + break + end + end + if idx then table.remove(self[store].__sorted, idx) end if not next(self[store].__priorities) then self[store] = nil end end end end -local function convertToString(id) - if _G.type(id) == "table" then return id.name or tostring(id) end - return tostring(id) -end - function _M:fireTalentCheck(event, ...) local store = sustainCallbackCheck[event] local ret = false if self[store] then upgradeStore(self[store], store) end if self[store] and next(self[store].__priorities) then - local sorted = self[store].__sorted - if not sorted then - sorted = {} - for id, _ in pairs(self[store].__priorities) do - sorted[#sorted + 1] = {self[store].__priorities[id], self[store][id], convertToString(id), id} - end - table.sort(sorted, - function(x, y) - local ap, bp = x[1], y[1] - -- edge case: equal priorities - if ap == bp then - if x[2] < y[2] or - (x[2] == y[2] and x[3] < y[3]) then return true end - return false - else return ap < bp end - end) - self[store].__sorted = sorted - end - - for _, info in ipairs(sorted) do + for _, info in ipairs(self[store].__sorted) do local priority, kind, stringId, tid = unpack(info) if kind == "effect" then self.__project_source = self.tmp[tid]