//TESH.scrollpos=37
//TESH.alwaysfold=0
//===========================================================================================
//Hydro Pump
//by Paskovich
//
//Needed objects:
// - an AoE targetted spell (like Blizzard)
// - a dummy unit with the 'ziggurat missile' model
// o be sure that its movement type is set to hover, and fly height to 50
//
//To implement the spell, copy and paste this trigger to your map.
//Change the datas below as they are written there.
//You will also need the Local Handle Vars and the other functions,
//so copy the whole script from the custom script window.
//
//Please give me a credit if you use this spell on your map!
//============================================================================================
function Trig_Hydro_Pump_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A000' //Your ability raw code.
endfunction
function Hydro_Pump_BlueDummyRC takes nothing returns integer
return 'u01G' //Blue dummy raw code. (the swirl unit)
endfunction
constant function Hydro_Pump_Radius takes nothing returns real
return 300.0 //Radius of the spell.
endfunction
constant function Hydro_Pump_SwirlDurSeconds takes nothing returns real
return 3.0 //Duration before the Hydro Pump comes up. (duration of the swirl)
endfunction
constant function Hydro_Pump_DistanceModifier takes nothing returns real
return 0.0 //How far the unit flyies (!from where it is!), related to the distance from the center point.
endfunction
function Hydro_Pump_MaxHeight takes nothing returns integer
local real MaxHeight = 0.0 //A unit exactly in the centerpoint reaches this fly height.
//Units on the border will reach 50.0 height only.
return R2I(MaxHeight) - 0
endfunction
constant function Hydro_Pump_DamageInitial takes nothing returns real
return 20.0
endfunction
constant function Hydro_Pump_DamageIncrease takes nothing returns integer
return GetUnitLevel(GetTriggerUnit())
endfunction
constant function Hydro_Pump_MinDamage takes nothing returns real
//Damage ranges from MaxDamage to MinDamage as we are closer to the border.
return 0.0 //Units at the border will take MinDamage damage.
endfunction
function Hydro_Pump_DamageWhenFall takes nothing returns boolean
//If you want the unit to take damage when it falls to the ground, set this to true.
return false //Note: Calculations are the same as above.
endfunction
constant function Hydro_Pump_Fall_DamageInitial takes nothing returns real
return 0.0
endfunction
constant function Hydro_Pump_Fall_DamageIncrease takes nothing returns real
return 0.0
endfunction
constant function Hydro_Pump_Fall_MinDamage takes nothing returns real
return 0.0
endfunction
//====================================================================
//This function calculates a curve, that has its maximum height set. (reqired for the jump)
function GetParabolaHeightPreset takes real dist, real maxdist,real maxheight returns real
local real t = (dist*2)/maxdist-1
return (-t*t+1)*maxheight
endfunction
//The target unit's jump timer
function Hydro_Pump_PumpUnit takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = GetHandleUnit(t, "PumpUnit")
local real CenterX = GetHandleReal(t, "CenterX")
local real CenterY = GetHandleReal(t, "CenterY")
local real maxDist = GetHandleReal(t, "maxDist")
local real maxHeight = GetHandleReal(t, "maxHeight")
local real distChange = maxDist/50
local real dmg
local real dis = DistanceBetweenPointsXY(CenterX, CenterY, GetUnitX(u), GetUnitY(u))
local real ang = AngleBetweenPointsXY(CenterX, CenterY, GetUnitX(u), GetUnitY(u))
//Calculate the unit's position
local real ppx = PolarProjectionX(CenterX, dis + distChange, ang)
local real ppy = PolarProjectionY(CenterY, dis + distChange, ang)
local real UnitX = GetHandleReal(t, "UnitX")
local real UnitY = GetHandleReal(t, "UnitY")
local real curDist = DistanceBetweenPointsXY(UnitX, UnitY, GetUnitX(u), GetUnitY(u))
local real hgt = GetParabolaHeightPreset(curDist, maxDist, maxHeight)
//Create effect every three 0.02 seconds.
if ModuloInteger(GetHandleInt(t, "counter"), 3) == 0 then
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl", u, "chest"))
endif
//Set the unit's position and facing.
call SetUnitPosition(u, ppx, ppy)
call SetUnitFlyHeight(u, hgt, 0)
call SetUnitFacing(u, ang)
//Chacks is the jump is over. (The timer is shot 50 times)
if GetHandleInt(t, "counter") == 50 then
call PauseTimer(t)
call SetUnitPathing(u, true)
call SetUnitFlyHeight(u, GetUnitDefaultFlyHeight(u), 0)
if Hydro_Pump_DamageWhenFall() then
if IsUnitEnemy(u, GetOwningPlayer(GetHandleUnit(t, "Caster"))) then
set dmg = GetHandleInt(t, "Level") * Hydro_Pump_Fall_DamageIncrease()
set dmg = Hydro_Pump_Fall_DamageInitial() + dmg
set dmg = PercentToInt(GetHandleInt(t, "Percent"), R2I(dmg - Hydro_Pump_Fall_MinDamage()))
set dmg = Hydro_Pump_Fall_MinDamage() + dmg
call UnitDamageTarget(GetHandleUnit(t, "Caster"), u, dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
endif
endif
// call UnitRemoveAbility(u, 'Avul')
call FlushHandleLocals(t)
call DestroyTimer(t)
endif
call SetHandleInt(t, "counter", GetHandleInt(t, "counter") + 1)
set t = null
set u = null
endfunction
//The initial swirl movement timer
function Hydro_Pump_Swirl takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = null
local real CenterX = GetHandleReal(t, "CenterX")
local real CenterY = GetHandleReal(t, "CenterY")
local real ang
local real dist
local real mindist
local real ppx
local real ppy
local integer a = 1
loop
exitwhen a > 12
set u = GetHandleUnit(t, "SwUnit"+I2S(a))
set ang = AngleBetweenPointsXY(CenterX, CenterY, GetUnitX(u), GetUnitY(u))
set dist = DistanceBetweenPointsXY(CenterX, CenterY, GetUnitX(u), GetUnitY(u))
set mindist = Hydro_Pump_Radius() / (40* Hydro_Pump_SwirlDurSeconds())
set ppx = PolarProjectionX(CenterX, dist - mindist, ang + 10)
set ppy = PolarProjectionY(CenterY, dist - mindist, ang + 10)
call SetUnitPosition(u, ppx, ppy)
call SetUnitFacing(u, ang+90)
set a = a + 1
endloop
//Checks is the swirl is small enough - destroy timer/swirl
if GetHandleInt(t, "times") >= (Hydro_Pump_Radius() / mindist) then
call PauseTimer(t)
set a = 1
loop
exitwhen a > 12
call KillUnit(GetHandleUnit(t, "SwUnit"+I2S(a)))
set a = a + 1
endloop
call FlushHandleLocals(t)
call DestroyTimer(t)
endif
call SetHandleInt(t, "times", GetHandleInt(t, "times") + 1)
set u = null
set t = null
endfunction
function Trig_Hydro_Pump_Actions takes nothing returns nothing
local unit c = GetTriggerUnit()
local location tl = GetSpellTargetLoc()
local timer t = CreateTimer()
local timer p = null
local real tx = GetLocationX(tl)
local real ty = GetLocationY(tl)
local group g
local unit u = null
local destructable d = null
local real dist
local real percent
local real ppx
local real ppy
local integer a = 1
local real dmg
call SetHandleReal(t, "CenterX", tx)
call SetHandleReal(t, "CenterY", ty)
//Create the initial swirl effect at the center of the target area.
call TerrainDeformCrater( tx, ty, Hydro_Pump_Radius(), 0, R2I((Hydro_Pump_SwirlDurSeconds()+0.3)*1000), false)
loop
exitwhen a > 12
set ppx = PolarProjectionX(tx, Hydro_Pump_Radius(), (a-1)*30)
set ppy = PolarProjectionY(ty, Hydro_Pump_Radius(), (a-1)*30)
call SetHandleHandle(t, "SwUnit"+I2S(a), CreateUnit(GetOwningPlayer(c), Hydro_Pump_BlueDummyRC(), ppx, ppy, (a-1)*30))
set a = a + 1
endloop
call TimerStart(t, 0.02, true, function Hydro_Pump_Swirl)
call TriggerSleepAction(Hydro_Pump_SwirlDurSeconds())
loop
exitwhen a > 7
call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl", PolarProjectionX(tx, Hydro_Pump_Radius()/2, a*45), PolarProjectionY(ty, Hydro_Pump_Radius()/2, a*45)))
set a = a + 1
endloop
//Picks enemy, non-building, not magic immune units in the target area -> start jumping timer.
set g = GetUnitsInRangeOfLocAll( Hydro_Pump_Radius(), tl)
loop
set u = FirstOfGroup(g)
call GroupRemoveUnit(g,u)
exitwhen u == null
if u != c and IsUnitType(u, UNIT_TYPE_STRUCTURE) == false and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) == false then
set p = CreateTimer()
//Calculate the unit's distance from the center / max height in the jump. (tricky heh? :))
//This makes the units fly at different heights.
set dist = DistanceBetweenPointsXY(tx, ty, GetUnitX(u), GetUnitY(u))
set percent = 100 - ((dist / Hydro_Pump_Radius()) * 100)
call SetHandleReal( p, "maxHeight" , 50 + PercentToInt(percent, Hydro_Pump_MaxHeight()) )
//Calculate and deal damage
if IsUnitEnemy(u, GetOwningPlayer(c)) then
call SetHandleInt(p, "Level", GetUnitAbilityLevel(c, GetSpellAbilityId()))
call SetHandleInt(p, "Percent", RoundR2I(percent))
set dmg = GetHandleInt(p, "Level") * Hydro_Pump_DamageIncrease()
set dmg = Hydro_Pump_DamageInitial() + dmg
set dmg = PercentToInt(percent, R2I(dmg - Hydro_Pump_MinDamage()))
set dmg = Hydro_Pump_MinDamage() + dmg
call UnitDamageTarget(c, u, dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
endif
//Set the parameters for the timer.
call SetHandleHandle(p, "PumpUnit", u)
call SetHandleHandle(p, "Caster", c)
call SetHandleReal( p, "CenterX" , tx)
call SetHandleReal( p, "CenterY" , ty)
call SetHandleReal( p, "UnitX", GetUnitX(u))
call SetHandleReal( p, "UnitY", GetUnitY(u))
call SetHandleInt( p, "counter" , 1)
call SetHandleReal( p, "maxDist" , dist * Hydro_Pump_DistanceModifier())
//Add Storm Crow Form - start timer.
call SetUnitPathing(u, false)
call UnitAddAbility(u, 'Arav')
// call UnitAddAbility(u, 'Avul')
call UnitRemoveAbility(u, 'Arav')
call TimerStart(p, 0.02, true, function Hydro_Pump_PumpUnit)
endif
endloop
//Null variables
call RemoveLocation(tl)
set p = null
set g = null
set u = null
set t = null
set tl = null
endfunction
//===========================================================================
function InitTrig_Hydro_Pump takes nothing returns nothing
set gg_trg_Hydro_Pump = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Hydro_Pump, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Hydro_Pump, Condition( function Trig_Hydro_Pump_Conditions ) )
call TriggerAddAction( gg_trg_Hydro_Pump, function Trig_Hydro_Pump_Actions )
endfunction