HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Damage over Time System

11-15-2008, 10:11 PM#1
zetanno
I am trying to find a damage over time system for my map and I would need some help cuz I haven't find anything yet . If it is possible ,it may also check is the unit has a specific buff to do the damage .
11-16-2008, 12:01 AM#2
TEC_Ghost
Collapse JASS:
//===============================================================
//Rejuvenation Callback Timer
//===============================================================
function Rejuvinate_Tick takes nothing returns nothing
local timer T = GetExpiredTimer()
local Rejuvinate Rejuv = GetTimerData(T)
local integer BonusHeal = 0


set Rejuv.CurrentTick = Rejuv.CurrentTick + 1
set Rejuv.CurrentDuration = Rejuv.CurrentDuration + 1


    if Rejuv.CurrentTick == R2I(Rejuv.Tick/INTERVAL) then
        
    if UnitHasBuffBJ(Rejuv.Target,'B000') == true then


            call SetUnitLifeBJ( Rejuv.Target, GetUnitStateSwap(UNIT_STATE_LIFE, Rejuv.Target) + (Rejuv.HealPerTick+BonusHeal))
    
            call CreateTextTagUnitBJ( "+" + I2S(Rejuv.HealPerTick+BonusHeal), Rejuv.Target, 0, 12, 0.00, 100, 0.00, 0 )
            call SetTextTagPermanentBJ( GetLastCreatedTextTag(), false )
            call SetTextTagLifespanBJ( GetLastCreatedTextTag(), 3.00 )
            call SetTextTagFadepointBJ( GetLastCreatedTextTag(), 1.50 )
            call SetTextTagVelocityBJ( GetLastCreatedTextTag(), 32.00, 90 )
        

        set Rejuv.CurrentTick = 0
        
    else
        //call BJDebugMsg("Debuffed")
        call Rejuv.destroy()
        call ReleaseTimer(T)
    
    endif

    if Rejuv.CurrentDuration >= R2I(Rejuv.Duration/INTERVAL) then
        //call DisplayTextToForce(GetPlayersAll(),"Done " +I2S(Rejuv))
        call UnitRemoveBuffBJ( 'B000', Rejuv.Target )
        call Rejuv.destroy()
        call ReleaseTimer(T)
    endif
    
endif
    
endfunction


//===============================================================
//Spell Cast Actions
//===============================================================
function Trig_Cast_Actions takes nothing returns nothing
local unit Caster = GetTriggerUnit()
local unit Target = GetSpellTargetUnit()
local timer T = NewTimer()
local Rejuvinate Rejuv

//Is Spell cast Rejuvinate====================================
if GetSpellAbilityId() == 'A001' then

//Check if the unit already has the buff==
if UnitHasBuffBJ(Target,'B000') == false then

    set Rejuv = Rejuvinate.create()
    set Rejuv.Caster = Caster
    set Rejuv.Target = Target
    
    call SetTimerData(T,Rejuv)
    
    //call DisplayTextToForce(GetPlayersAll(),"starting " +I2S(Rejuv))
    
    call TimerStart(T,INTERVAL,true,function Rejuvinate_Tick)
    set T = null
    
    
else
//If so then do nothing===================
    return
endif
endif
//===============================================ENDRejuvinate



endfunction

//===========================================================================
function InitTrig_Cast takes nothing returns nothing
    set gg_trg_Cast = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Cast, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddAction( gg_trg_Cast, function Trig_Cast_Actions )
endfunction

Here is a Heal over Time setup I made, I'm sure you can convert it to damage real easy :) It's not the best, but it works.
11-16-2008, 06:44 AM#3
zetanno
Good idea ,I'll use that to create a general DoT system. That INTERVAL is supposed to be a real like how often to heal ,right?
11-16-2008, 10:02 AM#4
TEC_Ghost
Collapse JASS:
globals
    constant real INTERVAL = .04 //Interval of the spell timer.
endglobals

struct Rejuvinate

integer Tick = 2                    //How many seconds do you want the unit to be healed.
integer CurrentTick = 0     
integer HealPerTick = 40            //Damage healed per tick.
integer CurrentDuration = 0 
integer Duration = 15               //Duration of the spell in seconds.
boolean AddHeroIntToHeal = true     //If you want to add the heroes Int to the HealPerTick set to true, false to turn off.

unit Target
unit Caster

endstruct

Interval is the timer delay, you define how often to heal with, integer Tick = 2
11-16-2008, 07:40 PM#5
zetanno
I've made a DoT system from what you told me but i have problems with detecting the buff . I'm using this < UnitHasBuffBJ (dat.u ,dat.Buff) > dat.u is the targeted unit and dat.Buff is the buff specified by the function .The problem is that it doesn't detect my buff or maybe dat.Buff is the problem ...
The function looks like this :
Collapse JASS:
struct data
unit caster
unit target
.....
integer Buff
....
endstruct

function DamageUnit takes nothing returns nothing
 local timer t = GetExpiredTimer()
 local data dat = GetTimerData(t)
............
if UnitHasBuffBJ (dat.u ,dat.Buff) == false or <if the target is dead>then
 call dat.destroy()
 call ReleaseTimer(t)
else 
 <something that damages the target>
endif
 set t = null
endfunction

