Thread Tools Display Modes
11-28-09, 06:15 PM   #1
Shark5060
A Deviate Faerie Dragon
 
Shark5060's Avatar
Join Date: Jul 2009
Posts: 14
Get Talent Info from other Players

Well, where to start..

I'm actually trying to enhance the "debuff" frame from the LUI Addon. for those who don't know the package - there is a little frame in the lower screen displaying applied debuffs of the mob. The main problem is that some debuffs can either be "skilled" or not (Like Farie Fire or Judgement of Wisdom or stuff). By default you have to add the name of the players with the skilled Talents in the config and then the frame displays the buff if the name fits.

I thought that it may be possible to read the talents the player who applied the debuff got and then update the frame.

My tries looked like this:

Code:
if UnitExists("target") then
 if (not UnitIsFriend("player","target")) and (UnitLevel("target") == -1) then
  while true do
   local name,_,_,count,_,_,_,caster = UnitAura("target",i,"HARMFUL")
   if not name then
    break
   elseif (name == "Judgement of Wisdom") then
    wisdom = true
    if UnitExists(caster) then
     -- Insert TalentCheck here...
     crit = true
    end
   end
   i = i + 1
  end
  if wisdom then
   wisdomColor = 'ffffff';
  end
  if crit then
   critColor = 'ffffff';
  end
  self.text:SetText('||cff'..wisdomColor..'WIS||r||cff'..critColor..'3%||r');
 else
  self:Hide();
 end
else
 self:Hide();
end
I tried to get the talent with GetTalentInfo(3,4,true) but sometimes I got the wrong talent when the caster used dualspec - you can determine the "right" spec with GetActiveTalentGroup() and you also can use it with GetTalentTabInfo() cause this supports a "groupindex" argument, but that doesn't help very much for my problem XD

anyone else got an idea how to solve it, or is there no actual solution for this problem ?
  Reply With Quote
11-28-09, 06:24 PM   #2
Akryn
A Firelord
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 479
You left out the only part of the code that's important, which is the actual talent check (!!)

If your question is, "is it possible to accurately get talent information from other players," then yes it is. If you are trying to do so and getting bad results, you just need to fix your code; it's not a problem with the game. I don't know what specific problem you have though, since you didn't post your code.
  Reply With Quote
11-28-09, 07:05 PM   #3
Shark5060
A Deviate Faerie Dragon
 
Shark5060's Avatar
Join Date: Jul 2009
Posts: 14
okay, well sure I left it out since I tried many possibilities and didn't remember which one worked at least a bit.

But since you say that it _IS_ possible to get these informations here is the latest code I used:

Code:
if UnitExists(caster) then
 local tTab = GetActiveTalentGroup(true,false)
 local _,_,_,_,cTal,mTal,_,_ = GetTalentInfo(3,4,true,false,tTab)

 if (cTal == mTal) then
  crit = true
 end
end
dunno if I forgot sth, since I had many chat outputs and checks included.. but I guess that's the "main" function.
__________________
The rush of battle is often a potent and lethal addiction, for war is a drug - Chris Hedges
  Reply With Quote
11-28-09, 07:55 PM   #4
Akryn
A Firelord
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 479
That part looks good to me. Are you:

1. Hooking NotifyInspect to make sure no one calls it between your call and the event firing.
2. Calling "NotifyInspect(caster)"
3. Waiting for INSPECT_TALENT_READY
4. Making sure (using #1 in some way) that this event fired because of your call of NotifyInspect

...before that code executes?
  Reply With Quote
11-28-09, 08:47 PM   #5
Shark5060
A Deviate Faerie Dragon
 
Shark5060's Avatar
Join Date: Jul 2009
Posts: 14
okay ... I didn't even know that there WERE such functions, tbh.

well.. after reading the API of these stuff, I'm not exactly sure how to use hooksecurefunc() .. but uhm I'll give it a try.

Code:
OnLoad:
self:RegisterEvent("INSPECT_TALENT_READY");
cTable = {};
cTalents = {};

onEvent:
if UnitExists(caster) then
 if not caster in cTable then
  local hooksecurefunc("NotifyInspect", function(caster));
  cTable[#cTable+1] = caster;
 else
  if (event == "INSPECT_TALENT_READY") then
   local tTab = GetActiveTalentGroup(true,false)
   local _,_,_,_,cTal,mTal,_,_ = GetTalentInfo(3,4,true,false,tTab)

   if (cTal == mTal) then
     crit = true
   end

   cTalents[#cTalents+1] = crit;
  end

  for i, #cTable do
   if ((cTable[i] == caster) and (cTalents[i] == true)) then
    crit = true
   end
  end
 end
end
__________________
The rush of battle is often a potent and lethal addiction, for war is a drug - Chris Hedges

Last edited by Shark5060 : 11-28-09 at 08:51 PM.
  Reply With Quote
11-28-09, 09:24 PM   #6
Akryn
A Firelord
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 479
Getting closer:

Code:
  local hooksecurefunc("NotifyInspect", function(caster));
You can't put "local" in front of a function call. You also need to define what the function you're passing as the second argument should do. What I do is define a higher-level local called inspectTainted which I set to true in the function I pass to hooksecurefunc, and set to false after I call NotifyInspect.

Code:
  if (event == "INSPECT_TALENT_READY") then
You need to make this a top-level conditional in your OnEvent function, or give it its own function. You also can't do any talent checking, or any action that depends on the talent check having been completed, other than in response to this event firing, or you will get bad data.
  Reply With Quote
11-28-09, 11:09 PM   #7
Shark5060
A Deviate Faerie Dragon
 
Shark5060's Avatar
Join Date: Jul 2009
Posts: 14
well... seems I don't understand "hooksecurefunc" very well..

so I call a function, which is described in the brackets "NotifyInspect" .. also this function calls another function in which I should THEN call the real NotifyInspect which was "reserved" (aka hooked) in the previous funktion.. I also should set a variable to "true" to check if the "INSPECT_TALENT_READY" was hooked or not.

if I understood everything right:

Code:
OnLoad:
self:RegisterEvent("INSPECT_TALENT_READY");
cTable = {};
cTalents = {};
inspecting = true;

local function getTal(caster,state)
 NotifyInspect(caster);
 inspecting = state;
end

onEvent:
if (event == "INSPECT_TALENT_READY") then
 if (inspecting == true) then
  local tTab = GetActiveTalentGroup(true,false)
  local _,_,_,_,cTal,mTal,_,_ = GetTalentInfo(3,4,true,false,tTab)

  if (cTal == mTal) then
    crit = true
  end

  cTalents[#cTalents+1] = crit;
  inspecting = false;
 end
end

if UnitExists(caster) then
 if not caster in cTable then
  hooksecurefunc("NotifyInspect", getTal(caster,true));
  cTable[#cTable+1] = caster;
 else
  for i, #cTable do
   if ((cTable[i] == caster) and (cTalents[i] == true)) then
    crit = true
   end
  end
 end
end
if not - well tell me how this funtion really works. I am really glad that you help me that much and even more that you try to explain it instead of posting the finished code !
__________________
The rush of battle is often a potent and lethal addiction, for war is a drug - Chris Hedges
  Reply With Quote
11-28-09, 11:50 PM   #8
Akryn
A Firelord
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 479
That is much closer.

hooksecurefunc calls the second function whenever the first function is called by *anyone* even if it's not your addon. The problem that we're solving with hooksecurefunc is that NotifyInspect takes time to return its result (INSPECT_TALENT_READY tells you it's ready) but another addon can call it in the mean time (tooltip addons are especially prone to do this).

If someone else calls the function after you do and before you get the answer, the answer you get will be *only* for the second caller. Therefore if that happens you need to ignore the result and ask again. You should not call NotifyInspect again from within the second function, as that function is being called in response to NotifyInspect being called; all you're doing is noting that it was called. If it was called by someone other than you *and* you are currently waiting for an answer from NotifyInspect then you need to try again.

You also only need to hook the function once, not every time your OnEvent gets called; you can do it in your OnLoad handler.

You shouldn't need to change your code much to accomplish that. One other point is that:

Code:
...
 inspecting = false;
 end
end

if UnitExists(caster) then
...
should be:


Code:
...
 inspecting = false;
 end
 elseif UnitExists(caster) then
...
or there should be some other way to prevent your other code from running if the event is INSPECT_TALENT_READY
  Reply With Quote
11-29-09, 12:23 AM   #9
Shark5060
A Deviate Faerie Dragon
 
Shark5060's Avatar
Join Date: Jul 2009
Posts: 14
well okay... guess now I understand it more clearly. Just got one problem - if the 2nd function argument is called EVERY time, the global function is called, then how should I ensure that it was my call and not by another addon ?

I mean if I set a variable in this function to true, it is set to true everytime some random addon tries to get the talents. Or is the function just triggered when the hooked one is called from within my addon ?

Code:
OnLoad:
self:RegisterEvent("INSPECT_TALENT_READY");
cTable = {};
cTalents = {};
inspecting = true;
hooksecurefunc("NotifyInspect", getTal(true));

local function getTal(state)
 inspecting = state;
end

onEvent:
if (event == "INSPECT_TALENT_READY") then
 if (inspecting == true) then
  local tTab = GetActiveTalentGroup(true,false)
  local _,_,_,_,cTal,mTal,_,_ = GetTalentInfo(3,4,true,false,tTab)

  if (cTal == mTal) then
    crit = true
  end

  cTalents[#cTalents+1] = crit;
  inspecting = false;
 end
end


-- called in another event just cut the code a bit
if UnitExists(caster) then
 if not caster in cTable then
  NotifyInspect(caster);
  cTable[#cTable+1] = caster;
 else
  for i, #cTable do
   if ((cTable[i] == caster) and (cTalents[i] == true)) then
    crit = true
   end
  end
 end
end
When the getTal() is called everytime someone calls NotifyInspect() I have to think about that problem again ... if not well.. guess than I'm not that far away from testing that ingame again xD
__________________
The rush of battle is often a potent and lethal addiction, for war is a drug - Chris Hedges
  Reply With Quote
11-29-09, 07:56 AM   #10
Coren
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Apr 2006
Posts: 6
There's two ways to recognize in the hook-function if it was your call of NotifyInspect:
a) evaluate debugstack():
- is the function that *called* NotifyInspect yours?
( if not strfind(debugstack(), "MyFunctionThatCallsNotifyInspect") then foreignCall = time(); end )
b) add an additional argument:
- hooksecurefunc("NotifyInspect", function(unit, flag) if (flag ~= "YourAddOnName") then foreignCall = time(); end)
- NotfiyInspect("unit", "YourAddOnName")
- this requires that you keep a list of functions you expanded and check on new versions of WoW if Blizzard added a new argument themselves...

Additional suggestion: add time barriers around your use of the function. (I use 10s of pause before I call NotifyInspect, then wait up to 10s for the reply, if any other but my NotifyInspect happened in the whole time frame, I ignore the results and requeue. This also catches the error that sometimes the event simply doesn't happen at all for *no* obvious reason.)
This means you actually do most of the work in OnUpdate/OnEvent calls, while your regular code just queues new requests.

Also, you might want to hook if the player is inspecting someone himself, and NOT do anything then (i.e. hook the OnShow/OnHide of the InspectFrame, put your code on hold in OnShow, restart it in OnHide).

P.S.: I hope your
> hooksecurefunc("NotifyInspect", getTal(true));
is after your definition of getTal...

Last edited by Coren : 11-29-09 at 08:07 AM.
  Reply With Quote
11-29-09, 10:23 AM   #11
Shark5060
A Deviate Faerie Dragon
 
Shark5060's Avatar
Join Date: Jul 2009
Posts: 14
After several hours of trying (and failing XD) I just discovered http://www.wowace.com/addons/libgrouptalents-1-0/

seems that one fixes all my problems, doesn't it ? sure it would have been nice to discover the way it works myself but seems that I'm not that much into programming as if needs.
__________________
The rush of battle is often a potent and lethal addiction, for war is a drug - Chris Hedges
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Get Talent Info from other Players


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