System Status

Jesus4Lyf

Good Idea™
Reaction score
397
Status​
Version 1.3.0​

Requirements:
- Jass NewGen
- AIDS
- DummyCaster
- Timer32

Documentation (code in map, can't fit in post):
JASS:
//
//      ___ _____ _ _____ _   _ ___ 
//     / __|_   _/_\_   _| | | / __|
//     \__ \ | |/ _ \| | | |_| \__ \    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(&quot;AId1&quot;,&quot;A5A&quot;..myChar<i>)
                    //! i makechange(current,&quot;Idef&quot;,1,myBin<i>)
                    //! i makechange(current,&quot;anam&quot;,&quot;Armor Bonus&quot;)
                    //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i end
                //! i createobject(&quot;AId1&quot;,&quot;A5A@&quot;)
                //! i makechange(current,&quot;Idef&quot;,1,-myBin[11])
                //! i makechange(current,&quot;anam&quot;,&quot;Armor Bonus&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                
                
                // Damage (15 = 32767 max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AItg&quot;,&quot;A5B&quot;..myChar<i>)
                    //! i makechange(current,&quot;Iatt&quot;,1,myBin<i>)
                    //! i makechange(current,&quot;anam&quot;,&quot;Damage Bonus&quot;)
                    //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i end
                //! i createobject(&quot;AItg&quot;,&quot;A5B@&quot;)
                //! i makechange(current,&quot;Iatt&quot;,1,-myBin[16])
                //! i makechange(current,&quot;anam&quot;,&quot;Damage Bonus&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                
                // Str/Agi/Int (10 = 1023 max)
                //! i for i=1,10 do
                    //! i createobject(&quot;AIs1&quot;,&quot;A5C&quot;..myChar<i>)
                    //! i makechange(current,&quot;Istr&quot;,1,myBin<i>)
                    //! i makechange(current,&quot;anam&quot;,&quot;Strength Bonus&quot;)
                    //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                    
                    //! i createobject(&quot;AIa1&quot;,&quot;A5D&quot;..myChar<i>)
                    //! i makechange(current,&quot;Iagi&quot;,1,myBin<i>)
                    //! i makechange(current,&quot;anam&quot;,&quot;Agility Bonus&quot;)
                    //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                    
                    //! i createobject(&quot;AIi1&quot;,&quot;A5E&quot;..myChar<i>)
                    //! i makechange(current,&quot;Iint&quot;,1,myBin<i>)
                    //! i makechange(current,&quot;anam&quot;,&quot;Intelligence Bonus&quot;)
                    //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i end
                //! i createobject(&quot;AIs1&quot;,&quot;A5C@&quot;)
                //! i makechange(current,&quot;Istr&quot;,1,-myBin[11])
                //! i makechange(current,&quot;anam&quot;,&quot;Strength Bonus&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i createobject(&quot;AIa1&quot;,&quot;A5D@&quot;)
                //! i makechange(current,&quot;Iagi&quot;,1,-myBin[11])
                //! i makechange(current,&quot;anam&quot;,&quot;Agility Bonus&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i createobject(&quot;AIi1&quot;,&quot;A5E@&quot;)
                //! i makechange(current,&quot;Iint&quot;,1,-myBin[11])
                //! i makechange(current,&quot;anam&quot;,&quot;Intelligence Bonus&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                
                // Attack Speed (9 = 511% max)
                //! i for i=1,9 do
                    //! i createobject(&quot;AIsx&quot;,&quot;A5F&quot;..myChar<i>)
                    //! i makechange(current,&quot;Isx1&quot;,1,myBin<i>*0.01)
                    //! i makechange(current,&quot;anam&quot;,&quot;Attack Speed Bonus&quot;)
                    //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i end
                //! i createobject(&quot;AIsx&quot;,&quot;A5F@&quot;)
                //! i makechange(current,&quot;Isx1&quot;,1,-myBin[10]*0.01)
                //! i makechange(current,&quot;anam&quot;,&quot;Attack Speed Bonus&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                
                // Max HP (20 = 1048575 max)
                //! i for i=1,20 do
                    //! i createobject(&quot;AIl2&quot;,&quot;A5G&quot;..myChar<i>)
                    //! i makechange(current,&quot;Ilif&quot;,1,myBin<i>)
                    //! i makechange(current,&quot;anam&quot;,&quot;Health Bonus&quot;)
                    //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i end
                //! i createobject(&quot;AIl2&quot;,&quot;A5G@&quot;)
                //! i makechange(current,&quot;Ilif&quot;,1,-myBin[21])
                //! i makechange(current,&quot;anam&quot;,&quot;Health Bonus&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                
                // Max Mana (20 = 1048575 max)
                //! i for i=1,20 do
                    //! i createobject(&quot;AImz&quot;,&quot;A5H&quot;..myChar<i>)
                    //! i makechange(current,&quot;Iman&quot;,1,myBin<i>)
                    //! i makechange(current,&quot;anam&quot;,&quot;Mana Bonus&quot;)
                    //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i end
                //! i createobject(&quot;AImz&quot;,&quot;A5H@&quot;)
                //! i makechange(current,&quot;Iman&quot;,1,-myBin[21])
                //! i makechange(current,&quot;anam&quot;,&quot;Mana Bonus&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                
                // 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
    
//to be continued in next post...</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


Demonstration:
JASS:
// Stuns every unit on the map for 5 seconds.
scope SimpleStun initializer Demo
    private function Timeout takes unit target, real time returns nothing
        // You should use your favourite timer system instead of TriggerSleepAction.
        call TriggerSleepAction(time)
        call Status[target].removeStun()
    endfunction
    function Stun takes unit target, real time returns nothing
        call Status[target].addStun()
        call Timeout.execute(target,time)
    endfunction
    
    private function Action takes nothing returns nothing
        call Stun(GetEnumUnit(),5.0)
    endfunction
    private function DoThings takes nothing returns nothing
        call TriggerSleepAction(1.0)
        // This is because deep down I love GUI and all the trouble it causes.
        call BJDebugMsg(&quot;Stunning everything for 5 seconds.&quot;)
        call ForGroupBJ(GetUnitsInRectAll(GetPlayableMapRect()),function Action)
        call TriggerSleepAction(5.0)
        call BJDebugMsg(&quot;5 seconds has passed.&quot;)
    endfunction
    private function Demo takes nothing returns nothing
        call DoThings.execute()
    endfunction
endscope
This is very efficient, provides only the basic functions, supports multi-instancing stuns on one unit at once (it will become unstunned when it has no more stuns remaining on it) and doesn't force you into using any particular timer system.

Usually with stuns you want to add effects when they begin and remove then when they end, or use them in unit sliding effects which may end abruptly if it hits a wall or something. For this reason (and the freedom of choice for timer system) I have not made a timed stun system, merely a stun system. I think this is the API that mappers truly need, rather than someone that tries to do too much for you. :)

