• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

GUI Damage over Time [GDoT]

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
This is a GUI version of Damage over Time system.
I don't know if there's already bunch of DoT system, I made this system just to see how good I'm in trigger editor and ofcourse for sharing.


  • GDoT Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set GDoT_DebugMode = False
      • -------- you can change this, just make sure below 0.10 --------
      • Set GDoT_INTERVAL = 0.05

  • GDoT
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • GDoTRegister_Caster Not equal to No unit
              • GDoTRegister_Target Not equal to No unit
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • And - All (Conditions) are true
                • Conditions
                  • GDoT_UseWrapper Equal to True
            • Then - Actions
              • Custom script: call ExecuteFunc("GDoTRegister")
            • Else - Actions
              • Custom script: call ExecuteFunc("GDoTRegisterEx")
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • GDoT_DebugMode Equal to True
            • Then - Actions
              • Game - Display to (All players) the text: GUI DoT: Error! App...
            • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • Custom script: function GDoTOnIterate takes nothing returns nothing
      • Set GDoT_Current = GDoT_MaxIndex
      • -------- --------
      • Custom script: loop
      • Custom script: exitwhen udg_GDoT_Current == 0
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GDoT_Active[GDoT_Current] Equal to True
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • And - All (Conditions) are true
                • Conditions
                  • GDoT_HitAmount[GDoT_Current] Greater than 0
                  • (GDoT_Target[GDoT_Current] is alive) Equal to True
            • Then - Actions
              • -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • GDoT_Freq[GDoT_Current] Greater than or equal to GDoT_DmgFrequency[GDoT_Current]
                • Then - Actions
                  • Unit - Cause GDoT_Caster[GDoT_Current] to damage GDoT_Target[GDoT_Current], dealing GDoT_DpS[GDoT_Current] damage of attack type GDoT_AttackType[GDoT_Current] and damage type GDoT_DamageType[GDoT_Current]
                  • -------- --------
                  • -------- on damage event --------
                  • Set GDoTEvent_Caster = GDoT_Caster[GDoT_Current]
                  • Set GDoTEvent_Target = GDoT_Target[GDoT_Current]
                  • Set GDoTEvent_DpS = GDoT_DpS[GDoT_Current]
                  • Set GDoTEvent_OnDamage = 1.00
                  • Set GDoTEvent_OnDamage = 0.00
                  • -------- --------
                  • Set GDoT_HitAmount[GDoT_Current] = (GDoT_HitAmount[GDoT_Current] - 1)
                  • Set GDoT_Freq[GDoT_Current] = 0.00
                • Else - Actions
                  • Set GDoT_Freq[GDoT_Current] = (GDoT_Freq[GDoT_Current] + GDoT_INTERVAL)
              • -------- --------
            • Else - Actions
              • Set GDoTEvent_Caster = GDoT_Caster[GDoT_Current]
              • Set GDoTEvent_Target = GDoT_Target[GDoT_Current]
              • Set GDoTEvent_DpS = GDoT_DpS[GDoT_Current]
              • Set GDoTEvent_EndDoT = 1.00
              • Set GDoTEvent_EndDoT = 0.00
              • -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • GDoT_Current Equal to GDoT_MaxIndex
                • Then - Actions
                  • Set GDoT_MaxIndex = (GDoT_MaxIndex - 1)
                • Else - Actions
                  • Set GDoT_Recycle[GDoT_Current] = GDoT_Recycle[0]
                  • Set GDoT_Recycle[0] = GDoT_Current
              • -------- --------
              • Special Effect - Destroy GDoT_DmgFx[GDoT_Current]
              • Set GDoT_Caster[GDoT_Current] = No unit
              • Set GDoT_Target[GDoT_Current] = No unit
              • Set GDoT_Freq[GDoT_Current] = 1.00
              • Set GDoT_DmgFrequency[GDoT_Current] = 1.00
              • Set GDoT_HitAmount[GDoT_Current] = 0
              • Set GDoT_DpS[GDoT_Current] = 0.00
              • Set GDoT_AttackType[GDoT_Current] = Spells
              • Set GDoT_DamageType[GDoT_Current] = Normal
              • Set GDoT_Active[GDoT_Current] = False
              • -------- --------
        • Else - Actions
      • Set GDoT_Current = (GDoT_Current - 1)
      • -------- --------
      • Custom script: endloop
      • -------- --------
      • -------- pause/stop the timer when there's nothing on the list --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GDoT_MaxIndex Equal to 0
        • Then - Actions
          • Countdown Timer - Pause GDoT_Iterator
        • Else - Actions
      • -------- --------
      • Custom script: endfunction
      • -------- --------
      • Custom script: function GDoTRegisterEx takes nothing returns nothing
      • -------- increase the instance by 1 or recycle --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GDoT_Recycle[0] Equal to 0
        • Then - Actions
          • Set GDoT_MaxIndex = (GDoT_MaxIndex + 1)
          • Set GDoT_Int = GDoT_MaxIndex
        • Else - Actions
          • Set GDoT_Int = GDoT_Recycle[0]
          • Set GDoT_Recycle[0] = GDoT_Recycle[GDoT_Int]
      • Set GDoT_Active[GDoT_Int] = True
      • -------- --------
      • -------- store everything we need... --------
      • Set GDoT_Caster[GDoT_Int] = GDoTRegister_Caster
      • Set GDoT_Target[GDoT_Int] = GDoTRegister_Target
      • -------- --------
      • Special Effect - Create a special effect attached to the GDoTRegister_FxAttachPoint of GDoTRegister_Target using GDoTRegister_DmgEffect
      • Set GDoT_DmgFx[GDoT_Int] = (Last created special effect)
      • -------- --------
      • Set GDoT_Freq[GDoT_Int] = GDoTRegister_DmgFrequency
      • Set GDoT_DmgFrequency[GDoT_Int] = GDoTRegister_DmgFrequency
      • -------- I use counter insteads duration for accurate damage. --------
      • Set GDoT_HitAmount[GDoT_Int] = (Integer((GDoTRegister_Duration / GDoTRegister_DmgFrequency)))
      • -------- --------
      • Set GDoT_DpS[GDoT_Int] = (GDoTRegister_TotalDamage / (Real(GDoT_HitAmount[GDoT_Int])))
      • Set GDoT_AttackType[GDoT_Int] = GDoTRegister_AttackType
      • Set GDoT_DamageType[GDoT_Int] = GDoTRegister_DamageType
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GDoT_MaxIndex Equal to 1
        • Then - Actions
          • Custom script: call TimerStart(udg_GDoT_Iterator, udg_GDoT_INTERVAL, true, function GDoTOnIterate)
        • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • Custom script: function GDoTRegister takes nothing returns nothing
      • -------- wrapper --------
      • -------- you can config these --------
      • Set GDoTRegister_FxAttachPoint = origin
      • Set GDoTRegister_DmgFrequency = 1.00
      • Set GDoTRegister_AttackType = Spells
      • Set GDoTRegister_DamageType = Normal
      • Set GDoT_UseWrapper = False
      • Custom script: call GDoTRegisterEx()