function DamageOverTime takes unit caster ,unit target,real damage .... integer Buff ...returns nothing
local timer t = NewTimer()
local data dat
 .....
 set dat.Buff = Buff
.......
 call TimerStart(t,howoften,true,function DamageUnit)
 set t = null
endfunction
This would be the idea ... Tell me,what do you think about it and what is wrong with it?
11-17-2008, 02:46 AM#6
TEC_Ghost
You're not setting the timer data, with the struct instance, so it's reading a null buff. Ya need to do
Collapse JASS:
 call SetTimerData(t,dat) 
11-17-2008, 04:48 AM#7
zetanno
I was setting the data but I didn't write that . Still not working . I got to think of something else ...
11-18-2008, 01:44 AM#8
TEC_Ghost
Just copy your whole trigger and I'll see whats wrong with it.
11-18-2008, 05:47 AM#9
zetanno
Ok this is the code and it requires CSData and CSSafety :
Collapse JASS:
library DamageTargetOverTime uses CSSafety
private struct data
unit c
unit u
timer t
real dmg
boolean attack
boolean ranged
damagetype DamageType
attacktype AttackType
weapontype WeaponType
real runned
real duration
real howoften
integer Buff
string Effect
string where
string stack
effect e
static method create takes unit c, unit u, real dmg, boolean attack, boolean ranged, attacktype AttackType, damagetype DamageType, weapontype WeaponType, real duration, real howoften, string stack,integer Buff, string Effect, string where returns data
    local data dat = data.allocate()
    local data d = GetCSData(u)
    if stack!=null and stack==d.stack then
       call data.destroy(d)
    endif
    set dat.t = NewTimer()
    set dat.u = u
    set dat.c = c
    set dat.dmg = dmg
    set dat.attack=attack
    set dat.ranged=ranged
    set dat.AttackType=AttackType
    set dat.DamageType=DamageType
    set dat.WeaponType=WeaponType
    set dat.duration = duration
    set dat.howoften=howoften
    set dat.Buff=Buff
    set dat.Effect=Effect
    set dat.where=where
    set dat.stack=stack
    set dat.runned=0
    if (Effect!=null or Effect!="") and (where!=null or where!="") then
       set dat.e=AddSpecialEffectTarget(Effect,u,where)
    endif
    call SetCSData(dat.t,dat)
    call SetCSData(u,dat)
    return dat
endmethod
method onDestroy takes nothing returns nothing
call DestroyEffect(.e)
call ReleaseTimer(.t)
endmethod
endstruct
private function Child takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local data dat = GetCSData(t)
    set dat.runned=dat.runned+dat.howoften
    if dat.runned>=dat.duration or GetUnitState(dat.u,UNIT_STATE_LIFE)<=.405 or (dat.Buff!=0 and UnitHasBuffBJ(dat.u,dat.Buff)==false) then
       call data.destroy(dat)
    else
       call DestroyEffect(dat.e)
       set dat.e=AddSpecialEffectTarget(dat.Effect,dat.u,dat.where)
       call UnitDamageTarget(dat.c, dat.u, dat.dmg, dat.attack, dat.ranged, dat.AttackType, dat.DamageType, dat.WeaponType)
    endif
    set t = null
endfunction
function DamageOverBuff takes unit whichUnit, unit target, real amount, boolean attack, boolean ranged, attacktype AttackType, damagetype DamageType, weapontype WeaponType, real howoften,integer Buff,string stack, string Effect, string where returns nothing
call TimerStart(data.create(whichUnit, target,amount,attack,ranged, AttackType, DamageType,WeaponType, 9999999, howoften,stack, Buff,Effect, where).t, howoften, true, function Child)
endfunction
function DamageOverTime takes unit whichUnit, unit target, real amount, boolean attack, boolean ranged, attacktype AttackType, damagetype DamageType, weapontype WeaponType, real duration, real howoften,string stack, string Effect, string where returns nothing
call TimerStart(data.create(whichUnit, target,amount,attack,ranged, AttackType, DamageType,WeaponType, duration, howoften,stack,0, Effect, where).t, howoften, true, function Child)
endfunction
endlibrary
The DamageOverTime function deals damage to unit and doesn't require a buff or something so the DoT effect can't be removed ,you have to wait for the duration to finish . The DamageOverBuff should deal x damage over y seconds while unit has the specific buff . The problem is that the buff integer is not saved correctly .I checked with Bloodlust : I2S('Bblo') = 112483645 (or something like this ) and I2S(dat.Buff) = 2246 . Using a buff like 'BUfa' instead of dat.Buff makes it work but only for a buff ... I just can't find the problem. Thanks again !
11-18-2008, 06:36 AM#10
TEC_Ghost
The buff integer will be something like 'B000' or 'B001' go into your abilities module and press CTRL+D it'll have the buffcode. Try that out.
11-18-2008, 09:05 AM#11
zetanno
....... thats a buff's raw code and to convert to integer you use 'raw' ... Those numbers are displayed when converting an integer like 'B00T' into a string ...but that doesn't matter . the function looks like this<call DamageOverBuff (caster,target,50(damage),ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null(no weapon type),'B000'(this is a buff's code or id)....) > and with the struct dat.Buff should be 'B000' but this isn't an integer and thats why when converting a raw code into a string it displays those numbers .
Now ,the raw code converted into an integer is a number and the dat.Buff is 0. I think there is something wrong with this ...