QuestHelper_File["manager_event.lua"] = "4.0.1.$svnversion$" QuestHelper_Loadtime["manager_event.lua"] = GetTime() -- zorba why does this file exist, are you a terrible person? you are a terrible person aren't you -- yep, I'm a terrible person -- File exists to centralize all the event hooks in one place. QH should never (rarely) eat CPU without going through this file. As a nice side effect, I can use this to measure when QH is using CPU. yaaaaay local next_started = false local time_used = 0 local EventRegistrar = {} local OnUpdate_Keyed = {} local qh_event_frame = CreateFrame("Frame") function QH_Hook_NotMyFault(func, ...) return func(...) end local function wraptime(ident, func, ...) if QuestHelper then QuestHelper: Assert(ident) end local st, qhh_nmf local qhh_adj = 0 if qh_loud_and_annoying then qhh_nmf = QH_Hook_NotMyFault --[[ Function nesting == OMFG NO! What seems to be happening here is that we are setting QH_HOOK_NotMyFault to be an anonymous function, which returns the result of an internal anonymous function, which takes the result of func as its argument, does some work with the outer function's variables and spits its arguments back out unmodified. The fix so far... We can set a variable to represent the result of func, do our data manipulation and then return the contents of the temp variable. SO MUCH PRETTIER! AND EASIER TO READ TO BOOT! --]] QH_Hook_NotMyFault = function(func, ...) local zst = GetTime() local ret = {func(...)} qhh_adj = qhh_adj + (GetTime() - zst) return unpack(ret) --print("a", GetTime()) --[[ return (function(...) --print("c", GetTime(), GetTime() - zst, qhh_adj) qhh_adj = qhh_adj + (GetTime() - zst) --print(qhh_adj) return ... end)(func(...)) --]] end st = GetTime() end func(...) if qh_loud_and_annoying then if GetTime() - st - qhh_adj > 0.0025 then QuestHelper: TextOut(string.format("Took way too long, %4f, at %s (adjusted by %4f)", (GetTime() - st - qhh_adj) * 1000, ident, qhh_adj * 1000)) end QH_Hook_NotMyFault = qhh_nmf end end local function OnEvent(_, event, ...) if not next_started then next_started, time_used = true, 0 end if not qh_hackery_eventless and EventRegistrar[event] then local tstart = GetTime() for _, v in pairs(EventRegistrar[event]) do wraptime(v.id, v.func, ...) end time_used = time_used + (GetTime() - tstart) end end qh_event_frame:UnregisterAllEvents() qh_event_frame:RegisterAllEvents() -- I wonder what the performance penalty of this actually is qh_event_frame:SetScript("OnEvent", OnEvent) function QH_Event(event, func, identifier) QuestHelper: Assert(func) if type(event) == "table" then for _, v in ipairs(event) do QH_Event(v, func, identifier) end else if not identifier then identifier = "(unknown event " .. event .. ")" end if not EventRegistrar[event] then --qh_event_frame:RegisterEvent(event) EventRegistrar[event] = {} end table.insert(EventRegistrar[event], {func = func, id = identifier}) end end local tls = GetTime() -- I'm just putting this here so I can stop rewriting it --[[ Try "/script qh_hackery_no_work = true". See if that fixes things. Whether it does or not, log out, log back in, then do "/qh hackery_event_timing = true". Wait a few seconds, then take a screenshot. Post that here. ]] local last_frame = GetTime() local time_per_frame = 0.01 -- Assume 100fps so we don't fuck with people's framerate local OnUpdate = {} local OnUpdateHigh = {} local function OnUpdateTrigger(_, ...) if not QuestHelper then return end if not next_started then next_started, time_used = true, 0 end do local tstart = GetTime() for _, v in pairs(OnUpdateHigh) do wraptime(v.id, v.func, ...) end for _, v in pairs(OnUpdate) do if v.func then wraptime(v.id, v.func, ...) end end time_used = time_used + (GetTime() - tstart) end local tframe = GetTime() local tplf = tframe - last_frame tplf = math.min(time_per_frame + 0.1, tplf) local tplf_weight = tplf * 20 time_per_frame = (time_per_frame * (1 / (tplf_weight + 0.0005)) + tplf) / (1 + 1 / (tplf_weight + 0.0005)) QuestHelper: Assert(time_per_frame > 0 and time_per_frame < 10000) -- hmmm local verbose = false if qh_hackery_event_timing and tls < GetTime() - 1 then tls = GetTime() print(string.format("Avg TPF %f, current TPLF %f, time_used %f, this adjustment %f, bonus time %f", time_per_frame, tplf, time_used, time_per_frame - tplf - time_used, math.min(time_per_frame - tplf, (time_per_frame - tplf) * 0.8, 0.05))) verbose = true end if not qh_hackery_no_work then QH_Timeslice_Work(time_used, time_per_frame, math.min(time_per_frame - tplf, (time_per_frame - tplf) * 0.8, 0.05), verbose) end last_frame = GetTime() next_started = false end function QH_OnUpdate(func, identifier) if not identifier then identifier = "(unknown onupdate)" end table.insert(OnUpdate, {func = func, id = identifier}) end function QH_OnUpdate_High(func, identifier) if not identifier then identifier = "(unknown high-onupdate)" end table.insert(OnUpdateHigh, {func = func, id = identifier}) end qh_event_frame:SetScript("OnUpdate", OnUpdateTrigger) function QH_Hook(target, hookname, func, identifier) if not identifier then identifier = string.format("(unknown hook %s/%s)", hookname, tostring(target)) end if hookname == "OnUpdate" then if not func then OnUpdate[target] = nil else OnUpdate[target] = {func = function (...) func(target, ...) end, id = identifier} end else if not func then target:SetScript(hookname, nil) else target:SetScript(hookname, function (...) wraptime(identifier, func, ...) end) end end end