How to use? Here some Demo
  • Demo Type Wrapper
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Thunder Clap
    • Actions
      • Set dontCopy_Unit[1] = (Triggering unit)
      • Set dontCopy_tempLoc[1] = (Position of dontCopy_Unit[1])
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 512.00 of dontCopy_tempLoc[1] matching ((Matching unit) Not equal to dontCopy_Unit[1])) and do (Actions)
        • Loop - Actions
          • Set GDoTRegister_Caster = dontCopy_Unit[1]
          • Set GDoTRegister_Target = (Picked unit)
          • Set GDoTRegister_DmgEffect = Abilities\Spells\Human\Banish\BanishTarget.mdl
          • Set GDoTRegister_TotalDamage = 500.00
          • Set GDoTRegister_Duration = 2.00
          • Set GDoT_UseWrapper = True
          • Trigger - Run GDoT <gen> (ignoring conditions)

  • Demo Type Advanced
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Thunder Clap
    • Actions
      • Set dontCopy_Unit[1] = (Triggering unit)
      • Set dontCopy_tempLoc[1] = (Position of dontCopy_Unit[1])
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 512.00 of dontCopy_tempLoc[1] matching ((Matching unit) Not equal to dontCopy_Unit[1])) and do (Actions)
        • Loop - Actions
          • Set GDoTRegister_Caster = dontCopy_Unit[1]
          • Set GDoTRegister_Target = (Picked unit)
          • Set GDoTRegister_DmgEffect = Environment\LargeBuildingFire\LargeBuildingFire1.mdl
          • Set GDoTRegister_TotalDamage = 500.00
          • Set GDoTRegister_Duration = 5.00
          • -------- advanced --------
          • Set GDoTRegister_FxAttachPoint = origin
          • Set GDoTRegister_DmgFrequency = 0.25
          • Set GDoTRegister_AttackType = Spells
          • Set GDoTRegister_DamageType = Fire
          • Trigger - Run GDoT <gen> (ignoring conditions)
          • Unit - Add Slow Aura to (Picked unit)
As you can see, there is two demo over there. The first one the way with wrapper and the second is with a little advanced options.
Contents

GUI Damage over Timer [GDoT] (Map)

Level 5
Joined
May 2, 2015
Messages
109
I trying to update this system because I detected a problem with the GUI linked list,
here is the new trigger
  • GDoT
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • GDoTRegister_Caster Not equal to No unit
              • GDoTRegister_Target Not equal to No unit
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • And - All (Conditions) are true
                • Conditions
                  • GDoT_UseWrapper Equal to True
            • Then - Actions
              • Custom script: call ExecuteFunc("GDoTRegister")
            • Else - Actions
              • Custom script: call ExecuteFunc("GDoTRegisterEx")
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • GDoT_DebugMode Equal to True
            • Then - Actions
              • Game - Display to (All players) the text: GUI DoT: Error! App...
            • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • Custom script: function GDoTOnIterate takes nothing returns nothing
      • Set GDoT_Current = GDoT_Next[0]
      • -------- --------
      • Custom script: loop
      • Custom script: exitwhen udg_GDoT_Current == 0
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • GDoT_HitAmount[GDoT_Current] Greater than 0
              • (GDoT_Target[GDoT_Current] is alive) Equal to True
        • Then - Actions
          • -------- --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • GDoT_Freq[GDoT_Current] Greater than or equal to GDoT_DmgFrequency[GDoT_Current]
            • Then - Actions
              • Unit - Cause GDoT_Caster[GDoT_Current] to damage GDoT_Target[GDoT_Current], dealing GDoT_DpS[GDoT_Current] damage of attack type GDoT_AttackType[GDoT_Current] and damage type GDoT_DamageType[GDoT_Current]
              • -------- --------
              • -------- on damage event --------
              • Set GDoTEvent_OnDamage = 1.00
              • Set GDoTEvent_Caster = GDoT_Caster[GDoT_Current]
              • Set GDoTEvent_Target = GDoT_Target[GDoT_Current]
              • Set GDoTEvent_DpS = GDoT_DpS[GDoT_Current]
              • Set GDoTEvent_OnDamage = 0.00
              • -------- --------
              • Set GDoT_HitAmount[GDoT_Current] = (GDoT_HitAmount[GDoT_Current] - 1)
              • Set GDoT_Freq[GDoT_Current] = 0.00
            • Else - Actions
              • Set GDoT_Freq[GDoT_Current] = (GDoT_Freq[GDoT_Current] + GDoT_INTERVAL)
          • -------- --------
        • Else - Actions
          • Set GDoTEvent_EndDoT = 1.00
          • Set GDoTEvent_Caster = GDoT_Caster[GDoT_Current]
          • Set GDoTEvent_Target = GDoT_Target[GDoT_Current]
          • Set GDoTEvent_DpS = GDoT_DpS[GDoT_Current]
          • Set GDoTEvent_EndDoT = 0.00
          • -------- --------
          • Set GDoT_Prev[GDoT_Next[GDoT_Current]] = GDoT_Prev[GDoT_Current]
          • Set GDoT_Next[GDoT_Prev[GDoT_Current]] = GDoT_Next[GDoT_Current]
          • -------- --------
          • Special Effect - Destroy GDoT_DmgFx[GDoT_Current]
          • Set GDoT_Caster[GDoT_Current] = No unit
          • Set GDoT_Target[GDoT_Current] = No unit
          • Set GDoT_Freq[GDoT_Current] = 1.00
          • Set GDoT_DmgFrequency[GDoT_Current] = 1.00
          • Set GDoT_HitAmount[GDoT_Current] = 0
          • Set GDoT_DpS[GDoT_Current] = 0.00
          • Set GDoT_AttackType[GDoT_Current] = Spells
          • Set GDoT_DamageType[GDoT_Current] = Normal
          • -------- --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • GDoT_Current Equal to GDoT_Index
            • Then - Actions
              • Set GDoT_Index = (GDoT_Index - 1)
            • Else - Actions
      • Set GDoT_Current = GDoT_Next[GDoT_Current]
      • -------- --------
      • Custom script: endloop
      • -------- --------
      • -------- pause/stop the timer when there's nothing on the list --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GDoT_Index Equal to 0
        • Then - Actions
          • Countdown Timer - Pause GDoT_Iterator
        • Else - Actions
      • -------- --------
      • Custom script: endfunction
      • -------- --------
      • Custom script: function GDoTRegisterEx takes nothing returns nothing
      • -------- increase the instance by 1 --------
      • Set GDoT_Index = (GDoT_Index + 1)
      • -------- --------
      • -------- store everything we need... --------
      • Set GDoT_Caster[GDoT_Index] = GDoTRegister_Caster
      • Set GDoT_Target[GDoT_Index] = GDoTRegister_Target
      • -------- --------
      • Special Effect - Create a special effect attached to the GDoTRegister_FxAttachPoint of GDoTRegister_Target using GDoTRegister_DmgEffect
      • Set GDoT_DmgFx[GDoT_Index] = (Last created special effect)
      • -------- --------
      • Set GDoT_Freq[GDoT_Index] = GDoTRegister_DmgFrequency
      • Set GDoT_DmgFrequency[GDoT_Index] = GDoTRegister_DmgFrequency
      • -------- I use counter insteads duration for accurate damage. --------
      • Set GDoT_HitAmount[GDoT_Index] = (Integer((GDoTRegister_Duration / GDoTRegister_DmgFrequency)))
      • -------- --------
      • Set GDoT_DpS[GDoT_Index] = (GDoTRegister_TotalDamage / (Real(GDoT_HitAmount[GDoT_Index])))
      • Set GDoT_AttackType[GDoT_Index] = GDoTRegister_AttackType
      • Set GDoT_DamageType[GDoT_Index] = GDoTRegister_DamageType
      • -------- --------
      • -------- add the instance to the list --------
      • Set GDoT_Next[GDoT_Index] = 0
      • Set GDoT_Prev[GDoT_Index] = GDoT_Prev[0]
      • Set GDoT_Next[GDoT_Prev[0]] = GDoT_Index
      • Set GDoT_Prev[0] = GDoT_Index
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GDoT_Index Equal to 1
        • Then - Actions
          • Custom script: call TimerStart(udg_GDoT_Iterator, udg_GDoT_INTERVAL, true, function GDoTOnIterate)
        • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • Custom script: function GDoTRegister takes nothing returns nothing
      • -------- wrapper --------
      • -------- you can config these --------
      • Set GDoTRegister_FxAttachPoint = origin
      • Set GDoTRegister_DmgFrequency = 1.00
      • Set GDoTRegister_AttackType = Spells
      • Set GDoTRegister_DamageType = Normal
      • Set GDoT_UseWrapper = False
      • Custom script: call GDoTRegisterEx()
but still, I can't solve it. The GDoT_Index just keep increasing.
Can you help me

EDIT: Update: Solved!
can you check the code :)
 
Last edited:
Level 5
Joined
May 2, 2015
Messages
109
Actually, this system is a mistake. There's already ton of system of this kind out there and they are even better.
If you guys have some idea that can make this system acceptable as approved system, I gladly to hear it. :)
And, about events in my system, can you guys tell me if I did something wrong.

@zv27: This is a system that can apply a DoT (Damage over Time) easily. You can see the demo I just provided in the description.
Also, except damaging units, you can also do something periodically by using the event. Like, creating a pulse of missile on every 0.25 s.
I haven't try this yet, but I think with the onDamage and EndDoT event, user can make a easy MUI spell.

@Chaosy: I don't know what to say about that easy method. From my imagination :) , that method will just wait and damage target (with just one hit) like a timed bomb. Can you tell me why use wait. From what I know, waits is forbidden.


EDIT: Updated!:
-fixed indexing problem
-fixed some minor problems
 
Last edited:

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,183
In jass it would be something like:

function DoT takes real dmg, unit target, real interval, integer numberOfTicks return nothing
//^ I am pretty sure those are considered local
local integer i = 0
loop
exitwhen i == numberofTicks
call TriggerSleepAction(interval)
deal dmg damage to target
set i = i + 1
endloop
endfunction

Waits can be up to 0.27 seconds inaccurate (at least that's what I read somewhere) which is why they are not used most of the time. But if it can cut down the code size to a third.. I'd say it's a decent trade.
 
Level 5
Joined
May 2, 2015
Messages
109
Ahh, now I understand. But still, my thought says using waits is not acceptable and I don't think that method can replace this kind of system as long as the accuration is the important thing in order to create a smooth and clean spell .
If there is 20 spell with DoT, 20 waits will loop.:eek:

And like you said waits is 0.27s inaccurate. I can't imagine a spell that requires high damage frequency.
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,183
I think there are some cases where waits are acceptable. Though they are few.
Still, even without a wait I think you could cut down your code in half at least.

This would be the loop:

every 0.03 seconds
pick every unit in myGroup
set u = picked unit
set h = handle of u
set count = load from hashtable with keys h 0 + 0.03
save count in hashtable with keys h and 0
set interval = load from hashtable with keys h 1
if count is greater or equal to interval
save 0 in hashtavle with keys h and 0
deal damage to u
set completedTicks = load from hashtable with keys h 2 + 1
save completedTicks in hashtable with keys h 2
if completedTicks is greater than or equal to load fro mhashtable with keys h 3
remove u from group, dot is finished
endif
endif

there are some lazy coding in that but the concept would be the same. Just move some stuff around for minimal bonus speed
 
Level 5
Joined
May 2, 2015
Messages
109
I will try and I'll add some sample spells that uses GDoT and its events, it will be the last update, I think (on second thought, I think its better to remove this system from Hive), and can I ask. Which is faster, Index or Hashtable? I'm confused:confused:
 
Level 10
Joined
Aug 21, 2010
Messages
316
I will try and I'll add some sample spells that uses GDoT and its events, it will be the last update, I think (on second thought, I think its better to remove this system from Hive), and can I ask. Which is faster, Index or Hashtable? I'm confused:confused:
There is no way that the human brain registers the difference in speed between the above,
but if you ask me,
1-0 in favor of the index in the first half of the match hahaha.
Of course a little humor does not hurt.
Now seriously, both the fine.
And one more thing. damage type fire = damage type magic no difference(
refers to your demo code)
 
Top