1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. We have recently started the 16th edition of the Mini Mapping Contest. The theme is mini RPG. Do check it out and have fun.
    Dismiss Notice
  5. Dismiss Notice
  6. The Highway to Hell has been laid open. Come along and participate in the 5th Special Effect Contest.
    Dismiss Notice
  7. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Drain System 1.02

Submitted by Adiktuz
This bundle is marked as approved. It works and satisfies the submission rules.
It's a system that handles life/mana drain for you... It also has support for setting four different event responses to aid you in making a not-just-another-drain spell...

Note: these drains are basically, non-channeled... but you can still create channeled drains by either utilizing the event responses or linking the Drain instance (which is returned by the creation methods) to the unit and calling the remove method if the unit
is ordered anything... you could also try the IsChanneling snippet on the JASS sections...

System:
Code (vJASS):

/*
    Drain System v1.02
    by Adiktuz
   
    A system that handles draining abilities
   
    Features:
        ->Can have a simultaneous life and mana drain
        ->Can have different values for the drain and the damage dealt to the drained unit
        ->Can set the attacktype and damagetype of the drain
       
    How to use:
       
        ->Drain.methodName(parameters)
       
    Methods that can be used for drains
   
    life(unit u1, unit u2, real lifedrain, real duration, real breakpoint, string lfx, string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey)
    mana(unit u1, unit u2, real manadrain, real duration,real breakpoint,string lfx,  string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey)
    lifeMana(unit u1, unit u2, real lifedrain, real manadrain, real duration,real breakpoint,string lfx,  string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey)
    lifeEx(unit u1, unit u2, real lifedrain, real lifedamage, real duration, real breakpoint, string lfx, string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey)
    manaEx(unit u1, unit u2, real manadrain, real manadamage, real duration,real breakpoint,string lfx,  string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey)
    lifeManaEx(unit u1, unit u2, real lifedrain, real lifedamage, real manadrain, real manadamage, real duration,real breakpoint,string lfx,  string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey)
   
    Parameters:
    unit u1 -> the caster
    unit u2 -> the target
    real lifedrain -> the amount of life added to u1 per second
    real lifedamage -> the amount of life damage to u2 per second
    real manadrain -> the amount of mana added to u1 per second
    real manadamage -> the amount of mana damage to u2 per second
    real duration -> the maximum duration of the drain
    real breakpoint -> the maximum range of the drain
    string lfx -> the string path of the lightning effect
    string e1 -> the special effect to be attached to u1 for the duration of the drain
    string e2 -> the special effect to be attached to u2 for the duration of the drain
    string apoint1 -> the attachment point of e1
    string apoint2 -> the attachment point of e2
    attacktype at -> the attack type of the life damage
    damagetype dt -> the damage type of the life damage
   
    Note: all of these methods return the instance of the drain so you can save it in a variable
   
    To forcibly stop a drain:
   
    remove(integer eventtype)
   
    integer eventtype -> determines if the drain is broken,ended or target died
                      -> if 1, it is broken
                      -> if 2, it ended
                      -> if 3, target died
                      -> use any other number if no event response should be run
   
    Extra/Interface/Events:
       
        registerUpdateEvent(integer eventkey, code ToDo) returns nothing
        -> allows you to register an action that will be run whenever a drain with the
           same eventkey as the one registered is updated (every T32_PERIOD)
       
        registerEndEvent(integer eventkey, code ToDo) returns nothing
        -> allows you to register an action that will be run whenever a drain with the
           same eventkey as the one registered ends (duration ends)
       
        registerBreakEvent(integer eventkey, code ToDo) returns nothing
        -> allows you to register an action that will be run whenever a drain with the
           same eventkey as the one registered is broken (the breakpoint is reached)
           
        registerDeathEvent(integer eventkey, code ToDo) returns nothing
        -> allows you to register an action that will be run whenever target unit dies
       
        registerSelfDeathEvent(integer eventkey, code ToDo) returns nothing
        -> allows you to register an action that will be run whenever the casting unit dies
           
        NOTE: If you're going to use the next five functions/methods, make sure you set the
              corresponding boolean at the globals block to true
       
        registerGlobalUpdateEvent(code ToDo) returns nothing
        -> allows you to register an action that will be run whenever a drain
           is updated (every T32_PERIOD)
       
        registerGlobalEndEvent(code ToDo) returns nothing
        -> allows you to register an action that will be run whenever a drain ends
       
        registerGlobalBreakEvent(code ToDo) returns nothing
        -> allows you to register an action that will be run whenever a drain breaks
       
        registerGlobalDeathEvent(code ToDo) returns nothing
        -> allows you to register an action that will be run whenever a drain target dies
       
        registerGlobalSelfDeathEvent(code ToDo) returns nothing
        -> allows you to register an action that will be run whenever a drain user dies
       
    To obtain the instance that run the events:
   
    getTriggeringDrain()
   
    See the example triggers for a better idea on how to use it
*/


library DrainSystem requires LightningSystem
   
    globals
        //Set to true if you're gonna use the global update event handler
        private constant boolean USE_GLOBAL_UPDATE = false
        //Set to true if you're gonna use the global end event handler
        private constant boolean USE_GLOBAL_END = false
        //Set to true if you're gonna use the global break event handler
        private constant boolean USE_GLOBAL_BREAK = false
        //Set to true if you're gonna use the global death event handler
        private constant boolean USE_GLOBAL_DEATH = false
        //Set to true if you're gonna use the global selfdeath event handler
        private constant boolean USE_GLOBAL_SELFDEATH = false
        //hbase eight of lightning for normal units
        private constant real zbuffer = 50.0
        //base height of lightning for flying units
        //negative because flying units seem to have a default positive buffer for the lightning z
        private constant real flyzbuffer = -100.0
        private Table UpdateTable
        private Table EndTable
        private Table BreakTable
        private Table DeathTable
        private Table SelfDeathTable
        private trigger globalUpdate
        private trigger globalEnd
        private trigger globalBreak
        private trigger globalDeath
        private trigger globalSelfDeath
    endglobals
   
    private module init
        static method onInit takes nothing returns nothing
            set UpdateTable = Table.create()
            set EndTable = Table.create()
            set BreakTable = Table.create()
            set DeathTable = Table.create()
            set SelfDeathTable = Table.create()
            static if USE_GLOBAL_UPDATE then
                set globalUpdate = CreateTrigger()
            endif
            static if USE_GLOBAL_END then
                set globalEnd = CreateTrigger()
            endif
            static if USE_GLOBAL_BREAK then
                set globalBreak = CreateTrigger()
            endif
            static if USE_GLOBAL_DEATH then
                set globalDeath = CreateTrigger()
            endif
            static if USE_GLOBAL_SELFDEATH then
                set globalSelfDeath = CreateTrigger()
            endif
        endmethod
    endmodule
   
    struct Drain extends array
        Lightning light
        unit u1
        unit u2
        real duration
        real lifedrain
        real manadrain
        real lifedamage
        real manadamage
        real breakpoint
        effect e1
        effect e2
        integer eventkey
        string apoint1
        string apoint2
        attacktype at
        damagetype dt
        boolean isLife
        boolean isMana
        static thistype instance
        private static integer instanceCount = 0
        private static thistype recycle = 0
        private thistype recycleNext
       
        static method registerSelfDeathEvent takes integer eventkey, code toDo returns nothing
            if not SelfDeathTable.handle.has(eventkey) then
                set SelfDeathTable.trigger[eventkey] = CreateTrigger()
            endif
            call TriggerAddCondition(SelfDeathTable.trigger[eventkey],Filter(toDo))
        endmethod
       
        static method registerDeathEvent takes integer eventkey, code toDo returns nothing
            if not DeathTable.handle.has(eventkey) then
                set DeathTable.trigger[eventkey] = CreateTrigger()
            endif
            call TriggerAddCondition(DeathTable.trigger[eventkey],Filter(toDo))
        endmethod
       
        static method registerEndEvent takes integer eventkey, code toDo returns nothing
            if not EndTable.handle.has(eventkey) then
                set EndTable.trigger[eventkey] = CreateTrigger()
            endif
            call TriggerAddCondition(EndTable.trigger[eventkey],Filter(toDo))
        endmethod
       
        static method registerBreakEvent takes integer eventkey, code toDo returns nothing
            if not BreakTable.handle.has(eventkey) then
                set BreakTable.trigger[eventkey] = CreateTrigger()
            endif
            call TriggerAddCondition(BreakTable.trigger[eventkey],Filter(toDo))
        endmethod
       
        static method registerUpdateEvent takes integer eventkey, code toDo returns nothing
            if not UpdateTable.handle.has(eventkey) then
                set UpdateTable.trigger[eventkey] = CreateTrigger()
            endif
            call TriggerAddCondition(UpdateTable.trigger[eventkey],Filter(toDo))
        endmethod
       
        static method registerGlobalEndEvent takes code toDo returns nothing
            call TriggerAddCondition(globalEnd,Filter(toDo))
        endmethod
       
        static method registerGlobalUpdateEvent takes code toDo returns nothing
            call TriggerAddCondition(globalUpdate,Filter(toDo))
        endmethod
       
        static method registerGlobalBreakEvent takes code toDo returns nothing
            call TriggerAddCondition(globalBreak,Filter(toDo))
        endmethod
       
        static method registerGlobalDeathEvent takes code toDo returns nothing
            call TriggerAddCondition(globalDeath,Filter(toDo))
        endmethod
       
        static method registerGlobalSelfDeathEvent takes code toDo returns nothing
            call TriggerAddCondition(globalSelfDeath,Filter(toDo))
        endmethod
       
        static method getZ takes unit u returns real
            if IsUnitType(u,UNIT_TYPE_FLYING) then
                return flyzbuffer
            endif
            return zbuffer
        endmethod
       
        static method getTriggeringDrain takes nothing returns thistype
            return instance
        endmethod
       
        method remove takes integer eventtype returns nothing
            call this.light.remove()
            call DestroyEffect(this.e1)
            call DestroyEffect(this.e2)
            set instance = this
            if eventtype == 1 then
                if BreakTable.handle.has(this.eventkey) then
                    call TriggerEvaluate(BreakTable.trigger[this.eventkey])
                endif
                static if USE_GLOBAL_BREAK then
                    call TriggerEvaluate(globalBreak)
                endif
            elseif eventtype == 2 then
                if EndTable.handle.has(this.eventkey) then
                    call TriggerEvaluate(EndTable.trigger[this.eventkey])
                endif
                static if USE_GLOBAL_END then
                    call TriggerEvaluate(globalEnd)
                endif
            elseif eventtype == 3 then
                if DeathTable.handle.has(this.eventkey) then
                    call TriggerEvaluate(DeathTable.trigger[this.eventkey])
                endif
                static if USE_GLOBAL_DEATH then
                    call TriggerEvaluate(globalDeath)
                endif
            elseif eventtype == 4 then
                if SelfDeathTable.handle.has(this.eventkey) then
                    call TriggerEvaluate(SelfDeathTable.trigger[this.eventkey])
                endif
                static if USE_GLOBAL_SELFDEATH then
                    call TriggerEvaluate(globalSelfDeath)
                endif
            endif
            call this.stopPeriodic()
            set .recycleNext=recycle
            set recycle=this
        endmethod
       
        static method new takes nothing returns thistype
            local thistype this = recycle
            if (this == 0) then
                set instanceCount = instanceCount + 1
                return instanceCount
            endif
                set recycle = recycle.recycleNext
            return this
        endmethod
       
        method periodic takes nothing returns nothing
            set this.duration = this.duration - T32_PERIOD
            set instance = this
            if UpdateTable.handle.has(this.eventkey) then
                call TriggerEvaluate(UpdateTable.trigger[this.eventkey])
            endif
            static if USE_GLOBAL_UPDATE then
                call TriggerEvaluate(globalUpdate)
            endif
            if this.isLife then
                call SetWidgetLife(this.u1,GetWidgetLife(this.u1) + this.lifedrain)
                call UnitDamageTarget(this.u1,this.u2,this.lifedamage,false,false,this.at,this.dt,null)
            endif
            if this.isMana then
                call SetUnitState(this.u1, UNIT_STATE_MANA, GetUnitState(this.u1,UNIT_STATE_MANA) + this.manadrain)
                call SetUnitState(this.u2, UNIT_STATE_MANA, GetUnitState(this.u2,UNIT_STATE_MANA) - this.manadamage)
            endif
            if this.duration <= 0.0 then
                call this.remove(2)
            elseif ((GetUnitX(this.u1) - GetUnitX(this.u2))*(GetUnitX(this.u1) - GetUnitX(this.u2)) + (GetUnitY(this.u1) - GetUnitY(this.u2))*(GetUnitY(this.u1) - GetUnitY(this.u2))) > this.breakpoint  then
                call this.remove(1)
            elseif GetWidgetLife(this.u2) < .405 or IsUnitType(this.u2,UNIT_TYPE_DEAD) then
                call this.remove(3)
            elseif GetWidgetLife(this.u1) < .405 or IsUnitType(this.u1,UNIT_TYPE_DEAD) then
                call this.remove(4)
            endif
        endmethod
       
        implement T32x
       
        static method life takes unit u1, unit u2, real lifedrain, real duration, real breakpoint, string lfx, string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey returns thistype
            local thistype this = thistype.new()
            set this.u1 = u1
            set this.u2 = u2
            set this.lifedrain = lifedrain*T32_PERIOD
            set this.manadrain = 0.0
            set this.duration = duration
            set this.breakpoint = breakpoint*breakpoint
            set this.eventkey = eventkey
            set this.e1 = AddSpecialEffectTarget(e1,u1,apoint1)
            set this.e2 = AddSpecialEffectTarget(e2,u2,apoint2)
            set this.at = at
            set this.dt = dt
            set this.lifedamage = this.lifedrain
            set this.manadamage = this.manadrain
            set this.isLife = true
            set this.isMana = false
            set this.light = Lightning.unitToUnit(u1,u2,thistype.getZ(u1),thistype.getZ(u2),false,0.0,lfx,this.eventkey)
            call this.startPeriodic()
            return this
        endmethod
       
        static method mana takes unit u1, unit u2, real manadrain, real duration,real breakpoint,string lfx,  string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey  returns thistype
            local thistype this = thistype.new()
            set this.u1 = u1
            set this.u2 = u2
            set this.lifedrain = 0.0
            set this.manadrain = manadrain*T32_PERIOD
            set this.duration = duration
            set this.breakpoint = breakpoint*breakpoint
            set this.eventkey = eventkey
            set this.e1 = AddSpecialEffectTarget(e1,u1,apoint1)
            set this.e2 = AddSpecialEffectTarget(e2,u2,apoint2)
            set this.at = at
            set this.dt = dt
            set this.lifedamage = this.lifedrain
            set this.manadamage = this.manadrain
            set this.isLife = false
            set this.isMana = true
            set this.light = Lightning.unitToUnit(u1,u2,thistype.getZ(u1),thistype.getZ(u2),false,0.0,lfx,this.eventkey)
            call this.startPeriodic()
            return this
        endmethod
       
        static method lifeMana takes unit u1, unit u2, real lifedrain, real manadrain, real duration,real breakpoint,string lfx,  string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey  returns thistype
            local thistype this = thistype.new()
            set this.u1 = u1
            set this.u2 = u2
            set this.lifedrain = lifedrain*T32_PERIOD
            set this.manadrain = manadrain*T32_PERIOD
            set this.duration = duration
            set this.breakpoint = breakpoint*breakpoint
            set this.eventkey = eventkey
            set this.e1 = AddSpecialEffectTarget(e1,u1,apoint1)
            set this.e2 = AddSpecialEffectTarget(e2,u2,apoint2)
            set this.lifedamage = this.lifedrain
            set this.manadamage = this.manadrain
            set this.isLife = true
            set this.isMana = true
            set this.light = Lightning.unitToUnit(u1,u2,thistype.getZ(u1),thistype.getZ(u2),false,0.0,lfx,this.eventkey)
            call this.startPeriodic()
            return this
        endmethod
       
        static method lifeEx takes unit u1, unit u2, real lifedrain, real lifedamage, real duration,real breakpoint,string lfx,  string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey returns thistype
            local thistype this = thistype.new()
            set this.u1 = u1
            set this.u2 = u2
            set this.lifedrain = lifedrain*T32_PERIOD
            set this.manadrain = 0.0
            set this.duration = duration
            set this.breakpoint = breakpoint*breakpoint
            set this.eventkey = eventkey
            set this.e1 = AddSpecialEffectTarget(e1,u1,apoint1)
            set this.e2 = AddSpecialEffectTarget(e2,u2,apoint2)
            set this.at = at
            set this.dt = dt
            set this.lifedamage = lifedamage*T32_PERIOD
            set this.manadamage = this.manadrain
            set this.isLife = true
            set this.isMana = false
            set this.light = Lightning.unitToUnit(u1,u2,thistype.getZ(u1),thistype.getZ(u2),false,0.0,lfx,this.eventkey)
            call this.startPeriodic()
            return this
        endmethod
       
        static method manaEx takes unit u1, unit u2, real manadrain, real manadamage, real duration,real breakpoint,string lfx,  string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey  returns thistype
            local thistype this = thistype.new()
            set this.u1 = u1
            set this.u2 = u2
            set this.lifedrain = 0.0
            set this.manadrain = manadrain*T32_PERIOD
            set this.duration = duration
            set this.breakpoint = breakpoint*breakpoint
            set this.eventkey = eventkey
            set this.e1 = AddSpecialEffectTarget(e1,u1,apoint1)
            set this.e2 = AddSpecialEffectTarget(e2,u2,apoint2)
            set this.at = at
            set this.dt = dt
            set this.lifedamage = this.lifedrain
            set this.manadamage = manadamage*T32_PERIOD
            set this.isLife = false
            set this.isMana = true
            set this.light = Lightning.unitToUnit(u1,u2,thistype.getZ(u1),thistype.getZ(u2),false,0.0,lfx,this.eventkey)
            call this.startPeriodic()
            return this
        endmethod
       
        static method lifeManaEx takes unit u1, unit u2, real lifedrain, real lifedamage, real manadrain, real manadamage,real breakpoint,string lfx,  real duration, string e1, string e2, string apoint1, string apoint2, attacktype at, damagetype dt,integer eventkey  returns thistype
            local thistype this = thistype.new()
            set this.u1 = u1
            set this.u2 = u2
            set this.lifedrain = lifedrain*T32_PERIOD
            set this.manadrain = manadrain*T32_PERIOD
            set this.duration = duration
            set this.breakpoint = breakpoint*breakpoint
            set this.eventkey = eventkey
            set this.e1 = AddSpecialEffectTarget(e1,u1,apoint1)
            set this.e2 = AddSpecialEffectTarget(e2,u2,apoint2)
            set this.lifedamage = lifedamage*T32_PERIOD
            set this.manadamage = manadamage*T32_PERIOD
            set this.isLife = true
            set this.isMana = true
            set this.light = Lightning.unitToUnit(u1,u2,thistype.getZ(u1),thistype.getZ(u2),false,0.0,lfx,this.eventkey)
            call this.startPeriodic()
            return this
        endmethod
       
        implement init
    endstruct
   
endlibrary


 


Samples

FoD

Code (vJASS):

library FoD initializer init requires DrainSystem

    globals
        private constant integer abil = 'A000'
        private constant string fx = "Abilities\\Spells\\Other\\SoulBurn\\SoulBurnbuff.mdl"
        private constant string fx2 = "Abilities\\Spells\\Human\\InnerFire\\InnerFireTarget.mdl"
        private constant string drainfx = "AFOD"
        private constant string point = "overhead"
        private constant string point2 = "overhead"
        private unit u = null
    endglobals
   
    private function drain takes nothing returns nothing
        set u = GetTriggerUnit()
        call Drain.lifeEx(u,GetSpellTargetUnit(),GetUnitAbilityLevel(u,abil)*GetHeroStr(u,true),GetUnitAbilityLevel(u,abil)*GetHeroInt(u,true), 5.0,800.0,drainfx,fx2,fx,point2,point,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_DIVINE,abil)
    endfunction
   
    private function break takes nothing returns nothing
        call BJDebugMsg("Finger of death was broken.")
    endfunction
   
    private function end takes nothing returns nothing
        call SetUnitState(Drain.getTriggeringDrain().u2,UNIT_STATE_MANA,0.0)
    endfunction
   
    private function init takes nothing returns nothing
        call RegisterSpellEffectEvent(abil,function drain)
        call Drain.registerBreakEvent(abil,function break)
        call Drain.registerEndEvent(abil,function end)
    endfunction
   
