- Joined
- Feb 22, 2006
- Messages
- 960
I saw some damage over time system, so i wanted to create my own. The user has much more power over the effect. Actually there are 4 diffrent OverTime effects.
Damage
DamageAoe
State
StateAoe
so look into it
The system requires TimerUtils by Vexorian so also give credits to him
TimerUtils:
Main System:
so first the 4 diffrent calls:
DamageOverTime Single Target:
example:
DamageOverTime AOE:
example:
StateOverTime Single Target:
example:
StateOverTime AOE:
example:
So pls give feedback and credits if you use this system
Damage
DamageAoe
State
StateAoe
so look into it
The system requires TimerUtils by Vexorian so also give credits to him
TimerUtils:
JASS:
library_once TimerUtils
//*********************************************************************
//* TimerUtils (Blue flavor)
//* ----------
//*
//* To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//* To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass) More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//* * Attaching
//* * Recycling (with double-free protection)
//*
//* set t=NewTimer() : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2) : Attach value 2 to timer
//* GetTimerData(t) : Get the timer's value.
//* You can assume a timer's value is 0
//* after NewTimer.
//*
//* Blue Flavor: Slower than the red flavor, it got a 408000 handle id
//* limit, which means that if more than 408000 handle ids
//* are used in your map, TimerUtils might fail, this
//* value is quite big and it is much bigger than the
//* timer limit in Red flavor.
//*
//********************************************************************
//================================================================
globals
private constant integer MAX_HANDLE_ID_COUNT = 408000
// values lower than 8191: very fast, but very unsafe.
// values bigger than 8191: not that fast, the bigger the number is the slower the function gets
// Most maps don't really need a value bigger than 50000 here, but if you are unsure, leave it
// as the rather inflated value of 408000
endglobals
//=================================================================================================
private function H2I takes handle h returns integer
return h
return 0
endfunction
//==================================================================================================
globals
private integer array data[MAX_HANDLE_ID_COUNT]
private constant integer MIN_HANDLE_ID=0x100000
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
debug call BJDebugMsg("SetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
debug endif
set data[H2I(t)-MIN_HANDLE_ID]=value
endfunction
function GetTimerData takes timer t returns integer
debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
debug call BJDebugMsg("GetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
debug endif
return data[H2I(t)-MIN_HANDLE_ID]
endfunction
//==========================================================================================
globals
private timer array tT
private integer tN = 0
private constant integer HELD=0x28829022
//use a totally random number here, the more improbable someone uses it, the better.
endglobals
//==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
set tT[0]=CreateTimer()
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==8191) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
//stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
endlibrary
Main System:
JASS:
//********************************************************************
//* OverTimeEffectSystem [OTES] v1.1
//*
//* By xD.Schurke
//*
//*
//* changelog:
//*
//* v1.1
//* - Fixed a bug with AOE Effects
//* - Added Test Ability for AOE Damage
//********************************************************************
library OTES requires TimerUtils
globals
private constant real MIN_TIMER_TIME = 0.035 //lower then 0.035 will lead to a lower performance
//===========DO NOT CHANGE ANYTHING BELOW THIS LINE=================
private group tmpG = CreateGroup()
endglobals
private struct OverTimeEffect
unit caster
unit tar
timer t
real interval = 0.
real duration = 0.
real curdur = 0.
real value = 0.
string sfx = ""
string attach = ""
integer style = 0
boolean pereodic = false
damagetype dt = null
unitstate us = null
real x = 0.
real y = 0.
real radius = 0.
group g = CreateGroup()
boolexpr filter = null
boolean pick = true
static method oteffect takes nothing returns nothing
local OverTimeEffect Dat = GetTimerData(GetExpiredTimer())
local real us = 0
if Dat.pereodic then
set Dat.curdur = Dat.curdur + Dat.interval
if Dat.style == 0 then
call UnitDamageTarget(Dat.caster,Dat.tar,Dat.value,false,false,ATTACK_TYPE_NORMAL,Dat.dt,null)
else
set us = GetUnitState(Dat.tar,Dat.us)
call SetUnitState(Dat.tar,Dat.us,us+Dat.value)
endif
call DestroyEffect(AddSpecialEffectTarget(Dat.sfx,Dat.tar,Dat.attach))
if Dat.curdur >= Dat.duration or GetUnitState(Dat.tar,UNIT_STATE_LIFE) <= 0 then
call OverTimeEffect.destroy(Dat)
endif
else
if Dat.style == 0 then
call UnitDamageTarget(Dat.caster,Dat.tar,Dat.value,false,false,ATTACK_TYPE_NORMAL,Dat.dt,null)
else
set us = GetUnitState(Dat.tar,Dat.us)
call SetUnitState(Dat.tar,Dat.us,us+Dat.value)
endif
call DestroyEffect(AddSpecialEffectTarget(Dat.sfx,Dat.tar,Dat.attach))
call OverTimeEffect.destroy(Dat)
endif
endmethod
static method oteffectaoe takes nothing returns nothing
local OverTimeEffect Dat = GetTimerData(GetExpiredTimer())
local real us = 0
local unit u
if Dat.pereodic then
set Dat.curdur = Dat.curdur + Dat.interval
if Dat.pick !=true then
if Dat.style == 0 then
loop
set u = FirstOfGroup(Dat.g)
exitwhen u == null
call UnitDamageTarget(Dat.caster,u,Dat.value,false,false,ATTACK_TYPE_NORMAL,Dat.dt,null)
call DestroyEffect(AddSpecialEffectTarget(Dat.sfx,u,Dat.attach))
call GroupAddUnit(tmpG,u)
call GroupRemoveUnit(Dat.g,u)
set u = null
endloop
loop
set u = FirstOfGroup(tmpG)
exitwhen u == null
call GroupAddUnit(Dat.g,u)
call GroupRemoveUnit(tmpG,u)
set u = null
endloop
else
loop
set u = FirstOfGroup(Dat.g)
exitwhen u == null
set us = GetUnitState(u,Dat.us)
call SetUnitState(u,Dat.us,us+Dat.value)
call DestroyEffect(AddSpecialEffectTarget(Dat.sfx,u,Dat.attach))
call GroupAddUnit(tmpG,u)
call GroupRemoveUnit(Dat.g,u)
set u = null
endloop
loop
set u = FirstOfGroup(tmpG)
exitwhen u == null
call GroupAddUnit(Dat.g,u)
call GroupRemoveUnit(tmpG,u)
set u = null
endloop
endif
else
call GroupEnumUnitsInRange(tmpG,Dat.x,Dat.y,Dat.radius,Dat.filter)
loop
set u = FirstOfGroup(tmpG)
exitwhen u == null
if Dat.style == 0 then
call UnitDamageTarget(Dat.caster,u,Dat.value,false,false,ATTACK_TYPE_NORMAL,Dat.dt,null)
call GroupRemoveUnit(tmpG,u)
else
set us = GetUnitState(u,Dat.us)
call SetUnitState(u,Dat.us,us+Dat.value)
call GroupRemoveUnit(tmpG,u)
endif
call DestroyEffect(AddSpecialEffectTarget(Dat.sfx,u,Dat.attach))
set u = null
endloop
endif
if Dat.curdur >= Dat.duration then
call OverTimeEffect.destroy(Dat)
endif
else
if Dat.pick !=true then
set tmpG = Dat.g
if Dat.style == 0 then
loop
set u = FirstOfGroup(tmpG)
exitwhen u == null
call UnitDamageTarget(Dat.caster,u,Dat.value,false,false,ATTACK_TYPE_NORMAL,Dat.dt,null)
call DestroyEffect(AddSpecialEffectTarget(Dat.sfx,u,Dat.attach))
call GroupRemoveUnit(tmpG,u)
set u = null
endloop
else
loop
set u = FirstOfGroup(tmpG)
exitwhen u == null
set us = GetUnitState(u,Dat.us)
call SetUnitState(u,Dat.us,us+Dat.value)
call DestroyEffect(AddSpecialEffectTarget(Dat.sfx,u,Dat.attach))
call GroupRemoveUnit(tmpG,u)
set u = null
endloop
endif
else
call GroupEnumUnitsInRange(tmpG,Dat.x,Dat.y,Dat.radius,Dat.filter)
loop
set u = FirstOfGroup(tmpG)
exitwhen u == null
if Dat.style == 0 then
call UnitDamageTarget(Dat.caster,u,Dat.value,false,false,ATTACK_TYPE_NORMAL,Dat.dt,null)
call GroupRemoveUnit(tmpG,u)
else
set us = GetUnitState(u,Dat.us)
call SetUnitState(u,Dat.us,us+Dat.value)
call GroupRemoveUnit(tmpG,u)
endif
call DestroyEffect(AddSpecialEffectTarget(Dat.sfx,u,Dat.attach))
set u = null
endloop
endif
call OverTimeEffect.destroy(Dat)
endif
endmethod
static method createDamage takes unit caster, unit target,real duration,boolean pereodic,real interval,real value,boolean ConsiderArmor,string sfx,string attach returns OverTimeEffect
local OverTimeEffect Dat = OverTimeEffect.allocate()
local real time = 0
if duration < MIN_TIMER_TIME or caster == null or target == null then
if pereodic and interval < MIN_TIMER_TIME then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5.,"The duration or interval can't be less then 0.03 seconds!")
call OverTimeEffect.destroy(Dat)
return 0
endif
endif
if ConsiderArmor then
set Dat.dt = DAMAGE_TYPE_NORMAL
else
set Dat.dt = DAMAGE_TYPE_UNIVERSAL
endif
set Dat.style = 0
set Dat.caster = caster
set Dat.tar = target
set Dat.sfx = sfx
set Dat.attach = attach
set Dat.value = value
set Dat.t = NewTimer()
set Dat.duration = duration
set Dat.interval = interval
if pereodic then
set Dat.pereodic = pereodic
set time = Dat.interval
else
set time = Dat.duration
endif
call SetTimerData(Dat.t,Dat)
call TimerStart(Dat.t,time,pereodic,function OverTimeEffect.oteffect)
return Dat
endmethod
static method createDamageAoe takes unit caster, real x,real y,real radius,boolexpr filter,boolean b, real duration,boolean pereodic,real interval,real value,boolean ConsiderArmor,string sfxpath,string attach returns OverTimeEffect
local OverTimeEffect Dat = OverTimeEffect.allocate()
local real time = 0
if duration < MIN_TIMER_TIME or caster == null then
if pereodic and interval < MIN_TIMER_TIME then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5.,"The duration or interval can't be less then 0.03 seconds!")
call OverTimeEffect.destroy(Dat)
return 0
endif
endif
if ConsiderArmor then
set Dat.dt = DAMAGE_TYPE_NORMAL
else
set Dat.dt = DAMAGE_TYPE_UNIVERSAL
endif
if b != true then
set Dat.pick = b
call GroupEnumUnitsInRange(Dat.g,x,y,radius,filter)
endif
set Dat.style = 0
set Dat.caster = caster
set Dat.x = x
set Dat.y = y
set Dat.radius = radius
set Dat.filter = filter
set Dat.t = NewTimer()
set Dat.duration = duration
set Dat.interval = interval
set Dat.value = value
set Dat.sfx = sfxpath
set Dat.attach = attach
if pereodic then
set Dat.pereodic = pereodic
set time = Dat.interval
else
set time = Dat.duration
endif
call SetTimerData(Dat.t,Dat)
call TimerStart(Dat.t,time,pereodic,function OverTimeEffect.oteffectaoe)
return Dat
endmethod
static method createState takes unit target,real duration,boolean pereodic,real interval,unitstate us,real value,string sfx,string attach returns OverTimeEffect
local OverTimeEffect Dat = OverTimeEffect.allocate()
local real time = 0
if duration < MIN_TIMER_TIME or target == null or us == null then
if pereodic and interval < MIN_TIMER_TIME then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5.,"The duration or interval can't be less then 0.03 seconds!")
call OverTimeEffect.destroy(Dat)
return 0
endif
endif
set Dat.style = 1
set Dat.us = us
set Dat.tar = target
set Dat.sfx = sfx
set Dat.attach = attach
set Dat.value = value
set Dat.t = NewTimer()
set Dat.duration = duration
set Dat.interval = interval
if pereodic then
set Dat.pereodic = pereodic
set time = Dat.interval
else
set Dat.duration = duration
set time = Dat.duration
endif
call SetTimerData(Dat.t,Dat)
call TimerStart(Dat.t,time,pereodic,function OverTimeEffect.oteffect)
return Dat
endmethod
static method createStateAoe takes real x,real y,real radius,boolexpr filter,boolean b, real duration,boolean pereodic,real interval,real value,unitstate us,string sfxpath,string attach returns OverTimeEffect
local OverTimeEffect Dat = OverTimeEffect.allocate()
local real time = 0
if duration < MIN_TIMER_TIME or us == null then
if pereodic and interval < MIN_TIMER_TIME then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5.,"The duration or interval can't be less then 0.03 seconds!")
call OverTimeEffect.destroy(Dat)
return 0
endif
endif
if b != true then
set Dat.pick = b
call GroupEnumUnitsInRange(Dat.g,x,y,radius,filter)
endif
set Dat.style = 1
set Dat.x = x
set Dat.y = y
set Dat.radius = radius
set Dat.filter = filter
set Dat.t = NewTimer()
set Dat.duration = duration
set Dat.interval = interval
set Dat.value = value
set Dat.sfx = sfxpath
set Dat.attach = attach
set Dat.us = us
if pereodic then
set Dat.pereodic = pereodic
set time = Dat.interval
else
set time = Dat.duration
endif
call SetTimerData(Dat.t,Dat)
call TimerStart(Dat.t,time,pereodic,function OverTimeEffect.oteffectaoe)
return Dat
endmethod
method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
set .caster = null
set .tar = null
set .t = null
set .dt = null
set .us = null
call DestroyGroup(.g)
set .g = null
set .filter = null
endmethod
endstruct
function OverTimeDamage takes unit caster, unit target,real duration,boolean pereodic,real interval,real value,boolean ConsiderArmor,string sfx,string attach returns nothing
call OverTimeEffect.createDamage(caster,target,duration,pereodic,interval,value,ConsiderArmor,sfx,attach)
endfunction
function OverTimeState takes unit target,real duration,boolean pereodic,real interval,unitstate us,real value,string sfx,string attach returns nothing
call OverTimeEffect.createState(target,duration,pereodic,interval,us,value,sfx,attach)
endfunction
function OverTimeDamageAoe takes unit caster, real x,real y,real radius,boolexpr filter,boolean b, real duration,boolean pereodic,real interval,real value,boolean ConsiderArmor,string sfxpath,string attach returns nothing
call OverTimeEffect.createDamageAoe(caster,x,y,radius,filter,b,duration,pereodic,interval,value,ConsiderArmor,sfxpath,attach)
endfunction
function OverTimeStateAoe takes real x,real y,real radius,boolexpr filter,boolean b, real duration,boolean pereodic,real interval,real value,unitstate us,string sfxpath,string attach returns nothing
call OverTimeEffect.createStateAoe(x,y,radius,filter,b,duration,pereodic,interval,value,us,sfxpath,attach)
endfunction
endlibrary
so first the 4 diffrent calls:
DamageOverTime Single Target:
call OverTimeDamage(<unit caster>,<unit target>,<real duration>,<boolean pereodic>,<real interval>,<real damage>,<boolean considerArmor>,<string effectpath>,<string effect attach>)
example:
call OverTimeDamage(udg_u, udg_t,3.,false,0.,200,true,"Objects\\Spawnmodels\\Human\\HumanLargeDeathExplode\\HumanLargeDeathExplode.mdl","origin")
DamageOverTime AOE:
call OverTimeDamageAoe(<unit caster>,<real x>,<real y>,<real radius>,<boolexpr filter>,<boolean refresh or not>,< real duration>,<boolean pereodic>,<real interval>,<real value>,<boolean ConsiderArmor>,<string sfxpath>,<string attach>)
example:
call OverTimeDamageAoe(udg_t,GetLocationX(GetSpellTargetLoc()),GetLocationY(GetSpellTargetLoc()),400,Condition(function filter),false,10,true,2,100,true,"Objects\\Spawnmodels\\Human\\HumanLargeDeathExplode\\HumanLargeDeathExplode.mdl","origin")
StateOverTime Single Target:
call OverTimeState(<unit caster>,<unit target>,<real duration>,<boolean pereodic>,<real interval>,<unitstate>,<real value>,<string effectpath>,<string effect attach>)
example:
call OverTimeState(udg_u, udg_t,5.,true,1.,UNIT_STATE_LIFE,100,"Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl","origin")
StateOverTime AOE:
call OverTimeStateAoe(<real x>,<real y>,<real radius>,<boolexpr filter>,<boolean refresh or not>, <real duration>,<boolean pereodic>,<real interval>,<real value>,<unitstate>,<string sfxpath>,<string attach>)
example:
call OverTimeStateAoe(GetLocationX(GetSpellTargetLoc()),GetLocationY(GetSpellTargetLoc()),400,Condition(function filter),true, 10,true,1,25,UNIT_STATE_MANA,"Abilities\\Spells\\Items\\AIma\\AImaTarget.mdl","chest")
So pls give feedback and credits if you use this system
Attachments
Last edited: