What's new
  • Visit Rebornbuddy
  • Visit Panda Profiles
  • Visit LLamamMagic
  • Visit Resources
  • Visit Downloads
  • Visit Portal

diminishing returns && q about speed of calls

kaihaider

Community Developer
Joined
May 18, 2010
Messages
1,325
Reaction score
5
Is there any way to check diminishing returns?

On a side note, how fast are API calls like StyxWoW.Me.CurrentTarget compared to an instance variable; if you consider making several dozen reference calls every tick. Is there any type or call you can think of that would benefit from creating an instance variable instead of many library calls each tick?
 
Last edited:
As a follow up question: is there a way to tell which API calls are just wrapped lua calls?
 
Bumping this as I was about to post a question of diminishing returns myself. What is the best way to track DR?
 
On a side note, how fast are API calls like StyxWoW.Me.CurrentTarget compared to an instance variable; if you consider making several dozen reference calls every tick. Is there any type or call you can think of that would benefit from creating an instance variable instead of many library calls each tick?

The CurrentTarget property gets the corresponding object by finding in a dictionary, as the ObjectManager is cached. So the call of this is as fast as looking an entry in a dictionary. I don't think you need to use an extra variable for that.

Concerning DR, I didn't see something related to it in HB. You eventually could read the sources of an addon like DiminishingReturns to know how it manages them.

I far as I know, it isn't no "easy way" to check if a function wraps lua call(s).
 
I was thinking about the issue of DR and I suppose it would be possible to create DateTime variables that track when *WE* cast certain spells that create DR.

LastCheapShot = DateTime.Now

Using something like this would not work if another rogue already has a target on DR. With talents like "Cloak and Dagger" where the rogue is teleported to the CurrentTarget from within 30 yards my routine will cast Cheap Shot 3 times in a row during Subterfuge or Shadow Dance because the current target does not have the "Cheap Shot" aura active because he is immune. The teleport makes this hard to stop because even if i run out of melee the CurrentTarget is still within 30 yards. I need a smart way to decide against using Cheap Shot when a target is immune.

Is it possible to get a return on the cast that specifies if it was immune or something like that?

Is there an easy way to attach to the combat log to track DR? Is there a CR that is using the combat log I could look at?
 
You can subscribe to tons of Lua events using the method LuaEvents.AttachEvent(string, delegate). Here is the list of all events available. Look at the event COMBAT_LOG_EVENT_UNFILTERED.

An easy check would be to cast Cheap Shot and reads if the remaining time to the debuff is equal to *approximately* 4 sec (5 sec with the glyph) or just exists to check immunity.
I suggest the approach where you have a DrManager that parses the combat log stands a list of people that have dr. Nevertheless, it would be a big work.
 
DR isn't available on the client. Only the server knows about it.

Most addons "track" it by simply tracking the buffs that have been placed on a target, and when. You can simply recreate that tracking system to deal with DRs if you really want. But we won't be doing that for you in the HB core. It's more of a "luxury" thing. Simply subscribing to the combat log event and listening for the immune message is enough to tell when you should back off using things.
 
Thank, anyone working on a big project like this?
 
I think I've made it, this is what I do and I'm sure you guy can develop it further for what you need.

Step 1: I use the standard CombatLog.cs from Singular, you guy can find it in Honorbuddy\Routines\Singular\Utilities\CombatLog.cs

