Torrent
Yup, a spell from DotA.Technical Details
Jass: Yes.
MUI: Yes.
Laggless: Yes.
Leakless: Yes.
Requires: NewGen Editor, GT, TimerUtils,GroupUtils, DummyCaster, AutoFly
How to import
Code:
1) Copy the Torrent trigger into your map
2) Copy the TidalErruption.mdx model (if you do not already have it) into your map and change the patch to TidalErruption.mdx
3) Copy the Torrent (A000) , Torrent Slow (A001) abilities into your map
and Copy the Torrent buff (B000)
4) Copy the libraries that I used (if you do not already have it) into your map
Description
Using his unparalleled knowledge of the sea, Kunkka is able to summon a blast of water at a targeted area. After 2 seconds a fierce torrent of water erupts from the ground, the stream blasting enemies caught in the AoE into the sky, dealing damage and slowing movement speed by 30%.
Level 1 - Deals 120 damage, slows for 1 second.
Level 2 - Deals 180 damage, slows for 2 seconds.
Level 3 - Deals 240 damage, slows for 3 seconds.
Level 4 - Deals 300 damage, slows for 4 seconds.
Code
JASS:
library Torrent initializer Init requires GT,DummyCaster,AutoFly,TimerUtils,GroupUtils
// DotA Torrent by muZk
globals
//SPELL CONFIGURABLES
private constant integer SPELL_ID = 039;A000039; // Torrent rawcode ability
private constant integer SLOW_ID = 039;A001039; // Slow effects rawcode ability
private constant real INTERVAL = 0.03125 // callback interval
private constant real WAIT = 2.0 // time you have to wait before of erruption
private constant real RADIUS = 222.00 // effect radius of torrent
private constant real MAX_HEIGHT = 625.00 // max flyheight of the torrent unit
private constant real DURATION = 1.5 // duration of fly
//EFFECTS
private constant string Bubbles = "Objects\\Spawnmodels\\Other\\IllidanFootprint\\IllidanWaterSpawnFootPrint.mdl" //First effect
private constant integer NumberOfBubbles = 6
private constant real DistanceOfTarget = 40.00 //Distance between bubbles and target point
private constant string Erruption = "TidalErruption.mdx" //Erruption effect after WAIT seconds
private constant string TargetFX = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl" //Effect on target when it is flying
//Other stuff
private constant attacktype A_TYPE = ATTACK_TYPE_HERO
private constant damagetype D_TYPE = DAMAGE_TYPE_UNIVERSAL
endglobals
globals
private constant real v = 4*MAX_HEIGHT/DURATION
private constant real g = 4*MAX_HEIGHT/(DURATION*DURATION)
private constant real callbacks = DURATION/INTERVAL
endglobals
// TORRENT DAMAGE : Torrent causes 60 + 60*Level, and Level is level of torrent ability
// That is the total damage, but it look realistic if you do that damage per callback
// So, this function returns the damage per callback
private function DAMAGE takes integer level returns real
return (60.00 + 60.00*level)/callbacks
endfunction
// Height function, takes a callbacks counter returns the current height
private function Height takes real i returns real
return (v*i-g*i*i)
endfunction
// SpellPreload just to avoid the first lag cast
private function SpellPreload takes integer id returns nothing
call UnitAddAbility(DUMMY,id)
call UnitRemoveAbility(DUMMY,id)
endfunction
//**CODE**
private struct data
unit u
integer n
real i
real x
real y
player p
group g
static method create takes nothing returns data
local data d = data.allocate()
local real a = 0
local real r = 6.2832/NumberOfBubbles
local string s = Bubbles
set d.u = GetTriggerUnit()
set d.x = GetSpellTargetX()
set d.y = GetSpellTargetY()
set d.p = GetTriggerPlayer()
set d.n = GetUnitAbilityLevel(d.u,SPELL_ID)
set d.i = 0.0
if IsUnitEnemy(d.u,GetLocalPlayer()) then
set s = ""
endif
loop
exitwhen a==6.2832
call DestroyEffect(AddSpecialEffect(s,d.x+DistanceOfTarget*Cos(a),d.y+DistanceOfTarget*Sin(a)))
set a = a + r
endloop
return d
endmethod
method onDestroy takes nothing returns nothing
call ReleaseGroup(.g)
endmethod
endstruct
private function UnitMove takes nothing returns nothing
local data d = GetTimerData(GetExpiredTimer())
local unit u = GetEnumUnit()
call SetUnitFlyHeight(u,Height(d.i), 0.00 )
call UnitDamageTarget(d.u,u,DAMAGE(d.n),false,false,A_TYPE,D_TYPE,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget(TargetFX,u,"origin"))
if not IsUnitPaused(u) then
call PauseUnit(u,true)
endif
set u = null
endfunction
private function SlowUnits takes nothing returns nothing
local unit u = GetEnumUnit()
call PauseUnit(u,false)
call SetUnitPathing(u,true)
call IssueTargetOrder(DUMMY,"slow",u)
set u = null
endfunction
private function callback takes nothing returns nothing
local timer t = GetExpiredTimer()
local data d = GetTimerData(t)
call ForGroup(d.g,function UnitMove)
set d.i = d.i + INTERVAL
if d.i > DURATION then
call ReleaseTimer(t)
call UnitAddAbility(DUMMY,SLOW_ID)
call SetUnitAbilityLevel(DUMMY,SLOW_ID,d.n)
call ForGroup(d.g,function SlowUnits)
call UnitRemoveAbility(DUMMY,SLOW_ID)
call d.destroy()
endif
set t = null
endfunction
private function Filt takes nothing returns boolean
local unit u = GetFilterUnit()
local data d = GetTimerData(GetExpiredTimer())
if IsUnitEnemy(u,d.p) and GetWidgetLife(u)>0.405 and not IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call PauseUnit(u,true)
call SetUnitPathing(u,false)
set u = null
return true
endif
set u = null
return false
endfunction
private function erruption takes nothing returns nothing
local timer t = GetExpiredTimer()
local data d = GetTimerData(t)
set d.g = NewGroup()
call DestroyEffect(AddSpecialEffect(Erruption,d.x,d.y))
call GroupEnumUnitsInRange(d.g,d.x,d.y,RADIUS,Condition(function Filt))
if FirstOfGroup(d.g) == null then
call ReleaseTimer(t)
else
call TimerStart(t,INTERVAL,true,function callback)
endif
set t = null
endfunction
private function onEffect takes nothing returns boolean
local data d = data.create()
local timer t = NewTimer()
call SetTimerData(t,d)
call TimerStart(t,WAIT,false,function erruption)
set t = null
return false
endfunction
private function Init takes nothing returns nothing
call GT_AddStartsEffectAction( function onEffect,SPELL_ID)
call SpellPreload(SLOW_ID)
endfunction
endlibrary
View attachment Torrent.w3x