Overlapping bit masks
Adirelle opened this issue ยท 7 comments
Currently sources, dispel type and CC type overlaps in the bitmask.
I'm wondering about rewriting them to allow proper combination, to the cost of being a little more complicated to match (e.g. using (mask, expected value) pairs instead of just a mask).
The first thing to do is to identify the fields (e.g. groups of values that are unique for a given spell).
- source: class or racial
- spell type: dispel (+types), cc (+types), survival, burst, interrupt, knockback (isn't it a CC ?), snare (same question)
- is it an aura ?
- is it an inverted aura ?
- is it an unique aura ?
- targeting: friend, foe, pet, self,
- does the spell have a cooldown ?
Then we assign a bitfield to each of them
--[[
Bit fields of the flag value:
0000 0000 0000 000a bcde ffgg ghhh iiii
0: unused
a: important ?
b: has cooldown ?
c: unique aura ?
d: inverted aura ?
e: is an aura ?
ff: target
ggg: subtype
hhh: type
iiii: source
]]
-- Basic constants use for the bitfields
lib.constants = {
-- Sources (4 bits)
RACIAL = 0x00000000, -- Racial trait
DEATHKNIGHT = 0x00000001,
DEMONHUNTER = 0x00000002,
DRUID = 0x00000003,
HUNTER = 0x00000004,
MAGE = 0x00000005,
MONK = 0x00000006,
PALADIN = 0x00000007,
PRIEST = 0x00000008,
ROGUE = 0x00000009,
SHAMAN = 0x0000000A,
WARLOCK = 0x0000000B,
WARRIOR = 0x0000000C,
-- Spell type (3 bits)
SURVIVAL = 0x00000000,
BURST = 0x00000010,
POWER_REGEN = 0x00000020,
INTERRUPT = 0x00000030,
CROWD_CTRL = 0x00000040,
DISPEL = 0x00000050,
-- Spell subtype (3 bits)
-- Crowd control subtypes
DISORIENT = 0x00000000,
INCAPACITATE = 0x00000080,
ROOT = 0x00000100,
STUN = 0x00000180,
TAUNT = 0x00000200,
KNOCKBACK = 0x00000280,
SNARE = 0x00000300,
-- Dispel subtypes
CURSE = 0x00000000,
DISEASE = 0x00000080,
MAGIC = 0x00000180,
POISON = 0x00000200,
-- Targeting (2 bits)
HELPFUL = 0x00000000, -- Usable on allies
HARMFUL = 0x00000400, -- Usable on enemies
PERSONAL = 0x00000800, -- Only usable on self
PET = 0x00000C00, -- Only usable on pet
-- Various flags (1 bit each)
AURA = 0x00001000, -- Applies an aura
INVERT_AURA = 0x00002000, -- Watch this as a debuff on allies or a buff on enemies
UNIQUE_AURA = 0x00004000, -- Only one aura on a given unit
COOLDOWN = 0x00010000, -- Has a cooldown
IMPORTANT = 0x00020000, -- Important spell the player should react to
}
We could add convenient methods to extract values from the flags, e.g. lib:GetSource(flags), lib:GetType(flags), ...
The main question I ask myself is the integration of snare and knockback in the CC subtypes. They are CC, but do they have a DR ? If not, we could easily move them to the spell types.
I see nothing about silences, did they get removed ?
What do you think of all this ?
Snares are technically not CC and do not share DR. Knockbacks are on a 10 sec timer and the target becomes fully immune to them in the 10 sec window. Silences are also a DR and are currently not listed under CC in LPS. They are under the INTERRUPT flag.
The problem with DR is that it can't be properly done without combat log parsing. The issue is that further applications of a same category spell reset the DR window to its full duration, so if the target is already immune, no auras will be applied. This is related to LPS only to the extent that probably it is not that useful to DR addons since it only provides aura information usable with UNIT_AURA. There are quite a few SPELL_AURA_APPLIED (or whatever it is actually called) cases though, where the aura is hidden and thus can only be acquired by parsing the combat log.
There is no firm reason not to include Knockbacks and Silences under CROWD_CTRL. It will even save two more bits for further growth with the current implementation. I think I left them outside just to signify that LPS has only provider spells info on those.
Another flag that would be useful is PASSIVE - to signify auras that are passively applied. It would allow to easily generate a rule for snares so that the rule is not applied to passive providers.
I actually think the current bitmask system is fine. The only issue is possibility for growth since we only have two spare bits now. I'm not sure I understand the benefit of changing it. Do you have a specific use case that is not possible currently?
I agree on the PASSIVE flag. It could be useful to (optionally) disable the feedback for all passive buffs. Buffs that you can't actively cause and you won't use (e.g. you won't play differently if it is present or not) are no good candidate for display ; they just cause feedback clutter.
Well, I have a specific uses of LPS in oUF_Adirelle, which is a bit different from AdiButtonAuras since it is a unit frame addon.
These specific uses are:
- Show survival buffs on raid frames so healers know when someone in their group use them,
- Show player's buffs on raid members, very useful for healers,
- Show CCs as big warnings icons on unit and raid frames, useful in PvP.
- Show dispellable debuffs on raid frames, very useful for healers.
- Show dispellable buffs on targets.
For the last two points, having both the source and the dispel type would help reduce the cases to test.
About the CC, I do not really need to handle the DR, though my addon DiminishingReturn, currently based on DRData-1.0, would better use PLS since it is more up-to-date and more actively maintained.
For CC you should be able to get all the info by using LPS:IterateSpells. The second return contains the source flags, the fifth contains the dr category. Silences and Knockbacks are not included but you don't need a warning for those apart from the DR immunity window duration, which requires combat log parsing. LPS only has provider spell info on those and for that reason you'll need to pull them separately. Again, no firm reason not to include those two under CC, but either way you'll have to handle them differently and this won't change the way you get them from LPS - i.e. LPS:IterateSpells("INTERRUPT")
.
I suppose for oUF_Adirelle you want a warning like "don't shoot at CC that breaks on damage". For that you don't need source information at all.
LPS:IterateSpells does not return the DISPEL category yet, because I wanted to figure a way to do it in ABA and update both together. However it is a minute of work to add this to LPS, I just have to update ABA calls to LPS:IterateSpells to account for the new return. I think the usage then would be something like that:
- Get all dispels for the current class -
LPS:IterateSpells("DISPEL", (select(2, UnitClass("player")))
- bit.band the 6th return to build a list of what the player can dispel. Basically like how LD does it now
- compare that to the 5th return of UnitAura for debuffs on friendly units or to the 9th return of UnitAura for buffs on foes.
I forgot (or didn't notice) the dispel and cc flags were extracted from the base flags and moved to the "specials" table. The DISPEL return value should fulfill my needs.
This is the current flag distribution on the bit mask. I'm leaning towards moving Knockbacks and Interrupts to CC and adding PASSIVE under "various flags". The reason is that if I just add PASSIVE on the 30th bit, we run out of place for growth - only one free bit remains, preferably for a new class in case Blizzard adds yet another one. What do you think?
IMPORTANT could be used for stuff like what was BURST_HASTE previously. Or to signify some otherwise important cooldowns that do not belong to a specific category.