• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

[vJASS] learning (v)Jass; trying to simplify code

Status
Not open for further replies.
Level 3
Joined
Jan 7, 2010
Messages
37
NVM; Problem solved.
//----------------------------------------------------------------------------------------------------------------------
I am currently learning Jass&vJass, therefore playing around with scripts.

I tried to get something working with a DOT system and took a look at Gorillabulls DOiT system, and created a DOiT effect that gets applied as an AoE
http://www.hiveworkshop.com/forums/spells-569/doit-v3-00-a-238343/

I played around and tried to minimize the code so I changed this part:
JASS:
        loop
            exitwhen instChecker == 0
            if doitSpellId[instChecker] == instanceID and target == doitTarget[instChecker] then // in any case the spell id and the unit must be the same
//now we check the instancekind and perform the nesessary operations
                if instancekind == 1 then
                    set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                    call onOnlyRefresh(doitSpellId[instChecker])
                    set sameUnit = true
                elseif instancekind == 2 then //stack new damage no refreshing
                    if doitMaxStackNumberPerInstance[instChecker ] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        set doitStackingDamage[instChecker] = doitStackingDamage[instChecker] + damg //stack damage
                        set doitDamage[instChecker] = doitStackingDamage[instChecker] / instance //reset the damage to the new
                        set doitStackCount[instChecker] = doitStackCount[instChecker] + 1
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then //infinite stacks :D !!!
                        set doitStackingDamage[instChecker] = doitStackingDamage[instChecker] + damg //stack damage
                        set doitDamage[instChecker] = doitStackingDamage[instChecker] / instance //reset the damage to the new
                    endif
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker ] then//we have reached the total number of stacks and now can only refresh
                    endif
                    call onOnlyStack(doitSpellId[instChecker])
                    set sameUnit = true
                elseif instancekind == 3 then //refresh and stack
                    if doitMaxStackNumberPerInstance[instChecker ] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        set doitStackingDamage[instChecker] = doitStackingDamage[instChecker] + damg //stack damage
                        set doitDamage[instChecker] = doitStackingDamage[instChecker] / instance //reset the damage to the new
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                        set doitStackCount[instChecker] = doitStackCount[instChecker] + 1
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then //infinite stacks :D !!!
                        set doitStackingDamage[instChecker] = doitStackingDamage[instChecker] + damg //stack damage
                        set doitDamage[instChecker] = doitStackingDamage[instChecker] / instance //reset the damage to the new
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                    endif
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker ] then//we have reached the total number of stacks and now can only refresh
                        call onMaxStackReached(doitSpellId[instChecker])
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                    endif
                    call onStackAndRefresh(doitSpellId[instChecker])
                    set sameUnit = true
                elseif instancekind == 4 then
                    if doitMaxStackNumberPerInstance[instChecker ] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        set doitDamage[instChecker] = (damg + doitRemainingDamage[instChecker]) / instance //stack damage
                        set doitStackCount[instChecker] = doitStackCount[instChecker] + 1
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then //infinite stacks :D !!!
                        set doitDamage[instChecker] = (damg + doitRemainingDamage[instChecker]) / instance //stack damage
                    endif
                    call onStackOld(doitSpellId[instChecker])
                    set sameUnit = true
                elseif instancekind == 5 then
                    if doitMaxStackNumberPerInstance[instChecker ] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        set doitDamage[instChecker] = (damg + doitRemainingDamage[instChecker]) / instance //stack damage
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                        set doitStackCount[instChecker] = doitStackCount[instChecker] + 1
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then //infinite stacks :D !!!
                        set doitDamage[instChecker] = (damg + doitRemainingDamage[instChecker]) / instance //stack damage
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                    endif
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker ] then//we have reached the total number of stacks and now can only refresh
                        call onMaxStackReached(doitSpellId[instChecker])
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again 0
                    endif

                    call onRefreshANDStackOld(doitSpellId[instChecker])
                    set sameUnit = true
                endif
            endif
            set instChecker = doitNext[instChecker]
        endloop
Into this:
JASS:
//====================================================================================
//	these are helper functions for the function "ApplyDoitEfffect" to keep the code small
//
//====================================================================================
private function setDoitStackCount takes integer i returns nothing
    set doitStackCount[i] = doitStackCount[i] + 1
endfunction

private function setDoitTci takes integer i returns nothing
    set doitTci[i] = 1 			//	reset the instance count for the desired instance
								//	to 0 so that it can keep damaging over time until it
								//	expires of its called again
endfunction

private function resetDoitDamage takes integer i, integer j returns nothing
    //	reset the damage to the new
    set doitDamage[i] = doitStackingDamage[i] / j 
endfunction

private function setDoitDamage takes integer i, integer j, real r returns nothing
    //	stack damage
    set doitDamage[i] = (r + doitRemainingDamage[i]) / j 
endfunction

private function setStackingDamage takes integer i, real r returns nothing
    //	stack damage
	set doitStackingDamage[i] = doitStackingDamage[i] + r 	
endfunction

private function helpApplyDoitEffect_1 takes integer i, integer j, real r returns nothing
	call setStackingDamage(i, r)
    call resetDoitDamage(i, j)
endfunction

private function helpApplyDoitEffect_2 takes integer i, integer j, real r returns nothing
	call setStackingDamage(i, r)
    call resetDoitDamage(i, j)
	call setDoitTci(i)
endfunction


//--------------------------------------------------------------------------------------------
// [More code here...]
//--------------------------------------------------------------------------------------------

        loop
            exitwhen instChecker == 0
//			************************************************************************************
            set sameUnit = true
//			************************************************************************************
//			in any case the spell id and the unit must be the same
//			************************************************************************************
            if doitSpellId[instChecker] == instanceID and target == doitTarget[instChecker] then 
//				************************************************************************************
//				now we check the instancekind
//				and perform the nesessary operations
//				************************************************************************************
                if instancekind == 1 then
//					reset the instance count for the desired instance to 0 so that it
//					can keep damaging over time until it expires of its called again
					call setDoitTci(instChecker) 
                    call onOnlyRefresh(doitSpellId[instChecker])
//				**************************************************************************************************
//				stack new damage no refreshing
//				**************************************************************************************************
                elseif instancekind == 2 then 
