Name | Type | is_array | initial_value |
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Stormcyclone initializer init
globals
private constant integer DUMMY_ID = 'dumx'
private constant integer DUMMY_CYCLONE_ID = 'dum1'
private constant integer SPELL_SKILL_ID = 'A000'
private constant integer SPELL_DUMMY_ID = 'A001'
private constant integer SPELL_DUMMY_BUFF = 'B000'
private constant integer SPELL_SKILL_ID_ORDER = 852183
private constant string SPELL_DUMMY_ID_ORDER = "slow"
private constant attacktype A_TYPE = ATTACK_TYPE_NORMAL
private constant damagetype D_TYPE = DAMAGE_TYPE_NORMAL
private constant weapontype W_TYPE = WEAPON_TYPE_WHOKNOWS
private constant real STORM_AREA = 800.
private constant string STORM_EDGE_SFX = "Abilities\\Spells\\NightElf\\FaerieFire\\FaerieFireTarget.mdl"
private constant real STORM_EDGE_SFX_AMOUNT = 36
private constant integer CYCLONE_WAVES_AMOUNT = 3
private constant integer CYCLONE_PER_WAVES = 4
private constant real CYCLONE_DAMAGE_AREA = 150.
private constant real CYCLONE_DAMAGE_INTERVAL = 1.
private constant real CYCLONE_MOVESPEED = 20.
// Don't change \\
private constant real LOOP_TIME = 0.03125
private constant hashtable HASH = InitHashtable()
private integer TEMP
endglobals
private function damage takes integer level returns real
return 75. * level
endfunction
struct Stormcyclone
unit caster = null
player owner = null
real dmg = 0.
group cgrp = CreateGroup()
group sgrp = CreateGroup()
group dgrp = CreateGroup()
effect array efc[1]
// == Slow struct == \\
static method slow_filter takes nothing returns boolean
local thistype this = TEMP
local unit u = GetFilterUnit()
if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u,.owner) and IsUnitType(u,UNIT_TYPE_STRUCTURE) == false and IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) == false and IsUnitInGroup(u,.sgrp) == false then
call GroupAddUnit(.sgrp,u)
endif
set u = null
return false
endmethod
static method slow_action takes nothing returns nothing
local thistype this = TEMP
local unit u1 = GetEnumUnit()
local unit u2
local real x = GetUnitX(u1) - GetUnitX(.caster)
local real y = GetUnitY(u1) - GetUnitY(.caster)
if GetWidgetLife(u1) < 0.405 then
call GroupRemoveUnit(.sgrp,u1)
endif
if GetUnitCurrentOrder(.caster) == SPELL_SKILL_ID_ORDER then
if SquareRoot(x * x + y * y) <= STORM_AREA then
if GetUnitAbilityLevel(u1,SPELL_DUMMY_BUFF) == 0 then
set u2 = CreateUnit(.owner,DUMMY_ID,GetUnitX(u1),GetUnitY(u1),0.)
call UnitApplyTimedLife(u2,'BTFL',1.)
call UnitAddAbility(u2,SPELL_DUMMY_ID)
call SetUnitAbilityLevel(u2,SPELL_DUMMY_ID,GetUnitAbilityLevel(.caster,SPELL_SKILL_ID))
call IssueTargetOrder(u2,SPELL_DUMMY_ID_ORDER,u1)
set u2 = null
endif
else
call UnitRemoveAbility(u1,SPELL_DUMMY_BUFF)
call GroupRemoveUnit(.sgrp,u1)
endif
else
call UnitRemoveAbility(u1,SPELL_DUMMY_BUFF)
call GroupRemoveUnit(.sgrp,u1)
endif
set u1 = null
endmethod
// == Damage struct == \\
static method cyclone_damage_remove takes nothing returns nothing
local thistype this = TEMP
local timer t = GetExpiredTimer()
call GroupRemoveUnit(.dgrp,LoadUnitHandle(HASH,GetHandleId(t),1))
call DestroyTimer(t)
set t = null
endmethod
static method cyclone_damage_add takes nothing returns boolean
local thistype this = TEMP
local unit u = GetFilterUnit()
local timer t = CreateTimer()
if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u,.owner) and IsUnitType(u,UNIT_TYPE_STRUCTURE) == false and IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) == false and IsUnitInGroup(u,.dgrp) == false then
call UnitDamageTarget(.caster,u,.dmg,true,false,A_TYPE,D_TYPE,W_TYPE)
call GroupAddUnit(.dgrp,u)
call SaveUnitHandle(HASH,GetHandleId(t),1,u)
call TimerStart(t,CYCLONE_DAMAGE_INTERVAL,false,function thistype.cyclone_damage_remove)
endif
set u = null
set t = null
return false
endmethod
// == Base struct == \\
static method cyclone_move takes nothing returns nothing
local thistype this = TEMP
local group g = CreateGroup()
local unit u = GetEnumUnit()
local integer v = GetUnitUserData(u)
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real f = GetWidgetLife(u) -1.
call SetWidgetLife(u, f + ((CYCLONE_MOVESPEED * 180.) / (bj_PI * v)) +1.)
set f = f * bj_DEGTORAD
set x = x + v *(Cos(f) - Cos(f - (CYCLONE_MOVESPEED / v)))
set y = y + v *(Sin(f) - Sin(f - (CYCLONE_MOVESPEED / v)))
call SetUnitX(u,x)
call SetUnitY(u,y)
call GroupEnumUnitsInRange(g,GetUnitX(u),GetUnitY(u),CYCLONE_DAMAGE_AREA,Condition(function thistype.cyclone_damage_add))
call DestroyGroup(g)
set g = null
set u = null
endmethod
static method periodic takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = LoadInteger(HASH,GetHandleId(t),0)
local group g = CreateGroup()
local unit u
local integer i = 0
if GetUnitCurrentOrder(.caster) == SPELL_SKILL_ID_ORDER then
call GroupEnumUnitsInRange(g,GetUnitX(.caster),GetUnitY(.caster),STORM_AREA,Condition(function thistype.slow_filter))
call ForGroup(.cgrp,function thistype.cyclone_move)
call ForGroup(.sgrp,function thistype.slow_action)
else
call ForGroup(.sgrp,function thistype.slow_action)
loop
exitwhen i == STORM_EDGE_SFX_AMOUNT
call DestroyEffect(.efc[i])
set i = i + 1
endloop
loop
set u = FirstOfGroup(.cgrp)
exitwhen u == null
call RemoveUnit(u)
call GroupRemoveUnit(.cgrp,u)
endloop
call PauseTimer(t)
call DestroyTimer(t)
set t = null
call DestroyGroup(.cgrp)
call DestroyGroup(.sgrp)
call .destroy()
endif
call DestroyGroup(g)
set g = null
set t = null
endmethod
static method create takes unit caster returns thistype
local thistype this = .allocate()
local timer t = CreateTimer()
local unit u
local integer a = 0
local integer b = 0
local real x1 = 0.
local real y1 = 0.
local real x2 = 0.
local real y2 = 0.
set .caster = caster
set .dmg = damage(GetUnitAbilityLevel(.caster,SPELL_SKILL_ID))
set .owner = GetOwningPlayer(caster)
set TEMP = this
loop
exitwhen a == STORM_EDGE_SFX_AMOUNT
set x1 = GetUnitX(.caster) + STORM_AREA * Cos(360 / STORM_EDGE_SFX_AMOUNT * bj_DEGTORAD * a)
set y1 = GetUnitY(.caster) + STORM_AREA * Sin(360 / STORM_EDGE_SFX_AMOUNT * bj_DEGTORAD * a)
set .efc[a] = AddSpecialEffect(STORM_EDGE_SFX,x1,y1)
set a = a + 1
endloop
set a = 0
loop
exitwhen a == CYCLONE_WAVES_AMOUNT
set x1 = STORM_AREA / CYCLONE_WAVES_AMOUNT * a + 120.
set b = 0
loop
exitwhen b == CYCLONE_PER_WAVES
set y1 = 360. / CYCLONE_PER_WAVES * b
set x2 = GetUnitX(.caster) + x1 * Cos(y1 * bj_DEGTORAD)
set y2 = GetUnitY(.caster) + x1 * Sin(y1 * bj_DEGTORAD)
set u = CreateUnit(.owner,DUMMY_CYCLONE_ID,x2,y2,0.)
call SetWidgetLife(u,y1 + 1.)
call SetUnitUserData(u,R2I(x1))
call GroupAddUnit(.cgrp,u)
set b = b + 1
endloop
set a = a + 1
endloop
call SaveInteger(HASH,GetHandleId(t),0,this)
call TimerStart(t,LOOP_TIME,true,function thistype.periodic)
set t = null
return this
endmethod
endstruct
private function condition takes nothing returns boolean
if GetSpellAbilityId() == SPELL_SKILL_ID then
call Stormcyclone.create(GetTriggerUnit())
endif
return false
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i == 16
call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
set i = i + 1
endloop
call TriggerAddCondition(t,function condition)
call Preload(STORM_EDGE_SFX)
set t = null
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
function MapInit_Group takes nothing returns nothing
call UnitAddAbility(GetEnumUnit(),'AAAA')
endfunction
function MapInit_Action takes nothing returns nothing
local group g = CreateGroup()
call FogEnable(false)
call FogMaskEnable(false)
call GroupEnumUnitsOfPlayer(g,Player(PLAYER_NEUTRAL_AGGRESSIVE),null)
call ForGroup(g,function MapInit_Group)
call DestroyGroup(g)
set g = null
endfunction
function InitTrig_MapInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterTimerEvent(t,0.,false)
call TriggerAddAction(t,function MapInit_Action)
set t = null
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Refresh_Group takes nothing returns boolean
local unit u = GetFilterUnit()
if IsUnitType(u,UNIT_TYPE_HERO) == true then
call SetWidgetLife(u,GetUnitState(u,UNIT_STATE_MAX_LIFE))
call SetUnitState(u,UNIT_STATE_MANA,GetUnitState(u,UNIT_STATE_MAX_MANA))
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl",GetUnitX(u),GetUnitY(u)))
endif
set u = null
return false
endfunction
function Refresh_Action takes nothing returns nothing
local group g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,GetTriggerPlayer(),Condition(function Refresh_Group))
call DestroyGroup(g)
set g = null
endfunction
function InitTrig_Refresh takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i == 16
call TriggerRegisterPlayerEvent(t,Player(i),EVENT_PLAYER_END_CINEMATIC)
set i = i + 1
endloop
call TriggerAddAction(t,function Refresh_Action)
set t = null
endfunction