System Status

Viikuna

No Marlo no game.
Reaction score
265
I think one good thing has come out so far, which is the notion of negative values for stun levels to be useful.

Nice.

Even though something, like anti stun for example, doesnt exists in normal wc3 ladder, doesnt mean that its not a good idea.

Anyways, here is my list:

-Negative values for stun, disarm, silence and ensnare.
-Add Disable. ( Especially if stun gets negative values. )

Also, do not do any lame Stun for X secs thingies, like Dusk did for UnitStatus.
If you want something like that, write a proper buff system, which supports dispelling buffs, stacking buffs, buff classes, and all kind of basic buff manipulation, like duration and level and stuff like that.

Doing your timed effects with system like that is really worth of it. That removing all buffs on unit death is just one example. ( Although you need to make sure that buff removal trigger fires after all other death triggers, in case you want to do something like: if dying unit has buff X then do stuff, which is again something which was not possible in normal wc3. )
 

Jesus4Lyf

Good Idea™
Reaction score
397
-Add Disable. ( Especially if stun gets negative values. )
Disable in Dusk's was hurl boulder - exactly the same as Stun (which was storm bolt). I don't understand why you want two stuns.
Edit: Ah. Knockbacks. Hmmm. Disable shouldn't have negative values, and Stun should. I see.
Also, do not do any lame Stun for X secs thingies, like Dusk did for UnitStatus.
I completely agree.

I don't think I can logically construct negative values for invisibility (because there are three types).
 

Jesus4Lyf

Good Idea™
Reaction score
397
Alrighty, I'm putting this forward as a BETA. I haven't actually tested it, but am about to. Just looking for feedback on this new design and implementation - in terms of the new abilities added. :)