//					**************************************************************************************************
//					can not have infinite instances and have not reached the total stack count
//					**************************************************************************************************
                    if doitMaxStackNumberPerInstance[instChecker] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then 
						call helpApplyDoitEffect_1(instChecker, instance, damg)
                        call setDoitStackCount(instChecker)
//					**************************************************************************************************
//					infinite stacks
//					**************************************************************************************************
                    elseif doitMaxStackNumberPerInstance[id] == 0 then 
						call helpApplyDoitEffect_1(instChecker, instance, damg)
                    endif
//					**************************************************************************************************
//					we have reached the total number of stacks and now can only refresh
//					**************************************************************************************************
//					???????
//					**************************************************************************************************
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker] then
//					???????
                    endif
//					**************************************************************************************************
                    call onOnlyStack(doitSpellId[instChecker])
//				**************************************************************************************************
//				refresh and stack
//				**************************************************************************************************					
                elseif instancekind == 3 then
//					**************************************************************************************************
//					can not have infinite instances and have not reached the total stack count
//					**************************************************************************************************
                    if doitMaxStackNumberPerInstance[instChecker] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker] then 
                        call helpApplyDoitEffect_2(instChecker, instance, damg)
                        call setDoitStackCount(instChecker)
//					**************************************************************************************************
//					infinite stacks						
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then 								
						call helpApplyDoitEffect_2(instChecker, instance, damg)
                    endif
//					**************************************************************************************************
//					we have reached the total number of stacks and now can only refresh
//					**************************************************************************************************
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker] then
                        call onMaxStackReached(doitSpellId[instChecker])
						call setDoitTci(instChecker)
                    endif
//					**************************************************************************************************
                    call onStackAndRefresh(doitSpellId[instChecker])
//				**************************************************************************************************
                elseif instancekind == 4 then
//					**************************************************************************************************
                    if doitMaxStackNumberPerInstance[instChecker] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
						call setDoitDamage(instChecker, instance, damg)
                        call setDoitStackCount(instChecker)
//					**************************************************************************************************	
                    elseif doitMaxStackNumberPerInstance[id] == 0 then 	//infinite stacks
                        call setDoitDamage(instChecker, instance, damg)
                    endif
//					**************************************************************************************************
                    call onStackOld(doitSpellId[instChecker])
//				**************************************************************************************************
                elseif instancekind == 5 then
//					**************************************************************************************************
                    if doitMaxStackNumberPerInstance[instChecker] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        call setDoitDamage(instChecker, instance, damg)
                        call setDoitTci(instChecker)
						call setDoitStackCount(instChecker)
//					**************************************************************************************************
                    elseif doitMaxStackNumberPerInstance[id] == 0 then 	//infinite stacks
                        call setDoitDamage(instChecker, instance, damg)
						call setDoitTci(instChecker)
                    endif
//					**************************************************************************************************
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker] then//we have reached the total number of stacks and now can only refresh
                        call onMaxStackReached(doitSpellId[instChecker])
						call setDoitTci(instChecker)
                    endif
//					**************************************************************************************************
                    call onRefreshANDStackOld(doitSpellId[instChecker])
//				**************************************************************************************************
                else
                    set sameUnit = false
                endif
//			**************************************************************************************************
            endif
            set instChecker = doitNext[instChecker]
//		**************************************************************************************************
        endloop

Before the DOiT effect was working fine, but now the DOiT effect will only be applied to one target. I replaced the broken code with the working code, it worked. So this is the exact problem.
Can somebody explain to me, why this won't work?
Map as attachment below.

JASS:
library DamageOverIntervalTime initializer Init /* v 3.00 by Gorillabul
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * A damage / healing over time system capable of: dealing damage / healing over time, refreshing, stacking, stacking and refreshing, stacking the new damage
 * with any remainder of the damage from the previous instance, refreshing that damage, stacking and refreshing that damage.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 */ 
globals
    private unit array doitDamager //The Unit dealing the damage.
    private unit array doitTarget // The target Unit
    private real array doitDamage //Amount of damage PER INTERVAL
    private integer array doitCounting
    private integer array doitRecycler
    private integer array doitPrev
    private integer array doitNext
    private integer array doitIterations //Number of times to add 1 to doitCurrentIteration ( interval / 0.03125 )
    private integer array doitCurrentIteration //Counting variable
    private integer array totalCurrentDoitIterations //Total iterations for an instance, if u specify a duration of 15 second and interval of 3 this is 5 (duration / interval)
    private integer array doitTci //Used to generate a consecutive Damage over time instance.
    private timer doitTimer //Timer to loop through the instances and pause if unused.
    private attacktype array doitAttackTypeIndex // the attacktype that deals damage for each instance(hero fortified siege...)
    private integer array doitInstanceIndex //the attacktype index is set by the user when using ApplyDoitEffect and is set to integer aid
    private integer array doitSpellId // the id of the current damage over time instance, this is from the spell which causes this effect
    private real array doitRemainingDamage // the damage of the current doit instnance this needs to be reduced each tick
    private real array doitStackingDamage
    private integer array doitMaxStackNumberPerInstance // the maximum number of times a spell can stack. this is configured through the function call. should be > 2 so u have at least 2 stacks..
    private integer array doitStackCount //current stack count of an instance
     
    private string array doitSfxName    //the special effect (i.e. burning effect) on the target unit
    private string array doitAttachPoint //where sfx will be applied
    private effect array doitSFX
     
     
     /* 
    set doitAttackTypeIndex[0] = ATTACK_TYPE_CHAOS
    set doitAttackTypeIndex[1] = ATTACK_TYPE_MAGIC
    set doitAttackTypeIndex[2] = ATTACK_TYPE_NORMAL
    set doitAttackTypeIndex[3] = ATTACK_TYPE_PIERCE
    set doitAttackTypeIndex[4] = ATTACK_TYPE_SIEGE
     */ 
