Thread Tools Display Modes
05-20-16, 06:10 PM   #1
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
Getting artifact perks data

I would like to get info about which artifact perks are currently active. So far I have the following code:

lua Code:
  1. local powers = C_ArtifactUI.GetPowers()
  2.  
  3. for i = 1, #powers do
  4.     local spellID, _, currentRank = C_ArtifactUI.GetPowerInfo(powers[i])
  5.  
  6.     if currentRank > 0 then
  7.         local name = GetSpellInfo(spellID)
  8.         -- do stuff
  9.     end
  10. end

However this only works when the ArtifactUI is open and I can't figure out how to open it programmatically. Would appreciate some help on that.
 
05-20-16, 06:14 PM   #2
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
As a temporary workaround, you can cache your results. Update your cache any time the Artifact UI is open, or appropriate events fire.
 
05-20-16, 07:06 PM   #3
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
I need the data for a spell dependency list. Like for marksmanship hunters Windburst applies Deadeye (or Vulnurable) when Mark of the Windrunner is selected. However both IsSpellKnown and IsPlayerSpell return false for Mark of the Windrunner and there is no spell added to the spell book. I can't rely on the user opening the artifact UI but I haven't found another way to get that information.
 
05-20-16, 07:22 PM   #4
dssd
A Fallenroot Satyr
Join Date: May 2016
Posts: 25
You can open the artifact UI by requesting to socket the artifact through a call like SocketContainerItem or SocketInventoryItem. At that point you should be able to request artifact data.
 
05-20-16, 07:57 PM   #5
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
This is an interesting idea!

On second thought, it is probably not nice to open the artifact UI without a user interaction as it could close other UI panels. And I'll have to rescan in case the user changes their spec and equips another artifact. I really hope they'll make the whole C_ArtifactUI API usable without the artifact UI being visible.
 
05-20-16, 08:03 PM   #6
syncrow
A Flamescale Wyrmkin
 
syncrow's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 149
Lua Code:
  1. function CollectPerkInfo()
  2.     if HasArtifactEquipped() then
  3.         local forceHide;
  4.  
  5.         -- opens (equipped) arfifact layout
  6.         if not ArtifactFrame:IsShown() then
  7.             forceHide = true
  8.             SocketInventoryItem(16)
  9.         end
  10.        
  11.         for i, powerID in ipairs(C_ArtifactUI.GetPowers()) do
  12.             local spellID, cost, currentRank, maxRank, bonusRanks, x, y, prereqsMet, isStart, isGoldMedal, isFinal = C_ArtifactUI.GetPowerInfo(powerID)
  13.  
  14.             -- you can now cache the info you want
  15.         end
  16.        
  17.         if ArtifactFrame:IsShown() and forceHide then
  18.             HideUIPanel(ArtifactFrame)
  19.         end
  20.     end
  21. end

Here is an example on how it could be used:
__________________

Last edited by syncrow : 05-20-16 at 09:52 PM.
 
05-20-16, 08:33 PM   #7
dssd
A Fallenroot Satyr
Join Date: May 2016
Posts: 25
Yeah, you can also just suppress the artifact UI from opening at all by doing something like unregistering the artifact open event from UIParent and then re-registering after you're done with your info.

The problem with the artifact api being available all the time is that a player could have up to 4 artifacts (druids), that's why you have to specify which one you want data on by using the socket function.
 
05-21-16, 03:30 AM   #8
Simca
An Aku'mai Servant
 
Simca's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2012
Posts: 33
I'm confused, can you not just call LoadAddOn for the load-on-demand Blizzard Addon in question? (Blizzard_ArtifactUI)
__________________
Assistant admin for MMO-Champion
WoW database file expert - ask me anything
 
05-21-16, 06:22 AM   #9
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
@Simca you can load the addon, but the C_ArtifactUI API returns just nils while the ArtifactFrame is not open. Or I'm too short sighted to get it.

