Snippet PeriodicDamage

Reaction score
341
PeriodicDamage
TriggerHappy187

Information

PeriodicDamage will let you cause damage to a unit over time. All it takes is one simple function call and with the three public functions this library provides it's easy to do so. Below is a list of the public functions.

  • UnitDamageTimedEx This function allows you to specify every option you would need for damaging a unit, including weapontype, damagetype and so on. Use this function if you have specific needs for how a unit should be damaged.
  • UnitDamageTimed This has less parameters than the one above but it is easier to use.
  • UnitDamageTimedSimple The easiest of all of the functions. This function doesn't require you to specify an attacker which is useful if you just want to damage a unit without another unit getting the experience or whatever.
  • GetLasCreatedPeriodicDamage Returns the last registered damagetimed struct.
  • DestroyPeriodicDamage Removes an instance of periodic damage, which means that nore more damage will be dealt to the unit.
  • SetTimedDamageValue Changes the damage dealt to a unit under the effect of PeriodicDamage.
  • SetTimedDamagePeriod Changes how often the unit is damaged.
  • SetPeriodicDamageEffect Creates an effect on the unit each time he is damaged.

Requirements


System Code

JASS:
//========================================================================================+
// _____                                                                                  |
//| ___ \          (_)           | |(_)                                                   |
//| |_/ /___  _ __  _   ___    __| | _   ___                                              |
//|  __// _ \| '__|| | / _ \  / _` || | / __|                                             |
//| |  |  __/| |   | || (_) || (_| || || (__                                              |
//\_|   \___||_|   |_| \___/  \__,_||_| \___|                                             |
//                ______                                                                  |
//                |  _  \   By TriggerHappy187                Version 1.2                 |
//                | | | | __ _  _ __ ___    __ _   __ _   ___                             |
//                | | | |/ _` || '_ ` _ \  / _` | / _` | / _ \                            |
//                | |/ /| (_| || | | | | || (_| || (_| ||  __/                            |
//                |___/  \__,_||_| |_| |_| \__,_| \__, | \___|                            |
//                                                 __/ |                                  |
//                                                |___/                                   |
//                                                                                        |
//+=======================================================================================+
//                                                                                        |
//                                                                                        |
// What is PeriodicDamage?                                                                |
// ^^^^^^^^^^^^^^^^^^^^^^^                                                                |
//      PeriodicDamage will let you cause damage to a unit over time.                     |
//      All it takes is one simple function call. These function calls                    |
//      will be explained below.                                                          |
//                                                                                        |
//                                                                                        |
// Public Functions                                                                       |
// ^^^^^^^^^^^^^^^^^^^^^^^                                                                |
//      UnitDamageTimedEx                                                                 |
//          This function allows you to specify every option you would need               |
//          for damaging a unit, including weapontype, damagetype and so on.              |
//          Use this function if you have specific needs for how a unit should be damaged.|
//          Parameters:                                                                   |____________________+
//              call UnitDamageTimedEx(attacker, unit, dmg, attacktype, damagetype, weapontype, timeout, times)|
//                                                                                                             |
//      UnitDamageTimed                                                                                        |
//          This has less parameters than the one above but it is easier to use.                               |
//          Parameters:                                                                                        |
//              call UnitDamageTimed(attacker, unit, dmg, timeout, times)                                      |
//                                                                                                             |
//      UnitDamageTimedSimple                                                                                  |
//          The easiest of all of the functions. This function doesn't require you                             |
//          to specify an attacker which is useful if you just want to damage a unit                           |
//          without another unit getting the experience or whatever.                                           |
//          Parameters:                                                                                        |
//              call UnitDamageTimed(unit, dmg, timeout, times)                                                |
//                                                                                                             |
//                                                                                                             |
//     GetLastCreatedPeriodicDamage()                                                                          |
//          Returns the last registered damagetimed struct.                                                    |
//                                                                                                             |
//                                                                                                             |
//     DestroyPeriodicDamage(instance)                                                                         |
//          Removes an instance of periodic damage, which means that nore more damage                          |
//          will be dealt to the unit.                                                                         |
//                                                                                                             |
//                                                                                                             |
//     SetPeriodicDamageValue(instance, damage)                                                                |
//          Changes the damage dealt to a unit under the effect of PeriodicDamage.                             |
//                                                                                                             |
//                                                                                                             |
//     SetPeriodicDamagePeriod(instance, period)                                                               |
//          Changes how often the unit is damaged.                                                             |
//                                                                                                             |
//                                                                                                             |
//     SetPeriodicDamageEffect(instance, effectmodel, attachmentpount)                                         |
//          Creates an effect on the unit each time he is damaged.                                             |
//                                                                                                             |
//                                                                                                             |
//     UnitDamagePointTimed                                                                                    |
//         Damages all units within range of the given coordinates                                             |
//                                                                                                             |
// Credits/Requirements                                                                                        | 
// ^^^^^^^^^^^^^^^^^^^^^^^                                                                                     |
//      * JassHelper (Comes with JassNewGenPack)                                                               |
//      * TimerUtils                                                                                           |
//                                                                                                             |
//=============================================================================================================+

