Topic hỏi đáp về cách làm map | version 15

Replace unit đó bằng một unit khác .

Nhưng như thế, lở mất hết các chỉ số, rồi cấp độ, các kill học dc, item nửa, trong map divide and fight con hiệp sỉ rồng, ulti củng thay đổi hình dạng thành 1 con rồng, nhưng mọi thứ củ đều không biếng mất, làm sao dc như thế, chỉ giúp ạ
 
Nhưng như thế, lở mất hết các chỉ số, rồi cấp độ, các kill học dc, item nửa, trong map divide and fight con hiệp sỉ rồng, ulti củng thay đổi hình dạng thành 1 con rồng, nhưng mọi thứ củ đều không biếng mất, làm sao dc như thế, chỉ giúp ạ

Metamorphosis của Night Elf .
 
Metamorphosis của Night Elf .

là sao cơ, ý mình là làm cách nào để thay đổi hình dạng ấy, cho hero thay đổi hình dạng luôn cơ chứ không cần phải có thời gian và và tốn hết 1 kill
 
Ai cho em hỏi trigger này:

1. Làm sao để unit này xuất hiện ở 1 vị trí (region) rồi unit đó tự động di chuyển đến phá nhà ở 1 vị trí (region).
2. khi hero chết, làm sao để hero đó tự hồi sinh ở 1 vị trí (region)
 
là sao cơ, ý mình là làm cách nào để thay đổi hình dạng ấy, cho hero thay đổi hình dạng luôn cơ chứ không cần phải có thời gian và và tốn hết 1 kill 

Kill hay Skill?
Thời gian nào, tức là một khi đổi thì đổi mãi mãi chứ không như Indian, sau 1 thời gian thì trở về cũ hả?
Cũng vẫn là Metamorphosis, chỉnh thời hạn của chiêu này về 0 (vô hạn).

Ai cho em hỏi trigger này:

1. Làm sao để unit này xuất hiện ở 1 vị trí (region) rồi unit đó tự động di chuyển đến phá nhà ở 1 vị trí (region). 
2. khi hero chết, làm sao để hero đó tự hồi sinh ở 1 vị trí (region)

1:
CreateAUnit
    Events
        Time - Every <SpawnDelayTime> seconds of game time
    Conditions
    Actions
        Unit - Create 1 <Unit> for <Player> at (Center of (<SpawnRegion>)) facing Default building facing degrees
        Unit - Order (Last created unit) to Right-Click (Center of (DestinationRegion))

2:
ReviveAHero
    Events
        Unit - A unit Dies
    Conditions
        ((Triggering unit) is A Hero) Equal to True
    Actions
        Wait <DelayTime> seconds
        Hero - Instantly revive (Dying unit) at (Center of (<ReviveRegion>)), Show revival graphics


Tham số


Phần tô đậm:
- Right-Click, nhưng tùy mục đích mà bạn có thể chọn kiểu di chuyển của đơn vị:
    + Right-Click: nhấn chuột phải, nếu là kể thù thì sẽ đánh, nếu là 1 đơn vị đồng minh thì nó sẽ theo đuôi, nếu là đất thì nó chỉ đi lại chỗ đó.
    + Attack-Move: di chuyến đến vị trí đó và đánh tất cả kẻ thù trên đường đi.
    + ...
- Dòng Wait... tùy bạn, nếu muốn sau 1 thời gian mới hồi sinh thì để dòng đó, nếu muốn chết 1 cái là hồi sinh luôn thì bỏ nó đi.
 
Chỉnh sửa cuối:
Kill hay Skill?
Thời gian nào, tức là một khi đổi thì đổi mãi mãi chứ không như Indian, sau 1 thời gian thì trở về cũ hả?
Cũng vẫn là Metamorphosis, chỉnh thời hạn của chiêu này về 0 (vô hạn).

skill, mình nhầm sr

thế biến thành con khác thì làm ntn, không lẽ chỉ có thể biến thành con demon đó thôi sao
 
Kill hay Skill?
Thời gian nào, tức là một khi đổi thì đổi mãi mãi chứ không như Indian, sau 1 thời gian thì trở về cũ hả?
Cũng vẫn là Metamorphosis, chỉnh thời hạn của chiêu này về 0 (vô hạn).



1:
CreateAUnit
    Events
        Time - Every <SpawnDelayTime> seconds of game time
    Conditions
    Actions
        Unit - Create 1 <Unit> for <Player> at (Center of (<SpawnRegion>)) facing Default building facing degrees
        Unit - Order (Last created unit) to Right-Click (Center of (DestinationRegion))

2:
ReviveAHero
    Events
        Unit - A unit Dies
    Conditions
        ((Triggering unit) is A Hero) Equal to True
    Actions
        Wait <DelayTime> seconds
        Hero - Instantly revive (Dying unit) at (Center of (<ReviveRegion>)), Show revival graphics


Tham số


Phần tô đậm:
- Right-Click, nhưng tùy mục đích mà bạn có thể chọn kiểu di chuyển của đơn vị:
    + Right-Click: nhấn chuột phải, nếu là kể thù thì sẽ đánh, nếu là 1 đơn vị đồng minh thì nó sẽ theo đuôi, nếu là đất thì nó chỉ đi lại chỗ đó.
    + Attack-Move: di chuyến đến vị trí đó và đánh tất cả kẻ thù trên đường đi.
    + ...
- Dòng Wait... tùy bạn, nếu muốn sau 1 thời gian mới hồi sinh thì để dòng đó, nếu muốn chết 1 cái là hồi sinh luôn thì bỏ nó đi.

Bạn ơi sao unit đc creat o region này nó chỉ đứng im, ko chịu di chuyển ra chỗ region unit
và làm sao để hero ở team 1 khi chết sẽ hôi sinh ở region bên này, còn hero team 2 khi chết sẽ hồi sinh ở region bên kia
 
Chỉnh sửa cuối:
cho hỏi mình chơi vài map có con nó đủ 4 chiêu , sau khi biến hình thì 2 hoặc 3 chiêu gì của nó biến thành chiêu khác và đến khi hết thời gian biến hình thì chiêu trở lại như cũ , có pro nào cho mình xin cái trigger với nếu đc thì cho map test luôn :D tks trước nha
 
cách thức làm system ép đồ thì xài loop hay hơn hashtble ? mình thấy nhiều system ép đồ hay xài loop thay vì hashtable ?
 
cho hỏi mình chơi vài map có con nó đủ 4 chiêu , sau khi biến hình thì 2 hoặc 3 chiêu gì của nó biến thành chiêu khác và đến khi hết thời gian biến hình thì chiêu trở lại như cũ , có pro nào cho mình xin cái trigger với nếu đc thì cho map test luôn :D tks trước nha
cũng vẫn chỉ là metamphosis thui bạn , con biến hình chuyển skill khác là dc
 
Chò mình hỏi cách ép các system như bên dưới!Theo mình hiểu thì copy tất cả text rồi sau đó save và mở lại, cái runtextmacro Status__CreateAbilities() sẽ tự tạo cho mình các abi để sử dụng phải ko? hay mình phải copy các object trước?Mình làm theo hướng dẫn như thế nhưng save map ko đc!
Mã:
//
//      ___ _____ _ _____ _   _ ___ 
//     / __|_   _/_\_   _| | | / __|
//     \__ \ | |/ _ \| | | |_| \__ \    By Jesus4Lyf.
//     |___/ |_/_/ \_\_| \____/|___/          v 1.3.0
//
//      What is Status?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Status allows you to apply stuns, silences, disable attacks and much
//          more. Status effects based off dummy casted spells are applied 0.0
//          seconds after the "add" method is called. Status aims to commoditise
//          unit effects in WC3.
//
//      Restrictions
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Disarming spell immune units is not possible. Some status effects will
//          not apply to invulnerable units, namely those which are dummy casted.
//
//      How to implement?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Create a new trigger called Status, go to 'Edit -> Convert to
//          Custom Text', and replace everything that's there with this script.
//
//          Save the map, close it, reopen it, and then delete the "!" from the
//          FAR left side of the next line (so "runtextmacro" will line up with this line):
  //!       runtextmacro Status__CreateAbilities()
//
//          Go to the object editor, and select abilities. Go to Special > Heroes,
//          and select Disarm (Both). Change Data - Attacks Prevented to Melee, Ranged.
//          For Disarm (Melee), change Attacks Prevented to Melee. For Disarm (Range),
//          change Attacks Prevented to Ranged. Object merger has a bug that does not
//          allow setting this field automatically.
//
//      Methods:
//     ¯¯¯¯¯¯¯¯¯¯
//          Statuses (short list):
//              - Disable (addDisable, removeDisable, isDisabled)
//              - Stun (addStun, removeStun, isStunned)
//              - Silence (addSilence, removeSilence, isSilenced)
//              - Doom (addDoom, removeDoom, isDoomed)
//              - DisarmMelee (addDisarmMelee, removeDisarmMelee, isDisarmedMelee)
//              - DisarmRange (addDisarmRange, removeDisarmRange, isDisarmedRange)
//              - Disarm (addDisarm, removeDisarm, isDisarmed) // this is both Melee AND Ranged.
//              - Immobolise (addImmobolise, removeImmobolise, isImmobolised)
//              - Invisible (addInvisible, removeInvisible, isInvisible)
//              - Ghost (addGhost, removeGhost, isGhost)
//              - Invulnerable (addInvulnerable, removeInvulnerable, isInvulnerable)
//              - Immunity (addImmunity, removeImmunity, isImmune)
//              - Pause (addPause, removePause, isPaused)
//              - Hide (addHide, removeHide, isHidden)
//              - Unpath (addUnpath, removeUnpath, isUnpathed)
//              - Hex (addHex, removeHex, isHexed)
//              - Locust (addLocust, removeLocust, isLocust) // does not remove correctly for flying units, use with caution.
//              - NeverMiss (addNeverMiss, removeNeverMiss, isNeverMiss)
//              - AlwaysMiss (addAlwaysMiss, removeAlwaysMiss, isAlwaysMiss)
//              - Untouchable (addUntouchable, removeUntouchable, isUntouchable) // 100% evasion
//              - Banish (addBanish, removeBanish, isBanished)
//              - Phase (addPhase, removePhase, isPhased) // clashes with windwalk, interrupts current order
//              - ResistantSkin (addResistantSkin, removeResistantSkin, isResistantSkin)
//              - ReflectPiercing (addReflectPiercing, removeReflectPiercing, isReflectPiercing)
//
//          Bonuses (short list):
//              - ArmorBonus (modArmorBonus, getArmorBonus)
//              - DamageBonus (modDamageBonus, getDamageBonus)
//              - StrBonus (modStrBonus, getStrBonus)
//              - AgiBonus (modAgiBonus, getAgiBonus)
//              - IntBonus (modIntBonus, getIntBonus)
//              - AttackSpeedBonus (modAttackSpeedBonus, getAttackSpeedBonus)
//              - Health (modHealthBonus, getHealthBonus)
//              - Mana (modManaBonus, getManaBonus)'
//              - HealthRegen (modHealthRegenBonus, getHealthRegenBonus)
//              - HealthRegenPercent (modHealthRegenPercentBonus, getHealthRegenPercentBonus) // percent of max
//              - ManaRegen (modManaRegenBonus, getManaRegenBonus)
//              - ManaRegenPercent (modManaRegenPercentBonus, getManaRegenPercentBonus) // percent of max
//              - MoveSpeed (modMoveSpeedBonus, getMoveSpeedBonus)
//              - MoveSpeedPercent (modMoveSpeedPercentBonus, getMoveSpeedPercentBonus) // percent of current move speed (after normal bonuses).
//
//      How to Use:
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Statuses:
//              Status[unit].add?()
//                  - Adds the status effect to the unit.
//                  - This does not add any animation.
//              Status[unit].remove?()
//                  - Removes the status effect added with .add?().
//                  - Will not actually remove it until all added instances are removed.
//              Status[unit].is?() --> boolean
//                  - Checks to see whether or not a unit has a status effect applied.
//
//          Bonuses:
//              Status[unit].mod?(amount)
//                  - Modifies the bonus by the amount given.
//                  - Use a negative value to reverse a bonus.
//                  - Supports giving negative of a bonus.
//              Status[unit].get?()
//                  - Gets the curret total amount for a given bonus.
//
//      Thanks:
//     ¯¯¯¯¯¯¯¯¯
//          - Weep: for suggesting that making the ability an ultimate hero ability
//            would allow it to stun magic immune units, and suggesting a simpler
//            target allowance for the ability.
//
//          - 13lade619: for noticing that the PreloadModule was not actually
//            implemented, causing first use lag.
//
library Status uses AIDS, DummyCaster, T32
    globals
        private constant real PERIOD=0.1 // for regen effects.
        private constant player DUMMY_CASTER_OWNER=Player(PLAYER_NEUTRAL_PASSIVE)
        private constant boolean PERMENANTLY_REVEAL=true // reveal all units always, or only during dummy spells
        
        // To change these, change them also in the externalblock before executing it.
        private constant integer ABIL_STUN='A500'
        private constant integer ABIL_SILENCE='A501'
        private constant integer ABIL_DISARM_BOTH='A502'
        private constant integer ABIL_DISARM_MELEE='A503'
        private constant integer ABIL_DISARM_RANGE='A504'
        private constant integer ABIL_IMMOBOLISE='A505'
        private constant integer ABIL_INVISIBLE='A507'
        private constant integer ABIL_GHOST='A508'
        private constant integer ABIL_DOOM='A509'
        private constant integer ABIL_IMMUNITY='A50B'
        private constant integer ABIL_HEX='A50C'
        private constant integer ABIL_UNLOCUST='A50D'
        private constant integer ABIL_NEVER_MISS='A50F'
        private constant integer ABIL_ALWAYS_MISS='A50H'
        private constant integer ABIL_UNTOUCHABLE='A50J'
        private constant integer ABIL_BANISH='A50K'
        private constant integer ABIL_PHASE='A50L'
        //private constant integer ABIL_DOUBLE_ATTACK='A50O'
        private constant integer ABIL_RESISTANT_SKIN='A50Q'
        private constant integer ABIL_REFLECT_PIERCING='A50S'
        private constant integer ABIL_DISABLE='A50T'
        
        private constant integer ABIL_ARMOR='A5A@'
        private constant integer ABIL_DAMAGE='A5B@'
        private constant integer ABIL_STR='A5C@'
        private constant integer ABIL_AGI='A5D@'
        private constant integer ABIL_INT='A5E@'
        private constant integer ABIL_ATTACK_SPEED='A5F@'
        private constant integer ABIL_HEALTH='A5G@'
        private constant integer ABIL_MANA='A5H@'
        
        private constant integer LEVELS_ARMOR=10
        private constant integer LEVELS_DAMAGE=15
        private constant integer LEVELS_STR=10
        private constant integer LEVELS_AGI=10
        private constant integer LEVELS_INT=10
        private constant integer LEVELS_ATTACK_SPEED=9
        private constant integer LEVELS_HEALTH=20
        private constant integer LEVELS_MANA=20
        
        // To change these, change them also in the externalblock before executing it.
        private constant integer BUFF_STUN='B500'
        private constant integer BUFF_SILENCE='B501'
        private constant integer BUFF_DOOM='B509'
        private constant integer BUFF_DISARM_MELEE='B503'
        private constant integer BUFF_DISARM_RANGE='B504'
        private constant integer BUFF_DISARM_BOTH='B502'
        private constant integer BUFF_IMMOBOLISE_GROUND='B505'
        private constant integer BUFF_IMMOBOLISE_AIR='B506'
        private constant integer BUFF_HEX='B50C'
        private constant integer BUFF_BANISH='B50K'
        private constant integer BUFF_PHASE='B50L'
        private constant integer BUFF_DISABLE='B50T'
        
        private constant integer OID_STOP=851972 //stop
        private constant integer OID_STUN=852231 //firebolt
        private constant integer OID_SILENCE=852668 //soulburn
        private constant integer OID_DISARM=852585 //drunkenhaze
        private constant integer OID_IMMOBOLISE=852106 //ensnare
        private constant integer OID_DOOM=852583 //doom
        private constant integer OID_HEX=852502 //hex
        private constant integer OID_UNLOCUST=852155 //ravenform
        private constant integer OID_BANISH=852486 //banish
        private constant integer OID_PHASE=852129 //windwalk
        private constant integer OID_DISABLE=852252 //creepthunderbolt (hurlboulder)
        
        private unit CASTER_DISARM_BOTH=null
        private unit CASTER_DISARM_MELEE=null
        private unit CASTER_DISARM_RANGE=null
    endglobals
    
    native UnitAlive takes unit id returns boolean
    
    private module PreloadModule
        private static method onInit takes nothing returns nothing
            local unit u=CreateUnit(DUMMY_CASTER_OWNER,DUMMY_TYPE,0,0,0)
            local integer abil
            //! textmacro Status__PreloadBonus takes BONUS
                set abil=ABIL_$BONUS$+LEVELS_$BONUS$
                loop
                    call UnitAddAbility(u,abil)
                    exitwhen abil==ABIL_$BONUS$
                    set abil=abil-1
                endloop
            //! endtextmacro
            call UnitAddAbility(u,ABIL_INVISIBLE)
            call UnitAddAbility(u,ABIL_GHOST)
            call UnitAddAbility(u,ABIL_IMMUNITY)
            call UnitAddAbility(u,ABIL_UNLOCUST)
            call UnitAddAbility(u,ABIL_NEVER_MISS)
            call UnitAddAbility(u,ABIL_ALWAYS_MISS)
            call UnitAddAbility(u,ABIL_UNTOUCHABLE)
            call UnitAddAbility(u,ABIL_PHASE)
            //call UnitAddAbility(u,ABIL_DOUBLE_ATTACK)
            call UnitAddAbility(u,ABIL_RESISTANT_SKIN)
            call UnitAddAbility(u,ABIL_REFLECT_PIERCING)
            //! runtextmacro Status__PreloadBonus("ARMOR")
            //! runtextmacro Status__PreloadBonus("DAMAGE")
            //! runtextmacro Status__PreloadBonus("STR")
            //! runtextmacro Status__PreloadBonus("AGI")
            //! runtextmacro Status__PreloadBonus("INT")
            //! runtextmacro Status__PreloadBonus("ATTACK_SPEED")
            //! runtextmacro Status__PreloadBonus("HEALTH")
            //! runtextmacro Status__PreloadBonus("MANA")
            call KillUnit(u)
            call RemoveUnit(u)
            set u=null
        endmethod
    endmodule
    
    private module StaticPeriodic
        private static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(),PERIOD,true,function thistype.periodicLink)
        endmethod
    endmodule
    
    private module StatusInit
        private static method onInit takes nothing returns nothing
            local integer i
            //! textmacro Status__CreateAbilities
                // For reflecting piercing.
                //! externalblock extension=lua ConstantMerger $FILENAME$
                //! i setvalue("Misc","DefendDeflection","1")
                //! endexternalblock
                
                // Start externalblock
                //! externalblock extension=lua ObjectMerger $FILENAME$
                
                ////////////////////
                // Status Effects //
                ////////////////////
                
                // Stun (X500, firebolt)
                //! i setobjecttype("buffs")
                //! i createobject("BPSE","B500")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"ftip","Stunned")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"fube","This unit is stunned; it cannot move, attack or cast spells.")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ACfb","A500")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Stun")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"Htb1",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                //! i makechange(current,"abuf",1,"B500")
                //! i makechange(current,"aher",1)
                //! i makechange(current,"arlv",6)
                
                // Silence (X501, soulburn)
                //! i setobjecttype("buffs")
                //! i createobject("BNso","B501")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Silence")
                //! i makechange(current,"fube","This unit is Silenced; it cannot cast spells.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNSilence.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANso","A501")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Silence")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"Nso1",1,0)
                //! i makechange(current,"Nso3",1,0)
                //! i makechange(current,"Nso2",1,99999)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B501")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                
                // Disarm (Both) (X502, drunkenhaze)
                //! i setobjecttype("buffs")
                //! i createobject("BNdh", "B502")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Disarmed")
                //! i makechange(current,"fube","This unit is Disarmed; it cannot attack.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANdh","A502")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Disarm (Both)")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amac",0)
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"Nsi2",1,0)
                //! i makechange(current,"Nsi3",1,0)
                //! i makechange(current,"aare",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B502")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Disarm (Melee) (X503, drunkenhaze)
                //! i setobjecttype("buffs")
                //! i createobject("BNdh", "B503")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Disarmed (Melee)")
                //! i makechange(current,"fube","This unit is Disarmed; it cannot use melee attacks.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANdh","A503")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Disarm (Melee)")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amac",0)
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"Nsi2",1,0)
                //! i makechange(current,"Nsi3",1,0)
                //! i makechange(current,"aare",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B503")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Disarm (Range) (X504, drunkenhaze)
                //! i setobjecttype("buffs")
                //! i createobject("BNdh", "B504")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Disarmed (Ranged)")
                //! i makechange(current,"fube","This unit is Disarmed; it cannot use ranged attacks.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANdh","A504")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Disarm (Range)")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amac",0)
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"Nsi2",1,0)
                //! i makechange(current,"Nsi3",1,0)
                //! i makechange(current,"aare",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B504")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Entangle (X505 - X506, ensnare)
                //! i setobjecttype("buffs")
                //! i createobject("Beng","B505")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Immobilised")
                //! i makechange(current,"fube","This unit is immobilised; it cannot move or fly.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNWirtsOtherLeg.blp")
                //! i makechange(current,"ftat","")
                
                //! i createobject("Bena","B506")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Immobilised")
                //! i makechange(current,"fube","This unit is immobilised; it cannot move or fly.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNWirtsOtherLeg.blp")
                //! i makechange(current,"ftat", "")
                
                //! i setobjecttype("abilities")
                //! i createobject("ACen","A505")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Immobilise")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"aher",1)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"areq","")
                //! i makechange(current,"Ens1",1,-1)
                //! i makechange(current,"Ens2",1,-1)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B505,B506")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Invisibility (X507)
                //! i setobjecttype("abilities")
                //! i createobject("Apiv","A507")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Invisibility")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"ahdu",1,0.5)
                //! i makechange(current,"adur",1,0.5)
                
                // Ghost (X508)
                //! i setobjecttype("abilities")
                //! i createobject("Agho","A508")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Ghost")
                //! i makechange(current,"ansf","(Status System)")
                
                // Doom (X509, doom)
                //! i setobjecttype("buffs")
                //! i createobject("BNdo","B509")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftat","")
                //! i makechange(current,"fube","This unit has been stricken with Doom; it cannot cast spells.")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANdo","A509")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Doom")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"Ndo1",1,0)
                //! i makechange(current,"Ndo2",1,0)
                //! i makechange(current,"Ndo3",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B509")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Spell Immunity (X50A - X50B)
                //! i setobjecttype("abilities")
                //! i createobject("Amim","A50A")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Spell Immunity")
                //! i makechange(current,"ansf","(Status System)")
                
                //! i createobject("Aspb","A50B")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Spell Immunity")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50A")
                
                // Hex (X50C, hex)
                //! i setobjecttype("buffs")
                //! i createobject("BOhx","B50C")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"feat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("AOhx","A50C")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Hex")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"asat","")
                //! i makechange(current,"alev",1)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B50C")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                
                // Unlocust (X50D, crowform)
                //! i setobjecttype("abilities")
                //! i createobject("Amrf","A50D")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Unlocust")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"Eme3",1,-1)
                //! i makechange(current,"Eme4",1,-1)
                //! i makechange(current,"acas",1,0)
                //! i makechange(current,"adur",1,0)
                
                // Never Miss (X50E - X50F)
                //! i setobjecttype("abilities")
                //! i createobject("ACct","A50E")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Never Miss")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"Ocr1",1,100)
                //! i makechange(current,"Ocr2",1,0)
                //! i makechange(current,"Ocr5",1,1)
                //! i makechange(current,"atar",1,"notself")
                
                //! i createobject("Aspb","A50F")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Never Miss")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50E")
                
                // Always Miss (X50G - X50H)
                //! i setobjecttype("abilities")
                //! i createobject("ACbh","A50G")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Always Miss")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"Hbh1",1,0)
                //! i makechange(current,"Hbh4",1,100)
                //! i makechange(current,"atar",1,"notself")
                
                //! i createobject("Aspb","A50H")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Always Miss")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50G")
                
                // Untouchable (X50I - X50J)
                //! i setobjecttype("abilities")
                //! i createobject("ACes","A50I")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Untouchable")
                //! i makechange(current,"ansf","(Status System)")
                
                //! i createobject("Aspb","A50J")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Untouchable")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50I")
                
                // Banish (X50K, banish)
                //! i setobjecttype("buffs")
                //! i createobject("BNdo","B50K")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftat","")
                //! i makechange(current,"fefl","")
                
                //! i setobjecttype("abilities")
                //! i createobject("AHbn","A50K")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Banish")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"aefs","")
                //! i makechange(current,"alev",1)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"Hbn1",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B50K")
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Phase (X50L, windwalk)
                //! i setobjecttype("buffs")
                //! i createobject("BOwk","B50L")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"ftip","Phase")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"fube","This unit is Phasing; it can walk through other units.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNMirrorImage.blp")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANwk","A50L")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Phase")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aefs","")
                //! i makechange(current,"Owk3",1,0)
                //! i makechange(current,"Owk4",1,0)
                //! i makechange(current,"Owk2",1,0)
                //! i makechange(current,"Owk1",1,-1)
                //! i makechange(current,"abuf",1,"B50L")
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"aher",0)
                /*
                // Double Attack (X50M - X50O)
                //! i setobjecttype("abilities")
                //! i createobject("ACsa","A50M")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Double Attack")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"Hfa1",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                
                //! i createobject("AIll","A50N")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Double Attack")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"asat","")
                //! i makechange(current,"atat","")
                //! i makechange(current,"Iob2",1,100)
                //! i makechange(current,"Iob3",1,100)
                //! i makechange(current,"Iob4",1,100)
                //! i makechange(current,"Idam",1,0)
                //! i makechange(current,"Iobu",1,"A50M")
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                
                //! i createobject("Aspb","A50O")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Double Attack")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50N")
                */
                
                // Resistant Skin (X50P - X50Q)
                //! i setobjecttype("abilities")
                //! i createobject("ACrk","A50P")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Resistant Skin")
                //! i makechange(current,"ansf","(Status System)")
                
                //! i createobject("Aspb","A50Q")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Resistant Skin")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50P")
                
                // Reflect Piercing (X50R - X50S)
                //! i setobjecttype("abilities")
                //! i createobject("Aegr","A50R")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Reflect Piercing")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"Def6",1,100)
                //! i makechange(current,"Def1",1,1)
                //! i makechange(current,"Def7",1,0)
                //! i makechange(current,"Def5",1,0)
                
                //! i createobject("Aspb","A50S")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Reflect Piercing")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50R")
                
                // Disable (X50T, creepthunderbolt (hurlboulder))
                //! i setobjecttype("buffs")
                //! i createobject("BPSE","B50T")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"ftip","Disabled")
                //! i makechange(current,"fube","This unit is Disabled; it cannot do anything.")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNReplay-Pause.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ACtb","A50T")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Disable")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"Ctb1",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                //! i makechange(current,"abuf",1,"B50T")
                //! i makechange(current,"aher",1)
                //! i makechange(current,"arlv",6)
                
                
                ////////////////////
                // Status Bonuses //
                ////////////////////
                //! i setobjecttype("abilities")
                
                //! i myChar={}
                //! i myChar[1]="A"
                //! i myChar[2]="B"
                //! i myChar[3]="C"
                //! i myChar[4]="D"
                //! i myChar[5]="E"
                //! i myChar[6]="F"
                //! i myChar[7]="G"
                //! i myChar[8]="H"
                //! i myChar[9]="I"
                //! i myChar[10]="J"
                //! i myChar[11]="K"
                //! i myChar[12]="L"
                //! i myChar[13]="M"
                //! i myChar[14]="N"
                //! i myChar[15]="O"
                //! i myChar[16]="P"
                //! i myChar[17]="Q"
                //! i myChar[18]="R"
                //! i myChar[19]="S"
                //! i myChar[20]="T"
                //! i myChar[21]="U"
                //! i myChar[22]="V"
                //! i myChar[23]="W"
                //! i myChar[24]="X"
                //! i myChar[25]="Y"
                //! i myChar[26]="Z"
                
                //! i myBin={}
                //! i myBin[1]=1
                //! i myBin[2]=2
                //! i myBin[3]=4
                //! i myBin[4]=8
                //! i myBin[5]=16
                //! i myBin[6]=32
                //! i myBin[7]=64
                //! i myBin[8]=128
                //! i myBin[9]=256
                //! i myBin[10]=512
                //! i myBin[11]=1024
                //! i myBin[12]=2048
                //! i myBin[13]=4096
                //! i myBin[14]=8192
                //! i myBin[15]=16384
                //! i myBin[16]=32768
                //! i myBin[17]=65536
                //! i myBin[18]=131072
                //! i myBin[19]=262144
                //! i myBin[20]=524288
                //! i myBin[21]=1048576
                //! i myBin[22]=2097152
                //! i myBin[23]=4194304
                //! i myBin[24]=8388608
                //! i myBin[25]=16777216
                //! i myBin[26]=33554432
                
                // Armor (10 = 1023 max)
                //! i for i=1,10 do
                    //! i createobject("AId1","A5A"..myChar[i])
                    //! i makechange(current,"Idef",1,myBin[i])
                    //! i makechange(current,"anam","Armor Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AId1","A5A@")
                //! i makechange(current,"Idef",1,-myBin[11])
                //! i makechange(current,"anam","Armor Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                
                // Damage (15 = 32767 max)
                //! i for i=1,15 do
                    //! i createobject("AItg","A5B"..myChar[i])
                    //! i makechange(current,"Iatt",1,myBin[i])
                    //! i makechange(current,"anam","Damage Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AItg","A5B@")
                //! i makechange(current,"Iatt",1,-myBin[16])
                //! i makechange(current,"anam","Damage Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // Str/Agi/Int (10 = 1023 max)
                //! i for i=1,10 do
                    //! i createobject("AIs1","A5C"..myChar[i])
                    //! i makechange(current,"Istr",1,myBin[i])
                    //! i makechange(current,"anam","Strength Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                    
                    //! i createobject("AIa1","A5D"..myChar[i])
                    //! i makechange(current,"Iagi",1,myBin[i])
                    //! i makechange(current,"anam","Agility Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                    
                    //! i createobject("AIi1","A5E"..myChar[i])
                    //! i makechange(current,"Iint",1,myBin[i])
                    //! i makechange(current,"anam","Intelligence Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AIs1","A5C@")
                //! i makechange(current,"Istr",1,-myBin[11])
                //! i makechange(current,"anam","Strength Bonus")
                //! i makechange(current,"ansf","(Status System)")
                //! i createobject("AIa1","A5D@")
                //! i makechange(current,"Iagi",1,-myBin[11])
                //! i makechange(current,"anam","Agility Bonus")
                //! i makechange(current,"ansf","(Status System)")
                //! i createobject("AIi1","A5E@")
                //! i makechange(current,"Iint",1,-myBin[11])
                //! i makechange(current,"anam","Intelligence Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // Attack Speed (9 = 511% max)
                //! i for i=1,9 do
                    //! i createobject("AIsx","A5F"..myChar[i])
                    //! i makechange(current,"Isx1",1,myBin[i]*0.01)
                    //! i makechange(current,"anam","Attack Speed Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AIsx","A5F@")
                //! i makechange(current,"Isx1",1,-myBin[10]*0.01)
                //! i makechange(current,"anam","Attack Speed Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // Max HP (20 = 1048575 max)
                //! i for i=1,20 do
                    //! i createobject("AIl2","A5G"..myChar[i])
                    //! i makechange(current,"Ilif",1,myBin[i])
                    //! i makechange(current,"anam","Health Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AIl2","A5G@")
                //! i makechange(current,"Ilif",1,-myBin[21])
                //! i makechange(current,"anam","Health Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // Max Mana (20 = 1048575 max)
                //! i for i=1,20 do
                    //! i createobject("AImz","A5H"..myChar[i])
                    //! i makechange(current,"Iman",1,myBin[i])
                    //! i makechange(current,"anam","Mana Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AImz","A5H@")
                //! i makechange(current,"Iman",1,-myBin[21])
                //! i makechange(current,"anam","Mana Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // End externalblock
                //! endexternalblock
            //! endtextmacro
            set thistype.dummyCaster=CreateUnit(DUMMY_CASTER_OWNER,DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster2=CreateUnit(DUMMY_CASTER_OWNER,DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster3=CreateUnit(DUMMY_CASTER_OWNER,DUMMY_TYPE,0,0,0)
            call UnitAddAbility(thistype.dummyCaster,ABIL_STUN)
            call UnitAddAbility(thistype.dummyCaster,ABIL_DISABLE)
            call UnitAddAbility(thistype.dummyCaster,ABIL_SILENCE)
            set CASTER_DISARM_BOTH=thistype.dummyCaster
            set CASTER_DISARM_MELEE=thistype.dummyCaster2
            set CASTER_DISARM_RANGE=thistype.dummyCaster3
            call UnitAddAbility(CASTER_DISARM_BOTH,ABIL_DISARM_BOTH)
            call UnitAddAbility(CASTER_DISARM_MELEE,ABIL_DISARM_MELEE)
            call UnitAddAbility(CASTER_DISARM_RANGE,ABIL_DISARM_RANGE)
            call UnitAddAbility(thistype.dummyCaster,ABIL_IMMOBOLISE)
            call UnitAddAbility(thistype.dummyCaster,ABIL_DOOM)
            call UnitAddAbility(thistype.dummyCaster,ABIL_HEX)
            call UnitAddAbility(thistype.dummyCaster,ABIL_BANISH)
            set i=bj_MAX_PLAYERS
            loop
                set i=i-1
                call SetPlayerAbilityAvailable(Player(i),ABIL_IMMUNITY,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_NEVER_MISS,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_ALWAYS_MISS,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_UNTOUCHABLE,false)
                //call SetPlayerAbilityAvailable(Player(i),ABIL_DOUBLE_ATTACK,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_RESISTANT_SKIN,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_REFLECT_PIERCING,false)
                exitwhen i==0
            endloop
        endmethod
    endmodule
    
    private module TwoPowArray
        readonly static integer array twoPow
        private static method onInit takes nothing returns nothing
            local integer i=0
            local integer val=1
            loop
                set thistype.twoPow[i]=val // thistype.twoPow[0]=1
                exitwhen i==30
                set i=i+1
                set val=val*2
            endloop
        endmethod
    endmodule
     struct Status extends array
        private method AIDS_onCreate takes nothing returns nothing
            static if PERMENANTLY_REVEAL then
                call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
            endif
            
            set this.disableLevel=0
            set this.stunLevel=0
            set this.silenceLevel=0
            set this.doomLevel=0
            set this.disarmMeleeLevel=0
            set this.disarmRangeLevel=0
            set this.immoboliseLevel=0
            set this.invisibleLevel=0
            set this.ghostLevel=0
            set this.invulnerableLevel=0
            set this.immunityLevel=0
            set this.pauseLevel=0
            set this.hideLevel=0
            set this.unpathLevel=0
            set this.hexLevel=0
            set this.locustLevel=0
            set this.neverMissLevel=0
            set this.alwaysMissLevel=0
            set this.untouchableLevel=0
            set this.banishLevel=0
            set this.phaseLevel=0
            set this.resistantSkinLevel=0
            set this.reflectPiercingLevel=0
            
            set this.armorBonus=0
            set this.damageBonus=0
            set this.strBonus=0
            set this.agiBonus=0
            set this.intBonus=0
            set this.attackSpeedBonus=0
            set this.healthBonus=0
            set this.manaBonus=0
            set this.healthRegenBonus=0
            set this.manaRegenBonus=0
            set this.healthRegenPercentBonus=0
            set this.manaRegenPercentBonus=0
            
            set this.moveSpeedBonus=0.0
            set this.moveSpeedPercentBonus=0.0
            call this.stopPeriodic()
        endmethod
        //! runtextmacro AIDS()
        private static unit dummyCaster=null
        private static unit dummyCaster2=null
        private static unit dummyCaster3=null
        
        implement StatusInit
        implement TwoPowArray
        implement PreloadModule
        
        ////////////////////
        // Status Effects //
        ////////////////////
        
        // Stun
        private integer stunLevel
        method addStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel+1
            if this.stunLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_STUN,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel-1
            if this.stunLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_STUN)
            endif
        endmethod
        method isStunned takes nothing returns boolean
            return this.stunLevel>0
        endmethod
        
        // Disable
        private integer disableLevel
        method addDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel+1
            if this.disableLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_DISABLE,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel-1
            if this.disableLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DISABLE)
            debug elseif this.disableLevel<0 then
                debug call BJDebugMsg("Status Error - More disables removed than previously added.")
            endif
        endmethod
        method isDisabled takes nothing returns boolean
            return this.disableLevel>0
        endmethod
        
        // Silence
        private integer silenceLevel
        method addSilence takes nothing returns nothing
            set this.silenceLevel=this.silenceLevel+1
            if this.silenceLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_SILENCE,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeSilence takes nothing returns nothing
            set this.silenceLevel=this.silenceLevel-1
            if this.silenceLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_SILENCE)
            endif
        endmethod
        method isSilenced takes nothing returns boolean
            return this.silenceLevel>0
        endmethod
        
        private integer doomLevel
        method addDoom takes nothing returns nothing
            set this.doomLevel=this.doomLevel+1
            if this.doomLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_DOOM,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeDoom takes nothing returns nothing
            set this.doomLevel=this.doomLevel-1
            if this.doomLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DOOM)
            endif
        endmethod
        method isDoomed takes nothing returns boolean
            return this.doomLevel>0
        endmethod
        
        // Disarm (Melee)
        private integer disarmMeleeLevel
        private integer disarmRangeLevel
        method addDisarmMelee takes nothing returns nothing
            set this.disarmMeleeLevel=this.disarmMeleeLevel+1
            if this.disarmMeleeLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                if this.disarmRangeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_RANGE)
                    call IssueTargetOrderById(CASTER_DISARM_BOTH,OID_DISARM,this.unit)
                else
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                endif
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method addDisarmRange takes nothing returns nothing
            set this.disarmRangeLevel=this.disarmRangeLevel+1
            if this.disarmRangeLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                if this.disarmMeleeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_MELEE)
                    call IssueTargetOrderById(CASTER_DISARM_BOTH,OID_DISARM,this.unit)
                else
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                endif
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method addDisarm takes nothing returns nothing
            set this.disarmMeleeLevel=this.disarmMeleeLevel+1
            set this.disarmRangeLevel=this.disarmRangeLevel+1
            if this.disarmMeleeLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                if this.disarmRangeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_RANGE)
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_MELEE)
                    call IssueTargetOrderById(CASTER_DISARM_BOTH,OID_DISARM,this.unit)
                else
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                endif
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            else
                if this.disarmRangeLevel>0 then
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                endif
            endif
        endmethod
        method removeDisarmMelee takes nothing returns nothing
            set this.disarmMeleeLevel=this.disarmMeleeLevel-1
            if this.disarmMeleeLevel==0 then
                if this.disarmRangeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                else
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_MELEE)
                endif
            endif
        endmethod
        method removeDisarmRange takes nothing returns nothing
            set this.disarmRangeLevel=this.disarmRangeLevel-1
            if this.disarmRangeLevel==0 then
                if this.disarmMeleeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                else
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_RANGE)
                endif
            endif
        endmethod
        method removeDisarm takes nothing returns nothing
            set this.disarmMeleeLevel=this.disarmMeleeLevel-1
            set this.disarmRangeLevel=this.disarmRangeLevel-1
            if this.disarmMeleeLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                call UnitRemoveAbility(this.unit,BUFF_DISARM_MELEE)
                if this.disarmRangeLevel>0 then
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                endif
            elseif this.disarmRangeLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                call UnitRemoveAbility(this.unit,BUFF_DISARM_RANGE)
                if this.disarmMeleeLevel>0 then
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                endif
            endif
        endmethod
        method isDisarmedMelee takes nothing returns boolean
            return this.disarmMeleeLevel>0
        endmethod
        method isDisarmedRange takes nothing returns boolean
            return this.disarmRangeLevel>0
        endmethod
        method isDisarmed takes nothing returns boolean
            return this.disarmMeleeLevel>0 and this.disarmRangeLevel>0
        endmethod
        
        // Immobolise
        private integer immoboliseLevel
        method addImmobolise takes nothing returns nothing
            set this.immoboliseLevel=this.immoboliseLevel+1
            if this.immoboliseLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_IMMOBOLISE,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeImmobolise takes nothing returns nothing
            set this.immoboliseLevel=this.immoboliseLevel-1
            if this.immoboliseLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_IMMOBOLISE_GROUND)
                call UnitRemoveAbility(this.unit,BUFF_IMMOBOLISE_AIR)
            endif
        endmethod
        method isImmobolised takes nothing returns boolean
            return this.immoboliseLevel>0
        endmethod
        
        // Invisibility
        private integer invisibleLevel
        method addInvisible takes nothing returns nothing
            set this.invisibleLevel=this.invisibleLevel+1
            if this.invisibleLevel>0 then
                call UnitAddAbility(this.unit,ABIL_INVISIBLE)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_INVISIBLE)
            endif
        endmethod
        method removeInvisible takes nothing returns nothing
            set this.invisibleLevel=this.invisibleLevel-1
            if this.invisibleLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_INVISIBLE)
                call UnitRemoveAbility(this.unit,ABIL_INVISIBLE)
            endif
        endmethod
        method isInvisible takes nothing returns boolean
            return this.invisibleLevel>0
        endmethod
        
        // Ghost
        private integer ghostLevel
        method addGhost takes nothing returns nothing
            set this.ghostLevel=this.ghostLevel+1
            if this.ghostLevel>0 then
                call UnitAddAbility(this.unit,ABIL_GHOST)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_GHOST)
            endif
        endmethod
        method removeGhost takes nothing returns nothing
            set this.ghostLevel=this.ghostLevel-1
            if this.ghostLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_GHOST)
                call UnitRemoveAbility(this.unit,ABIL_GHOST)
            endif
        endmethod
        method isGhost takes nothing returns boolean
            return this.ghostLevel>0
        endmethod
        
        // Invulnerability
        private integer invulnerableLevel
        method addInvulnerable takes nothing returns nothing
            set this.invulnerableLevel=this.invulnerableLevel+1
            if this.invulnerableLevel>0 then
                call SetUnitInvulnerable(this.unit,true)
            endif
        endmethod
        method removeInvulnerable takes nothing returns nothing
            set this.invulnerableLevel=this.invulnerableLevel-1
            if this.invulnerableLevel==0 then
                call SetUnitInvulnerable(this.unit,false)
            endif
        endmethod
        method isInvulnerable takes nothing returns boolean
            return this.invulnerableLevel>0
        endmethod
        
        // Spell Immunity
        private integer immunityLevel
        method addImmunity takes nothing returns nothing
            set this.immunityLevel=this.immunityLevel+1
            if this.immunityLevel>0 then
                call UnitAddAbility(this.unit,ABIL_IMMUNITY)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_IMMUNITY)
            endif
        endmethod
        method removeImmunity takes nothing returns nothing
            set this.immunityLevel=this.immunityLevel-1
            if this.immunityLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_IMMUNITY)
                call UnitRemoveAbility(this.unit,ABIL_IMMUNITY)
            endif
        endmethod
        method isImmune takes nothing returns boolean
            return this.immunityLevel>0
        endmethod
        
        // Pause
        private integer pauseLevel
        method addPause takes nothing returns nothing
            set this.pauseLevel=this.pauseLevel+1
            if this.pauseLevel>0 then
                call PauseUnit(this.unit,true)
            endif
        endmethod
        method removePause takes nothing returns nothing
            set this.pauseLevel=this.pauseLevel-1
            if this.pauseLevel==0 then
                call PauseUnit(this.unit,false)
            endif
        endmethod
        method isPaused takes nothing returns boolean
            return this.pauseLevel>0
        endmethod
        
        // Hide
        private integer hideLevel
        method addHide takes nothing returns nothing
            set this.hideLevel=this.hideLevel+1
            if this.hideLevel>0 then
                call ShowUnit(this.unit,false)
            endif
        endmethod
        method removeHide takes nothing returns nothing
            set this.hideLevel=this.hideLevel-1
            if this.hideLevel==0 then
                call ShowUnit(this.unit,true)
            endif
        endmethod
        method isHidden takes nothing returns boolean
            return this.hideLevel>0
        endmethod
        
        // Unpath
        private integer unpathLevel
        method addUnpath takes nothing returns nothing
            set this.unpathLevel=this.unpathLevel+1
            if this.unpathLevel>0 then
                call SetUnitPathing(this.unit,false)
            endif
        endmethod
        method removeUnpath takes nothing returns nothing
            set this.unpathLevel=this.unpathLevel-1
            if this.unpathLevel==0 then
                call SetUnitPathing(this.unit,true)
            endif
        endmethod
        method isUnpathed takes nothing returns boolean
            return this.unpathLevel>0
        endmethod
        
        // Hex
        private integer hexLevel
        method addHex takes nothing returns nothing
            set this.hexLevel=this.hexLevel+1
            if this.hexLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_HEX,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeHex takes nothing returns nothing
            set this.hexLevel=this.hexLevel-1
            if this.hexLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_HEX)
            endif
        endmethod
        method isHexed takes nothing returns boolean
            return this.hexLevel>0
        endmethod
        
        // Locust
        private integer locustLevel
        method addLocust takes nothing returns nothing
            set this.locustLevel=this.locustLevel+1
            if this.locustLevel>0 then
                call UnitAddAbility(this.unit,'Aloc')
                call UnitMakeAbilityPermanent(this.unit,true,'Aloc')
            endif
        endmethod
        method removeLocust takes nothing returns nothing
            set this.locustLevel=this.locustLevel-1
            if this.locustLevel==0 then
                call ShowUnit(this.unit,false)
                call UnitMakeAbilityPermanent(this.unit,false,'Aloc')
                call UnitRemoveAbility(this.unit,'Aloc')
                call ShowUnit(this.unit,true)
                call UnitAddAbility(this.unit,ABIL_UNLOCUST)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_UNLOCUST)
                call IssueImmediateOrderById(this.unit,OID_UNLOCUST)
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_UNLOCUST)
                call UnitRemoveAbility(this.unit,ABIL_UNLOCUST)
            endif
        endmethod
        method isLocust takes nothing returns boolean
            return this.locustLevel>0
        endmethod
        
        // Never Miss
        private integer neverMissLevel
        method addNeverMiss takes nothing returns nothing
            set this.neverMissLevel=this.neverMissLevel+1
            if this.neverMissLevel>0 then
                call UnitAddAbility(this.unit,ABIL_NEVER_MISS)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_NEVER_MISS)
            endif
        endmethod
        method removeNeverMiss takes nothing returns nothing
            set this.neverMissLevel=this.neverMissLevel-1
            if this.neverMissLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_NEVER_MISS)
                call UnitRemoveAbility(this.unit,ABIL_NEVER_MISS)
            endif
        endmethod
        method isNeverMiss takes nothing returns boolean
            return this.neverMissLevel>0
        endmethod
        
        // Always Miss
        private integer alwaysMissLevel
        method addAlwaysMiss takes nothing returns nothing
            set this.alwaysMissLevel=this.alwaysMissLevel+1
            if this.alwaysMissLevel>0 then
                call UnitAddAbility(this.unit,ABIL_ALWAYS_MISS)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_ALWAYS_MISS)
            endif
        endmethod
        method removeAlwaysMiss takes nothing returns nothing
            set this.alwaysMissLevel=this.alwaysMissLevel-1
            if this.alwaysMissLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_ALWAYS_MISS)
                call UnitRemoveAbility(this.unit,ABIL_ALWAYS_MISS)
            endif
        endmethod
        method isAlwaysMiss takes nothing returns boolean
            return this.alwaysMissLevel>0
        endmethod
        
        // Untouchable
        private integer untouchableLevel
        method addUntouchable takes nothing returns nothing
            set this.untouchableLevel=this.untouchableLevel+1
            if this.untouchableLevel>0 then
                call UnitAddAbility(this.unit,ABIL_UNTOUCHABLE)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_UNTOUCHABLE)
            endif
        endmethod
        method removeUntouchable takes nothing returns nothing
            set this.untouchableLevel=this.untouchableLevel-1
            if this.untouchableLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_UNTOUCHABLE)
                call UnitRemoveAbility(this.unit,ABIL_UNTOUCHABLE)
            endif
        endmethod
        method isUntouchable takes nothing returns boolean
            return this.untouchableLevel>0
        endmethod
        
        // Banish
        private integer banishLevel
        method addBanish takes nothing returns nothing
            set this.banishLevel=this.banishLevel+1
            if this.banishLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_BANISH,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeBanish takes nothing returns nothing
            set this.banishLevel=this.banishLevel-1
            if this.banishLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_BANISH)
            endif
        endmethod
        method isBanished takes nothing returns boolean
            return this.banishLevel>0
        endmethod
        
        // Phase
        private integer phaseLevel
        method addPhase takes nothing returns nothing
            set this.phaseLevel=this.phaseLevel+1
            if this.phaseLevel>0 then
                call SetPlayerAbilityAvailable(GetOwningPlayer(this.unit),ABIL_PHASE,true)
                if UnitAddAbility(this.unit,ABIL_PHASE) then
                    call UnitMakeAbilityPermanent(this.unit,true,ABIL_PHASE)
                endif
                call IssueImmediateOrderById(this.unit,OID_PHASE)
                call SetPlayerAbilityAvailable(GetOwningPlayer(this.unit),ABIL_PHASE,false)
            endif
        endmethod
        method removePhase takes nothing returns nothing
            set this.phaseLevel=this.phaseLevel-1
            if this.phaseLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_PHASE)
            endif
        endmethod
        method isPhased takes nothing returns boolean
            return this.phaseLevel>0
        endmethod
        /*
        // Double Attack
        private integer doubleAttackLevel
        method addDoubleAttack takes nothing returns nothing
            set this.doubleAttackLevel=this.doubleAttackLevel+1
            if this.doubleAttackLevel>0 then
                call UnitAddAbility(this.unit,ABIL_DOUBLE_ATTACK)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_DOUBLE_ATTACK)
            endif
        endmethod
        method removeDoubleAttack takes nothing returns nothing
            set this.doubleAttackLevel=this.doubleAttackLevel-1
            if this.doubleAttackLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_DOUBLE_ATTACK)
                call UnitRemoveAbility(this.unit,ABIL_DOUBLE_ATTACK)
            endif
        endmethod
        method isDoubleAttack takes nothing returns boolean
            return this.doubleAttackLevel>0
        endmethod
        */
        // Resistant Skin
        private integer resistantSkinLevel
        method addResistantSkin takes nothing returns nothing
            set this.resistantSkinLevel=this.resistantSkinLevel+1
            if this.resistantSkinLevel>0 then
                call UnitAddAbility(this.unit,ABIL_RESISTANT_SKIN)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_RESISTANT_SKIN)
            endif
        endmethod
        method removeResistantSkin takes nothing returns nothing
            set this.resistantSkinLevel=this.resistantSkinLevel-1
            if this.resistantSkinLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_RESISTANT_SKIN)
                call UnitRemoveAbility(this.unit,ABIL_RESISTANT_SKIN)
            endif
        endmethod
        method isResistantSkin takes nothing returns boolean
            return this.resistantSkinLevel>0
        endmethod
        
        // Reflect Piercing
        private integer reflectPiercingLevel
        method addReflectPiercing takes nothing returns nothing
            set this.reflectPiercingLevel=this.reflectPiercingLevel+1
            if this.reflectPiercingLevel>0 then
                call UnitAddAbility(this.unit,ABIL_REFLECT_PIERCING)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_REFLECT_PIERCING)
            endif
        endmethod
        method removeReflectPiercing takes nothing returns nothing
            set this.reflectPiercingLevel=this.reflectPiercingLevel-1
            if this.reflectPiercingLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_REFLECT_PIERCING)
                call UnitRemoveAbility(this.unit,ABIL_REFLECT_PIERCING)
            endif
        endmethod
        method isReflectPiercing takes nothing returns boolean
            return this.reflectPiercingLevel>0
        endmethod
        
        
        ////////////////////
        // Status Bonuses //
        ////////////////////
        private static method setBonus takes unit u, integer abil, integer levels, integer amount returns nothing
            local boolean addNeg=false
            if amount<0 then
                set addNeg=true
                set amount=amount+thistype.twoPow[levels]
            else
                call UnitMakeAbilityPermanent(u,false,abil)
                call UnitRemoveAbility(u,abil)
            endif
            
            set abil=abil+levels
            set levels=thistype.twoPow[levels]
            loop
                set levels=levels/2
                
                if amount>=levels then
                    call UnitAddAbility(u,abil)
                    call UnitMakeAbilityPermanent(u,true,abil)
                    set amount=amount-levels
                else
                    call UnitMakeAbilityPermanent(u,false,abil)
                    call UnitRemoveAbility(u,abil)
                endif
                
                set abil=abil-1
                exitwhen levels==1
            endloop
            
            if addNeg then
                call UnitAddAbility(u,abil)
                call UnitMakeAbilityPermanent(u,true,abil)
            endif
        endmethod
        
        private integer armorBonus
        method modArmorBonus takes integer amount returns nothing
            set this.armorBonus=this.armorBonus+amount
            debug if this.armorBonus>=thistype.twoPow[LEVELS_ARMOR] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modArmorBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_ARMOR])+".")
            debug endif
            debug if this.armorBonus<-thistype.twoPow[LEVELS_ARMOR] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modArmorBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_ARMOR])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_ARMOR,LEVELS_ARMOR,this.armorBonus)
        endmethod
        method getArmorBonus takes nothing returns integer
            return this.armorBonus
        endmethod
        
        private integer damageBonus
        method modDamageBonus takes integer amount returns nothing
            set this.damageBonus=this.damageBonus+amount
            debug if this.damageBonus>=thistype.twoPow[LEVELS_DAMAGE] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modDamageBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_DAMAGE])+".")
            debug endif
            debug if this.damageBonus<-thistype.twoPow[LEVELS_DAMAGE] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modDamageBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_DAMAGE])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_DAMAGE,LEVELS_DAMAGE,this.damageBonus)
        endmethod
        method getDamageBonus takes nothing returns integer
            return this.damageBonus
        endmethod
        
        private integer strBonus
        method modStrBonus takes integer amount returns nothing
            set this.strBonus=this.strBonus+amount
            debug if this.strBonus>=thistype.twoPow[LEVELS_STR] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modStrBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_STR])+".")
            debug endif
            debug if this.strBonus<-thistype.twoPow[LEVELS_STR] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modStrBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_STR])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_STR,LEVELS_STR,this.strBonus)
        endmethod
        method getStrBonus takes nothing returns integer
            return this.strBonus
        endmethod
        
        private integer agiBonus
        method modAgiBonus takes integer amount returns nothing
            set this.agiBonus=this.agiBonus+amount
            debug if this.agiBonus>=thistype.twoPow[LEVELS_AGI] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modAgiBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_AGI])+".")
            debug endif
            debug if this.agiBonus<-thistype.twoPow[LEVELS_AGI] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modAgiBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_AGI])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_AGI,LEVELS_AGI,this.agiBonus)
        endmethod
        method getAgiBonus takes nothing returns integer
            return this.agiBonus
        endmethod
        
        private integer intBonus
        method modIntBonus takes integer amount returns nothing
            set this.intBonus=this.intBonus+amount
            debug if this.intBonus>=thistype.twoPow[LEVELS_INT] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modIntBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_INT])+".")
            debug endif
            debug if this.intBonus<-thistype.twoPow[LEVELS_INT] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modIntBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_INT])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_INT,LEVELS_INT,this.intBonus)
        endmethod
        method getIntBonus takes nothing returns integer
            return this.intBonus
        endmethod
        
        private integer attackSpeedBonus
        method modAttackSpeedBonus takes integer amount returns nothing
            set this.attackSpeedBonus=this.attackSpeedBonus+amount
            debug if this.attackSpeedBonus>=thistype.twoPow[LEVELS_ATTACK_SPEED] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modAttackSpeedBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_ATTACK_SPEED])+".")
            debug endif
            debug if this.attackSpeedBonus<-thistype.twoPow[LEVELS_ATTACK_SPEED] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modAttackSpeedBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_ATTACK_SPEED])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_ATTACK_SPEED,LEVELS_ATTACK_SPEED,this.attackSpeedBonus)
        endmethod
        method getAttackSpeedBonus takes nothing returns integer
            return this.attackSpeedBonus
        endmethod
        
        private integer healthBonus
        method modHealthBonus takes integer amount returns nothing
            set this.healthBonus=this.healthBonus+amount
            debug if this.healthBonus>=thistype.twoPow[LEVELS_HEALTH] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modHealthBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_HEALTH])+".")
            debug endif
            debug if this.healthBonus<-thistype.twoPow[LEVELS_HEALTH] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modHealthBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_HEALTH])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_HEALTH,LEVELS_HEALTH,this.healthBonus)
        endmethod
        method getHealthBonus takes nothing returns integer
            return this.healthBonus
        endmethod
        
        private integer manaBonus
        method modManaBonus takes integer amount returns nothing
            set this.manaBonus=this.manaBonus+amount
            debug if this.manaBonus>=thistype.twoPow[LEVELS_MANA] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modManaBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_MANA])+".")
            debug endif
            debug if this.manaBonus<-thistype.twoPow[LEVELS_MANA] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modManaBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_MANA])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_MANA,LEVELS_MANA,this.manaBonus)
        endmethod
        method getManaBonus takes nothing returns integer
            return this.manaBonus
        endmethod
        
        // Periodic bonuses
        private static unit updateUnit
        
        private static group healthRegenGroup=CreateGroup()
        private static method healthRegenPeriodic takes nothing returns nothing
            set thistype.updateUnit=GetEnumUnit()
            if UnitAlive(thistype.updateUnit) then
                call SetWidgetLife(thistype.updateUnit,GetWidgetLife(thistype.updateUnit)+thistype[thistype.updateUnit].healthRegenBonus)
            endif
        endmethod
        private real healthRegenBonus
        method modHealthRegenBonus takes real amount returns nothing
            set this.healthRegenBonus=this.healthRegenBonus+amount*PERIOD
            if this.healthRegenBonus==0 then
                call GroupRemoveUnit(thistype.healthRegenGroup,this.unit)
            else
                call GroupAddUnit(thistype.healthRegenGroup,this.unit)
            endif
        endmethod
        method getHealthRegenBonus takes nothing returns real
            return this.healthRegenBonus/PERIOD
        endmethod
        
        private static group manaRegenGroup=CreateGroup()
        private static method manaRegenPeriodic takes nothing returns nothing
            set thistype.updateUnit=GetEnumUnit()
            if UnitAlive(thistype.updateUnit) then
                call SetUnitState(thistype.updateUnit,UNIT_STATE_MANA,GetUnitState(thistype.updateUnit,UNIT_STATE_MANA)+thistype[thistype.updateUnit].manaRegenBonus)
            endif
        endmethod
        private real manaRegenBonus
        method modManaRegenBonus takes real amount returns nothing
            set this.manaRegenBonus=this.manaRegenBonus+amount*PERIOD
            if this.manaRegenBonus==0 then
                call GroupRemoveUnit(thistype.manaRegenGroup,this.unit)
            else
                call GroupAddUnit(thistype.manaRegenGroup,this.unit)
            endif
        endmethod
        method getManaRegenBonus takes nothing returns real
            return this.manaRegenBonus/PERIOD
        endmethod
        
        private static group healthRegenPercentGroup=CreateGroup()
        private static method healthRegenPercentPeriodic takes nothing returns nothing
            set thistype.updateUnit=GetEnumUnit()
            if UnitAlive(thistype.updateUnit) then
                call SetWidgetLife(thistype.updateUnit,GetWidgetLife(thistype.updateUnit)+GetUnitState(thistype.updateUnit,UNIT_STATE_MAX_LIFE)*thistype[thistype.updateUnit].healthRegenPercentBonus)
            endif
        endmethod
        private real healthRegenPercentBonus
        method modHealthRegenPercentBonus takes real amount returns nothing
            set this.healthRegenPercentBonus=this.healthRegenPercentBonus+amount*PERIOD*0.01
            if this.healthRegenPercentBonus==0 then
                call GroupRemoveUnit(thistype.healthRegenPercentGroup,this.unit)
            else
                call GroupAddUnit(thistype.healthRegenPercentGroup,this.unit)
            endif
        endmethod
        method getHealthRegenPercentBonus takes nothing returns real
            return this.healthRegenPercentBonus/PERIOD/0.01
        endmethod
        
        private static group manaRegenPercentGroup=CreateGroup()
        private static method manaRegenPercentPeriodic takes nothing returns nothing
            set thistype.updateUnit=GetEnumUnit()
            if UnitAlive(thistype.updateUnit) then
                call SetUnitState(thistype.updateUnit,UNIT_STATE_MANA,GetUnitState(thistype.updateUnit,UNIT_STATE_MANA)+GetUnitState(thistype.updateUnit,UNIT_STATE_MAX_MANA)*thistype[thistype.updateUnit].manaRegenPercentBonus)
            endif
        endmethod
        private real manaRegenPercentBonus
        method modManaRegenPercentBonus takes real amount returns nothing
            set this.manaRegenPercentBonus=this.manaRegenPercentBonus+amount*PERIOD*0.01
            if this.manaRegenPercentBonus==0 then
                call GroupRemoveUnit(thistype.manaRegenPercentGroup,this.unit)
            else
                call GroupAddUnit(thistype.manaRegenPercentGroup,this.unit)
            endif
        endmethod
        method getManaRegenPercentBonus takes nothing returns real
            return this.manaRegenPercentBonus/PERIOD/0.01
        endmethod
        
        // Links periodic effects.
        private static method periodicLink takes nothing returns nothing
            call ForGroup(thistype.healthRegenGroup,function thistype.healthRegenPeriodic)
            call ForGroup(thistype.manaRegenGroup,function thistype.manaRegenPeriodic)
            call ForGroup(thistype.healthRegenPercentGroup,function thistype.healthRegenPercentPeriodic)
            call ForGroup(thistype.manaRegenPercentGroup,function thistype.manaRegenPercentPeriodic)
        endmethod
        implement StaticPeriodic
        
        ////////////////////
        // Movement Speed //
        ////////////////////
        
        private real moveSpeedBonus
        private real moveSpeedPercentBonus
        private real x
        private real y
        private static real updateUnitX
        private static real updateUnitY
        private static real xInc
        private static real yInc
        private static real updateDist
        private method periodic takes nothing returns nothing
            set thistype.updateUnit=this.unit
            set thistype.updateUnitX=GetUnitX(thistype.updateUnit)
            set thistype.updateUnitY=GetUnitY(thistype.updateUnit)
            set thistype.xInc=thistype.updateUnitX-this.x
            set thistype.yInc=thistype.updateUnitY-this.y
            set thistype.updateDist=SquareRoot(thistype.xInc*thistype.xInc+thistype.yInc*thistype.yInc)
            if thistype.updateDist>0 then
                if UnitAlive(thistype.updateUnit) and this.disableLevel<=0 and this.stunLevel<=0 and this.pauseLevel<=0 and this.immoboliseLevel<=0 and GetUnitMoveSpeed(thistype.updateUnit)>0 then
                    if this.moveSpeedPercentBonus!=0.0 then
                        set thistype.updateUnitX=thistype.updateUnitX+thistype.xInc*this.moveSpeedPercentBonus
                        set thistype.updateUnitY=thistype.updateUnitY+thistype.yInc*this.moveSpeedPercentBonus
                    endif
                    if this.moveSpeedBonus!=0.0 then
                        set thistype.updateDist=this.moveSpeedBonus/thistype.updateDist
                        set thistype.updateUnitX=thistype.updateUnitX+thistype.xInc*thistype.updateDist
                        set thistype.updateUnitY=thistype.updateUnitY+thistype.yInc*thistype.updateDist
                    endif
                    call SetUnitX(thistype.updateUnit,thistype.updateUnitX)
                    call SetUnitY(thistype.updateUnit,thistype.updateUnitY)
                endif
            endif
            set this.x=thistype.updateUnitX
            set this.y=thistype.updateUnitY
        endmethod
        implement T32xs
        method modMoveSpeedBonus takes real amount returns nothing
            set this.moveSpeedBonus=this.moveSpeedBonus+amount*T32_PERIOD
            if this.moveSpeedBonus==0 and this.moveSpeedPercentBonus==0 then
                call this.stopPeriodic()
            else
                set this.x=GetUnitX(this.unit)
                set this.y=GetUnitY(this.unit)
                call this.startPeriodic()
            endif
        endmethod
        method getMoveSpeedBonus takes nothing returns real
            return this.moveSpeedBonus/T32_PERIOD
        endmethod
        method modMoveSpeedPercentBonus takes real amount returns nothing
            set this.moveSpeedPercentBonus=this.moveSpeedPercentBonus+amount*0.01
            if this.moveSpeedBonus==0 and this.moveSpeedPercentBonus==0 then
                call this.stopPeriodic()
            else
                set this.x=GetUnitX(this.unit)
                set this.y=GetUnitY(this.unit)
                call this.startPeriodic()
            endif
        endmethod
        method getMoveSpeedPercentBonus takes nothing returns real
            return this.moveSpeedPercentBonus/0.01
        endmethod
    endstruct
