System Set Unit Current State (Damage Over Time)

Kenny

Back for now.
Reaction score
202
Set Unit Current State

AKA SUCS

By kenny!

This is a system i through together because i was sick of writing damage over time scripts every time i needed one. It began as a simple DoT system, but it has now developed into a system that can be used to damage unit over time, heal unit over time, reduce mana over time and replenish mana over time. It uses two pretty simple functions, one for health and one for mana.

The functions allow you to specify which target, to heal or damage that target, how much damage, what interval to use, the max duration, attack and damage types and special effects with attachment points.

Examples of function calls:

JASS:
call SUCS_Health(true,caster,target,20.00,1.00,10.00,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,'A000',"Dirt.mdx","chest")

or

call SUCS_Mana(true,caster,target,40.00,3.00,15.00,'A001',"Water.mdx","origin")


Each of these will reduce the health or mana of a target unit over time.

Pros:
  • Do not need to write a damage over time script yourself.
  • Removes the need to write one everytime you need a damage over time spell.
  • Completely self-contained. No need for other systems. MUI and leakless.
  • Includes a warning message if arguments in the function are invalid.
  • Easy implementation.
  • Very simplistic system, but effective.

Cons:
  • A lot of arguments in the function may get annoying, but they are worth it nonetheless.
  • Requires the use of spells and buffs that are made by you. This however, is countered by its effectiveness :).
  • You did not write it yourself. So unless your alright at JASS you will have to read it a few times to get it.

The major con for many people will be number two on the list. So let me explain it. Lets say you trigger a spell, and it is going to be like Soul Burn from the melee hero Firelord. So instead of writing all the script by yourself you decide to use this system :). so all you need to do in the actions function is this:

JASS:
call SUCS_Health(true,caster,target,10.00,1.00,20.00,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_FIRE,'A000',"Abilities\\Spells\\Other\\ImmolationRed\\ImmolationRedDamage.mdl","chest")


And your basically done. Now i know what your thinking, wow that function call is too long. Well, in all honesty is probably is, but this allows you to change almost every aspect of the spell, which is a major + in my books.

So now what your thinking is whats with the 'A000' thing. Well, this is a dummy skill that you will need to make (Maybe based off Slow Aura or something). This spell will also have a buff, that you will also have to make. This ensure that the spell not only works well, but looks good and makes it non-stackable with the same spell, to reduce conflicting.

And finally, now what you are probably thinking is why the hell should i do all that. Well lets think about it.

- Making a dummy spell with its own buff = Maybe 5 minutes MAX.
- Making your own damage over time spell that works well and has as much possibilities as this one = Maybe hours for some of us out there, and probably more then 5 minutes for the rest of you people.

So there it is, the reason to use this system.

More information is in the script of the system below. Please report any leaks, bugs, mistakes or anything that should be added/removed to me asap, i am positive someone will find something.

JASS:
library SUCS

//***************************************************************************************
//*     
//*     Set Unit Current State (SUCS):                                *** By kenny! ***
//*     v1.00
//*
//*     Can be used as a global Damage Over Time system for a variety of applications
//*     within ones map. Uses specified variables by the user to create the desired
//*     damage over time spell.
//*
//*     Requires:
//*         - No other systems. This system is completely self-contained.
//*         - A vJASS preprocessor ( NewGen Jass Pack 1.5a ).
//*         - The use of Spells and Buffs
//***************************************************************************************

//***************************************************************************************
//*
//*     Usage:
//*         There are two functions that can be called in this system. One is SUCS_Health
//*         and the other is SUCS_Mana. Each function requires certain arguments to
//*         ensure that it works properly. Each function has two uses. One is damaging
//*         or decreasing health/mana and the other is healing health/mana. 
//*
//*     Function List and Descriptions:
//*        
//*         call SUCS_Health(IsDamage,Caster,Target,Damage,Interval,MaxDuration,AttackType,DamageType,BuffSpell,Sfx,Attach)
//*             * As you can see this function has a lot of calls. This is due to the 
//*               amount of variables needed for damage over time.
//*         call SUCS_Mana(IsDamage,Caster,Target,Damage,Interval,MaxDuration,BuffSpell,Sfx,Attach)
//*             * This function has two less arguments. It does not need AttackType or
//*               DamageType as it is dealing with mana.
//*
//*         - IsDamage    - This is a boolean argument. If it returns true it will deal
//*                         DAMAGE, if it returns false it will HEAL the target.
//*         - Caster      - The unit that will be dealing the damage/casting the spell.
//*         - Target      - The unit that will be getting dealt damage/healed.
//*         - Damage      - The amount of damage dealt or hp/mana healed per interval.
//*         - Interval    - Duration between damage dealt, damage dealt every X seconds.
//*         - MaxDuration - The maximum duration of the spell/damage over time.
//*         - AttackType  - Attacktype of the damage dealt.
//*         - DamageType  - Damagetype of the damage dealt.
//*         - BuffSpell   - This is the buff spell that is needed for the system. Each
//*                         spell that uses this system will need a spell ( Best based
//*                         off Slow Aura(Tornado) ) and the corresponding buff for that
//*                         spell.
//*         - Sfx         - The special effect that will be attached to the target unit.
//*                         This effect will be shown every Interval. It is NOT an effect
//*                         that lasts the duration of the spell. If you do not want an
//*                         effect put "" or null.
//*         - Attach      - The attachment point of the special effect (above). If you
//*                         do not specify an attachment point the default is "chest".
//***************************************************************************************

//***************************************************************************************
//*
//*     Pros:
//*         - Do not need to write a damage over time script yourself.
//*         - Removes the need to write one everytime you need a damage over time spell.
//*         - Completely self-contained. No need for other systems. MUI and leakless.
//*         - Includes a warning message if arguments in the function are invalid.
//*         - Easy implementation.
//*         - Very simplistic system, but effective.
//*
//*     Cons:
//*         - A lot of arguments in the function may get annoying, but they are worth it
//*           nonetheless.
//*         - Requires the use of spells and buffs that are made by you. This however, is
//*           countered by its effectiveness <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile    :)" loading="lazy" data-shortname=":)" />.
//*         - You did not write it yourself. So unless your alright at JASS you will have
//*           to read it a few times to get it.
//***************************************************************************************

//***************************************************************************************
//*
//*     Examples of use:
//*
//*     call SUCS_Health(true,caster,target,25.00,1.00,10.00,ATTACK_TYPE_CHAOS,
//*          DAMAGE_TYPE_UNIVERSAL,&#039;A000&#039;,&quot;Dust.mdx&quot;,&quot;origin&quot;)
//*
//*         * This will deal 25 chaos damage per second for 10 seconds to the target.
//*           The unit will have a dust effect appear on it every second at its origin.
//*           The spell &#039;A000&#039; will be a spell based off something like Slow Aura, which
//*           will give the unit a buff, and make sure the same spell wont stack together.
//***************************************************************************************

//***************************************************************************************
//* DO NOT TOUCH UNDER HERE UNLESS YOU KNOW WHAT YOU ARE DOING!!
//***************************************************************************************

globals
    private timer Timer = CreateTimer()
    private integer Total = 0        
    private integer array DataArray
endglobals

private struct Data
    attacktype at
    boolean hp
    boolean isdam
    damagetype dt
    integer buffspell = 0
    real dam = 0.00
    real interval = 0.00
    real threshold = 0.00
    real duration = 0.00
    string sfx
    string attachment
    unit cast
    unit targ
    
    //* Below: Adds Special effect to target.
    static method AddEffects takes unit u, string sfx, string attach returns nothing
        if sfx != &quot;&quot; and sfx != null then
            if attach != &quot;&quot; and attach != null then
                call DestroyEffect(AddSpecialEffectTarget(sfx,u,attach))
            else
                call DestroyEffect(AddSpecialEffectTarget(sfx,u,&quot;chest&quot;))
            endif
        endif
    endmethod
    
    //* Below: Begins the damage over time. Shows a warning is something is wrong.
    static method create takes boolean IsHealth, boolean IsDamage, unit Caster, unit Target, real Damage, real Interval, real MaxDuration, attacktype AttackType, damagetype DamageType, integer BuffSpell, string Sfx, string Attach returns Data
        local Data d = Data.allocate()
        
        if Caster == null or Target == null or Damage &lt;= 0.00 or Interval &lt;= 0.00 or MaxDuration &lt;= 0.00 or BuffSpell == 0 then
            call BJDebugMsg(&quot;Error: Invalid input into SUCS_Health/Mana&quot;)
            return 0
        endif
        
        if GetUnitAbilityLevel(Caster,BuffSpell) &gt; 0 then
            return 0
        endif
        
        set d.hp = IsHealth
        set d.isdam = IsDamage
        set d.cast = Caster
        set d.targ = Target
        set d.dam = Damage
        set d.interval = Interval
        set d.threshold = MaxDuration
        set d.buffspell = BuffSpell
        set d.at = AttackType
        set d.dt = DamageType
        set d.sfx = Sfx
        set d.attachment = Attach
          
        // Below: Adds spell to unit if it does not aleady have it.
        call UnitAddAbility(d.targ,d.buffspell)
            
        if Total == 0 then
            call TimerStart(Timer,d.interval,true,function Data.Execute)
            // call BJDebugMsg(&quot;DoT Started&quot;)
        endif
        
        set DataArray[Total] = d
        set Total = Total + 1
            
        return d
    endmethod
    
    //* Below: Heals/Damages unit per Interval. Finishes at MaxDuration or if unit is dead.
    static method Execute takes nothing returns nothing
        local integer i = Total - 1
        local Data d
        
        loop
            exitwhen i &lt; 0
            set d = DataArray<i>
            
            if d.duration &gt;= d.threshold or GetWidgetLife(d.targ) &lt;= 0.405 then
                call UnitRemoveAbility(d.targ,d.buffspell)  // Removes buff.
                call d.destroy()    // Finishes the damage over time.
                set Total = Total - 1
                if Total &lt; 0 then
                    call PauseTimer(Timer)
                    set Total = 0
                else
                    set DataArray<i> = DataArray[Total]
                endif
            elseif GetWidgetLife(d.targ) &gt;= 0.405 and GetUnitAbilityLevel(d.targ,d.buffspell) &gt; 0 then
                if d.hp then
                    if d.isdam then
                        // Damages the target unit.
                        call UnitDamageTarget(d.cast,d.targ,d.dam,false,false,d.at,d.dt,null)
                        call d.AddEffects(d.targ,d.sfx,d.attachment)
                    else
                        // Heals the target unit.
                        call SetWidgetLife(d.targ,GetWidgetLife(d.targ)+d.dam)
                        call d.AddEffects(d.targ,d.sfx,d.attachment)
                    endif
                else
                    if d.isdam then
                        // Damages the target units mana.
                        call SetUnitState(d.targ,UNIT_STATE_MANA,GetUnitState(d.targ,UNIT_STATE_MANA)-d.dam)
                        call d.AddEffects(d.targ,d.sfx,d.attachment)
                    else
                        // Replenishes target units mana.
                        call SetUnitState(d.targ,UNIT_STATE_MANA,GetUnitState(d.targ,UNIT_STATE_MANA)+d.dam)
                        call d.AddEffects(d.targ,d.sfx,d.attachment)
                    endif
                endif
                
                set d.duration = d.duration + d.interval
            endif
            set i = i - 1
        endloop
    endmethod
    
    //* Below: finishes the damage over time.
    private method onDestroy takes nothing returns nothing
        set .cast = null
        set .targ = null
        // call BJDebugMsg(&quot;DoT Ended&quot;)
    endmethod
endstruct

//* Below: Only two functions used in this library.
public function Health takes boolean IsDamage, unit Caster, unit Target, real Damage, real Interval, real MaxDuration, attacktype AttackType, damagetype DamageType, integer BuffSpell, string Sfx, string Attach returns nothing
    call Data.create(true,IsDamage,Caster,Target,Damage,Interval,MaxDuration,AttackType,DamageType,BuffSpell,Sfx,Attach)
endfunction

public function Mana takes boolean IsDamage, unit Caster, unit Target, real Damage, real Interval, real MaxDuration, integer BuffSpell, string Sfx, string Attach returns nothing
    call Data.create(false,IsDamage,Caster,Target,Damage,Interval,MaxDuration,null,null,BuffSpell,Sfx,Attach)
endfunction

endlibrary</i></i>


DEMO MAP WILL BE ATTACHED AS SOON AS I HAVE WC3 BACK!!
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,495
> map will be attached as soon as I have wc3 back

You mean it crashed and burned right after you posted this? Or where is this coming from?
 

Kenny

Back for now.
Reaction score
202
You mean it crashed and burned right after you posted this? Or where is this coming from?

Haha, no. I don't have WC3 on this computer, i just used notepad. But i made this is WC3 a while ago and it used ABC and CSSafety. So i decided today to make it use nothing. Heres where the bad news comes in:

I thought that a basic struct array could be used, such as ones you use in knockback functions. But after reading through my script more carefully this time, i realised that this actually doesn't even work...

I just looked for syntax, i didn't even think about the logistics of it.

So i guess you could say that:

You mean it crashed and burned right after you posted this?

The crashing and burning part is probably true. It may pass the syntax check but im doubting this will actually work now. I guess thats what i get for not testing it extensively and testing after the final changes.

My bad, um you can graveyard this or something if you want. Ill go back to the drawing board.
 

Kenny

Back for now.
Reaction score
202
Its not really WIP. I thought it was done, figured it was screwed up, asked for it to be graveyarded, end of story. Honest mistake on my behalf, dont know how i let it slip pass me. When i said "back to the drawing board" i was refering to re-writing a whole other system that isnt shit.
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
I was reading through your script, and I can only see one problem in it.

Hero1 casts a health sucking ability on a weak unit. Hero2 casts a health sucking ability on a strong unit. The Total variable for instances of the spell is at 1 right now (2 values, 0 and 1). Because Hero1's target is weak, he dies much earlier than the length of the spell. Total is set to 1, but Hero2 occupies the second array value. Hero3 casts another life spell, and all of a sudden, Hero2's spell ends, and Hero3's spell starts normally, while Hero2's spell leaves all of the attachments and leaks no longer accessible by variable.

Basically, the same thing happens as with GUI non-MUI, except that you can have multiple units cast the spell. They just all have to finish their spell in the order they started them.

There are two ways to fix this problem.

One is to go through a loop each time you destroy a struct, and put spells in order, filling the gap of a destroyed struct with the struct ahead of it. However, you're already doing a looping method, which might not be such a great thing for lag.

The other way would be to removed the conditions for when a unit dies to remove the struct, and to just let the spell go through the rest of its timer expires, and then destroy the struct at the end of the spell. However, this would create conflicts with spells with different durations.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top