black.sheep
Active Member
- Reaction score
- 24
How would I go about doing this? I'm not intrested in the explosion, just the damage stacking.
scope pressure initializer i
private struct Dat
real damage
real duration
endstruct
globals
private group effected = CreateGroup()
private group g = CreateGroup()
private constant real TIMEROUT=.10
private constant integer USER=039;h038039;
private constant real DURATION=1.5
private constant real DAMAGEINC=0.50
private constant real DAMAGECAP=20
private constant string EFFECT="Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl"
private timer time=CreateTimer()
private Dat array DB
endglobals
private function c takes nothing returns boolean
if GetUnitAbilityLevel(GetTriggerUnit(),039;B014039;) == 1 and GetUnitTypeId(GetEventDamageSource()) == USER then
return true
endif
return false
endfunction
private function gro takes nothing returns nothing
local Dat tempDat
set tempDat=DB[GetUnitUserData(GetEnumUnit())]
set tempDat.duration = tempDat.duration - TIMEROUT
if tempDat.duration > 0 then
call GroupRemoveUnit(effected,GetEnumUnit())
set tempDat.damage = 0
call tempDat.destroy()
if CountUnitsInGroup(effected) == 0 then
call PauseTimer(time)
endif
endif
endfunction
private function p takes nothing returns nothing
call ForGroup(effected,function gro)
endfunction
private function a takes nothing returns nothing
local Dat tempDat
call UnitRemoveAbility(GetTriggerUnit(),039;B014039;)
if IsUnitInGroup(GetTriggerUnit(),effected) == true then
set tempDat=DB[GetUnitUserData(GetTriggerUnit())]
call Damage_Pure(GetEventDamageSource(),GetTriggerUnit(),tempDat.damage)
if tempDat.damage < DAMAGECAP then
set tempDat.damage = tempDat.damage+DAMAGEINC
endif
debug call BJDebugMsg(R2S(tempDat.damage))
else
set tempDat=Dat.create()
set tempDat=DB[GetUnitUserData(GetTriggerUnit())]
set tempDat.damage = 0
debug call BJDebugMsg(R2S(tempDat.damage))
set DB[GetUnitUserData(GetTriggerUnit())]=tempDat
if CountUnitsInGroup(effected)==0 then
call TimerStart(time,TIMEROUT,true,function p)
endif
call GroupAddUnit(effected,GetTriggerUnit())
endif
call DestroyEffect(AddSpecialEffectTarget(EFFECT,GetTriggerUnit(),"chest"))
endfunction
private function i takes nothing returns nothing
local trigger t=CreateTrigger()
call Damage_RegisterEvent(t)
call TriggerAddCondition(t,Condition(function c))
call TriggerAddAction(t,function a)
endfunction
endscope
//Requires AIDS, Damage, Recycle, optional ABC
scope Test initializer Init
globals
private constant integer ATKER_ID = 039;h038039;
private constant integer BUFF_ID = 039;B014039;
private constant real DAMAGE_CAP = 20.
private constant real DAMAGE_INCREASE = .5
private constant real DURATION = 1.5
private constant string GFX = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl"
private hashtable hasht = InitHashtable()
endglobals
private keyword Data
private struct TimerList
timer t
thistype next
thistype prev
method onDestroy takes nothing returns nothing
//Remove attached stuffs.
static if LIBRARY_ABC then
//If ABC is available, use ABC instead of hashtable.
call ClearTimerStructA(.t)
call ClearTimerStructB(.t)
call ClearTimerStructC(.t)
else
call FlushChildHashtable(hasht,GetHandleId(.t))
endif
//Recycle the timer.
call Timer.release(.t)
//Unlink.
set .prev.next = .next
set .next.prev = .prev
//Who can guess why I didn't nullify the timer here? =P
endmethod
method chainDestroy takes nothing returns nothing
loop
set this = this.next
exitwhen this == 0
call .destroy()
endloop
endmethod
static method onExpired takes nothing returns nothing
//Get struct from timer
static if LIBRARY_ABC then
local timer t = GetExpiredTimer()
local thistype this = LoadTimerStructA(t)
local integer damagedUnitId = LoadTimerStructB(t)
local integer atkerId = LoadTimerStructC(t)
//Use ABC if available.
else
local integer tId = GetHandleId(GetExpiredTimer())
local thistype this = LoadInteger(hasht,tId,0)
local integer damagedUnitId = LoadInteger(hasht,tId,1)
local integer atkerId = LoadInteger(hasht,tId,2)
endif
local real r = LoadReal(hasht,damagedUnitId,atkerId)
//Prevent bug, so we get the value again instead of storing it in struct.
set r = r - DAMAGE_INCREASE
//Decrease the damage stack amount
call SaveReal(hasht,damagedUnitId,atkerId,r)
//Set it.
call .destroy()
//destroy the struct.
endmethod
static method add takes Data d, integer id, real r returns nothing
local thistype this = .allocate()
//Get a new instance.
local integer tId
set .t = Timer.get()
//Get a timer from timer stack.
set d.head.prev.next = this
set .prev = d.head.prev
set d.head.prev = this
set .next = 0
//LinkedList
call SaveReal(hasht,d,id,r)
//Set the damage stack value.
static if LIBRARY_ABC then
call SetTimerStructA(.t,this)
call SetTimerStructB(.t,d)
call SetTimerStructC(.t,id)
else
set tId = GetHandleId(.t)
call SaveInteger(hasht,tId,0,this)
call SaveInteger(hasht,tId,1,d)
call SaveInteger(hasht,tId,2,id)
endif
//Attach stuffs to timer.
call TimerStart(.t,DURATION,false,function thistype.onExpired)
//Start the timer.
endmethod
endstruct
private struct Data extends array
boolean isCapped
TimerList head
method AIDS_onCreate takes nothing returns nothing
//Create list for timer
set .head = TimerList.create()
//LinkedList.
set .head.next = .head
set .head.prev = .head
endmethod
method AIDS_onDestroy takes nothing returns nothing
call .head.chainDestroy()
call FlushChildHashtable(hasht,this)
set .isCapped = false
//Remove all stacked damage from all source
//Remove the cap, ready for later usage
//Force removing the timers, since the unit is removed, the timers are
//useless and may cause bug.
endmethod
//! runtextmacro AIDS()
endstruct
private function Act takes nothing returns nothing
local Data d = Data[GetTriggerUnit()] //Struct of attaacked unit.
local integer id = GetUnitId(GetEventDamageSource()) //Id of attacker.
local real r = LoadReal(hasht,d,id) //Damage stack count.
set r = RMinBJ(r + DAMAGE_INCREASE, DAMAGE_CAP) //Limit the amount of damage stacking.
call Damage_Pure(GetIndexUnit(id),d.unit,r) //Deal damage.
if r < DAMAGE_CAP or (r >= DAMAGE_CAP and d.isCapped == false) then
//If current value less than capped value
//or first reach to capped value then
call TimerList.add(d,id,r)
//make timer and callback.
if r >= DAMAGE_CAP then
set d.isCapped = true
//Flag it.
endif
endif
call DestroyEffect(AddSpecialEffectTarget(GFX,d.unit,"chest"))
//visual effect.
endfunction
private function Cond takes nothing returns boolean
if GetUnitAbilityLevel(GetTriggerUnit(),039;B014039;) > 0 and GetUnitTypeId(GetEventDamageSource()) == ATKER_ID and Damage_IsAttack() then
//Condition : Unit type stuffs and the important : Damage_IsAttack(), it can prevent recursion/ infinite loop.
call Act()
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
call Damage_RegisterEvent(t)
call TriggerAddCondition(t,Condition(function Cond))
endfunction
endscope