PS. I have been developing this since releasing DummyCaster. But today I realised the interface was wrong, and reduced it to 40 lines of code.

PPS. Today I realised that I should overhaul this, and make it epic.

PPPS. This is now 1958 lines long and cannot fit in a post. :p

Updates:
- Version 1.3.0: Fixed typo "alwaysNeverMiss" --> "removeAlwaysMiss".
- Version 1.2.9: Implemented the written (but unimplemented) PreloadModule (thanks 13lade619).
- Version 1.2.8: Gave Disable a different buff to Stun.
- Version 1.2.7: Added ReflectPiercing status.
- Version 1.2.6: Added MoveSpeed and MoveSpeedPercent bonuses, and Resistant Skin as a status. Also added HealthRegen, HealthRegenPercent, ManaRegen and ManaRegenPercent bonuses. Changed all "isXStatus" methods to simply read the level for the unit instead of check for the buff.
- Version 1.2.5: Fixed a bug where setting health or strength to negative would instantly kill the subject.
- Version 1.2.4: Added Phase status and added life and mana bonuses. Also preloaded all abilities.
- Version 1.2.3: Added many new statuses or released them publicly, as well as bonuses. All of them now implement negatively as well, except for Disable (which should not).
- Version 1.2.0: Now supports Silence, Disarm (Melee), Disarm (Range), Disarm (Both Melee and Range) and Immobolise, as well as Stun.

Stun:
- Version 1.1.3: No longer overwrites "Stone Form".
- Version 1.1.2: Now hits mechanical units.
- Version 1.1.1: Modified to issue the order by ID. I had the ID there, but I still used the "firebolt" string for some reason.
- Version 1.1.0: Stun can now stun magic immune targets.
- Version 1.0.1: Removed the stun level check before issuing the stun order.
- Version 1.0.0: Release.
 

Attachments

  • Status.w3x
    79.8 KB · Views: 878
  • Status.txt
    95.5 KB · Views: 782

Jesus4Lyf

Good Idea™
Reaction score
397
JASS:
//continued..
    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&gt;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&gt;0
        endmethod
        
        // Disable
        private integer disableLevel
        method addDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel+1
            if this.disableLevel&gt;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&lt;0 then
                debug call BJDebugMsg(&quot;Status Error - More disables removed than previously added.&quot;)
            endif
        endmethod
        method isDisabled takes nothing returns boolean
            return this.disableLevel&gt;0
        endmethod
        
        // Silence
        private integer silenceLevel
        method addSilence takes nothing returns nothing
            set this.silenceLevel=this.silenceLevel+1
            if this.silenceLevel&gt;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&gt;0
        endmethod
        
        private integer doomLevel
        method addDoom takes nothing returns nothing
            set this.doomLevel=this.doomLevel+1
            if this.doomLevel&gt;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&gt;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&gt;0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                if this.disarmRangeLevel&gt;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&gt;0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                if this.disarmMeleeLevel&gt;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&gt;0 then
                static if not PERMENANTLY_REVEAL then
                    call UnitShareVision(this.unit,DUMMY_CASTER_OWNER,true)
                endif
                if this.disarmRangeLevel&gt;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&gt;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&gt;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&gt;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&gt;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&gt;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&gt;0
        endmethod
        method isDisarmedRange takes nothing returns boolean
            return this.disarmRangeLevel&gt;0
        endmethod
        method isDisarmed takes nothing returns boolean
            return this.disarmMeleeLevel&gt;0 and this.disarmRangeLevel&gt;0
        endmethod
        
        // Immobolise
        private integer immoboliseLevel
        method addImmobolise takes nothing returns nothing
            set this.immoboliseLevel=this.immoboliseLevel+1
            if this.immoboliseLevel&gt;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&gt;0
        endmethod
        
        // Invisibility
        private integer invisibleLevel
        method addInvisible takes nothing returns nothing
            set this.invisibleLevel=this.invisibleLevel+1
            if this.invisibleLevel&gt;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&gt;0
        endmethod
        
        // Ghost
        private integer ghostLevel
        method addGhost takes nothing returns nothing
            set this.ghostLevel=this.ghostLevel+1
            if this.ghostLevel&gt;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&gt;0
        endmethod
        
        // Invulnerability
        private integer invulnerableLevel
        method addInvulnerable takes nothing returns nothing
            set this.invulnerableLevel=this.invulnerableLevel+1
            if this.invulnerableLevel&gt;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&gt;0
        endmethod
        
        // Spell Immunity
        private integer immunityLevel
        method addImmunity takes nothing returns nothing
            set this.immunityLevel=this.immunityLevel+1
            if this.immunityLevel&gt;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&gt;0
        endmethod
        
        // Pause
        private integer pauseLevel
        method addPause takes nothing returns nothing
            set this.pauseLevel=this.pauseLevel+1
            if this.pauseLevel&gt;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&gt;0
        endmethod
        
        // Hide
        private integer hideLevel
        method addHide takes nothing returns nothing
            set this.hideLevel=this.hideLevel+1
            if this.hideLevel&gt;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&gt;0
        endmethod
        
        // Unpath
        private integer unpathLevel
        method addUnpath takes nothing returns nothing
            set this.unpathLevel=this.unpathLevel+1
            if this.unpathLevel&gt;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&gt;0
        endmethod
        
        // Hex
        private integer hexLevel
        method addHex takes nothing returns nothing
            set this.hexLevel=this.hexLevel+1
            if this.hexLevel&gt;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&gt;0
        endmethod
        
        // Locust
        private integer locustLevel
        method addLocust takes nothing returns nothing
            set this.locustLevel=this.locustLevel+1
            if this.locustLevel&gt;0 then
                call UnitAddAbility(this.unit,&#039;Aloc&#039;)
                call UnitMakeAbilityPermanent(this.unit,true,&#039;Aloc&#039;)
            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,&#039;Aloc&#039;)
                call UnitRemoveAbility(this.unit,&#039;Aloc&#039;)
                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&gt;0
        endmethod
        
        // Never Miss
        private integer neverMissLevel
        method addNeverMiss takes nothing returns nothing
            set this.neverMissLevel=this.neverMissLevel+1
            if this.neverMissLevel&gt;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&gt;0
        endmethod
        
        // Always Miss
        private integer alwaysMissLevel
        method addAlwaysMiss takes nothing returns nothing
            set this.alwaysMissLevel=this.alwaysMissLevel+1
            if this.alwaysMissLevel&gt;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&gt;0
        endmethod
        
        // Untouchable
        private integer untouchableLevel
        method addUntouchable takes nothing returns nothing
            set this.untouchableLevel=this.untouchableLevel+1
            if this.untouchableLevel&gt;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&gt;0
        endmethod
        
        // Banish
        private integer banishLevel
        method addBanish takes nothing returns nothing
            set this.banishLevel=this.banishLevel+1
            if this.banishLevel&gt;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&gt;0
        endmethod
        
        // Phase
        private integer phaseLevel
        method addPhase takes nothing returns nothing
            set this.phaseLevel=this.phaseLevel+1
            if this.phaseLevel&gt;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&gt;0
        endmethod
        /*
        // Double Attack
        private integer doubleAttackLevel
        method addDoubleAttack takes nothing returns nothing
            set this.doubleAttackLevel=this.doubleAttackLevel+1
            if this.doubleAttackLevel&gt;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&gt;0
        endmethod
        */
        // Resistant Skin
        private integer resistantSkinLevel
        method addResistantSkin takes nothing returns nothing
            set this.resistantSkinLevel=this.resistantSkinLevel+1
            if this.resistantSkinLevel&gt;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&gt;0
        endmethod
        
        // Reflect Piercing
        private integer reflectPiercingLevel
        method addReflectPiercing takes nothing returns nothing
            set this.reflectPiercingLevel=this.reflectPiercingLevel+1
            if this.reflectPiercingLevel&gt;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&gt;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&lt;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&gt;=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&gt;=thistype.twoPow[LEVELS_ARMOR] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modArmorBonus(&quot;+I2S(amount)+&quot;) - must not reach &gt;= &quot;+I2S(thistype.twoPow[LEVELS_ARMOR])+&quot;.&quot;)
            debug endif
            debug if this.armorBonus&lt;-thistype.twoPow[LEVELS_ARMOR] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modArmorBonus(&quot;+I2S(amount)+&quot;) - must not reach &lt; -&quot;+I2S(thistype.twoPow[LEVELS_ARMOR])+&quot;.&quot;)
            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&gt;=thistype.twoPow[LEVELS_DAMAGE] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modDamageBonus(&quot;+I2S(amount)+&quot;) - must not reach &gt;= &quot;+I2S(thistype.twoPow[LEVELS_DAMAGE])+&quot;.&quot;)
            debug endif
            debug if this.damageBonus&lt;-thistype.twoPow[LEVELS_DAMAGE] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modDamageBonus(&quot;+I2S(amount)+&quot;) - must not reach &lt; -&quot;+I2S(thistype.twoPow[LEVELS_DAMAGE])+&quot;.&quot;)
            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&gt;=thistype.twoPow[LEVELS_STR] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modStrBonus(&quot;+I2S(amount)+&quot;) - must not reach &gt;= &quot;+I2S(thistype.twoPow[LEVELS_STR])+&quot;.&quot;)
            debug endif
            debug if this.strBonus&lt;-thistype.twoPow[LEVELS_STR] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modStrBonus(&quot;+I2S(amount)+&quot;) - must not reach &lt; -&quot;+I2S(thistype.twoPow[LEVELS_STR])+&quot;.&quot;)
            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&gt;=thistype.twoPow[LEVELS_AGI] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modAgiBonus(&quot;+I2S(amount)+&quot;) - must not reach &gt;= &quot;+I2S(thistype.twoPow[LEVELS_AGI])+&quot;.&quot;)
            debug endif
            debug if this.agiBonus&lt;-thistype.twoPow[LEVELS_AGI] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modAgiBonus(&quot;+I2S(amount)+&quot;) - must not reach &lt; -&quot;+I2S(thistype.twoPow[LEVELS_AGI])+&quot;.&quot;)
            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&gt;=thistype.twoPow[LEVELS_INT] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modIntBonus(&quot;+I2S(amount)+&quot;) - must not reach &gt;= &quot;+I2S(thistype.twoPow[LEVELS_INT])+&quot;.&quot;)
            debug endif
            debug if this.intBonus&lt;-thistype.twoPow[LEVELS_INT] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modIntBonus(&quot;+I2S(amount)+&quot;) - must not reach &lt; -&quot;+I2S(thistype.twoPow[LEVELS_INT])+&quot;.&quot;)
            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&gt;=thistype.twoPow[LEVELS_ATTACK_SPEED] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modAttackSpeedBonus(&quot;+I2S(amount)+&quot;) - must not reach &gt;= &quot;+I2S(thistype.twoPow[LEVELS_ATTACK_SPEED])+&quot;.&quot;)
            debug endif
            debug if this.attackSpeedBonus&lt;-thistype.twoPow[LEVELS_ATTACK_SPEED] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modAttackSpeedBonus(&quot;+I2S(amount)+&quot;) - must not reach &lt; -&quot;+I2S(thistype.twoPow[LEVELS_ATTACK_SPEED])+&quot;.&quot;)
            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&gt;=thistype.twoPow[LEVELS_HEALTH] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modHealthBonus(&quot;+I2S(amount)+&quot;) - must not reach &gt;= &quot;+I2S(thistype.twoPow[LEVELS_HEALTH])+&quot;.&quot;)
            debug endif
            debug if this.healthBonus&lt;-thistype.twoPow[LEVELS_HEALTH] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modHealthBonus(&quot;+I2S(amount)+&quot;) - must not reach &lt; -&quot;+I2S(thistype.twoPow[LEVELS_HEALTH])+&quot;.&quot;)
            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&gt;=thistype.twoPow[LEVELS_MANA] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modManaBonus(&quot;+I2S(amount)+&quot;) - must not reach &gt;= &quot;+I2S(thistype.twoPow[LEVELS_MANA])+&quot;.&quot;)
            debug endif
            debug if this.manaBonus&lt;-thistype.twoPow[LEVELS_MANA] then
                debug call BJDebugMsg(&quot;Status Error: Status[&quot;+GetUnitName(this.unit)+&quot;].modManaBonus(&quot;+I2S(amount)+&quot;) - must not reach &lt; -&quot;+I2S(thistype.twoPow[LEVELS_MANA])+&quot;.&quot;)
            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&gt;0 then
                if UnitAlive(thistype.updateUnit) and this.disableLevel&lt;=0 and this.stunLevel&lt;=0 and this.pauseLevel&lt;=0 and this.immoboliseLevel&lt;=0 and GetUnitMoveSpeed(thistype.updateUnit)&gt;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 &quot;Stun&quot; 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
 

