local function pairsByKey (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end
...
function foo()
local bar = {
["key1"]="value1",
["key2"]="value2",
["key3"]="value3",
}
for k, v in pairsByKey(bar) do
dostuffwith(k, v)
end
end
I have no idea if what I do leads to a lot of garbage or not
It creates a table and a function everytime it's called, depending on how you use it, it could produce some quite a bit of garbage. Something like this will only create the required iteration function and sorted array when required.
[SIZE=2]
[SIZE=2]local pairsByKeys; do[/SIZE]
[SIZE=2]local sortedtbl, iter[/SIZE]
[SIZE=2]function pairsByKeys(tbl, f)[/SIZE]
[SIZE=2] if sortedtbl then[/SIZE]
[SIZE=2] wipe(sortedtbl)[/SIZE]
[SIZE=2] else[/SIZE]
[SIZE=2] sortedtbl = {}[/SIZE]
[SIZE=2] function iter(tbl, i)[/SIZE]
[SIZE=2] i = i + 1[/SIZE]
[SIZE=2] if sortedtbl[i] == nil then[/SIZE]
[SIZE=2] return nil, nil, nil[/SIZE]
[SIZE=2] else[/SIZE]
[SIZE=2] return i, sortedtbl[i], tbl[sortedtbl[i]][/SIZE]
[SIZE=2] end[/SIZE]
[SIZE=2] end[/SIZE]
[SIZE=2] end[/SIZE]
[SIZE=2] for k, v in pairs(tbl) do[/SIZE]
[SIZE=2] table.insert(sortedtbl, k)[/SIZE]
[SIZE=2] end[/SIZE]
[SIZE=2] table.sort(sortedtbl, f)[/SIZE]
[SIZE=2] return iter, tbl, 0[/SIZE]
[SIZE=2]end[/SIZE]
[SIZE=2]end[/SIZE]
[SIZE=2]local tbl = {[/SIZE]
[SIZE=2]key1 = "val1",[/SIZE]
[SIZE=2]key2 = "val2",[/SIZE]
[SIZE=2]key3 = "val3",[/SIZE]
[SIZE=2]key4 = "val4",[/SIZE]
[SIZE=2]key5 = "val5",[/SIZE]
[SIZE=2]key6 = "val6",[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2]for i, k, v in pairsByKeys(tbl) do[/SIZE]
[SIZE=2]print(k, v)[/SIZE]
[SIZE=2]end[/SIZE]
[/SIZE]
There is exactly one WoW API function that can send messages to other players: SendAddonMessage.
It's nice for me to say this again: (and again and again)
DO NOT TRUST ADDONS THAT USE SendAddonMessage!
Any addon with SendAddonMessage _can_ send any global (and even everything locally available within it's own code) variable data from any addon to any player without userinteraction, and hey get this: all SavedVariables data is global; accessible and available for all other addons!
Big potential for misuse.
If you want to use an addon:
1) search the complete source code (incl. libs) for 'SendAddonMessage'
2) if you find 'SendAddonMessage' read the code and try to understand what this addon is sending
3) if you do not know (by source code) what this addon is sending: DO NOT USE IT!
Simple and radical solution.
If a mod was doing something truly dodgy they would probably obfuscate the reference i.e.
local f = _G[string.char(83, 101, 110, 100, 65, 100, 100, 111, 110, 77, 101, 115, 115, 97, 103, 101)]
It's not clear to my why OnUpdate is involved in all of this, but that's a separate question. And if you do need OnUpdate, why not attach scripts to active frames individually? I think you should tell us what actual goal you have, beyond the specifics, because the right answer very much depends upon what you ultimately try to achieve.
Having one OnUpdate is more efficient than many, thus why Ace_Timer-3.0 exists.
The above code doesn't work, it prints out the numbers from 10 to 0 within 1 sec.
Works for me, just tested in WoWLua, if your on about starting the timer then minimising WoW waiting 10 seconds and then having it print numbers 10 to 0 within 1 sec then this is to be expected, as the timer has to catch up.
Windowed fullscreen, the only mode you should *ever* use.
Why? I thought you get an FPS boost when not using windowed mode?
Anyway when alt-tabbed out WoW doesn't run the OnUpdate handlers while in fullscreen mode so instead of telling the time relative to each OnUpdate you would want to get the fixed time using time() or GetTime().
e.g.
local startTime = GetTime()
local counter = 10
CreateFrame("Frame"):SetScript("OnUpdate", function(f)
local currentTime = GetTime()
if currentTime - 1 > startTime then
for i = counter, counter - math.floor((currentTime - 1) - startTime), -1 do
if i > 0 then
print("countdown: " .. i)
startTime = GetTime()
counter = counter - 1
else
print("reached 0")
f:SetScript("OnUpdate", nil)
end
end
end
end)
local starttime = time() + <how many seconds you want your timer to run for>
frame:SetScript("OnUpdate", function(frame)
if time() > starttime then
frame:SetScript("OnUpdate", nil)
--stuff to run when the timer finishes
end
end)
Something like that, or you could just use AceTimer.
Coming a bit late in the discussion. Be careful the name you choose because, although the function is called CollapseSkillHeaderPreHook, it's code is executed AFTER the hooked function has returned.
Yup your right, edited my previous code to avoid confusion.
local OldCollapseSkillHeader = CollapseSkillHeader
local function CollapseSkillHeaderPostHook(arg1, arg2, ...)
-- do stuff with arg1 and arg2
--arg1 and arg2 are the arguments sent to CollapseSkillHeader, while ... is the return from CollapseSkillHeader
return ...
end
function CollapseSkillHeader(arg1, arg2, ...)
return CollapseSkillHeaderPostHook(arg1, arg2, OldCollapseSkillHeader(...))
end
Heres something which should help finding out whats changing the function.
local mt = getmetatable(_G)
local function newnewindex(t, key, val)
if key == "HandleModifiedItemClick" then
print(debugstack(2))
end
t[key] = val
end
if mt then
if mt.__newindex then
local _mtnewindex = mt.__newindex
--pre hook newindex
function mt.__newindex(t, key, ...)
if key == "HandleModifiedItemClick" then
print(debugstack(2))
end
return _mtnewindex(t, key, ...)
end
else
mt.__newindex = newnewindex
end
else
setmetatable(_G, {__newindex = newnewindex})
end
local addon = CreateFrame("Frame")
local t = 0
local partypos = 0
local iconpos = 0
local units = {"player", "party1", "party2", "party3", "party4"}
addon:SetScript("OnUpdate", function(self, el)
if t > 1 then --update icons after a sec
local unit
if partypos == 5 then
partypos = 0
end
partypos = partypos + 1
if iconpos == 8 then
iconpos = 0
end
iconpos = iconpos + 1
SetRaidTarget(units[partypos], iconpos)
t = 0
end
t = t + el
end)
addon:Hide()
local function y()
addon:Show()
end
local function n()
addon:Hide()
for i = 1, 5 do
SetRaidTarget(units[i], 0)
end
end
local function toggle()
if addon:IsShown() then
n()
else y()
end
end
local cmds = setmetatable({
-- enable
on = y,
enable = y,
go = y,
["true"] = y,
y = y,
--disable
off = n,
disable = n,
stop = n,
["false"] = n,
n = n
}, {__index = toggle})
SlashCmdList["ICONHELL"] = function(msg)
local a = msg:match("(%S+)")
if a then
cmds[a:lower()]()
else
toggle()
end
end
SLASH_ICONHELL1 = "/iconhell"
SLASH_ICONHELL2 = "/ihell"
Does this work (I don't have a wow account so I can't test.
local addon = CreateFrame("Frame")
local t = 0
local partypos = 0
local iconpos = 0
local units = {"player", "party1", "party2", "party3", "party4"}
f:SetScript("OnUpdate", function(self, el)
if t > 1 then --update icons after a sec
local unit
if partypos == 5 then
partypos = 0
end
partypos = partypos + 1
if iconpos == 8 then
iconpos = 0
end
iconpos = iconpos + 1
SetRaidTarget(units[partypos], iconpos)
t = 0
end
t = t + el
end)
f:Hide()
local y = function()
addon:Show()
end
local n = function()
addon:Hide()
for i = 1, 5 do
SetRaidTarget(units[i], 0)
end
end
local cmds = setmetatable({
-- enable
on = y,
enable = y,
go = y,
["true"] = y,
y = y,
--disable
off = n,
disable = n,
stop = n,
["false"] = n,
n = n
}, {__index = function()
if addon:IsShown() then
n()
else y()
end
end})
SlashCmdList["ICONHELL"] = function(msg)
local a = msg:match("(%S+)")
if a then
cmds[a:lower()]()
end
end
SLASH_ICONHELL1 = "/iconhell"
SLASH_ICONHELL2 = "/ihell"
make an addon file stick in the code, then type /ihell .
quick warning, it's a 100% drycoded, but might work properly on first go.
Sorry to hijack the thread, but a related question. During testing/updating/etc of SmartRes2, if I use my slash commands (/sr and /smartres) sometimes they open right to the SmartRes2 panel, and sometimes they open to Interface.. Addons, and you have to scroll down to the SR2 entry. It isn't consistent, and I did notice an addon on curse.com that "fixes" this, but I do not have it installed.
Any ideas why the inconsistency? Furthermore, if it does not open right the panel on first slash use, it will every time after I use a slash after. It is the first time that sometimes it works, sometimes it doesn't.
iirc it's because of weirdness when using InterfaceOptionsFrame_OpenToCategory with too many categories, you might be noticing this discrepancy because you don't have a panels sub panels expanded.
0
It creates a table and a function everytime it's called, depending on how you use it, it could produce some quite a bit of garbage. Something like this will only create the required iteration function and sorted array when required.
0
If a mod was doing something truly dodgy they would probably obfuscate the reference i.e.
So your best option is probably StopAddonMessage
0
0
Having one OnUpdate is more efficient than many, thus why Ace_Timer-3.0 exists.
0
Works for me, just tested in WoWLua, if your on about starting the timer then minimising WoW waiting 10 seconds and then having it print numbers 10 to 0 within 1 sec then this is to be expected, as the timer has to catch up.
0
Why? I thought you get an FPS boost when not using windowed mode?
Anyway when alt-tabbed out WoW doesn't run the OnUpdate handlers while in fullscreen mode so instead of telling the time relative to each OnUpdate you would want to get the fixed time using time() or GetTime().
e.g.
0
Something like that, or you could just use AceTimer.
0
0
Yup your right, edited my previous code to avoid confusion.
0
0
0
0
Does this work (I don't have a wow account so I can't test.
0
make an addon file stick in the code, then type /ihell .
quick warning, it's a 100% drycoded, but might work properly on first go.
0
iirc it's because of weirdness when using InterfaceOptionsFrame_OpenToCategory with too many categories, you might be noticing this discrepancy because you don't have a panels sub panels expanded.