(vJass) CustomAura (Test it)

Status
Not open for further replies.
Sure, here you go.

JASS:
library CustomAura requires GroupUtils, Table optional CABuff
    
    globals
        private constant real PERIOD = 0.0375
    endglobals

    private interface eventHandler
        method onLoop takes nothing returns nothing defaults nothing
        method onRegister takes unit theUnit returns nothing defaults nothing
        method onUnregister takes unit theUnit returns nothing defaults nothing
        method onStart takes nothing returns nothing defaults nothing
        method onEnd takes nothing returns nothing defaults nothing
        method getRadius takes nothing returns real defaults 0.
        method unitFilter takes unit theUnit returns boolean defaults true
    endinterface
    
    struct CustomAura extends eventHandler
        public              unit            theUnit         = null
        private             group           affect          = null
        private             group           last            = null
        public              boolean         isAlive         = true
        public              boolean         isPaused        = false
        private             boolean         hasStarted      = false
        
        //: == ---------------------------- ---------------------------- 
        //: #  Indexing & Structstuff
        //: == ---------------------------- ---------------------------- 
        private             integer         index           = 0
        private static      thistype        curInstance     = 0
        private static      timer           t               = null
        private static      integer         a               = 0
        private static      thistype        array           i
        
        implement TableMacros
        public static method create takes unit theUnit returns thistype
            local thistype this = thistype.allocate()
            
            set .affect = NewGroup()
            set .last = NewGroup()
            set .theUnit = theUnit
            
            set .index              = thistype.a
            set thistype.i[.index]  = this
            set thistype.a          = thistype.a +1
            if thistype.a == 1 then
                call TimerStart(thistype.t, PERIOD, true, function thistype.run)
            endif
            
            return this
        endmethod
        
        public method isUnitAffected takes unit theUnit returns boolean
            return IsUnitInGroup(theUnit, .affect)
        endmethod
        
        public method affectUnit takes unit theUnit returns nothing
            call GroupAddUnit(.affect, theUnit)
            if not IsUnitInGroup(theUnit, .last) then
                call .onRegister(theUnit)
            endif
        endmethod
        
        public method unaffectUnit takes unit theUnit returns nothing
            if not IsUnitInGroup(theUnit, .affect) then
                call GroupRemoveUnit(.last, theUnit)
                call .onUnregister(theUnit)
            endif
        endmethod
        
        private static method unaffectAllEnum takes nothing returns nothing
            local thistype this = thistype.curInstance
            call .unaffectUnit(GetEnumUnit())
        endmethod
        
        public method unaffectAll takes nothing returns nothing
            set thistype.curInstance = this
            call GroupClear(.affect)
            call ForGroup(.last, function thistype.unaffectAllEnum)
        endmethod
        
        private static method tryRegister takes nothing returns boolean
            local thistype this = thistype.curInstance
            local unit u = GetFilterUnit()
            
            if .unitFilter(u) then
                call .affectUnit(u)
            endif
            
            set u = null
            return false
        endmethod
        
        private static method tryUnregister takes nothing returns nothing
            local thistype this = thistype.curInstance
            local unit u = GetEnumUnit()
            
            call .unaffectUnit(u)
            
            set u = null
        endmethod
        
        private method move takes nothing returns nothing
            call .onLoop()
            if .isPaused then
                return
            endif
            if not .hasStarted then
                set .hasStarted = true
                call .onStart()
            endif
            
            call GroupAddGroup(.affect, .last)
            call GroupClear(.affect)
            call GroupEnumUnitsInRange(.affect, GetUnitX(.theUnit), GetUnitY(.theUnit), .getRadius(), Condition(function thistype.tryRegister))
            call ForGroup(.last, function thistype.tryUnregister)
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.t = CreateTimer()
        endmethod
        
        public static method run takes nothing returns nothing
            local integer i = 0
            
            loop
                exitwhen i >= thistype.a
                
                if thistype.i[i].isAlive and thistype.i[i] != 0 then
                    set thistype.curInstance = thistype.i[i]
                    call thistype.i[i].move()
                else
                    if thistype.i[i] != 0 then
                        call thistype.i[i].destroy()
                    endif
                    set thistype.a = thistype.a -1
                    set thistype.i[i] = thistype.i[thistype.a]
                    set thistype.i[i].index = i
                    set i = i -1
                endif
                
                set i = i +1
            endloop
            
            if thistype.a == 0 then
                call PauseTimer(thistype.t)
            endif
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call GroupClear(.affect)
            call ForGroup(.last, function thistype.tryUnregister)
            call ReleaseGroup(.affect)
            call ReleaseGroup(.last)
            call .onEnd()
        endmethod
    endstruct
endlibrary

Addons
JASS:
library CABuff initializer init requires CustomDummy

    globals
        private unit CASTER = null
    endglobals
    
    private function init takes nothing returns nothing
        set CASTER = CreateDummy(Player(PLAYER_NEUTRAL_PASSIVE), 0., 0.)
        call UnitAddAbility(CASTER, 'Aloc')
    endfunction
    
    module CABuff
        private integer theSpell = 0
        private integer theLevel = 0
        private integer theBuff = 0
        
        public method setBuff takes integer theSpell, integer theLevel, integer theBuff returns nothing
            set .theSpell = theSpell
            set .theLevel = theLevel
            set .theBuff = theBuff
        endmethod
        
        public method addBuff takes unit theUnit returns nothing
            call SetUnitX(CASTER, GetUnitX(theUnit))
            call SetUnitY(CASTER, GetUnitY(theUnit))
            call SetUnitOwner(CASTER, GetOwningPlayer(.theUnit), false)
            call UnitAddAbility(CASTER, .theSpell)
            call SetUnitAbilityLevel(CASTER, .theSpell, .theLevel)
            call IssueTargetOrder(CASTER, "slow", theUnit)
            call UnitRemoveAbility(CASTER, .theSpell)
        endmethod
        
        public method removeBuff takes unit theUnit returns nothing
            call UnitRemoveAbility(theUnit, .theBuff)
        endmethod
    endmodule
    
endlibrary

JASS:
library CABonus

    module CABonus
        public integer hp = 0
        public integer mp = 0
        
        public integer amr = 0
        public integer dmg = 0
        
        public integer as = 0
        
        public integer mr = 0
        public integer lf = 0
        
        public integer str = 0
        public integer agi = 0
        public integer int = 0
        
        public integer sr = 0
        
        public method addBonus takes unit theUnit returns nothing
            if .hp != 0 then
                call AddUnitBonus(theUnit, BONUS_LIFE, .hp)
            endif
            
            if .mp != 0 then
                call AddUnitBonus(theUnit, BONUS_MANA, .mp)
            endif
            
            if .amr != 0 then
                call AddUnitBonus(theUnit, BONUS_ARMOR, .amr)
            endif
            
            if .dmg != 0 then
                call AddUnitBonus(theUnit, BONUS_DAMAGE, .dmg)
            endif
            
            if .as != 0 then
                call AddUnitBonus(theUnit, BONUS_ATTACK_SPEED, .as)
            endif
            
            if .mr != 0 then
                call AddUnitBonus(theUnit, BONUS_MANA_REGEN_PERCENT, .mr)
            endif
            
            if .lf != 0 then
                call AddUnitBonus(theUnit, BONUS_LIFE_REGEN, .lf)
            endif
            
            if .str != 0 then
                call AddUnitBonus(theUnit, BONUS_STRENGTH, .str)
            endif
            
            if .agi != 0 then
                call AddUnitBonus(theUnit, BONUS_AGILITY, .agi)
            endif
            
            if .int != 0 then
                call AddUnitBonus(theUnit, BONUS_INTELLIGENCE, .int)
            endif
            
            if .sr!= 0 then
                call AddUnitBonus(theUnit, BONUS_SIGHT_RANGE, .sr)
            endif
        endmethod
        
        public method removeBonus takes unit theUnit returns nothing
            if .hp != 0 then
                call AddUnitBonus(theUnit, BONUS_LIFE, -.hp)
            endif
            
            if .mp != 0 then
                call AddUnitBonus(theUnit, BONUS_MANA, -.mp)
            endif
            
            if .amr != 0 then
                call AddUnitBonus(theUnit, BONUS_ARMOR, -.amr)
            endif
            
            if .dmg != 0 then
                call AddUnitBonus(theUnit, BONUS_DAMAGE, -.dmg)
            endif
            
            if .as != 0 then
                call AddUnitBonus(theUnit, BONUS_ATTACK_SPEED, -.as)
            endif
            
            if .mr != 0 then
                call AddUnitBonus(theUnit, BONUS_MANA_REGEN_PERCENT, -.mr)
            endif
            
            if .lf != 0 then
                call AddUnitBonus(theUnit, BONUS_LIFE_REGEN, -.lf)
            endif
            
            if .str != 0 then
                call AddUnitBonus(theUnit, BONUS_STRENGTH, -.str)
            endif
            
            if .agi != 0 then
                call AddUnitBonus(theUnit, BONUS_AGILITY, -.agi)
            endif
            
            if .int != 0 then
                call AddUnitBonus(theUnit, BONUS_INTELLIGENCE, -.int)
            endif
            
            if .sr!= 0 then
                call AddUnitBonus(theUnit, BONUS_SIGHT_RANGE, -.sr)
            endif
        endmethod
    endmodule
endlibrary

Example
JASS:
library ExampleAura requires CustomAura

    globals
        private constant integer BUFF_ID = 'buf1'
        private constant integer BUFF_SPELL = 'spl1'
    endglobals
    
    private struct aura extends CustomAura
    
        implement optional CABuff
        implement optional CABonus
        
        private static method new takes nothing returns boolean
            local unit u = GetTriggerUnit()
            local integer i = GetHandleId(u)
            local integer l = GetUnitAbilityLevel(u, GetLearnedSkill())
            local thistype this = thistype.load(i)
            
            if this == 0 then
                set this = thistype.create(u)
                set .ID = i
                call .save()
            else
                call .unaffectAll()
            endif
            
            call .setBuff(BUFF_SPELL, l, BUFF_ID)
            set .dmg = - l * 2
            
            return false
        endmethod
        
        method onRegister takes unit theUnit returns nothing
            call .addBuff(theUnit)
            call .addBonus(theUnit)
        endmethod
        
        method onUnregister takes unit theUnit returns nothing
            call .removeBuff(theUnit)
            call .removeBonus(theUnit)
        endmethod
        
        method getRadius takes nothing returns real
            return 500.
        endmethod
        
        method unitFilter takes unit theUnit returns boolean
            return IsUnitEnemy(theUnit, GetOwningPlayer(.theUnit)) and GetUnitState(theUnit, UNIT_STATE_LIFE) > 0.405
        endmethod
        
        private static method onInit takes nothing returns nothing
            local integer i = 0
            local trigger t = CreateTrigger()
            
            call TriggerAddCondition(t, Condition(function thistype.new))
            loop
                exitwhen i >= bj_MAX_PLAYER_SLOTS
                
                call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_HERO_SKILL, null)
                set i = i +1
            endloop
        endmethod
    endstruct

endlibrary

Please note, this is a beta!
 
Level 9
Joined
Dec 12, 2007
Messages
489
hmmm... i like the way it do and how that it takes advantage from BonusMod...

but few things bother me:
first, you mention that CABuff, CustomDummy, and CABonus is optional, yet your example shows that those are required for the aura to be working...
could you make an example of the aura not using those optional library?
or you could just combine it into one single library?

second,
JASS:
        public method addBuff takes unit theUnit returns nothing
            call SetUnitX(CASTER, GetUnitX(theUnit))
            call SetUnitY(CASTER, GetUnitY(theUnit))
            call SetUnitOwner(CASTER, GetOwningPlayer(.theUnit), false)
            call UnitAddAbility(CASTER, .theSpell)
            call SetUnitAbilityLevel(CASTER, .theSpell, .theLevel)
            call IssueTargetOrder(CASTER, "slow", theUnit)
            call UnitRemoveAbility(CASTER, .theSpell)
        endmethod
this is on your CABuff library, there is a hardcoded value on there that you might want to change that.

overall, I like the way your aura works, good job.
 
but few things bother me:
first, you mention that CABuff, CustomDummy, and CABonus is optional, yet your example shows that those are required for the aura to be working...
could you make an example of the aura not using those optional library?
or you could just combine it into one single library?
You only need to remove the implement CABuff and implement CABonus to remove it (aswell as set .dmg = X and call .setBuff()). I wanted to give an example how to use the addons.

this is on your CABuff library, there is a hardcoded value on there that you might want to change that.
You mean slow? Well I could change it, I don't know whether I should. Please also check my signature for the download link so we could maybe move the discussion to there.
 