Viikuna

No Marlo no game.
Reaction score
265
You cannot stun magic immune or invulnerable units this way.

This is solved by using a dummy unit with 100% bash, like Anitarf does in his buff system.

Also, Im not really a fan of little systems like these.

I would rather see some big bad ass buff system, that allows you to create triggered custom buffs, that can have various effects, like stun, spellcast disable, attack disable and total disable, as well as stats modifying stuff, ( example: attack, armor, strength, manaregen, movespeed )

( It should probably use UnitProperties for this stats modifying stuff )

Buff system should also support some nice triggered effects, that you can apply onBuffStart and remove onBuffEnd ( or whatever names you use for that stuff ) as well as do stuff periodically during the buff duration.

edit. Actually, that stats modifying stuff can also be done in onAdd and onRemove just fine. But yea, Big
Bad Ass Buff System.

edit2. Actually, if you dont like the idea of Big Bad Ass Buff System you could convert this to something like that DummyCaster struct I used in Quicksand. People then use this for stunning, and slowing and rooting etc.

JASS:

   set Stun=Buff.create( STUN_ABILITY_ID,STUN_ORDER_ID)
   set Roots=Buff.create( ROOTS_ABILITY_ID,ROOTS_ORDER_ID)  
   
   //...

   call Stun.add( unit )
   // ...
   call Stun.remove( unit )
 