@dssd yes, but only one artifact can be active at a time per design. And the API could provide just that info.

@syncrow HasArtifactEquipped() returns true even if the player has respecced but hasn't changed weapons yet, meaning your code gets potentially wrong information.
 
05-21-16, 06:30 AM   #10
syncrow
A Flamescale Wyrmkin
 
syncrow's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 149
Originally Posted by Rainrider View Post
HasArtifactEquipped() returns true even if the player has respecced but hasn't changed weapons yet
You'll change weapon automatically when you respec?! Or am I wrong?
__________________
 
06-12-16, 02:23 AM   #11
kokomala
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 29
Originally Posted by Rainrider View Post
@dssd yes, but only one artifact can be active at a time per design. And the API could provide just that info.
You can still view the Artifact Perk UI by shift + right click for any artifact that may be in your bags. The artifact API will use whatever artifact is currently 'open', even if it is in your bags.

Pity the API didn't use specID.

Edit:
As this is something I've needed for my own project, I messed around and wrote a quick libstub library for caching artifact information (including those in your bags). Used some of the code above as a base (credit to your macro Rainrider). Data updates is handled by the library, you only need to call the data functions.

This is my first library (woo!) so code could probably be done better. Let me know if you have any issues with it: http://www.wowinterface.com/download...facts-1.0.html

Last edited by kokomala : 06-12-16 at 09:58 AM.
 
06-12-16, 04:33 PM   #12
liquidbase
A Warpwood Thunder Caller
 
liquidbase's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2010
Posts: 97
Originally Posted by kokomala View Post
You can still view the Artifact Perk UI by shift + right click for any artifact that may be in your bags. The artifact API will use whatever artifact is currently 'open', even if it is in your bags.

Pity the API didn't use specID.

Edit:
As this is something I've needed for my own project, I messed around and wrote a quick libstub library for caching artifact information (including those in your bags). Used some of the code above as a base (credit to your macro Rainrider). Data updates is handled by the library, you only need to call the data functions.

This is my first library (woo!) so code could probably be done better. Let me know if you have any issues with it: http://www.wowinterface.com/download...facts-1.0.html
Nice job !
Will check it out for my ArtifactBar in DuffedUI for the tooltip.
 
05-21-16, 12:57 PM   #13
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Originally Posted by Simca View Post
I'm confused, can you not just call LoadAddOn for the load-on-demand Blizzard Addon in question? (Blizzard_ArtifactUI)
Loading an addon out of context doesn't magicly give access to API data and will often times cause errors.



Originally Posted by syncrow View Post
Originally Posted by Rainrider View Post
HasArtifactEquipped() returns true even if the player has respecced but hasn't changed weapons yet, meaning your code gets potentially wrong information.
You'll change weapon automatically when you respec?! Or am I wrong?
The game tries to swap weapons when you change spec. It'll even unequip your current one if you don't have the artifact for the new spec. Sometimes it bugs out and fails this though.
__________________
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 : 05-21-16 at 01:01 PM.
 
05-21-16, 01:00 PM   #14
dssd
A Fallenroot Satyr
Join Date: May 2016
Posts: 25
@Simca Almost the opposite of that is what Rainrider wants I believe. When you use socket item that tells C to prepare artifact data for that artifact. When it's ready it fires the "ARTIFACT_UPDATE" event which Blizzard's Lua code looks for. That's how it knows to load the addon if it isn't already and open the UI. I believe Rainrider wants to just have C prepare the data without opening the Lua UI. That's why I recommended unregistering Blizzard's code from "ARTIFACT_UPDATE" before asking C to load the data for an artifact.

@syncrow I believe it leaves it equipped but in an "unusable" state kind of like if an equipped item reaches 0 durability.
 
