Changing/hooking method
...without specifying an object.
I want to change the toning of every status bar without modifying the .blp. So now i want to change the SetStatusBarColor(r, g, b, a) method to basically do SetStatusBarColor(r*0.8, g*0.8, b*0.8, a). This is what i have at the moment: lua Code:
How can i make it so whenever object:SetStatusBarColor() is executed (by blizzard code or any other addon), my ModSetStatusBarColor() is fired? I tried google, wowprogramming, wowpedia and the forum search but i think i can't get the search term right. |
Do you mean
hooksecurefunc("functionName", hookfunc) frame:HookScript("handler", function) ? |
I tried that, but it needs the frame name as far as i understand it. I want it to work without specifying the frame.
I could probably do PlayerFrameHealthBar:HookScript("SetStatusBarColor", ModSetStatusBarColor(self)) but then i'd have to do it for every frame. To reword my request: Some blizzard or addon code executes object:SetStatusBarColor(r, g, b, a). Instead of using the given r, g, b values it should use my modified values (e.g. r*0.8, g*0.8, b*0.8). |
Not possible. You can hook a specific statusbar's SetStatusBarColor. Every object of the widget creates a metatable with an __index reference to a global SetStatusBarColor() that is not part of FrameXML anymore but of WoW's internals.
The only alternative would be to loop trough all UIParent members and check for frames of GetObjectType() "statusbar", then use hooksecurefunc to safely hook (some of the statusbars may be part of unit frames or other secure template derivates) into the function. A bit excessive for something as fancy as a color replacement imo. You would also face the problem of dynamicly created statusbars (bossmods, cooldown addons etc.). That's something you couldn't track without scaning over and over again, an act that would eat up nearly all game resources. |
All frames of the same type share their metatable, so you can hook the method like this:
Code:
local Meta = getmetatable( CreateFrame( "StatusBar" ) ).__index; |
Oh, true that. I should have thought that comment through. On the other hand the standard interface will call the function only once most of the time and that's before your addon loads. So in practice you wouldn't get around using the suggested brute force technique at least once when loading.
|
Quote:
/script print(getmetatable(NamePlate1:GetChildren())) /script print(getmetatable(CreateFrame("StatusBar"))) /script local healthBar=NamePlate1:GetChildren(); print(healthBar); healthBar:SetStatusBarColor(0,0,0) -> this works And i came to the conclusion, that i don't understand nameplates at all. At first start up, nameplates start with NamePlate1 (up to NamePlate4), two tables per nameplate (the first seems to be the health bar) and one metatable for all (getmetatable(NamePlate1/2/3/4:GetChildren()) returns the same metatable as getmetatable(CreateFrame("StatusBar"))). After reloading the interface, they start with NamePlate5 (to ...8) and NamePlate1 to ...4 don't exist anymore. Those new nameplates have new tables but the same metatable as 1 to 4. Then i log out and log in again, nameplates start at ...9 with new tables and a new metatable. |
Naturally they share the same metamethods. All objects of the same widget do, that is exactly why the above code works. You hook into their prototype.
The reason you see different values inside the metatable after a relog is that the memory for the functions is dynamically allocated when logging in. _index.SetStatusBarColor may return function:123AF6 before and function:AB34FF after a relog but it's still a reference to the same function, just with a newly generated handle. Between /reloadui prototypes seem to stay in memory so the output for the metatables is the same. And nameplates are anonymous children of WorldFrame that are dynamically created on demand. When you reload the ui or relog all frames are created again, so are the nameplates and their tables. I can confirm however that they have their original statusbar color first while calling SetStatusBarColor directly jumps into the function hook like it should, which can only mean that SetStatusBarColor isn't called when the frame is being created... I guess. Maybe the Blizzard code calls HealthBar:GetStatusBarTexture():SetVertexColor() instead or something like that. |
WoW actually manipulates the nameplates directly in C++, bypassing their Lua methods and thus skipping any hooks. Unfortunately, that leaves no way to detect color changes short of checking their color every time the screen repaints.
If you're determined to make the nameplates match though, you could overlay a transparent black texture over the nameplate bars as soon as they get created. |
Quote:
This is my latest approach (similar to rNameplates): lua Code:
Edit: So after further blatant copying from rNameplates i tried this: lua Code:
It works for some time, then stops working, starts working again. Hiding nameplates and showing them again sometimes helps, sometimes it doesn't. I get a serious urge to give up on the case. Edit: I just thought that there's little reason to hook the script at this point?! |
All times are GMT -6. The time now is 02:16 PM. |
vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI