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. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  5. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  6. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  7. The results are out! Check them out.
    Dismiss Notice
  8. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  9. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  10. 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.

DamageOverTime(DOT) 1.7

Submitted by Dynasti
This bundle is marked as approved. It works and satisfies the submission rules.
This system allows you to damage a unit over time. You can deal, lets say 200 damage over 0.7 secconds if you want to.

This system is not a "Damage After Time", but a Damage Over Time.

System requires JassNewGenPack

Fixes
  • v1.0 - Release
  • v1.1 - Fixed a minior bug
  • v1.2 - Added the manual
  • v1.3 - Minior Fixing
  • v1.4 - Last fixes thanks to Dr Super Good
  • v1.5 - Added one more comment + Added one more test.
  • v1.6 - Scripted the code all over again, now more effective :D
  • v1.7 - After a long time I'm finaly reuploading this after it got deleted, and I've redone the whole ting. More efficient than ever.


Please, if any bugs or ways of improvement is found. Please post. Thx

Code
Code (vJASS):
// o o o o o o o o o o o o o o o o o o o o o o o
// o Damage Over Time by Dynasti o Version 1.7 o
// o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
// o                                                      How To Implement                                                   o
// o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
// o                                                                                                                         o
// o    1. - Make sure that you opened the system in the newest version of JNGP                                              o
// o    2. - Copy this trigger into you map                                                                                  o
// o                                                                                                                         o
// o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
// o                                                      How to Use                                                         o
// o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
// o                                                                                                                         o
// o    - This system requires you to give 8 variables for it to function perfectly.                                         o
// o        Variables are:                                                                                                   o
// o            1. - A unit that does the damage, lets call it " A "                                                         o
// o            2. - A widget that is given the damage, lets call it " B "                                                   o
// o            3. - A real value that is the damage, lets call it " D "                                                     o
// o            4. - A real value that is the time it takes to do the damage, lets call it " T "                             o
// o            5. - An attacktype that is used to regulate the damage, lets call it " AT "                                  o
// o            6. - A damagetype that is used to regulate the damage, lets call it " DT "                                   o
// o            7. - A string that is the model of the period effect, lets call it " EX "                                    o
// o            8. - A string that is the attachment for the " EX " string, lets call it " ExAttach "                        o
// o                                                                                                                         o
// o        The call:                                                                                                        o
// o            call DamageOverTimeEx( A , B , D , T , AT , DT , EX , ExAttach )                                             o
// o            you have now succesfully called the function and started the damage over time.                               o
// o                                                                                                                         o
// o            if you want something simpler and not have the effect do this:                                               o
// o                call DamageOverTime( A , B , D , T , AT , DT )                                                           o
// o            now you have done the simpler call.                                                                          o
// o                                                                                                                         o
// o        Tips:                                                                                                            o
// o            To not make the target " B " run away or run after you, do this:                                             o
// o                call DamageOverTimeEx( B , B , D , T , AT , DT , EX , ExAttach )                                         o
// o            Or for the simpler call:                                                                                     o
// o                call DamageOverTime( B , B , D , T , AT , DT )                                                           o
// o                                                                                                                         o
// o            What we now have done is set the unit that does the damage to the unit that takes the damage, " B ".         o
// o            This does so that the unit " B " does damage to itself and will not run away or attack any unit.             o
// o                NB: Damaging itself will result to bounty for the own dying unit or, no bounty at all for the killer.    o
// o                                                                                                                         o
// o                                                                                                                         o
// o        If for any reason you want to cancel you need to save the DOT struct as a variable in whatever you're using.     o
// o                                                                                                                         o
// o        First, you need to have the DOT struct variable stored as some integer to cancel a DOT.                          o
// o        Example:                                                                                                         o
// o        [...]                                                                                                            o
// o            set SomeInteger = DamageOverTime(A, B, D, T, AT, DT, EX, ExAttach)                                           o
// o                                                                                                                         o
// o            Since function DamageOverTimeEx or DamageOverTime returns the struct to you, you can store it for later use  o
// o                IMPORTANT!: If you do the stopcall after the DoT has stopped you might screw up things. To do this, you  o
// o                            can use the "check" function to check if the struct value you have stored is running and to  o
// o                            what unit.                                                                                   o
// o                                                                                                                         o
// o        The "Check" function:                                                                                            o
// o            the function "IsDamageRunning takes DOT dat returns unit" will return 'null' as a value if the struct isn't  o
// o            running, and will return a unit handle if the struct is running. But wait, you might be thinking:            o
// o            What if it is another unit than the unit I started it with?! Well do this:                                   o
// o                [...]                                                                                                    o
// o                    if MyUnitVariable == IsDamageRunning(StructVariable) then                                            o
// o                        [your actions here]                                                                              o
// o                        call EndDamageOverTime(StructVariable)                                                           o
// o                    else                                                                                                 o
// o                        set StructVariable = 0                                                                           o
// o                    endif                                                                                                o
// o                                                                                                                         o
// o                By doing this, it will insure you that you won't accedently end another unit's DOT effect                o
// o                                                                                                                         o
// o                                                                                                                         o
// o    - For more info go to: www.HiveWorkshop.com or visit www.Ngo.clan.su , user at both sites are Dynasti                o
// o                                                                                                                         o
// o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
library DOT initializer Init

    globals
        private constant integer FPS = 40 // This is how many times the struct loop will run in a single second. 30-40 is recomended
       
        // DO NOT TUCH! =)
        private constant real Interval = (1.0 / FPS)
    endglobals
   
    private struct DOT
        unit Attacker
        widget Target

        real Damage
        integer EndCount

        attacktype AttackType
        damagetype DamageType
       
        effect Effect
       
        static integer array Index
        static integer Total = 0
       
        static timer Tim = null
       
        static integer Count = -2147483648 // Just a random low number, it is needed
       
        static method Loop takes nothing returns nothing
            local DOT dat
            local integer i = 0

            set DOT.Count = DOT.Count + 1
           
            loop
                exitwhen i >= DOT.Total
                set dat = DOT.Index[i]
               
                if DOT.Count > dat.EndCount or GetWidgetLife(dat.Target) <= .405 then
                    call DestroyEffect(dat.Effect)

                    set dat.Effect     = null
                    set dat.Attacker   = null
                    set dat.Target     = null
                    set dat.AttackType = null
                    set dat.DamageType = null
           
                    call dat.destroy()
                   
                    set DOT.Total = DOT.Total - 1
                    set DOT.Index[i] = DOT.Index[DOT.Total]

                    set i = i - 1
                else
                    call UnitDamageTarget(dat.Attacker, dat.Target, dat.Damage, false, false, dat.AttackType, dat.DamageType, null)
                endif
               
                set i = i + 1
            endloop
           
            if DOT.Total == 0 then
                call PauseTimer(DOT.Tim)
            endif
        endmethod
       
        static method Start takes unit Attacker, widget Target, real Damage, real Time, attacktype AttackType, damagetype DamageType, string Effect, string EffectAttach returns DOT
            local DOT dat = DOT.allocate()
           
            set dat.Attacker   = Attacker
            set dat.Target     = Target
            set dat.AttackType = AttackType
            set dat.DamageType = DamageType
           
            if Effect != "" and Effect != null then
                if EffectAttach != "" and EffectAttach != null then
                    set dat.Effect = AddSpecialEffectTarget(Effect, Target, EffectAttach)
                endif
            endif
           
            set dat.Damage   = Damage * Interval / Time
            set dat.EndCount = DOT.Count + R2I(Time / Interval)
           
            if DOT.Total == 0 then
                call TimerStart(DOT.Tim, Interval, true, function DOT.Loop)
            endif
           
            set DOT.Index[DOT.Total] = dat
            set DOT.Total = DOT.Total + 1
           
            return dat
        endmethod
    endstruct
   
//=========================================================================================
   
    function DamageOverTimeEx takes unit Attacker, widget Target, real Damage, real Time, attacktype AttackType, damagetype DamageType, string Effect, string EffectAttach returns DOT
        return DOT.Start(Attacker, Target, Damage, Time, AttackType, DamageType, Effect, EffectAttach)
    endfunction
   
    function DamageOverTime takes unit Attacker, widget Target, real Damage, real Time, attacktype AttackType, damagetype DamageType returns DOT
        return DOT.Start(Attacker, Target, Damage, Time, AttackType, DamageType, "", "")
    endfunction
   
    function EndDamageOverTime takes DOT dat returns nothing
        set dat.EndCount = DOT.Count + 1
    endfunction
   
    function IsDamageRunning takes DOT dat returns unit
        return dat.Target
    endfunction
   
//=========================================================================================

    private function Init takes nothing returns nothing
        set DOT.Tim = CreateTimer()
    endfunction

endlibrary

Documentation
Code (vJASS):
library DOT initializer Init // Function 'Init' will be run at map start

    globals
        private constant integer FPS = 40 // This is how many times the struct loop will run in a single second. 30-40 is recomended
       
        // DO NOT TUCH! =)
        private constant real Interval = (1.0 / FPS)
    endglobals
   
    private struct DOT
        unit Attacker // The unit that will deal damage to the target
        widget Target // The unit that will be dealt damage to by the Attacker

        real Damage // Used for storing the damage value for each tick
        integer EndCount // Used for knowing when the dot will stop

        attacktype AttackType // Attack Type of the damage
        damagetype DamageType // Damage type of the damage dealt
       
        effect Effect // The effect that will stick to the unit for the duration
       
        static integer array Index // Used for indexing system
        static integer Total = 0 // Used for indexing system
       
        static timer Tim = null // Timer for the loop
       
        static integer Count = -2147483648 // Just a random low number, it is needed. I used for indexing system
       
        static method Loop takes nothing returns nothing // Loop method
            local DOT dat // Localizing the struct
            local integer i = 0 // Integer used for the loop

            set DOT.Count = DOT.Count + 1 // Adding 1 more to the counter. The counter is made that when the count
                                          // that is stored in the struct is larger than the Struct count, the DOT is finished.
           
            loop // Loop
                exitwhen i >= DOT.Total // If there is no structs need to be run, loop will end
                set dat = DOT.Index[i] // Indexing
               
                if DOT.Count > dat.EndCount or GetWidgetLife(dat.Target) <= .405 then // If the DOT's time is over or the target is dead,
                                                                                      //it will end the DOT period
                    call DestroyEffect(dat.Effect)

                    set dat.Effect     = null
                    set dat.Attacker   = null
                    set dat.Target     = null
                    set dat.AttackType = null
                    set dat.DamageType = null
           
                    call dat.destroy()
                   
                    set DOT.Total = DOT.Total - 1
                    set DOT.Index[i] = DOT.Index[DOT.Total]

                    set i = i - 1
                else // Else if the target is alive and DOT's time isn't done, it will deal damage
                    call UnitDamageTarget(dat.Attacker, dat.Target, dat.Damage, false, false, dat.AttackType, dat.DamageType, null)
                endif
               
                set i = i + 1 // Couning the loop
            endloop
           
            if DOT.Total == 0 then // If there is no more structs left, the timer will pause
                call PauseTimer(DOT.Tim)
            endif
        endmethod // End of loop methond
       
        static method Start takes unit Attacker, widget Target, real Damage, real Time, attacktype AttackType, damagetype DamageType, string Effect, string EffectAttach returns DOT // The start method
            local DOT dat = DOT.allocate() // Allocating a new struct value
           
            // Storing the variables
            set dat.Attacker   = Attacker
            set dat.Target     = Target
            set dat.AttackType = AttackType
            set dat.DamageType = DamageType
            //======================
           
            if Effect != "" and Effect != null then // If no effect is asked for, it will not store it
                if EffectAttach != "" and EffectAttach != null then // This is done for efficency tasks, if effect is not asked for, it will not checked if attach is asked for.
                    set dat.Effect = AddSpecialEffectTarget(Effect, Target, EffectAttach)
                endif
            endif
           
            set dat.Damage   = Damage * Interval / Time // Calucating the damage that needs to be done each loop
            set dat.EndCount = DOT.Count + R2I(Time / Interval) // Calculating the DOT's time
           
            if DOT.Total == 0 then // If there is no other structs running the timer is paused, so it needs to be started again
                call TimerStart(DOT.Tim, Interval, true, function DOT.Loop)
            endif
           
            set DOT.Index[DOT.Total] = dat // Indexing
            set DOT.Total = DOT.Total + 1 // Indexing
           
            return dat
        endmethod
    endstruct
   
//=========================================================================================
   
    // The function for DOT with effect
    function DamageOverTimeEx takes unit Attacker, widget Target, real Damage, real Time, attacktype AttackType, damagetype DamageType, string Effect, string EffectAttach returns DOT
        return DOT.Start(Attacker, Target, Damage, Time, AttackType, DamageType, Effect, EffectAttach)
    endfunction
   
    // The easier function for DOT with no effect
    function DamageOverTime takes unit Attacker, widget Target, real Damage, real Time, attacktype AttackType, damagetype DamageType returns DOT
        return DOT.Start(Attacker, Target, Damage, Time, AttackType, DamageType, "", "")
    endfunction
   
    // Function for stopping a DOT
    function EndDamageOverTime takes DOT dat returns nothing
        set dat.EndCount = DOT.Count + 1
    endfunction
   
    // Function for checkign if the struct is running, will return 'null' if not, else it will return a unit handle
    function IsDamageRunning takes DOT dat returns unit
        return dat.Target
    endfunction
   
//=========================================================================================

    private function Init takes nothing returns nothing // Creating the timer
        set DOT.Tim = CreateTimer()
    endfunction

endlibrary


IMPORTANT. MAP ISN'T COMPILED ATM TO THE NEWEST VERSION BECAUSE I'M A FUCKNUT AND HAVE NO CLUE HOW TO FIX MY vJASS EDITOR. HELP IS APPRECIATED.

code still works tho, just not map. Will fix asap
Contents

DOT By Dynasti (Map)

Reviews
Moderator
15:36, 6th Mar 2010 The_Reborn_Devil: It's a pretty neat and useful system. Easy to use and well documented. Status: Approved Rating: Recommended
  1. 15:36, 6th Mar 2010
    The_Reborn_Devil:
    It's a pretty neat and useful system. Easy to use and well documented.


    Status: Approved
    Rating: Recommended
     
  2. 88WaRCraFT3

    88WaRCraFT3

    Joined:
    Jun 9, 2009
    Messages:
    1,139
    Resources:
    1
    Spells:
    1
    Resources:
    1
    spells need to be 1.24 compatible. Unable to open map.
     
  3. Dynasti

    Dynasti

    Joined:
    Oct 18, 2007
    Messages:
    877
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    Wut?! I just edited it into the newest version!!

    Will fix ASAP!
     
  4. The_Witcher

    The_Witcher

    Joined:
    Dec 29, 2008
    Messages:
    229
    Resources:
    13
    Tools:
    1
    Spells:
    12
    Resources:
    13
    Well thats what a good, efficient, etc. system should be like...
    full review will follow...
    BUT one question:
    you did this:
    Code (vJASS):
        private struct DOT
                ...
            static timer Tim = null
                ...
        endstruct
                ...
        private function Init takes nothing returns nothing
            set DOT.Tim = CreateTimer()
        endfunction


    But why?? couldn't it be this too (which is much shorter)??:
    Code (vJASS):
        private struct DOT
                ...
            static timer Tim = CreateTimer()
                ...
        endstruct
                ...
     
  5. Dynasti

    Dynasti

    Joined:
    Oct 18, 2007
    Messages:
    877
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    Well due to the fact that this has been known to cause bugs. Atleast in the older versions of vJass. I'm on the safe side, and it has nothing to do with efficiency. It runs at the beginning of the map ( when it's loading). 1/10000 of a second faster? No one will notice. :)
     
  6. The_Witcher

    The_Witcher

    Joined:
    Dec 29, 2008
    Messages:
    229
    Resources:
    13
    Tools:
    1
    Spells:
    12
    Resources:
    13
    sry i didn't want to offend you ;D

    i just wanted to maybe learn something new, as i did because of your fast answer;D
     
  7. Dynasti

    Dynasti

    Joined:
    Oct 18, 2007
    Messages:
    877
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    ^^ no problem, I'm not offended :)
     
  8. Inferior

    Inferior

    Joined:
    Nov 3, 2008
    Messages:
    110
    Resources:
    3
    Icons:
    1
    Spells:
    2
    Resources:
    3
    NICE TO HAVE YA BACK DYNASTI. Nice system btw as always ^^
     
  9. CHA_Owner

    CHA_Owner

    Joined:
    Feb 11, 2008
    Messages:
    799
    Resources:
    2
    Spells:
    2
    Resources:
    2
    Update test-map please so we can see an example of its use.
     
  10. The_Witcher

    The_Witcher

    Joined:
    Dec 29, 2008
    Messages:
    229
    Resources:
    13
    Tools:
    1
    Spells:
    12
    Resources:
    13
    He's right!! Your map can't be opened in Warcraft (it can in WE)...

    but the code you posted here seems all right...

    please fix that!!
     
  11. Kingz

    Kingz

    Joined:
    Jun 5, 2008
    Messages:
    2,470
    Resources:
    6
    Spells:
    5
    Tutorials:
    1
    Resources:
    6
    It looks really neat now that you reuploaded it.

    Glad to have ya back ;)
     
  12. Dynasti

    Dynasti

    Joined:
    Oct 18, 2007
    Messages:
    877
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    I quote myself in the first post:

     
  13. Thanathos

    Thanathos

    Joined:
    Aug 2, 2008
    Messages:
    202
    Resources:
    5
    Spells:
    5
    Resources:
    5
    Interesting problem you have there. I´ve been doing some debugging with your code and i found something out. When i tested the map without anything changed wc3 directed my to the main menu as the other reported too.
    I figured out that the functions DamageOverTimeEx, DamageOverTime, EndDamageOverTime and IsDamageRunning are somehow causing this malfunction.
    When i removed them and replaced their calls in the demo triggers with the .start method of the struct everything worked fine.

    Im attatching the changed map so others can tell if this generally works or just for me.
    ~TNT​
     

    Attached Files:

  14. Dynasti

    Dynasti

    Joined:
    Oct 18, 2007
    Messages:
    877
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    Thx mate, I'll fix the code ASAP.

    Strange this, was working before, must be something in the latests updates stopping something I'm doing. And the weirdest part is that I'm not even getting any syntax errors :S

    Anyways thx alot man

    +++rep
     
  15. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    oh you're back, remember when you and paladon made this a while ago :D
     
  16. Dynasti

    Dynasti

    Joined:
    Oct 18, 2007
    Messages:
    877
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    Ahem :p

    Well I made my thing, he made his, we clashed it into one map and posted it.
    This was when Paladon was into GUI and stuff.
     
  17. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,426
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    By the way, this crashes on load because of this function:
    Code (vJASS):
        function IsDamageRunning takes DOT dat returns unit
            return dat.Target
        endfunction


    It seems fine at first, but look at this:
    Code (vJASS):
        private struct DOT
            unit Attacker
            widget Target


    Widget. It can't convert the widget to a unit so it crashes. =)

    You can change the
    returns unit
    to
    returns widget
    , or change the parameter to take a unit and change the struct member, or whatever is best. But anyway, that's the cause for your crash.

    Also, you don't need to null struct members, since they are globals (they don't cause reference leaks like locals do). =)

    Nice system otherwise.
     
  18. Dynasti

    Dynasti

    Joined:
    Oct 18, 2007
    Messages:
    877
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    Ty so much for finding that error ^^ +rep


    And I null the globals because they're arrays, and if you've stored lets say 8000 hex codes that's worse than saving none. Imo.
     
  19. gorillabull

    gorillabull

    Joined:
    Jul 17, 2011
    Messages:
    1,367
    Resources:
    2
    Spells:
    2
    Resources:
    2
    god this just deals damage in a loop thats not ideal
     
    Last edited: Jan 31, 2013