endglobals
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * HOW TO USE - 
 * 
 * function ApplyDoitEffect takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind , integer maxNumOfStacks returns nothing
 * 
 * - this function will register a unit to be damaged or healed over time, the names are self explanatory duration is how long
 * you want your target to be damaged for and interval is the timeout between dealing damage.
 * For example a unit takes damage every 3 seconds for 15 seconds would define an interval of 3 and a duration of 15.
 * The aid integer corresponds to doitInstanceIndex and determines the attacktype used per instance, look at how doitAttackTypeIndex
 * is set.
 * Instance types are as follows:
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * 0 - dont refresh, dont stack only create new instance
 * 1 - refresh dont stack .. refresh checks if the current instance is the same as any of the instances on the list and thus refreshes that instance if instnacetype is 1
 * 2 - stack (new damage + total old damage) stacks the current damage to previous original + current , this is very powerful and should probly only be used without refresh
 * 3 - refresh AND stack (new damage + total old damage) refreshes the dot to its orignal duration and stacks the damage very very very powerful
 * 4 - stack (new damage + remainder of old damage ) far more harmless i suppose if u have 500 damage left from an original 3000 damage this is not much of a boost
 * 5 - refresh AND stack (new damage + remainder of old damage ) a bit more volatile but still not as fatal
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * 
 * 
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * HOW TO IMPORT
 * 
 * Copy this trigger into your map, then call ApplyDoitEffect(caster, target, amount , duration , interval, attacktypeindex, instanceID, instancetype ...... ) set amount to a negative value
 * for healing over time, and take a look at the example.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 





//====================================================================================
//====================================================================================
//	this function takes a spell id and if this id is on the list of spell ids which
//	have created a damage/healing over time instance it retrieves the current instance
//	of that spellID
//====================================================================================
private function doitGetSpellInstanceID takes integer spellID returns integer
    local integer l = doitNext[0]

    if doitNext[0] == 0 then
        return 0 								// there are no current isntances
    elseif doitNext[0] > 0 then
        loop
            exitwhen l == 0
            if doitSpellId[l] == spellID then 	// there is an instance
                return l
            endif
            set l = doitNext[l]
        endloop
    endif
    return 0
endfunction

//====================================================================================
//====================================================================================
//	these functions right here are called whenever any of the actions they are
//	associated with are executed, you can do aditional modifications here such as:
//	modifying the damage/healing.
//************************************************************************************
// 	by some other factor like a percentage since these funcions give you the current
//	instance of the dot/hot to work with you can essentially modify all the private
//	globals here...
// 		example:
//			if spellID[instance] == 'abcd' then
// 				set doitDamage[instance] = 50k
//			endif
//************************************************************************************
// 	you can call these functions with any kind of ids however since the dot/how
//	instances change value you might need to call the function doitGetSpellInstanceID
//	if you want to retrieve the instance of a certain spell that has been cast.
//====================================================================================
private function onOnlyRefresh takes integer spellID returns nothing
    call BJDebugMsg("instance# " + I2S(doitGetSpellInstanceID(spellID)) + " has been refreshed" )
endfunction

private function onOnlyStack takes integer spellID returns nothing
    call BJDebugMsg("the damage for instance# " + I2S(doitGetSpellInstanceID(spellID)) + " has been stacked")
endfunction
private function onStackAndRefresh takes integer spellID returns nothing
    call BJDebugMsg("the damage for instance # " + I2S(doitGetSpellInstanceID(spellID)) + " has been refreshed AND stacked" )
endfunction

private function onStackOld takes integer spellID returns nothing
    call BJDebugMsg("the damage for instance # " + I2S(doitGetSpellInstanceID(spellID)) + " has been stacked with any remaining damage to deal" )
endfunction

private function onRefreshANDStackOld takes integer spellID returns nothing
	//	something... something...
endfunction

private function onRefreshOld takes integer spellID returns nothing
	//	something... something...
endfunction

private function onMaxStackReached takes integer spellID returns nothing
    call BJDebugMsg("max stack has been reached for instance # " + I2S(doitGetSpellInstanceID(spellID)) + "from now this will only be refreshed.")
endfunction

//====================================================================================
//====================================================================================
//	this function is called when an instance runs out
//====================================================================================
private function KillDoit takes integer i returns nothing
        //new
        call DestroyEffect(doitSFX[i])
        set doitAttachPoint[i] = ""
        set doitSfxName[i] = ""
        call UnitRemoveAbility(doitTarget[i],'B001')
        //
        set doitNext[doitPrev[i]] = doitNext[i]
        set doitPrev[doitNext[i]] = doitPrev[i]
        set doitRecycler[i] = doitRecycler[0]
        set doitRecycler[0] = i
        set totalCurrentDoitIterations[i] = 0
        set doitIterations[i] = 0
        set doitTci[i] = 0
endfunction

//====================================================================================
//	this Loop handles all
//
//====================================================================================
private function DoitLoop takes nothing returns nothing
    local integer l = doitNext[0]

    if l == 0 then
        call PauseTimer(doitTimer)
    endif
    loop
        exitwhen l == 0
        set doitCurrentIteration[l] = doitCurrentIteration[l] + 1
        if doitCurrentIteration[l] == doitIterations[l] then
            set doitCurrentIteration[l] = 0
            set doitTci[l] = doitTci[l] + 1 // one instance has occured
            if not IsUnitType(doitTarget[l], UNIT_TYPE_DEAD) then
                if doitDamage[l] > 0 then
                    call UnitDamageTarget( doitDamager[l] , doitTarget[l], doitDamage[l] , true, false, doitAttackTypeIndex[doitInstanceIndex[l]], DAMAGE_TYPE_UNIVERSAL, null)
                    set doitRemainingDamage[l] = doitRemainingDamage[l] - doitDamage[l] //since we have dealt damage the total damage needed to be dealt is decreased.
                else
                    call SetWidgetLife(doitTarget[l], GetWidgetLife(doitTarget[l]) + (doitDamage[l] * - 1 ))
                endif
            else // if the unit is dead destroy everything
				call KillDoit(l)
            endif
        endif
        if doitTci[l] == totalCurrentDoitIterations[l] and IsUnitType(doitTarget[l], UNIT_TYPE_DEAD) == false then
            call KillDoit(l)
        endif
        set l = doitNext[l]
    endloop
endfunction

