WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Learning, need help (https://www.wowinterface.com/forums/showthread.php?t=54818)

_Max_Cavalera_ 11-11-16 02:42 PM

Learning, need help
 
Hey guys,

I started a little addon for educational purposes. I'm trying to do everything I can for my self because that's the way I usually learn best, but I just hit a strange wall.

My addon is working as intended... when it works.... because some times it just ignores the events that start it up so... it just doesn't work until one of the other events hits.

I'm sure i'm making a huge mistake somewhere, as I said, I'm just learning, it's my first ever try.

My intention isn't really for anyone to fix it, just to give me some hints on what I'm doing wrong so I can learn :)

Thank you

edit:. Oh btw, in case you use the addon to see how it looks, that's not at all how it's gonna look, I just made 2 lines of info available to test out if it was "printing" what I wanted xD This is a VERY early stage addon.

edit:. I completely forgot to say that the event that seems to be some times ignored is only the initial one, in my case the PLAYER_LOGIN.
I also tried PLAYER_ENTERING_WORLD and have the same problem, some times it works, some times it doesn't.

I've seen it happen on the PLAYER_SPECIALIZATION_CHANGED but it's VERY rare, but it's probably from the same reason.

The rest of them seem to work well every time, every time I use an artifact power item I look at the addon and it seems to always update instantly to that event.

MunkDev 11-11-16 03:38 PM

Lua Code:
  1. function frame:m4xEventHandler(self, event, ...)
  2.     if ( HasArtifactEquipped() ) then
  3.         frame:m4xArtifact_PopulateValues()
  4.     end
  5. end

Lua Code:
  1. function frame:m4xEventHandler(event, ...)
  2.     if ( HasArtifactEquipped() ) then
  3.         self:m4xArtifact_PopulateValues()
  4.     end
  5. end

Colon syntax in a function implies the first argument is self. This probably won't fix your problem though as nothing in that function actually uses the event information.

SDPhantom 11-11-16 04:10 PM

Most ArtifactUI data isn't available when PLAYER_LOGIN fires. As the ArtifactUI is built off the old socketing system, you need to attempt to socket an artifact using SocketInventoryItem() or SocketContainerItem() and wait for ARTIFACT_UPDATE to fire before you can get meaningful data.

You might want to get an error display addon like Swatter or BugSack as the Blizzard default error handler is terrible at reporting errors on login.

PS: Since 7.0, textures don't support setting them to a solid color via :SetTexture() anymore. This functionality was split off into a new function :SetColorTexture().

_Max_Cavalera_ 11-11-16 04:12 PM

I completely forgot to say that the event that seems to be some times ignored is only the initial one, in my case the PLAYER_LOGIN.
I also tried PLAYER_ENTERING_WORLD and have the same problem, some times it works, some times it doesn't.

I've seen it happen on the PLAYER_SPECIALIZATION_CHANGED but it's VERY rare, but it's probably from the same reason.

The rest of them seem to work well every time, every time I use an artifact power item I look at the addon and it seems to always update instantly to that event.

I'm gonna add this to the original post.

Quote:

Originally Posted by SDPhantom (Post 320768)
Most ArtifactUI data isn't available when PLAYER_LOGIN fires. As the ArtifactUI is built off the old socketing system, you need to attempt to socket an artifact using SocketInventoryItem() or SocketContainerItem() and wait for ARTIFACT_UPDATE to fire before you can get meaningful data.

You might want to get an error display addon like Swatter or BugSack as the Blizzard default error handler is terrible at reporting errors on login.

PS: Since 7.0, textures don't support setting them to a solid color via :SetTexture() anymore. This functionality was split off into a new function :SetColorTexture().

I am using bugsack, isn't reporting anything from that.

The strange thing about that PLAYER_LOGIN not having the ArtifactUI data is that some times it works, so how is it working those times?

Thanks for the tip on the texture thing, i'm going to check it out.

SDPhantom 11-11-16 04:25 PM

When you reload the UI, the game doesn't clear the data it caches from server inquiries, so that data would remain available through the reload. The only time this data is cleared is when you log out.

Digging through Blizzard's ArtifactWatchBar, all you really need to watch for are UNIT_INVENTORY_CHANGED (for UnitID player) and ARTIFACT_XP_UPDATE if you're just sticking with the XP system. If you're going to look into scanning traits, you'll run into the situation I explained previously.



Note artifacts can be unequipped and spec changes don't directly contribute to data being updated about the newly equipped artifact. This is still the change in player's inventory. To illustrate this, here's an example of what goes on when you switch specs.
Code:

Client: Switch Specs
Server: Switching Now (Client displays progress bar)
Server: Switching Complete
Client fires PLAYER_SPECIALIZATION_CHANGED
Client: Equip New Artifact
Server: Item Equipped
Client fires UNIT_INVENTORY_CHANGED (UnitID = player)


_Max_Cavalera_ 11-11-16 05:09 PM