endlibrary



 



ForkedDrain
Code (vJASS):

library ForkedDrain initializer init requires DrainSystem

    globals
        private constant integer abil = 'A001'
        private constant string fx = "Abilities\\Spells\\Other\\Drain\\DrainTarget.mdl"
        private constant string fx2 = "Abilities\\Spells\\Other\\Drain\\DrainTarget.mdl"
        private constant string drainfx = "DRAB"
        private constant string point = "overhead"
        private constant string point2 = "overhead"
        private constant real radius = 150.0
        private constant integer TARGETS = 2
        private integer maxtargs
        private integer curtargs = 1
        private unit u = null
        private unit tmpU = null
        private unit tmpUo = null
        private group tmpGroup = CreateGroup()
        private integer level
    endglobals
   
    private function filter takes nothing returns boolean
        set tmpU = GetFilterUnit()
        if IsUnitEnemy(tmpU,GetOwningPlayer(u)) and GetWidgetLife(tmpU) > .405 and (not IsUnitType(tmpU,UNIT_TYPE_STRUCTURE)) and curtargs < maxtargs and tmpU != tmpUo then
            call Drain.life(u,tmpU,level*20,5.0,800.0,drainfx,fx2,fx,point2,point,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_DIVINE,abil)
            set curtargs = curtargs + 1
        endif
        return false
    endfunction
   
    private function drain takes nothing returns nothing
        set u = GetTriggerUnit()
        set level = GetUnitAbilityLevel(u,abil)
        set tmpUo = GetSpellTargetUnit()
        call Drain.life(u,tmpUo,level*20,5.0,800.0,drainfx,fx2,fx,point2,point,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_DIVINE,abil)
        set maxtargs = TARGETS*level
        call GroupEnumUnitsInRange(tmpGroup, GetUnitX(tmpUo), GetUnitY(tmpUo), radius*level, Filter(function filter))
        set curtargs = 1
    endfunction
   
    private function dead takes nothing returns nothing
        call BJDebugMsg(GetUnitName(Drain.getTriggeringDrain().u2) + " has died from Forked Drain.")
    endfunction
   
    private function init takes nothing returns nothing
        call RegisterSpellEffectEvent(abil,function drain)
        call Drain.registerDeathEvent(abil,function dead)
    endfunction
   