//====================================================================================
//====================================================================================
//	this function creates an instance...
//
//====================================================================================
private function doitDefault takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind, integer maxNumOfStacks returns nothing
//private function doitDefault takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind, integer maxNumOfStacks, string sfx, string attachpoint returns nothing
    local integer instance 		= R2I(duration / interval )
    local integer id 			= doitRecycler[0]
    local integer instChecker 	= 0
    // new; sfx
    //local real tempx = GetLocationX(GetUnitLoc(target))
    //local real tempy = GetLocationY(GetUnitLoc(target))
    //local unit u    //  temp unit applies visual debuff
    //local effect s
    
    set instChecker 			= doitNext[0]

    call TimerStart(doitTimer, 0.031250000, true , function DoitLoop )
    if id == 0 then
        set doitCounting[0] = doitCounting[0] + 1
        set id = doitCounting[0]
    else
        set doitRecycler[0] = doitRecycler[id]
    endif
	
    set doitNext[id] 						= 0
    set doitPrev[id] 						= doitPrev[0]
    set doitNext[doitPrev[0]]				= id
    set doitPrev[0] 						= id
    set doitDamager[id] 					= damager
    set doitTarget[id] 						= target
    set doitIterations[id] 					= R2I(interval / 0.031250000)
    set totalCurrentDoitIterations[id] 		= R2I(instance)
    set doitDamage[id] 						= damg / instance
    set doitInstanceIndex[id] 				= attacktypeindex
    set doitSpellId[id] 					= instanceID
    set doitStackingDamage[id] 				= damg // set this to damage so we can stack it later.
    set doitRemainingDamage[id] 			= damg //initially is equal to the full damage.
    set doitMaxStackNumberPerInstance[id] 	= maxNumOfStacks // this will be set to + 1 on each stack
    set doitStackCount[id] 					= 0
    
    //set doitSfx[id]                         = sfx
    //set doitAttachPoint[id]                 = attachpoint
    
    //if not IsUnitType(target, UNIT_TYPE_DEAD)   then
     // set s = AddSpecialEffectTarget(sfx, target, attachpoint)
    //  set u = CreateUnitAtLoc(GetOwningPlayer(damager), 'e000', Location(tempx, tempy), 0.0)   // 'e000' = dummy unit
   //   call UnitAddAbility(u, 'A003')                                                                   // 'A003' debuff ability
    //  call IssueTargetOrder(u, "innerfire", target)                                            //apply debuff (visual only)
   //   call UnitApplyTimedLife(u,'BTLF',1.0)
   //   set u = null
   //endif
endfunction




//====================================================================================
//====================================================================================
//	these are helper functions for the function "ApplyDoitEfffect" to keep the code small
//
//====================================================================================
private function setDoitStackCount takes integer i returns nothing
    set doitStackCount[i] = doitStackCount[i] + 1
endfunction

private function setDoitTci takes integer i returns nothing
    set doitTci[i] = 1 			//	reset the instance count for the desired instance
								//	to 0 so that it can keep damaging over time until it
								//	expires of its called again
endfunction

private function resetDoitDamage takes integer i, integer j returns nothing
    //	reset the damage to the new
    set doitDamage[i] = doitStackingDamage[i] / j 
endfunction

private function setDoitDamage takes integer i, integer j, real r returns nothing
    //	stack damage
    set doitDamage[i] = (r + doitRemainingDamage[i]) / j 
endfunction

private function setStackingDamage takes integer i, real r returns nothing
    //	stack damage
	set doitStackingDamage[i] = doitStackingDamage[i] + r 	
endfunction

private function helpApplyDoitEffect_1 takes integer i, integer j, real r returns nothing
	call setStackingDamage(i, r)
    call resetDoitDamage(i, j)
endfunction

private function helpApplyDoitEffect_2 takes integer i, integer j, real r returns nothing
	call setStackingDamage(i, r)
    call resetDoitDamage(i, j)
	call setDoitTci(i)
endfunction

//************************************************************************************
//************************************************************************************

//************************************************************************************
//************************************************************************************

//************************************************************************************
//************************************************************************************

//====================================================================================
//====================================================================================
//	handles the dot effect
//====================================================================================
function ApplyDoitEffect    takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind , integer maxNumOfStacks returns nothing
//function ApplyDoitEffect    takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind , integer maxNumOfStacks, string sfx, string attachpoint returns nothing
    local integer instance 		= R2I(duration / interval )
    local integer id 			= doitRecycler[0]
    local integer instChecker 	= 0
    local boolean sameUnit 		= false
	
    set instChecker = doitNext[0]

//	************************************
//	if there are *no* instances running
//	we need to create one
//	************************************
//	if there are no instances
    if doitNext[0] == 0 then 								
//		we need to create one  	
        call doitDefault(damager, target, damg, duration, interval, attacktypeindex, instanceID, instancekind , maxNumOfStacks )
        //call doitDefault(damager, target, damg, duration, interval, attacktypeindex, instanceID, instancekind , maxNumOfStacks, sfx, attachpoint )	
//	************************************	
//	if there *are* instances running
//	************************************
	elseif doitNext[0] > 0 then		
        set instChecker = doitNext[0]
        loop
            exitwhen instChecker == 0
            if doitSpellId[instChecker] == instanceID and target == doitTarget[instChecker] then // in any case the spell id and the unit must be the same