I'm not counting reloads as a login, when I said it some times works I mean actual logins, going out to char select and going in again.

As for the specialization change, initially I was using UNIT_INVENTORY_CHANGED, but since that happens every time you loot something or anything changes in the inventory, in my mind it wasn't really an efficient way of doing it. It pretty much causes a memory leak, no? Not that it would ever be a problem per se, we're talking a few kb but still...

And like I said, PLAYER_SPECIALIZATION_CHANGED seems to work 99% of the time, which is why it is as strange as the PLAYER_LOGIN working some times and others not.

My mindset to having chosen PLAYER_SPECIALIZATION_CHANGED in the first place was, I'm never really going to unequip my artifact, it's the only weapon now. I also can't equip any other artifact without changing the specialization and changing it automatically changes to the correct artifact. So it seemed like the perfect solution.

SDPhantom 11-11-16 10:39 PM

UNIT_INVENTORY_CHANGED fires when you equip, swap, or unequip an item. BAG_UPDATE is the event that fires when you loot, drop, or move items around in your bags. The idea of an event firing causing a memory leak is a misconception. Code not properly releasing objects that they allocated memory for is what causes memory leaks. Lua uses a garbage collection system that runs once in a while to clear out data that's no longer in use. The problem with your data usage wasn't how frequent the code was run, but recreating expensive data structures when you didn't need to. Furthermore, with UNIT_* functions, you can use :RegisterUnitEvent() instead of :RegisterEvent() to only respond to the event firing for a specific unit rather than everyone in your party/raid. For example, this is the bare minimum for your code to function properly and efficiently.