library PeriodicDamage initializer onInit requires TimerUtils

    globals // Configurables
        private constant integer    DUMMY          = 'hfoo' // Any random unit-type (with no shadow)
        private constant integer    DEFAULT_PLAYER = PLAYER_NEUTRAL_PASSIVE
        private constant attacktype DEFAULT_AT     = ATTACK_TYPE_NORMAL
        private constant damagetype DEFAULT_DT     = DAMAGE_TYPE_NORMAL
        private constant weapontype DEFAULT_WT     = WEAPON_TYPE_WHOKNOWS
    endglobals
    
    private keyword damagetimed
    globals // Don't modify below this line.
        damagetimed lastCreatedPeriodicDamage = 0
        private group GROUP=CreateGroup()
    endglobals
    
    struct damagetimed
        
        unit u
        unit attacker
        integer times
        integer c = 0
        attacktype at
        damagetype dt
        weapontype wt
        real dmg
        timer t
        string fx = ""
        string attach = ""
        
        static unit dummy
        
        static method callback takes nothing returns nothing
            local damagetimed d = GetTimerData(GetExpiredTimer())
            call UnitDamageTarget(d.attacker, d.u, d.dmg, true, false, d.at, d.dt, d.wt)
            if d.fx != "" and d.attach != "" then
                call DestroyEffect(AddSpecialEffectTarget(d.fx, d.u, d.attach))
            endif
            set d.c = d.c + 1
            if d.c == d.times then
                call ReleaseTimer(d.t)
                call d.destroy()
            endif
        endmethod
        
        method setDamage takes real amount returns nothing
            set this.dmg = amount
        endmethod
        
        method setEffect takes string fx, string attachpoint returns nothing
            set this.fx = fx
            set this.attach = attachpoint
        endmethod
        
        method setPeriod takes real period returns nothing
            call PauseTimer(this.t)
            call TimerStart(this.t, period, true, function damagetimed.callback)
        endmethod
        
        static method last takes nothing returns damagetimed
            return lastCreatedPeriodicDamage
        endmethod
        
        static method create takes unit b, unit u, real a, attacktype at, damagetype dt, weapontype wt, real period, integer times returns damagetimed
            local damagetimed d = damagetimed.allocate()
            set d.u = u
            set d.attacker = b
            set d.times = times
            set d.at = at
            set d.wt = wt
            set d.dt = dt
            set d.dmg = a
            set d.t = NewTimer()
            call SetTimerData(d.t, d)
            call TimerStart(d.t, period, true, function damagetimed.callback)
            set lastCreatedPeriodicDamage = d
            return d
        endmethod
        
    endstruct

    function UnitDamageTimedEx takes unit b, unit u, real a, attacktype at, damagetype dt, weapontype wt, real period, integer duration returns damagetimed
        return damagetimed.create(b, u, a, at, dt, wt, period, duration)
    endfunction
    
    function UnitDamageTimed takes unit attacker, unit u, real dmg, real period, integer duration returns damagetimed
        return damagetimed.create(attacker, u, dmg, DEFAULT_AT, DEFAULT_DT, DEFAULT_WT, period, duration)
    endfunction
    
    function UnitDamageTimedSimple takes unit u, real dmg, real period, integer duration returns damagetimed
        return damagetimed.create(damagetimed.dummy, u, dmg, DEFAULT_AT, DEFAULT_DT, DEFAULT_WT, period, duration)
    endfunction
    
    function UnitDamagePointTimed takes real x, real y, real radius, filterfunc filter, real dmg, real period, integer duration returns nothing
        local unit u
        call GroupEnumUnitsInRange(GROUP, x, y, radius, filter)
        loop
            set u = FirstOfGroup(GROUP)
            exitwhen u == null
            call damagetimed.create(damagetimed.dummy, u, dmg, DEFAULT_AT, DEFAULT_DT, DEFAULT_WT, period, duration)
        endloop
    endfunction
    
    function DestroyPeriodicDamage takes damagetimed d returns nothing
        call ReleaseTimer(d.t)
        call d.destroy()
    endfunction
    
    function SetPeriodicDamageValue takes damagetimed d, real dmg returns nothing
        set d.dmg = dmg
    endfunction
    
    function SetPeriodicDamageEffect takes damagetimed d, string fx, string attachpoint returns nothing
        set d.fx = fx
        set d.attach = attachpoint
    endfunction
    
    function SetPeriodicDamagePeriod takes damagetimed d, real period returns nothing
        call PauseTimer(d.t)
        call TimerStart(d.t, period, true, function damagetimed.callback)
    endfunction
    
    function GetLastCreatedPeriodicDamage takes nothing returns damagetimed
        return lastCreatedPeriodicDamage
    endfunction
    
    private function onInit takes nothing returns nothing
        set damagetimed.dummy = CreateUnit(Player(13), DUMMY, 0, 0, 0)
        call SetUnitScale(damagetimed.dummy, .01, .01, .01)
        call PauseUnit(damagetimed.dummy, true)
        call UnitAddAbility(damagetimed.dummy, 'Aloc')
        call SetUnitOwner(damagetimed.dummy, Player(DEFAULT_PLAYER), false)
    endfunction

endlibrary


For those of you who want to know how to use it.

JASS:
scope PDUsage initializer onInit

    private function Actions takes nothing returns nothing
        local unit tobeattacked = CreateUnit(Player(0), 'hfoo', 0, 0, 0) // The unit to be damaged
        local real dmg = 100 // how much damage
        local real period = 1. // how often
        local integer times = 3 // how many times
        call UnitDamageTimedSimple(tobeattacked, dmg, period, times) // the unit will be dealt 300dmg over 3 seconds
        set tobeattacked = null // clear leaks
    endfunction

    //===========================================================================
    private function onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterTimerEvent(t, 0.00, false)
        call TriggerAddAction(t, function Actions)
    endfunction

endscope
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
but what is the period and pretty nice +rep
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
all i wanted to know is thats its 1 second
 

Flare

Stops copies me!
Reaction score
662
Nice, simple, appears to get the job done...
:thup:

One small thing I'd like to suggest - perhaps the times parameter should be duration parameter. Maybe it's just me, but I think that a clearly defined duration is nicer than a number of damage ticks.
Knowing precisely how long the effect will last at first glance is far more informative than having to spend time calculating how often your X ticks will have to occur to achieve the desired duration. Figuring out how long a spell that ticks 16 times, once every 0.75 seconds, is more effort than simple setting a spell to tick every 0.75 seconds for 12 seconds :p Same overall effect, but you can see straight-off that the spell will last 12 seconds, no calculations (however simple they may be) whatsoever :)

EDIT: Also, what're the chances of this being modified to allow the addition of special effects? I'm not saying that you have to, but it would certainly be a nice addition (a fiery damage-over-time effect just doesn't cut it if there isn't any visible fire :D). Might make the function a tad long, but perhaps you could do something where the user would add an effect to the DoT like so
JASS:
set PeriodicDamage_EffectPath = "model\\path.mdx"
set PeriodicDamage_AttachPoint = "chest"
call UnitDamageTimed (...)

and set EffectPath and AttachPoint to "" after the effect has been created (so that subsequent DoT's wouldn't get the same effect unless so desired)
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
TimeUtils is not fast enough to handle when many instance are running.(lag) You could add linked list, so it can runs more smoothly.

Your example is bad... You could inline it....
 

Flare

Stops copies me!
Reaction score
662
Your example is bad... You could inline it....
It's just an example to demonstrate how the function is called. It doesn't matter if how good/bad it is, as long as it gets the point across.

From looking at the given example and comments kingkingyyk3, do you have an idea of how you would use the system? If so, then the example is fine and doesn't need to be changed.
 
Reaction score
341
Your example is bad... You could inline it....

It's also understandable for noobs.

TimeUtils is not fast enough to handle when many instance are running.(lag) You could add linked list, so it can runs more smoothly.

Well until I see some proof, I'll stick with TU. I'm also not familiar with LinkedLists.
 

Dr.Jack

That's Cap'n to you!
Reaction score
109
How about adding functions like these?

StopUnitDamage - Stops a damaging the unit
ModifyDamage - Modify the damage dealt.
ModifyTime - Modify the damaging duration.
 

Larcenist

REP: Respect, Envy, Prosperity?
Reaction score
211
TimeUtils is not fast enough to handle when many instance are running.(lag) You could add linked list, so it can runs more smoothly.

So you've seen someone use linked lists and thought that they should be abused for everything?

A simple struct stack with a global timer on the other hand could be used for something like this.
 
Reaction score
341
Updated to version 1.1, added a bunch of new functions/methods.

Tell me if I forgot something because I did it pretty fast.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Bloated, simple concept already, done to death.
That's my problem with this snippet.

Do we need snippets for the obvious? And it isn't that useful directly since remaking it for the specific purpose is going to be more efficient. And more flexible, since often we'll want a knockback or stun or maybe make it splash in AoE or have some kind of effect... or...
 
Reaction score
341
Well I think it's extremely useful for shortening spell codes.

I mean, it takes like all of this to damage the unit over time;

JASS:
scope spell

    private struct data
        unit u
        unit t
        timer ti
    endstruct
    
    function callback takes nothing returns nothing
        local data d = GetTimerData(GetExpiredTimer())
        call UnitDamageTarget(....)
        if .. then
            call ReleaseTimer(d.t)
            call d.destroy()
        endif
    endfunction
    
    function Actions takes nothing returns nothing
        local data d = data.create()
        set d.u = GetTriggerUnit()
        set d.t = GetSpellTargetUnit()
        set d.ti = NewTimer()
        call SetTimerData(d.ti, d)
        call TimerStart(d.ti, 0.03, true, function callback)
        return d
    endfunction
    
    function onInit takes nothing returns nothing
        ....
        .....
        ......
    endfunction
    
endscope


While it would only be a function call with PeriodicDamage. I understand for some more complex spells that already use a timer and expect to damage a unit within that interval then they probably wouldn't use this.
 

Jesus4Lyf

Good Idea™
Reaction score
397
JASS:
private struct data
    unit u
    unit t
    timer ti
endstruct
function callback takes nothing returns nothing
    local data d = GetTimerData(GetExpiredTimer())
    call UnitDamageTarget(....)
    if .. then
        call ReleaseTimer(d.t)
        call d.destroy()
    endif
endfunction
function Actions takes nothing returns nothing
    local data d = data.create()
    set d.u = GetTriggerUnit()
    set d.t = GetSpellTargetUnit()
    set d.ti = NewTimer()
    call SetTimerData(d.ti, d)
    call TimerStart(d.ti, 0.03, true, function callback)
    return d
endfunction
All of 22 lines?

Besides, you can make a self-target permanent immolation! :p (Jokes, but it does work.)

Or use Shadow Strike.

Just my thoughts on this. =/
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top