Note that everything can be negative (except Disable).
JASS:
//
//      ___ _____ _ _____ _   _ ___ 
//     / __|_   _/_\_   _| | | / __|
//     \__ \ | |/ _ \| | | |_| \__ \    By Jesus4Lyf.
//     |___/ |_/_/ \_\_| \____/|___/          v 1.2.1
//
//      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.
//
//      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 object 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 lines (so "runtextmacro" will line up with this line):
//!          runtextmacro Status__CreateAbilities()
//
//      Methods:
//     ¯¯¯¯¯¯¯¯¯¯
//          Statuses (short list):
//              - Disable (addDisable, removeDisable, isDisabled)
//              - Stun (addStun, removeStun, isStunned)
//              - Silence (addSilence, removeSilence, isSilenced)
//              - DisarmMelee (addDisarmMelee, removeDisarmMelee, isDisarmedMelee)
//              - DisarmRange (addDisarmRange, removeDisarmRange, isDisarmedRange)
//              - Disarm (addDisarm, removeDisarm, isDisarmed) - note: 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)
//
//          Bonuses (short list):
//              - ArmorBonus (modArmorBonus, getArmorBonus)
//              - DamageBonus (modDamageBonus, getDamageBonus)
//              - StrBonus (modStrBonus, getStrBonus)
//              - AgiBonus (modAgiBonus, getAgiBonus)
//              - IntBonus (modIntBonus, getIntBonus)
//              - AttackSpeedBonus (modAttackSpeedBonus, getAttackSpeedBonus)
//
//      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.
//
library Status uses AIDS, DummyCaster
    globals
        // 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 NEGATIVE_ABIL='00B0'-'00A0'
        private constant integer ABIL_ARMOR='A5AA'
        private constant integer ABIL_DAMAGE='A5CA'
        private constant integer ABIL_STR='A5EA'
        private constant integer ABIL_AGI='A5GA'
        private constant integer ABIL_INT='A5IA'
        private constant integer ABIL_ATTACK_SPEED='A5KA'
        
        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
        
        // 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_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 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 unit CASTER_DISARM_BOTH=null
        private unit CASTER_DISARM_MELEE=null
        private unit CASTER_DISARM_RANGE=null
    endglobals
    
    private module StatusInit
        private static method onInit takes nothing returns nothing
            //! textmacro Status__CreateAbilities
                // 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,"fnsf","(Status System)")
                //! 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")
                
                // Ponder the mysteries of life...
                // Or read this line. (If it compiles, ship it.)
                // Previously used for a 3-level version of drunkenhaze.
                ///! i makechange(current,"Nsi1",0,"\00\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\00\00\00\00\4e\73\69\31\00\00\00\00\02\00\00\00\01\00\00\00\02\00\00\00\00\00\00\00\4e\73\69\31\00\00\00\00\03\00\00\00\01\00\00\00\03\00\00\00\00\00\00\00")
                
                // 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")
                //! i makechange(current,"Nsi1",0,"\00\00\00\00\01\00\00\00\01\00\00\00\03\00\00\00\00\00\00\00")
                
                // 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")
                //! i makechange(current,"Nsi1",0,"\00\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\00\00\00\00")
                
                // 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")
                //! i makechange(current,"Nsi1",0,"\00\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00\00\00\00\00")
                
                // 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)")
                
                ////////////////////
                // 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 createobject(&quot;AId1&quot;,&quot;A5B&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
                
                // Damage (15 = 32767 max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AItg&quot;,&quot;A5C&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 createobject(&quot;AItg&quot;,&quot;A5D&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
                
                // Str/Agi/Int (10 = 1023 max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AIs1&quot;,&quot;A5E&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;AIs1&quot;,&quot;A5F&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;A5G&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;AIa1&quot;,&quot;A5H&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;A5I&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 createobject(&quot;AIi1&quot;,&quot;A5J&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
                
                // Attack Speed (9 = 511% max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AIsx&quot;,&quot;A5K&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 createobject(&quot;AIsx&quot;,&quot;A5L&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
                
                // End externalblock
                //! endexternalblock
            //! endtextmacro
            set thistype.dummyCaster=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster2=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster3=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_TYPE,0,0,0)
            call UnitAddAbility(thistype.dummyCaster,ABIL_STUN)
            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)
        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
                exitwhen i==30
                set i=i+1
                set val=val*2
            endloop
        endmethod
    endmodule
    
    struct Status extends array
        private method AIDS_onCreate takes nothing returns nothing
            set this.disableLevel=0
            set this.stunLevel=0
            set this.silenceLevel=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.armorBonus=0
            set this.damageBonus=0
            set this.strBonus=0
            set this.agiBonus=0
            set this.intBonus=0
            set this.attackSpeedBonus=0
        endmethod
        //! runtextmacro AIDS()
        private static unit dummyCaster=null
        private static unit dummyCaster2=null
        private static unit dummyCaster3=null
        implement StatusInit
        implement TwoPowArray
        
        ////////////////////
        // Status Effects //
        ////////////////////
        
        // Stun
        private integer stunLevel
        private integer disableLevel
        method addStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel+1
            if this.stunLevel&gt;0 then
                call IssueTargetOrderById(thistype.dummyCaster,OID_STUN,this.unit)
            endif
        endmethod
        method removeStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel-1
            if this.stunLevel==0 and this.disableLevel&lt;=0 then
                call UnitRemoveAbility(this.unit,BUFF_STUN)
            endif
        endmethod
        method isStunned takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_STUN)&gt;0 and this.stunLevel&gt;0
        endmethod
        method addDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel+1
            if this.disableLevel&gt;0 then
                call IssueTargetOrderById(thistype.dummyCaster,OID_STUN,this.unit)
            endif
        endmethod
        method removeDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel-1
            if this.disableLevel==0 and this.stunLevel&lt;=0 then
                call UnitRemoveAbility(this.unit,BUFF_STUN)
            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 GetUnitAbilityLevel(this.unit,BUFF_STUN)&gt;0 and 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
                call IssueTargetOrderById(thistype.dummyCaster,OID_SILENCE,this.unit)
            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 GetUnitAbilityLevel(this.unit,BUFF_SILENCE)&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
                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
            endif
        endmethod
        method addDisarmRange takes nothing returns nothing
            set this.disarmRangeLevel=this.disarmRangeLevel+1
            if this.disarmRangeLevel&gt;0 then
                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
            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
                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
            else
                if this.disarmRangeLevel&gt;0 then
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                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)
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                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)
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                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)
                if this.disarmRangeLevel&gt;0 then
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                endif
            elseif this.disarmRangeLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                if this.disarmMeleeLevel&gt;0 then
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                endif
            endif
        endmethod
        method isDisarmedMelee takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_DISARM_BOTH)&gt;0 or GetUnitAbilityLevel(this.unit,BUFF_DISARM_MELEE)&gt;0
        endmethod
        method isDisarmedRange takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_DISARM_BOTH)&gt;0 or GetUnitAbilityLevel(this.unit,BUFF_DISARM_RANGE)&gt;0
        endmethod
        method isDisarmed takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_DISARM_BOTH)&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
                call IssueTargetOrderById(thistype.dummyCaster,OID_IMMOBOLISE,this.unit)
            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 UnitAddType(this.unit,UNIT_TYPE_MAGIC_IMMUNE)
            endif
        endmethod
        method removeImmunity takes nothing returns nothing
            set this.immunityLevel=this.immunityLevel-1
            if this.immunityLevel==0 then
                call UnitRemoveType(this.unit,UNIT_TYPE_MAGIC_IMMUNE)
            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
        
        ////////////////////
        // Status Bonuses //
        ////////////////////
        //! textmacro Status__ModBonus takes CURRENT, ABIL, LEVELS
            local integer abil
            local integer pow=thistype.twoPow[$LEVELS$]
            
            if amount==0 then
                return
            endif
            
            // current is 0, set to amount
            if this.$CURRENT$==0 then
                set this.$CURRENT$=amount
                
                if amount&gt;0 then
                    set abil=$ABIL$+$LEVELS$
                else
                    set abil=$ABIL$+NEGATIVE_ABIL+$LEVELS$
                    set amount=-amount
                endif
                
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if amount&gt;=pow then
                        set amount=amount-pow
                        call UnitAddAbility(this.unit,abil)
                        call UnitMakeAbilityPermanent(this.unit,true,abil)
                    endif
                    
                    if pow==1 then //exitwhen
                        return
                    endif
                endloop
            endif
            
            // random prep
            if this.$CURRENT$&gt;0 then
                set abil=$ABIL$+$LEVELS$
            else
                set abil=$ABIL$+NEGATIVE_ABIL+$LEVELS$
            endif
            
            // current + amount = 0, remove all current
            if this.$CURRENT$==-amount then
                set this.$CURRENT$=0
                
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if GetUnitAbilityLevel(this.unit,abil)&gt;0 then
                        call UnitMakeAbilityPermanent(this.unit,false,abil)
                        call UnitRemoveAbility(this.unit,abil)
                    endif
                    
                    if pow==1 then //exitwhen
                        return
                    endif
                endloop
            endif
            
            // current + amount is on the other side of 0
            if (this.$CURRENT$&lt;0 and this.$CURRENT$+amount&gt;0)or(this.$CURRENT$&gt;0 and this.$CURRENT$+amount&lt;0) then
                // remove all current
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if GetUnitAbilityLevel(this.unit,abil)&gt;0 then
                        call UnitMakeAbilityPermanent(this.unit,false,abil)
                        call UnitRemoveAbility(this.unit,abil)
                    endif
                    
                    exitwhen pow==1 // only difference
                endloop
                
                // set current to amount
                set this.$CURRENT$=amount
                
                if amount&gt;0 then
                    set abil=$ABIL$+$LEVELS$
                else
                    set abil=$ABIL$+NEGATIVE_ABIL+$LEVELS$
                    set amount=-amount
                endif
                
                // add new
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if amount&gt;=pow then
                        set amount=amount-pow
                        call UnitAddAbility(this.unit,abil)
                        call UnitMakeAbilityPermanent(this.unit,true,abil)
                    endif
                    
                    if pow==1 then //exitwhen
                        return
                    endif
                endloop
            endif
            
            // amount will leave bonus on same side of 0, neither current or amount is 0
            set amount=this.$CURRENT$+amount
            set this.$CURRENT$=amount
            if amount&lt;0 then
                set amount=-amount
            endif
            
            loop
                set pow=pow/2
                set abil=abil-1
                
                if amount&gt;=pow then
                    set amount=amount-pow
                    call UnitAddAbility(this.unit,abil)
                    call UnitMakeAbilityPermanent(this.unit,true,abil)
                elseif GetUnitAbilityLevel(this.unit,abil)&gt;0 then
                    call UnitMakeAbilityPermanent(this.unit,false,abil)
                    call UnitRemoveAbility(this.unit,abil)
                endif
                
                if pow==1 then //exitwhen
                    return
                endif
            endloop
        //! endtextmacro
        
        private integer armorBonus
        method modArmorBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;armorBonus&quot;,&quot;ABIL_ARMOR&quot;,&quot;LEVELS_ARMOR&quot;)
        endmethod
        method getArmorBonus takes nothing returns integer
            return this.armorBonus
        endmethod
        
        private integer damageBonus
        method modDamageBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;damageBonus&quot;,&quot;ABIL_DAMAGE&quot;,&quot;LEVELS_DAMAGE&quot;)
        endmethod
        method getDamageBonus takes nothing returns integer
            return this.damageBonus
        endmethod
        
        private integer strBonus
        method modStrBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;strBonus&quot;,&quot;ABIL_STR&quot;,&quot;LEVELS_STR&quot;)
        endmethod
        method getStrBonus takes nothing returns integer
            return this.strBonus
        endmethod
        
        private integer agiBonus
        method modAgiBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;agiBonus&quot;,&quot;ABIL_AGI&quot;,&quot;LEVELS_AGI&quot;)
        endmethod
        method getAgiBonus takes nothing returns integer
            return this.agiBonus
        endmethod
        
        private integer intBonus
        method modIntBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;intBonus&quot;,&quot;ABIL_INT&quot;,&quot;LEVELS_INT&quot;)
        endmethod
        method getIntBonus takes nothing returns integer
            return this.intBonus
        endmethod
        
        private integer attackSpeedBonus
        method modAttackSpeedBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;attackSpeedBonus&quot;,&quot;ABIL_ATTACK_SPEED&quot;,&quot;LEVELS_ATTACK_SPEED&quot;)
        endmethod
        method getAttackSpeedBonus takes nothing returns integer
            return this.attackSpeedBonus
        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
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>

1030 lines of object merging goodness. :p
 

RaiJin

New Member
Reaction score
40
Alrighty, I'm putting this forward as a BETA. I haven't actually tested it, but am about to. Just looking for feedback on this new design and implementation - in terms of the new abilities added. :)