endlibrary

library Stun uses Status // Deprecated. Backwards compatability with "Stun" system.
    function AddStun takes unit whichUnit returns nothing
        call Status[whichUnit].addStun()
    endfunction
    function RemoveStun takes unit whichUnit returns nothing
        call Status[whichUnit].removeStun()
    endfunction
    function Stun_IsUnitStunned takes unit whichUnit returns boolean
        return Status[whichUnit].isStunned()
    endfunction
endlibrary
 
Chào tất cả mọi người :)
Mình đang làm đoạn code spawn creep ở một nhà chính nhất định, mình không rõ về việc xài Group sao cho không leak, ai có thể check leak và sửa dùm mình phần leak trong đoạn code sau (nếu có) được không ? Cảm ơn rất nhiều:

Đây là đoạn Library giúp đỡ spawn, nói chung là không cần check vì nó không leak, mình copy ra để dễ hiểu code:
Mã:
function spawnHelper takes integer unitId returns nothing
    local unit p = GetEnumUnit()
    local real x = GetUnitX(p)
    local real y = GetUnitY(p)
    local unit s = CreateUnit( GetOwningPlayer(GetEnumUnit()), unitId, x, y, bj_UNIT_FACING)
    set s = null
    set p = null
endfunction

Đây là đoạn code spawn unit, cần được check leak:
Mã:
scope spawnfootmen

globals
    private integer base = 'hbar' // base buiding
    private integer footmen = 'hfoo' // footmen
endglobals

private function Spawn takes nothing returns nothing
    call spawnHelper(footmen)
endfunction

private function Cond takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'hbar' and GetWidgetLife(GetFilterUnit()) > 0.405
endfunction

private function Acts takes nothing returns nothing
    local group g = CreateGroup()
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function Cond))

//    local group g = GetUnitsInRectMatching(bj_mapInitialPlayableArea, Condition(function Cond))
//call GroupEnumUnitsOfType(g,"Barrack",Filter(function True))

//    local group g = GetUnitsOfTypeIdAll(base)
    call ForGroup(g, function Spawn)
    call GroupClear(g)
    call DestroyGroup(g)
//    call DestroyBoolExpr(Cond)
//    return g
    set g = null
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger( )
    
    call TriggerRegisterTimerEvent( trig, 0.50, true)
    call TriggerAddAction( trig, function Acts )
    
    set trig = null
endfunction

endscope

Đoạn " call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function Cond))" mình không rõ là leak hay không ?
 
AI chỉ cho em:
1. khi hero team 1 chết sẽ hồi sinh tại vị trí bên này (region) còn hero ở team 2 chết sẽ hôi sinh tại vị trí bên kia (region)
2. Khi chọn hero, hero đó sẽ tự có 1 skill mà ko cần phải tăng, nó hiện thị ở ô bên cạnh Attribute Bonus
 