Lua Code:
  1. local KnowledgeMultipliers={
  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 MainFrame=CreateFrame("Frame","M4xArtifactFrame",UIParent);
  10. local ExpText=MainFrame:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall");
  11. ExpText:SetPoint("TOPLEFT",UIParent,"TOPLEFT");--   This is the object we're anchoring everything to
  12. ExpText:SetText("Initializing...");
  13.  
  14. --  This will twist your thinking, but you can set the points of your parents to a child as long as you don't create any circular references, as in points depending on each other.
  15. MainFrame:SetAllPoints(ExpText);
  16.  
  17. local Background=MainFrame:CreateTexture(nil,"BACKGROUND");
  18. Background:SetColorTexture(0,0,0,0.2);
  19. Background:SetAllPoints(ExpText);
  20.  
  21. MainFrame:RegisterUnitEvent("UNIT_INVENTORY_CHANGED","player");
  22. MainFrame:RegisterEvent("ARTIFACT_XP_UPDATE");
  23. MainFrame:SetScript("OnEvent",function(self,event,...)
  24.     local itemid,_,_,_,exp,lvl=C_ArtifactUI.GetEquippedArtifactInfo()
  25.     if itemid then
  26.         local available,tonext=0,C_ArtifactUI.GetCostForPointAtRank(lvl);
  27.         local _,knowledge=GetCurrencyInfo(1171);
  28.         while exp>=tonext do exp,lvl,available,tonext=exp-tonext,lvl+1,available+1,C_ArtifactUI.GetCostForPointAtRank(lvl+1); end
  29.  
  30. --      %5$d and %6$d force grab integers from the 5th and 6th parameters respectively
  31.         ExpText:SetFormattedText("AP |cff00ff00%d/%d (%.0f%%)|r"..(available>0 and " (+%d)" or "").."\nAK |cff00ff00%5$d (+%6$d%%)|r",exp,tonext,100*exp/tonext,available,knowledge,KnowledgeMultipliers[knowledge]);
  32.     end
  33.  
  34.     MainFrame:SetShown(itemid and true or false);-- Typecast to boolean
  35. end);

_Max_Cavalera_ 11-12-16 07:46 AM

Quote:

Originally Posted by SDPhantom (Post 320774)
UNIT_INVENTORY_CHANGED fires when you equip, swap, or unequip an item. BAG_UPDATE is the event that fires when you loot, drop, or move items around in your bags.

Well... I completely messed that one up, was probably using BAG_UPDATE, no wonder it wasn't a good choice :p

You've been a huge help, I've learned a lot so far, thank you for that.

I'm going to study the code and apply those ideas maybe later today if I have time. In any case, when I have it working I'll post an update here.

Once again thank you for your help :D

edit:. Apparently I WAS using UNIT_INVENTORY_CHANGED and it does fire when you loot stuff :(
I even made a video to show you.

edit:. I know I'm a bother xD But I'm just like this, I NEEEED to know why stuff does one thing and then another and how it works.

So I did some testing, and apparently, the game fires some events completely randomly or whatever and that's why PLAYER_SPECIALIZATION_CHANGED some times works and other times doesn't.

Here's a pic of my test



I chose those events because they seemed to be the most important when changing spec.
As you can see, it worked when PLAYER_SPECIALIZATION_CHANGED was the last event to fire (or should I say, when it happens AFTER UNIT_INVENTORY_CHANGED), which doesn't happen always. In my test it did like 8 out of 10 times.

The spellcast succeeded ones are, one from finishing changing the spec, the other one is from the passive hidden effect that changes the artifact weapon automatically. I have no idea why some times events for the same thing fire twice, because even though two of those spellcast events aren't the same as they're doing different things, the other ones are "re-fires" of one of those two

I did exactly the same thing every time, didn't move or anything, had the spec window open, choose spec, clicked apply, let it finish, choose another spec, clicked apply, let it finish, etc etc etc... all specs have their artifact weapon in the bag available.

Lombra 11-12-16 12:16 PM

Didn't really read the thread thoroughly, but use PLAYER_EQUIPMENT_CHANGED if you want to track equipment changes.

SDPhantom 11-12-16 01:50 PM

UNIT_INVENTORY_CHANGED seems to be bugged and firing when you loot an item you don't already have or split a stack. PLAYER_EQUIPMENT_CHANGED would be interchangeable and doesn't appear to be affected by this bug.

Phanx 11-13-16 10:39 AM

Quote:

Originally Posted by SDPhantom (Post 320774)
Lua Code:
  1. MainFrame:SetShown(itemid and true or false);-- Typecast to boolean

Not specifically related to anything, but another, less verbose way to do that would be:

Lua Code:
  1. MainFrame:SetShown(not not itemid); -- Typecast to boolean

SDPhantom 11-13-16 12:21 PM

Quote:

Originally Posted by Phanx (Post 320804)
Lua Code:
  1. MainFrame:SetShown(not not itemid); -- Typecast to boolean

I saw this in Blizzard code recently and thought it harder to follow. :p

Seerah 11-13-16 12:50 PM

Quote:

Originally Posted by SDPhantom (Post 320806)
I saw this in Blizzard code recently and thought it harder to follow. :p

I think it is, too. And it doesn't save on anything other than space.

Lombra 11-13-16 02:04 PM

Unless it for some reason can be false; "itemid ~= nil".

_Max_Cavalera_ 11-13-16 09:34 PM

I haven't had any time today to implement anything but I wanted to stop by to thank you guys for the help and keeping the discussion alive :)

btw, by my limited tests, PLAYER_EQUIPMENT_CHANGED seems to be the best solution so far for my "problem"

SDPhantom 11-14-16 01:09 PM

Quote:

Originally Posted by Lombra (Post 320808)
Unless it for some reason can be false; "itemid ~= nil".

The API is consistent in returning nil if doesn't have any data. Checking for nil specifically is overboard in this case and is a waste of CPU resources on an extra operation or two.

Lombra 11-14-16 02:14 PM

Quote:

Originally Posted by SDPhantom (Post 320826)
The API is consistent in returning nil if doesn't have any data. Checking for nil specifically is overboard in this case and is a waste of CPU resources on an extra operation or two.

Sure, but since we were talking readability I prefer that expression personally.

Seerah 11-14-16 05:05 PM

But nil isn't the same as false.

SDPhantom 11-15-16 12:19 AM

Again, differentiating false in this situation is overkill. The API never returns false in place of a value that isn't normally boolean. As a matter of fact, API that returns data often doesn't provide any returns when there isn't any available, not even nil. However, when Lua attempts to assign no value to a variable, it ends up assigning nil anyway.

_Max_Cavalera_ 11-15-16 09:17 AM

ok, i've been reading the code you put up (thanks once again for that), i'm implementing it right now, have a few questions though since I'm doing this to learn, implementing without knowing why or what something does isn't really an option xD

I'll start at the end since people always like to start at the beginning ;)

Lua Code:
  1. MainFrame:SetShown(itemid and true or false);

Can you explain this line to me? I think that it's supposed to be, show frame if itemID exists?! but I don't get how the and true or false works.

Backgrounds... do I really need them? I know I had one, I made it because I was learning from a book and it listed the background as something to use when making a frame but as you know mine wasn't even working and i didn't even notice it because it was already supposed to be almost invisible at 0.2 alpha.
It works without one so I guess there's no problem in not having one? Or can it create problems?

Can you explain why %5$d and %6$d is needed to grab the 5th and 6th parameter when the position of those in the string are the 5th and 6th? Shouldn't they already pick up the right ones with just %d? Or is it \n that breaks that?
By the way, I didn't know I could do that so, thanks ;)

EDIT:. ok I understand this one now I think, it's because of the (available>0 and " (+%d)" or ""), they MIGHT or MIGHT NOT be the 5th and 6th... damn I'm dumb...

And finally,

Lua Code:
  1. (available>0 and " (+%d)" or "")

You have this on the formatted text, I guess it's supposed to be if available > 0 do the first one else do the other one?!?! So it's like an IF statement to use inside strings?

How does it work? From what you have I think it's (if condition and then or else) but the fact that the if condition is followed by and seems so strange to me xD


All times are GMT -6. The time now is 11:46 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI