View Single Post
  #2  
Unread 04-21-2013, 04:24 PM
Garan's Avatar
Garan Garan is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Oct 2010
Posts: 340
Just a quick glance shows that you are redefining the self.effectAddedHandler function on every call to EffectTracker:HandleEffects so the table representing the function is not the same after each call. The function should either be defined once and used for everyone or there should be a table of functions with one instance for each player depending on what exactly you are doing with the function. But in any case you definately should not be redefining the function and then expecting it to match when you remove it - in other words, only functions that match an entry in the event table will get removed and since you redefined it, it doesn't match and isn't removed. As implemented, this actually should fail for all but one party member, that being the last one passed to EffectTracker:HandleEffects so I'm not sure how you were testing but if you only tested with a party of two then it would appeared to be working for all but the local player (when in fact it was just working for the last one added).

Basically, to fix this, move the definition of the callback funtions outside of the routine that adds them (you would use the "sender" argument to determine which player triggered the event) or create a table of functions, one for each player, i.e. self.effectAddedHandler[player:GetName()]=function...
Of couse, if you go the route of using a table, then you have to pass the correct instance to the removecallback -
RemoveCallback(v, "EffectAdded", self.effectAddedHandler[k]);

So, option 1 is to move the definition outside :HandleEffects and use the Sender to determine the player that fired the event
Code:
self.effectAddedHandler = function(sender, args)
 -- outputs data to chat window (code not important to discussion)
end
function EffectTracker:HandleEffects(player)
 self.effectList[player:GetName()] = player:GetEffects(); -- kept for removecallback function
 AddCallback(player:GetEffects(), "EffectAdded", self.effectAddedHandler);
end
-- used to make sure party is current
self.partyChangedHandler = function(sender, args)
 if localPlayer:GetParty() == nil then
  RemoveCallback(party, "MemberAdded", self.partyChangedHandler);
  RemoveCallback(party, "MemberRemoved", self.partyChangedHandler);
  self:RemoveEffectCallbacks();
 end
 party = localPlayer:GetParty();
 self:TrackEffects();
end
function EffectTracker:UpdateParty()
 AddCallback(localPlayer, "PartyChanged", self.partyChangedHandler);
 AddCallback(localPlayer, "RaidChanged", self.partyChangedHandler);
 if party ~= nil then
  self:TrackEffects();
 end
end
-- this is where the problem is
function EffectTracker:RemoveEffectCallbacks()
 if self.effectList ~= nil then
  for k, v in pairs(self.effectList) do
                 -- should remove event functions for the EffectAdded events for all members of the fellowship. It works for every member of the fellowship, but fails to remove the localplayers event.
   RemoveCallback(v, "EffectAdded", self.effectAddedHandler);
  end
                -- added this to remove that callback that is not removed using RemoveCallback() function
  if localPlayer:GetEffects()["EffectAdded"] ~= nil then
   localPlayer:GetEffects()["EffectAdded"] = nil;
  end
 end
end
and option 2 is to use a table of handlers
Code:
self.effectAddedHandler={}
function EffectTracker:HandleEffects(player)
 local playerName=player:GetName()
 self.effectList[playerName] = player:GetEffects(); -- kept for removecallback function
 self.effectAddedHandler[playerName] = function(sender, args)
  -- outputs data to chat window (code not important to discussion)
 end
 AddCallback(player:GetEffects(), "EffectAdded", self.effectAddedHandler[playerName]);
end
-- used to make sure party is current
self.partyChangedHandler = function(sender, args)
 if localPlayer:GetParty() == nil then
  RemoveCallback(party, "MemberAdded", self.partyChangedHandler);
  RemoveCallback(party, "MemberRemoved", self.partyChangedHandler);
  self:RemoveEffectCallbacks();
 end
 party = localPlayer:GetParty();
 self:TrackEffects();
end
function EffectTracker:UpdateParty()
 AddCallback(localPlayer, "PartyChanged", self.partyChangedHandler);
 AddCallback(localPlayer, "RaidChanged", self.partyChangedHandler);
 if party ~= nil then
  self:TrackEffects();
 end
end
-- this is where the problem is
function EffectTracker:RemoveEffectCallbacks()
 if self.effectList ~= nil then
  for k, v in pairs(self.effectList) do
                 -- should remove event functions for the EffectAdded events for all members of the fellowship. It works for every member of the fellowship, but fails to remove the localplayers event.
   RemoveCallback(v, "EffectAdded", self.effectAddedHandler[k]);
  end
                -- added this to remove that callback that is not removed using RemoveCallback() function
  if localPlayer:GetEffects()["EffectAdded"] ~= nil then
   localPlayer:GetEffects()["EffectAdded"] = nil;
  end
 end
end
As I first mentioned, this was just a quick glance so there may be other issues but this was the first that I noticed and seemed to cause the symptom you were experiencing. I also didn't test the solution code so there may be typos but the intent should be clear.

Last edited by Garan : 04-21-2013 at 04:40 PM.
Reply With Quote