Chỉnh sửa cuối:
cũng vẫn chỉ là metamphosis thui bạn , con biến hình chuyển skill khác là dc

thế chỉnh làm sao cho nó ra hình con khác mà không phải là demon form

Mọi người chỉ mình chỉnh làm sao để hẻo lên mổi cấp lên bao nhiêu Agi, bao nhiều Strenght, bao nhiêu intel tự mình quyết định dc ko
 
Chò mình hỏi cách ép các system như bên dưới!Theo mình hiểu thì copy tất cả text rồi sau đó save và mở lại, cái runtextmacro Status__CreateAbilities() sẽ tự tạo cho mình các abi để sử dụng phải ko? hay mình phải copy các object trước?Mình làm theo hướng dẫn như thế nhưng save map ko đc!
Mã:
//
//      ___ _____ _ _____ _   _ ___ 
//     / __|_   _/_\_   _| | | / __|
//     \__ \ | |/ _ \| | | |_| \__ \    By Jesus4Lyf.
//     |___/ |_/_/ \_\_| \____/|___/          v 1.3.0
//
//      What is Status?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Status allows you to apply stuns, silences, disable attacks and much
//          more. Status effects based off dummy casted spells are applied 0.0
//          seconds after the "add" method is called. Status aims to commoditise
//          unit effects in WC3.
//
//      Restrictions
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Disarming spell immune units is not possible. Some status effects will
//          not apply to invulnerable units, namely those which are dummy casted.
//
//      How to implement?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Create a new trigger called Status, go to 'Edit -> Convert to
//          Custom Text', and replace everything that's there with this script.
//
//          Save the map, close it, reopen it, and then delete the "!" from the
//          FAR left side of the next line (so "runtextmacro" will line up with this line):
  //!       runtextmacro Status__CreateAbilities()