Note that everything can be negative (except Disable).
JASS:
//
//      ___ _____ _ _____ _   _ ___ 
//     / __|_   _/_\_   _| | | / __|
//     \__ \ | |/ _ \| | | |_| \__ \    By Jesus4Lyf.
//     |___/ |_/_/ \_\_| \____/|___/          v 1.2.1
//
//      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 &quot;add&quot; method is called.
//
//      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 object called Status, go to &#039;Edit -&gt; Convert to
//          Custom Text&#039;, and replace everything that&#039;s there with this script.
//
//          Save the map, close it, reopen it, and then delete the &quot;!&quot; from the
//          FAR left side of the next lines (so &quot;runtextmacro&quot; will line up with this line):
//!          runtextmacro Status__CreateAbilities()
//
//      Methods:
//     ¯¯¯¯¯¯¯¯¯¯
//          Statuses (short list):
//              - Disable (addDisable, removeDisable, isDisabled)
//              - Stun (addStun, removeStun, isStunned)
//              - Silence (addSilence, removeSilence, isSilenced)
//              - DisarmMelee (addDisarmMelee, removeDisarmMelee, isDisarmedMelee)
//              - DisarmRange (addDisarmRange, removeDisarmRange, isDisarmedRange)
//              - Disarm (addDisarm, removeDisarm, isDisarmed) - note: 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)
//
//          Bonuses (short list):
//              - ArmorBonus (modArmorBonus, getArmorBonus)
//              - DamageBonus (modDamageBonus, getDamageBonus)
//              - StrBonus (modStrBonus, getStrBonus)
//              - AgiBonus (modAgiBonus, getAgiBonus)
//              - IntBonus (modIntBonus, getIntBonus)
//              - AttackSpeedBonus (modAttackSpeedBonus, getAttackSpeedBonus)
//
//      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?() --&gt; 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.
//
library Status uses AIDS, DummyCaster
    globals
        // To change these, change them also in the externalblock before executing it.
        private constant integer ABIL_STUN=&#039;A500&#039;
        private constant integer ABIL_SILENCE=&#039;A501&#039;
        private constant integer ABIL_DISARM_BOTH=&#039;A502&#039;
        private constant integer ABIL_DISARM_MELEE=&#039;A503&#039;
        private constant integer ABIL_DISARM_RANGE=&#039;A504&#039;
        private constant integer ABIL_IMMOBOLISE=&#039;A505&#039;
        private constant integer ABIL_INVISIBLE=&#039;A507&#039;
        private constant integer ABIL_GHOST=&#039;A508&#039;
        
        private constant integer NEGATIVE_ABIL=&#039;00B0&#039;-&#039;00A0&#039;
        private constant integer ABIL_ARMOR=&#039;A5AA&#039;
        private constant integer ABIL_DAMAGE=&#039;A5CA&#039;
        private constant integer ABIL_STR=&#039;A5EA&#039;
        private constant integer ABIL_AGI=&#039;A5GA&#039;
        private constant integer ABIL_INT=&#039;A5IA&#039;
        private constant integer ABIL_ATTACK_SPEED=&#039;A5KA&#039;
        
        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
        
        // To change these, change them also in the externalblock before executing it.
        private constant integer BUFF_STUN=&#039;B500&#039;
        private constant integer BUFF_SILENCE=&#039;B501&#039;
        private constant integer BUFF_DISARM_MELEE=&#039;B503&#039;
        private constant integer BUFF_DISARM_RANGE=&#039;B504&#039;
        private constant integer BUFF_DISARM_BOTH=&#039;B502&#039;
        private constant integer BUFF_IMMOBOLISE_GROUND=&#039;B505&#039;
        private constant integer BUFF_IMMOBOLISE_AIR=&#039;B506&#039;
        
        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 unit CASTER_DISARM_BOTH=null
        private unit CASTER_DISARM_MELEE=null
        private unit CASTER_DISARM_RANGE=null
    endglobals
    
    private module StatusInit
        private static method onInit takes nothing returns nothing
            //! textmacro Status__CreateAbilities
                // Start externalblock
                //! externalblock extension=lua ObjectMerger $FILENAME$
                
                ////////////////////
                // Status Effects //
                ////////////////////
                
                // Stun (X500, firebolt)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BPSE&quot;,&quot;B500&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ACfb&quot;,&quot;A500&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Stun&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;aani&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;Htb1&quot;,1,0)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;invulnerable,vulnerable&quot;)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B500&quot;)
                //! i makechange(current,&quot;aher&quot;,1)
                //! i makechange(current,&quot;arlv&quot;,6)
                
                // Silence (X501, soulburn)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BNso&quot;,&quot;B501&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Silence&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is Silenced; it cannot cast spells.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNSilence.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ANso&quot;,&quot;A501&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Silence&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;Nso1&quot;,1,0)
                //! i makechange(current,&quot;Nso3&quot;,1,0)
                //! i makechange(current,&quot;Nso2&quot;,1,99999)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B501&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;invulnerable,vulnerable&quot;)
                
                // Ponder the mysteries of life...
                // Or read this line. (If it compiles, ship it.)
                // Previously used for a 3-level version of drunkenhaze.
                ///! i makechange(current,&quot;Nsi1&quot;,0,&quot;\00\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\00\00\00\00\4e\73\69\31\00\00\00\00\02\00\00\00\01\00\00\00\02\00\00\00\00\00\00\00\4e\73\69\31\00\00\00\00\03\00\00\00\01\00\00\00\03\00\00\00\00\00\00\00&quot;)
                
                // Disarm (Both) (X502, drunkenhaze)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BNdh&quot;, &quot;B502&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Disarmed&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is Disarmed; it cannot attack.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ANdh&quot;,&quot;A502&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Disarm (Both)&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amac&quot;,0)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;Nsi2&quot;,1,0)
                //! i makechange(current,&quot;Nsi3&quot;,1,0)
                //! i makechange(current,&quot;aare&quot;,1,0)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B502&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;notself&quot;)
                //! i makechange(current,&quot;Nsi1&quot;,0,&quot;\00\00\00\00\01\00\00\00\01\00\00\00\03\00\00\00\00\00\00\00&quot;)
                
                // Disarm (Melee) (X503, drunkenhaze)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BNdh&quot;, &quot;B503&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Disarmed (Melee)&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is Disarmed; it cannot use melee attacks.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ANdh&quot;,&quot;A503&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Disarm (Melee)&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amac&quot;,0)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;Nsi2&quot;,1,0)
                //! i makechange(current,&quot;Nsi3&quot;,1,0)
                //! i makechange(current,&quot;aare&quot;,1,0)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B503&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;notself&quot;)
                //! i makechange(current,&quot;Nsi1&quot;,0,&quot;\00\00\00\00\01\00\00\00\01\00\00\00\01\00\00\00\00\00\00\00&quot;)
                
                // Disarm (Range) (X504, drunkenhaze)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BNdh&quot;, &quot;B504&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Disarmed (Ranged)&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is Disarmed; it cannot use ranged attacks.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ANdh&quot;,&quot;A504&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Disarm (Range)&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amac&quot;,0)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;Nsi2&quot;,1,0)
                //! i makechange(current,&quot;Nsi3&quot;,1,0)
                //! i makechange(current,&quot;aare&quot;,1,0)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B504&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;notself&quot;)
                //! i makechange(current,&quot;Nsi1&quot;,0,&quot;\00\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00\00\00\00\00&quot;)
                
                // Entangle (X505 - X506, ensnare)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;Beng&quot;,&quot;B505&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Immobilised&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is immobilised; it cannot move or fly.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNWirtsOtherLeg.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i createobject(&quot;Bena&quot;,&quot;B506&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Immobilised&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is immobilised; it cannot move or fly.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNWirtsOtherLeg.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;, &quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ACen&quot;,&quot;A505&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Immobilise&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;aani&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;aher&quot;,1)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;areq&quot;,&quot;&quot;)
                //! i makechange(current,&quot;Ens1&quot;,1,-1)
                //! i makechange(current,&quot;Ens2&quot;,1,-1)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B505,B506&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;notself&quot;)
                
                // Invisibility (X507)
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;Apiv&quot;,&quot;A507&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Invisibility&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ahdu&quot;,1,0.5)
                //! i makechange(current,&quot;adur&quot;,1,0.5)
                
                // Ghost (X508)
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;Agho&quot;,&quot;A508&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Ghost&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                
                ////////////////////
                // Status Bonuses //
                ////////////////////
                //! i setobjecttype(&quot;abilities&quot;)
                
                //! i myChar={}
                //! i myChar[1]=&quot;A&quot;
                //! i myChar[2]=&quot;B&quot;
                //! i myChar[3]=&quot;C&quot;
                //! i myChar[4]=&quot;D&quot;
                //! i myChar[5]=&quot;E&quot;
                //! i myChar[6]=&quot;F&quot;
                //! i myChar[7]=&quot;G&quot;
                //! i myChar[8]=&quot;H&quot;
                //! i myChar[9]=&quot;I&quot;
                //! i myChar[10]=&quot;J&quot;
                //! i myChar[11]=&quot;K&quot;
                //! i myChar[12]=&quot;L&quot;
                //! i myChar[13]=&quot;M&quot;
                //! i myChar[14]=&quot;N&quot;
                //! i myChar[15]=&quot;O&quot;
                //! i myChar[16]=&quot;P&quot;
                //! i myChar[17]=&quot;Q&quot;
                //! i myChar[18]=&quot;R&quot;
                //! i myChar[19]=&quot;S&quot;
                //! i myChar[20]=&quot;T&quot;
                //! i myChar[21]=&quot;U&quot;
                //! i myChar[22]=&quot;V&quot;
                //! i myChar[23]=&quot;W&quot;
                //! i myChar[24]=&quot;X&quot;
                //! i myChar[25]=&quot;Y&quot;
                //! i myChar[26]=&quot;Z&quot;
                
                //! 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 createobject(&quot;AId1&quot;,&quot;A5B&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
                
                // Damage (15 = 32767 max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AItg&quot;,&quot;A5C&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 createobject(&quot;AItg&quot;,&quot;A5D&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
                
                // Str/Agi/Int (10 = 1023 max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AIs1&quot;,&quot;A5E&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;AIs1&quot;,&quot;A5F&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;A5G&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;AIa1&quot;,&quot;A5H&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;A5I&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 createobject(&quot;AIi1&quot;,&quot;A5J&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
                
                // Attack Speed (9 = 511% max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AIsx&quot;,&quot;A5K&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 createobject(&quot;AIsx&quot;,&quot;A5L&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
                
                // End externalblock
                //! endexternalblock
            //! endtextmacro
            set thistype.dummyCaster=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster2=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster3=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_TYPE,0,0,0)
            call UnitAddAbility(thistype.dummyCaster,ABIL_STUN)
            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)
        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
                exitwhen i==30
                set i=i+1
                set val=val*2
            endloop
        endmethod
    endmodule
    
    struct Status extends array
        private method AIDS_onCreate takes nothing returns nothing
            set this.disableLevel=0
            set this.stunLevel=0
            set this.silenceLevel=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.armorBonus=0
            set this.damageBonus=0
            set this.strBonus=0
            set this.agiBonus=0
            set this.intBonus=0
            set this.attackSpeedBonus=0
        endmethod
        //! runtextmacro AIDS()
        private static unit dummyCaster=null
        private static unit dummyCaster2=null
        private static unit dummyCaster3=null
        implement StatusInit
        implement TwoPowArray
        
        ////////////////////
        // Status Effects //
        ////////////////////
        
        // Stun
        private integer stunLevel
        private integer disableLevel
        method addStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel+1
            if this.stunLevel&gt;0 then
                call IssueTargetOrderById(thistype.dummyCaster,OID_STUN,this.unit)
            endif
        endmethod
        method removeStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel-1
            if this.stunLevel==0 and this.disableLevel&lt;=0 then
                call UnitRemoveAbility(this.unit,BUFF_STUN)
            endif
        endmethod
        method isStunned takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_STUN)&gt;0 and this.stunLevel&gt;0
        endmethod
        method addDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel+1
            if this.disableLevel&gt;0 then
                call IssueTargetOrderById(thistype.dummyCaster,OID_STUN,this.unit)
            endif
        endmethod
        method removeDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel-1
            if this.disableLevel==0 and this.stunLevel&lt;=0 then
                call UnitRemoveAbility(this.unit,BUFF_STUN)
            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 GetUnitAbilityLevel(this.unit,BUFF_STUN)&gt;0 and 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
                call IssueTargetOrderById(thistype.dummyCaster,OID_SILENCE,this.unit)
            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 GetUnitAbilityLevel(this.unit,BUFF_SILENCE)&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
                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
            endif
        endmethod
        method addDisarmRange takes nothing returns nothing
            set this.disarmRangeLevel=this.disarmRangeLevel+1
            if this.disarmRangeLevel&gt;0 then
                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
            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
                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
            else
                if this.disarmRangeLevel&gt;0 then
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                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)
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                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)
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                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)
                if this.disarmRangeLevel&gt;0 then
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                endif
            elseif this.disarmRangeLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                if this.disarmMeleeLevel&gt;0 then
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                endif
            endif
        endmethod
        method isDisarmedMelee takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_DISARM_BOTH)&gt;0 or GetUnitAbilityLevel(this.unit,BUFF_DISARM_MELEE)&gt;0
        endmethod
        method isDisarmedRange takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_DISARM_BOTH)&gt;0 or GetUnitAbilityLevel(this.unit,BUFF_DISARM_RANGE)&gt;0
        endmethod
        method isDisarmed takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_DISARM_BOTH)&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
                call IssueTargetOrderById(thistype.dummyCaster,OID_IMMOBOLISE,this.unit)
            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 UnitAddType(this.unit,UNIT_TYPE_MAGIC_IMMUNE)
            endif
        endmethod
        method removeImmunity takes nothing returns nothing
            set this.immunityLevel=this.immunityLevel-1
            if this.immunityLevel==0 then
                call UnitRemoveType(this.unit,UNIT_TYPE_MAGIC_IMMUNE)
            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
        
        ////////////////////
        // Status Bonuses //
        ////////////////////
        //! textmacro Status__ModBonus takes CURRENT, ABIL, LEVELS
            local integer abil
            local integer pow=thistype.twoPow[$LEVELS$]
            
            if amount==0 then
                return
            endif
            
            // current is 0, set to amount
            if this.$CURRENT$==0 then
                set this.$CURRENT$=amount
                
                if amount&gt;0 then
                    set abil=$ABIL$+$LEVELS$
                else
                    set abil=$ABIL$+NEGATIVE_ABIL+$LEVELS$
                    set amount=-amount
                endif
                
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if amount&gt;=pow then
                        set amount=amount-pow
                        call UnitAddAbility(this.unit,abil)
                        call UnitMakeAbilityPermanent(this.unit,true,abil)
                    endif
                    
                    if pow==1 then //exitwhen
                        return
                    endif
                endloop
            endif
            
            // random prep
            if this.$CURRENT$&gt;0 then
                set abil=$ABIL$+$LEVELS$
            else
                set abil=$ABIL$+NEGATIVE_ABIL+$LEVELS$
            endif
            
            // current + amount = 0, remove all current
            if this.$CURRENT$==-amount then
                set this.$CURRENT$=0
                
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if GetUnitAbilityLevel(this.unit,abil)&gt;0 then
                        call UnitMakeAbilityPermanent(this.unit,false,abil)
                        call UnitRemoveAbility(this.unit,abil)
                    endif
                    
                    if pow==1 then //exitwhen
                        return
                    endif
                endloop
            endif
            
            // current + amount is on the other side of 0
            if (this.$CURRENT$&lt;0 and this.$CURRENT$+amount&gt;0)or(this.$CURRENT$&gt;0 and this.$CURRENT$+amount&lt;0) then
                // remove all current
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if GetUnitAbilityLevel(this.unit,abil)&gt;0 then
                        call UnitMakeAbilityPermanent(this.unit,false,abil)
                        call UnitRemoveAbility(this.unit,abil)
                    endif
                    
                    exitwhen pow==1 // only difference
                endloop
                
                // set current to amount
                set this.$CURRENT$=amount
                
                if amount&gt;0 then
                    set abil=$ABIL$+$LEVELS$
                else
                    set abil=$ABIL$+NEGATIVE_ABIL+$LEVELS$
                    set amount=-amount
                endif
                
                // add new
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if amount&gt;=pow then
                        set amount=amount-pow
                        call UnitAddAbility(this.unit,abil)
                        call UnitMakeAbilityPermanent(this.unit,true,abil)
                    endif
                    
                    if pow==1 then //exitwhen
                        return
                    endif
                endloop
            endif
            
            // amount will leave bonus on same side of 0, neither current or amount is 0
            set amount=this.$CURRENT$+amount
            set this.$CURRENT$=amount
            if amount&lt;0 then
                set amount=-amount
            endif
            
            loop
                set pow=pow/2
                set abil=abil-1
                
                if amount&gt;=pow then
                    set amount=amount-pow
                    call UnitAddAbility(this.unit,abil)
                    call UnitMakeAbilityPermanent(this.unit,true,abil)
                elseif GetUnitAbilityLevel(this.unit,abil)&gt;0 then
                    call UnitMakeAbilityPermanent(this.unit,false,abil)
                    call UnitRemoveAbility(this.unit,abil)
                endif
                
                if pow==1 then //exitwhen
                    return
                endif
            endloop
        //! endtextmacro
        
        private integer armorBonus
        method modArmorBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;armorBonus&quot;,&quot;ABIL_ARMOR&quot;,&quot;LEVELS_ARMOR&quot;)
        endmethod
        method getArmorBonus takes nothing returns integer
            return this.armorBonus
        endmethod
        
        private integer damageBonus
        method modDamageBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;damageBonus&quot;,&quot;ABIL_DAMAGE&quot;,&quot;LEVELS_DAMAGE&quot;)
        endmethod
        method getDamageBonus takes nothing returns integer
            return this.damageBonus
        endmethod
        
        private integer strBonus
        method modStrBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;strBonus&quot;,&quot;ABIL_STR&quot;,&quot;LEVELS_STR&quot;)
        endmethod
        method getStrBonus takes nothing returns integer
            return this.strBonus
        endmethod
        
        private integer agiBonus
        method modAgiBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;agiBonus&quot;,&quot;ABIL_AGI&quot;,&quot;LEVELS_AGI&quot;)
        endmethod
        method getAgiBonus takes nothing returns integer
            return this.agiBonus
        endmethod
        
        private integer intBonus
        method modIntBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;intBonus&quot;,&quot;ABIL_INT&quot;,&quot;LEVELS_INT&quot;)
        endmethod
        method getIntBonus takes nothing returns integer
            return this.intBonus
        endmethod
        
        private integer attackSpeedBonus
        method modAttackSpeedBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;attackSpeedBonus&quot;,&quot;ABIL_ATTACK_SPEED&quot;,&quot;LEVELS_ATTACK_SPEED&quot;)
        endmethod
        method getAttackSpeedBonus takes nothing returns integer
            return this.attackSpeedBonus
        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
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>