//now we check the instancekind and perform the nesessary operations
                if instancekind == 1 then
                    set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                    call onOnlyRefresh(doitSpellId[instChecker])
                    set sameUnit = true
                elseif instancekind == 2 then //stack new damage no refreshing
                    if doitMaxStackNumberPerInstance[instChecker ] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        set doitStackingDamage[instChecker] = doitStackingDamage[instChecker] + damg //stack damage
                        set doitDamage[instChecker] = doitStackingDamage[instChecker] / instance //reset the damage to the new
                        set doitStackCount[instChecker] = doitStackCount[instChecker] + 1
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then //infinite stacks :D !!!
                        set doitStackingDamage[instChecker] = doitStackingDamage[instChecker] + damg //stack damage
                        set doitDamage[instChecker] = doitStackingDamage[instChecker] / instance //reset the damage to the new
                    endif
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker ] then//we have reached the total number of stacks and now can only refresh
                    endif
                    call onOnlyStack(doitSpellId[instChecker])
                    set sameUnit = true
                elseif instancekind == 3 then //refresh and stack
                    if doitMaxStackNumberPerInstance[instChecker ] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        set doitStackingDamage[instChecker] = doitStackingDamage[instChecker] + damg //stack damage
                        set doitDamage[instChecker] = doitStackingDamage[instChecker] / instance //reset the damage to the new
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                        set doitStackCount[instChecker] = doitStackCount[instChecker] + 1
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then //infinite stacks :D !!!
                        set doitStackingDamage[instChecker] = doitStackingDamage[instChecker] + damg //stack damage
                        set doitDamage[instChecker] = doitStackingDamage[instChecker] / instance //reset the damage to the new
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                    endif
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker ] then//we have reached the total number of stacks and now can only refresh
                        call onMaxStackReached(doitSpellId[instChecker])
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                    endif
                    call onStackAndRefresh(doitSpellId[instChecker])
                    set sameUnit = true
                elseif instancekind == 4 then
                    if doitMaxStackNumberPerInstance[instChecker ] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        set doitDamage[instChecker] = (damg + doitRemainingDamage[instChecker]) / instance //stack damage
                        set doitStackCount[instChecker] = doitStackCount[instChecker] + 1
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then //infinite stacks :D !!!
                        set doitDamage[instChecker] = (damg + doitRemainingDamage[instChecker]) / instance //stack damage
                    endif
                    call onStackOld(doitSpellId[instChecker])
                    set sameUnit = true
                elseif instancekind == 5 then
                    if doitMaxStackNumberPerInstance[instChecker ] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        set doitDamage[instChecker] = (damg + doitRemainingDamage[instChecker]) / instance //stack damage
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                        set doitStackCount[instChecker] = doitStackCount[instChecker] + 1
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then //infinite stacks :D !!!
                        set doitDamage[instChecker] = (damg + doitRemainingDamage[instChecker]) / instance //stack damage
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again
                    endif
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker ] then//we have reached the total number of stacks and now can only refresh
                        call onMaxStackReached(doitSpellId[instChecker])
                        set doitTci[instChecker] = 1 //reset the instance count for the desired instance to 0 so that it can keep damaging over time until it expires of its called again 0
                    endif

                    call onRefreshANDStackOld(doitSpellId[instChecker])
                    set sameUnit = true
                endif
            endif
            set instChecker = doitNext[instChecker]
        endloop
//		**************************************************************************************************
// 		we have cast our dot spell on a different unit and must now add it to the system.
        if not sameUnit then
            if id == 0 then
                set doitCounting[0] = doitCounting[0] + 1
                set id = doitCounting[0]
            else
                set doitRecycler[0] = doitRecycler[id]
            endif
            call doitDefault(damager, target, damg, duration, interval, attacktypeindex, instanceID, instancekind, maxNumOfStacks )
        endif
//	**************************************************************************************************
    endif
    if instancekind == 0 then
        call doitDefault(damager, target, damg, duration, interval, attacktypeindex, instanceID, instancekind, maxNumOfStacks )
    endif
 
 
 
//  new
   // if not sameUnit then    //  only applies the visual debuff if there is none yet; aka shall not stack visual debuffs; aka one visual debuff is enough
    //    if not IsUnitType(target, UNIT_TYPE_DEAD)   then
    //       set sfx = AddSpecialEffectTarget(doitSfxName[id], doitTarget[id], doitAttachPoint[id])
    //        set tempunit = CreateUnitAtLoc(GetOwningPlayer(doitDamager[id]), 'e000', Location(tempx, tempy), 0.0)   // 'e000' = dummy unit
     //       call UnitAddAbility(tempunit, 'A003')                                                                   // 'A003' debuff ability
    //        call IssueTargetOrder(tempunit, "innerfire", doitTarget[id])                                            //apply debuff (visual only)
    //        call UnitApplyTimedLife(tempunit,'BTLF',1.0)
   //         set tempunit = null
   //     endif
//    endif
endfunction

//====================================================================================
//	Init and shit
//====================================================================================
private function Init takes nothing returns nothing
    local integer l = 0
    local trigger t = CreateTrigger( )
    set doitRecycler[0] = 0

    loop
        exitwhen l > 15
        set doitCounting [l] = 0
        set l = l + 1
    endloop
    set doitAttackTypeIndex[0] = ATTACK_TYPE_CHAOS
    set doitAttackTypeIndex[1] = ATTACK_TYPE_MAGIC
    set doitAttackTypeIndex[2] = ATTACK_TYPE_NORMAL
    set doitAttackTypeIndex[3] = ATTACK_TYPE_PIERCE
    set doitAttackTypeIndex[4] = ATTACK_TYPE_SIEGE
    set doitCounting[0] = 0
    set doitTimer = CreateTimer()
endfunction

endlibrary

JASS:
library DamageOverIntervalTimeDWP initializer Init /* v 3.00 by Gorillabul
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * A damage / healing over time system capable of: dealing damage / healing over time, refreshing, stacking, stacking and refreshing, stacking the new damage
 * with any remainder of the damage from the previous instance, refreshing that damage, stacking and refreshing that damage.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 */ 
globals
    private unit array doitDamager //The Unit dealing the damage.
    private unit array doitTarget // The target Unit
    private real array doitDamage //Amount of damage PER INTERVAL
    private integer array doitCounting
    private integer array doitRecycler
    private integer array doitPrev
    private integer array doitNext
    private integer array doitIterations //Number of times to add 1 to doitCurrentIteration ( interval / 0.03125 )
    private integer array doitCurrentIteration //Counting variable
    private integer array totalCurrentDoitIterations //Total iterations for an instance, if u specify a duration of 15 second and interval of 3 this is 5 (duration / interval)
    private integer array doitTci //Used to generate a consecutive Damage over time instance.
    private timer doitTimer //Timer to loop through the instances and pause if unused.
    private attacktype array doitAttackTypeIndex // the attacktype that deals damage for each instance(hero fortified siege...)
    private integer array doitInstanceIndex //the attacktype index is set by the user when using ApplyDoitEffect and is set to integer aid
    private integer array doitSpellId // the id of the current damage over time instance, this is from the spell which causes this effect
    private real array doitRemainingDamage // the damage of the current doit instnance this needs to be reduced each tick
    private real array doitStackingDamage
    private integer array doitMaxStackNumberPerInstance // the maximum number of times a spell can stack. this is configured through the function call. should be > 2 so u have at least 2 stacks..
    private integer array doitStackCount //current stack count of an instance
     
    private string array doitSfxName    //the special effect (i.e. burning effect) on the target unit
    private string array doitAttachPoint //where sfx will be applied
    private effect array doitSFX
     
     
     /* 
    set doitAttackTypeIndex[0] = ATTACK_TYPE_CHAOS
    set doitAttackTypeIndex[1] = ATTACK_TYPE_MAGIC
    set doitAttackTypeIndex[2] = ATTACK_TYPE_NORMAL
    set doitAttackTypeIndex[3] = ATTACK_TYPE_PIERCE
    set doitAttackTypeIndex[4] = ATTACK_TYPE_SIEGE
     */ 