//
//          Go to the object editor, and select abilities. Go to Special > Heroes,
//          and select Disarm (Both). Change Data - Attacks Prevented to Melee, Ranged.
//          For Disarm (Melee), change Attacks Prevented to Melee. For Disarm (Range),
//          change Attacks Prevented to Ranged. Object merger has a bug that does not
//          allow setting this field automatically.
//
//      Methods:
//     ¯¯¯¯¯¯¯¯¯¯
//          Statuses (short list):
//              - Disable (addDisable, removeDisable, isDisabled)
//              - Stun (addStun, removeStun, isStunned)
//              - Silence (addSilence, removeSilence, isSilenced)
//              - Doom (addDoom, removeDoom, isDoomed)
//              - DisarmMelee (addDisarmMelee, removeDisarmMelee, isDisarmedMelee)
//              - DisarmRange (addDisarmRange, removeDisarmRange, isDisarmedRange)
//              - Disarm (addDisarm, removeDisarm, isDisarmed) // this is both Melee AND Ranged.
//              - Immobolise (addImmobolise, removeImmobolise, isImmobolised)
//              - Invisible (addInvisible, removeInvisible, isInvisible)
//              - Ghost (addGhost, removeGhost, isGhost)
//              - Invulnerable (addInvulnerable, removeInvulnerable, isInvulnerable)
//              - Immunity (addImmunity, removeImmunity, isImmune)
//              - Pause (addPause, removePause, isPaused)
//              - Hide (addHide, removeHide, isHidden)
//              - Unpath (addUnpath, removeUnpath, isUnpathed)
//              - Hex (addHex, removeHex, isHexed)
//              - Locust (addLocust, removeLocust, isLocust) // does not remove correctly for flying units, use with caution.
//              - NeverMiss (addNeverMiss, removeNeverMiss, isNeverMiss)
//              - AlwaysMiss (addAlwaysMiss, removeAlwaysMiss, isAlwaysMiss)
//              - Untouchable (addUntouchable, removeUntouchable, isUntouchable) // 100% evasion
//              - Banish (addBanish, removeBanish, isBanished)
//              - Phase (addPhase, removePhase, isPhased) // clashes with windwalk, interrupts current order
//              - ResistantSkin (addResistantSkin, removeResistantSkin, isResistantSkin)
//              - ReflectPiercing (addReflectPiercing, removeReflectPiercing, isReflectPiercing)
//
//          Bonuses (short list):
//              - ArmorBonus (modArmorBonus, getArmorBonus)
//              - DamageBonus (modDamageBonus, getDamageBonus)
//              - StrBonus (modStrBonus, getStrBonus)
//              - AgiBonus (modAgiBonus, getAgiBonus)
//              - IntBonus (modIntBonus, getIntBonus)
//              - AttackSpeedBonus (modAttackSpeedBonus, getAttackSpeedBonus)
//              - Health (modHealthBonus, getHealthBonus)
//              - Mana (modManaBonus, getManaBonus)'
//              - HealthRegen (modHealthRegenBonus, getHealthRegenBonus)
//              - HealthRegenPercent (modHealthRegenPercentBonus, getHealthRegenPercentBonus) // percent of max
//              - ManaRegen (modManaRegenBonus, getManaRegenBonus)
//              - ManaRegenPercent (modManaRegenPercentBonus, getManaRegenPercentBonus) // percent of max
//              - MoveSpeed (modMoveSpeedBonus, getMoveSpeedBonus)
//              - MoveSpeedPercent (modMoveSpeedPercentBonus, getMoveSpeedPercentBonus) // percent of current move speed (after normal bonuses).
//
//      How to Use:
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Statuses:
//              Status[unit].add?()
//                  - Adds the status effect to the unit.
//                  - This does not add any animation.
//              Status[unit].remove?()
//                  - Removes the status effect added with .add?().
//                  - Will not actually remove it until all added instances are removed.
//              Status[unit].is?() --> boolean
//                  - Checks to see whether or not a unit has a status effect applied.
//
//          Bonuses:
//              Status[unit].mod?(amount)
//                  - Modifies the bonus by the amount given.
//                  - Use a negative value to reverse a bonus.
//                  - Supports giving negative of a bonus.
//              Status[unit].get?()
//                  - Gets the curret total amount for a given bonus.
//
//      Thanks:
//     ¯¯¯¯¯¯¯¯¯
//          - Weep: for suggesting that making the ability an ultimate hero ability
//            would allow it to stun magic immune units, and suggesting a simpler
//            target allowance for the ability.
//
//          - 13lade619: for noticing that the PreloadModule was not actually
//            implemented, causing first use lag.
//
library Status uses AIDS, DummyCaster, T32
    globals
        private constant real PERIOD=0.1 // for regen effects.
        private constant player DUMMY_CASTER_OWNER=Player(PLAYER_NEUTRAL_PASSIVE)
        private constant boolean PERMENANTLY_REVEAL=true // reveal all units always, or only during dummy spells
        
        // To change these, change them also in the externalblock before executing it.
        private constant integer ABIL_STUN='A500'
        private constant integer ABIL_SILENCE='A501'
        private constant integer ABIL_DISARM_BOTH='A502'
        private constant integer ABIL_DISARM_MELEE='A503'
        private constant integer ABIL_DISARM_RANGE='A504'
        private constant integer ABIL_IMMOBOLISE='A505'
        private constant integer ABIL_INVISIBLE='A507'
        private constant integer ABIL_GHOST='A508'
        private constant integer ABIL_DOOM='A509'
        private constant integer ABIL_IMMUNITY='A50B'
        private constant integer ABIL_HEX='A50C'
        private constant integer ABIL_UNLOCUST='A50D'
        private constant integer ABIL_NEVER_MISS='A50F'
        private constant integer ABIL_ALWAYS_MISS='A50H'
        private constant integer ABIL_UNTOUCHABLE='A50J'
        private constant integer ABIL_BANISH='A50K'
        private constant integer ABIL_PHASE='A50L'
        //private constant integer ABIL_DOUBLE_ATTACK='A50O'
        private constant integer ABIL_RESISTANT_SKIN='A50Q'
        private constant integer ABIL_REFLECT_PIERCING='A50S'
        private constant integer ABIL_DISABLE='A50T'
        
        private constant integer ABIL_ARMOR='A5A@'
        private constant integer ABIL_DAMAGE='A5B@'
        private constant integer ABIL_STR='A5C@'
        private constant integer ABIL_AGI='A5D@'
        private constant integer ABIL_INT='A5E@'
        private constant integer ABIL_ATTACK_SPEED='A5F@'
        private constant integer ABIL_HEALTH='A5G@'
        private constant integer ABIL_MANA='A5H@'
        
        private constant integer LEVELS_ARMOR=10
        private constant integer LEVELS_DAMAGE=15
        private constant integer LEVELS_STR=10
        private constant integer LEVELS_AGI=10
        private constant integer LEVELS_INT=10
        private constant integer LEVELS_ATTACK_SPEED=9
        private constant integer LEVELS_HEALTH=20
        private constant integer LEVELS_MANA=20
        
        // To change these, change them also in the externalblock before executing it.
        private constant integer BUFF_STUN='B500'
        private constant integer BUFF_SILENCE='B501'
        private constant integer BUFF_DOOM='B509'
        private constant integer BUFF_DISARM_MELEE='B503'
        private constant integer BUFF_DISARM_RANGE='B504'
        private constant integer BUFF_DISARM_BOTH='B502'
        private constant integer BUFF_IMMOBOLISE_GROUND='B505'
        private constant integer BUFF_IMMOBOLISE_AIR='B506'
        private constant integer BUFF_HEX='B50C'
        private constant integer BUFF_BANISH='B50K'
        private constant integer BUFF_PHASE='B50L'
        private constant integer BUFF_DISABLE='B50T'
        
        private constant integer OID_STOP=851972 //stop
        private constant integer OID_STUN=852231 //firebolt
        private constant integer OID_SILENCE=852668 //soulburn
        private constant integer OID_DISARM=852585 //drunkenhaze
        private constant integer OID_IMMOBOLISE=852106 //ensnare
        private constant integer OID_DOOM=852583 //doom
        private constant integer OID_HEX=852502 //hex
        private constant integer OID_UNLOCUST=852155 //ravenform
        private constant integer OID_BANISH=852486 //banish
        private constant integer OID_PHASE=852129 //windwalk
        private constant integer OID_DISABLE=852252 //creepthunderbolt (hurlboulder)
        
        private unit CASTER_DISARM_BOTH=null
        private unit CASTER_DISARM_MELEE=null
        private unit CASTER_DISARM_RANGE=null
    endglobals
    
    native UnitAlive takes unit id returns boolean
    
    private module PreloadModule
        private static method onInit takes nothing returns nothing
            local unit u=CreateUnit(DUMMY_CASTER_OWNER,DUMMY_TYPE,0,0,0)
            local integer abil
            //! textmacro Status__PreloadBonus takes BONUS
                set abil=ABIL_$BONUS$+LEVELS_$BONUS$
                loop
                    call UnitAddAbility(u,abil)
                    exitwhen abil==ABIL_$BONUS$
                    set abil=abil-1
                endloop
            //! endtextmacro
            call UnitAddAbility(u,ABIL_INVISIBLE)
            call UnitAddAbility(u,ABIL_GHOST)
            call UnitAddAbility(u,ABIL_IMMUNITY)
            call UnitAddAbility(u,ABIL_UNLOCUST)
            call UnitAddAbility(u,ABIL_NEVER_MISS)
            call UnitAddAbility(u,ABIL_ALWAYS_MISS)
            call UnitAddAbility(u,ABIL_UNTOUCHABLE)
            call UnitAddAbility(u,ABIL_PHASE)
            //call UnitAddAbility(u,ABIL_DOUBLE_ATTACK)
            call UnitAddAbility(u,ABIL_RESISTANT_SKIN)
            call UnitAddAbility(u,ABIL_REFLECT_PIERCING)
            //! runtextmacro Status__PreloadBonus("ARMOR")
            //! runtextmacro Status__PreloadBonus("DAMAGE")
            //! runtextmacro Status__PreloadBonus("STR")
            //! runtextmacro Status__PreloadBonus("AGI")
            //! runtextmacro Status__PreloadBonus("INT")
            //! runtextmacro Status__PreloadBonus("ATTACK_SPEED")
            //! runtextmacro Status__PreloadBonus("HEALTH")
            //! runtextmacro Status__PreloadBonus("MANA")
            call KillUnit(u)
            call RemoveUnit(u)
            set u=null
        endmethod
    endmodule
    
    private module StaticPeriodic
        private static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(),PERIOD,true,function thistype.periodicLink)
        endmethod
    endmodule
    
    private module StatusInit
        private static method onInit takes nothing returns nothing
            local integer i
            //! textmacro Status__CreateAbilities
                // For reflecting piercing.
                //! externalblock extension=lua ConstantMerger $FILENAME$
                //! i setvalue("Misc","DefendDeflection","1")
                //! endexternalblock
                
                // Start externalblock
                //! externalblock extension=lua ObjectMerger $FILENAME$
                
                ////////////////////
                // Status Effects //
                ////////////////////
                
                // Stun (X500, firebolt)
                //! i setobjecttype("buffs")
                //! i createobject("BPSE","B500")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"ftip","Stunned")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"fube","This unit is stunned; it cannot move, attack or cast spells.")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ACfb","A500")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Stun")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"Htb1",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                //! i makechange(current,"abuf",1,"B500")
                //! i makechange(current,"aher",1)
                //! i makechange(current,"arlv",6)
                
                // Silence (X501, soulburn)
                //! i setobjecttype("buffs")
                //! i createobject("BNso","B501")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Silence")
                //! i makechange(current,"fube","This unit is Silenced; it cannot cast spells.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNSilence.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANso","A501")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Silence")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"Nso1",1,0)
                //! i makechange(current,"Nso3",1,0)
                //! i makechange(current,"Nso2",1,99999)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B501")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                
                // Disarm (Both) (X502, drunkenhaze)
                //! i setobjecttype("buffs")
                //! i createobject("BNdh", "B502")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Disarmed")
                //! i makechange(current,"fube","This unit is Disarmed; it cannot attack.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANdh","A502")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Disarm (Both)")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amac",0)
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"Nsi2",1,0)
                //! i makechange(current,"Nsi3",1,0)
                //! i makechange(current,"aare",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B502")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Disarm (Melee) (X503, drunkenhaze)
                //! i setobjecttype("buffs")
                //! i createobject("BNdh", "B503")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Disarmed (Melee)")
                //! i makechange(current,"fube","This unit is Disarmed; it cannot use melee attacks.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANdh","A503")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Disarm (Melee)")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amac",0)
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"Nsi2",1,0)
                //! i makechange(current,"Nsi3",1,0)
                //! i makechange(current,"aare",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B503")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Disarm (Range) (X504, drunkenhaze)
                //! i setobjecttype("buffs")
                //! i createobject("BNdh", "B504")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Disarmed (Ranged)")
                //! i makechange(current,"fube","This unit is Disarmed; it cannot use ranged attacks.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANdh","A504")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Disarm (Range)")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amac",0)
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"Nsi2",1,0)
                //! i makechange(current,"Nsi3",1,0)
                //! i makechange(current,"aare",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B504")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Entangle (X505 - X506, ensnare)
                //! i setobjecttype("buffs")
                //! i createobject("Beng","B505")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Immobilised")
                //! i makechange(current,"fube","This unit is immobilised; it cannot move or fly.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNWirtsOtherLeg.blp")
                //! i makechange(current,"ftat","")
                
                //! i createobject("Bena","B506")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftip","Immobilised")
                //! i makechange(current,"fube","This unit is immobilised; it cannot move or fly.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNWirtsOtherLeg.blp")
                //! i makechange(current,"ftat", "")
                
                //! i setobjecttype("abilities")
                //! i createobject("ACen","A505")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Immobilise")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"aher",1)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"alev",1)
                //! i makechange(current,"areq","")
                //! i makechange(current,"Ens1",1,-1)
                //! i makechange(current,"Ens2",1,-1)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B505,B506")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Invisibility (X507)
                //! i setobjecttype("abilities")
                //! i createobject("Apiv","A507")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Invisibility")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"ahdu",1,0.5)
                //! i makechange(current,"adur",1,0.5)
                
                // Ghost (X508)
                //! i setobjecttype("abilities")
                //! i createobject("Agho","A508")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Ghost")
                //! i makechange(current,"ansf","(Status System)")
                
                // Doom (X509, doom)
                //! i setobjecttype("buffs")
                //! i createobject("BNdo","B509")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftat","")
                //! i makechange(current,"fube","This unit has been stricken with Doom; it cannot cast spells.")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANdo","A509")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Doom")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"Ndo1",1,0)
                //! i makechange(current,"Ndo2",1,0)
                //! i makechange(current,"Ndo3",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B509")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Spell Immunity (X50A - X50B)
                //! i setobjecttype("abilities")
                //! i createobject("Amim","A50A")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Spell Immunity")
                //! i makechange(current,"ansf","(Status System)")
                
                //! i createobject("Aspb","A50B")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Spell Immunity")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50A")
                
                // Hex (X50C, hex)
                //! i setobjecttype("buffs")
                //! i createobject("BOhx","B50C")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"feat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("AOhx","A50C")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Hex")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"asat","")
                //! i makechange(current,"alev",1)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B50C")
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                
                // Unlocust (X50D, crowform)
                //! i setobjecttype("abilities")
                //! i createobject("Amrf","A50D")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Unlocust")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"Eme3",1,-1)
                //! i makechange(current,"Eme4",1,-1)
                //! i makechange(current,"acas",1,0)
                //! i makechange(current,"adur",1,0)
                
                // Never Miss (X50E - X50F)
                //! i setobjecttype("abilities")
                //! i createobject("ACct","A50E")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Never Miss")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"Ocr1",1,100)
                //! i makechange(current,"Ocr2",1,0)
                //! i makechange(current,"Ocr5",1,1)
                //! i makechange(current,"atar",1,"notself")
                
                //! i createobject("Aspb","A50F")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Never Miss")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50E")
                
                // Always Miss (X50G - X50H)
                //! i setobjecttype("abilities")
                //! i createobject("ACbh","A50G")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Always Miss")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"Hbh1",1,0)
                //! i makechange(current,"Hbh4",1,100)
                //! i makechange(current,"atar",1,"notself")
                
                //! i createobject("Aspb","A50H")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Always Miss")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50G")
                
                // Untouchable (X50I - X50J)
                //! i setobjecttype("abilities")
                //! i createobject("ACes","A50I")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Untouchable")
                //! i makechange(current,"ansf","(Status System)")
                
                //! i createobject("Aspb","A50J")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Untouchable")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50I")
                
                // Banish (X50K, banish)
                //! i setobjecttype("buffs")
                //! i createobject("BNdo","B50K")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"ftat","")
                //! i makechange(current,"fefl","")
                
                //! i setobjecttype("abilities")
                //! i createobject("AHbn","A50K")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Banish")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"aefs","")
                //! i makechange(current,"alev",1)
                //! i makechange(current,"arlv",6)
                //! i makechange(current,"Hbn1",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"abuf",1,"B50K")
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"notself")
                
                // Phase (X50L, windwalk)
                //! i setobjecttype("buffs")
                //! i createobject("BOwk","B50L")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"ftip","Phase")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"fube","This unit is Phasing; it can walk through other units.")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNMirrorImage.blp")
                
                //! i setobjecttype("abilities")
                //! i createobject("ANwk","A50L")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Phase")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aefs","")
                //! i makechange(current,"Owk3",1,0)
                //! i makechange(current,"Owk4",1,0)
                //! i makechange(current,"Owk2",1,0)
                //! i makechange(current,"Owk1",1,-1)
                //! i makechange(current,"abuf",1,"B50L")
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"aher",0)
                /*
                // Double Attack (X50M - X50O)
                //! i setobjecttype("abilities")
                //! i createobject("ACsa","A50M")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Double Attack")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"Hfa1",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                
                //! i createobject("AIll","A50N")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Double Attack")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"amat","")
                //! i makechange(current,"asat","")
                //! i makechange(current,"atat","")
                //! i makechange(current,"Iob2",1,100)
                //! i makechange(current,"Iob3",1,100)
                //! i makechange(current,"Iob4",1,100)
                //! i makechange(current,"Idam",1,0)
                //! i makechange(current,"Iobu",1,"A50M")
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                
                //! i createobject("Aspb","A50O")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Double Attack")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50N")
                */
                
                // Resistant Skin (X50P - X50Q)
                //! i setobjecttype("abilities")
                //! i createobject("ACrk","A50P")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Resistant Skin")
                //! i makechange(current,"ansf","(Status System)")
                
                //! i createobject("Aspb","A50Q")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Resistant Skin")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50P")
                
                // Reflect Piercing (X50R - X50S)
                //! i setobjecttype("abilities")
                //! i createobject("Aegr","A50R")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Reflect Piercing")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"Def6",1,100)
                //! i makechange(current,"Def1",1,1)
                //! i makechange(current,"Def7",1,0)
                //! i makechange(current,"Def5",1,0)
                
                //! i createobject("Aspb","A50S")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Reflect Piercing")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"spb5",1,"")
                //! i makechange(current,"spb4",1,1)
                //! i makechange(current,"spb3",1,1)
                //! i makechange(current,"spb1",1,"A50R")
                
                // Disable (X50T, creepthunderbolt (hurlboulder))
                //! i setobjecttype("buffs")
                //! i createobject("BPSE","B50T")
                //! i makechange(current,"frac","other")
                //! i makechange(current,"ftip","Disabled")
                //! i makechange(current,"fube","This unit is Disabled; it cannot do anything.")
                //! i makechange(current,"fnsf","(Status System)")
                //! i makechange(current,"fart","ReplaceableTextures\\CommandButtons\\BTNReplay-Pause.blp")
                //! i makechange(current,"ftat","")
                
                //! i setobjecttype("abilities")
                //! i createobject("ACtb","A50T")
                //! i makechange(current,"aart","")
                //! i makechange(current,"arac","other")
                //! i makechange(current,"anam","Disable")
                //! i makechange(current,"ansf","(Status System)")
                //! i makechange(current,"aani","")
                //! i makechange(current,"amat","")
                //! i makechange(current,"amsp",0)
                //! i makechange(current,"Ctb1",1,0)
                //! i makechange(current,"aran",1,99999)
                //! i makechange(current,"acdn",1,0)
                //! i makechange(current,"ahdu",1,0)
                //! i makechange(current,"adur",1,0)
                //! i makechange(current,"amcs",1,0)
                //! i makechange(current,"atar",1,"invulnerable,vulnerable")
                //! i makechange(current,"abuf",1,"B50T")
                //! i makechange(current,"aher",1)
                //! i makechange(current,"arlv",6)
                
                
                ////////////////////
                // Status Bonuses //
                ////////////////////
                //! i setobjecttype("abilities")
                
                //! i myChar={}
                //! i myChar[1]="A"
                //! i myChar[2]="B"
                //! i myChar[3]="C"
                //! i myChar[4]="D"
                //! i myChar[5]="E"
                //! i myChar[6]="F"
                //! i myChar[7]="G"
                //! i myChar[8]="H"
                //! i myChar[9]="I"
                //! i myChar[10]="J"
                //! i myChar[11]="K"
                //! i myChar[12]="L"
                //! i myChar[13]="M"
                //! i myChar[14]="N"
                //! i myChar[15]="O"
                //! i myChar[16]="P"
                //! i myChar[17]="Q"
                //! i myChar[18]="R"
                //! i myChar[19]="S"
                //! i myChar[20]="T"
                //! i myChar[21]="U"
                //! i myChar[22]="V"
                //! i myChar[23]="W"
                //! i myChar[24]="X"
                //! i myChar[25]="Y"
                //! i myChar[26]="Z"
                
                //! i myBin={}
                //! i myBin[1]=1
                //! i myBin[2]=2
                //! i myBin[3]=4
                //! i myBin[4]=8
                //! i myBin[5]=16
                //! i myBin[6]=32
                //! i myBin[7]=64
                //! i myBin[8]=128
                //! i myBin[9]=256
                //! i myBin[10]=512
                //! i myBin[11]=1024
                //! i myBin[12]=2048
                //! i myBin[13]=4096
                //! i myBin[14]=8192
                //! i myBin[15]=16384
                //! i myBin[16]=32768
                //! i myBin[17]=65536
                //! i myBin[18]=131072
                //! i myBin[19]=262144
                //! i myBin[20]=524288
                //! i myBin[21]=1048576
                //! i myBin[22]=2097152
                //! i myBin[23]=4194304
                //! i myBin[24]=8388608
                //! i myBin[25]=16777216
                //! i myBin[26]=33554432
                
                // Armor (10 = 1023 max)
                //! i for i=1,10 do
                    //! i createobject("AId1","A5A"..myChar[i])
                    //! i makechange(current,"Idef",1,myBin[i])
                    //! i makechange(current,"anam","Armor Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AId1","A5A@")
                //! i makechange(current,"Idef",1,-myBin[11])
                //! i makechange(current,"anam","Armor Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                
                // Damage (15 = 32767 max)
                //! i for i=1,15 do
                    //! i createobject("AItg","A5B"..myChar[i])
                    //! i makechange(current,"Iatt",1,myBin[i])
                    //! i makechange(current,"anam","Damage Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AItg","A5B@")
                //! i makechange(current,"Iatt",1,-myBin[16])
                //! i makechange(current,"anam","Damage Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // Str/Agi/Int (10 = 1023 max)
                //! i for i=1,10 do
                    //! i createobject("AIs1","A5C"..myChar[i])
                    //! i makechange(current,"Istr",1,myBin[i])
                    //! i makechange(current,"anam","Strength Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                    
                    //! i createobject("AIa1","A5D"..myChar[i])
                    //! i makechange(current,"Iagi",1,myBin[i])
                    //! i makechange(current,"anam","Agility Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                    
                    //! i createobject("AIi1","A5E"..myChar[i])
                    //! i makechange(current,"Iint",1,myBin[i])
                    //! i makechange(current,"anam","Intelligence Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AIs1","A5C@")
                //! i makechange(current,"Istr",1,-myBin[11])
                //! i makechange(current,"anam","Strength Bonus")
                //! i makechange(current,"ansf","(Status System)")
                //! i createobject("AIa1","A5D@")
                //! i makechange(current,"Iagi",1,-myBin[11])
                //! i makechange(current,"anam","Agility Bonus")
                //! i makechange(current,"ansf","(Status System)")
                //! i createobject("AIi1","A5E@")
                //! i makechange(current,"Iint",1,-myBin[11])
                //! i makechange(current,"anam","Intelligence Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // Attack Speed (9 = 511% max)
                //! i for i=1,9 do
                    //! i createobject("AIsx","A5F"..myChar[i])
                    //! i makechange(current,"Isx1",1,myBin[i]*0.01)
                    //! i makechange(current,"anam","Attack Speed Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AIsx","A5F@")
                //! i makechange(current,"Isx1",1,-myBin[10]*0.01)
                //! i makechange(current,"anam","Attack Speed Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // Max HP (20 = 1048575 max)
                //! i for i=1,20 do
                    //! i createobject("AIl2","A5G"..myChar[i])
                    //! i makechange(current,"Ilif",1,myBin[i])
                    //! i makechange(current,"anam","Health Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AIl2","A5G@")
                //! i makechange(current,"Ilif",1,-myBin[21])
                //! i makechange(current,"anam","Health Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // Max Mana (20 = 1048575 max)
                //! i for i=1,20 do
                    //! i createobject("AImz","A5H"..myChar[i])
                    //! i makechange(current,"Iman",1,myBin[i])
                    //! i makechange(current,"anam","Mana Bonus")
                    //! i makechange(current,"ansf","(Status System)")
                //! i end
                //! i createobject("AImz","A5H@")
                //! i makechange(current,"Iman",1,-myBin[21])
                //! i makechange(current,"anam","Mana Bonus")
                //! i makechange(current,"ansf","(Status System)")
                
                // End externalblock
                //! endexternalblock
            //! endtextmacro
            set thistype.dummyCaster=CreateUnit(DUMMY_CASTER_OWNER,DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster2=CreateUnit(DUMMY_CASTER_OWNER,DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster3=CreateUnit(DUMMY_CASTER_OWNER,DUMMY_TYPE,0,0,0)
            call UnitAddAbility(thistype.dummyCaster,ABIL_STUN)
            call UnitAddAbility(thistype.dummyCaster,ABIL_DISABLE)
            call UnitAddAbility(thistype.dummyCaster,ABIL_SILENCE)
            set CASTER_DISARM_BOTH=thistype.dummyCaster
            set CASTER_DISARM_MELEE=thistype.dummyCaster2
            set CASTER_DISARM_RANGE=thistype.dummyCaster3
            call UnitAddAbility(CASTER_DISARM_BOTH,ABIL_DISARM_BOTH)
            call UnitAddAbility(CASTER_DISARM_MELEE,ABIL_DISARM_MELEE)
            call UnitAddAbility(CASTER_DISARM_RANGE,ABIL_DISARM_RANGE)
            call UnitAddAbility(thistype.dummyCaster,ABIL_IMMOBOLISE)
            call UnitAddAbility(thistype.dummyCaster,ABIL_DOOM)
            call UnitAddAbility(thistype.dummyCaster,ABIL_HEX)
            call UnitAddAbility(thistype.dummyCaster,ABIL_BANISH)
            set i=bj_MAX_PLAYERS
            loop
                set i=i-1
                call SetPlayerAbilityAvailable(Player(i),ABIL_IMMUNITY,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_NEVER_MISS,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_ALWAYS_MISS,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_UNTOUCHABLE,false)
                //call SetPlayerAbilityAvailable(Player(i),ABIL_DOUBLE_ATTACK,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_RESISTANT_SKIN,false)
                call SetPlayerAbilityAvailable(Player(i),ABIL_REFLECT_PIERCING,false)
                exitwhen i==0
            endloop
        endmethod
    endmodule
    
    private module TwoPowArray
        readonly static integer array twoPow
        private static method onInit takes nothing returns nothing
            local integer i=0
            local integer val=1
            loop
                set thistype.twoPow[i]=val // thistype.twoPow[0]=1
                exitwhen i==30
                set i=i+1
                set val=val*2
            endloop
        endmethod
    endmodule
     struct Status extends array
        private method AIDS_onCreate takes nothing returns nothing
            static if PERMENANTLY_REVEAL then
                call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
            endif
            
            set this.disableLevel=0
            set this.stunLevel=0
            set this.silenceLevel=0
            set this.doomLevel=0
            set this.disarmMeleeLevel=0
            set this.disarmRangeLevel=0
            set this.immoboliseLevel=0
            set this.invisibleLevel=0
            set this.ghostLevel=0
            set this.invulnerableLevel=0
            set this.immunityLevel=0
            set this.pauseLevel=0
            set this.hideLevel=0
            set this.unpathLevel=0
            set this.hexLevel=0
            set this.locustLevel=0
            set this.neverMissLevel=0
            set this.alwaysMissLevel=0
            set this.untouchableLevel=0
            set this.banishLevel=0
            set this.phaseLevel=0
            set this.resistantSkinLevel=0
            set this.reflectPiercingLevel=0
            
            set this.armorBonus=0
            set this.damageBonus=0
            set this.strBonus=0
            set this.agiBonus=0
            set this.intBonus=0
            set this.attackSpeedBonus=0
            set this.healthBonus=0
            set this.manaBonus=0
            set this.healthRegenBonus=0
            set this.manaRegenBonus=0
            set this.healthRegenPercentBonus=0
            set this.manaRegenPercentBonus=0
            
            set this.moveSpeedBonus=0.0
            set this.moveSpeedPercentBonus=0.0
            call this.stopPeriodic()
        endmethod
        //! runtextmacro AIDS()
        private static unit dummyCaster=null
        private static unit dummyCaster2=null
        private static unit dummyCaster3=null
        
        implement StatusInit
        implement TwoPowArray
        implement PreloadModule
        
        ////////////////////
        // Status Effects //
        ////////////////////
        
        // Stun
        private integer stunLevel
        method addStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel+1
            if this.stunLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_STUN,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel-1
            if this.stunLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_STUN)
            endif
        endmethod
        method isStunned takes nothing returns boolean
            return this.stunLevel>0
        endmethod
        
        // Disable
        private integer disableLevel
        method addDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel+1
            if this.disableLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_DISABLE,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel-1
            if this.disableLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DISABLE)
            debug elseif this.disableLevel<0 then
                debug call BJDebugMsg("Status Error - More disables removed than previously added.")
            endif
        endmethod
        method isDisabled takes nothing returns boolean
            return this.disableLevel>0
        endmethod
        
        // Silence
        private integer silenceLevel
        method addSilence takes nothing returns nothing
            set this.silenceLevel=this.silenceLevel+1
            if this.silenceLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_SILENCE,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeSilence takes nothing returns nothing
            set this.silenceLevel=this.silenceLevel-1
            if this.silenceLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_SILENCE)
            endif
        endmethod
        method isSilenced takes nothing returns boolean
            return this.silenceLevel>0
        endmethod
        
        private integer doomLevel
        method addDoom takes nothing returns nothing
            set this.doomLevel=this.doomLevel+1
            if this.doomLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_DOOM,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeDoom takes nothing returns nothing
            set this.doomLevel=this.doomLevel-1
            if this.doomLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DOOM)
            endif
        endmethod
        method isDoomed takes nothing returns boolean
            return this.doomLevel>0
        endmethod
        
        // Disarm (Melee)
        private integer disarmMeleeLevel
        private integer disarmRangeLevel
        method addDisarmMelee takes nothing returns nothing
            set this.disarmMeleeLevel=this.disarmMeleeLevel+1
            if this.disarmMeleeLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                if this.disarmRangeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_RANGE)
                    call IssueTargetOrderById(CASTER_DISARM_BOTH,OID_DISARM,this.unit)
                else
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                endif
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method addDisarmRange takes nothing returns nothing
            set this.disarmRangeLevel=this.disarmRangeLevel+1
            if this.disarmRangeLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                if this.disarmMeleeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_MELEE)
                    call IssueTargetOrderById(CASTER_DISARM_BOTH,OID_DISARM,this.unit)
                else
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                endif
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method addDisarm takes nothing returns nothing
            set this.disarmMeleeLevel=this.disarmMeleeLevel+1
            set this.disarmRangeLevel=this.disarmRangeLevel+1
            if this.disarmMeleeLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                if this.disarmRangeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_RANGE)
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_MELEE)
                    call IssueTargetOrderById(CASTER_DISARM_BOTH,OID_DISARM,this.unit)
                else
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                endif
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            else
                if this.disarmRangeLevel>0 then
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                endif
            endif
        endmethod
        method removeDisarmMelee takes nothing returns nothing
            set this.disarmMeleeLevel=this.disarmMeleeLevel-1
            if this.disarmMeleeLevel==0 then
                if this.disarmRangeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                else
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_MELEE)
                endif
            endif
        endmethod
        method removeDisarmRange takes nothing returns nothing
            set this.disarmRangeLevel=this.disarmRangeLevel-1
            if this.disarmRangeLevel==0 then
                if this.disarmMeleeLevel>0 then
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                else
                    call UnitRemoveAbility(this.unit,BUFF_DISARM_RANGE)
                endif
            endif
        endmethod
        method removeDisarm takes nothing returns nothing
            set this.disarmMeleeLevel=this.disarmMeleeLevel-1
            set this.disarmRangeLevel=this.disarmRangeLevel-1
            if this.disarmMeleeLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                call UnitRemoveAbility(this.unit,BUFF_DISARM_MELEE)
                if this.disarmRangeLevel>0 then
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                endif
            elseif this.disarmRangeLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                call UnitRemoveAbility(this.unit,BUFF_DISARM_RANGE)
                if this.disarmMeleeLevel>0 then
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                    endif
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                    static if not PERMENANTLY_REVEAL then
                        call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                    endif
                endif
            endif
        endmethod
        method isDisarmedMelee takes nothing returns boolean
            return this.disarmMeleeLevel>0
        endmethod
        method isDisarmedRange takes nothing returns boolean
            return this.disarmRangeLevel>0
        endmethod
        method isDisarmed takes nothing returns boolean
            return this.disarmMeleeLevel>0 and this.disarmRangeLevel>0
        endmethod
        
        // Immobolise
        private integer immoboliseLevel
        method addImmobolise takes nothing returns nothing
            set this.immoboliseLevel=this.immoboliseLevel+1
            if this.immoboliseLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_IMMOBOLISE,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeImmobolise takes nothing returns nothing
            set this.immoboliseLevel=this.immoboliseLevel-1
            if this.immoboliseLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_IMMOBOLISE_GROUND)
                call UnitRemoveAbility(this.unit,BUFF_IMMOBOLISE_AIR)
            endif
        endmethod
        method isImmobolised takes nothing returns boolean
            return this.immoboliseLevel>0
        endmethod
        
        // Invisibility
        private integer invisibleLevel
        method addInvisible takes nothing returns nothing
            set this.invisibleLevel=this.invisibleLevel+1
            if this.invisibleLevel>0 then
                call UnitAddAbility(this.unit,ABIL_INVISIBLE)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_INVISIBLE)
            endif
        endmethod
        method removeInvisible takes nothing returns nothing
            set this.invisibleLevel=this.invisibleLevel-1
            if this.invisibleLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_INVISIBLE)
                call UnitRemoveAbility(this.unit,ABIL_INVISIBLE)
            endif
        endmethod
        method isInvisible takes nothing returns boolean
            return this.invisibleLevel>0
        endmethod
        
        // Ghost
        private integer ghostLevel
        method addGhost takes nothing returns nothing
            set this.ghostLevel=this.ghostLevel+1
            if this.ghostLevel>0 then
                call UnitAddAbility(this.unit,ABIL_GHOST)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_GHOST)
            endif
        endmethod
        method removeGhost takes nothing returns nothing
            set this.ghostLevel=this.ghostLevel-1
            if this.ghostLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_GHOST)
                call UnitRemoveAbility(this.unit,ABIL_GHOST)
            endif
        endmethod
        method isGhost takes nothing returns boolean
            return this.ghostLevel>0
        endmethod
        
        // Invulnerability
        private integer invulnerableLevel
        method addInvulnerable takes nothing returns nothing
            set this.invulnerableLevel=this.invulnerableLevel+1
            if this.invulnerableLevel>0 then
                call SetUnitInvulnerable(this.unit,true)
            endif
        endmethod
        method removeInvulnerable takes nothing returns nothing
            set this.invulnerableLevel=this.invulnerableLevel-1
            if this.invulnerableLevel==0 then
                call SetUnitInvulnerable(this.unit,false)
            endif
        endmethod
        method isInvulnerable takes nothing returns boolean
            return this.invulnerableLevel>0
        endmethod
        
        // Spell Immunity
        private integer immunityLevel
        method addImmunity takes nothing returns nothing
            set this.immunityLevel=this.immunityLevel+1
            if this.immunityLevel>0 then
                call UnitAddAbility(this.unit,ABIL_IMMUNITY)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_IMMUNITY)
            endif
        endmethod
        method removeImmunity takes nothing returns nothing
            set this.immunityLevel=this.immunityLevel-1
            if this.immunityLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_IMMUNITY)
                call UnitRemoveAbility(this.unit,ABIL_IMMUNITY)
            endif
        endmethod
        method isImmune takes nothing returns boolean
            return this.immunityLevel>0
        endmethod
        
        // Pause
        private integer pauseLevel
        method addPause takes nothing returns nothing
            set this.pauseLevel=this.pauseLevel+1
            if this.pauseLevel>0 then
                call PauseUnit(this.unit,true)
            endif
        endmethod
        method removePause takes nothing returns nothing
            set this.pauseLevel=this.pauseLevel-1
            if this.pauseLevel==0 then
                call PauseUnit(this.unit,false)
            endif
        endmethod
        method isPaused takes nothing returns boolean
            return this.pauseLevel>0
        endmethod
        
        // Hide
        private integer hideLevel
        method addHide takes nothing returns nothing
            set this.hideLevel=this.hideLevel+1
            if this.hideLevel>0 then
                call ShowUnit(this.unit,false)
            endif
        endmethod
        method removeHide takes nothing returns nothing
            set this.hideLevel=this.hideLevel-1
            if this.hideLevel==0 then
                call ShowUnit(this.unit,true)
            endif
        endmethod
        method isHidden takes nothing returns boolean
            return this.hideLevel>0
        endmethod
        
        // Unpath
        private integer unpathLevel
        method addUnpath takes nothing returns nothing
            set this.unpathLevel=this.unpathLevel+1
            if this.unpathLevel>0 then
                call SetUnitPathing(this.unit,false)
            endif
        endmethod
        method removeUnpath takes nothing returns nothing
            set this.unpathLevel=this.unpathLevel-1
            if this.unpathLevel==0 then
                call SetUnitPathing(this.unit,true)
            endif
        endmethod
        method isUnpathed takes nothing returns boolean
            return this.unpathLevel>0
        endmethod
        
        // Hex
        private integer hexLevel
        method addHex takes nothing returns nothing
            set this.hexLevel=this.hexLevel+1
            if this.hexLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_HEX,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeHex takes nothing returns nothing
            set this.hexLevel=this.hexLevel-1
            if this.hexLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_HEX)
            endif
        endmethod
        method isHexed takes nothing returns boolean
            return this.hexLevel>0
        endmethod
        
        // Locust
        private integer locustLevel
        method addLocust takes nothing returns nothing
            set this.locustLevel=this.locustLevel+1
            if this.locustLevel>0 then
                call UnitAddAbility(this.unit,'Aloc')
                call UnitMakeAbilityPermanent(this.unit,true,'Aloc')
            endif
        endmethod
        method removeLocust takes nothing returns nothing
            set this.locustLevel=this.locustLevel-1
            if this.locustLevel==0 then
                call ShowUnit(this.unit,false)
                call UnitMakeAbilityPermanent(this.unit,false,'Aloc')
                call UnitRemoveAbility(this.unit,'Aloc')
                call ShowUnit(this.unit,true)
                call UnitAddAbility(this.unit,ABIL_UNLOCUST)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_UNLOCUST)
                call IssueImmediateOrderById(this.unit,OID_UNLOCUST)
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_UNLOCUST)
                call UnitRemoveAbility(this.unit,ABIL_UNLOCUST)
            endif
        endmethod
        method isLocust takes nothing returns boolean
            return this.locustLevel>0
        endmethod
        
        // Never Miss
        private integer neverMissLevel
        method addNeverMiss takes nothing returns nothing
            set this.neverMissLevel=this.neverMissLevel+1
            if this.neverMissLevel>0 then
                call UnitAddAbility(this.unit,ABIL_NEVER_MISS)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_NEVER_MISS)
            endif
        endmethod
        method removeNeverMiss takes nothing returns nothing
            set this.neverMissLevel=this.neverMissLevel-1
            if this.neverMissLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_NEVER_MISS)
                call UnitRemoveAbility(this.unit,ABIL_NEVER_MISS)
            endif
        endmethod
        method isNeverMiss takes nothing returns boolean
            return this.neverMissLevel>0
        endmethod
        
        // Always Miss
        private integer alwaysMissLevel
        method addAlwaysMiss takes nothing returns nothing
            set this.alwaysMissLevel=this.alwaysMissLevel+1
            if this.alwaysMissLevel>0 then
                call UnitAddAbility(this.unit,ABIL_ALWAYS_MISS)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_ALWAYS_MISS)
            endif
        endmethod
        method removeAlwaysMiss takes nothing returns nothing
            set this.alwaysMissLevel=this.alwaysMissLevel-1
            if this.alwaysMissLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_ALWAYS_MISS)
                call UnitRemoveAbility(this.unit,ABIL_ALWAYS_MISS)
            endif
        endmethod
        method isAlwaysMiss takes nothing returns boolean
            return this.alwaysMissLevel>0
        endmethod
        
        // Untouchable
        private integer untouchableLevel
        method addUntouchable takes nothing returns nothing
            set this.untouchableLevel=this.untouchableLevel+1
            if this.untouchableLevel>0 then
                call UnitAddAbility(this.unit,ABIL_UNTOUCHABLE)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_UNTOUCHABLE)
            endif
        endmethod
        method removeUntouchable takes nothing returns nothing
            set this.untouchableLevel=this.untouchableLevel-1
            if this.untouchableLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_UNTOUCHABLE)
                call UnitRemoveAbility(this.unit,ABIL_UNTOUCHABLE)
            endif
        endmethod
        method isUntouchable takes nothing returns boolean
            return this.untouchableLevel>0
        endmethod
        
        // Banish
        private integer banishLevel
        method addBanish takes nothing returns nothing
            set this.banishLevel=this.banishLevel+1
            if this.banishLevel>0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                call IssueTargetOrderById(thistype.dummyCaster,OID_BANISH,this.unit)
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,false)
                endif
            endif
        endmethod
        method removeBanish takes nothing returns nothing
            set this.banishLevel=this.banishLevel-1
            if this.banishLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_BANISH)
            endif
        endmethod
        method isBanished takes nothing returns boolean
            return this.banishLevel>0
        endmethod
        
        // Phase
        private integer phaseLevel
        method addPhase takes nothing returns nothing
            set this.phaseLevel=this.phaseLevel+1
            if this.phaseLevel>0 then
                call SetPlayerAbilityAvailable(GetOwningPlayer(this.unit),ABIL_PHASE,true)
                if UnitAddAbility(this.unit,ABIL_PHASE) then
                    call UnitMakeAbilityPermanent(this.unit,true,ABIL_PHASE)
                endif
                call IssueImmediateOrderById(this.unit,OID_PHASE)
                call SetPlayerAbilityAvailable(GetOwningPlayer(this.unit),ABIL_PHASE,false)
            endif
        endmethod
        method removePhase takes nothing returns nothing
            set this.phaseLevel=this.phaseLevel-1
            if this.phaseLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_PHASE)
            endif
        endmethod
        method isPhased takes nothing returns boolean
            return this.phaseLevel>0
        endmethod
        /*
        // Double Attack
        private integer doubleAttackLevel
        method addDoubleAttack takes nothing returns nothing
            set this.doubleAttackLevel=this.doubleAttackLevel+1
            if this.doubleAttackLevel>0 then
                call UnitAddAbility(this.unit,ABIL_DOUBLE_ATTACK)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_DOUBLE_ATTACK)
            endif
        endmethod
        method removeDoubleAttack takes nothing returns nothing
            set this.doubleAttackLevel=this.doubleAttackLevel-1
            if this.doubleAttackLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_DOUBLE_ATTACK)
                call UnitRemoveAbility(this.unit,ABIL_DOUBLE_ATTACK)
            endif
        endmethod
        method isDoubleAttack takes nothing returns boolean
            return this.doubleAttackLevel>0
        endmethod
        */
        // Resistant Skin
        private integer resistantSkinLevel
        method addResistantSkin takes nothing returns nothing
            set this.resistantSkinLevel=this.resistantSkinLevel+1
            if this.resistantSkinLevel>0 then
                call UnitAddAbility(this.unit,ABIL_RESISTANT_SKIN)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_RESISTANT_SKIN)
            endif
        endmethod
        method removeResistantSkin takes nothing returns nothing
            set this.resistantSkinLevel=this.resistantSkinLevel-1
            if this.resistantSkinLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_RESISTANT_SKIN)
                call UnitRemoveAbility(this.unit,ABIL_RESISTANT_SKIN)
            endif
        endmethod
        method isResistantSkin takes nothing returns boolean
            return this.resistantSkinLevel>0
        endmethod
        
        // Reflect Piercing
        private integer reflectPiercingLevel
        method addReflectPiercing takes nothing returns nothing
            set this.reflectPiercingLevel=this.reflectPiercingLevel+1
            if this.reflectPiercingLevel>0 then
                call UnitAddAbility(this.unit,ABIL_REFLECT_PIERCING)
                call UnitMakeAbilityPermanent(this.unit,true,ABIL_REFLECT_PIERCING)
            endif
        endmethod
        method removeReflectPiercing takes nothing returns nothing
            set this.reflectPiercingLevel=this.reflectPiercingLevel-1
            if this.reflectPiercingLevel==0 then
                call UnitMakeAbilityPermanent(this.unit,false,ABIL_REFLECT_PIERCING)
                call UnitRemoveAbility(this.unit,ABIL_REFLECT_PIERCING)
            endif
        endmethod
        method isReflectPiercing takes nothing returns boolean
            return this.reflectPiercingLevel>0
        endmethod
        
        
        ////////////////////
        // Status Bonuses //
        ////////////////////
        private static method setBonus takes unit u, integer abil, integer levels, integer amount returns nothing
            local boolean addNeg=false
            if amount<0 then
                set addNeg=true
                set amount=amount+thistype.twoPow[levels]
            else
                call UnitMakeAbilityPermanent(u,false,abil)
                call UnitRemoveAbility(u,abil)
            endif
            
            set abil=abil+levels
            set levels=thistype.twoPow[levels]
            loop
                set levels=levels/2
                
                if amount>=levels then
                    call UnitAddAbility(u,abil)
                    call UnitMakeAbilityPermanent(u,true,abil)
                    set amount=amount-levels
                else
                    call UnitMakeAbilityPermanent(u,false,abil)
                    call UnitRemoveAbility(u,abil)
                endif
                
                set abil=abil-1
                exitwhen levels==1
            endloop
            
            if addNeg then
                call UnitAddAbility(u,abil)
                call UnitMakeAbilityPermanent(u,true,abil)
            endif
        endmethod
        
        private integer armorBonus
        method modArmorBonus takes integer amount returns nothing
            set this.armorBonus=this.armorBonus+amount
            debug if this.armorBonus>=thistype.twoPow[LEVELS_ARMOR] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modArmorBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_ARMOR])+".")
            debug endif
            debug if this.armorBonus<-thistype.twoPow[LEVELS_ARMOR] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modArmorBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_ARMOR])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_ARMOR,LEVELS_ARMOR,this.armorBonus)
        endmethod
        method getArmorBonus takes nothing returns integer
            return this.armorBonus
        endmethod
        
        private integer damageBonus
        method modDamageBonus takes integer amount returns nothing
            set this.damageBonus=this.damageBonus+amount
            debug if this.damageBonus>=thistype.twoPow[LEVELS_DAMAGE] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modDamageBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_DAMAGE])+".")
            debug endif
            debug if this.damageBonus<-thistype.twoPow[LEVELS_DAMAGE] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modDamageBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_DAMAGE])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_DAMAGE,LEVELS_DAMAGE,this.damageBonus)
        endmethod
        method getDamageBonus takes nothing returns integer
            return this.damageBonus
        endmethod
        
        private integer strBonus
        method modStrBonus takes integer amount returns nothing
            set this.strBonus=this.strBonus+amount
            debug if this.strBonus>=thistype.twoPow[LEVELS_STR] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modStrBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_STR])+".")
            debug endif
            debug if this.strBonus<-thistype.twoPow[LEVELS_STR] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modStrBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_STR])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_STR,LEVELS_STR,this.strBonus)
        endmethod
        method getStrBonus takes nothing returns integer
            return this.strBonus
        endmethod
        
        private integer agiBonus
        method modAgiBonus takes integer amount returns nothing
            set this.agiBonus=this.agiBonus+amount
            debug if this.agiBonus>=thistype.twoPow[LEVELS_AGI] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modAgiBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_AGI])+".")
            debug endif
            debug if this.agiBonus<-thistype.twoPow[LEVELS_AGI] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modAgiBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_AGI])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_AGI,LEVELS_AGI,this.agiBonus)
        endmethod
        method getAgiBonus takes nothing returns integer
            return this.agiBonus
        endmethod
        
        private integer intBonus
        method modIntBonus takes integer amount returns nothing
            set this.intBonus=this.intBonus+amount
            debug if this.intBonus>=thistype.twoPow[LEVELS_INT] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modIntBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_INT])+".")
            debug endif
            debug if this.intBonus<-thistype.twoPow[LEVELS_INT] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modIntBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_INT])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_INT,LEVELS_INT,this.intBonus)
        endmethod
        method getIntBonus takes nothing returns integer
            return this.intBonus
        endmethod
        
        private integer attackSpeedBonus
        method modAttackSpeedBonus takes integer amount returns nothing
            set this.attackSpeedBonus=this.attackSpeedBonus+amount
            debug if this.attackSpeedBonus>=thistype.twoPow[LEVELS_ATTACK_SPEED] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modAttackSpeedBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_ATTACK_SPEED])+".")
            debug endif
            debug if this.attackSpeedBonus<-thistype.twoPow[LEVELS_ATTACK_SPEED] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modAttackSpeedBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_ATTACK_SPEED])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_ATTACK_SPEED,LEVELS_ATTACK_SPEED,this.attackSpeedBonus)
        endmethod
        method getAttackSpeedBonus takes nothing returns integer
            return this.attackSpeedBonus
        endmethod
        
        private integer healthBonus
        method modHealthBonus takes integer amount returns nothing
            set this.healthBonus=this.healthBonus+amount
            debug if this.healthBonus>=thistype.twoPow[LEVELS_HEALTH] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modHealthBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_HEALTH])+".")
            debug endif
            debug if this.healthBonus<-thistype.twoPow[LEVELS_HEALTH] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modHealthBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_HEALTH])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_HEALTH,LEVELS_HEALTH,this.healthBonus)
        endmethod
        method getHealthBonus takes nothing returns integer
            return this.healthBonus
        endmethod
        
        private integer manaBonus
        method modManaBonus takes integer amount returns nothing
            set this.manaBonus=this.manaBonus+amount
            debug if this.manaBonus>=thistype.twoPow[LEVELS_MANA] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modManaBonus("+I2S(amount)+") - must not reach >= "+I2S(thistype.twoPow[LEVELS_MANA])+".")
            debug endif
            debug if this.manaBonus<-thistype.twoPow[LEVELS_MANA] then
                debug call BJDebugMsg("Status Error: Status["+GetUnitName(this.unit)+"].modManaBonus("+I2S(amount)+") - must not reach < -"+I2S(thistype.twoPow[LEVELS_MANA])+".")
            debug endif
            call thistype.setBonus(this.unit,ABIL_MANA,LEVELS_MANA,this.manaBonus)
        endmethod
        method getManaBonus takes nothing returns integer
            return this.manaBonus
        endmethod
        
        // Periodic bonuses
        private static unit updateUnit
        
        private static group healthRegenGroup=CreateGroup()
        private static method healthRegenPeriodic takes nothing returns nothing
            set thistype.updateUnit=GetEnumUnit()
            if UnitAlive(thistype.updateUnit) then
                call SetWidgetLife(thistype.updateUnit,GetWidgetLife(thistype.updateUnit)+thistype[thistype.updateUnit].healthRegenBonus)
            endif
        endmethod
        private real healthRegenBonus
        method modHealthRegenBonus takes real amount returns nothing
            set this.healthRegenBonus=this.healthRegenBonus+amount*PERIOD
            if this.healthRegenBonus==0 then
                call GroupRemoveUnit(thistype.healthRegenGroup,this.unit)
            else
                call GroupAddUnit(thistype.healthRegenGroup,this.unit)
            endif
        endmethod
        method getHealthRegenBonus takes nothing returns real
            return this.healthRegenBonus/PERIOD
        endmethod
        
        private static group manaRegenGroup=CreateGroup()
        private static method manaRegenPeriodic takes nothing returns nothing
            set thistype.updateUnit=GetEnumUnit()
            if UnitAlive(thistype.updateUnit) then
                call SetUnitState(thistype.updateUnit,UNIT_STATE_MANA,GetUnitState(thistype.updateUnit,UNIT_STATE_MANA)+thistype[thistype.updateUnit].manaRegenBonus)
            endif
        endmethod
        private real manaRegenBonus
        method modManaRegenBonus takes real amount returns nothing
            set this.manaRegenBonus=this.manaRegenBonus+amount*PERIOD
            if this.manaRegenBonus==0 then
                call GroupRemoveUnit(thistype.manaRegenGroup,this.unit)
            else
                call GroupAddUnit(thistype.manaRegenGroup,this.unit)
            endif
        endmethod
        method getManaRegenBonus takes nothing returns real
            return this.manaRegenBonus/PERIOD
        endmethod
        
        private static group healthRegenPercentGroup=CreateGroup()
        private static method healthRegenPercentPeriodic takes nothing returns nothing
            set thistype.updateUnit=GetEnumUnit()
            if UnitAlive(thistype.updateUnit) then
                call SetWidgetLife(thistype.updateUnit,GetWidgetLife(thistype.updateUnit)+GetUnitState(thistype.updateUnit,UNIT_STATE_MAX_LIFE)*thistype[thistype.updateUnit].healthRegenPercentBonus)
            endif
        endmethod
        private real healthRegenPercentBonus
        method modHealthRegenPercentBonus takes real amount returns nothing
            set this.healthRegenPercentBonus=this.healthRegenPercentBonus+amount*PERIOD*0.01
            if this.healthRegenPercentBonus==0 then
                call GroupRemoveUnit(thistype.healthRegenPercentGroup,this.unit)
            else
                call GroupAddUnit(thistype.healthRegenPercentGroup,this.unit)
            endif
        endmethod
        method getHealthRegenPercentBonus takes nothing returns real
            return this.healthRegenPercentBonus/PERIOD/0.01
        endmethod
        
        private static group manaRegenPercentGroup=CreateGroup()
        private static method manaRegenPercentPeriodic takes nothing returns nothing
            set thistype.updateUnit=GetEnumUnit()
            if UnitAlive(thistype.updateUnit) then
                call SetUnitState(thistype.updateUnit,UNIT_STATE_MANA,GetUnitState(thistype.updateUnit,UNIT_STATE_MANA)+GetUnitState(thistype.updateUnit,UNIT_STATE_MAX_MANA)*thistype[thistype.updateUnit].manaRegenPercentBonus)
            endif
        endmethod
        private real manaRegenPercentBonus
        method modManaRegenPercentBonus takes real amount returns nothing
            set this.manaRegenPercentBonus=this.manaRegenPercentBonus+amount*PERIOD*0.01
            if this.manaRegenPercentBonus==0 then
                call GroupRemoveUnit(thistype.manaRegenPercentGroup,this.unit)
            else
                call GroupAddUnit(thistype.manaRegenPercentGroup,this.unit)
            endif
        endmethod
        method getManaRegenPercentBonus takes nothing returns real
            return this.manaRegenPercentBonus/PERIOD/0.01
        endmethod
        
        // Links periodic effects.
        private static method periodicLink takes nothing returns nothing
            call ForGroup(thistype.healthRegenGroup,function thistype.healthRegenPeriodic)
            call ForGroup(thistype.manaRegenGroup,function thistype.manaRegenPeriodic)
            call ForGroup(thistype.healthRegenPercentGroup,function thistype.healthRegenPercentPeriodic)
            call ForGroup(thistype.manaRegenPercentGroup,function thistype.manaRegenPercentPeriodic)
        endmethod
        implement StaticPeriodic
        
        ////////////////////
        // Movement Speed //
        ////////////////////
        
        private real moveSpeedBonus
        private real moveSpeedPercentBonus
        private real x
        private real y
        private static real updateUnitX
        private static real updateUnitY
        private static real xInc
        private static real yInc
        private static real updateDist
        private method periodic takes nothing returns nothing
            set thistype.updateUnit=this.unit
            set thistype.updateUnitX=GetUnitX(thistype.updateUnit)
            set thistype.updateUnitY=GetUnitY(thistype.updateUnit)
            set thistype.xInc=thistype.updateUnitX-this.x
            set thistype.yInc=thistype.updateUnitY-this.y
            set thistype.updateDist=SquareRoot(thistype.xInc*thistype.xInc+thistype.yInc*thistype.yInc)
            if thistype.updateDist>0 then
                if UnitAlive(thistype.updateUnit) and this.disableLevel<=0 and this.stunLevel<=0 and this.pauseLevel<=0 and this.immoboliseLevel<=0 and GetUnitMoveSpeed(thistype.updateUnit)>0 then
                    if this.moveSpeedPercentBonus!=0.0 then
                        set thistype.updateUnitX=thistype.updateUnitX+thistype.xInc*this.moveSpeedPercentBonus
                        set thistype.updateUnitY=thistype.updateUnitY+thistype.yInc*this.moveSpeedPercentBonus
                    endif
                    if this.moveSpeedBonus!=0.0 then
                        set thistype.updateDist=this.moveSpeedBonus/thistype.updateDist
                        set thistype.updateUnitX=thistype.updateUnitX+thistype.xInc*thistype.updateDist
                        set thistype.updateUnitY=thistype.updateUnitY+thistype.yInc*thistype.updateDist
                    endif
                    call SetUnitX(thistype.updateUnit,thistype.updateUnitX)
                    call SetUnitY(thistype.updateUnit,thistype.updateUnitY)
                endif
            endif
            set this.x=thistype.updateUnitX
            set this.y=thistype.updateUnitY
        endmethod
        implement T32xs
        method modMoveSpeedBonus takes real amount returns nothing
            set this.moveSpeedBonus=this.moveSpeedBonus+amount*T32_PERIOD
            if this.moveSpeedBonus==0 and this.moveSpeedPercentBonus==0 then
                call this.stopPeriodic()
            else
                set this.x=GetUnitX(this.unit)
                set this.y=GetUnitY(this.unit)
                call this.startPeriodic()
            endif
        endmethod
        method getMoveSpeedBonus takes nothing returns real
            return this.moveSpeedBonus/T32_PERIOD
        endmethod
        method modMoveSpeedPercentBonus takes real amount returns nothing
            set this.moveSpeedPercentBonus=this.moveSpeedPercentBonus+amount*0.01
            if this.moveSpeedBonus==0 and this.moveSpeedPercentBonus==0 then
                call this.stopPeriodic()
            else
                set this.x=GetUnitX(this.unit)
                set this.y=GetUnitY(this.unit)
                call this.startPeriodic()
            endif
        endmethod
        method getMoveSpeedPercentBonus takes nothing returns real
            return this.moveSpeedPercentBonus/0.01
        endmethod
    endstruct