1030 lines of object merging goodness. :p


JESUS that is freaking AMAZING, seriously, but if i use a wait to remove it like you did in your example, would it be inaccurate?

one more question xD

if i were to use that dummy caster to cast it on 10 units INSTANTLY, would it actually cast it on all 10? because sometimes it'll only cast it on the last unit
 

Jesus4Lyf

Good Idea™
Reaction score
397
if i use a wait to remove it like you did in your example, would it be inaccurate?
As inaccurate as waits are. One should use a timer system instead. There's still some bugs in that version I posted, by the way, for example, the drunken brawler spell does not install correctly (and I don't suspect I can fix it anymore).
if i were to use that dummy caster to cast it on 10 units INSTANTLY, would it actually cast it on all 10? because sometimes it'll only cast it on the last unit
'Tis the point of DummyCaster. It should cast on all 10. :thup:

Testing it will probably take longer than writing it did, and writing it took a while, but thanks for the feedback and questions. :)

Edit: After some careful thought, I also realised I did the negative bonuses in the worst possible way... I will revise them some time to use one negative ability, but in the mean time the interface is what's important to me.

Edit2: I've noticed that everything seems to work except the drunken brawler object merger stuff (the hotfix didn't help), and my attempt at applying spell immunity. I expect I'll use a spellbook for spell immunity, and i'll document how to implement the drunken brawler stuff. As well as that, I'll get around to reworking how I implement negative bonuses. :p
 