endglobals
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * HOW TO USE - 
 * 
 * function ApplyDoitEffect takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind , integer maxNumOfStacks returns nothing
 * 
 * - this function will register a unit to be damaged or healed over time, the names are self explanatory duration is how long
 * you want your target to be damaged for and interval is the timeout between dealing damage.
 * For example a unit takes damage every 3 seconds for 15 seconds would define an interval of 3 and a duration of 15.
 * The aid integer corresponds to doitInstanceIndex and determines the attacktype used per instance, look at how doitAttackTypeIndex
 * is set.
 * Instance types are as follows:
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * 0 - dont refresh, dont stack only create new instance
 * 1 - refresh dont stack .. refresh checks if the current instance is the same as any of the instances on the list and thus refreshes that instance if instnacetype is 1
 * 2 - stack (new damage + total old damage) stacks the current damage to previous original + current , this is very powerful and should probly only be used without refresh
 * 3 - refresh AND stack (new damage + total old damage) refreshes the dot to its orignal duration and stacks the damage very very very powerful
 * 4 - stack (new damage + remainder of old damage ) far more harmless i suppose if u have 500 damage left from an original 3000 damage this is not much of a boost
 * 5 - refresh AND stack (new damage + remainder of old damage ) a bit more volatile but still not as fatal
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * 
 * 
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 * HOW TO IMPORT
 * 
 * Copy this trigger into your map, then call ApplyDoitEffect(caster, target, amount , duration , interval, attacktypeindex, instanceID, instancetype ...... ) set amount to a negative value
 * for healing over time, and take a look at the example.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 





//====================================================================================
//====================================================================================
//	this function takes a spell id and if this id is on the list of spell ids which
//	have created a damage/healing over time instance it retrieves the current instance
//	of that spellID
//====================================================================================
private function doitGetSpellInstanceID takes integer spellID returns integer
    local integer l = doitNext[0]

    if doitNext[0] == 0 then
        return 0 								// there are no current isntances
    elseif doitNext[0] > 0 then
        loop
            exitwhen l == 0
            if doitSpellId[l] == spellID then 	// there is an instance
                return l
            endif
            set l = doitNext[l]
        endloop
    endif
    return 0
endfunction

//====================================================================================
//====================================================================================
//	these functions right here are called whenever any of the actions they are
//	associated with are executed, you can do aditional modifications here such as:
//	modifying the damage/healing.
//************************************************************************************
// 	by some other factor like a percentage since these funcions give you the current
//	instance of the dot/hot to work with you can essentially modify all the private
//	globals here...
// 		example:
//			if spellID[instance] == 'abcd' then
// 				set doitDamage[instance] = 50k
//			endif
//************************************************************************************
// 	you can call these functions with any kind of ids however since the dot/how
//	instances change value you might need to call the function doitGetSpellInstanceID
//	if you want to retrieve the instance of a certain spell that has been cast.
//====================================================================================
private function onOnlyRefresh takes integer spellID returns nothing
    call BJDebugMsg("instance# " + I2S(doitGetSpellInstanceID(spellID)) + " has been refreshed" )
endfunction

private function onOnlyStack takes integer spellID returns nothing
    call BJDebugMsg("the damage for instance# " + I2S(doitGetSpellInstanceID(spellID)) + " has been stacked")
endfunction
private function onStackAndRefresh takes integer spellID returns nothing
    call BJDebugMsg("the damage for instance # " + I2S(doitGetSpellInstanceID(spellID)) + " has been refreshed AND stacked" )
endfunction

private function onStackOld takes integer spellID returns nothing
    call BJDebugMsg("the damage for instance # " + I2S(doitGetSpellInstanceID(spellID)) + " has been stacked with any remaining damage to deal" )
endfunction

private function onRefreshANDStackOld takes integer spellID returns nothing
	//	something... something...
endfunction

private function onRefreshOld takes integer spellID returns nothing
	//	something... something...
endfunction

private function onMaxStackReached takes integer spellID returns nothing
    call BJDebugMsg("max stack has been reached for instance # " + I2S(doitGetSpellInstanceID(spellID)) + "from now this will only be refreshed.")
endfunction

//====================================================================================
//====================================================================================
//	this function is called when an instance runs out
//====================================================================================
private function KillDoit takes integer i returns nothing
        //new
        call DestroyEffect(doitSFX[i])
        set doitAttachPoint[i] = ""
        set doitSfxName[i] = ""
        call UnitRemoveAbility(doitTarget[i],'B001')
        //
        set doitNext[doitPrev[i]] = doitNext[i]
        set doitPrev[doitNext[i]] = doitPrev[i]
        set doitRecycler[i] = doitRecycler[0]
        set doitRecycler[0] = i
        set totalCurrentDoitIterations[i] = 0
        set doitIterations[i] = 0
        set doitTci[i] = 0
endfunction

//====================================================================================
//	this Loop handles all
//
//====================================================================================
private function DoitLoop takes nothing returns nothing
    local integer l = doitNext[0]

    if l == 0 then
        call PauseTimer(doitTimer)
    endif
    loop
        exitwhen l == 0
        set doitCurrentIteration[l] = doitCurrentIteration[l] + 1
        if doitCurrentIteration[l] == doitIterations[l] then
            set doitCurrentIteration[l] = 0
            set doitTci[l] = doitTci[l] + 1 // one instance has occured
            if not IsUnitType(doitTarget[l], UNIT_TYPE_DEAD) then
                if doitDamage[l] > 0 then
                    call UnitDamageTarget( doitDamager[l] , doitTarget[l], doitDamage[l] , true, false, doitAttackTypeIndex[doitInstanceIndex[l]], DAMAGE_TYPE_UNIVERSAL, null)
                    set doitRemainingDamage[l] = doitRemainingDamage[l] - doitDamage[l] //since we have dealt damage the total damage needed to be dealt is decreased.
                else
                    call SetWidgetLife(doitTarget[l], GetWidgetLife(doitTarget[l]) + (doitDamage[l] * - 1 ))
                endif
            else // if the unit is dead destroy everything
				call KillDoit(l)
            endif
        endif
        if doitTci[l] == totalCurrentDoitIterations[l] and IsUnitType(doitTarget[l], UNIT_TYPE_DEAD) == false then
            call KillDoit(l)
        endif
        set l = doitNext[l]
    endloop
