Thread Tools Display Modes
08-01-08, 02:54 AM   #1
Olvar
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 10
Question InCombatLockdown() versus Events and Bool

What would be more efficient to check if the player is in combat, in your opinion?

1. Calling InCombatLockdown().

2. Registering events PLAYER_REGEN_DISABLED and PLAYER_REGEN_ENABLED and remembering the status in a local bool variable.
  Reply With Quote
08-01-08, 03:43 AM   #2
VagrantEsha
Token Werewolf Fan
 
VagrantEsha's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Apr 2008
Posts: 27
Would you be registering any other events in the mod?
  Reply With Quote
08-01-08, 05:02 AM   #3
Olvar
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 10
I already have PLAYER_REGEN_DISABLED and COMBAT_LOG_EVENT_UNFILTERED registered, which is why I think that changing some InCombat bool to false in a PLAYER_REGEN_ENABLED event might be faster than using InCombatLockdown().

But I wanted to know what other authors with more knowledge of the whole system think about it.

From what I understand, using something local is always faster. Thus working with a local bool variable should be more efficient than calling a global function.
  Reply With Quote
08-01-08, 06:09 AM   #4
Taffu
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 149
I've always found PLAYER_REGEN_ENABLED and PLAYER_REGEN_DISABLED to be more reliable means for combat association, and using a local.
  Reply With Quote
08-01-08, 06:55 AM   #5
Akryn
A Firelord
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 479
Originally Posted by Taffu View Post
I've always found PLAYER_REGEN_ENABLED and PLAYER_REGEN_DISABLED to be more reliable means for combat association, and using a local.
the other advantage to the events is that they fire when the player is not locked down; so if you want to perform some last-second actions before things get locked, you can do that.
  Reply With Quote
08-01-08, 09:42 AM   #6
Duugu
Premium Member
 
Duugu's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 851
COMBAT_LOG_UNFILTERED means there are a LOT calls oft your event handler - at least in combat or with other people in range. Or not?
And how often will you call InCombatLockdown() in your code?

I don't think that there are mentionable performance differences between both ways ... at least not within common scenarios.

Furthermore you could make InCombatLockdown() local, or not?

local InCombatLockdown = InCombatLockdown

Shouldn't this boost the performance?

Last edited by Duugu : 08-01-08 at 09:46 AM.
  Reply With Quote
08-01-08, 10:03 AM   #7
Shirik
Blasphemer!
Premium Member
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2007
Posts: 818
Originally Posted by Olvar View Post
What would be more efficient to check if the player is in combat, in your opinion?

1. Calling InCombatLockdown().

2. Registering events PLAYER_REGEN_DISABLED and PLAYER_REGEN_ENABLED and remembering the status in a local bool variable.
There is a difference, though the difference is slight.

Firstly, before I say anything, accessing locals is free. However, you probably don't mean local, you probably mean upvalue. But if it were truly a local, it would be a free lookup (and the test is extremely fast).

Calling InCombatLockdown() can be a global call unless you retain a local copy of it, and even then it will require a call. This means this will always be slower.


HOWEVER: The two things you are saying are not the same:

Code:
local isInLockdown = false;
local frame = CreateFrame "FRAME"
frame:RegisterEvent("PLAYER_REGEN_ENABLED");
frame:RegisterEvent("PLAYER_REGEN_DISABLED");
frame:SetScript("OnEvent", function(self, event, ...)
   if event == "PLAYER_REGEN_DISABLED"
      isInLockdown = true;
   elseif event == "PLAYER_REGEN_ENABLED"
      isInLockdown = false;
   end
end);
This will work for most purposes, but let's say that we had a little change:


Code:
local isInLockdown = false;
local frame = CreateFrame "FRAME"
frame:RegisterEvent("PLAYER_REGEN_ENABLED");
frame:RegisterEvent("PLAYER_REGEN_DISABLED");
frame:SetScript("OnEvent", function(self, event, ...)
   if event == "PLAYER_REGEN_DISABLED"
      isInLockdown = true;
      test();
   elseif event == "PLAYER_REGEN_ENABLED"
      isInLockdown = false;
      test();
   end
end);

function test()
   assert(isInLockdown == not not InCombatLockdown());
