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.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +1
  • V-SNES V-SNES:
    Happy Friday!
    +1

      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