endfunction

//====================================================================================
//====================================================================================
//	this function creates an instance...
//
//====================================================================================
private function doitDefault takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind, integer maxNumOfStacks returns nothing
//private function doitDefault takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind, integer maxNumOfStacks, string sfx, string attachpoint returns nothing
    local integer instance 		= R2I(duration / interval )
    local integer id 			= doitRecycler[0]
    local integer instChecker 	= 0
    // new; sfx
    //local real tempx = GetLocationX(GetUnitLoc(target))
    //local real tempy = GetLocationY(GetUnitLoc(target))
    //local unit u    //  temp unit applies visual debuff
    //local effect s
    
    set instChecker 			= doitNext[0]

    call TimerStart(doitTimer, 0.031250000, true , function DoitLoop )
    if id == 0 then
        set doitCounting[0] = doitCounting[0] + 1
        set id = doitCounting[0]
    else
        set doitRecycler[0] = doitRecycler[id]
    endif
	
    set doitNext[id] 						= 0
    set doitPrev[id] 						= doitPrev[0]
    set doitNext[doitPrev[0]]				= id
    set doitPrev[0] 						= id
    set doitDamager[id] 					= damager
    set doitTarget[id] 						= target
    set doitIterations[id] 					= R2I(interval / 0.031250000)
    set totalCurrentDoitIterations[id] 		= R2I(instance)
    set doitDamage[id] 						= damg / instance
    set doitInstanceIndex[id] 				= attacktypeindex
    set doitSpellId[id] 					= instanceID
    set doitStackingDamage[id] 				= damg // set this to damage so we can stack it later.
    set doitRemainingDamage[id] 			= damg //initially is equal to the full damage.
    set doitMaxStackNumberPerInstance[id] 	= maxNumOfStacks // this will be set to + 1 on each stack
    set doitStackCount[id] 					= 0
    
    //set doitSfx[id]                         = sfx
    //set doitAttachPoint[id]                 = attachpoint
    
    //if not IsUnitType(target, UNIT_TYPE_DEAD)   then
     // set s = AddSpecialEffectTarget(sfx, target, attachpoint)
    //  set u = CreateUnitAtLoc(GetOwningPlayer(damager), 'e000', Location(tempx, tempy), 0.0)   // 'e000' = dummy unit
   //   call UnitAddAbility(u, 'A003')                                                                   // 'A003' debuff ability
    //  call IssueTargetOrder(u, "innerfire", target)                                            //apply debuff (visual only)
   //   call UnitApplyTimedLife(u,'BTLF',1.0)
   //   set u = null
   //endif
endfunction




//====================================================================================
//====================================================================================
//	these are helper functions for the function "ApplyDoitEfffect" to keep the code small
//
//====================================================================================
private function setDoitStackCount takes integer i returns nothing
    set doitStackCount[i] = doitStackCount[i] + 1
endfunction

private function setDoitTci takes integer i returns nothing
    set doitTci[i] = 1 			//	reset the instance count for the desired instance
								//	to 0 so that it can keep damaging over time until it
								//	expires of its called again
endfunction

private function resetDoitDamage takes integer i, integer j returns nothing
    //	reset the damage to the new
    set doitDamage[i] = doitStackingDamage[i] / j 
endfunction

private function setDoitDamage takes integer i, integer j, real r returns nothing
    //	stack damage
    set doitDamage[i] = (r + doitRemainingDamage[i]) / j 
endfunction

private function setStackingDamage takes integer i, real r returns nothing
    //	stack damage
	set doitStackingDamage[i] = doitStackingDamage[i] + r 	
endfunction

private function helpApplyDoitEffect_1 takes integer i, integer j, real r returns nothing
	call setStackingDamage(i, r)
    call resetDoitDamage(i, j)
endfunction

private function helpApplyDoitEffect_2 takes integer i, integer j, real r returns nothing
	call setStackingDamage(i, r)
    call resetDoitDamage(i, j)
	call setDoitTci(i)
endfunction

//====================================================================================
//====================================================================================
//	handles the dot effect
//====================================================================================
function ApplyDoitEffectDWP    takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind , integer maxNumOfStacks returns nothing
//function ApplyDoitEffect    takes unit damager , unit target , real damg , real duration , real interval, integer attacktypeindex , integer instanceID , integer instancekind , integer maxNumOfStacks, string sfx, string attachpoint returns nothing
    local integer instance 		= R2I(duration / interval )
    local integer id 			= doitRecycler[0]
    local integer instChecker 	= 0
    local boolean sameUnit 		= false
	
    set instChecker = doitNext[0]

//	************************************
//	if there are *no* instances running
//	we need to create one
//	************************************
//	if there are no instances
    if doitNext[0] == 0 then 								
//		we need to create one  	
        call doitDefault(damager, target, damg, duration, interval, attacktypeindex, instanceID, instancekind , maxNumOfStacks )
        //call doitDefault(damager, target, damg, duration, interval, attacktypeindex, instanceID, instancekind , maxNumOfStacks, sfx, attachpoint )	
//	************************************	
//	if there *are* instances running
//	************************************
	elseif doitNext[0] > 0 then		
        set instChecker = doitNext[0]
        loop
            exitwhen instChecker == 0
//			************************************************************************************
            set sameUnit = true
//			************************************************************************************
//			in any case the spell id and the unit must be the same
//			************************************************************************************
            if doitSpellId[instChecker] == instanceID and target == doitTarget[instChecker] then 
//				************************************************************************************
//				now we check the instancekind
//				and perform the nesessary operations
//				************************************************************************************
                if instancekind == 1 then
//					reset the instance count for the desired instance to 0 so that it
//					can keep damaging over time until it expires of its called again
					call setDoitTci(instChecker) 
                    call onOnlyRefresh(doitSpellId[instChecker])
