• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Lua] SpellStealEvent

Lua:
--[[ SpellStealEvent V1.2 by Tasyen

Requires Warcraft 3 V1.33+
SpellStealEvent provides an event when a buff is transfered using the spellsteal ability. It tells the buff gainer/loser and the buff.
This System works by checking for dmg events which trigger when a spell steal appears. Inside that events it iterates over all abilities the unit has and checks for lost ones.

udg_SpellStealEventBuff
udg_SpellStealEventGainer
udg_SpellStealEventLoser
udg_SpellStealEvent = 1.0


call SpellStealEventInit() to start the system (it creates a trigger)
autohandled when you have Global Initialization 3.0.0.1 https://www.hiveworkshop.com/threads/global-initialization.317099/

--]]
SpellStealEvent = {
    -- what To do 
    Action = function(gainer, buffCode, loser)
        --print(string.pack('>I4', buffCode), GetObjectName(buffCode), GetAbilityName(buffCode))
        --if true then return true end
        udg_SpellStealEventBuff = buffCode
        udg_SpellStealEventGainer = gainer
        udg_SpellStealEventLoser = loser
        globals.udg_SpellStealEvent = 0.0
        globals.udg_SpellStealEvent = 1.0
        globals.udg_SpellStealEvent = 0.0
    end
    ,BuffArrayA = {Count = 0}
    ,Counter = __jarray(0)
}
function SpellStealEventInit()
    -- create a spellcast event for spellsteals to add a counter to spellsteal targets. The counter filters out dmg events not relevant to spellsteal
    SpellStealEvent.TriggerCast = CreateTrigger()
    TriggerRegisterAnyUnitEventBJ(SpellStealEvent.TriggerCast, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    TriggerAddAction(SpellStealEvent.TriggerCast, function()
        if GetUnitCurrentOrder(GetTriggerUnit()) == OrderId("spellsteal") then
            SpellStealEvent.Counter[GetSpellTargetUnit()] = SpellStealEvent.Counter[GetSpellTargetUnit()] + 1
        end
    end)

    SpellStealEvent.Trigger = CreateTrigger()
    TriggerRegisterAnyUnitEventBJ(SpellStealEvent.Trigger, EVENT_PLAYER_UNIT_DAMAGING)
    TriggerAddAction(SpellStealEvent.Trigger, function()
        if GetEventDamage() == 0 then
           -- local oldTime = os.clock()
            if BlzGetEventAttackType() == ATTACK_TYPE_NORMAL and SpellStealEvent.Counter[GetEventDamageSource()] > 0 then
                -- SpellSteal first throws an DAMAGE_TYPE_UNKNOWN event, then an DAMAGE_TYPE_NORMAL Event. There is 0 game-time between the events
                if BlzGetEventDamageType() == DAMAGE_TYPE_UNKNOWN then
                    SpellStealEvent.BuffCountA = UnitCountBuffsExBJ(bj_BUFF_POLARITY_EITHER, bj_BUFF_RESIST_EITHER, GetTriggerUnit(), true, true)
                    SpellStealEvent.BuffCountB = UnitCountBuffsExBJ(bj_BUFF_POLARITY_EITHER, bj_BUFF_RESIST_EITHER, GetEventDamageSource(), true, true)
--                    print("SpellSteal", GetUnitName(GetEventDamageSource()), " -> ", GetUnitName(GetTriggerUnit()))

                    -- save all buffs the unit has
                    SpellStealEvent.BuffArrayA.Count = 0
                    
                    local i = 0
                    local abi
                    local buffId
                    while true do
                        abi = BlzGetUnitAbilityByIndex(GetEventDamageSource(), i)
                        buffId = BlzGetAbilityId(abi)
                        if buffId <= 0 then break end
                        SpellStealEvent.BuffArrayA.Count = SpellStealEvent.BuffArrayA.Count + 1
                        SpellStealEvent.BuffArrayA[SpellStealEvent.BuffArrayA.Count] = buffId
                        i = i + 1
                    end
                    abi = nil
                    
                elseif BlzGetEventDamageType() == DAMAGE_TYPE_NORMAL and SpellStealEvent.BuffCountA and SpellStealEvent.BuffCountB then
                    SpellStealEvent.BuffCountA = UnitCountBuffsExBJ(bj_BUFF_POLARITY_EITHER, bj_BUFF_RESIST_EITHER, GetTriggerUnit(), true, true) - SpellStealEvent.BuffCountA
                    SpellStealEvent.BuffCountB = UnitCountBuffsExBJ(bj_BUFF_POLARITY_EITHER, bj_BUFF_RESIST_EITHER, GetEventDamageSource(), true, true) - SpellStealEvent.BuffCountB
                    
                    if SpellStealEvent.BuffCountA > 0 and SpellStealEvent.BuffCountB < 0 then
                        --print("SpellSteal", GetUnitName(GetEventDamageSource()), " -> ", GetUnitName(GetTriggerUnit()))

                        -- find buffs the unit does not have anymore from the saved list
                        for i= 1, SpellStealEvent.BuffArrayA.Count do
                            if not UnitHasBuffBJ(GetEventDamageSource(), SpellStealEvent.BuffArrayA[i]) then
                                SpellStealEvent.Action(GetTriggerUnit(), SpellStealEvent.BuffArrayA[i], GetEventDamageSource())
                                --print(string.pack('>I4', SpellStealEvent.BuffArrayA[i]))

                                -- spell steal only steals one buff, hence stop the loop
                                break
                            end
                        end
                    end
                    SpellStealEvent.BuffCountA = nil
                    SpellStealEvent.BuffCountB = nil
                    SpellStealEvent.Counter[GetEventDamageSource()] = SpellStealEvent.Counter[GetEventDamageSource()] - 1
                end
            end
            --print(os.clock() - oldTime)
        end

    
    end)

    if OnGlobalInit then
        OnGlobalInit(SpellStealEventInit)
    end
end

Lua:
--[[ SpellStealEvent V1.1 by Tasyen

SpellStealEvent provides an event when a buff is transfered using the spellsteal ability. It tells the buff gainer/loser and the buff.
This System works by checking for dmg events which trigger when a spell steal appears. Inside that events it iterates over all default Buffs and custom Buffs from 'B000' to 'B0ZZ' cosidering only World Editor suggested Ids.
It contains more options upto B2ZZ (disabled), but I doubt anyone has such amount of Buffs.
udg_SpellStealEventBuff
udg_SpellStealEventGainer
udg_SpellStealEventLoser
udg_SpellStealEvent = 1.0


call SpellStealEventInit() to start the system (it creates a trigger)

--]]
SpellStealEvent = {
    BuffArrayA = {Count = 0}
    ,Counter = __jarray(0)
}
function SpellStealEventInit()
       BuffIdStrings = {'BPSE','BSTN','Bchd','Bdef','Bdet','Bfre','Bfro','Bvul','Bpoi','Bpsd','Bpsi','Bsha','Bspe','Btrv','Bclf','Bcmg','Bhea','Binf','Binv','Bmlc','Bmlt','Bmil','Bpxf','Bphx','Bply','Bslo','BHab','BHad','BHav','BHbn','BHbd','BHbz','BHds','Bdcb','Bdcl','Bdcm','Bdtb','Bdtl','Bdtm','BHfs','BHtc','BHwe','Bakb','Boar','Barm','Bbof','Bbsk','Bblo','Bdvv','Bdig','Bens','Bena','Beng','Beye','Bhwd','Blsh','Blsa','Bliq','Bprg','Bspl','Bstt','BOac','BOae','BOeq','BOea','BOhx','BOmi','BOsh','BOsf','BOvd','BOvc','BOwd','BOww','BOwk','Bbar','Bcor','Bcyc','Bcy2','Beat','Bfae','Bgra','Bmfl','Bmfa','Bpsh','Bps1','Brej','Broa','Bspo','Bssd','Bssi','Bvng','BEah','BEar','BEer','BEfn','BEim','BEia','BEme','BEst','BEsh','BEsv','Bams','Bam2','Babr','Bapl','Bcri','Bcrs','Bfrz','Bplg','Bpoc','Bpos','Brai','Brpb','Brpl','Brpm','Bspa','Buhf','Buns','Bweb','Bwea','BUan','BUau','BUav','BUcb','BUcs','BUdd','BUfa','BUim','BUsl','BUsp','BUst','BUts','BUtt','Basl','BCbf','BCtc','Bfzy','Bmec','BNmr','Bpig','BNpi','BNsa','Bshs','BNss','Btdg','Btsp','Btsa','BNba','BNbf','BHca','Bcsd','Bcsi','BNdm','BNdo','BNdi','BNdh','BNef','BNht','BNms','BNsi','BNst','BNsg','BNsq','BNsw','BNto','BNwm','BNbr','BNdc','BNin','BNpa','BNpm','BNrd','BNrf','BNsl','BIcb','BFig','BIcf','BIil','BIrb','BIrg','BIrl','BIrm','BIsv','BIsh','BIwb','BImo','BIpv','Xclf','Xfla','XHbz','XHfs','Xbof','XOeq','XOre','Xesn','XEsf','XEtq','XUdd','XNmo','XErc','XErf','XIct','AEsd','AEtr','ANmd','Bivs','BUad','Bult','BNab','BNcr','BNhs','XNhs','BNtm','BNeg','BNcs','XNcs','BNfy','BNcg','BNic','BNso','BNlm','BNvc','BNva','XNvc','Xbdt','Xbli','Xdis','Xfhs','Xfhm','Xfhl','Xfos','Xfom','Xfol','Xfns','Xfnm','Xfnl','Xfus','Xfum','Xful','BIhm'
    ,'B000','B001','B002','B003','B004','B005','B006','B007','B008','B009','B00A','B00B','B00C','B00D','B00E','B00F','B00G','B00H','B00I','B00J','B00K','B00L','B00M','B00N','B00O','B00P','B00Q','B00R','B00S','B00T','B00U','B00V','B00W','B00X','B00Y','B00Z','B010','B011','B012','B013','B014','B015','B016','B017','B018','B019','B01A','B01B','B01C','B01D','B01E','B01F','B01G','B01H','B01I','B01J','B01K','B01L','B01M','B01N','B01O','B01P','B01Q','B01R','B01S','B01T','B01U','B01V','B01W','B01X','B01Y','B01Z','B020','B021','B022','B023','B024','B025','B026','B027','B028','B029','B02A','B02B','B02C','B02D','B02E','B02F','B02G','B02H','B02I','B02J','B02K','B02L','B02M','B02N','B02O','B02P','B02Q','B02R','B02S','B02T','B02U','B02V','B02W','B02X','B02Y','B02Z','B030','B031','B032','B033','B034','B035','B036','B037','B038','B039','B03A','B03B','B03C','B03D','B03E','B03F','B03G','B03H','B03I','B03J','B03K','B03L','B03M','B03N','B03O','B03P','B03Q','B03R','B03S','B03T','B03U','B03V','B03W','B03X','B03Y','B03Z','B040','B041','B042','B043','B044','B045','B046','B047','B048','B049','B04A','B04B','B04C','B04D','B04E','B04F','B04G','B04H','B04I','B04J','B04K','B04L','B04M','B04N','B04O','B04P','B04Q','B04R','B04S','B04T','B04U','B04V','B04W','B04X','B04Y','B04Z','B050','B051','B052','B053','B054','B055','B056','B057','B058','B059','B05A','B05B','B05C','B05D','B05E','B05F','B05G','B05H','B05I','B05J','B05K','B05L','B05M','B05N','B05O','B05P','B05Q','B05R','B05S','B05T','B05U','B05V','B05W','B05X','B05Y','B05Z','B060','B061','B062','B063','B064','B065','B066','B067','B068','B069','B06A','B06B','B06C','B06D','B06E','B06F','B06G','B06H','B06I','B06J','B06K','B06L','B06M','B06N','B06O','B06P','B06Q','B06R','B06S','B06T','B06U','B06V','B06W','B06X','B06Y','B06Z','B070','B071','B072','B073','B074','B075','B076','B077','B078','B079','B07A','B07B','B07C','B07D','B07E','B07F','B07G','B07H','B07I','B07J','B07K','B07L','B07M','B07N','B07O','B07P','B07Q','B07R','B07S','B07T','B07U','B07V','B07W','B07X','B07Y','B07Z','B080','B081','B082','B083','B084','B085','B086','B087','B088','B089','B08A','B08B','B08C','B08D','B08E','B08F','B08G','B08H','B08I','B08J','B08K','B08L','B08M','B08N','B08O','B08P','B08Q','B08R','B08S','B08T','B08U','B08V','B08W','B08X','B08Y','B08Z','B090','B091','B092','B093','B094','B095','B096','B097','B098','B099','B09A','B09B','B09C','B09D','B09E','B09F','B09G','B09H','B09I','B09J','B09K','B09L','B09M','B09N','B09O','B09P','B09Q','B09R','B09S','B09T','B09U','B09V','B09W','B09X','B09Y','B09Z'
    ,'B0A0','B0A0','B0A1','B0A2','B0A3','B0A4','B0A5','B0A6','B0A7','B0A8','B0A9','B0AA','B0AB','B0AC','B0AD','B0AE','B0AF','B0AG','B0AH','B0AI','B0AJ','B0AK','B0AL','B0AM','B0AN','B0AO','B0AP','B0AQ','B0AR','B0AS','B0AT','B0AU','B0AV','B0AW','B0AX','B0AY','B0AZ','B0B0','B0B0','B0B1','B0B2','B0B3','B0B4','B0B5','B0B6','B0B7','B0B8','B0B9','B0BA','B0BB','B0BC','B0BD','B0BE','B0BF','B0BG','B0BH','B0BI','B0BJ','B0BK','B0BL','B0BM','B0BN','B0BO','B0BP','B0BQ','B0BR','B0BS','B0BT','B0BU','B0BV','B0BW','B0BX','B0BY','B0BZ','B0C0','B0C0','B0C1','B0C2','B0C3','B0C4','B0C5','B0C6','B0C7','B0C8','B0C9','B0CA','B0CB','B0CC','B0CD','B0CE','B0CF','B0CG','B0CH','B0CI','B0CJ','B0CK','B0CL','B0CM','B0CN','B0CO','B0CP','B0CQ','B0CR','B0CS','B0CT','B0CU','B0CV','B0CW','B0CX','B0CY','B0CZ','B0D0','B0D0','B0D1','B0D2','B0D3','B0D4','B0D5','B0D6','B0D7','B0D8','B0D9','B0DA','B0DB','B0DC','B0DD','B0DE','B0DF','B0DG','B0DH','B0DI','B0DJ','B0DK','B0DL','B0DM','B0DN','B0DO','B0DP','B0DQ','B0DR','B0DS','B0DT','B0DU','B0DV','B0DW','B0DX','B0DY','B0DZ','B0E0','B0E0','B0E1','B0E2','B0E3','B0E4','B0E5','B0E6','B0E7','B0E8','B0E9','B0EA','B0EB','B0EC','B0ED','B0EE','B0EF','B0EG','B0EH','B0EI','B0EJ','B0EK','B0EL','B0EM','B0EN','B0EO','B0EP','B0EQ','B0ER','B0ES','B0ET','B0EU','B0EV','B0EW','B0EX','B0EY','B0EZ','B0F0','B0F0','B0F1','B0F2','B0F3','B0F4','B0F5','B0F6','B0F7','B0F8','B0F9','B0FA','B0FB','B0FC','B0FD','B0FE','B0FF','B0FG','B0FH','B0FI','B0FJ','B0FK','B0FL','B0FM','B0FN','B0FO','B0FP','B0FQ','B0FR','B0FS','B0FT','B0FU','B0FV','B0FW','B0FX','B0FY','B0FZ','B0G0','B0G0','B0G1','B0G2','B0G3','B0G4','B0G5','B0G6','B0G7','B0G8','B0G9','B0GA','B0GB','B0GC','B0GD','B0GE','B0GF','B0GG','B0GH','B0GI','B0GJ','B0GK','B0GL','B0GM','B0GN','B0GO','B0GP','B0GQ','B0GR','B0GS','B0GT','B0GU','B0GV','B0GW','B0GX','B0GY','B0GZ','B0H0','B0H0','B0H1','B0H2','B0H3','B0H4','B0H5','B0H6','B0H7','B0H8','B0H9','B0HA','B0HB','B0HC','B0HD','B0HE','B0HF','B0HG','B0HH','B0HI','B0HJ','B0HK','B0HL','B0HM','B0HN','B0HO','B0HP','B0HQ','B0HR','B0HS','B0HT','B0HU','B0HV','B0HW','B0HX','B0HY','B0HZ','B0I0','B0I0','B0I1','B0I2','B0I3','B0I4','B0I5','B0I6','B0I7','B0I8','B0I9','B0IA','B0IB','B0IC','B0ID','B0IE','B0IF','B0IG','B0IH','B0II','B0IJ','B0IK','B0IL','B0IM','B0IN','B0IO','B0IP','B0IQ','B0IR','B0IS','B0IT','B0IU','B0IV','B0IW','B0IX','B0IY','B0IZ','B0J0','B0J0','B0J1','B0J2','B0J3','B0J4','B0J5','B0J6','B0J7','B0J8','B0J9','B0JA','B0JB','B0JC','B0JD','B0JE','B0JF','B0JG','B0JH','B0JI','B0JJ','B0JK','B0JL','B0JM','B0JN','B0JO','B0JP'
    ,'B0JQ','B0JR','B0JS','B0JT','B0JU','B0JV','B0JW','B0JX','B0JY','B0JZ','B0K0','B0K0','B0K1','B0K2','B0K3','B0K4','B0K5','B0K6','B0K7','B0K8','B0K9','B0KA','B0KB','B0KC','B0KD','B0KE','B0KF','B0KG','B0KH','B0KI','B0KJ','B0KK','B0KL','B0KM','B0KN','B0KO','B0KP','B0KQ','B0KR','B0KS','B0KT','B0KU','B0KV','B0KW','B0KX','B0KY','B0KZ','B0L0','B0L0','B0L1','B0L2','B0L3','B0L4','B0L5','B0L6','B0L7','B0L8','B0L9','B0LA','B0LB','B0LC','B0LD','B0LE','B0LF','B0LG','B0LH','B0LI','B0LJ','B0LK','B0LL','B0LM','B0LN','B0LO','B0LP','B0LQ','B0LR','B0LS','B0LT','B0LU','B0LV','B0LW','B0LX','B0LY','B0LZ','B0M0','B0M0','B0M1','B0M2','B0M3','B0M4','B0M5','B0M6','B0M7','B0M8','B0M9','B0MA','B0MB','B0MC','B0MD','B0ME','B0MF','B0MG','B0MH','B0MI','B0MJ','B0MK','B0ML','B0MM','B0MN','B0MO','B0MP','B0MQ','B0MR','B0MS','B0MT','B0MU','B0MV','B0MW','B0MX','B0MY','B0MZ','B0N0','B0N0','B0N1','B0N2','B0N3','B0N4','B0N5','B0N6','B0N7','B0N8','B0N9','B0NA','B0NB','B0NC','B0ND','B0NE','B0NF','B0NG','B0NH','B0NI','B0NJ','B0NK','B0NL','B0NM','B0NN','B0NO','B0NP','B0NQ','B0NR','B0NS','B0NT','B0NU','B0NV','B0NW','B0NX','B0NY','B0NZ','B0O0','B0O0','B0O1','B0O2','B0O3','B0O4','B0O5','B0O6','B0O7','B0O8','B0O9','B0OA','B0OB','B0OC','B0OD','B0OE','B0OF','B0OG','B0OH','B0OI','B0OJ','B0OK','B0OL','B0OM','B0ON','B0OO','B0OP','B0OQ','B0OR','B0OS','B0OT','B0OU','B0OV','B0OW','B0OX','B0OY','B0OZ','B0P0','B0P0','B0P1','B0P2','B0P3','B0P4','B0P5','B0P6','B0P7','B0P8','B0P9','B0PA','B0PB','B0PC','B0PD','B0PE','B0PF','B0PG','B0PH','B0PI','B0PJ','B0PK','B0PL','B0PM','B0PN','B0PO','B0PP','B0PQ','B0PR','B0PS','B0PT','B0PU','B0PV','B0PW','B0PX','B0PY','B0PZ','B0Q0','B0Q0','B0Q1','B0Q2','B0Q3','B0Q4','B0Q5','B0Q6','B0Q7','B0Q8','B0Q9','B0QA','B0QB','B0QC','B0QD','B0QE','B0QF','B0QG','B0QH','B0QI','B0QJ','B0QK','B0QL','B0QM','B0QN','B0QO','B0QP','B0QQ','B0QR','B0QS','B0QT','B0QU','B0QV','B0QW','B0QX','B0QY','B0QZ','B0R0','B0R0','B0R1','B0R2','B0R3','B0R4','B0R5','B0R6','B0R7','B0R8','B0R9','B0RA','B0RB','B0RC','B0RD','B0RE','B0RF','B0RG','B0RH','B0RI','B0RJ','B0RK','B0RL','B0RM','B0RN','B0RO','B0RP','B0RQ','B0RR','B0RS','B0RT','B0RU','B0RV','B0RW','B0RX','B0RY','B0RZ','B0S0','B0S0','B0S1','B0S2','B0S3','B0S4','B0S5','B0S6','B0S7','B0S8','B0S9','B0SA','B0SB','B0SC','B0SD','B0SE','B0SF','B0SG','B0SH','B0SI','B0SJ','B0SK','B0SL','B0SM','B0SN','B0SO','B0SP','B0SQ','B0SR','B0SS','B0ST','B0SU','B0SV','B0SW','B0SX','B0SY','B0SZ','B0T0','B0T0','B0T1','B0T2','B0T3','B0T4','B0T5','B0T6','B0T7','B0T8','B0T9','B0TA','B0TB','B0TC','B0TD','B0TE','B0TF'
    ,'B0TG','B0TH','B0TI','B0TJ','B0TK','B0TL','B0TM','B0TN','B0TO','B0TP','B0TQ','B0TR','B0TS','B0TT','B0TU','B0TV','B0TW','B0TX','B0TY','B0TZ','B0U0','B0U0','B0U1','B0U2','B0U3','B0U4','B0U5','B0U6','B0U7','B0U8','B0U9','B0UA','B0UB','B0UC','B0UD','B0UE','B0UF','B0UG','B0UH','B0UI','B0UJ','B0UK','B0UL','B0UM','B0UN','B0UO','B0UP','B0UQ','B0UR','B0US','B0UT','B0UU','B0UV','B0UW','B0UX','B0UY','B0UZ','B0V0','B0V0','B0V1','B0V2','B0V3','B0V4','B0V5','B0V6','B0V7','B0V8','B0V9','B0VA','B0VB','B0VC','B0VD','B0VE','B0VF','B0VG','B0VH','B0VI','B0VJ','B0VK','B0VL','B0VM','B0VN','B0VO','B0VP','B0VQ','B0VR','B0VS','B0VT','B0VU','B0VV','B0VW','B0VX','B0VY','B0VZ','B0W0','B0W0','B0W1','B0W2','B0W3','B0W4','B0W5','B0W6','B0W7','B0W8','B0W9','B0WA','B0WB','B0WC','B0WD','B0WE','B0WF','B0WG','B0WH','B0WI','B0WJ','B0WK','B0WL','B0WM','B0WN','B0WO','B0WP','B0WQ','B0WR','B0WS','B0WT','B0WU','B0WV','B0WW','B0WX','B0WY','B0WZ','B0X0','B0X0','B0X1','B0X2','B0X3','B0X4','B0X5','B0X6','B0X7','B0X8','B0X9','B0XA','B0XB','B0XC','B0XD','B0XE','B0XF','B0XG','B0XH','B0XI','B0XJ','B0XK','B0XL','B0XM','B0XN','B0XO','B0XP','B0XQ','B0XR','B0XS','B0XT','B0XU','B0XV','B0XW','B0XX','B0XY','B0XZ','B0Y0','B0Y0','B0Y1','B0Y2','B0Y3','B0Y4','B0Y5','B0Y6','B0Y7','B0Y8','B0Y9','B0YA','B0YB','B0YC','B0YD','B0YE','B0YF','B0YG','B0YH','B0YI','B0YJ','B0YK','B0YL','B0YM','B0YN','B0YO','B0YP','B0YQ','B0YR','B0YS','B0YT','B0YU','B0YV','B0YW','B0YX','B0YY','B0YZ','B0Z0','B0Z0','B0Z1','B0Z2','B0Z3','B0Z4','B0Z5','B0Z6','B0Z7','B0Z8','B0Z9','B0ZA','B0ZB','B0ZC','B0ZD','B0ZE','B0ZF','B0ZG','B0ZH','B0ZI','B0ZJ','B0ZK','B0ZL','B0ZM','B0ZN','B0ZO','B0ZP','B0ZQ','B0ZR','B0ZS','B0ZT','B0ZU','B0ZV','B0ZW','B0ZX','B0ZY','B0ZZ'
    -- already 1332 custom buffs
    --,'B100','B101','B102','B103','B104','B105','B106','B107','B108','B109','B10A','B10B','B10C','B10D','B10E','B10F','B10G','B10H','B10I','B10J','B10K','B10L','B10M','B10N','B10O','B10P','B10Q','B10R','B10S','B10T','B10U','B10V','B10W','B10X','B10Y','B10Z','B110','B111','B112','B113','B114','B115','B116','B117','B118','B119','B11A','B11B','B11C','B11D','B11E','B11F','B11G','B11H','B11I','B11J','B11K','B11L','B11M','B11N','B11O','B11P','B11Q','B11R','B11S','B11T','B11U','B11V','B11W','B11X','B11Y','B11Z','B120','B121','B122','B123','B124','B125','B126','B127','B128','B129','B12A','B12B','B12C','B12D','B12E','B12F','B12G','B12H','B12I','B12J','B12K','B12L','B12M','B12N','B12O','B12P','B12Q','B12R','B12S','B12T','B12U','B12V','B12W','B12X','B12Y','B12Z','B130','B131','B132','B133','B134','B135','B136','B137','B138','B139','B13A','B13B','B13C','B13D','B13E','B13F','B13G','B13H','B13I','B13J','B13K','B13L','B13M','B13N','B13O','B13P','B13Q','B13R','B13S','B13T','B13U','B13V','B13W','B13X','B13Y','B13Z','B140','B141','B142','B143','B144','B145','B146','B147','B148','B149','B14A','B14B','B14C','B14D','B14E','B14F','B14G','B14H','B14I','B14J','B14K','B14L','B14M','B14N','B14O','B14P','B14Q','B14R','B14S','B14T','B14U','B14V','B14W','B14X','B14Y','B14Z','B150','B151','B152','B153','B154','B155','B156','B157','B158','B159','B15A','B15B','B15C','B15D','B15E','B15F','B15G','B15H','B15I','B15J','B15K','B15L','B15M','B15N','B15O','B15P','B15Q','B15R','B15S','B15T','B15U','B15V','B15W','B15X','B15Y','B15Z','B160','B161','B162','B163','B164','B165','B166','B167','B168','B169','B16A','B16B','B16C','B16D','B16E','B16F','B16G','B16H','B16I','B16J','B16K','B16L','B16M','B16N','B16O','B16P','B16Q','B16R','B16S','B16T','B16U','B16V','B16W','B16X','B16Y','B16Z','B170','B171','B172','B173','B174','B175','B176','B177','B178','B179','B17A','B17B','B17C','B17D','B17E','B17F','B17G','B17H','B17I','B17J','B17K','B17L','B17M','B17N','B17O','B17P','B17Q','B17R','B17S','B17T','B17U','B17V','B17W','B17X','B17Y','B17Z','B180','B181','B182','B183','B184','B185','B186','B187','B188','B189','B18A','B18B','B18C','B18D','B18E','B18F','B18G','B18H','B18I','B18J','B18K','B18L','B18M','B18N','B18O','B18P','B18Q','B18R','B18S','B18T','B18U','B18V','B18W','B18X','B18Y','B18Z','B190','B191','B192','B193','B194','B195','B196','B197','B198','B199','B19A','B19B','B19C','B19D','B19E','B19F','B19G','B19H','B19I','B19J','B19K','B19L','B19M','B19N','B19O','B19P','B19Q','B19R','B19S','B19T','B19U','B19V','B19W','B19X','B19Y','B19Z'
    --,'B1A0','B1A0','B1A1','B1A2','B1A3','B1A4','B1A5','B1A6','B1A7','B1A8','B1A9','B1AA','B1AB','B1AC','B1AD','B1AE','B1AF','B1AG','B1AH','B1AI','B1AJ','B1AK','B1AL','B1AM','B1AN','B1AO','B1AP','B1AQ','B1AR','B1AS','B1AT','B1AU','B1AV','B1AW','B1AX','B1AY','B1AZ','B1B0','B1B0','B1B1','B1B2','B1B3','B1B4','B1B5','B1B6','B1B7','B1B8','B1B9','B1BA','B1BB','B1BC','B1BD','B1BE','B1BF','B1BG','B1BH','B1BI','B1BJ','B1BK','B1BL','B1BM','B1BN','B1BO','B1BP','B1BQ','B1BR','B1BS','B1BT','B1BU','B1BV','B1BW','B1BX','B1BY','B1BZ','B1C0','B1C0','B1C1','B1C2','B1C3','B1C4','B1C5','B1C6','B1C7','B1C8','B1C9','B1CA','B1CB','B1CC','B1CD','B1CE','B1CF','B1CG','B1CH','B1CI','B1CJ','B1CK','B1CL','B1CM','B1CN','B1CO','B1CP','B1CQ','B1CR','B1CS','B1CT','B1CU','B1CV','B1CW','B1CX','B1CY','B1CZ','B1D0','B1D0','B1D1','B1D2','B1D3','B1D4','B1D5','B1D6','B1D7','B1D8','B1D9','B1DA','B1DB','B1DC','B1DD','B1DE','B1DF','B1DG','B1DH','B1DI','B1DJ','B1DK','B1DL','B1DM','B1DN','B1DO','B1DP','B1DQ','B1DR','B1DS','B1DT','B1DU','B1DV','B1DW','B1DX','B1DY','B1DZ','B1E0','B1E0','B1E1','B1E2','B1E3','B1E4','B1E5','B1E6','B1E7','B1E8','B1E9','B1EA','B1EB','B1EC','B1ED','B1EE','B1EF','B1EG','B1EH','B1EI','B1EJ','B1EK','B1EL','B1EM','B1EN','B1EO','B1EP','B1EQ','B1ER','B1ES','B1ET','B1EU','B1EV','B1EW','B1EX','B1EY','B1EZ','B1F0','B1F0','B1F1','B1F2','B1F3','B1F4','B1F5','B1F6','B1F7','B1F8','B1F9','B1FA','B1FB','B1FC','B1FD','B1FE','B1FF','B1FG','B1FH','B1FI','B1FJ','B1FK','B1FL','B1FM','B1FN','B1FO','B1FP','B1FQ','B1FR','B1FS','B1FT','B1FU','B1FV','B1FW','B1FX','B1FY','B1FZ','B1G0','B1G0','B1G1','B1G2','B1G3','B1G4','B1G5','B1G6','B1G7','B1G8','B1G9','B1GA','B1GB','B1GC','B1GD','B1GE','B1GF','B1GG','B1GH','B1GI','B1GJ','B1GK','B1GL','B1GM','B1GN','B1GO','B1GP','B1GQ','B1GR','B1GS','B1GT','B1GU','B1GV','B1GW','B1GX','B1GY','B1GZ','B1H0','B1H0','B1H1','B1H2','B1H3','B1H4','B1H5','B1H6','B1H7','B1H8','B1H9','B1HA','B1HB','B1HC','B1HD','B1HE','B1HF','B1HG','B1HH','B1HI','B1HJ','B1HK','B1HL','B1HM','B1HN','B1HO','B1HP','B1HQ','B1HR','B1HS','B1HT','B1HU','B1HV','B1HW','B1HX','B1HY','B1HZ','B1I0','B1I0','B1I1','B1I2','B1I3','B1I4','B1I5','B1I6','B1I7','B1I8','B1I9','B1IA','B1IB','B1IC','B1ID','B1IE','B1IF','B1IG','B1IH','B1II','B1IJ','B1IK','B1IL','B1IM','B1IN','B1IO','B1IP','B1IQ','B1IR','B1IS','B1IT','B1IU','B1IV','B1IW','B1IX','B1IY','B1IZ','B1J0','B1J0','B1J1','B1J2','B1J3','B1J4','B1J5','B1J6','B1J7','B1J8','B1J9','B1JA','B1JB','B1JC','B1JD','B1JE','B1JF','B1JG','B1JH','B1JI','B1JJ','B1JK','B1JL','B1JM','B1JN','B1JO','B1JP'
    --,'B1JQ','B1JR','B1JS','B1JT','B1JU','B1JV','B1JW','B1JX','B1JY','B1JZ','B1K0','B1K0','B1K1','B1K2','B1K3','B1K4','B1K5','B1K6','B1K7','B1K8','B1K9','B1KA','B1KB','B1KC','B1KD','B1KE','B1KF','B1KG','B1KH','B1KI','B1KJ','B1KK','B1KL','B1KM','B1KN','B1KO','B1KP','B1KQ','B1KR','B1KS','B1KT','B1KU','B1KV','B1KW','B1KX','B1KY','B1KZ','B1L0','B1L0','B1L1','B1L2','B1L3','B1L4','B1L5','B1L6','B1L7','B1L8','B1L9','B1LA','B1LB','B1LC','B1LD','B1LE','B1LF','B1LG','B1LH','B1LI','B1LJ','B1LK','B1LL','B1LM','B1LN','B1LO','B1LP','B1LQ','B1LR','B1LS','B1LT','B1LU','B1LV','B1LW','B1LX','B1LY','B1LZ','B1M0','B1M0','B1M1','B1M2','B1M3','B1M4','B1M5','B1M6','B1M7','B1M8','B1M9','B1MA','B1MB','B1MC','B1MD','B1ME','B1MF','B1MG','B1MH','B1MI','B1MJ','B1MK','B1ML','B1MM','B1MN','B1MO','B1MP','B1MQ','B1MR','B1MS','B1MT','B1MU','B1MV','B1MW','B1MX','B1MY','B1MZ','B1N0','B1N0','B1N1','B1N2','B1N3','B1N4','B1N5','B1N6','B1N7','B1N8','B1N9','B1NA','B1NB','B1NC','B1ND','B1NE','B1NF','B1NG','B1NH','B1NI','B1NJ','B1NK','B1NL','B1NM','B1NN','B1NO','B1NP','B1NQ','B1NR','B1NS','B1NT','B1NU','B1NV','B1NW','B1NX','B1NY','B1NZ','B1O0','B1O0','B1O1','B1O2','B1O3','B1O4','B1O5','B1O6','B1O7','B1O8','B1O9','B1OA','B1OB','B1OC','B1OD','B1OE','B1OF','B1OG','B1OH','B1OI','B1OJ','B1OK','B1OL','B1OM','B1ON','B1OO','B1OP','B1OQ','B1OR','B1OS','B1OT','B1OU','B1OV','B1OW','B1OX','B1OY','B1OZ','B1P0','B1P0','B1P1','B1P2','B1P3','B1P4','B1P5','B1P6','B1P7','B1P8','B1P9','B1PA','B1PB','B1PC','B1PD','B1PE','B1PF','B1PG','B1PH','B1PI','B1PJ','B1PK','B1PL','B1PM','B1PN','B1PO','B1PP','B1PQ','B1PR','B1PS','B1PT','B1PU','B1PV','B1PW','B1PX','B1PY','B1PZ','B1Q0','B1Q0','B1Q1','B1Q2','B1Q3','B1Q4','B1Q5','B1Q6','B1Q7','B1Q8','B1Q9','B1QA','B1QB','B1QC','B1QD','B1QE','B1QF','B1QG','B1QH','B1QI','B1QJ','B1QK','B1QL','B1QM','B1QN','B1QO','B1QP','B1QQ','B1QR','B1QS','B1QT','B1QU','B1QV','B1QW','B1QX','B1QY','B1QZ','B1R0','B1R0','B1R1','B1R2','B1R3','B1R4','B1R5','B1R6','B1R7','B1R8','B1R9','B1RA','B1RB','B1RC','B1RD','B1RE','B1RF','B1RG','B1RH','B1RI','B1RJ','B1RK','B1RL','B1RM','B1RN','B1RO','B1RP','B1RQ','B1RR','B1RS','B1RT','B1RU','B1RV','B1RW','B1RX','B1RY','B1RZ','B1S0','B1S0','B1S1','B1S2','B1S3','B1S4','B1S5','B1S6','B1S7','B1S8','B1S9','B1SA','B1SB','B1SC','B1SD','B1SE','B1SF','B1SG','B1SH','B1SI','B1SJ','B1SK','B1SL','B1SM','B1SN','B1SO','B1SP','B1SQ','B1SR','B1SS','B1ST','B1SU','B1SV','B1SW','B1SX','B1SY','B1SZ','B1T0','B1T0','B1T1','B1T2','B1T3','B1T4','B1T5','B1T6','B1T7','B1T8','B1T9','B1TA','B1TB','B1TC','B1TD','B1TE','B1TF'
    --,'B1TG','B1TH','B1TI','B1TJ','B1TK','B1TL','B1TM','B1TN','B1TO','B1TP','B1TQ','B1TR','B1TS','B1TT','B1TU','B1TV','B1TW','B1TX','B1TY','B1TZ','B1U0','B1U0','B1U1','B1U2','B1U3','B1U4','B1U5','B1U6','B1U7','B1U8','B1U9','B1UA','B1UB','B1UC','B1UD','B1UE','B1UF','B1UG','B1UH','B1UI','B1UJ','B1UK','B1UL','B1UM','B1UN','B1UO','B1UP','B1UQ','B1UR','B1US','B1UT','B1UU','B1UV','B1UW','B1UX','B1UY','B1UZ','B1V0','B1V0','B1V1','B1V2','B1V3','B1V4','B1V5','B1V6','B1V7','B1V8','B1V9','B1VA','B1VB','B1VC','B1VD','B1VE','B1VF','B1VG','B1VH','B1VI','B1VJ','B1VK','B1VL','B1VM','B1VN','B1VO','B1VP','B1VQ','B1VR','B1VS','B1VT','B1VU','B1VV','B1VW','B1VX','B1VY','B1VZ','B1W0','B1W0','B1W1','B1W2','B1W3','B1W4','B1W5','B1W6','B1W7','B1W8','B1W9','B1WA','B1WB','B1WC','B1WD','B1WE','B1WF','B1WG','B1WH','B1WI','B1WJ','B1WK','B1WL','B1WM','B1WN','B1WO','B1WP','B1WQ','B1WR','B1WS','B1WT','B1WU','B1WV','B1WW','B1WX','B1WY','B1WZ','B1X0','B1X0','B1X1','B1X2','B1X3','B1X4','B1X5','B1X6','B1X7','B1X8','B1X9','B1XA','B1XB','B1XC','B1XD','B1XE','B1XF','B1XG','B1XH','B1XI','B1XJ','B1XK','B1XL','B1XM','B1XN','B1XO','B1XP','B1XQ','B1XR','B1XS','B1XT','B1XU','B1XV','B1XW','B1XX','B1XY','B1XZ','B1Y0','B1Y0','B1Y1','B1Y2','B1Y3','B1Y4','B1Y5','B1Y6','B1Y7','B1Y8','B1Y9','B1YA','B1YB','B1YC','B1YD','B1YE','B1YF','B1YG','B1YH','B1YI','B1YJ','B1YK','B1YL','B1YM','B1YN','B1YO','B1YP','B1YQ','B1YR','B1YS','B1YT','B1YU','B1YV','B1YW','B1YX','B1YY','B1YZ','B1Z0','B1Z0','B1Z1','B1Z2','B1Z3','B1Z4','B1Z5','B1Z6','B1Z7','B1Z8','B1Z9','B1ZA','B1ZB','B1ZC','B1ZD','B1ZE','B1ZF','B1ZG','B1ZH','B1ZI','B1ZJ','B1ZK','B1ZL','B1ZM','B1ZN','B1ZO','B1ZP','B1ZQ','B1ZR','B1ZS','B1ZT','B1ZU','B1ZV','B1ZW','B1ZX','B1ZY','B1ZZ'
    --,'B200','B201','B202','B203','B204','B205','B206','B207','B208','B209','B20A','B20B','B20C','B20D','B20E','B20F','B20G','B20H','B20I','B20J','B20K','B20L','B20M','B20N','B20O','B20P','B20Q','B20R','B20S','B20T','B20U','B20V','B20W','B20X','B20Y','B20Z','B210','B211','B212','B213','B214','B215','B216','B217','B218','B219','B21A','B21B','B21C','B21D','B21E','B21F','B21G','B21H','B21I','B21J','B21K','B21L','B21M','B21N','B21O','B21P','B21Q','B21R','B21S','B21T','B21U','B21V','B21W','B21X','B21Y','B21Z','B220','B221','B222','B223','B224','B225','B226','B227','B228','B229','B22A','B22B','B22C','B22D','B22E','B22F','B22G','B22H','B22I','B22J','B22K','B22L','B22M','B22N','B22O','B22P','B22Q','B22R','B22S','B22T','B22U','B22V','B22W','B22X','B22Y','B22Z','B230','B231','B232','B233','B234','B235','B236','B237','B238','B239','B23A','B23B','B23C','B23D','B23E','B23F','B23G','B23H','B23I','B23J','B23K','B23L','B23M','B23N','B23O','B23P','B23Q','B23R','B23S','B23T','B23U','B23V','B23W','B23X','B23Y','B23Z','B240','B241','B242','B243','B244','B245','B246','B247','B248','B249','B24A','B24B','B24C','B24D','B24E','B24F','B24G','B24H','B24I','B24J','B24K','B24L','B24M','B24N','B24O','B24P','B24Q','B24R','B24S','B24T','B24U','B24V','B24W','B24X','B24Y','B24Z','B250','B251','B252','B253','B254','B255','B256','B257','B258','B259','B25A','B25B','B25C','B25D','B25E','B25F','B25G','B25H','B25I','B25J','B25K','B25L','B25M','B25N','B25O','B25P','B25Q','B25R','B25S','B25T','B25U','B25V','B25W','B25X','B25Y','B25Z','B260','B261','B262','B263','B264','B265','B266','B267','B268','B269','B26A','B26B','B26C','B26D','B26E','B26F','B26G','B26H','B26I','B26J','B26K','B26L','B26M','B26N','B26O','B26P','B26Q','B26R','B26S','B26T','B26U','B26V','B26W','B26X','B26Y','B26Z','B270','B271','B272','B273','B274','B275','B276','B277','B278','B279','B27A','B27B','B27C','B27D','B27E','B27F','B27G','B27H','B27I','B27J','B27K','B27L','B27M','B27N','B27O','B27P','B27Q','B27R','B27S','B27T','B27U','B27V','B27W','B27X','B27Y','B27Z','B280','B281','B282','B283','B284','B285','B286','B287','B288','B289','B28A','B28B','B28C','B28D','B28E','B28F','B28G','B28H','B28I','B28J','B28K','B28L','B28M','B28N','B28O','B28P','B28Q','B28R','B28S','B28T','B28U','B28V','B28W','B28X','B28Y','B28Z','B290','B291','B292','B293','B294','B295','B296','B297','B298','B299','B29A','B29B','B29C','B29D','B29E','B29F','B29G','B29H','B29I','B29J','B29K','B29L','B29M','B29N','B29O','B29P','B29Q','B29R','B29S','B29T','B29U','B29V','B29W','B29X','B29Y','B29Z'
    --,'B2A0','B2A0','B2A1','B2A2','B2A3','B2A4','B2A5','B2A6','B2A7','B2A8','B2A9','B2AA','B2AB','B2AC','B2AD','B2AE','B2AF','B2AG','B2AH','B2AI','B2AJ','B2AK','B2AL','B2AM','B2AN','B2AO','B2AP','B2AQ','B2AR','B2AS','B2AT','B2AU','B2AV','B2AW','B2AX','B2AY','B2AZ','B2B0','B2B0','B2B1','B2B2','B2B3','B2B4','B2B5','B2B6','B2B7','B2B8','B2B9','B2BA','B2BB','B2BC','B2BD','B2BE','B2BF','B2BG','B2BH','B2BI','B2BJ','B2BK','B2BL','B2BM','B2BN','B2BO','B2BP','B2BQ','B2BR','B2BS','B2BT','B2BU','B2BV','B2BW','B2BX','B2BY','B2BZ','B2C0','B2C0','B2C1','B2C2','B2C3','B2C4','B2C5','B2C6','B2C7','B2C8','B2C9','B2CA','B2CB','B2CC','B2CD','B2CE','B2CF','B2CG','B2CH','B2CI','B2CJ','B2CK','B2CL','B2CM','B2CN','B2CO','B2CP','B2CQ','B2CR','B2CS','B2CT','B2CU','B2CV','B2CW','B2CX','B2CY','B2CZ','B2D0','B2D0','B2D1','B2D2','B2D3','B2D4','B2D5','B2D6','B2D7','B2D8','B2D9','B2DA','B2DB','B2DC','B2DD','B2DE','B2DF','B2DG','B2DH','B2DI','B2DJ','B2DK','B2DL','B2DM','B2DN','B2DO','B2DP','B2DQ','B2DR','B2DS','B2DT','B2DU','B2DV','B2DW','B2DX','B2DY','B2DZ','B2E0','B2E0','B2E1','B2E2','B2E3','B2E4','B2E5','B2E6','B2E7','B2E8','B2E9','B2EA','B2EB','B2EC','B2ED','B2EE','B2EF','B2EG','B2EH','B2EI','B2EJ','B2EK','B2EL','B2EM','B2EN','B2EO','B2EP','B2EQ','B2ER','B2ES','B2ET','B2EU','B2EV','B2EW','B2EX','B2EY','B2EZ','B2F0','B2F0','B2F1','B2F2','B2F3','B2F4','B2F5','B2F6','B2F7','B2F8','B2F9','B2FA','B2FB','B2FC','B2FD','B2FE','B2FF','B2FG','B2FH','B2FI','B2FJ','B2FK','B2FL','B2FM','B2FN','B2FO','B2FP','B2FQ','B2FR','B2FS','B2FT','B2FU','B2FV','B2FW','B2FX','B2FY','B2FZ','B2G0','B2G0','B2G1','B2G2','B2G3','B2G4','B2G5','B2G6','B2G7','B2G8','B2G9','B2GA','B2GB','B2GC','B2GD','B2GE','B2GF','B2GG','B2GH','B2GI','B2GJ','B2GK','B2GL','B2GM','B2GN','B2GO','B2GP','B2GQ','B2GR','B2GS','B2GT','B2GU','B2GV','B2GW','B2GX','B2GY','B2GZ','B2H0','B2H0','B2H1','B2H2','B2H3','B2H4','B2H5','B2H6','B2H7','B2H8','B2H9','B2HA','B2HB','B2HC','B2HD','B2HE','B2HF','B2HG','B2HH','B2HI','B2HJ','B2HK','B2HL','B2HM','B2HN','B2HO','B2HP','B2HQ','B2HR','B2HS','B2HT','B2HU','B2HV','B2HW','B2HX','B2HY','B2HZ','B2I0','B2I0','B2I1','B2I2','B2I3','B2I4','B2I5','B2I6','B2I7','B2I8','B2I9','B2IA','B2IB','B2IC','B2ID','B2IE','B2IF','B2IG','B2IH','B2II','B2IJ','B2IK','B2IL','B2IM','B2IN','B2IO','B2IP','B2IQ','B2IR','B2IS','B2IT','B2IU','B2IV','B2IW','B2IX','B2IY','B2IZ','B2J0','B2J0','B2J1','B2J2','B2J3','B2J4','B2J5','B2J6','B2J7','B2J8','B2J9','B2JA','B2JB','B2JC','B2JD','B2JE','B2JF','B2JG','B2JH','B2JI','B2JJ','B2JK','B2JL','B2JM','B2JN','B2JO','B2JP'
    --,'B2JQ','B2JR','B2JS','B2JT','B2JU','B2JV','B2JW','B2JX','B2JY','B2JZ','B2K0','B2K0','B2K1','B2K2','B2K3','B2K4','B2K5','B2K6','B2K7','B2K8','B2K9','B2KA','B2KB','B2KC','B2KD','B2KE','B2KF','B2KG','B2KH','B2KI','B2KJ','B2KK','B2KL','B2KM','B2KN','B2KO','B2KP','B2KQ','B2KR','B2KS','B2KT','B2KU','B2KV','B2KW','B2KX','B2KY','B2KZ','B2L0','B2L0','B2L1','B2L2','B2L3','B2L4','B2L5','B2L6','B2L7','B2L8','B2L9','B2LA','B2LB','B2LC','B2LD','B2LE','B2LF','B2LG','B2LH','B2LI','B2LJ','B2LK','B2LL','B2LM','B2LN','B2LO','B2LP','B2LQ','B2LR','B2LS','B2LT','B2LU','B2LV','B2LW','B2LX','B2LY','B2LZ','B2M0','B2M0','B2M1','B2M2','B2M3','B2M4','B2M5','B2M6','B2M7','B2M8','B2M9','B2MA','B2MB','B2MC','B2MD','B2ME','B2MF','B2MG','B2MH','B2MI','B2MJ','B2MK','B2ML','B2MM','B2MN','B2MO','B2MP','B2MQ','B2MR','B2MS','B2MT','B2MU','B2MV','B2MW','B2MX','B2MY','B2MZ','B2N0','B2N0','B2N1','B2N2','B2N3','B2N4','B2N5','B2N6','B2N7','B2N8','B2N9','B2NA','B2NB','B2NC','B2ND','B2NE','B2NF','B2NG','B2NH','B2NI','B2NJ','B2NK','B2NL','B2NM','B2NN','B2NO','B2NP','B2NQ','B2NR','B2NS','B2NT','B2NU','B2NV','B2NW','B2NX','B2NY','B2NZ','B2O0','B2O0','B2O1','B2O2','B2O3','B2O4','B2O5','B2O6','B2O7','B2O8','B2O9','B2OA','B2OB','B2OC','B2OD','B2OE','B2OF','B2OG','B2OH','B2OI','B2OJ','B2OK','B2OL','B2OM','B2ON','B2OO','B2OP','B2OQ','B2OR','B2OS','B2OT','B2OU','B2OV','B2OW','B2OX','B2OY','B2OZ','B2P0','B2P0','B2P1','B2P2','B2P3','B2P4','B2P5','B2P6','B2P7','B2P8','B2P9','B2PA','B2PB','B2PC','B2PD','B2PE','B2PF','B2PG','B2PH','B2PI','B2PJ','B2PK','B2PL','B2PM','B2PN','B2PO','B2PP','B2PQ','B2PR','B2PS','B2PT','B2PU','B2PV','B2PW','B2PX','B2PY','B2PZ','B2Q0','B2Q0','B2Q1','B2Q2','B2Q3','B2Q4','B2Q5','B2Q6','B2Q7','B2Q8','B2Q9','B2QA','B2QB','B2QC','B2QD','B2QE','B2QF','B2QG','B2QH','B2QI','B2QJ','B2QK','B2QL','B2QM','B2QN','B2QO','B2QP','B2QQ','B2QR','B2QS','B2QT','B2QU','B2QV','B2QW','B2QX','B2QY','B2QZ','B2R0','B2R0','B2R1','B2R2','B2R3','B2R4','B2R5','B2R6','B2R7','B2R8','B2R9','B2RA','B2RB','B2RC','B2RD','B2RE','B2RF','B2RG','B2RH','B2RI','B2RJ','B2RK','B2RL','B2RM','B2RN','B2RO','B2RP','B2RQ','B2RR','B2RS','B2RT','B2RU','B2RV','B2RW','B2RX','B2RY','B2RZ','B2S0','B2S0','B2S1','B2S2','B2S3','B2S4','B2S5','B2S6','B2S7','B2S8','B2S9','B2SA','B2SB','B2SC','B2SD','B2SE','B2SF','B2SG','B2SH','B2SI','B2SJ','B2SK','B2SL','B2SM','B2SN','B2SO','B2SP','B2SQ','B2SR','B2SS','B2ST','B2SU','B2SV','B2SW','B2SX','B2SY','B2SZ','B2T0','B2T0','B2T1','B2T2','B2T3','B2T4','B2T5','B2T6','B2T7','B2T8','B2T9','B2TA','B2TB','B2TC','B2TD','B2TE','B2TF'
    --,'B2TG','B2TH','B2TI','B2TJ','B2TK','B2TL','B2TM','B2TN','B2TO','B2TP','B2TQ','B2TR','B2TS','B2TT','B2TU','B2TV','B2TW','B2TX','B2TY','B2TZ','B2U0','B2U0','B2U1','B2U2','B2U3','B2U4','B2U5','B2U6','B2U7','B2U8','B2U9','B2UA','B2UB','B2UC','B2UD','B2UE','B2UF','B2UG','B2UH','B2UI','B2UJ','B2UK','B2UL','B2UM','B2UN','B2UO','B2UP','B2UQ','B2UR','B2US','B2UT','B2UU','B2UV','B2UW','B2UX','B2UY','B2UZ','B2V0','B2V0','B2V1','B2V2','B2V3','B2V4','B2V5','B2V6','B2V7','B2V8','B2V9','B2VA','B2VB','B2VC','B2VD','B2VE','B2VF','B2VG','B2VH','B2VI','B2VJ','B2VK','B2VL','B2VM','B2VN','B2VO','B2VP','B2VQ','B2VR','B2VS','B2VT','B2VU','B2VV','B2VW','B2VX','B2VY','B2VZ','B2W0','B2W0','B2W1','B2W2','B2W3','B2W4','B2W5','B2W6','B2W7','B2W8','B2W9','B2WA','B2WB','B2WC','B2WD','B2WE','B2WF','B2WG','B2WH','B2WI','B2WJ','B2WK','B2WL','B2WM','B2WN','B2WO','B2WP','B2WQ','B2WR','B2WS','B2WT','B2WU','B2WV','B2WW','B2WX','B2WY','B2WZ','B2X0','B2X0','B2X1','B2X2','B2X3','B2X4','B2X5','B2X6','B2X7','B2X8','B2X9','B2XA','B2XB','B2XC','B2XD','B2XE','B2XF','B2XG','B2XH','B2XI','B2XJ','B2XK','B2XL','B2XM','B2XN','B2XO','B2XP','B2XQ','B2XR','B2XS','B2XT','B2XU','B2XV','B2XW','B2XX','B2XY','B2XZ','B2Y0','B2Y0','B2Y1','B2Y2','B2Y3','B2Y4','B2Y5','B2Y6','B2Y7','B2Y8','B2Y9','B2YA','B2YB','B2YC','B2YD','B2YE','B2YF','B2YG','B2YH','B2YI','B2YJ','B2YK','B2YL','B2YM','B2YN','B2YO','B2YP','B2YQ','B2YR','B2YS','B2YT','B2YU','B2YV','B2YW','B2YX','B2YY','B2YZ','B2Z0','B2Z0','B2Z1','B2Z2','B2Z3','B2Z4','B2Z5','B2Z6','B2Z7','B2Z8','B2Z9','B2ZA','B2ZB','B2ZC','B2ZD','B2ZE','B2ZF','B2ZG','B2ZH','B2ZI','B2ZJ','B2ZK','B2ZL','B2ZM','B2ZN','B2ZO','B2ZP','B2ZQ','B2ZR','B2ZS','B2ZT','B2ZU','B2ZV','B2ZW','B2ZX','B2ZY','B2ZZ'
    -- as if anyone would have more than 4205 unique buffs
}

    BuffIdCodes = {}
    for i, k in ipairs(BuffIdStrings) do
        BuffIdCodes[i] = FourCC(k)
        BuffIdCodes[BuffIdCodes[i]] = i
    end

    -- create a spellcast event for spellsteals to add a counter to spellsteal targets. The counter filters out dmg events not relevant to spellsteal
    SpellStealEvent.TriggerCast = CreateTrigger()
    TriggerRegisterAnyUnitEventBJ(SpellStealEvent.TriggerCast, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    TriggerAddAction(SpellStealEvent.TriggerCast, function()
        if GetUnitCurrentOrder(GetTriggerUnit()) == OrderId("spellsteal") then
            SpellStealEvent.Counter[GetSpellTargetUnit()] = SpellStealEvent.Counter[GetSpellTargetUnit()] + 1
        end
    end)

    SpellStealEvent.Trigger = CreateTrigger()
    TriggerRegisterAnyUnitEventBJ(SpellStealEvent.Trigger, EVENT_PLAYER_UNIT_DAMAGING)
    TriggerAddAction(SpellStealEvent.Trigger, function()
        if GetEventDamage() == 0 then
           -- local oldTime = os.clock()
            if BlzGetEventAttackType() == ATTACK_TYPE_NORMAL and SpellStealEvent.Counter[GetEventDamageSource()] > 0 then
                -- SpellSteal first throws an DAMAGE_TYPE_UNKNOWN event, then an DAMAGE_TYPE_NORMAL Event. There is 0 game-time between the events
                if BlzGetEventDamageType() == DAMAGE_TYPE_UNKNOWN then
                    SpellStealEvent.BuffCountA = UnitCountBuffsExBJ(bj_BUFF_POLARITY_EITHER, bj_BUFF_RESIST_EITHER, GetTriggerUnit(), true, true)
                    SpellStealEvent.BuffCountB = UnitCountBuffsExBJ(bj_BUFF_POLARITY_EITHER, bj_BUFF_RESIST_EITHER, GetEventDamageSource(), true, true)
--                    print("SpellSteal", GetUnitName(GetEventDamageSource()), " -> ", GetUnitName(GetTriggerUnit()))

                    -- save all buffs the unit has
                    SpellStealEvent.BuffArrayA.Count = 0
                    for i, buffId in ipairs(BuffIdCodes) do
                        if UnitHasBuffBJ(GetEventDamageSource(), buffId) then
                            SpellStealEvent.BuffArrayA.Count = SpellStealEvent.BuffArrayA.Count + 1
                            SpellStealEvent.BuffArrayA[SpellStealEvent.BuffArrayA.Count] = buffId
                            --print(BuffIdStrings[i])
                        end
                    end
                elseif BlzGetEventDamageType() == DAMAGE_TYPE_NORMAL and SpellStealEvent.BuffCountA and SpellStealEvent.BuffCountB then
                    SpellStealEvent.BuffCountA = UnitCountBuffsExBJ(bj_BUFF_POLARITY_EITHER, bj_BUFF_RESIST_EITHER, GetTriggerUnit(), true, true) - SpellStealEvent.BuffCountA
                    SpellStealEvent.BuffCountB = UnitCountBuffsExBJ(bj_BUFF_POLARITY_EITHER, bj_BUFF_RESIST_EITHER, GetEventDamageSource(), true, true) - SpellStealEvent.BuffCountB
                    
                    if SpellStealEvent.BuffCountA > 0 and SpellStealEvent.BuffCountB < 0 then
                        --print("SpellSteal", GetUnitName(GetEventDamageSource()), " -> ", GetUnitName(GetTriggerUnit()))

                        -- find buffs the unit does not have anymore from the saved list
                        for i= 1, SpellStealEvent.BuffArrayA.Count do
                            if not UnitHasBuffBJ(GetEventDamageSource(), SpellStealEvent.BuffArrayA[i]) then
                                udg_SpellStealEventBuff = SpellStealEvent.BuffArrayA[i]
                                udg_SpellStealEventGainer = GetTriggerUnit()
                                udg_SpellStealEventLoser = GetEventDamageSource()
                                globals.udg_SpellStealEvent = 0.0
                                globals.udg_SpellStealEvent = 1.0
                                globals.udg_SpellStealEvent = 0.0
                                --print(BuffIdStrings[BuffIdCodes[SpellStealEvent.BuffArrayA[i]]])
                                --print(string.pack('>I4', buffId))

                                -- spell steal only steals one buff, hence stop the loop
                                break
                            end
                        end
                    end
                    SpellStealEvent.BuffCountA = nil
                    SpellStealEvent.BuffCountB = nil
                    SpellStealEvent.Counter[GetEventDamageSource()] = SpellStealEvent.Counter[GetEventDamageSource()] - 1
                end
            end
            --print(os.clock() - oldTime)
        end    
    end)
end

ChangeLog:
V1.2 uses BlzGetAbilityId from V1.33+
V1.1 added a SpellEvent & Counter, to be less of a burden for other 0 dmg events.
 
Last edited:
I don't know of any.
Unit Ability loops with BlzGetUnitAbilityByIndex miss the "ability to ObjectId" converter. While they can find buff Abilities.
The Ability buffField can not be read with BlzGetAbilityxxxField (I don't know how). When that would work one could populate the table automatic.

if someone finds a better way, pls tell us.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
I don't know of any.
Unit Ability loops with BlzGetUnitAbilityByIndex miss the "ability to ObjectId" converter. While they can find buff Abilities.
The Ability buffField can not be read with BlzGetAbilityxxxField (I don't know how). When that would work one could populate the table automatic.

if someone finds a better way, pls tell us.
The way is to start with a Buff Event in the first place. Problem is, there isn't one, at least not one that doesn't require every single buff to be manually scripted.

So, I guess without a proper native (once M$ hopefully gets around to it), there wouldn't be a way to do it.

What one COULD do, however, is to use this resource of yours, combine it with a unit with infinite range, visibility, 0 cooldown, and have it always steal a buff the instant it gets applied. Hook that event, check the buff against the table, then spell-steal it back onto the original unit (or re-apply it using the ability that caused the buff somehow). It would be a lot of work, for sure, but it would create an event that currently doesn't (natively) exist - one that works with real buffs and not just triggered ones.

Actually, for Debuffs at least, it is possible to already detect a buff on the unit right away with your indexed table and a zero-damage-unknown-type event. I don't think the damage event fires for positive buffs like Bloodlust, though.

You might even be able to capture the SpellEffectEvent and just assume that the unit might get a buff (and if not, just disregard). This would also allow you to incorporate positive buffs.

Looking at your code, I don't think much would need to be changed to alter this from a Spell Steal Event to an actual Buff Event.
 
Last edited:
Ty, for your feedback.

The way is to start with a Buff Event in the first place. Problem is, there isn't one, at least not one that doesn't require every single buff to be manually scripted.
y, such an event would be great.
one could create such for single target active abilities with instant effect (inner fire, slow, blood lust, ...). But such abilities have hardcoded buffs anyway. So kinda less useful.
For any buff one could loop all units every 0.0x seconds and count/compare buffs. Taxing but would give a buff gained/lost event without the buff-source.

Actually, for Debuffs at least, it is possible to already detect a buff on the unit right away with your indexed table and a zero-damage-unknown-type event. I don't think the damage event fires for positive buffs like Bloodlust, though.
Yeah +buffs shouldn't fire damage events. But Difficult to know the gained/lost buff without a old buffSet of the unit.

The spellsteal dummy sounds intressting but not doable. How I stop the dummy from stealing old buffs?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Here's my recommendation:

Keep the table portion with the existing natural WarCraft 3 buffs, but instead of defining an extremely long string of custom buffs, use a definer function that adds said ability to a dummy unit, mark the buff as valid, if not then don't store anything against that buff.

Something like this makes more sense:
Lua:
local buffIdStrings = {'BPSE','BSTN','Bchd','Bdef','Bdet','Bfre','Bfro','Bvul','Bpoi','Bpsd','Bpsi','Bsha','Bspe','Btrv','Bclf','Bcmg','Bhea','Binf','Binv','Bmlc','Bmlt','Bmil','Bpxf','Bphx','Bply','Bslo','BHab','BHad','BHav','BHbn','BHbd','BHbz','BHds','Bdcb','Bdcl','Bdcm','Bdtb','Bdtl','Bdtm','BHfs','BHtc','BHwe','Bakb','Boar','Barm','Bbof','Bbsk','Bblo','Bdvv','Bdig','Bens','Bena','Beng','Beye','Bhwd','Blsh','Blsa','Bliq','Bprg','Bspl','Bstt','BOac','BOae','BOeq','BOea','BOhx','BOmi','BOsh','BOsf','BOvd','BOvc','BOwd','BOww','BOwk','Bbar','Bcor','Bcyc','Bcy2','Beat','Bfae','Bgra','Bmfl','Bmfa','Bpsh','Bps1','Brej','Broa','Bspo','Bssd','Bssi','Bvng','BEah','BEar','BEer','BEfn','BEim','BEia','BEme','BEst','BEsh','BEsv','Bams','Bam2','Babr','Bapl','Bcri','Bcrs','Bfrz','Bplg','Bpoc','Bpos','Brai','Brpb','Brpl','Brpm','Bspa','Buhf','Buns','Bweb','Bwea','BUan','BUau','BUav','BUcb','BUcs','BUdd','BUfa','BUim','BUsl','BUsp','BUst','BUts','BUtt','Basl','BCbf','BCtc','Bfzy','Bmec','BNmr','Bpig','BNpi','BNsa','Bshs','BNss','Btdg','Btsp','Btsa','BNba','BNbf','BHca','Bcsd','Bcsi','BNdm','BNdo','BNdi','BNdh','BNef','BNht','BNms','BNsi','BNst','BNsg','BNsq','BNsw','BNto','BNwm','BNbr','BNdc','BNin','BNpa','BNpm','BNrd','BNrf','BNsl','BIcb','BFig','BIcf','BIil','BIrb','BIrg','BIrl','BIrm','BIsv','BIsh','BIwb','BImo','BIpv','Xclf','Xfla','XHbz','XHfs','Xbof','XOeq','XOre','Xesn','XEsf','XEtq','XUdd','XNmo','XErc','XErf','XIct','AEsd','AEtr','ANmd','Bivs','BUad','Bult','BNab','BNcr','BNhs','XNhs','BNtm','BNeg','BNcs','XNcs','BNfy','BNcg','BNic','BNso','BNlm','BNvc','BNva','XNvc','Xbdt','Xbli','Xdis','Xfhs','Xfhm','Xfhl','Xfos','Xfom','Xfol','Xfns','Xfnm','Xfnl','Xfus','Xfum','Xful','BIhm'}

for i = FourCC("B000"), FourCC("B2ZZ") do
    if UnitAddAbility(unit, i) then
        buffTable[#buffTable+1] = i
        UnitRemoveAbility(unit, i)
    end
end

In addition to being more versatile, it will be significantly faster thanks to not needing to scan through hundreds of nil buff handles. It does add quite a bit to the loading time, but we can blame Blizzard for lack of a better alternative.

Also, since the 0 damage event fires for any debuff applied on a unit, you can expand on the usefulness of this resource to make it a generic "unit is debuffed" event (it's similar to what I'm using for Attack Engine, but in Attack Engine I at least know what buffs I'm looking for).
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Not particularly significant but as advice comments like:
-- what To do
Doesn't really have any value. Sometimes this means you need to add more context (what to do when) but in this case it's fairly obvious.

On another note, is this actually a reliable means of determining that the spell effect corresponds with a spell steal?
Code:
if GetUnitCurrentOrder(GetTriggerUnit()) == OrderId("spellsteal") then
Maybe I'm wrong, but I don't think the unit's current order is guaranteed to be any particular ability during said ability's effect trigger.
 
Last edited:
Maybe I'm wrong, but I don't think the unit's current order is guaranteed to be any particular ability during said ability's effect trigger.
When the ability is neither super instant (Windwalk, defend, berserk, ...) nor used over items. Then that can be used to know the ability used is a copy of spellsteal or whatever order you use.

Although it might break when there are many such spellcast triggers and an earlier stopped the unit altering the order (which breaks the spellcasting anyway :)).
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
When the ability is neither super instant (Windwalk, defend, berserk, ...) nor used over items. Then that can be used to know the ability used is a copy of spellsteal or whatever order you use.

Although it might break when there are many such spellcast triggers and an earlier stopped the unit altering the order (which breaks the spellcasting anyway :)).

Is spell steal an instant effect always? There's no potential for it to be tied to a missile or something that would allow you to change the units order prior to the spell effect triggering?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Is spell steal an instant effect always? There's no potential for it to be tied to a missile or something that would allow you to change the units order prior to the spell effect triggering?
The only thing that comes to mind that could delay it is if the caster has Sphere, but I'm also not sure if Sphere is just a visual thing or if it actually waits for the missile.
 
Is spell steal an instant effect always? There's no potential for it to be tied to a missile or something that would allow you to change the units order prior to the spell effect triggering?
the spellcasting is instant but the buff transfer is delayed by a missile. Hence I wait for this damage events with the specific damage type
 
Top