Thread Tools Display Modes
11-20-16, 08:28 AM   #41
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
Been full of work lately.
I'm gonna try to add some more functionality to the addon, click to open the artifactUI, slash commands, unlock/lock to move the frame, maybe a right click menu to change the info shown on the main frame.
I'm gonna do these over time and post the code here as I do for review and notes from you guys, if you can obviously

I do have a question about something that I've been trying.

One thing C_ArtifactUI.GetEquippedArtifactInfo() returns is (I think) the icon from the artifact, I've tried returning it and it gives me a number and not the usual string with the icon path, I'm assuming that's the icon id?!?!
How can I get the actual icon from that? Can't find how to do it anywhere.

I'm also wondering your opinion on the way I did the tooltip, is directly making a function for OnEnter not as good or efficient as doing it on a SetScript like SDPhantom did on his example solution?

Thank you guys for all your help, when I first came here I actually wasn't expecting so much help, this is a great community.
  Reply With Quote
11-20-16, 09:12 AM   #42
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Yes, those are something like texture IDs. You can use them directly with SetTexture, though. Do you actually need the texture path for something?

The SetScript procedure is the same. The only difference is in your version you may reuse the OnEnter function elsewhere if you like. That's a good idea if you need to use the same script for more than one frame, but in this case I would set it directly.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
11-20-16, 08:17 PM   #43
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
I don't know how it works, but usually with the texture path I can just put the path inside a SetText and get the icon next to the text, right? Pretty sure I've seen people do that, but can't really find it right now :/
  Reply With Quote
11-20-16, 11:10 PM   #44
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
You can type in the number in place of the path and it'll work. For example, this shows the icon for the Marksman Hunter artifact.
Code:
|T1137849:0|t
See UI escape sequences - Textures.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 11-20-16 at 11:16 PM.
  Reply With Quote
11-21-16, 05:37 AM   #45
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
ok I see, I was missing the "escape sequence", I actually thought I would have to do something like that, like I do with colors using |c |r, but I didn't know how that's called so searching for it was pretty difficult to get any results.
Thanks for the link, covers a bunch of those and now I know what to look for

edit:. I'm currently trying to make a click work and can't make it work for the love of me, is it just not possible to have a click work on a Frame frame? Do I actually need to make a Button frame for it to work?