//				**************************************************************************************************
//				stack new damage no refreshing
//				**************************************************************************************************
                elseif instancekind == 2 then 
//					**************************************************************************************************
//					can not have infinite instances and have not reached the total stack count
//					**************************************************************************************************
                    if doitMaxStackNumberPerInstance[instChecker] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then 
						call helpApplyDoitEffect_1(instChecker, instance, damg)
                        call setDoitStackCount(instChecker)
//					**************************************************************************************************
//					infinite stacks
//					**************************************************************************************************
                    elseif doitMaxStackNumberPerInstance[id] == 0 then 
						call helpApplyDoitEffect_1(instChecker, instance, damg)
                    endif
//					**************************************************************************************************
//					we have reached the total number of stacks and now can only refresh
//					**************************************************************************************************
//					???????
//					**************************************************************************************************
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker] then
//					???????
                    endif
//					**************************************************************************************************
                    call onOnlyStack(doitSpellId[instChecker])
//				**************************************************************************************************
//				refresh and stack
//				**************************************************************************************************					
                elseif instancekind == 3 then
//					**************************************************************************************************
//					can not have infinite instances and have not reached the total stack count
//					**************************************************************************************************
                    if doitMaxStackNumberPerInstance[instChecker] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker] then 
                        call helpApplyDoitEffect_2(instChecker, instance, damg)
                        call setDoitStackCount(instChecker)
//					**************************************************************************************************
//					infinite stacks						
                    elseif doitMaxStackNumberPerInstance[id ] == 0 then 								
						call helpApplyDoitEffect_2(instChecker, instance, damg)
                    endif
//					**************************************************************************************************
//					we have reached the total number of stacks and now can only refresh
//					**************************************************************************************************
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker] then
                        call onMaxStackReached(doitSpellId[instChecker])
						call setDoitTci(instChecker)
                    endif
//					**************************************************************************************************
                    call onStackAndRefresh(doitSpellId[instChecker])
//				**************************************************************************************************
                elseif instancekind == 4 then
//					**************************************************************************************************
                    if doitMaxStackNumberPerInstance[instChecker] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
						call setDoitDamage(instChecker, instance, damg)
                        call setDoitStackCount(instChecker)
//					**************************************************************************************************	
                    elseif doitMaxStackNumberPerInstance[id] == 0 then 	//infinite stacks
                        call setDoitDamage(instChecker, instance, damg)
                    endif
//					**************************************************************************************************
                    call onStackOld(doitSpellId[instChecker])
//				**************************************************************************************************
                elseif instancekind == 5 then
//					**************************************************************************************************
                    if doitMaxStackNumberPerInstance[instChecker] != 0 and doitStackCount[instChecker] != doitMaxStackNumberPerInstance[instChecker ] then //can not have infinite instances and have not reached the total stack count
                        call setDoitDamage(instChecker, instance, damg)
                        call setDoitTci(instChecker)
						call setDoitStackCount(instChecker)
//					**************************************************************************************************
                    elseif doitMaxStackNumberPerInstance[id] == 0 then 	//infinite stacks
                        call setDoitDamage(instChecker, instance, damg)
						call setDoitTci(instChecker)
                    endif
//					**************************************************************************************************
                    if doitStackCount[instChecker] == doitMaxStackNumberPerInstance[instChecker] then//we have reached the total number of stacks and now can only refresh
                        call onMaxStackReached(doitSpellId[instChecker])
						call setDoitTci(instChecker)
                    endif
//					**************************************************************************************************
                    call onRefreshANDStackOld(doitSpellId[instChecker])
//				**************************************************************************************************
                else
                    set sameUnit = false
                endif
//			**************************************************************************************************
            endif
            set instChecker = doitNext[instChecker]
//		**************************************************************************************************
        endloop
//		**************************************************************************************************
// 		we have cast our dot spell on a different unit and must now add it to the system.
        if not sameUnit then
            if id == 0 then
                set doitCounting[0] = doitCounting[0] + 1
                set id = doitCounting[0]
            else
                set doitRecycler[0] = doitRecycler[id]
            endif
            call doitDefault(damager, target, damg, duration, interval, attacktypeindex, instanceID, instancekind, maxNumOfStacks )
        endif
//	**************************************************************************************************
    endif
    if instancekind == 0 then
        call doitDefault(damager, target, damg, duration, interval, attacktypeindex, instanceID, instancekind, maxNumOfStacks )
    endif
 
 
 
//  new
   // if not sameUnit then    //  only applies the visual debuff if there is none yet; aka shall not stack visual debuffs; aka one visual debuff is enough
    //    if not IsUnitType(target, UNIT_TYPE_DEAD)   then
    //       set sfx = AddSpecialEffectTarget(doitSfxName[id], doitTarget[id], doitAttachPoint[id])
    //        set tempunit = CreateUnitAtLoc(GetOwningPlayer(doitDamager[id]), 'e000', Location(tempx, tempy), 0.0)   // 'e000' = dummy unit
     //       call UnitAddAbility(tempunit, 'A003')                                                                   // 'A003' debuff ability
    //        call IssueTargetOrder(tempunit, "innerfire", doitTarget[id])                                            //apply debuff (visual only)
    //        call UnitApplyTimedLife(tempunit,'BTLF',1.0)
   //         set tempunit = null
   //     endif
//    endif
endfunction

//====================================================================================
//	Init and shit
//====================================================================================
private function Init takes nothing returns nothing
    local integer l = 0
    local trigger t = CreateTrigger( )
    set doitRecycler[0] = 0

    loop
        exitwhen l > 15
        set doitCounting [l] = 0
        set l = l + 1
    endloop
    set doitAttackTypeIndex[0] = ATTACK_TYPE_CHAOS
    set doitAttackTypeIndex[1] = ATTACK_TYPE_MAGIC
    set doitAttackTypeIndex[2] = ATTACK_TYPE_NORMAL
    set doitAttackTypeIndex[3] = ATTACK_TYPE_PIERCE
    set doitAttackTypeIndex[4] = ATTACK_TYPE_SIEGE
    set doitCounting[0] = 0
    set doitTimer = CreateTimer()
endfunction

endlibrary
 

Attachments

  • I dont understand.w3x
    176.5 KB · Views: 92
Last edited:
Status
Not open for further replies.
Top