Step 2: I prepare a HashSet of ControlStun debuff
Code:
        private static readonly HashSet<int> ControlStunHS = new HashSet<int>
            {
                //Death Knight
                108194, // "ctrlstun", // Asphyxiate (talent)
                91800, // "ctrlstun", // Gnaw (Ghoul)
                91797, // "ctrlstun", // Monstrous Blow (Dark Transformation Ghoul)
                115001, // "ctrlstun", // Remorseless Winter (talent)
                // Druid
                22570, // "ctrlstun", // Maim
                9005, // "ctrlstun", // Pounce
                5211, // "ctrlstun", // Mighty Bash (talent)
                102795, // "ctrlstun", // Bear Hug
                113801,
                // "ctrlstun", // Bash (treants in feral spec) (Bugged by blizzard - it instantly applies all 3 levels of DR right now, making any target instantly immune to ctrlstuns)
                // Hunter
                24394, // "ctrlstun", // Intimidation
                90337, // "ctrlstun", // Bad Manner (Monkey)
                50519, // "ctrlstun", // Sonic Blast (Bat)
                //  56626,// "ctrlstun", // Sting (Wasp) //FIXME: this doesn't share with ctrlstun anymore. Unknown what it is right now, so watch for it on www.arenajunkies.com/topic/227748-mop-diminishing-returns-updating-the-list
                117526, // "ctrlstun", // Binding Shot (talent)
                96201, // "ctrlstun", // Web Wrap (Shale Spider)
                // Mage
                44572, // "ctrlstun", // Deep Freeze
                118271, // "ctrlstun", // Combustion Impact (Combustion; Fire)
                // Monk
                119392, // "ctrlstun", // Charging Ox Wave (talent)
                119381, // "ctrlstun", // Leg Sweep (talent)
                122242, // "ctrlstun", // Clash (Brewmaster)
                120086, // "ctrlstun", // Fists of Fury (Windwalker)
                // Paladin
                853, // "ctrlstun", // Hammer of Justice
                110698, // "ctrlstun", // Hammer of Justice (Symbiosis)
                119072, // "ctrlstun", // Holy Wrath (Protection)
                105593, // "ctrlstun", // Fist of Justice (talent)
                115752, // "ctrlstun", // Glyph of Blinding Light
                // Priest
                //  88625,// "ctrlstun", // Holy Word: Chastise //FIXME: this doesn't share with ctrlstun anymore. Unknown what it is right now, so watch for it on www.arenajunkies.com/topic/227748-mop-diminishing-returns-updating-the-list
                // Rogue
                1833, // "ctrlstun", // Cheap Shot
                408, // "ctrlstun", // Kidney Shot
                // Shaman
                118905, // "ctrlstun", // Static Charge (Capacitor Totem)
                // Warlock
                30283, // "ctrlstun", // Shadowfury
                89766, // "ctrlstun", // Axe Toss (Felguard)
                //  22703,// "ctrlstun", // Infernal Awakening (Infernal) // According to the DR thread on AJ, this doesn't have DR at all.
                // Warrior
                132168, // "ctrlstun", // Shockwave
                105771, // "ctrlstun", // Warbringer (talent)
                // Tauren
                20549, // "ctrlstun", // War Stomp
            };

Step 3: I create 2 Dictionary that store Control Stun expire time and Control Stun DR level
Code:
        private static Dictionary<WoWUnit, DateTime> ControlStunExpire = new Dictionary<WoWUnit, DateTime>();
        private static Dictionary<WoWUnit, int> ControlStunLevel = new Dictionary<WoWUnit, int>();

Steap 4: I create a function that increase DR level by 1 every time an unit got new debuff
Code:
        private static int ControlStunLevelGet(WoWUnit unit)
        {
            if (unit == null || !unit.IsValid)
            {
                return 0;
            }

            if (ControlStunLevel.ContainsKey(unit))
            {
                return ControlStunLevel[unit];
            }
            return 0;
        }


Step 5: I create a function that add unit got Control Stun debuff to these dictionary
Code:
        private static void ControlStunAdd(WoWUnit unit)
        {
            if (!ControlStunExpire.ContainsKey(unit))
            {
                ControlStunExpire.Add(unit, DateTime.Now + TimeSpan.FromSeconds(14));
            }
            else
            {
                ControlStunExpire.Remove(unit);
                ControlStunExpire.Add(unit, DateTime.Now + TimeSpan.FromSeconds(14));
            }

            if (!ControlStunLevel.ContainsKey(unit))
            {
                ControlStunLevel.Add(unit, 1);
                Logging.Write("ControlStun DR Level {1} on {0}", SafeName(unit), 1);
            }
            else
            {
                var currentlevel = ControlStunLevel[unit];
                ControlStunLevel.Remove(unit);
                ControlStunLevel.Add(unit, currentlevel + 1);
                Logging.Write("ControlStun DR Level {1} on {0}", SafeName(unit), currentlevel + 1);
            }
        }

Step 6: Now

Then I made a HandleCombatLog that only monitor event "SPELL_AURA_APPLIED" - "SPELL_AURA_REFRESH" and add to the 2 dictionary unit get stun, dr level, expiration time

Code:
        private static void HandleCombatLogTH(object sender, LuaEventArgs args)
        {
            var e = new CombatLogEventArgs(args.EventName, args.FireTimeStamp, args.Args);

            if (e.DestUnit == null ||
                e.Event != "SPELL_AURA_REFRESH" &&
                e.Event != "SPELL_AURA_APPLIED" ||
                !IsEnemy(e.DestUnit) ||
                !ControlStunHS.Contains(e.SpellId))
                return;

            if (ControlStunHS.Contains(e.SpellId))
            {
                ControlStunAdd(e.DestUnit);
            }
        }

Step 7: DR expire in 15 sec so I made this function to remove them from list, I call it every time when rotation start.
Code:
        private static List<WoWUnit> ControlStunRemoveList = new List<WoWUnit>();

        private static void ControlStunRemove()
        {
            ControlStunRemoveList.Clear();
            foreach (var unit in ControlStunExpire)
            {
                if (unit.Value < DateTime.Now)
                {
                    ControlStunRemoveList.Add(unit.Key);
                }
            }

            foreach (var unit in ControlStunRemoveList)
            {
                if (unit == null || !unit.IsValid)
                {
                    continue;
                }

                if (ControlStunExpire.ContainsKey(unit))
                {
                    ControlStunExpire.Remove(unit);
                }

                if (ControlStunLevel.ContainsKey(unit))
                {
                    ControlStunLevel.Remove(unit);
                }
                Logging.Write("StunControl DR expired on {0}", SafeName(unit));
            }
        }

Step 8: Finally 2 function that attach and detach CombatLogEvent, you don't always need it for example, you don't have to watch Stun DR on PvE... do remove it will make CR run faster in raid.
Code:
        #region AttachCombatLogEventTH

        private static bool CombatLogAttachedTH;

        private static void AttachCombatLogEventTH()
        {
            if (CombatLogAttachedTH)
                return;

            Lua.Events.AttachEvent("COMBAT_LOG_EVENT_UNFILTERED", HandleCombatLogTH);

            string filterCriteria = "return args[2] == 'SPELL_AURA_APPLIED')";

            if (!Lua.Events.AddFilter("COMBAT_LOG_EVENT_UNFILTERED", filterCriteria))
            {
                Logging.Write(
                    "ERROR: Could not add combat log event filter! - Performance may be horrible, and things may not work properly!");
            }

            Logging.Write("Attached AttachCombatLogEventTH");

            CombatLogAttachedTH = true;
        }

        #endregion

        #region DetachCombatLogEventTH

        private static void DetachCombatLogEventTH()
        {
            if (!CombatLogAttachedTH)
                return;

            Logging.Write("DetachCombatLogEventTH");
            Logging.Write("Removed combat log filter");
            Lua.Events.RemoveFilter("COMBAT_LOG_EVENT_UNFILTERED");
            Logging.Write("Detached combat log");
            Lua.Events.DetachEvent("COMBAT_LOG_EVENT_UNFILTERED", HandleCombatLogTH);

            CombatLogAttachedTH = false;
        }

        #endregion

I hope you guy can improved this.

Thank you for reading.

TuanHA
 
Last edited:
Just update with improved DR tracker using SPELL_AURA_REFRESH as SPELL_AURA_APPLIED is not enough.

This is what I get:

When a Paladin in my team cast Blind and it affect 3 unit around Warlock, Mage and his Pet
[19:51:49.336 N] Disorients DR Level 1 on Warlock
[19:51:49.348 N] Disorients DR Level 1 on Elemental
[19:51:49.349 N] Disorients DR Level 1 on Mage

14 sec later the timer remove Disorients DR on them
[19:52:03.393 N] Disorients DR expired on Elemental
[19:52:03.393 N] Disorients DR expired on Warlock
[19:52:03.393 N] Disorients DR expired on Mage


When a warrior friend charge a Paladin, he also stun a Warrior and a nearby warlock pet
[19:51:59.704 N] ControlStun DR Level 1 on Demon
[19:51:59.705 N] ControlStun DR Level 1 on Warrior
[19:51:59.706 N] ControlStun DR Level 1 on Paladin
 
hi Tuanha thank you for that code!

string filterCriteria = "return args[2] == 'SPELL_AURA_APPLIED')";

i'm not sure but maybe the ) doesn't go there
 
Back
Top