Jesus4Lyf

Good Idea™
Reaction score
397
This is solved by using a dummy unit with 100% bash, like Anitarf does in his buff system.
Can that instant cast?
Buff system should also support some nice triggered effects, that you can apply onBuffStart and remove onBuffEnd ( or whatever names you use for that stuff ) as well as do stuff periodically during the buff duration.

edit. Actually, that stats modifying stuff can also be done in onAdd and onRemove just fine. But yea, Big Bad Ass Buff System.
I dunno. All this stuff is inconsistent. Do you make it so the user has to design their own buffs and such, or is it done through a textmacro for example?

It's not like you can really give a good interface for buff stuff either way. I'd largely just write the 5 lines of code or w/e to do it myself.

Stun is needed so often. I could extend it to other effects, like Silence. I suppose it makes sense.
 

Weep

Godspeed to the sound of the pounding
Reaction score
401
This is solved by using a dummy unit with 100% bash, like Anitarf does in his buff system.
Would that work on ethereal?

Stun spells can work on magic immune if the spell is made to be an "ultimate" hero ability, and Gameplay - Magic Immunes Resist Ultimates is set to false in the Gameplay Constants. (False is the default.)

[edit] I'm not sure how this would play with the spell shield item, though, or anti-magic shell.
 

Viikuna