end
You will find assertion failures popping up all over the place. In particular, you go into lockdown at some time shortly after PLAYER_REGEN_DISABLED. At PLAYER_REGEN_DISABLED, you are still not in lockdown. This may be a relevant difference for some addons. Keep this in mind.
__________________
たしかにひとつのじだいがおわるのお
ぼくはこのめでみたよ
だけどつぎがじぶんおばんだってことわ
しりたくなかったんだ
It's my turn next.

Shakespeare liked regexes too!
/(bb|[^b]{2})/
  Reply With Quote
08-01-08, 11:20 AM   #8
Tekkub
A Molten Giant
 
Tekkub's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 960
The real question is how often, on average, are you calling InCombatLockdown()? If it's more than twice per combat session, the events would be the faster route. You can, of course, hold a local of the function to avoid that global lookup Shirik mentions, but there's not much point to that if you're only calling once or twice.
  Reply With Quote
08-02-08, 04:44 AM   #9
Olvar
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 10
First of all, thanks for taking part in the discussion, guys.

In case you are wondering, what this is for, it's part of my Pull Waring addon:
http://www.wowinterface.com/download...llWarning.html

I know that COMBAT_LOG_EVENT_UNFILTERED means a lot of events, which is why I want to make the test as fast as possible. Unfortunately Faerie Fire is still not part of the filtered combat log, so I'm forced to use the unfiltered events.

The only advantage (for my purposes) of InCombatLockdown() I can think of right now, is that the check is correct even when the addon is enabled after you are already in combat. But I can check that when I'm registering the events and simply set my local bool accordingly.

I'll have to do an update of my addon anway, because I found a very peculiar bug during a raid yesterday. Try the following:

/rw ** Body Pull **
(Leads to the pull warning sound and the message ** Body Pull ** being displayed)

/rw *** Body Pull ***
(You can hear the pull warning sound, but there will be no message!)

According to my tests, a raid warning starting with at least three asterisks won't be displayed, but the sound effect is generated. Very strange indeed.
  Reply With Quote
08-02-08, 07:42 AM   #10
Broken Hope
A Defias Bandit
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 3
Originally Posted by Olvar View Post
I'll have to do an update of my addon anway, because I found a very peculiar bug during a raid yesterday. Try the following:

/rw ** Body Pull **
(Leads to the pull warning sound and the message ** Body Pull ** being displayed)

/rw *** Body Pull ***
(You can hear the pull warning sound, but there will be no message!)

According to my tests, a raid warning starting with at least three asterisks won't be displayed, but the sound effect is generated. Very strange indeed.
That's not a bug as far as I know, it's due to mods like Bigwigs and Deadly Boss Mods, they have Bossblock features which block RW spam from other mods, these RW messages have 3 asterisks at the start.

This is taken from the BossBlock module of Bigwigs

Code:
function plugin:IsSpam(text)
	if type(text) ~= "string" then return end
	if fnd(text, "%*%*%*") then return true end
end
  Reply With Quote
08-02-08, 12:51 PM   #11
Tekkub
A Molten Giant
 
Tekkub's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 960
Stupid question, but are you wanting to only listen to COMBAT_LOG_EVENT_UNFILTERED when in combat?
  Reply With Quote
08-03-08, 05:51 AM   #12
Olvar
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 10
Originally Posted by Broken Hope View Post
That's not a bug as far as I know, it's due to mods like Bigwigs and Deadly Boss Mods, they have Bossblock features which block RW spam from other mods, these RW messages have 3 asterisks at the start.
Thanks for clearing this up. That explains a lot. I knew that BigWigs had some filter, but I didn't know how it actually worked. I've changed my output accordingly.

Originally Posted by Tekkub View Post
Stupid question, but are you wanting to only listen to COMBAT_LOG_EVENT_UNFILTERED when in combat?
Since Pull Warning shall display a warning as soon as an enemy is pulled but otherwise keep quite during combat, I need the event just before combat is entered. Of course this could be done with PLAYER_REGEN_DISABLED only, but the event for an instant cast fires a little bit earlier and I also like the fact that I'm able to display the pullers name and the enemy.

But your question wasn't stupid at all, because it reminded me that I could actually unregister COMBAT_LOG_EVENT_UNFILTERED during combat. I'm not sure how efficient UnregisterEvent() is, but for a longer combat and especially in a raid it will be much better than catching all those combat events and ignoring them.

The redesigned code seems to work fine solo and in a group. I should have a chance to test it in a raid this evening. Unless I notice any problems I'll probably update the addon tomorrow.

Thank again for the discussion.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » InCombatLockdown() versus Events and Bool


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