System DOT - Damage Over Time

cr4xzZz

Also known as azwraith_ftL.
Damage Over Time System v1.1

This is supposed to be a remake of my DPS system because it was not good enough. So I bring you this fresh new system that allows you to damage a unit for a specific duration every specific second(s) if it has a specific buff. It has a variety of Set and Get functions that allow you to control the system almost completely. I hope this one is better than the last one...

Requires:
- JASS NewGen Editor
- ABCT v2.0 (or higher)
- PUI v4.2 (or higher)

Implementation Instructions:
JASS:

//==============================================================================
//        Damage Over Time System [v 1.1] by cr4xzZz
//==============================================================================

' PURPOSE:

 - Creating damage over time spells the easy way
 - Save time on damage over time spells
 
 ' HOW IT WORKS:
 
  - When you call the start function ( DOT_Start() ) 
    a periodic timer will run every 0.1 seconds for 
    5 seconds, checking each period if the target
    has the assigned buff you chose. If in that time
    the target is applied the buff then DOT starts
    with all the values you used. If the target does 
    not recieve that buff on time (5 secs) then the
    function is cancelled. These values can be
    changed to satisfy your needs (look for a 
    comment in the globals in the DOT trigger). 
  - After the normal damaging starts the system
    checks if the target has the assigned buff 
    each time before it damages it. If the target
    does not have that buff then the damaging
    stops. The system stops if the buff is dispelled,
    too (obviously). 
  - The system attaches all values to array globals
    thanks to PUI. That way they can easily be used
    for Set and Get functions.
    
' HOW TO USE:

 - call DOT_Start( DAMAGER, TARGET, PERIOD, DURATION, BUFF, DAMAGE, ATTACK TYPE, DAMAGE TYPE, MELEE?, RANGED?, EFFECT, ATTACHMENT POINT)
    * DAMAGER - unit; The unit that is going to damage something
    * TARGET - unit; The target unit that is going to be damaged
    * PERIOD - real; Period per damaging 
    * DURATION - real; Maximum duration of the damaging
    * BUFF - integer; The buff that is required for the damaging to work
        // raw code !
        //! IF THE TARGET DOES NOT HAVE THAT
        //! BUFF THEN THE DAMAGING STOPS
    * DAMAGE - real; The damage dealt per each period
        //! NOTE THAT THIS IS NOT THE MAX DAMAGE
    * ATTACK TYPE - attacktype; The attack type of the damaging
    * DAMAGE TYPE - damagetype; The damage type of the damaging
    * MELEE? - boolean; If it is a melee type damage 
    * RANGED? - boolean; If it i s a ranged type damage
        // these two booleans must be true or false
    * EFFECT - string; Special effect string
    * ATTACHMENT POINT - string; The attachment point of the special effect
    
' OTHER FUNCTIONS:

//! Note that these functions work only on the TARGET
//! and NOT on the DAMAGER ! This means that the
//! unit argument should be a TARGET that has DOT 
//! on it.

 - call DOT_SetDamage(unit TARGET, real AMOUNT)
 - call DOT_SetDuration(unit TARGET, integer AMOUNT)
 - call DOT_SetAttackType(unit TARGET, attacktype ATTACK TYPE)
 - call DOT_SetDamageType(unit TARGET, damagetype DAMAGE TYPE)
    // this must be true or false
 - call DOT_SetMelee(unit TARGET, boolean MELEE?)
    // this must be true or false
 - call DOT_SetRange(unit TARGET, boolean RANGED?)
 - call DOT_SetEffect(unit TARGET, string EFFECT)
 - call DOT_SetAttachmentPoint(unit TARGET, string ATTACHMENT POINT)

 
 - call DOT_GetDamage(unit TARGET) -> real AMOUNT
 - call DOT_GetDuration(unit TARGET) -> integer AMOUNT
 - call DOT_GetAttackType(unit TARGET) -> attacktype ATTACK TYPE
 - call DOT_GetDamageType(unit TARGET) -> damagetype DAMAGE TYPE
 - call DOT_GetMelee(unit TARGET) -> boolean MELEE?
 - call DOT_GetRange(unit TARGET) -> boolean RANGED?
 - call DOT_GetEffect(unit TARGET) -> string EFFECT
 - call DOT_GetAttachmentPoint(unit TARGET) -> string ATTACHMENT POINT
 
 - call DOT_Stop(unit TARGET) // stop all assigned DOT functions
 - call DOT_AddDuration(unit TARGET, integer AMOUNT) // add more duration to the damaging
 
 ' PROS:
    - Easy to use 
    - A lot customizeable
    - Can be fully controlled
' CONS:
    - None? (cannot think of any...)
    
' HOW TO IMPLEMENT: 
    - Copy the ABCT and PUI systems if you
      do not have them
    - Copy the DOT trigger in your map
    
' CREDITS TO:
    - Cohadar for ABCT v2.0 and PUI v4.2
    
' CHANGELOG:
    - v1.0: First release
    - v1.1: No changes at all. Just uses the newest version of ABCT (v 2.0)

Code:
JASS:

//==============================================================================
//        Damage Over Time System [v 1.1] by cr4xzZz
//==============================================================================


library DOT uses ABCT, PUI

globals
    private real array DPP
    private integer array DURATION
    private attacktype array ATTACK
    private damagetype array DAMAGE
    private string array EFFECT
    private string array POINT
    private boolean array MELEE
    private boolean array RANGE
// - Can be configured - 
    private constant real CHECK_PERIOD = 0.1 //period for buff checkup
    private constant real MAX_CHECK_TIME = 5. //max wait time for buff checkup
endglobals
// - DO NOT change anything below this line !!! -

private struct SysStruct
    unit damager
    unit target
    real period
    integer buffz
    integer temp
    timer clock = CreateTimer()
    
    static method create takes unit whichUnit, unit whichTarg, integer whichBuff, real whichPeriod returns SysStruct
        local SysStruct data = SysStruct.allocate()
        set data.damager = whichUnit
        set data.target = whichTarg
        set data.buffz = whichBuff
        set data.period = whichPeriod
        set data.temp = R2I(MAX_CHECK_TIME / CHECK_PERIOD)
        return data
    endmethod

    method onDestroy takes nothing returns nothing
        set DURATION[GetUnitIndex(.target)] = 0
        call PauseTimer(.clock)
        call DestroyTimer(.clock)
    endmethod
endstruct

// - - - - - SET FUNCTIONS - - - - -
public function SetDamage takes unit whichUnit, real whichDmg returns nothing
    set DPP[GetUnitIndex(whichUnit)] = whichDmg
endfunction

public function SetDuration takes unit whichUnit, integer whichInt returns nothing
    if whichInt > 0 then
        set DURATION[GetUnitIndex(whichUnit)] = whichInt
    else    
        //debug call BJDebugMsg("|cffffcc00[DOT] -|r Cannot use <= 0 in SetDuration(). Use Stop() instead")
    endif
endfunction

public function SetAttackType takes unit whichUnit, attacktype whichAttackType returns nothing
    set ATTACK[GetUnitIndex(whichUnit)] = whichAttackType 
endfunction

public function SetDamageType takes unit whichUnit, damagetype whichDamageType returns nothing
    set DAMAGE[GetUnitIndex(whichUnit)] = whichDamageType
endfunction

public function SetMelee takes unit whichUnit, boolean whichBool returns nothing
    set MELEE[GetUnitIndex(whichUnit)] = whichBool
endfunction

public function SetRanged takes unit whichUnit, boolean whichBool returns nothing
    set RANGE[GetUnitIndex(whichUnit)] = whichBool
endfunction

public function SetEffect takes unit whichUnit, string whichFx returns nothing
    set EFFECT[GetUnitIndex(whichUnit)] = whichFx
endfunction

public function SetAttachmentPoint takes unit whichUnit, string whichPoint returns nothing
    set POINT[GetUnitIndex(whichUnit)] = whichPoint
endfunction

// = = = = = = = = = = = = = = = = = = = = = = = = = =
// - - - - - GET FUNCTIONS - - - - -
public function GetDamage takes unit whichUnit returns real
    return DPP[GetUnitIndex(whichUnit)] 
endfunction

public function GetDuration takes unit whichUnit returns integer
    return DURATION[GetUnitIndex(whichUnit)]
endfunction

public function GetAttackType takes unit whichUnit returns attacktype
    return ATTACK[GetUnitIndex(whichUnit)]
endfunction

public function GetDamageType takes unit whichUnit returns damagetype
    return DAMAGE[GetUnitIndex(whichUnit)]
endfunction

public function GetMelee takes unit whichUnit returns boolean
    return MELEE[GetUnitIndex(whichUnit)]
endfunction

public function GetRange takes unit whichUnit returns boolean
    return RANGE[GetUnitIndex(whichUnit)]
endfunction

public function GetEffect takes unit whichUnit returns string
    return EFFECT[GetUnitIndex(whichUnit)]
endfunction

public function GetAttachmentPoint takes unit whichUnit returns string
    return POINT[GetUnitIndex(whichUnit)]
endfunction
// = = = = = = = = = = = = = = = = = = = = = = = = = =

public function Stop takes unit whichUnit returns nothing
    set DURATION[GetUnitIndex(whichUnit)] = 0
    //debug call BJDebugMsg("|cffffcc00[DOT] -|r DOT stops")
endfunction

public function AddDuration takes unit whichUnit, integer whichInt returns nothing
    set DURATION[GetUnitIndex(whichUnit)] = DURATION[GetUnitIndex(whichUnit)] + whichInt
endfunction

private function Damage takes nothing returns boolean
    local SysStruct data = ABCT_GetData()
    local integer pui = GetUnitIndex(data.target)
    if GetWidgetLife(data.target) >= 0.405 and GetUnitAbilityLevel(data.target, data.buffz) > 0 and DURATION[pui] > 0 then
        call UnitDamageTarget(data.damager, data.target, DPP[pui], MELEE[pui], RANGE[pui], ATTACK[pui], DAMAGE[pui], null)
        call DestroyEffect(AddSpecialEffectTarget(EFFECT[pui], data.target, POINT[pui]))
    else
        call data.destroy()
        //debug call BJDebugMsg("|cffffcc00[DOT] -|r DOT finishes")
        return true
    endif
    set DURATION[pui] = DURATION[pui] - 1
    return false
endfunction

private function Check takes nothing returns boolean
    local SysStruct data = ABCT_GetData()
    if GetUnitAbilityLevel(data.target, data.buffz) > 0 then
        call ABCT_Start(function Damage, data, data.period)
        //debug call BJDebugMsg("|cffffcc00[DOT] -|r DOT starts")
        return true
    endif
    set data.temp = data.temp - 1
    if data.temp <= 0 then 
        call data.destroy()
        //debug call BJDebugMsg("|cffffcc00[DOT] -|r DOT cancelled")
        return true
    endif
    return false
endfunction

public function Start takes unit whichUnit, unit whichTarg, real whichPeriod, real whichDur, integer whichBuff, real whichDmg, attacktype whichAttackType, damagetype whichDamageType, boolean isMelee, boolean isRange, string whichFx, string whichPoint returns nothing
    local SysStruct data = SysStruct.create(whichUnit, whichTarg, whichBuff, whichPeriod)
    local integer pui = GetUnitIndex(data.target)
    set DPP[pui] = whichDmg
    set DURATION[pui] = DURATION[pui] + R2I((1. / whichPeriod) * whichDur)
    set ATTACK[pui] = whichAttackType
    set DAMAGE[pui] = whichDamageType
    set MELEE[pui] = isMelee
    set RANGE[pui] = isRange
    set EFFECT[pui] = whichFx
    set POINT[pui] = whichPoint
    call ABCT_Start(function Check, data, CHECK_PERIOD)
endfunction

endlibrary


Test map includes Frost Nova and Acid Bomb spell test (for buffs).

Changelog:
JASS:

  v1 -    First release
  v1.1 - Absolutely no changes. The system just uses the newest version of ABCT.
 

Attachments

0zaru

Learning vJASS ;)
SetDuration shouldn't add more duration to the current duration. It should set the duration :p Maybe rename it to addDuration

Maybe add a debug in front of

call BJDebugMsg("|cffffcc00[DOT] -|r DOT finishes") and the rest of bjdebugmsg..

Seems very nice :d
 

GoGo-Boy

You can change this now in User CP
Oh I said I was looking for it when it has been out already ^_°. However, sounds really great!!
2 questions though.
First, the special effects, are that the effects that occur each time the damage happens or the ones that last as long as the buff resists? (I guess the periodic damage effect, since we can manipulate the buff to correspond anyway).

Second, you have this setblabla(unit target...) getblabla(unit target) in EVERY function you give us, isn't there a way to remove them and optimize the system, since it's the same unit anyway?
 

cr4xzZz

Also known as azwraith_ftL.
> SetDuration shouldn't add more duration to the current duration. It should set the duration
Yah, u're right ... I wanted to keep the "set" and "get" theme :D I'll fix it later cuz now I'm not on my precious computer

> ^_°. However, sounds really great
Thank you. ^^


> First, the special effects, are that the effects that occur each time the damage happens or the ones that last as long as the buff resists?
Well, the effect appears every time the unit is damaged. I forgot to mention that in the first post... Will do in the next ver. ^^

> Second, you have this setblabla(unit target...) getblabla(unit target) in EVERY function you give us, isn't there a way to remove them and optimize the system, since it's the same unit anyway?
Urm, you can use it for every unit you want. If I find a more optimized way I'll make it, but as for now I think it's fine. :eek:

EDIT: Okay, fixed SetDuration() and added AddDuration() ^^

EDIT2:
> Maybe add a debug in front of
What's the purpose of that anyway? Doesn't normal BJDebugMsg work fine?
 

0zaru

Learning vJASS ;)
Yes but It's displayed even when you are playing on b.net...

debug keyword works like this:

When you are testing the map in debug mode (JassHelper > Enable DebugMode) the parser simple deletes the word debug leaving the function call normally. But if you are not in debug mode It simple deletes that line.
 

cr4xzZz

Also known as azwraith_ftL.
> It simple deletes that line.
Ow, I see...
Well, any other comments, anybody? ^^

EDIT:
New version. Absolutely no changes. Just uses the newest version of ABCT - v2.0.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    It happens in corporations. They just absorb the companies they buy and it is not about the love of making awesome games it is how much money can we make with the least amount of cost.
  • The Helper The Helper:
    Blizzard is watered down now hopefully they can pull it together
  • The Helper The Helper:
    they got a server engineer job opening :)
  • Ghan Ghan:
    I really do not want to move to California otherwise I might consider it.
  • The Helper The Helper:
    yeah California is not anywhere you really want to live
  • The Helper The Helper:
    That is why I did not take the job Blizzard offered me back in the day, there is no way I could have moved my family there on what they were offering, not even close and that was like 20 years ago
  • The Helper The Helper:
    yeah they wanted me on the tech support team when they did not get me they got one of the next MVPs in Dinobot
  • The Helper The Helper:
    Dinobot was one of the youngest of the MVPs tkron probably could have worked for Blizzard but he had a good job in Chicago doing business programming already
  • The Helper The Helper:
    Dinobot probably still works for Blizzard would love to reconnect with that guy
  • The Helper The Helper:
    I wonder what ever happened to Wargasm?
  • The Helper The Helper:
    This new version of Xenforo really is awesome
  • Ghan Ghan:
    Wargasm is still around. He works for the domain registrar where thehelper.net is kept.

    Members online

    No members online now.

    Affiliates

    Hive Workshop
    Top