No Marlo no game.
Reaction score
265
Good point.

I think what Weep suggested is the way to go.
 

Weep

Godspeed to the sound of the pounding
Reaction score
401
Do you need this to work on magic immune? =/
If it can, why not? Let the user decide if they want to stun magic immune.

We can't account for everything. o.o
We can try! :D

Attacks can take effect instantly, but not "instant cast" in the sense of having one unit cast successively at once. One dummy per target would be needed.
 

Jesus4Lyf

Good Idea™
Reaction score
397
One dummy per target would be needed.
Then I'd prefer the current way.

Even so, the stun would have to either not work on ethereal units, or not work on spell immune units? So this is moot point. Makes more sense not to work on spell immune.

Lol, what if a unit had evasion?

I'm still convinced a spell has the best set of pros vs cons - and definitely the most expected.
 
Reaction score
91
You can always use Aerial Shackles but it would require 1 dummy per unit; still, it goes through magic immunes and will always "stun" your target.
 

Kenny

Back for now.
Reaction score
202
Even so, the stun would have to either not work on ethereal units, or not work on spell immune units? So this is moot point. Makes more sense not to work on spell immune.

I think he went that attacking would need one dummy per target. If you made the spell an ultimate then it would work on magic immune and ethereal.

Lol, what if a unit had evasion?

Isn't there an option on bash to not miss any attacks? Same with critical strike.

Anyways this is good. Personally, I like this for something like stun. I don't see a need for a massive system for buffs. Stuns are pretty much an integral part of warcraft, having a separate system for it is smart. Plus this works really well.

Also makes me think you should update Stack Safety with some more safety functions soon. :D
 

Weep

Godspeed to the sound of the pounding
Reaction score
401
Even so, the stun would have to either not work on ethereal units, or not work on spell immune units? So this is moot point. Makes more sense not to work on spell immune.
Heh, makes more sense to not work on ethereal, to me. They're like ghosts - how can you konk a ghost on the head? :p Besides, which situation is less common, and therefore less important to support: spell immune or ethereal?

But you're right, it is moot; as an "ultimate", the spell could stun magic immune units in most maps, which I think is good enough (and I don't see any validity to your preference to limit it at the system-level). Besides, even as a last resort, the system could use both methods, only using the attack-bash if the target is spell immune, but that's not really necessary.

Lol, what if a unit had evasion?
That's the nice thing about a 100% bash with Never Miss set true. :D
 

Viikuna

No Marlo no game.
Reaction score
265
You can always use Aerial Shackles but it would require 1 dummy per unit; still, it goes through magic immunes and will always "stun" your target.

Aerial Shackles is actually pretty good for disabling target, when you dont wanna mess your stunning functions.
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
Or the "Custom stun system" could run of the effect of the stun's buff and pause safety?

This is just an idea... :D

JASS:

function StunUnit takes unit u, real dura returns nothing
    local effect sfx = AddSpecialEffectTarget(u, STUNEFFECT, &quot;overhead&quot;)
    call TriggerSleepAction(dura)
    call DestroyEffect(sfx)
    set sfx = null
// It could even use some timer system... 
// And AIDS, of course there&#039;s not a system made by J4L that does not uses AIDS!!:exclamationmark:
endfunction
 

Jesus4Lyf

Good Idea™
Reaction score
397

Weep

Godspeed to the sound of the pounding
Reaction score
401
I don't see how to make an ability an ultimate.
Make the ability a hero ability and set its required level to something higher than 1. (...I think. Usually I set it to 6 to match the built-in abilities. In case you're concerned, you can, of course, add hero abilities to non-hero units through triggers and it'll work just fine.)

I don't want dummy-per-cast or else I wouldn't use this myself...
In case it wasn't clear, that was only needed for dummies that would attack/bash. "Ultimates" work just like normal spells, except the map can allow them to work even on spell immune units.

(Not every spell will work properly as an ultimate, but fortunately, stun does. I've tried. :))
 

Azlier

Old World Ghost
Reaction score
461
That's incredible! Ultimate abilities can be created rather than just needing to clone an existing one. Very nice.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top