/////////////////////////////////////////////////////////////////////////////////////////
//Cyclone Leap v1.04 //
//by Adiktuz //
//Credits to The_Reborn_Devil and Silvenon for GroupRecycler and Knockback libraries //
//How to use: //
//1) Copy this whole library and paste into your map //
//2) Copy the spell data if you want //
//3)Modify the fields to your liking //
/////////////////////////////////////////////////////////////////////////////////////////
scope Leap initializer init
globals
private constant integer LEAP_ID = 'A000' //Rawcode of Leap spell
private constant integer FLY_ID = 'Amrf' //RAwcode of medivh's raven form
private constant string CYCLONE = "Abilities\\Spells\\Other\\Tornado\\TornadoElemental.mdl" //Path to the cyclone model
private constant real TICK = .03 //Timer interval
private constant string A_POINT = "origin" //The attachment point of the effect
private constant attacktype AT = ATTACK_TYPE_MAGIC
private constant damagetype DT = DAMAGE_TYPE_NORMAL
//Do not edit below the following globals
//There are some functions to edit values after this globals
private timer LEAP_TIMER = CreateTimer()
private group TEMP_GROUP = CreateGroup() //I cannot use NewGroup in a global block
private Leap data
private Leap instance
private real ANGLE = 0.00
private integer array DAT[8190]
private integer TOTAL = 0
private boolexpr FILTER
private real MaX
private real MiX
private real MaY
private real MiY
private unit FU = null
//
endglobals
//Various functions for some of the data
//This allows easier formula modification
private function DPS takes integer level returns real
return level*75.00
endfunction
private function RADIUS takes nothing returns real
return 250.00
endfunction
private function DIST_PER_SEC takes nothing returns real
return 600.00
endfunction
private function KB_DIST takes nothing returns real
return 100.00
endfunction
private function KB_TIME takes nothing returns real
return 1.00
endfunction
private function GRAV takes nothing returns real
return 100.00
endfunction
//End functions
struct Leap
unit caster
effect cyclone
integer level
player owner
real x
real y
real tx
real ty
real dx
real dy
group damagegroup
real damage
real distanceperloop
real totaldistance
real z
real dz
static method check takes nothing returns boolean
set FU = GetFilterUnit()
if IsUnitEnemy( FU, instance.owner) and GetWidgetLife(FU) >= .405 and IsUnitInGroup(FU, instance.damagegroup) != true then
call UnitDamageTarget(instance.caster, FU, instance.damage, false, false, AT, DT, null)
call GroupAddUnit(instance.damagegroup, FU)
call Knockback(FU, KB_DIST(), bj_DEGTORAD*(GetUnitFacing(FU) + 180.00),KB_TIME() )
endif
return true
endmethod
static method onLoop takes nothing returns nothing
local integer i = 0
loop
exitwhen i == TOTAL
set data = DAT[i]
set data.x = data.x + data.dx
set data.y = data.y + data.dy
if data.x <= MaX and data.x >= MiX then
call SetUnitX(data.caster, data.x)
endif
if data.y <= MaY and data.y >= MiY then
call SetUnitY(data.caster, data.y)
endif
set data.z = data.z + data.dz
set data.dz = data.dz - TICK*GRAV()
call SetUnitFlyHeight(data.caster, data.z, 0.00)
set instance = data
call GroupEnumUnitsInRange(TEMP_GROUP, data.x, data.y, RADIUS() , FILTER)
if data.z <= 0.00 then
call DestroyEffect(data.cyclone)
call ReleaseGroup(data.damagegroup)
call data.destroy()
set TOTAL = TOTAL - 1
set DAT[i] = DAT[TOTAL]
set i = i - 1
endif
set i = i + 1
endloop
if TOTAL == 0 then
call PauseTimer(LEAP_TIMER)
endif
endmethod
static method Create takes nothing returns thistype
set data = Leap.allocate()
set data.caster = GetTriggerUnit()
set data.cyclone = AddSpecialEffectTarget(CYCLONE, data.caster, A_POINT)
set data.owner = GetOwningPlayer(data.caster)
set data.tx = GetSpellTargetX()
set data.ty = GetSpellTargetY()
set data.x = GetUnitX(data.caster)
set data.y = GetUnitY(data.caster)
set ANGLE = Atan2(data.ty - data.y, data.tx - data.x)
set data.damagegroup = NewGroup()
set data.level = GetUnitAbilityLevel(data.caster, LEAP_ID)
set data.totaldistance = SquareRoot((data.tx - data.x)*(data.tx - data.x) + (data.ty - data.y)*(data.ty - data.y))
set data.distanceperloop = TICK*DIST_PER_SEC()
set data.z = 0.00
set data.dz = (GRAV() * (data.totaldistance/DIST_PER_SEC()))/2
//This next if is to ensure that the spell works correct when you cast in on your portrait
//coz it causes a weird bug...
if data.totaldistance <= 0.00 then
set data.totaldistance = 1.00
endif
set data.dx = data.distanceperloop*Cos(ANGLE)
set data.dy = data.distanceperloop*Sin(ANGLE)
set data.damage = DPS(data.level)
if UnitAddAbility(data.caster, FLY_ID) then
call UnitRemoveAbility(data.caster, FLY_ID)
endif
set DAT[TOTAL] = data
set TOTAL = TOTAL + 1
if TOTAL == 1 then
call TimerStart(LEAP_TIMER, TICK, true, function Leap.onLoop)
endif
return data
endmethod
endstruct
private function LeapCheck takes nothing returns boolean
return GetSpellAbilityId() == LEAP_ID
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
call TriggerAddAction(t, function Leap.Create)
call TriggerAddCondition(t, Filter(function LeapCheck))
loop
exitwhen i > 15
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
set i = i + 1
endloop
set FILTER = Filter(function Leap.check)
set MaX = GetRectMaxX(bj_mapInitialPlayableArea)
set MiX = GetRectMinX(bj_mapInitialPlayableArea)
set MaY = GetRectMaxY(bj_mapInitialPlayableArea)
set MiY = GetRectMinY(bj_mapInitialPlayableArea)
endfunction
endscope