I've tried with and without frame:EnableMouse(true), with and without frame:RegisterForClicks("AnyUp"), and all combinations of both (with one without the other, with both).
Tried that with function OnClick(self) and with frame:SetScript("OnClick", function(self) nothing seems to work.

On the tests where I used frame:RegisterForClicks("AnyUp") I get
attempt to call method 'RegisterForClicks' (a nil value)
and on frame:SetScript("OnClick", function(self) I get
m4xArtifactFrame doesn't have a "OnClick" script
Doing this with a Button seems to work but if it's possible to do with just the Frame it would be better since it would be one less thing to create and have on the screen (even if "invisible").

Last edited by _Max_Cavalera_ : 11-21-16 at 08:56 AM.
  Reply With Quote
11-21-16, 11:45 AM   #46
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
You can just make your frame a button instead. No need to make an extra frame. Buttons support everything that frames do. Or you can use the "OnMouseUp" frame script, which gives you practically the same behavior as "OnClick". In that case, you also need EnableMouse and RegisterForClicks, I think. For buttons those come by default.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
11-21-16, 01:03 PM   #47
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
There shouldn't be any reason not to make your frame as a button if you want to respond to clicks. The advantages of buttons are that they innately support clicking and you can set textures to illustrate the various button states (up, down, highlight, and disabled). You can make a frame do this, but it's a lot of work to get it to do so and honestly isn't worth the effort.

UI objects in WoW form a hierarchy in which more specialized objects inherit methods of the generic ones. For example, Buttons inherit everything a Frame has and adds more features while a CheckButton inherits from Buttons (and Frames indirectly) and adds its own stuff on top of that.

There's an illustration of this here: Widget API
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
11-21-16, 01:59 PM   #48
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
ok, yeah that seems like a good idea, it's not like I'm using the Frame specifically for anything other than to define a space/anchor for everything else, right? So making it a button would allow me to use the OnClick and continue to do everything I'm already using it for.

edit:. ok..... i'm stupid..... damn....

After trying a million things before and after Lombra's post and not getting any results I realized it was actually working, what wasn't working was what I made it do, I made it open the artifact weapon window and that wasn't working, but the click was being registered and working, I just added a chat message to test (yes I should have done this in the first place xD) and the chat message shows.

edit:. ok, making the frame a button like Lombra first suggested and then doing

Lua Code:
  1. frame:SetScript("OnMouseUp", function(self, button)
  2.     if button == "LeftButton" then
  3.         ArtifactFrame_LoadUI()
  4.         if (ArtifactFrame:IsVisible()) then
  5.             HideUIPanel(ArtifactFrame)
  6.         else
  7.             SocketInventoryItem(16);
  8.         end
  9.     end
  10. end);

Seems to be enough, didn't even need the registerforclicks, tries with and without, seems to be the same.

Here's my full code so far.

Lua Code:
  1. local akMulti = {
  2.     25, 50, 90, 140, 200,
  3.     275, 375, 500, 650, 850,
  4.     1100, 1400, 1775, 2250, 2850,
  5.     3600, 4550, 5700, 7200, 9000,
  6.     11300, 14200, 17800, 22300, 24900
  7. };
  8.  
  9. local frame = CreateFrame("Button", "m4xArtifactFrame", UIParent);
  10. local text = frame:CreateFontString(nil, "ARTWORK");
  11. text:SetFont("Fonts\\FRIZQT__.TTF", 15, "OUTLINE");
  12. text:SetJustifyH("LEFT");
  13. text:SetTextColor(1, 0.82, 0);
  14. text:SetPoint("TOPLEFT", UIParent, "TOPLEFT");
  15.  
  16. frame:SetAllPoints(text);
  17.  
  18. frame:RegisterEvent("PLAYER_LOGIN");
  19. frame:RegisterEvent("PLAYER_ENTERING_WORLD");
  20. frame:RegisterEvent("PLAYER_EQUIPMENT_CHANGED");
  21. frame:RegisterEvent("ARTIFACT_CLOSE");
  22. frame:RegisterEvent("ARTIFACT_RESPEC_PROMPT");
  23. frame:RegisterEvent("ARTIFACT_XP_UPDATE");
  24.  
  25. frame:SetScript("OnEvent", function(self, event, ...)
  26.     local itemID, _, _, _, totalXP, pointsSpent = C_ArtifactUI.GetEquippedArtifactInfo()
  27.    
  28.     if itemID then
  29.         local pointsFree, xpToNextPoint = 0, C_ArtifactUI.GetCostForPointAtRank(pointsSpent);
  30.        
  31.         while totalXP >= xpToNextPoint do
  32.             totalXP, pointsSpent, pointsFree, xpToNextPoint = totalXP - xpToNextPoint, pointsSpent + 1, pointsFree + 1, C_ArtifactUI.GetCostForPointAtRank(pointsSpent + 1);
  33.         end
  34.  
  35.         text:SetFormattedText("AP |cff00ff00%d/%d (%.1f%%)|r" .. (pointsFree > 0 and " (+%d)" or ""), totalXP, xpToNextPoint, 100 * totalXP / xpToNextPoint, pointsFree);
  36.     end
  37.  
  38.     frame:SetShown(itemID and true or false);
  39. end);
  40.  
  41. local function OnEnter(self)
  42.     local _, akLevel = GetCurrencyInfo(1171);
  43.     local _, _, itemName, itemIcon, _, pointsSpent = C_ArtifactUI.GetEquippedArtifactInfo()
  44.     local _, effectiveStat = UnitStat("player", 3);
  45.  
  46.     GameTooltip:SetOwner(self, "ANCHOR_BOTTOM");
  47.     GameTooltip:SetText(string.format("|T%d:0|t %s", itemIcon, itemName));
  48.     GameTooltip:AddLine(" ");
  49.     GameTooltip:AddLine(string.format("Artifact Knowledge Level: |cff00ff00%d (+%d%%)|r", akLevel, akMulti[akLevel] or 0));
  50.     GameTooltip:AddLine(string.format("Next Artifact Knowledge: |cff00ff00%d (+%d%%)|r", akLevel + 1, akMulti[akLevel + 1]));
  51.     GameTooltip:AddLine(" ");
  52.     GameTooltip:AddLine(string.format("Stamina from points: |cff00ff00+%g%% (+%d)|r", pointsSpent * 0.75, effectiveStat - (effectiveStat / ((pointsSpent * 0.75 / 100) + 1))));
  53.     GameTooltip:Show();
  54. end
  55.  
  56. local function OnLeave(self)
  57.     GameTooltip:Hide();
  58. end
  59.  
  60. frame:SetScript("OnMouseUp", function(self, button)
  61.     if button == "LeftButton" then
  62.         if ArtifactFrame and ArtifactFrame:IsVisible() then
  63.             HideUIPanel(ArtifactFrame);
  64.         else
  65.             SocketInventoryItem(16);
  66.         end
  67.     end
  68. end);
  69.  
  70. frame:SetScript("OnEnter", OnEnter);
  71. frame:SetScript("OnLeave", OnLeave);

I'm still trying out events for the initial load, because I have a few times that the text wasn't becoming visible with PLAYER_ENTERING_WORLD, we talked about this, I think it was SDPhantom that said the addon didn't have the artifact info available at that point.
I donno, is there any other events that happen once at start bu after that one? The PLAYER_LOGIN one is probably not doing anything tbh.
I just need to get this to load at start every time and for some reason, some times it doesn't, it IS rare but it happens.

Last edited by _Max_Cavalera_ : 11-21-16 at 02:31 PM.
  Reply With Quote
11-21-16, 09:14 PM   #49
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
You haven't registered the UNIT_INVENTORY_CHANGED event.
Code:
frame:RegisterUnitEvent("UNIT_INVENTORY_CHANGED", "player")
You can get rid of:

PLAYER_LOGIN
PLAYER_EQUIPMENT_CHANGED
ARTIFACT_CLOSE
ARTIFACT_RESPEC_PROMPT
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 11-21-16 at 10:14 PM.
  Reply With Quote
11-22-16, 06:15 AM   #50
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
Originally Posted by Fizzlemizz View Post
You haven't registered the UNIT_INVENTORY_CHANGED event.
Code:
frame:RegisterUnitEvent("UNIT_INVENTORY_CHANGED", "player")
You can get rid of:

PLAYER_LOGIN
PLAYER_EQUIPMENT_CHANGED
ARTIFACT_CLOSE
ARTIFACT_RESPEC_PROMPT
We already talked about that.
  Reply With Quote
11-22-16, 10:22 AM   #51
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
Indeed, doesn't mean you don't need the event. If you think it's overkill, you can always unregister it after it has done the job.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 11-22-16 at 10:34 AM.
  Reply With Quote
11-22-16, 05:24 PM   #52
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
Yeah, i guess...

I'm gonna keep trying to find another way, it's not like I have a deadline on this or anything, it's just a learning tool.
  Reply With Quote
11-22-16, 06:16 PM   #53
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
If you're going for a "real world" addon example, any method will also have to take into consideration the possibility of starting the game with a non artifact weapon and at some later stage equiping one, unless the artifact system is loaded when any weapon is equiped.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 11-22-16 at 06:21 PM.
  Reply With Quote
11-22-16, 08:08 PM   #54
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
Doesn't PLAYER_EQUIPMENT_CHANGED already take care of that?

I use it to update when we change specialization (change weapon) and it works fine for that at least.

As it was talked about, the problem for me with UNIT_INVENTORY_CHANGED is that is fires way too much and I don't think that's a good implementation. I know it won't really do anything harmful in an addon this size, but since I'm doing this to learn I don't think learning bad ways to do something is a good idea.

That's why I started to look for events that were more specific to what this addon does, so that the addon only updates when it's actually relevant.

I know I probably have too much now but that's just because I'm still testing them, I probably have that part different every day xD
  Reply With Quote
11-22-16, 09:31 PM   #55
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,871
The vagaries of the WoW login system.

Getting into the game:

PLAYER_EQUIPMENT_CHANGED appears to fire only when you login from the launcher but not on logout/login or /reload. It is also when the artifact information is available.

UNIT_INVENTORY_CHANGED fires after PLAYER_EQUIPMENT_CHANGED and also when loging out/in.

I'm currently testing with both events registerd and unregistering UNIT_INVENTORY_CHANGED after the first time it fires, this "should" cover login in with an artifact weapon equiped.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 11-23-16 at 12:15 AM.
  Reply With Quote
11-23-16, 06:07 AM   #56
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
If you checked the posts where we talked about it you probably know this.

Initially I started by using UNIT_INVENTORY_CHANGED, then i realized my mega tiny addon went from the initial 4kb memory to like 30kb (not instantly, I wasn't paying attention to it), I thought it was strange so I checked what was going on and it was UNIT_INVENTORY_CHANGED that was firing every time I mined and since I was farming mines, every mine it would go up and up and up.
Sure, eventually the garbage collection kicks in and down to 4 it goes, and yes, on something this size that's irrelevant but to me using something that fires for everything and their cousin instead of specific events that are in some way connected to what the addon does makes it bad practice.

This is probably Blizzard's mistake though, from everything said to me here and what I've read online, UNIT_INVENTORY_CHANGED shouldn't be firing for something like looting.

But yes, i think what you said about using it at start and unregister it is most probably the best solution, at least unless I find something I had no idea about (which wouldn't be strange xD).

Last edited by _Max_Cavalera_ : 11-23-16 at 08:02 AM.
  Reply With Quote
11-23-16, 06:41 AM   #57
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
The frequency in which code is run doesn't automatically make it bad at memory management. It just makes it more important to watch what you do in your code. First of all is limiting dynamic creation of functions and tables in code that runs repeatedly. These are the most memory-expensive objects in Lua and their misuse can cause your memory usage to skyrocket.

To a lesser extent, but nonetheless does contribute to memory issues are string operations. Strings as a data type are handled internally in a unique way in which strings containing the same sequence of bytes share the same memory space. This means 100 strings of "something" takes up the same space as a few of them. However, when you start concatenating numbers and other data to them, they suddenly have different contents and are reallocated to a new space in memory.

For example:
Lua Code:
  1. for i=1,100 local str="Something"; end-- Generates only one string in memory containing "Something"
  2. for i=1,100 local str="Something"..i; end-- Generates 100 strings in memory containing "Something1" through "Something100"
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
11-28-16, 02:21 PM   #58
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
So, I've been trying to find out how to do something and after a few days of trying in my free time I'm going crazy.

I have this array of tables (I think that's how you call it), and I'm trying to change a specific value in it, this is the example

Character in this example is Trololo-Moonglade

Lua Code:
  1. addonDB= {
  2.     ["chars"] = {
  3.         ["Moonglade Trololo"] = {
  4.             ["profile"] = "profilename",
  5.         },
  6.     },
  7. };

So, to change the profile name my understanding is that I can do

Lua Code:
  1. addonDB["chars"]["Moonglade Trololo"]["profile"] = "anotherprofilename"

Right? (maybe it's not right and that's the problem right there xD)

And following the same logic, to create a new one I could do

Lua Code:
  1. local name, _ = UnitName("player");
  2. local realm = GetRealmName();
  3.  
  4. addonDB["chars"][realm .. " " .. name]["profile"] = "newprofilename"

So, what am I doing wrong? I get an error saying "attempt to index field '?' (a nil value)" on the "addonDB[......." line

Last edited by _Max_Cavalera_ : 11-28-16 at 03:36 PM.
  Reply With Quote
11-28-16, 02:48 PM   #59
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Well, your 'C' in chars is capitalised differently. I don't think it's possible to make out any other errors from the information given.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
11-28-16, 03:32 PM   #60
_Max_Cavalera_
A Fallenroot Satyr
 
_Max_Cavalera_'s Avatar
Join Date: Dec 2007
Posts: 28
Originally Posted by Lombra View Post
Well, your 'C' in chars is capitalised differently. I don't think it's possible to make out any other errors from the information given.
lol xD i edited it, but that's not the problem, that error was just here when i wrote it again, on the actual addon it's fine.
Also had an error on "profile", wrote "profiles", but again, that error isn't present on the code.

The addon doesn't really do anything else, this is literally the entire code.

Lua Code:
  1. local button = CreateFrame("Button", "m4xConfigButton", UIParent, "UIPanelButtonTemplate");
  2. local text = button:CreateFontString(nil, "ARTWORK");
  3.  
  4. text:SetFont("Fonts\\FRIZQT__.TTF", 15, "OUTLINE");
  5. text:SetTextColor(1, 0.82, 0);
  6. text:SetPoint("CENTER");
  7. text:SetText("Create Profile");
  8.  
  9. button:SetFrameStrata("HIGH");
  10. button:SetPoint("CENTER");
  11. button:SetWidth(160);
  12. button:SetHeight(40);
  13.  
  14. button:SetScript("OnClick", function(self)
  15.  
  16. local name, _ = UnitName("player");
  17. local realm = GetRealmName();
  18.  
  19. if not addonDB["chars"][realm .. " " .. name] then
  20. addonDB["chars"][realm .. " " .. name]["profile"] = "default"

Aaaannnd..... maybe I should have the variable name and realm done outside the function?!?!?! I'm going to try that. If that's it I'm going to kill my self.

Last edited by _Max_Cavalera_ : 11-28-16 at 03:52 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Learning, need help

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