Thread Tools Display Modes
10-03-15, 06:00 PM   #1
Nikita S. Doroshenko
A Cyclonian
 
Nikita S. Doroshenko's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2015
Posts: 45
How can i hook complex Blizz functions, like: Module:FuncName(arguments)?

I would like to SetJustifyH "CENTER" all ObjectiveTrackerBlocks and remove all "Dashes" as well. I'm talking about Blocks that contains information about Quests you currently track:
(Sorry for different language on screenshot)


Files that respond to this frames locates in Interface\AddOns\Blizzard_ObjectiveTracker\ folder.
There are lots of files in this folder, but I think most relevant is this: Blizzard_ObjectiveTracker.lua (link to wowprogramming.com)

There are lot's of complex functions that I had never worked before. For example:

Lua Code:
  1. function DEFAULT_OBJECTIVE_TRACKER_MODULE:SetHeader(block, text, animateReason)
  2.     block.module = self;
  3.     block.isHeader = true;
  4.     block.Text:SetText(text);
  5.     block.animateReason = animateReason or 0;
  6.     self.Header = block;
  7. end

I tried to investigate more information about this functions and how they works, and for me (person who never programmed before, it's pretty hard to instantly understand them, but i would like).
On Hooking Functions Guide I read that it's possible to hook this strange functions. This Guide gives this example:
Lua Code:
  1. --[[Functions called using the object calling syntax, object:method(...), can also be hooked; one simply has to remember that the construct is merely syntactic sugar for objec*****thod(object, ...);. To hook a function that was originally declared as:]]
  2. function AnAddon.Module:FuncName(arg1)
  3.   -- Things happen here...
  4. end
  5. --[[We store the original function and replace it with a hook:]]
  6. local original_AnAddon_Module_FuncName = AnAddon.Module.FuncName;
  7. function AnAddon.Module:FuncName(...)
  8.   local arg1 = ...; -- Use the vararg expression in case the function signature changes
  9.   if type(arg1) == "number" and arg1 > 0 then
  10.     -- Call the original function; because of object calling syntax,
  11.     --   pass self as the first argument.
  12.     return original_AnAddon_Module_FuncName(self, ...);
  13.   end
  14. end
  15. --[[The example hook above will only allow the original function to be called if the first argument is a strictly positive number.]]
According to this example, i tryed to hook Blizzards function "DEFAULT_OBJECTIVE_TRACKER_MODULE:SetHeader" with this code:

Lua Code:
  1. local DEFAULT_OBJECTIVE_TRACKER_MODULE_SET_HEADER = DEFAULT_OBJECTIVE_TRACKER_MODULE.SetHeader
  2. function DEFAULT_OBJECTIVE_TRACKER_MODULE:SetHeader(...)
  3.     print("TEST")
  4.     return DEFAULT_OBJECTIVE_TRACKER_MODULE_SET_HEADER(self, ...);
  5. end

But it looks like that i'm doing something wrong. I don't get any lua errors, but no print("TEST") as well, so it's not hooked.
I will very appreciate if you could help me with example of how can i hook this complex functions or with advice or ideas how can i SetJustifyH("CENTER") and remove Dash without hooking this crazy functions (Names of ObjectiveTrackerBlocks are dynamic: example on screenshot)
  Reply With Quote
10-03-15, 07:46 PM   #2
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
SetHeader method is only used when Blizzard_ObjectiveTracker add-on is loaded, your function won't be call because your add-on can't be loaded before the Blizzard_ObjectiveTracker.

For secure, you should use hooksecurefunc. Maybe you can test on

Lua Code:
  1. DEFAULT_OBJECTIVE_TRACKER_MODULE:AddObjective
  Reply With Quote
10-03-15, 08:13 PM   #3
sticklord
A Wyrmkin Dreamwalker
AddOn Author - Click to view addons
Join Date: Aug 2014
Posts: 57
I'm not entirely sure, especially when it comes to metatables, but it seems like it stores the functions to the table DEFAULT_OBJECTIVE_TRACKER_MODULE and then creates a link to these with the metatable, so it still links to the old function in the memory if you dont hook it before the metatable is created. And it seems SetHeader is used only once per trackerframe on startup so I believe you cant hook it (theres a good chance Im wrong here though).

Maybe you can do something like this though

Code:
local trackers = {
	QUEST_TRACKER_MODULE,
	SCENARIO_CONTENT_TRACKER_MODULE,
	SCENARIO_TRACKER_MODULE,
}

for i,t in pairs(trackers) do
	t.Text:SetJustifyH('CENTER')
end
That is if it's the header you want to edit.
  Reply With Quote
10-03-15, 08:27 PM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Based on the code used in Who Framed Watcher Wabbit this should probably work:

lua Code:
  1. -- Keep track of headers and lines we already processed:
  2. local skinnedHeaders, skinnedLines = {}, {}
  3.  
  4. -- Function to apply changes to headers and lines:
  5. local function UpdateLine(module, block, objectiveKey, text, lineType, useFullHeight, hideDash, colorStyle)
  6.     -- Process the header:
  7.     local header = block.HeaderText
  8.     if header and not skinnedHeaders[header] then
  9.         -- Center align the header text:
  10.         header:SetJustifyH("CENTER")
  11.         -- (You can add more changes here if you like)
  12.         -- Add it to the table of headers we already processed:
  13.         skinnedHeaders[header] = true
  14.     end
  15.     -- Process the line itself:
  16.     local line = block.lines[objectiveKey]
  17.     if line and not skinnedLines[lines] then
  18.         -- Center align the line text:
  19.         line.Text:SetJustifyH("CENTER")
  20.         -- (You can add more changes here if you like)
  21.         -- If the line has a dash...
  22.         if line.Dash then
  23.             -- ...hide the dash:
  24.             line.Dash:Hide()
  25.             -- ...and prevent it from being shown in the future:
  26.             line.Dash.Show = line.Dash.Hide
  27.         end
  28.         -- Add it to the list of lines we already processed:
  29.         skinnedLines[line] = true
  30.     end
  31. end
  32.  
  33. -- Hook the AddObjective method for all modules:
  34. for i = 1, #ObjectiveTrackerFrame.MODULES do
  35.     hooksecurefunc(ObjectiveTrackerFrame.MODULES[i], "AddObjective", UpdateLine)
  36. end
  37. hooksecurefunc(SCENARIO_TRACKER_MODULE, "AddObjective", UpdateLine)

Depending on how the lines are sized and anchored (I didn't look) you may need to make additional changes to support center alignment. If it doesn't look properly centered, post a screenshot.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » How can i hook complex Blizz functions, like: Module:FuncName(arguments)?

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off