//TESH.scrollpos=12
//TESH.alwaysfold=0
library PoisionDarts requires Math
globals
private constant real Tick = 1./30.
private constant real Speed = 1000.
private constant real DotInterval=0.1
private attacktype Attacktype = ATTACK_TYPE_PIERCE
private damagetype Damagetype = DAMAGE_TYPE_DEMOLITION
private string DeadEffect = ""
private constant integer DartUnit = 'h002'
private constant integer PoisionDartSpellID = 'AOsw'
endglobals
struct Dart
unit Caster
unit Dart
real Damage
real DistanceLeft
real DotDamage
real DotDuration
string DotEffect
vector position
vector velocity
private integer di
private static timer dTim = CreateTimer()
private static integer dTotal = 0
private static thistype array dDarts
private static group g = CreateGroup()
private static thistype temp
private static boolean hit = false
private method onDestroy takes nothing returns nothing
set dTotal = dTotal - 1
set dDarts[di] = dDarts[dTotal]
set dDarts[di].di=di
if dTotal == 0 then
call PauseTimer(dTim)
endif
endmethod
private static method DamageUnits takes nothing returns nothing
if IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(temp.Caster)) and not hit then
call UnitDamageTarget(temp.Caster,GetEnumUnit(),temp.Damage,true, false, Attacktype, Damagetype, WEAPON_TYPE_WHOKNOWS)
set udg_DTA_Target = GetEnumUnit()
set udg_DTA_DmgDealer = temp.Caster
set udg_DTA_TotalDamageDealt = temp.DotDamage
set udg_DTA_Time = temp.DotDuration
set udg_DTA_Interval = DotInterval
set udg_DTA_SpecialEffect = temp.DotEffect
set udg_DTA_EffectAttachmentPoint = "origin"
set udg_DTA_Attacktype = Attacktype
set udg_DTA_DamageType = Damagetype
call TriggerExecute( gg_trg_Get_DOT )
set hit=true
endif
endmethod
private static method onLoop takes nothing returns nothing
local thistype dat
local integer i2 = 0
loop
exitwhen i2 > dTotal - 1
set dat = dDarts[i2]
set dat.DistanceLeft = dat.DistanceLeft - (Speed * Tick)
call dat.position.add(dat.velocity)
call SetUnitXYZ(dat.Dart,dat.position.x,dat.position.y,dat.position.z)
set temp=dat
call GroupEnumUnitsInRange(g,dat.position.x,dat.position.y,40.,null)
call ForGroup(g,function thistype.DamageUnits)
call GroupClear(g)
if (dat.DistanceLeft <=0. or GetLocZ(dat.position.x,dat.position.y)> dat.position.z or hit) then
call RemoveUnit(dat.Dart)
call DestroyEffect(AddSpecialEffect(DeadEffect,dat.position.x,dat.position.y))
call dat.position.destroy()
call dat.velocity.destroy()
set dat.Caster=null
set dat.Dart=null
call dat.destroy()
set hit=false
endif
set i2 = i2+1
endloop
endmethod
static method NewDart takes unit caster, vector target ,real damage, real distance, real dot, real dotdur, string doteffect, real scale returns nothing
local thistype dat
local vector dir
set dat = thistype.allocate()
if dTotal==0 then
call TimerStart(dTim,Tick,true,function thistype.onLoop)
endif
set dat.di=dTotal
set dDarts[dat.di] = dat
set dTotal = dTotal+1
set dat.Caster = caster
set dat.Damage = damage
set dat.DistanceLeft = distance
set dat.DotDamage=dot
set dat.DotDuration=dotdur
set dat.DotEffect=doteffect
set dat.position = vector.create(GetUnitX(dat.Caster),GetUnitY(dat.Caster),GetUnitZ(dat.Caster)+40.)
set dir=vector.difference(target,dat.position)
call dir.vecNormalise()
set dat.velocity = vector.create(Speed*Tick*dir.x,Speed*Tick*dir.y,Speed*Tick*dir.z)
set dat.Dart = CreateUnit(GetOwningPlayer(dat.Caster),DartUnit,dat.position.x,dat.position.y,Atan(dat.velocity.y/dat.velocity.x)*bj_RADTODEG)
call MakeUnitFly(dat.Dart)
call SetUnitZ(dat.Dart,dat.position.z)
call SetUnitScale(dat.Dart,scale,scale,scale)
endmethod
endstruct
private struct PoisionDart
unit Caster
integer DartsLeft
integer SpellLevel
real ShootDelay
real DartDamage
real ShootDistance
real OverTimeDamage
real OverTimeDamageDuration
string OverTimeDamageEffect
real Scale
vector target
timer tim
//============================ settings ==============================
private static method GetDistance takes integer level returns real
return 700.
endmethod
private static method GetDamage takes integer level returns real
return 30.+(15*I2R(level))
endmethod
private static method GetDartCount takes integer level returns integer
return 5+(2*level)
endmethod
private static method GetShootDelay takes integer level returns real
return 0.1
endmethod
private static method GetDamageOverTime takes integer level returns real
return 10.+(5.*level)
endmethod
private static method GetDamageOverTimeDuration takes integer level returns real
return 5.
endmethod
//========================== end of settings =========================
private static method onEnd takes nothing returns nothing
local timer t = GetExpiredTimer()
local timer t2
local thistype dat = PoisionDart(GetTimerData(t))
if (dat.DartsLeft >0) then
set dat.DartsLeft=dat.DartsLeft-1
call Dart.NewDart(dat.Caster,dat.target,dat.DartDamage,dat.ShootDistance,dat.OverTimeDamage,dat.OverTimeDamageDuration,dat.OverTimeDamageEffect,dat.Scale)
call StartSound(gg_snd_RainOfFireTarget1) // RainOfFireTarget1 ersetzten
set t = NewTimer()
call SetTimerData(t, dat)
call TimerStart(t, dat.ShootDelay, false, function thistype.onEnd)
else
set dat.Caster=null
call dat.target.destroy()
call dat.destroy()
endif
endmethod
private static method Check takes nothing returns boolean
local thistype dat
local timer t
if GetSpellAbilityId() == PoisionDartSpellID then
call StartSound(gg_snd_RainOfFireTarget1) // RainOfFireTarget1 ersetzten
set dat = thistype.allocate()
set dat.SpellLevel = GetUnitAbilityLevel(GetTriggerUnit(), PoisionDartSpellID)
set dat.DartsLeft = GetDartCount(dat.SpellLevel)-1+GetNumberOfItemsFromUnit(GetTriggerUnit(),'I000') //rune id
set t = NewTimer()
call SetTimerData(t, dat)
set dat.ShootDelay=GetShootDelay(dat.SpellLevel)//-(0.02*GetNumberOfItemsFromUnit(GetTriggerUnit(),'I000')) // rune id
set dat.Caster = GetTriggerUnit()
set dat.DartDamage = GetDamage(dat.SpellLevel)+(10*GetNumberOfItemsFromUnit(GetTriggerUnit(),'I000')) // rune id
set dat.ShootDistance = GetDistance(dat.SpellLevel)+(100*GetNumberOfItemsFromUnit(GetTriggerUnit(),'I000')) // rune id
set dat.target = vector.create(GetSpellTargetX(),GetSpellTargetY(),GetLocZ(GetSpellTargetX(),GetSpellTargetY())+40.)
set dat.OverTimeDamage = GetDamageOverTime(dat.SpellLevel)
set dat.OverTimeDamageDuration = GetDamageOverTimeDuration(dat.SpellLevel)
set dat.OverTimeDamageEffect="" //DoT effect
if GetNumberOfItemsFromUnit(GetTriggerUnit(),'I000') > 0 then //rune id
set dat.Scale=2.
else
set dat.Scale=1.
endif
call TimerStart(t, dat.ShootDelay, false, function thistype.onEnd)
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function thistype.Check))
endmethod
endstruct
endlibrary