Might want to rearrange your methods a bit, like so:
JASS:
struct CustomAura extends eventHandler
        public              unit            theUnit         = null
        private             group           affect          = null
        private             group           last            = null
        public              boolean         isAlive         = true
        public              boolean         isPaused        = false
        private             boolean         hasStarted      = false
        
        //: == ---------------------------- ---------------------------- 
        //: #  Indexing & Structstuff
        //: == ---------------------------- ---------------------------- 
        private             integer         index           = 0
        private static      thistype        curInstance     = 0
        private static      timer           t               = null
        private static      integer         a               = 0
        private static      thistype        array           i
        
        implement TableMacros
        
        public method isUnitAffected takes unit theUnit returns boolean
            return IsUnitInGroup(theUnit, .affect)
        endmethod
        
        public method affectUnit takes unit theUnit returns nothing
            call GroupAddUnit(.affect, theUnit)
            if not IsUnitInGroup(theUnit, .last) then
                call .onRegister(theUnit)
            endif
        endmethod
        
        public method unaffectUnit takes unit theUnit returns nothing
            if not IsUnitInGroup(theUnit, .affect) then
                call GroupRemoveUnit(.last, theUnit)
                call .onUnregister(theUnit)
            endif
        endmethod
        
        private static method unaffectAllEnum takes nothing returns nothing
            local thistype this = thistype.curInstance
            call .unaffectUnit(GetEnumUnit())
        endmethod
        
        public method unaffectAll takes nothing returns nothing
            set thistype.curInstance = this
            call GroupClear(.affect)
            call ForGroup(.last, function thistype.unaffectAllEnum)
        endmethod
        
        private static method tryRegister takes nothing returns boolean
            local thistype this = thistype.curInstance
            local unit u = GetFilterUnit()
            
            if .unitFilter(u) then
                call .affectUnit(u)
            endif
            
            set u = null
            return false
        endmethod
        
        private static method tryUnregister takes nothing returns nothing
            local thistype this = thistype.curInstance
            local unit u = GetEnumUnit()
            
            call .unaffectUnit(u)
            
            set u = null
        endmethod
        
        private method move takes nothing returns nothing
            call .onLoop()
            if .isPaused then
                return
            endif
            if not .hasStarted then
                set .hasStarted = true
                call .onStart()
            endif
            
            call GroupAddGroup(.affect, .last)
            call GroupClear(.affect)
            call GroupEnumUnitsInRange(.affect, GetUnitX(.theUnit), GetUnitY(.theUnit), .getRadius(), Condition(function thistype.tryRegister))
            call ForGroup(.last, function thistype.tryUnregister)
        endmethod
        
        public static method run takes nothing returns nothing
            local integer i = 0
            
            loop
                exitwhen i >= thistype.a
                
                if thistype.i[i].isAlive and thistype.i[i] != 0 then
                    set thistype.curInstance = thistype.i[i]
                    call thistype.i[i].move()
                else
                    if thistype.i[i] != 0 then
                        call thistype.i[i].destroy()
                    endif
                    set thistype.a = thistype.a -1
                    set thistype.i[i] = thistype.i[thistype.a]
                    set thistype.i[i].index = i
                    set i = i -1
                endif
                
                set i = i +1
            endloop
            
            if thistype.a == 0 then
                call PauseTimer(thistype.t)
            endif
        endmethod
        
        public static method create takes unit theUnit returns thistype
            local thistype this = thistype.allocate()
            
            set .affect = NewGroup()
            set .last = NewGroup()
            set .theUnit = theUnit
            
            set .index              = thistype.a
            set thistype.i[.index]  = this
            set thistype.a          = thistype.a +1
            if thistype.a == 1 then
                call TimerStart(thistype.t, PERIOD, true, function thistype.run)
            endif
            
            return this
        endmethod
        
        private static method onInit takes nothing returns nothing
            set thistype.t = CreateTimer()
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call GroupClear(.affect)
            call ForGroup(.last, function thistype.tryUnregister)
            call ReleaseGroup(.affect)
            call ReleaseGroup(.last)
            call .onEnd()
        endmethod
    endstruct

Save a trigger, save a life. Only YOU can prevent forest fires.

Otherwise, nice job.
 
Status
Not open for further replies.
Top