I've got a question about "Hooking" functions

I have some things that need to happen when a macro is edited and saved or created.

There are two functions that appear to be accessible buried down in the Macro UI code in FrameXML, but honestly, I’ve never hooked a function before and I’m not sure what happens when I do.

What I’m HOPING is that my hooked function will run the extra bits every time the original is called.

If that’s the case, I’m good, but I could use confirmation.

Yes. If you apply a secure hook then it executes immediately after Blizzard’s function every time. It receives the same arguments that Blizzard’s did.

local myFunc()
   -- do stuff here
end

hooksecurefunc("Name_of_Blizzard_Macro_Function", myFunc)

(There are other ways of hooking that can preempt Blizzard’s code, but that is not usually what you want to do.)

Thanks, Dahk.

I’m just wanting something to happen after the Blizzard stuff happens, and even that is stuff that there’s no real restriction on. I’m already set up so that none of this will happen in combat.

@Dahk - got a follow up for you.

The notes say that the hooked function gets the same parameters passed as the original.

Does the function definition have to reflect that?

Assume this:

BlizzardFunction(a, b, c)

local function MyFunc()

    do something with a
    do something with b
    do something with c

end

or

local function MyFunc(a, b, c)

    do something with a
    do something with b
    do something with c

end
hooksecurefunc("BlizzardFunction", myfunc)

Which one would I use?

Also, I’m concerned that someone else might need the function so I thought about this:

local useHookedCode

local function MyFunc(a, b, c)

    if useHookedCode then

        do something with a
        do something with b
        do something with c

        useHookedCode = false

    end

end

useHookedCode = true

BlizzardFunction(a, b, c)

Wouldn’t that leave the function’s . . . well, functionality . . . unchanged when/if someone else calls it?

Your function doesn’t effect the original. If you don 't need the passed arguments you don’t have to reflect them.

BlizzFunction(a, b, c)
    ...
end

hooksecurefunc("BlizzFunction", function()
    ...
   -- no a, b or c required 'caus just doing stuff
end)

If you do want a, b, c in your function then define them in your function.

hooksecurefunc("BlizzFunction", function(a, b, c)
    -- do stuff with a, b, c
end)

All hooked function are called in order of hooking and because none of the functions interact, you don’t care… unless they are all differntly altering the value of some global(s) everyone else is using.

Because lua is single threaded, all the hooks will be executed before other code moves on each time the original function is called.

So hooks are not global?

I was really confused by the wiki on it partly because some of it is written very poorly (probably someone working with English as a second language, not because they don’t know their stuff).

That said, sometimes I DO need the hooked code and sometimes I don’t.

Putting a “use it” status flag that’s accessible to it but not passed in and that works just like the original function if nil works for me. I’d just like to understand how hooking works a little better.

You can only hook a function that is in scope ie. global or previously defined in your local or namespace scope.

The scope of your function is what it is scoped as and the usual rules apply.

addon A

local x, y, x = 1, 2, 3

hooksecurefunc("BlizzFunc", function(a, b, c)
    print(x, y, z) -- prints 1, 2, 3 each time
end)

addon B

local x, y, x = 4, 5, 6

hooksecurefunc("BlizzFunc", function(a, b, c)
    print(x, y, z) -- prints 4, 5, 6 each time
end)

I did a proof-of-concept test by hooking EditMacro().

My hook function just prints out “Used hooked version”.

When I use the Blizzard Macro UI and save a macro after making changes, I get “Used hooked version” printed out.

That’s why I thought hooked functions were global (assuming the original function is global).