endlibrary




 


Credits

Required Libraries by the system:




ChangeLog

v1.01 - fixed things
v1.02 - added a new event handler for when the caster dies
- made the drain end when the caster dies (I wonder why I didn't from the start)
- added global event handlers for all the five event handlers


Keywords:
adiktuz,scrolls,lanthanum,system,spell,drain,life,mana,damage,siphon
Contents

Drain System 1.02 (Map)

Reviews
Moderator
04:29, 20th Oct 2012 Magtheridon96: Approved.
  1. 04:29, 20th Oct 2012
    Magtheridon96: Approved.
     
  2. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    enjoy... :)
     
  3. FRENGERS

    FRENGERS

    Joined:
    Aug 4, 2012
    Messages:
    971
    Resources:
    4
    Icons:
    3
    Maps:
    1
    Resources:
    4
    Humm.... Just life and mana??
    It should can drain armor or damage or everything ;) ;)
     
  4. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    no I won't add it... that would require an immense amount of abilities in the OE because you cannot directly modify those thru triggers...

    that should be another resource, but it's definitely not something that I will do...
     
  5. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    I think Nest's Event library should be in use here instead of handling all triggers on your own + TriggerEvaluate. For the events that is of course.

    IS it just me or is the screenshot really fucked up? The lightnings are a mess! :)
     
  6. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    One thing I forgot to mention in the review:

    Code (vJASS):
    if IsUnitType(u,UNIT_TYPE_FLYING) then
        return flyzbuffer
    else
        return zbuffer
    endif

    ->
    Code (vJASS):
    if IsUnitType(u,UNIT_TYPE_FLYING) then
        return flyzbuffer
    endif
    return zbuffer
     


    and

    Code (vJASS):
    local thistype this
    if (recycle == 0) then
        set instanceCount = instanceCount + 1
        return instanceCount
    else
        set this = recycle
        set recycle = recycle.recycleNext
    endif
    return this

    ->
    Code (vJASS):
    local thistype this = recycle
    if (this == 0) then
        set instanceCount = instanceCount + 1
        return instanceCount
    endif
    set recycle = recycle.recycleNext
    return this


    :p

    Also, you can add booleans to the struct to determine whether the ability only does life drain/mana drain.
    This way, your periodic static method would have less of an effect on the game because it would only be making function calls if needed :D

    One other very tiny improvement would be to cache unit coordinates in the periodic function since there are many calls in there o_O

    Code (vJASS):
    local real x = GetUnitX(this.u1) - GetUnitX(this.u2)
    local real y = GetUnitY(this.u1) - GetUnitY(this.u2)

    // distance would then be x*x + y*y


    :D
     
  7. FRENGERS

    FRENGERS

    Joined:
    Aug 4, 2012
    Messages:
    971
    Resources:
    4
    Icons:
    3
    Maps:
    1
    Resources:
    4
    No, Why DotA can make that Static Link ( Razor )
    It's Draining Damage -..-
     
  8. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    @Maggy - okay, I'll update it maybe tonight after I get back home... I'll study the Event library first... :)

    @FRENGERS - I never said it was impossible, I said it was a pain to do... and you need some other system if you want the bonus damage to stay after the drain... and that is totally out of my plans for now... and it's not that useful, at least not on most custom maps that uses their own damage system...

    @baassee - I think it's because of the spider's attack animation (if you're talking about the discrepancy in the drain's distance from one of the spideys...
     
  9. FRENGERS

    FRENGERS

    Joined:
    Aug 4, 2012
    Messages:
    971
    Resources:
    4
    Icons:
    3
    Maps:
    1
    Resources:
    4
    Ukay2 maybe you can make it later :/ :/ I realy need it if can -..-
     
  10. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    OLD

    Updated...

    Btw, Lightning was actually created because of this system (the idea of a Drain system crossed my mind before the idea of the Lightning)...

    and, I won't be running events Blizz-like by utilizing Event because that would defeat the purpose of making the event handling simpler for the user...


    Updated!

    Made the drain end when the caster dies when I realized that I haven't had that feature... and of course added an event handler for that... take note that the event handler will run for all the current drains of the caster so for example in Forked Drain, you have 3 targets then you died, it will run three times...

    Also added global event handlers for all the five event handlers... Global meaning event handlers that will fire for all drains... they are toggled via constant booleans and static ifs so that the system won't include them if they're not gonna be used... :)

    EDIT: I will add a global event handler for drain start so that you can fire a general event for all drains that have started...
     
    Last edited: Nov 9, 2012
  11. DiggetyBo

    DiggetyBo

    Joined:
    Apr 19, 2013
    Messages:
    86
    Resources:
    0
    Resources:
    0
    Hey man,

    Awesome system,

    I wanted to use the Forked Drain, but more as a passive. How would I got about changing the event from the ability init as an active, to a percentage chance (maybe 30%) to proc when the hero auto attacks? I still want forked lightning to be associated with an ability, so it shows the ability on the skill console, but as a just passive. and if the hero learns Forked lightning passive, the trigger will be ready to handle the auto attack percentage event from that point on.

    Do you know what I mean?
     
  12. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    Triggering the passive part is not part of the system anymore, you'd need to do it yourself...

    You'd need a damage detection system so that you can detect when a unit deals damage to another unit...
     
  13. DiggetyBo

    DiggetyBo

    Joined:
    Apr 19, 2013
    Messages:
    86
    Resources:
    0
    Resources:
    0
    Ok, I'll give it a whack. Can you tell me which line of code starts the actions? (event, if it's still called that?) I'm assuming it would be something like unit uses ability 'A001' or something. But I couldn't find it for the life of me.

    My goal is pretty simple, I don't think I need a dds. I'll show you what I mean in GUI since its a little easier for me.

    • Events
      • Unit - A unit Is attacked
    • Conditions
      • And - All (Conditions) are true
        • Conditions
          • (Attacking unit) Equal to ForkedDrainCaster
          • (Random integer number between 1 and 10) Greater than 6
    • Actions
      • Custom script: run the forked drain trigger?


    ForkedDrainCaster can be set externally whenever a hero learns forked lightning as a skill, or something to that effect. I'd imagine also under actions we should define forked drain's target variables. How many variables like that would have to be defined in order for the drain system to distinguish the target and such? For the actions we could throw in some custom script to run forked lightning as it's supposed to, without changing the system too much. Would this way work, using this imple gui approach to determine whether or not to trigger forked drain?
     
  14. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    I don't suggest using Is Attacked, because that event is abusable...

    but anyway, you cannot call the Forked drain outside of the library because I set it to private...

    I'm on work right now and as such I can't do much...