endlibrary

library Stun uses Status // Deprecated. Backwards compatability with "Stun" system.
    function AddStun takes unit whichUnit returns nothing
        call Status[whichUnit].addStun()
    endfunction
    function RemoveStun takes unit whichUnit returns nothing
        call Status[whichUnit].removeStun()
    endfunction
    function Stun_IsUnitStunned takes unit whichUnit returns boolean
        return Status[whichUnit].isStunned()
    endfunction
endlibrary

//! runtextmacro Status__CreateAbilities() đúng là sẽ tạo abilities cho mình (gồm các object)
nếu không thì báo lỗi cái gì?

Chào tất cả mọi người :)
Mình đang làm đoạn code spawn creep ở một nhà chính nhất định, mình không rõ về việc xài Group sao cho không leak, ai có thể check leak và sửa dùm mình phần leak trong đoạn code sau (nếu có) được không ? Cảm ơn rất nhiều:

Đây là đoạn Library giúp đỡ spawn, nói chung là không cần check vì nó không leak, mình copy ra để dễ hiểu code:
Mã:
function spawnHelper takes integer unitId returns nothing
    local unit p = GetEnumUnit()
    local real x = GetUnitX(p)
    local real y = GetUnitY(p)
    local unit s = CreateUnit( GetOwningPlayer(GetEnumUnit()), unitId, x, y, bj_UNIT_FACING)
    set s = null
    set p = null