05-22-16, 12:45 PM   #15
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
Originally Posted by dssd View Post
[...] When you use socket item that tells C to prepare artifact data for that artifact. When it's ready it fires the "ARTIFACT_UPDATE" event which Blizzard's Lua code looks for. That's how it knows to load the addon if it isn't already and open the UI. I believe Rainrider wants to just have C prepare the data without opening the Lua UI. That's why I recommended unregistering Blizzard's code from "ARTIFACT_UPDATE" before asking C to load the data for an artifact.

@syncrow I believe it leaves it equipped but in an "unusable" state kind of like if an equipped item reaches 0 durability.
Tested with the macro:
lua Code:
  1. /run local u,e,a=UIParent,"ARTIFACT_UPDATE",C_ArtifactUI;u:UnregisterEvent(e);SocketInventoryItem(16);for i,p in ipairs(a.GetPowers()) do print(GetSpellInfo((a.GetPowerInfo(p)))) end;a.Clear();u:RegisterEvent(e)
  1. You have to do C_ArtifactUI.Clear() when ready or else the artifact item remains in a locked state (item is grayed out and Shift+Right Clicking it no longer works)
  2. Once the ArtifactFrame has been opened, this no longer prevents the artifact UI from opening. You have to unregister "ARTIFACT_UPDATE" from ArtifactFrame as well (remember checking for nil here, as the ArtifactFrame exists only after Blizzard_ArtifactUI has been loaded)

You could use GetInventoryItemQuality("player", INVSLOT_MAINHAND) == LE_ITEM_QUALITY_ARTIFACT and GetInventoryItemEquippedUnusable("player", INVSLOT_MAINHAND) to check whether the right artifact is currently equipped.

Also using just SPELLS_CHANGED for tracking changes seems to be enough, at least for my purposes, but I haven't tested this extensively yet.
 
06-12-16, 05:10 PM   #16
syncrow
A Flamescale Wyrmkin
 
syncrow's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 149
Originally Posted by kokomala View Post
Let me know if you have any issues with it: http://www.wowinterface.com/download...facts-1.0.html
Once "Blizzard_ArtifactUI" is loaded, SocketInventoryItem(16) forces the UI to show the ArtifactFrame.
  • So you should use this gathering method only before the ArtifactUI was loaded
  • Afterwards its better to update your library whenever the ArtifactFrame is shown / updated while shown to avoid closing other frames...
__________________

Last edited by syncrow : 06-12-16 at 05:17 PM.
 
06-12-16, 07:02 PM   #17
kokomala
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 29
Originally Posted by syncrow View Post
Once "Blizzard_ArtifactUI" is loaded, SocketInventoryItem(16) forces the UI to show the ArtifactFrame.
  • So you should use this gathering method only before the ArtifactUI was loaded
  • Afterwards its better to update your library whenever the ArtifactFrame is shown / updated while shown to avoid closing other frames...
That's basically what I do. I have 3 primary internal functions for gathering. RefreshEquipped(), RefreshBags() handle initial gathering/search functions which has the above check (or similar) and C_ArtifactUI.Clear(). They then call RefreshPowers() function which assumes C_ArtifactUI is populated (it does a small check) and does the actual data population. This is all called during login (PLAYER_ENTERING_WORLD)

During regular gameplay, I call RefreshPowers() and that only occurs during ARTIFACT_UPDATE.

I was originally going to have a force update function, but I don't think that is necessary. Debating on writing a communication portion for sending trait information to other players, however that may be better suited for the addon itself rather than the library.

Last edited by kokomala : 06-12-16 at 08:44 PM.
 
06-13-16, 08:19 AM   #18
kokomala
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 29
Small update to the library. Minor optimisations (aka removed the double caching on first load etc), couple of minor changes to the error logic. More importantly added a new public function for number of powers purchased (which is now cached) which saves overhead.

I now class it as feature complete and looks to be working without issue.

Please let me know if you break it. Gathering artifact power to test it during gameplay is rather time consuming

Last edited by kokomala : 06-13-16 at 08:24 AM.
 
06-13-16, 01:55 PM   #19
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
The way you uploaded it, it won't load at all (no ToC file).