RaiJin

New Member
Reaction score
40
weird but i can't save when I imported Status 1.2.1 :/

it says that the private method OnInit is redeclared because AIDS on init and StatusInit is clashing
 

the Immortal

I know, I know...
Reaction score
51
For max life/mana may I suggest abusing that lovely bug with bonus item abilities using base 5 f. ex.? Managed to write an amusingly simple script able to add 1 000 000 hp to 100 units simultaneously with a real slight delay using only 2 abils of 7 levels (3125 per add) each. Making them abils with 8-9 levels should make em.. well.. limitless.
 

Jesus4Lyf

Good Idea™
Reaction score
397
updated it, same problem though ;(
Doesn't make sense, there is no init in the struct. The inits are moved to modules. The AIDS init has nothing to conflict with... <_<

Here's an update, now with Doom (such a cool status effect...) and working spell immunity effect. I have also documented how to implement it properly. I have also tested that all add/removes work.
JASS:
//
//      ___ _____ _ _____ _   _ ___ 
//     / __|_   _/_\_   _| | | / __|
//     \__ \ | |/ _ \| | | |_| \__ \    By Jesus4Lyf.
//     |___/ |_/_/ \_\_| \____/|___/          v 1.2.2
//
//      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 &quot;add&quot; method is called.
//
//      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 object called Status, go to &#039;Edit -&gt; Convert to
//          Custom Text&#039;, and replace everything that&#039;s there with this script.
//
//          Save the map, close it, reopen it, and then delete the &quot;!&quot; from the
//          FAR left side of the next lines (so &quot;runtextmacro&quot; will line up with this line):
//!          runtextmacro Status__CreateAbilities()
//
//          Go to the object editor, and select abilities. Go to Special &gt; 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) - note: 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)
//
//          Bonuses (short list):
//              - ArmorBonus (modArmorBonus, getArmorBonus)
//              - DamageBonus (modDamageBonus, getDamageBonus)
//              - StrBonus (modStrBonus, getStrBonus)
//              - AgiBonus (modAgiBonus, getAgiBonus)
//              - IntBonus (modIntBonus, getIntBonus)
//              - AttackSpeedBonus (modAttackSpeedBonus, getAttackSpeedBonus)
//
//      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?() --&gt; 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.
//
library Status uses AIDS, DummyCaster
    globals
        // To change these, change them also in the externalblock before executing it.
        private constant integer ABIL_STUN=&#039;A500&#039;
        private constant integer ABIL_SILENCE=&#039;A501&#039;
        private constant integer ABIL_DISARM_BOTH=&#039;A502&#039;
        private constant integer ABIL_DISARM_MELEE=&#039;A503&#039;
        private constant integer ABIL_DISARM_RANGE=&#039;A504&#039;
        private constant integer ABIL_IMMOBOLISE=&#039;A505&#039;
        private constant integer ABIL_INVISIBLE=&#039;A507&#039;
        private constant integer ABIL_GHOST=&#039;A508&#039;
        private constant integer ABIL_DOOM=&#039;A509&#039;
        private constant integer ABIL_IMMUNITY=&#039;A50B&#039;
        
        private constant integer NEGATIVE_ABIL=&#039;00B0&#039;-&#039;00A0&#039;
        private constant integer ABIL_ARMOR=&#039;A5AA&#039;
        private constant integer ABIL_DAMAGE=&#039;A5CA&#039;
        private constant integer ABIL_STR=&#039;A5EA&#039;
        private constant integer ABIL_AGI=&#039;A5GA&#039;
        private constant integer ABIL_INT=&#039;A5IA&#039;
        private constant integer ABIL_ATTACK_SPEED=&#039;A5KA&#039;
        
        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
        
        // To change these, change them also in the externalblock before executing it.
        private constant integer BUFF_STUN=&#039;B500&#039;
        private constant integer BUFF_SILENCE=&#039;B501&#039;
        private constant integer BUFF_DOOM=&#039;B509&#039;
        private constant integer BUFF_DISARM_MELEE=&#039;B503&#039;
        private constant integer BUFF_DISARM_RANGE=&#039;B504&#039;
        private constant integer BUFF_DISARM_BOTH=&#039;B502&#039;
        private constant integer BUFF_IMMOBOLISE_GROUND=&#039;B505&#039;
        private constant integer BUFF_IMMOBOLISE_AIR=&#039;B506&#039;
        
        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 unit CASTER_DISARM_BOTH=null
        private unit CASTER_DISARM_MELEE=null
        private unit CASTER_DISARM_RANGE=null
    endglobals
    
    private module StatusInit
        private static method onInit takes nothing returns nothing
            local integer i
            //! textmacro Status__CreateAbilities
                // Start externalblock
                //! externalblock extension=lua ObjectMerger $FILENAME$
                
                ////////////////////
                // Status Effects //
                ////////////////////
                
                // Stun (X500, firebolt)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BPSE&quot;,&quot;B500&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ACfb&quot;,&quot;A500&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Stun&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;aani&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;Htb1&quot;,1,0)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;invulnerable,vulnerable&quot;)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B500&quot;)
                //! i makechange(current,&quot;aher&quot;,1)
                //! i makechange(current,&quot;arlv&quot;,6)
                
                // Silence (X501, soulburn)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BNso&quot;,&quot;B501&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Silence&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is Silenced; it cannot cast spells.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNSilence.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ANso&quot;,&quot;A501&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Silence&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;Nso1&quot;,1,0)
                //! i makechange(current,&quot;Nso3&quot;,1,0)
                //! i makechange(current,&quot;Nso2&quot;,1,99999)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B501&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;invulnerable,vulnerable&quot;)
                
                // Disarm (Both) (X502, drunkenhaze)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BNdh&quot;, &quot;B502&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Disarmed&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is Disarmed; it cannot attack.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ANdh&quot;,&quot;A502&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Disarm (Both)&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amac&quot;,0)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;Nsi2&quot;,1,0)
                //! i makechange(current,&quot;Nsi3&quot;,1,0)
                //! i makechange(current,&quot;aare&quot;,1,0)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B502&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;notself&quot;)
                
                // Disarm (Melee) (X503, drunkenhaze)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BNdh&quot;, &quot;B503&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Disarmed (Melee)&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is Disarmed; it cannot use melee attacks.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ANdh&quot;,&quot;A503&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Disarm (Melee)&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amac&quot;,0)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;Nsi2&quot;,1,0)
                //! i makechange(current,&quot;Nsi3&quot;,1,0)
                //! i makechange(current,&quot;aare&quot;,1,0)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B503&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;notself&quot;)
                
                // Disarm (Range) (X504, drunkenhaze)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BNdh&quot;, &quot;B504&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Disarmed (Ranged)&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is Disarmed; it cannot use ranged attacks.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNBattleStations.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ANdh&quot;,&quot;A504&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Disarm (Range)&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amac&quot;,0)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;Nsi2&quot;,1,0)
                //! i makechange(current,&quot;Nsi3&quot;,1,0)
                //! i makechange(current,&quot;aare&quot;,1,0)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B504&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;notself&quot;)
                
                // Entangle (X505 - X506, ensnare)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;Beng&quot;,&quot;B505&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Immobilised&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is immobilised; it cannot move or fly.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNWirtsOtherLeg.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                
                //! i createobject(&quot;Bena&quot;,&quot;B506&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftip&quot;,&quot;Immobilised&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit is immobilised; it cannot move or fly.&quot;)
                //! i makechange(current,&quot;fart&quot;,&quot;ReplaceableTextures\\CommandButtons\\BTNWirtsOtherLeg.blp&quot;)
                //! i makechange(current,&quot;ftat&quot;, &quot;&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ACen&quot;,&quot;A505&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Immobilise&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;aani&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;amsp&quot;,0)
                //! i makechange(current,&quot;aher&quot;,1)
                //! i makechange(current,&quot;arlv&quot;,6)
                //! i makechange(current,&quot;alev&quot;,1)
                //! i makechange(current,&quot;areq&quot;,&quot;&quot;)
                //! i makechange(current,&quot;Ens1&quot;,1,-1)
                //! i makechange(current,&quot;Ens2&quot;,1,-1)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B505,B506&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;ahdu&quot;,1,0)
                //! i makechange(current,&quot;adur&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;notself&quot;)
                
                // Invisibility (X507)
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;Apiv&quot;,&quot;A507&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Invisibility&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ahdu&quot;,1,0.5)
                //! i makechange(current,&quot;adur&quot;,1,0.5)
                
                // Ghost (X508)
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;Agho&quot;,&quot;A508&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Ghost&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                
                // Doom (X509, doom)
                //! i setobjecttype(&quot;buffs&quot;)
                //! i createobject(&quot;BNdo&quot;,&quot;B509&quot;)
                //! i makechange(current,&quot;frac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;fnsf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;ftat&quot;,&quot;&quot;)
                //! i makechange(current,&quot;fube&quot;,&quot;This unit has been stricken with Doom; it cannot cast spells.&quot;)
                
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;ANdo&quot;,&quot;A509&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Doom&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;aani&quot;,&quot;&quot;)
                //! i makechange(current,&quot;Ndo1&quot;,1,0)
                //! i makechange(current,&quot;Ndo2&quot;,1,0)
                //! i makechange(current,&quot;Ndo3&quot;,1,0)
                //! i makechange(current,&quot;aran&quot;,1,99999)
                //! i makechange(current,&quot;abuf&quot;,1,&quot;B509&quot;)
                //! i makechange(current,&quot;acdn&quot;,1,0)
                //! i makechange(current,&quot;amcs&quot;,1,0)
                //! i makechange(current,&quot;atar&quot;,1,&quot;notself&quot;)
                
                // Spell Immunity (X50A - X50B)
                //! i setobjecttype(&quot;abilities&quot;)
                //! i createobject(&quot;Amim&quot;,&quot;A50A&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Spell Immunity&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                
                //! i createobject(&quot;Aspb&quot;,&quot;A50B&quot;)
                //! i makechange(current,&quot;aart&quot;,&quot;&quot;)
                //! i makechange(current,&quot;arac&quot;,&quot;other&quot;)
                //! i makechange(current,&quot;anam&quot;,&quot;Spell Immunity&quot;)
                //! i makechange(current,&quot;ansf&quot;,&quot;(Status System)&quot;)
                //! i makechange(current,&quot;spb5&quot;,1,&quot;&quot;)
                //! i makechange(current,&quot;spb4&quot;,1,1)
                //! i makechange(current,&quot;spb3&quot;,1,1)
                //! i makechange(current,&quot;spb1&quot;,1,&quot;A50A&quot;)
                
                ////////////////////
                // Status Bonuses //
                ////////////////////
                //! i setobjecttype(&quot;abilities&quot;)
                
                //! i myChar={}
                //! i myChar[1]=&quot;A&quot;
                //! i myChar[2]=&quot;B&quot;
                //! i myChar[3]=&quot;C&quot;
                //! i myChar[4]=&quot;D&quot;
                //! i myChar[5]=&quot;E&quot;
                //! i myChar[6]=&quot;F&quot;
                //! i myChar[7]=&quot;G&quot;
                //! i myChar[8]=&quot;H&quot;
                //! i myChar[9]=&quot;I&quot;
                //! i myChar[10]=&quot;J&quot;
                //! i myChar[11]=&quot;K&quot;
                //! i myChar[12]=&quot;L&quot;
                //! i myChar[13]=&quot;M&quot;
                //! i myChar[14]=&quot;N&quot;
                //! i myChar[15]=&quot;O&quot;
                //! i myChar[16]=&quot;P&quot;
                //! i myChar[17]=&quot;Q&quot;
                //! i myChar[18]=&quot;R&quot;
                //! i myChar[19]=&quot;S&quot;
                //! i myChar[20]=&quot;T&quot;
                //! i myChar[21]=&quot;U&quot;
                //! i myChar[22]=&quot;V&quot;
                //! i myChar[23]=&quot;W&quot;
                //! i myChar[24]=&quot;X&quot;
                //! i myChar[25]=&quot;Y&quot;
                //! i myChar[26]=&quot;Z&quot;
                
                //! 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 createobject(&quot;AId1&quot;,&quot;A5B&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
                
                // Damage (15 = 32767 max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AItg&quot;,&quot;A5C&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 createobject(&quot;AItg&quot;,&quot;A5D&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
                
                // Str/Agi/Int (10 = 1023 max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AIs1&quot;,&quot;A5E&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;AIs1&quot;,&quot;A5F&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;A5G&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;AIa1&quot;,&quot;A5H&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;A5I&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 createobject(&quot;AIi1&quot;,&quot;A5J&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
                
                // Attack Speed (9 = 511% max)
                //! i for i=1,15 do
                    //! i createobject(&quot;AIsx&quot;,&quot;A5K&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 createobject(&quot;AIsx&quot;,&quot;A5L&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
                
                // End externalblock
                //! endexternalblock
            //! endtextmacro
            set thistype.dummyCaster=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster2=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_TYPE,0,0,0)
            set thistype.dummyCaster3=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_TYPE,0,0,0)
            call UnitAddAbility(thistype.dummyCaster,ABIL_STUN)
            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)
            set i=bj_MAX_PLAYERS
            loop
                set i=i-1
                call SetPlayerAbilityAvailable(Player(i),ABIL_IMMUNITY,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
                exitwhen i==30
                set i=i+1
                set val=val*2
            endloop
        endmethod
    endmodule
    
    struct Status extends array
        private method AIDS_onCreate takes nothing returns nothing
            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.armorBonus=0
            set this.damageBonus=0
            set this.strBonus=0
            set this.agiBonus=0
            set this.intBonus=0
            set this.attackSpeedBonus=0
        endmethod
        //! runtextmacro AIDS()
        private static unit dummyCaster=null
        private static unit dummyCaster2=null
        private static unit dummyCaster3=null
        implement StatusInit
        implement TwoPowArray
        
        ////////////////////
        // Status Effects //
        ////////////////////
        
        // Stun
        private integer stunLevel
        private integer disableLevel
        method addStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel+1
            if this.stunLevel&gt;0 then
                call IssueTargetOrderById(thistype.dummyCaster,OID_STUN,this.unit)
            endif
        endmethod
        method removeStun takes nothing returns nothing
            set this.stunLevel=this.stunLevel-1
            if this.stunLevel==0 and this.disableLevel&lt;=0 then
                call UnitRemoveAbility(this.unit,BUFF_STUN)
            endif
        endmethod
        method isStunned takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_STUN)&gt;0 and this.stunLevel&gt;0
        endmethod
        method addDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel+1
            if this.disableLevel&gt;0 then
                call IssueTargetOrderById(thistype.dummyCaster,OID_STUN,this.unit)
            endif
        endmethod
        method removeDisable takes nothing returns nothing
            set this.disableLevel=this.disableLevel-1
            if this.disableLevel==0 and this.stunLevel&lt;=0 then
                call UnitRemoveAbility(this.unit,BUFF_STUN)
            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 GetUnitAbilityLevel(this.unit,BUFF_STUN)&gt;0 and 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
                call IssueTargetOrderById(thistype.dummyCaster,OID_SILENCE,this.unit)
            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 GetUnitAbilityLevel(this.unit,BUFF_SILENCE)&gt;0
        endmethod
        
        private integer doomLevel
        method addDoom takes nothing returns nothing
            set this.doomLevel=this.doomLevel+1
            if this.doomLevel&gt;0 then
                call IssueTargetOrderById(thistype.dummyCaster,OID_DOOM,this.unit)
            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 GetUnitAbilityLevel(this.unit,BUFF_DOOM)&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
                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
            endif
        endmethod
        method addDisarmRange takes nothing returns nothing
            set this.disarmRangeLevel=this.disarmRangeLevel+1
            if this.disarmRangeLevel&gt;0 then
                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
            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
                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
            else
                if this.disarmRangeLevel&gt;0 then
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                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)
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                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)
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                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)
                if this.disarmRangeLevel&gt;0 then
                    call IssueTargetOrderById(CASTER_DISARM_RANGE,OID_DISARM,this.unit)
                endif
            elseif this.disarmRangeLevel==0 then
                call UnitRemoveAbility(this.unit,BUFF_DISARM_BOTH)
                if this.disarmMeleeLevel&gt;0 then
                    call IssueTargetOrderById(CASTER_DISARM_MELEE,OID_DISARM,this.unit)
                endif
            endif
        endmethod
        method isDisarmedMelee takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_DISARM_BOTH)&gt;0 or GetUnitAbilityLevel(this.unit,BUFF_DISARM_MELEE)&gt;0
        endmethod
        method isDisarmedRange takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_DISARM_BOTH)&gt;0 or GetUnitAbilityLevel(this.unit,BUFF_DISARM_RANGE)&gt;0
        endmethod
        method isDisarmed takes nothing returns boolean
            return GetUnitAbilityLevel(this.unit,BUFF_DISARM_BOTH)&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
                call IssueTargetOrderById(thistype.dummyCaster,OID_IMMOBOLISE,this.unit)
            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
        
        ////////////////////
        // Status Bonuses //
        ////////////////////
        //! textmacro Status__ModBonus takes CURRENT, ABIL, LEVELS
            local integer abil
            local integer pow=thistype.twoPow[$LEVELS$]
            
            if amount==0 then
                return
            endif
            
            // current is 0, set to amount
            if this.$CURRENT$==0 then
                set this.$CURRENT$=amount
                
                if amount&gt;0 then
                    set abil=$ABIL$+$LEVELS$
                else
                    set abil=$ABIL$+NEGATIVE_ABIL+$LEVELS$
                    set amount=-amount
                endif
                
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if amount&gt;=pow then
                        set amount=amount-pow
                        call UnitAddAbility(this.unit,abil)
                        call UnitMakeAbilityPermanent(this.unit,true,abil)
                    endif
                    
                    if pow==1 then //exitwhen
                        return
                    endif
                endloop
            endif
            
            // random prep
            if this.$CURRENT$&gt;0 then
                set abil=$ABIL$+$LEVELS$
            else
                set abil=$ABIL$+NEGATIVE_ABIL+$LEVELS$
            endif
            
            // current + amount = 0, remove all current
            if this.$CURRENT$==-amount then
                set this.$CURRENT$=0
                
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if GetUnitAbilityLevel(this.unit,abil)&gt;0 then
                        call UnitMakeAbilityPermanent(this.unit,false,abil)
                        call UnitRemoveAbility(this.unit,abil)
                    endif
                    
                    if pow==1 then //exitwhen
                        return
                    endif
                endloop
            endif
            
            // current + amount is on the other side of 0
            if (this.$CURRENT$&lt;0 and this.$CURRENT$+amount&gt;0)or(this.$CURRENT$&gt;0 and this.$CURRENT$+amount&lt;0) then
                // remove all current
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if GetUnitAbilityLevel(this.unit,abil)&gt;0 then
                        call UnitMakeAbilityPermanent(this.unit,false,abil)
                        call UnitRemoveAbility(this.unit,abil)
                    endif
                    
                    exitwhen pow==1 // only difference
                endloop
                
                // set current to amount
                set this.$CURRENT$=amount
                
                if amount&gt;0 then
                    set abil=$ABIL$+$LEVELS$
                else
                    set abil=$ABIL$+NEGATIVE_ABIL+$LEVELS$
                    set amount=-amount
                endif
                
                // add new
                loop
                    set pow=pow/2
                    set abil=abil-1
                    
                    if amount&gt;=pow then
                        set amount=amount-pow
                        call UnitAddAbility(this.unit,abil)
                        call UnitMakeAbilityPermanent(this.unit,true,abil)
                    endif
                    
                    if pow==1 then //exitwhen
                        return
                    endif
                endloop
            endif
            
            // amount will leave bonus on same side of 0, neither current or amount is 0
            set amount=this.$CURRENT$+amount
            set this.$CURRENT$=amount
            if amount&lt;0 then
                set amount=-amount
            endif
            
            loop
                set pow=pow/2
                set abil=abil-1
                
                if amount&gt;=pow then
                    set amount=amount-pow
                    call UnitAddAbility(this.unit,abil)
                    call UnitMakeAbilityPermanent(this.unit,true,abil)
                elseif GetUnitAbilityLevel(this.unit,abil)&gt;0 then
                    call UnitMakeAbilityPermanent(this.unit,false,abil)
                    call UnitRemoveAbility(this.unit,abil)
                endif
                
                if pow==1 then //exitwhen
                    return
                endif
            endloop
        //! endtextmacro
        
        private integer armorBonus
        method modArmorBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;armorBonus&quot;,&quot;ABIL_ARMOR&quot;,&quot;LEVELS_ARMOR&quot;)
        endmethod
        method getArmorBonus takes nothing returns integer
            return this.armorBonus
        endmethod
        
        private integer damageBonus
        method modDamageBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;damageBonus&quot;,&quot;ABIL_DAMAGE&quot;,&quot;LEVELS_DAMAGE&quot;)
        endmethod
        method getDamageBonus takes nothing returns integer
            return this.damageBonus
        endmethod
        
        private integer strBonus
        method modStrBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;strBonus&quot;,&quot;ABIL_STR&quot;,&quot;LEVELS_STR&quot;)
        endmethod
        method getStrBonus takes nothing returns integer
            return this.strBonus
        endmethod
        
        private integer agiBonus
        method modAgiBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;agiBonus&quot;,&quot;ABIL_AGI&quot;,&quot;LEVELS_AGI&quot;)
        endmethod
        method getAgiBonus takes nothing returns integer
            return this.agiBonus
        endmethod
        
        private integer intBonus
        method modIntBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;intBonus&quot;,&quot;ABIL_INT&quot;,&quot;LEVELS_INT&quot;)
        endmethod
        method getIntBonus takes nothing returns integer
            return this.intBonus
        endmethod
        
        private integer attackSpeedBonus
        method modAttackSpeedBonus takes integer amount returns nothing
            //! runtextmacro Status__ModBonus(&quot;attackSpeedBonus&quot;,&quot;ABIL_ATTACK_SPEED&quot;,&quot;LEVELS_ATTACK_SPEED&quot;)
        endmethod
        method getAttackSpeedBonus takes nothing returns integer
            return this.attackSpeedBonus
        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
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>

Line count's 1102. Next I need to change negative bonuses to use one ability, then this is set to release again, I believe.

Doom is seriously an awesome effect. It reduces a unit to moving and attacking only, as in they can't pick hero abilities or use items either. :)

Edit: Oh, I want to try to add locust to this as well, as an effect. We'll see if it's possible to remove completely. ;)
Edit2: Figured out how to remove it completely, yay (including single click selection). Just tidying it up before I post it. Also added hex, and must note to self to add banish.
 

RaiJin

New Member
Reaction score
40
JASS:
struct Status extends array
        private method AIDS_onCreate takes nothing returns nothing
            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.armorBonus=0
            set this.damageBonus=0
            set this.strBonus=0
            set this.agiBonus=0
            set this.intBonus=0
            set this.attackSpeedBonus=0
        endmethod
        //! runtextmacro AIDS() &lt;--- THISS
        private static unit dummyCaster=null
        private static unit dummyCaster2=null
        private static unit dummyCaster3=null
        implement StatusInit &lt;-- THIS
        implement TwoPowArray


this part it says that init function redeclared
 

Jesus4Lyf

Good Idea™
Reaction score
397
this part it says that init function redeclared
Check in NewGen what version of JassHelper you're using. In NewGen (JassHelper > About, or something like that). :)

Alright, added Locust, Banish, NeverMiss, AlwaysMiss and Untouchable (100% evasion). Next I need to fix the way negative bonus mods work.
It is now 1381 lines and is too long to fit in this post.

.removeLocust() works really well. It completely restores most units to their previous state. It doesn't seem to work on summoned flying units. <_<
So yay for figuring out a way to do that. :D
 

RaiJin

New Member
Reaction score
40
jesus are you goin to add slow? that would be pretty awesome

and all of these support negative values? or soon to be?
 

Jesus4Lyf

Good Idea™
Reaction score
397
jesus are you goin to add slow? that would be pretty awesome
Hope to, using a MSX/T32 plug-in (no 522 move speed cap).
and all of these support negative values? or soon to be?
All except Disable support negative values (disable should not, it's for things like knock backs). :)
 

RaiJin

New Member
Reaction score
40
what about making this system being able to do durations?

like StunUnit(unit,duration)? that would be completely awesome
 

Jesus4Lyf

Good Idea™
Reaction score
397
what about making this system being able to do durations?

like StunUnit(unit,duration)? that would be completely awesome
Better off using TimerUtils, a buff system, or SpellStruct to handle this. Actually, a couple of pages back there was a big discussion on this.

Released Version 1.2.3 on the first page. I had to attach it as a text file since it otherwise won't fit. The text file is bigger than the demo map. It features so much crap I can't be bothered mentioning it. I've also tested it to a reasonable degree. :)

Hoping for moderator review. :)
 

Nexor

...
Reaction score
74
Why does the example map have only one example function?
Stun all units for 5 seconds, duh

Some other examples could show the real power of Status
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top