endfunction

Đây là đoạn code spawn unit, cần được check leak:
Mã:
scope spawnfootmen

globals
    private integer base = 'hbar' // base buiding
    private integer footmen = 'hfoo' // footmen
endglobals

private function Spawn takes nothing returns nothing
    call spawnHelper(footmen)
endfunction

private function Cond takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'hbar' and GetWidgetLife(GetFilterUnit()) > 0.405
endfunction

private function Acts takes nothing returns nothing
    local group g = CreateGroup()
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function Cond))

//    local group g = GetUnitsInRectMatching(bj_mapInitialPlayableArea, Condition(function Cond))
//call GroupEnumUnitsOfType(g,"Barrack",Filter(function True))

//    local group g = GetUnitsOfTypeIdAll(base)
    call ForGroup(g, function Spawn)
    call GroupClear(g)
    call DestroyGroup(g)
//    call DestroyBoolExpr(Cond)
//    return g
    set g = null
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger( )
    
    call TriggerRegisterTimerEvent( trig, 0.50, true)
    call TriggerAddAction( trig, function Acts )
    
    set trig = null
endfunction

endscope

Đoạn " call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function Cond))" mình không rõ là leak hay không ?

code thì toàn handle nhiều mà leak chắc là không có
1 GetFilterUnit() = handle, nhiều = leak nhẹ và có thể
local unit u = GetFilterUnit()
set u =null hoặc xài global var

thế chỉnh làm sao cho nó ra hình con khác mà không phải là demon form

Mọi người chỉ mình chỉnh làm sao để hẻo lên mổi cấp lên bao nhiêu Agi, bao nhiều Strenght, bao nhiêu intel tự mình quyết định dc ko

bạn có biết sơ qua về Object Editor trong warcraft chưa ?
 

code thì toàn handle nhiều mà leak chắc là không có
1 GetFilterUnit() = handle, nhiều = leak nhẹ và có thể
local unit u = GetFilterUnit()
set u =null hoặc xài global var


Mình đang có ý tưởng làm một cái Snippet nhỏ Anti-cheat, ví dụ player nào gõ lệnh mà có "-" ở đằng trước sẽ hiện full cả câu lệnh cho tất cả những người chơi trong map.

Ví dụ -gold 99999, có "-" sẽ Display text message đến tất cả player khác là -gold 99999 để họ biết là có thể player này xài cheat hoặc CDSHT

Mình không biết có khả quan không, mấy vụ dùng Chat message rồi detect substring mình không rành.

À mà mình làm xong rồi:

Untitled Trigger 004
Events
Player - Player 1 (Red) types a chat message containing - as A substring
Player - Player 2 (Blue) types a chat message containing - as A substring
Player - Player 3 (Teal) types a chat message containing - as A substring
Player - Player 4 (Purple) types a chat message containing - as A substring
Player - Player 5 (Yellow) types a chat message containing - as A substring
Player - Player 6 (Orange) types a chat message containing - as A substring
Player - Player 7 (Green) types a chat message containing - as A substring
Player - Player 8 (Pink) types a chat message containing - as A substring
Player - Player 9 (Gray) types a chat message containing - as A substring
Player - Player 10 (Light Blue) types a chat message containing - as A substring
Player - Player 11 (Dark Green) types a chat message containing - as A substring
Player - Player 12 (Brown) types a chat message containing - as A substring
Conditions
Actions
Game - Display to (All players) for 30.00 seconds the text: ((Name of (Triggering player)) + ( typed + (Entered chat string)))
 
Chỉnh sửa cuối:
bạn có biết sơ qua về Object Editor trong warcraft chưa ?


Àh có rồi mình có mò mẩm và tạo dc vài unit custom từ mấy thứ đã có, tất nhiên mấy cái đó chả là gì, nên chắc mình chỉ biết dc chút chút, cơ bản thôi
 
Sao ko ai giup em zay :((
1. khi hero team 1 chết sẽ hồi sinh tại vị trí bên này (region) còn hero ở team 2 chết sẽ hôi sinh tại vị trí bên kia (region)
2. Khi chọn hero, hero đó sẽ tự có 1 skill mà ko cần phải tăng, nó hiện thị ở ô bên cạnh Attribute Bonus
 
Back
Top