//TESH.scrollpos=0
//TESH.alwaysfold=0
//The rawcode of the spell
constant function TB_SID takes nothing returns integer
return 'A076'
endfunction
//The rawcode of the dummy unit (Tornado)
constant function TB_DID takes nothing returns integer
return 'h018'
endfunction
//The rawcode of the slow-ability
constant function TB_SlowID takes nothing returns integer
return 'A075'
endfunction
//The movement speed of the knockbacks
constant function TB_SPEED takes nothing returns real
return 18.0
endfunction
//A timer intervall. Better do not change
constant function TB_INTERVALL takes nothing returns real
return 0.02
endfunction
//The collision size of the Tornado. Enemies in that range will be affected
constant function TB_COLLISION takes nothing returns real
return 110.0
endfunction
//This is how far an enemy is knocked when hit by the Tornado
constant function TB_ENEMY_DISTANCE takes real level returns real
return level * 220 + 350
endfunction
//Howlong the enemies are affected by the slow
constant function TB_SlowDuration takes real level returns real
return level * 0 + 4
endfunction
//Calculates the damage. It´s related to the level of the ability and the
//intellegence of the casting hero.
function TB_GetDamage takes unit u returns real
local integer level = GetUnitAbilityLevel(u,TB_SID())
local real damage = level*1.75*GetHeroInt(u,true)
return damage
endfunction
//This will slow down the enemies. You can change the model though.
function TB_SlowEffect takes unit u returns effect
local string SFX = "Abilities\\Spells\\Other\\Tornado\\Tornado_Target.mdl"
local string ATTATCH = "overhead"
call SetUnitVertexColor(u,90,90,255,200)
call UnitAddAbility(u,TB_SlowID())
return AddSpecialEffectTarget(SFX,u,ATTATCH)
endfunction
//Special effect being displayed when a unit is knocked away.
function TB_SpecialEffect takes real x, real y returns nothing
local string s = "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl"
call DestroyEffect(AddSpecialEffect(s,x,y))
endfunction
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//Will remove the slow effect after the deisered time.
function TB_RemoveSlow takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
//Get the timer and the id
local unit u = LoadUnitHandle(udg_TB_HASHTABLE ,id,0)
//Reset the affected unit
call SetUnitVertexColor(u,255,255,255,255)
call UnitRemoveAbility(u,TB_SlowID())
call DestroyEffect(LoadEffectHandle(udg_TB_HASHTABLE ,id,5))
//Clean up stuff
call FlushChildHashtable(udg_TB_HASHTABLE ,id)
call PauseTimer(t)
call DestroyTimer(t)
set t = null
set u = null
endfunction
//Checks if a unit is outside the map or not.
function TB_IsOutOfMap takes widget w, real x, real y returns boolean
local real array p
set p[0] = 64.0
set p[1] = GetRectMaxX(bj_mapInitialPlayableArea) - p[0]
set p[2] = GetRectMaxY(bj_mapInitialPlayableArea) - p[0]
set p[3] = GetRectMinX(bj_mapInitialPlayableArea) + p[0]
set p[4] = GetRectMinY(bj_mapInitialPlayableArea) + p[0]
return x >= p[1] or x <= p[3] or y >= p[2] or y <= p[4]
endfunction
//Callback which will move the an affected unit
function TB_EnemyKnock takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
//Getting the timer + id
local unit u = LoadUnitHandle(udg_TB_HASHTABLE ,id,0)
local real x = GetWidgetX(u) + LoadReal(udg_TB_HASHTABLE ,id,1)
local real y = GetWidgetY(u) + LoadReal(udg_TB_HASHTABLE ,id,2)
local real d = LoadReal(udg_TB_HASHTABLE ,id,3) - TB_SPEED()
//Getting the stuff attatched to it and doing some calcs
//Moving the unit
call SetUnitX(u,x)
call SetUnitY(u,y)
call TB_SpecialEffect(x,y)
call SaveReal(udg_TB_HASHTABLE ,id,3,d)
//Checks if the knockback is over
if d <= .0 or TB_IsOutOfMap(u,x,y) then
call SaveBoolean(udg_TB_HASHTABLE ,GetHandleId(u),8,false)
call PauseTimer(t)
call TimerStart(t,TB_SlowDuration(LoadInteger(udg_TB_HASHTABLE ,id,6)),false, function TB_RemoveSlow)
endif
set t = null
set u = null
endfunction
//A function which will deal with all enemies near a tornado
function TB_EnemyDetect takes nothing returns boolean
local integer id = LoadInteger(udg_TB_HASHTABLE ,0,0)
//Getting the id of the corresponding timer.
local unit u = GetFilterUnit()
local unit d = null
local timer t = null
local real x
local real y
local real rad
local real dmg
local integer lv
//If the unit fits our conditions...
if IsUnitEnemy(u,LoadPlayerHandle(udg_TB_HASHTABLE ,id,4)) and not(LoadBoolean(udg_TB_HASHTABLE ,GetHandleId(u),8) or IsUnitType(u,UNIT_TYPE_DEAD) or IsUnitType(u,UNIT_TYPE_STRUCTURE) or IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) ) then
set lv = LoadInteger(udg_TB_HASHTABLE ,id,6)
set d = LoadUnitHandle(udg_TB_HASHTABLE ,id,0)
set x = GetWidgetX(u) - GetWidgetX(d)
set y = GetWidgetY(u) - GetWidgetY(d)
set rad = Atan2(x,y)
set dmg = LoadReal(udg_TB_HASHTABLE ,id,7)
//.... we do some calcs for starting the knockback
set t = CreateTimer()
set id = GetHandleId(t)
call SaveUnitHandle(udg_TB_HASHTABLE ,id,0,u)
call SaveReal(udg_TB_HASHTABLE ,id,1,Cos(rad)*TB_SPEED())
call SaveReal(udg_TB_HASHTABLE ,id,2,Sin(rad)*TB_SPEED())
call SaveReal(udg_TB_HASHTABLE ,id,3,TB_ENEMY_DISTANCE(LoadInteger(udg_TB_HASHTABLE ,id,6)))
call SaveInteger(udg_TB_HASHTABLE ,id,6,lv)
call SaveEffectHandle(udg_TB_HASHTABLE ,id,5,TB_SlowEffect(u))
call SaveBoolean(udg_TB_HASHTABLE ,GetHandleId(u),8,true)
call SetUnitAbilityLevel(u,TB_SlowID(),lv)
//Creating a timer and attatching stuff to it
//1.Deal damage 2. Start the knockback 3. Cleanup
call UnitDamageTarget(d,u,dmg,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
call TimerStart(t,TB_INTERVALL(),true, function TB_EnemyKnock)
set d = null
set t = null
endif
set u = null
return false
endfunction
//Call back for a timer which moves a tornadom (similar to the MoveEnemiy func but not equal)
function TB_TornadoMove takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
local unit u = LoadUnitHandle(udg_TB_HASHTABLE ,id,0)
local real x = GetWidgetX(u) + LoadReal(udg_TB_HASHTABLE ,id,1)
local real y = GetWidgetY(u) + LoadReal(udg_TB_HASHTABLE ,id,2)
local real d = LoadReal(udg_TB_HASHTABLE ,id,3) - TB_SPEED()
//Getting timer and stuff...doing calcs
call SaveInteger(udg_TB_HASHTABLE ,0,0,id)
call GroupClear(LoadGroupHandle(udg_TB_HASHTABLE,1,1))
call GroupEnumUnitsInRange(LoadGroupHandle(udg_TB_HASHTABLE,1,1),x,y,TB_COLLISION(), Filter( function TB_EnemyDetect))
//Looking for units near the tornado
//Moving the tornado
call SetUnitX(u,x)
call SetUnitY(u,y)
call SaveReal(udg_TB_HASHTABLE ,id,3,d)
//If the tornado is near it´s end we stop this thing
if d <= .0 or TB_IsOutOfMap(u,x,y) then
call PauseTimer(t)
call DestroyTimer(t)
call KillUnit(u)
call FlushChildHashtable(udg_TB_HASHTABLE ,id)
endif
set t = null
set u = null
endfunction
//The function which starts this whole thing off
function TB_onCast takes nothing returns nothing
local timer t = CreateTimer()
local unit c = GetTriggerUnit()
local location l = GetSpellTargetLoc()
local real x = GetWidgetX(c)
local real y = GetWidgetY(c)
local integer id = GetHandleId(t)
local unit u = CreateUnit(GetOwningPlayer(c),TB_DID(),x,y,0)
local real r
//Getting various data
set x = GetLocationX(l)-x
set y = GetLocationY(l)-y
set r = Atan2(y,x)
call SaveUnitHandle(udg_TB_HASHTABLE ,id,0,u)
call SaveReal(udg_TB_HASHTABLE ,id,1,Cos(r)*TB_SPEED())
call SaveReal(udg_TB_HASHTABLE ,id,2,Sin(r)*TB_SPEED())
call SaveReal(udg_TB_HASHTABLE ,id,3,SquareRoot(x*x+y*y))
//Doing some calcs and attatching some stuff to it
call SavePlayerHandle(udg_TB_HASHTABLE ,id,4,GetOwningPlayer(u))
call SaveInteger(udg_TB_HASHTABLE ,id,6,GetUnitAbilityLevel(c,TB_SID()))
call SaveReal(udg_TB_HASHTABLE ,id,7,TB_GetDamage(c))
//Attatching other things
call TimerStart(t,TB_INTERVALL(),true, function TB_TornadoMove)
//Start the tornado
//Cleanup
call RemoveLocation(l)
set t = null
set c = null
set l = null
set u = null
endfunction
//Checks if the correct spell is casted
function TB_onCheck takes nothing returns boolean
return GetSpellAbilityId() == TB_SID()
endfunction
//Trigger restier and onInit stuff
function InitTrig_Wind_of_the_South takes nothing returns nothing
local trigger trig = CreateTrigger()
set udg_TB_HASHTABLE = InitHashtable()
call SaveGroupHandle(udg_TB_HASHTABLE ,1,1,CreateGroup())
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddAction(trig, function TB_onCast)
call TriggerAddCondition(trig, Filter( function TB_onCheck))
set trig = null
endfunction