You need a way to tell users when data changed. You could use CallbackHandler for this.

Your RefreshEquipped() and RefreshBags() are double dipping as SocketInventoryItem and SocketContainerItem will issue ARTIFACT_UPDATE and your event handler will call RefreshPowers() again.

As long as you call RefreshEquipped() and RefreshBags() only at PLAYER_ENTERING_WORLD (PEW) you could spare the checks for ArtifactFrame. Your first call to SocketInventoryItem will load the ArtifactUI and from then on you actually open and close ArtifactFrame for every artifact in the player's inventory. This is probably not a problem as the user won't have any open UI panels during PEW. If you change this (by adding a forced update), you will have to consider that the ArtifactFrame listens for ARTIFACT_UPDATE as well.

GetPowerPurchased actually returns the number of purchased traits. Maybe GetNumTraitsPurchased would be a better name. Same goes for GetPowers and the like. I know you follow Blizzard's own naming here, but they probably coded that before the UI wording was set in place and didn't care to update the API to reflect that. Also prepending Lib to your addon name would be nice, but this is just my personal taste.

As for features, you could also provide the knowledge level and multiplier as those are only available when the ArtifactFrame is shown. They are shared between artifacts. The API for them is C_ArtifactUI.GetArtifactKnowledgeLevel() and C_ArtifactUI.GetArtifactKnowledgeMultiplier().
 
06-14-16, 01:21 AM   #20
kokomala
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 29
Originally Posted by Rainrider View Post
*snip*
Nice feedback. First library I've written, so a small learning curve - but everything helps

The library will work fine if it's embedded and your addon is reacting to events to pull data. I can make it standalone enabled and implement CallBackHandler to fire a cache update event, which will make this a little more friendly for UI display updates.

Feature wise, this was more intended towards caching just the traits. However thinking on it, it might be better to simply expand it to cache more of the data provided by C_ArtifactUI API (saves future requests). I'll need to look at the API listing again and see how best to manage what options there are. I don't want the library to take up too much UI time if I can help it. A fair bit of the functions will likely not be needed.

Naming wise was to keep it the somewhat similar to Blizzard's, as this partially turns the library into a cached alias for C_ArtifactUI, which is why I've opted to return information in the same format. I did totally do a goof on PowersPurchased (should have used GetTotalPurchasedRanks) :P

Your RefreshEquipped() and RefreshBags() are double dipping as SocketInventoryItem and SocketContainerItem will issue ARTIFACT_UPDATE and your event handler will call RefreshPowers() again.
This was the case on the first release and should be fixed in the 1.1 version. I basically shifted f:RegisterEvent('ARTIFACT_UPDATE') into the PEW event code, and then unregistered the PEW event to avoid rescanning whenever you hit a load screen.

--
One thing I've been debating on is if I should add bank inventory scanning - I'm leaning towards yes, regardless of how unlikely it is for an unscanned artifact to be equipped and used prior to caching that specific artifact. However this is entirely dependant if I can code it such that it doesn't intrude on the user - part of the issue is you can't 'socket' an item whilst it's in the bank.

Thanks again. Will keep the update discussion in this thread as I progress

edit:
As long as you call RefreshEquipped() and RefreshBags() only at PLAYER_ENTERING_WORLD (PEW) you could spare the checks for ArtifactFrame.
Initially I was going to keep this in, but after playing around with bag scanning after closing the bank it's far simpler to simply register/unregister both the UI and my controller for ARTIFACT_UPDATE during the scan. This avoids multiple triggers and it's fast enough.

The only issue is that if you have the artifact frame open, then close the bank - the artifact frame will close due to the data caching. I'd rather not have the library do this, but there's no other way to cache a new artifact. Something to muse over.

Last edited by kokomala : 06-14-16 at 09:09 AM.
 
 

WoWInterface » Site Forums » Archived Beta Forums » Legion Beta archived threads » Getting artifact perks data

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