1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. Ride into the sunset with the 32nd Modeling Contest. The contest is optionally paired. Best of luck, people!
    Dismiss Notice
  5. This adventure has come to an end. Congratulate our heroes in the 16th Mini Mapping Contest Results.
    Dismiss Notice
  6. From the gates of hell, the 5th Special Effect Contest Results have emerged.
    Dismiss Notice
  7. Race against the odds and Reforge, Don't Refund. The 14th Techtree Contest has begun!
    Dismiss Notice
  8. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Trigger Viewer

Distributor Spell Pack v1.0a.w3x
Variables
Requirements
RegisterPlayerUnitEvent
SpellEffectEvent
UnitIndexer
Airburn
Slow
Distributor
Read
Distributor
Distributor Slam
DIstributor SlingShot
Distributor Dragon
Distributor Reunion
Test
Test
Enter map-specific custom script code below. This text will be included in the map script after variables are declared and before any trigger code.
//TESH.scrollpos=0
//TESH.alwaysfold=0
constant native UnitAlive takes unit id returns boolean
Name Type Is Array Initial Value
//TESH.scrollpos=46
//TESH.alwaysfold=0
/**************************************************************
*
*   RegisterPlayerUnitEvent
*   v5.1.0.1
*   By Magtheridon96
*
*   I would like to give a special thanks to Bribe, azlier
*   and BBQ for improving this library. For modularity, it only
*   supports player unit events.
*
*   Functions passed to RegisterPlayerUnitEvent must either
*   return a boolean (false) or nothing. (Which is a Pro)
*
*   Warning:
*   --------
*
*       - Don't use TriggerSleepAction inside registered code.
*       - Don't destroy a trigger unless you really know what you're doing.
*
*   API:
*   ----
*
*       - function RegisterPlayerUnitEvent takes playerunitevent whichEvent, code whichFunction returns nothing
*           - Registers code that will execute when an event fires.
*       - function RegisterPlayerUnitEventForPlayer takes playerunitevent whichEvent, code whichFunction, player whichPlayer returns nothing
*           - Registers code that will execute when an event fires for a certain player.
*       - function GetPlayerUnitEventTrigger takes playerunitevent whichEvent returns trigger
*           - Returns the trigger corresponding to ALL functions of a playerunitevent.
*
**************************************************************/

library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
    globals
        private trigger array t
    endglobals
   
    function RegisterPlayerUnitEvent takes playerunitevent p, code c returns nothing
        local integer i = GetHandleId(p)
        local integer k = 15
        if t[i] == null then
            set t[i] = CreateTrigger()
            loop
                call TriggerRegisterPlayerUnitEvent(t[i], Player(k), p, null)
                exitwhen k == 0
                set k = k - 1
            endloop
        endif
        call TriggerAddCondition(t[i], Filter(c))
    endfunction
   
    function RegisterPlayerUnitEventForPlayer takes playerunitevent p, code c, player pl returns nothing
        local integer i = 16 * GetHandleId(p) + GetPlayerId(pl)
        if t[i] == null then
            set t[i] = CreateTrigger()
            call TriggerRegisterPlayerUnitEvent(t[i], pl, p, null)
        endif
        call TriggerAddCondition(t[i], Filter(c))
    endfunction
   
    function GetPlayerUnitEventTrigger takes playerunitevent p returns trigger
        return t[GetHandleId(p)]
    endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//============================================================================
// SpellEffectEvent
// - Version 1.1.0.0
//
// API
// ---
//     RegisterSpellEffectEvent(integer abil, code onCast)
//
// Requires
// --------
//     RegisterPlayerUnitEvent: hiveworkshop.com/forums/showthread.php?t=203338
//
// Optional
// --------
//     Table: hiveworkshop.com/forums/showthread.php?t=188084
//
library SpellEffectEvent requires RegisterPlayerUnitEvent, optional Table
 
//============================================================================
private module M
   
    static if LIBRARY_Table then
        static Table tb
    else
        static hashtable ht = InitHashtable()
    endif
   
    static method onCast takes nothing returns nothing
        static if LIBRARY_Table then
            call TriggerEvaluate(.tb.trigger[GetSpellAbilityId()])
        else
            call TriggerEvaluate(LoadTriggerHandle(.ht, 0, GetSpellAbilityId()))
        endif
    endmethod
 
    private static method onInit takes nothing returns nothing
        static if LIBRARY_Table then
            set .tb = Table.create()
        endif
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
    endmethod
endmodule
 
//============================================================================
private struct S extends array
    implement M
endstruct
 
//============================================================================
function RegisterSpellEffectEvent takes integer abil, code onCast returns nothing
    static if LIBRARY_Table then
        if not S.tb.handle.has(abil) then
            set S.tb.trigger[abil] = CreateTrigger()
        endif
        call TriggerAddCondition(S.tb.trigger[abil], Filter(onCast))
    else
        if not HaveSavedHandle(S.ht, 0, abil) then
            call SaveTriggerHandle(S.ht, 0, abil, CreateTrigger())
        endif
        call TriggerAddCondition(LoadTriggerHandle(S.ht, 0, abil), Filter(onCast))
    endif
endfunction
 
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library UnitIndexer initializer init /* v1.0.1 by JC Helas
*******************************************************************
*
*   A simple unit indexer with triggerless and very easy to use.
*   feel free to use this without credits, this system is not surely
*   work safetly but contact me if may happens, also help me improve
*   this as well.
*
*   *USAGE*
*
*   UnitIndexerEvent = 1.0 A unit has been index.
*                          Returns UnitIndexerEventObject
*                                  UnitIndexerEventData
*   UnitIndexerEvent = 2.0 A unit has been removed from game.
*                          Returns UnitIndexerEventData
*   UnitIndexerEvent = 3.0 Index has initialize.
*   UnitIndexerEvent = 4.0 Index has not initialize.
*  
*   You can simply stop unit from being index by turning UnitIndexerStop
*   into "true". make sure to turn it to false.
*
*   set UnitIndexerStop=true
*   call CreateUnit(...)
*   set UnitIndexerStop=false
*
*******************************************************************/

    globals
        real UnitIndexerEvent        = 0.0
        unit UnitIndexerEventObject  = null
        integer UnitIndexerEventData = 0
        boolean UnitIndexerStop      = false
       
        private constant group  grup        = CreateGroup()
        private constant timer  tmr         = CreateTimer()
        private player uowner               = null
    endglobals
   
    private function createfilter takes nothing returns boolean
        local unit u=GetFilterUnit()
        local integer data=GetUnitUserData(u)
        if not UnitIndexerStop /*
      */
and not IsUnitIllusion(u) /*
      */
and ((data==0) or not(UnitStruct.filter(u,data))) then
            call UnitStruct.createthis(u)
        endif
        set u=null
        return false
    endfunction
   
    struct UnitStruct
        public unit UnitIndexed
        public player UnitPlayerIndexed
        public integer UnitPlayerIdIndexed
        static method removethis takes thistype this returns nothing
            set UnitIndexerEventData=this
            set UnitIndexerEvent=2.0
            set UnitIndexerEvent=0.0
            set UnitIndexed=null
            set UnitPlayerIndexed=null
            set UnitPlayerIdIndexed=0
            call deallocate()
        endmethod
        static method createthis takes unit u returns nothing
            local thistype this=allocate()
            set UnitIndexed=u
            set UnitPlayerIndexed=GetOwningPlayer(u)
            set UnitPlayerIdIndexed=GetPlayerId(UnitPlayerIndexed)
            call SetUnitUserData(u,this)
            set UnitIndexerEventObject=u
            set UnitIndexerEventData=this
            set UnitIndexerEvent=1.0
            set UnitIndexerEvent=0.0
        endmethod
        static method filter takes unit u,thistype this returns boolean
            return UnitIndexed==u
        endmethod
    endstruct
   
    private function removed takes unit u returns nothing
        local integer data=GetUnitUserData(u)
        if UnitStruct.filter(u,data) then
            call UnitStruct.removethis(GetUnitUserData(u))
        endif
    endfunction
   
    private function init takes nothing returns nothing
        local unit u
        local region reg=CreateRegion()
        local rect rct=GetWorldBounds()
        set gg_trg_UnitIndexer=CreateTrigger()
        call RegionAddRect(reg,rct)
        set UnitIndexerEvent=4.0
        set UnitIndexerEvent=0.0
        call GroupEnumUnitsInRect(grup,rct,Filter(function createfilter))
        call GroupClear(grup)
        call TriggerRegisterEnterRegion(gg_trg_UnitIndexer,reg,Filter(function createfilter))
        set UnitIndexerEvent=3.0
        set UnitIndexerEvent=0.0
        call RemoveRect(rct)
        set u=null
        set reg=null
        set rct=null
    endfunction
    hook RemoveUnit removed
endlibrary
//TESH.scrollpos=30
//TESH.alwaysfold=0
struct AirBurn
    static constant real MaxHeight=1000.0
    static constant real Periodic=0.0312500
    static constant real DefaultDur=10
    static constant real DefaultHeight=5000.0
    static constant real SinMax=90.0
    static constant integer fly='Amrf'
   
    static constant real RateHeight=DefaultDur/DefaultHeight
   
    static timer Tmr=CreateTimer()
    static integer Imax=0
    static integer array Icon[8190]
   
    static real array Usin[8190]
    static real array Uheight[8190]
    static boolean array Ucondition[8190]
   
    integer ID
   
    static method SinSpeed takes real h returns real
        return SinMax/((RateHeight*h)/Periodic)
    endmethod
   
    static method HeightUpdate takes real s, real h returns real
        return Sin(s*bj_DEGTORAD)*h
    endmethod
   
    static method lop takes nothing returns nothing
        local unit u
        local integer id
        local thistype this
        local integer i=1
        loop
            exitwhen i>Imax
            set this=Icon[i]
            set u=UnitStruct(ID).UnitIndexed
           
            if Ucondition[ID] then
                set Usin[ID]=Usin[ID]+SinSpeed(Uheight[ID])
               
                if Usin[ID]>=SinMax then
                    set Ucondition[ID]=false
                endif
            else
                set Usin[ID]=Usin[ID]-SinSpeed(Uheight[ID])
               
                if Usin[ID]<=0 then
                    set Icon[i]=Icon[Imax]
                    set Imax=Imax-1
                    set i=i-1
                    call deallocate(ID)
                   
                    if Imax==0 then
                        call PauseTimer(Tmr)
                    endif
                endif
            endif
            call SetUnitFlyHeight(u,HeightUpdate(Usin[ID],Uheight[ID]),0.0)
            set i=i+1
        endloop
        set u=null
    endmethod
   
    static method exe takes unit u, real h returns nothing
        local integer id=GetUnitUserData(u)
        local real rh
        local thistype this
        if Usin[id]==0 then
            call UnitAddAbility(u,fly)
            call UnitRemoveAbility(u,fly)
            set Usin[id]=0
            set Uheight[id]=h
            set Ucondition[id]=true
            set this=allocate()
            set Imax=Imax+1
            set Icon[Imax]=this
            set ID=id
            if Imax==1 then
                call TimerStart(Tmr,Periodic,true,function AirBurn.lop)
            endif
        elseif Ucondition[id] then
            set rh=GetUnitFlyHeight(u)
            set Uheight[id]=Uheight[id]+(h/2)
            set Usin[id]=(SinMax/Uheight[id])*rh
        elseif not Ucondition[id] then
            set Ucondition[id]=true
            set rh=GetUnitFlyHeight(u)
            set Uheight[id]=rh+h
            set Usin[id]=(SinMax/Uheight[id])*rh
        endif
    endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct Slow
    private static constant real PERIODIC = 0.031250
    private static timer tmr=CreateTimer()
    private static integer ix=0
    private static integer array ic
    private static real array duration
    private static real array base
    private static real array amount
    private static real array fade
    private unit object
    private static method onLoop takes nothing returns nothing
        local thistype this
        local integer i=1
        local integer id
        loop
            exitwhen i>ix
            set this=ic[i]
            set id=GetUnitUserData(object)
            if duration[id]>=PERIODIC then
                set duration[id]=duration[id]-PERIODIC
                call SetUnitMoveSpeed(object,base[id]-((amount[id]/fade[id])*duration[id]))
            else
                set object=null
                set base[id]=0.0
                set fade[id]=0.0
                set amount[id]=0.0
                set duration[id]=0.0
                call deallocate()
                set ic[i]=ic[ix]
                set ix=ix-1
                set i=i-1
                if ix==0 then
                    call PauseTimer(tmr)
                endif
            endif
            set i=i+1
        endloop
    endmethod
    public static method Add takes unit u,real a,real d,boolean stack returns nothing
        local thistype this
        local integer id=GetUnitUserData(u)
        set base[id]=GetUnitDefaultMoveSpeed(u)
        set amount[id]=a
        if duration[id]<=0.0 then
            set this=allocate()
            set ix=ix+1
            set ic[ix]=this
            set object=u
            if ix==1 then
                call TimerStart(tmr,PERIODIC,true,function thistype.onLoop)
            endif
            set duration[id]=d
            set fade[id]=d
        elseif stack then
            set duration[id]=duration[id]+d
            set fade[id]=duration[id]
        else
            set duration[id]=d
            set fade[id]=d
        endif
    endmethod
endstruct
Distributor Spell Pack v1.0a
by JC Helas

Configureable 100%

Please dont forget to credit me when using this, thank you.

Changelog:
v1.0a
-Reduced Memory Usage

How to import:
E search mo XD
Just kidding
Fist copy the imported model
Seconds copy all objects
Finally copy the requrements and the Distributor folder
Enjoy...
//TESH.scrollpos=132
//TESH.alwaysfold=0
scope Distributor
//*****************************************************************
//
//  CONFIGURES
//
//*****************************************************************
    globals
//*****************************************************************
//
// Determine the ability id of Life Distributor
//
//*****************************************************************
        private constant integer    ABI_LIFE  = 'A000'
//*****************************************************************
//
// Determine the ability id if Mana Distributor
//
//*****************************************************************
        private constant integer    ABI_MANA  = 'A001'
//*****************************************************************
//
//  Determine the unit type id of dummy
//      Note: Make sure to import the dummy model
//
//*****************************************************************
        private constant integer    DUMMY_ID  = 'u000'
//*****************************************************************
//
//  Determine the ball life time of ball after contributing
//  state of enemies
//
//*****************************************************************
        private constant real       BALL_TIME = 30.0
//*****************************************************************
//
//  Determine the base amount of contribution
//
//*****************************************************************
        private constant real       DIST_AMT  = 5.0
//*****************************************************************
//
//  Determine the additional amount of contribution
//      -Max 100 being rate by casters int
//
//*****************************************************************
        private constant real       DIST_INT  = 3.25
//*****************************************************************
//
//  Determine the duration of state contribution
//
//*****************************************************************
        private constant real       DURATION  = 10.0
//*****************************************************************
//
//  Determine the constant height of ball at contributing
//
//*****************************************************************
        private constant real       HEIGHT    = 50.0
//*****************************************************************
//
//  Determine the travel distance at caster position
//
//*****************************************************************
        private constant real       RANGE     = 600.0
//*****************************************************************
//
//  Determine the distance aquired of constributing
//
//*****************************************************************
        private constant real       AOE       = 50.0
//*****************************************************************
//
//  Determine the speed of ball
//      -Basing to range
//      -100 Max,could be heigher but plays unpleasing
//
//*****************************************************************
        private constant real       SPEED     = 2.0
//*****************************************************************
//
//  Determine the model of life ball
//
//*****************************************************************
        private constant string     LIFE_MODEL= "Abilities\\Weapons\\BloodElfMissile\\BloodElfMissile.mdl"
//*****************************************************************
//
//  Determine the model of mana ball
//
//*****************************************************************
        private constant string     MANA_MODEL= "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
//*****************************************************************
//
//  Determine the effect of life collisions
//
//*****************************************************************
        private constant string     LIFE_HIT  = "Abilities\\Spells\\Human\\Feedback\\SpellBreakerAttack.mdl"
//*****************************************************************
//
//  Determine the effect mana collisions
//
//*****************************************************************
        private constant string     MANA_HIT  = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
//*****************************************************************
//
//  Determine the location of model attachment
//
//*****************************************************************
        private constant string     ATTACH    = "origin"
//*****************************************************************
//
//  Determine the attack type of life contributing
//
//*****************************************************************
        private constant attacktype ATK_TYPE  = ATTACK_TYPE_MAGIC
//*****************************************************************
//
//  Determine the damage type of life contributing
//
//*****************************************************************
        private constant damagetype DMG_TYPE  = DAMAGE_TYPE_NORMAL
//*****************************************************************
//
//  The followings are not configureable
//
//*****************************************************************
        private constant player     OWNER     = Player(PLAYER_NEUTRAL_PASSIVE)
   
        private constant real       PERIODIC  = 0.0312500
       
        private constant integer    LIFE_TYPE = 1
       
        private constant integer    MANA_TYPE = 2
       
    endglobals
   
    constant native UnitAlive takes unit id returns boolean
   
    private function Filters takes unit t returns boolean
        return UnitAlive(t) and not IsUnitType(t,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(t,UNIT_TYPE_STRUCTURE)
    endfunction
   
    private function DistanceBetweenXY takes real x1,real y1,real x2,real y2 returns real
        local real dx=x2-x1
        local real dy=y2-y1
        return dx*dx+dy*dy
    endfunction
   
    struct DISTRIBUTOR_dummy//DISTRIBUTOR_ to prevent conflictions because the struct is not privatize
        static constant hashtable hash=InitHashtable()
        private static constant timer tmr = CreateTimer()
        private static integer ix         = 0
        private static integer array ic
        private unit dummy
        private unit target
        private real dur
        private real dist
        private real rate
        private real deg
        private real degc
        private real speed
        private real z
        private boolean bol
        private static method Death takes nothing returns nothing
            local unit u=GetTriggerUnit()
            local integer id=GetHandleId(u)
            if GetUnitTypeId(u)==DUMMY_ID and IsUnitInGroup(u,LoadGroupHandle(hash,GetHandleId(LoadUnitHandle(hash,id,1)),0)) then
                call DestroyEffect(LoadEffectHandle(hash,id,0))
                call SaveEffectHandle(hash,id,0,null)
                call SaveUnitHandle(hash,id,1,null)
                call SaveBoolean(hash,id,0,false)
                call RemoveSavedHandle(hash,id,0)
                call RemoveSavedHandle(hash,id,1)
                call RemoveSavedBoolean(hash,id,0)
            endif
            set u=null
        endmethod
        private static method Loop takes nothing returns nothing
            local thistype this
            local integer i= 1
            local real xd
            local real yd
            local real x
            local real y
            local real z
            local real r
            local integer id
            loop
                exitwhen i>ix
                set this   = ic[i]
                set id     = GetHandleId(dummy)
                set z      = .z
                if dur>0.0 then
                    if target!=null and UnitAlive(target) then
                        set x      = GetUnitX(target)-(dist/2.0)*Cos(deg*bj_DEGTORAD)
                        set y      = GetUnitY(target)-(dist/2.0)*Sin(deg*bj_DEGTORAD)
                        set dur    = dur-PERIODIC
                        if rate>=180.0 then
                            set rate=0
                            if bol then
                                set bol=false
                            else
                                set bol=true
                            endif
                        else
                            set rate=rate+(180.0/dist)*speed
                            if bol then
                                set r=(dist/180.0)*(180.0-rate)
                            else
                                set r=(dist/180.0)*rate
                            endif
                        endif
                        set x  = x+r*Cos(deg*bj_DEGTORAD)
                        set y  = y+r*Sin(deg*bj_DEGTORAD)
                        set x  = x+(Sin((rate*2.0)*bj_DEGTORAD)*(dist/2.0))*Cos((deg+degc)*bj_DEGTORAD)
                        set y  = y+(Sin((rate*2.0)*bj_DEGTORAD)*(dist/2.0))*Sin((deg+degc)*bj_DEGTORAD)
                        call SetUnitX(dummy,x)
                        call SetUnitY(dummy,y)
                        call SetUnitFlyHeight(dummy,z,0.0)
                    else
                        set target=LoadUnitHandle(hash,id,1)
                        set x=GetUnitX(target)
                        set y=GetUnitY(target)
                        set xd=GetUnitX(dummy)
                        set yd=GetUnitY(dummy)
                        call SetUnitFlyHeight(dummy,z,0.0)
                        set r=DistanceBetweenXY(x,y,xd,yd)
                        if r>((dist*dist)/2.0) then
                            set deg=bj_RADTODEG*Atan2(y-yd,x-xd)
                        elseif r<((dist*dist)/2.0) then
                            set deg=bj_RADTODEG*Atan2(yd-y,xd-x)
                        endif
                        if UnitAlive(target) then
                            set xd=xd+speed*Cos(deg*bj_DEGTORAD)
                            set yd=yd+speed*Sin(deg*bj_DEGTORAD)
                            call SetUnitX(dummy,xd)
                            call SetUnitY(dummy,yd)
                            set rate=0.0
                            if deg<=0.0 then
                                set deg=deg+360.0
                            endif
                            if r>(dist/2.0) then
                                set r=r-(dist/2.0)
                            else
                                set r=(dist/2.0)-r
                            endif
                            if r>speed then
                                set target=null
                            endif
                        else
                            set dur=0.0
                        endif
                    endif
                else
                    call UnitApplyTimedLife(.dummy,'BTLF',BALL_TIME)
                    call SaveBoolean(hash,id,0,true)
                    set dummy=null
                    set target=null
                    call deallocate()
                    set ic[i]=ic[ix]
                    set ix=ix-1
                    set i=i-1
                    if ix==0 then
                        call PauseTimer(tmr)
                    endif
                endif
                set i=i+1
            endloop
        endmethod
        static method Add takes unit dum,string fx,unit target,real dist,real speed,real deg,real z,real dur,boolean bol,boolean left returns unit
            local thistype this
            local unit u   = null
            local integer id
            set this   = allocate()
            set ix     = ix + 1
            set ic[ix] = this
            set .z     = z
            set .bol   = bol
            set .deg   = deg
            set .dur   = dur
            set .rate  = 0.0
            set .dist  = dist
            set .speed = (dist/100.0)*speed
            set .target= target
            if left then
                set .degc=90.0
            else
                set .degc=-90.0
            endif
            if dum==null then
                set UnitIndexerStop=true
                set .dummy=CreateUnit(OWNER,DUMMY_ID,GetUnitX(target),GetUnitY(target),0.0)
                set UnitIndexerStop=false
                set u=.dummy
                set id=GetHandleId(u)
                call SaveBoolean(hash,id,0,false)
                call UnitAddAbility(u,'Amrf')
                call UnitRemoveAbility(u,'Amrf')
                call SaveEffectHandle(hash,id,0,AddSpecialEffectTarget(fx,.dummy,ATTACH))
            else
                set .dummy=dum
                set id=GetHandleId(dum)
                call SaveBoolean(hash,id,0,false)
            endif
            if ix==1 then
                call TimerStart(tmr,PERIODIC,true,function thistype.Loop)
            endif
            return u
        endmethod
        private static method onInit takes nothing returns nothing
            call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH,function thistype.Death)
        endmethod
    endstruct
    private struct createballs
        private static constant timer tmr = CreateTimer()
        private static constant group grp = CreateGroup()
        private static integer ix=0
        private static integer array ic
        private unit dummy
        private unit caster
        private player owner
        private integer dtype
        private real distribute
        private static method onLoop takes nothing returns nothing
            local thistype this
            local integer i=1
            local real x
            local real y
            local unit t
            local real amt
            local real dist
            local real state
            local boolean ally
            loop
                exitwhen i>ix
                set this=ic[i]
                if not LoadBoolean(DISTRIBUTOR_dummy.hash,GetHandleId(.dummy),0) then
                    set x=GetUnitX(.dummy)
                    set y=GetUnitY(.dummy)
                    if IsUnitType(.caster,UNIT_TYPE_HERO) then
                        set amt=DIST_AMT+((GetHeroInt(.caster,true)/100.0)*DIST_INT)
                    else
                        set amt=DIST_AMT
                    endif
                    call GroupEnumUnitsInRange(grp,x,y,AOE,null)
                    loop
                        set t=FirstOfGroup(grp)
                        exitwhen t==null
                        if Filters(t) and GetUnitTypeId(t)!=DUMMY_ID then
                            set ally=IsUnitAlly(t,.owner)
                            if .dtype==LIFE_TYPE then
                                set state=GetWidgetLife(t)
                                if ally then
                                    call SetWidgetLife(t,state+distribute)
                                    set distribute=0.0
                                else
                                    call UnitDamageTarget(.caster,t,amt,true,true,ATK_TYPE,DMG_TYPE,null)
                                    set distribute=distribute+amt
                                endif
                                if GetWidgetLife(t)!=state then
                                    call DestroyEffect(AddSpecialEffectTarget(LIFE_HIT,t,ATTACH))
                                endif
                            elseif .dtype==MANA_TYPE then
                                set state=GetUnitState(t,UNIT_STATE_MANA)
                                if ally then
                                    call SetUnitState(t,UNIT_STATE_MANA,state+distribute)
                                    set distribute=0.0
                                else
                                    if state>0.0 then
                                        call SetUnitState(t,UNIT_STATE_MANA,state-amt)
                                        set distribute=distribute+amt
                                    endif
                                endif
                                if GetUnitState(t,UNIT_STATE_MANA)!=state then
                                    call DestroyEffect(AddSpecialEffectTarget(MANA_HIT,t,ATTACH))
                                endif
                            endif
                        endif
                        call GroupRemoveUnit(grp,t)
                    endloop
                    call GroupClear(grp)
                else
                    set .dummy=null
                    set .caster=null
                    set .owner=null
                    call deallocate()
                    set ic[i]=ic[ix]
                    set ix=ix-1
                    set i=i-1
                    if ix==0 then
                        call PauseTimer(tmr)
                    endif
                endif
                set i=i+1
            endloop
        endmethod
        private static method onCast takes nothing returns nothing
            local integer abi=GetSpellAbilityId()
            local thistype this
            local string fx
            if abi==ABI_LIFE or abi==ABI_MANA then
                set this=allocate()
                set ix=ix+1
                set ic[ix]=this
                set .caster=GetTriggerUnit()
                set .owner=GetOwningPlayer(.caster)
                if abi==ABI_LIFE then
                    set fx=LIFE_MODEL
                    set .dtype=LIFE_TYPE
                else
                    set fx=MANA_MODEL
                    set .dtype=MANA_TYPE
                endif
                if GetRandomInt(1,100)>50 then
                    set .dummy=DISTRIBUTOR_dummy.Add(null,fx,GetSpellTargetUnit(),RANGE,SPEED,GetRandomReal(0,360),HEIGHT,DURATION,false,true)
                else
                    set .dummy=DISTRIBUTOR_dummy.Add(null,fx,GetSpellTargetUnit(),RANGE,SPEED,GetRandomReal(0,360),HEIGHT,DURATION,true,false)
                endif
                set .distribute=0.0
                set abi=GetHandleId(.dummy)
                call SaveInteger(DISTRIBUTOR_dummy.hash,abi,0,.dtype)
                call SaveUnitHandle(DISTRIBUTOR_dummy.hash,abi,1,.caster)
                set abi=GetHandleId(.caster)
                if not HaveSavedHandle(DISTRIBUTOR_dummy.hash,abi,0) then
                    call SaveGroupHandle(DISTRIBUTOR_dummy.hash,abi,0,CreateGroup())
                endif
                call GroupAddUnit(LoadGroupHandle(DISTRIBUTOR_dummy.hash,abi,0),.dummy)
                if ix==1 then
                    call TimerStart(tmr,PERIODIC,true,function thistype.onLoop)
                endif
            endif
        endmethod
        private static method onInit takes nothing returns nothing
            call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
        endmethod
    endstruct
endscope
//TESH.scrollpos=292
//TESH.alwaysfold=0
scope DistributorSlam
    globals
//*****************************************************************
//
//  Determine the ability id of distributor slam
//
//*****************************************************************
        private constant integer ABILITY_ID   = 'A002'
//*****************************************************************
//
//  Determine the model of life ball
//
//*****************************************************************
        private constant string     LIFE_MODEL  = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
//*****************************************************************
//
//  Determine the model of mana ball
//
//*****************************************************************
        private constant string     MANA_MODEL  = "Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl"
//*****************************************************************
//
//  Determine the effect of life slam
//
//*****************************************************************
        private constant string     LIFE_SLAM   = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
//*****************************************************************
//
//  Determine the effect of mana slam
//
//*****************************************************************
        private constant string     MANA_SLAM   = "Objects\\Spawnmodels\\NightElf\\NEDeathSmall\\NEDeathSmall.mdl"
//*****************************************************************
//
//  Determine the location of model attachment
//
//*****************************************************************
        private constant string     ATTACH    = "origin"
//*****************************************************************
//
//  Determine the attack type of life slam
//
//*****************************************************************
        private constant attacktype ATK_TYPE  = ATTACK_TYPE_MAGIC
//*****************************************************************
//
//  Determine the damage type of life slam
//
//*****************************************************************
        private constant damagetype DMG_TYPE  = DAMAGE_TYPE_NORMAL
//*****************************************************************
//
//  Determine the range of ball search
//
//*****************************************************************
        private constant real       SEARCH    = 600.0
//*****************************************************************
//
//  Determine the damage base amount of life ball
//
//*****************************************************************
        private constant real       DMG_LIFE  = 75
//*****************************************************************
//
//  Determine the damage base amount of mana ball
//
//*****************************************************************
        private constant real       DMG_MANA  = 75
//*****************************************************************
//
//  Determine the damage level amount of life ball
//
//*****************************************************************
        private constant real       DMG_LIFELV= 25
//*****************************************************************
//
//  Determine the damage level amount of mana ball
//
//*****************************************************************
        private constant real       DMG_MANALV= 25
//*****************************************************************
//
//  Determine the int percent amount damage will be
//
//*****************************************************************
        private constant real       DMG_INT   = 3.50
//*****************************************************************
//
//  Determine the life affect of area damage
//
//*****************************************************************
        private constant real       AOE       = 200.0
//*****************************************************************
//
//  Determine the raise height of balls
//
//*****************************************************************
        private constant real       Z_RAISE   = 600.0
//*****************************************************************
//
//  Determine the travel duration to Z Raise
//
//*****************************************************************
        private constant real       TRAVEL_DUR= 2.0
//*****************************************************************
//
//  Determine the travel duration to target area
//
//*****************************************************************
        private constant real       SLAM_DUR  = 0.50
//*****************************************************************
//
//  Determine the travel duration to target area
//
//*****************************************************************
        private constant real       SLAM_INTER= 0.25
//*****************************************************************
//
//  Determine the arc speed of ball
//
//*****************************************************************
        private constant real       ARC_SPEED = 15.0
//*****************************************************************
//
//  Determine the airburn height to enemy exploded of life explotion
//
//*****************************************************************
        private constant real       AIR_BURN  = 300.0
//*****************************************************************
//
//  Determine the slow amount of mana explotion
//
//*****************************************************************
        private constant real       SLOW_AMT  = 250.0
//*****************************************************************
//
//  Determine the slow duration
//
//*****************************************************************
        private constant real       SLOW_DUR  = 2.0
//*****************************************************************
//
//  The followings are not configureable
//
//*****************************************************************
        private constant real       PERIODIC  = 0.0312500
    endglobals
    private function Filters takes unit t returns boolean
        return UnitAlive(t) and not IsUnitType(t,UNIT_TYPE_MAGIC_IMMUNE)
    endfunction
    private function DistanceBetweenXY takes real x1,real y1,real x2,real y2 returns real
        local real dx=x2-x1
        local real dy=y2-y1
        return SquareRoot(dx*dx+dy*dy)
    endfunction
    private struct slam_cast
        private static constant timer tmr=CreateTimer()
        private static constant group grp=CreateGroup()
        private static integer ix=0
        private static integer array ic
        private unit caster
        private unit dummy
        private player owner
        private real dspeed
        private real tspeed
        private real zspeed
        private real distc
        private real distt
        private real xc
        private real yc
        private real xt
        private real yt
        private real arnd
        private real dmg
        private string fx
        private static method AddGroup takes nothing returns nothing
            call GroupAddUnit(grp, GetEnumUnit())
        endmethod
        private static method onLoop takes nothing returns nothing
            local thistype this
            local integer i=1
            local real x
            local real y
            local real a
            local integer id
            local unit t
            loop
                exitwhen i>ix
                set this=ic[i]
                set id=GetHandleId(dummy)
                if not LoadBoolean(DISTRIBUTOR_dummy.hash,id,0) then
                    if distc>0.0 then
                        set distc=distc-dspeed
                        set x=GetUnitX(dummy)
                        set y=GetUnitY(dummy)
                        set a=bj_RADTODEG*Atan2(yc-y,xc-x)
                        set x=x+dspeed*Cos(a*bj_DEGTORAD)
                        set y=y+dspeed*Sin(a*bj_DEGTORAD)
                        set x=x+ARC_SPEED*Cos((a+arnd)*bj_DEGTORAD)
                        set y=y+ARC_SPEED*Sin((a+arnd)*bj_DEGTORAD)
                        call SetUnitX(dummy,x)
                        call SetUnitY(dummy,y)
                        call SetUnitFlyHeight(dummy,GetUnitFlyHeight(dummy)+zspeed,0.0)
                        if distc<=0.0 then
                            call DestroyEffect(LoadEffectHandle(DISTRIBUTOR_dummy.hash,id,0))
                            if LoadInteger(DISTRIBUTOR_dummy.hash,id,0)==1 then
                                call SaveEffectHandle(DISTRIBUTOR_dummy.hash,id,0,AddSpecialEffectTarget(LIFE_MODEL,dummy,ATTACH))
                            else
                                call SaveEffectHandle(DISTRIBUTOR_dummy.hash,id,0,AddSpecialEffectTarget(MANA_MODEL,dummy,ATTACH))
                            endif
                            set zspeed=Z_RAISE/(((distt/tspeed)*PERIODIC)/PERIODIC)
                        endif
                    elseif distt>0.0 then
                        set distt=distt-tspeed
                        set x=GetUnitX(dummy)
                        set y=GetUnitY(dummy)
                        set a=bj_RADTODEG*Atan2(yt-y,xt-x)
                        set x=x+tspeed*Cos(a*bj_DEGTORAD)
                        set y=y+tspeed*Sin(a*bj_DEGTORAD)
                        //set x=x+ARC_SPEED*Cos((a+arnd)*bj_DEGTORAD)
                        //set y=y+ARC_SPEED*Sin((a+arnd)*bj_DEGTORAD)
                        call SetUnitX(dummy,x)
                        call SetUnitY(dummy,y)
                        call SetUnitFlyHeight(dummy,GetUnitFlyHeight(dummy)-zspeed,0.0)
                        if distt<=0 then
                            call SaveBoolean(DISTRIBUTOR_dummy.hash,id,0,true)
                            call DestroyEffect(LoadEffectHandle(DISTRIBUTOR_dummy.hash,id,0))
                            set id=LoadInteger(DISTRIBUTOR_dummy.hash,id,0)
                            call GroupEnumUnitsInRange(grp,x,y,AOE,null)
                            loop
                                set t=FirstOfGroup(grp)
                                exitwhen t==null
                                if Filters(t) and not IsUnitAlly(t,owner) then
                                    call UnitDamageTarget(caster,t,dmg,true,true,ATK_TYPE,DMG_TYPE,null)
                                    if id==1 then
                                        if GetUnitFlyHeight(t)<(AIR_BURN/4.0) then
                                            call AirBurn.exe(t,AIR_BURN)
                                        endif
                                    else
                                        call Slow.Add(t,SLOW_AMT,SLOW_DUR,false)
                                    endif
                                endif
                                call GroupRemoveUnit(grp,t)
                            endloop
                            call GroupClear(grp)
                            call DestroyEffect(AddSpecialEffect(fx,x,y))
                            call KillUnit(dummy)
                        endif
                    endif
                else
                    set caster=null
                    set dummy=null
                    set owner=null
                    call deallocate()
                    set ic[i]=ic[ix]
                    set ix=ix-1
                    set i=i-1
                    if ix==0 then
                        call PauseTimer(tmr)
                    endif
                endif
                set i=i+1
            endloop
            set t=null
        endmethod
        private static method onCast takes nothing returns nothing
            local thistype this
            local unit u
            local unit d
            local real x1
            local real y1
            local real x2
            local real y2
            local real xt
            local real yt
            local real dist
            local real dur
            local player p
            local integer lv
            local integer id
           
            set u=GetTriggerUnit()
            set x1=GetUnitX(u)
            set y1=GetUnitY(u)
            set xt=GetSpellTargetX()
            set yt=GetSpellTargetY()
            set lv=GetUnitAbilityLevel(u,ABILITY_ID)
            set id=GetHandleId(u)
            call ForGroup(LoadGroupHandle(DISTRIBUTOR_dummy.hash,id,0),function thistype.AddGroup)
            set dur=0
            set p=GetOwningPlayer(u)
            loop
                set d=FirstOfGroup(grp)
                exitwhen d==null
                set id=GetHandleId(d)
                set x2=GetUnitX(d)
                set y2=GetUnitY(d)
                set dist=DistanceBetweenXY(x2,y2,x1,y1)
                if UnitAlive(d) and LoadBoolean(DISTRIBUTOR_dummy.hash,id,0) and dist<=SEARCH then
                    set this=allocate()
                    set ix=ix+1
                    set ic[ix]=this
                    set caster=u
                    set dummy=d
                    set owner=p
                    set xc=x1
                    set yc=y1
                    set distc=dist
                    set dist=GetRandomReal(-AOE,AOE)
                    set .xt=xt+dist*Cos(GetRandomReal(0,360)*bj_DEGTORAD)
                    set .yt=yt+dist*Sin(GetRandomReal(0,360)*bj_DEGTORAD)
                    set dur=dur+SLAM_INTER
                    set distt=DistanceBetweenXY(x1,y1,xt,yt)
                    set dspeed=distc/(TRAVEL_DUR/PERIODIC)
                    set tspeed=distt/(SLAM_DUR+dur/PERIODIC)
                    set zspeed=Z_RAISE/(TRAVEL_DUR/PERIODIC)
                    if GetRandomInt(1,100)>50 then
                        set arnd=90
                    else
                        set arnd=-90
                    endif
                    if IsUnitType(caster,UNIT_TYPE_HERO) then
                        set dmg=(GetHeroInt(caster,true)/100.0)*DMG_INT
                    else
                        set dmg=0.0
                    endif
                    if LoadInteger(DISTRIBUTOR_dummy.hash,id,0)==1 then
                        set dmg=dmg+(DMG_LIFE+(DMG_LIFELV*lv))
                        set fx=LIFE_SLAM
                    else
                        set dmg=dmg+(DMG_MANA+(DMG_MANALV*lv))
                        set fx=MANA_SLAM
                    endif
                    call UnitAddAbility(d,'Amrf')
                    call UnitRemoveAbility(d,'Amrf')
                    call SaveBoolean(DISTRIBUTOR_dummy.hash,id,0,false)
                    if ix==1 then
                        call TimerStart(tmr,PERIODIC,true,function thistype.onLoop)
                    endif
                endif
                call GroupRemoveUnit(grp,d)
            endloop
            call GroupClear(grp)
            set u=null
            set d=null
            set p=null
        endmethod
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(ABILITY_ID,function thistype.onCast)
        endmethod
    endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope DistributorSlingShot
    globals
//*****************************************************************
//
//  Determine the ability id of distributor slingshot
//
//*****************************************************************
        private constant integer  ABILITY_ID    = 'A003'
//*****************************************************************
//
//  Determine the model of life ball
//
//*****************************************************************
        private constant string     LIFE_MODEL  = "Abilities\\Weapons\\KeeperGroveMissile\\KeeperGroveMissile.mdl"
//*****************************************************************
//
//  Determine the model of mana ball
//
//*****************************************************************
        private constant string     MANA_MODEL  = "Abilities\\Weapons\\BlackKeeperMissile\\BlackKeeperMissile.mdl"
//*****************************************************************
//
//  Determine the effect of life slam
//
//*****************************************************************
        private constant string     LIFE_HIT    = "Abilities\\Spells\\Undead\\ReplenishHealth\\ReplenishHealthCaster.mdl"
//*****************************************************************
//
//  Determine the effect of mana slam
//
//*****************************************************************
        private constant string     MANA_HIT    = "Abilities\\Spells\\Undead\\ReplenishMana\\ReplenishManaCaster.mdl"
//*****************************************************************
//
//  Determine the location of model attachment
//
//*****************************************************************
        private constant string     ATTACH      = "origin"
//*****************************************************************
//
//  Determine the attack type of life slingshot
//
//*****************************************************************
        private constant attacktype ATK_TYPE    = ATTACK_TYPE_MAGIC
//*****************************************************************
//
//  Determine the damage type of life slingshot
//
//*****************************************************************
        private constant damagetype DMG_TYPE    = DAMAGE_TYPE_NORMAL
//*****************************************************************
//
//  Determine the range of ball search
//
//*****************************************************************
        private constant real       SEARCH      = 600.0
//*****************************************************************
//
//  Determine the damage base amount of life ball
//
//*****************************************************************
        private constant real       DMG_LIFE    = 50
//*****************************************************************
//
//  Determine the damage base amount of mana ball
//
//*****************************************************************
        private constant real       DMG_MANA    = 50
//*****************************************************************
//
//  Determine the damage level amount of life ball
//
//*****************************************************************
        private constant real       DMG_LIFELV  = 25
//*****************************************************************
//
//  Determine the damage level amount of mana ball
//
//*****************************************************************
        private constant real       DMG_MANALV  = 25
//*****************************************************************
//
//  Determine the int percent amount damage will be
//
//*****************************************************************
        private constant real       DMG_INT     = 8.0
//*****************************************************************
//
//  Determine the life affect of area damage
//
//*****************************************************************
        private constant real       AOE         = 64.0
//*****************************************************************
//
//  Determine the duration dummy before travel
//
//*****************************************************************
        private constant real       READY_DUR   = 0.75
//*****************************************************************
//
//  Determine the interval of each travels
//
//*****************************************************************
        private constant real       INTERVAL    = 0.125
//*****************************************************************
//
//  Determine the ready speed. must slow so it will look cooler
//
//*****************************************************************
        private constant real       RED_SPED    = 2.0
//*****************************************************************
//
//  Determine the travel speed
//
//*****************************************************************
        private constant real       SPEED       = 50.0
//*****************************************************************
//
//  Determine the penetrate distance
//
//*****************************************************************
        private constant real       PEN_DIST    = 600.0
//*****************************************************************
//
//  Determine the knockback distance
//
//*****************************************************************
        private constant real       KNOCK_BACK  = 10.0
//*****************************************************************
//
//  Determine the height of ball
//
//*****************************************************************
        private constant real       HEIGHT      = 50.0
//*****************************************************************
//
//  The followings are not configureable
//
//*****************************************************************
        private constant real       PERIODIC    = 0.0312500
    endglobals
    private function Filters takes unit t returns boolean
        return UnitAlive(t) and not IsUnitType(t,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(t,UNIT_TYPE_STRUCTURE)
    endfunction
    private function DistanceBetweenXY takes real x1,real y1,real x2,real y2 returns real
        local real dx=x2-x1
        local real dy=y2-y1
        return SquareRoot(dx*dx+dy*dy)
    endfunction
    private struct slingshot_cast
        private static constant timer tmr=CreateTimer()
        private static constant group grp=CreateGroup()
        private static integer ix=0
        private static integer array ic
        private unit caster
        private unit target
        private unit dummy
        private real dmg
        private real interval
        private real dist
        private group grup
        private player owner
        private string fx
        private static method AddGroup takes nothing returns nothing
            call GroupAddUnit(grp, GetEnumUnit())
        endmethod
        private static method onLoop takes nothing returns nothing
            local thistype this
            local integer i=1
            local real x1
            local real y1
            local real x2
            local real y2
            local real a
            local integer id
            loop
                exitwhen i>ix
                set this=ic[i]
                set x1=GetUnitX(dummy)
                set y1=GetUnitY(dummy)
                set id=GetHandleId(dummy)
                call SetUnitFlyHeight(dummy,HEIGHT,0.0)
                if not LoadBoolean(DISTRIBUTOR_dummy.hash,id,0) then
                    if interval>0.0 then
                        set interval=interval-PERIODIC
                        set x2=GetUnitX(target)
                        set y2=GetUnitY(target)
                        set a=bj_RADTODEG*Atan2(y2-y1,x2-x1)
                        set x1=x1-RED_SPED*Cos(a*bj_DEGTORAD)
                        set y1=y1-RED_SPED*Sin(a*bj_DEGTORAD)
                        call SetUnitX(dummy,x1)
                        call SetUnitY(dummy,y1)
                        call SetUnitFacing(dummy,a)
                        if interval<=0.0 then
                            set dist=dist+DistanceBetweenXY(x1,y1,x2,y2)
                            call DestroyEffect(LoadEffectHandle(DISTRIBUTOR_dummy.hash,id,0))
                            if LoadInteger(DISTRIBUTOR_dummy.hash,id,0)==1 then
                                call SaveEffectHandle(DISTRIBUTOR_dummy.hash,id,0,AddSpecialEffectTarget(LIFE_MODEL,dummy,ATTACH))
                            else
                                call SaveEffectHandle(DISTRIBUTOR_dummy.hash,id,0,AddSpecialEffectTarget(MANA_MODEL,dummy,ATTACH))
                            endif
                        endif
                    elseif dist>0.0 then
                        set dist=dist-SPEED
                        set a=GetUnitFacing(dummy)
                        set x1=x1+SPEED*Cos(a*bj_DEGTORAD)
                        set y1=y1+SPEED*Sin(a*bj_DEGTORAD)
                        call SetUnitX(dummy,x1)
                        call SetUnitY(dummy,y1)
                        call GroupEnumUnitsInRange(grp,x1,y1,AOE,null)
                        loop
                            set target=FirstOfGroup(grp)
                            exitwhen target==null
                            if Filters(target) and not IsUnitAlly(target,owner) and not IsUnitInGroup(target,grup) then
                                call GroupAddUnit(grup,target)
                                call UnitDamageTarget(caster,target,dmg,true,true,ATK_TYPE,DMG_TYPE,null)
                                call SetUnitX(target,GetUnitX(target)+KNOCK_BACK*Cos(a*bj_DEGTORAD))
                                call SetUnitY(target,GetUnitY(target)+KNOCK_BACK*Sin(a*bj_DEGTORAD))
                                call AddSpecialEffectTarget(fx,target,ATTACH)
                            endif
                            call GroupRemoveUnit(grp,target)
                        endloop
                        call GroupClear(grp)
                        if dist<=0.0 then
                            call SaveBoolean(DISTRIBUTOR_dummy.hash,id,0,true)
                            call DestroyEffect(LoadEffectHandle(DISTRIBUTOR_dummy.hash,id,0))
                            call KillUnit(dummy)
                        endif
                    endif
                else
                    set caster=null
                    set target=null
                    set dummy=null
                    set owner=null
                    call GroupClear(grup)
                    call deallocate()
                    set ic[i]=ic[ix]
                    set ix=ix-1
                    set i=i-1
                    if ix==0 then
                        call PauseTimer(tmr)
                    endif
                endif
                set i=i+1
            endloop
        endmethod
        private static method onCast takes nothing returns nothing
            local thistype this
            local unit u
            local unit t
            local unit d
            local real x1
            local real y1
            local real x2
            local real y2
            local real dur
            local real dist
            local integer lv
            local integer id
            local player p
            set u=GetTriggerUnit()
            set t=GetSpellTargetUnit()
            set x1=GetUnitX(u)
            set y1=GetUnitY(u)
            set lv=GetUnitAbilityLevel(u,ABILITY_ID)
            set id=GetHandleId(u)
            set p=GetOwningPlayer(u)
            set dur=0
            call ForGroup(LoadGroupHandle(DISTRIBUTOR_dummy.hash,id,0),function thistype.AddGroup)
            loop
                set d=FirstOfGroup(grp)
                exitwhen d==null
                set id=GetHandleId(d)
                set x2=GetUnitX(d)
                set y2=GetUnitY(d)
                set dist=DistanceBetweenXY(x2,y2,x1,y1)
                if UnitAlive(d) and LoadBoolean(DISTRIBUTOR_dummy.hash,id,0) and dist<=SEARCH then
                    set this=allocate()
                    set ix=ix+1
                    set ic[ix]=this
                    set caster=u
                    set target=t
                    set dummy=d
                    set owner=p
                    set .dist=PEN_DIST
                    set dur=dur+INTERVAL
                    set interval=READY_DUR+dur
                    if grup==null then
                        set grup=CreateGroup()
                    else
                        call GroupClear(grup)
                    endif
                    if IsUnitType(caster,UNIT_TYPE_HERO) then
                        set dmg=(GetHeroInt(caster,true)/100.0)*DMG_INT
                    else
                        set dmg=0.0
                    endif
                    if LoadInteger(DISTRIBUTOR_dummy.hash,id,0)==1 then
                        set dmg=dmg+(DMG_LIFE+(DMG_LIFELV*lv))
                        set fx=LIFE_HIT
                    else
                        set dmg=dmg+(DMG_MANA+(DMG_MANALV*lv))
                        set fx=MANA_HIT
                    endif
                    call UnitAddAbility(d,'Amrf')
                    call UnitRemoveAbility(d,'Amrf')
                    call SaveBoolean(DISTRIBUTOR_dummy.hash,id,0,false)
                    if ix==1 then
                        call TimerStart(tmr,PERIODIC,true,function thistype.onLoop)
                    endif
                endif
                call GroupRemoveUnit(grp,d)
            endloop
            call GroupClear(grp)
        endmethod
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(ABILITY_ID,function thistype.onCast)
        endmethod
    endstruct
endscope
 
//TESH.scrollpos=42
//TESH.alwaysfold=0
scope DistributorDragon
    globals
//*****************************************************************
//
//  Determine the ability id of distributor dragon
//
//*****************************************************************
        private constant integer  ABILITY_ID    = 'A004'
//*****************************************************************
//
//  Determine the unit type id of dummy
//      Note: Make sure to import the dummy model
//
//*****************************************************************
        private constant integer    DUMMY_ID    = 'u000'
//*****************************************************************
//
//  Determine the model of life dragon
//
//*****************************************************************
        private constant integer  LIFE_DRAGON   = 'nrwm'
//*****************************************************************
//
//  Determine the model of mana dragon
//
//*****************************************************************
        private constant integer  MANA_DRAGON   = 'nadr'
//*****************************************************************
//
//  Determine the model of life ball
//
//*****************************************************************
        private constant string     LIFE_MODEL  = "Abilities\\Spells\\Undead\\UnholyAura\\UnholyAura.mdl"
//*****************************************************************
//
//  Determine the model of mana ball
//
//*****************************************************************
        private constant string     MANA_MODEL  = "Abilities\\Spells\\Undead\\VampiricAura\\VampiricAura.mdl"
//*****************************************************************
//
//  Determine the location of model attachment
//
//*****************************************************************
        private constant string     ATTACH      = "origin"
//*****************************************************************
//
//  Determine the range of ball search
//
//*****************************************************************
        private constant real       SEARCH      = 600.0
//*****************************************************************
//
//  Determine the interval of hatch
//
//*****************************************************************
        private constant real       HATCH_INTER = 3.0
//*****************************************************************
//
//  Determine the interval of spawning
//
//*****************************************************************
        private constant real       SPAWN_INTER = 1.5
//*****************************************************************
//
//  Determine the duration of dragon
//
//*****************************************************************
        private constant real       DURATION    = 10.0
//*****************************************************************
//
//  Determine the additional duration of each level
//
//*****************************************************************
        private constant real       DURATIONLV  = 5.0
//*****************************************************************
//
//  Determine the max size of spawn effect
//
//*****************************************************************
        private constant real       SPAWN_SCALE = 3.0
//*****************************************************************
//
//  Determine the max size of spawn effect
//
//*****************************************************************
        private constant real       HATCH_SCALE = 30.0
//*****************************************************************
//
//  Determine the max size of dragon
//
//*****************************************************************
        private constant real       DRAGON_SCALE= 1.75
//*****************************************************************
//
//  Determine the effect of life slam
//
//*****************************************************************
        private constant player     OWNER       = Player(PLAYER_NEUTRAL_PASSIVE)
        private constant real       PERIODIC    = 0.0312500
    endglobals
    private function Filters takes unit t returns boolean
        return UnitAlive(t) and not IsUnitType(t,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(t,UNIT_TYPE_STRUCTURE)
    endfunction
    private function DistanceBetweenXY takes real x1,real y1,real x2,real y2 returns real
        local real dx=x2-x1
        local real dy=y2-y1
        return SquareRoot(dx*dx+dy*dy)
    endfunction
    private struct dragon_cast
        private static constant timer tmr=CreateTimer()
        private static constant group grp=CreateGroup()
        private static integer ix=0
        private static integer array ic
        private unit caster
        private unit dummy
        private unit dragon
        private unit spawndummy
        private real spawninterval
        private real hatchinterval
        private real duration
        private player owner
        private effect fx
        private static method AddGroup takes nothing returns nothing
            call GroupAddUnit(grp, GetEnumUnit())
        endmethod
        private static method onLoop takes nothing returns nothing
            local thistype this
            local integer i=1
            local integer id
            local real scale
            local real a
            loop
                exitwhen i>ix
                set this=ic[i]
                set a=GetUnitFacing(dummy)
                set id=GetHandleId(dummy)
                if not LoadBoolean(DISTRIBUTOR_dummy.hash,id,0) then
                    if spawninterval>0.0 then
                        set spawninterval=spawninterval-PERIODIC
                        if hatchinterval<=0.0 then
                            set scale=(SPAWN_SCALE/SPAWN_INTER)*spawninterval
                            call SetUnitFacing(spawndummy,((360.0/SPAWN_INTER)-(SPAWN_INTER-spawninterval))+a)
                            call SetUnitFacing(dragon,((360.0/SPAWN_INTER)-(SPAWN_INTER-spawninterval))+a)
                            set a=(DRAGON_SCALE/SPAWN_INTER)*(SPAWN_INTER-spawninterval)
                            call SetUnitScale(dragon,a,a,a)
                            call SetUnitPosition(dragon,GetUnitX(dummy),GetUnitY(dummy))
                            if spawninterval<=0.0 then
                                call PauseUnit(dragon,false)
                                call UnitApplyTimedLife(dragon,'BTLF',duration)
                                call SaveBoolean(DISTRIBUTOR_dummy.hash,id,0,true)
                                call KillUnit(dummy)
                                call DestroyEffect(fx)
                                call KillUnit(spawndummy)
                            endif
                        else
                            set scale=(SPAWN_SCALE/SPAWN_INTER)*(SPAWN_INTER-spawninterval)
                        endif
                        call SetUnitScale(spawndummy,scale,scale,scale)
                    elseif hatchinterval>0.0 then
                        set hatchinterval=hatchinterval-PERIODIC
                        set scale=(HATCH_SCALE/HATCH_INTER)*(HATCH_INTER-hatchinterval)
                        call SetUnitFacing(spawndummy,((360.0/HATCH_INTER)-(HATCH_INTER-hatchinterval))+a)
                        call SetUnitScale(dummy,scale,scale,scale)
                        if hatchinterval<=0.0 then
                            call DestroyEffect(LoadEffectHandle(DISTRIBUTOR_dummy.hash,id,0))
                            set spawninterval=SPAWN_INTER
                            if LoadInteger(DISTRIBUTOR_dummy.hash,id,0)==1 then
                                set dragon=CreateUnit(owner,LIFE_DRAGON,GetUnitX(dummy),GetUnitY(dummy),a)
                            else
                                set dragon=CreateUnit(owner,MANA_DRAGON,GetUnitX(dummy),GetUnitY(dummy),a)
                            endif
                            call SetUnitScale(dragon,0.10,0.10,0.10)
                            call PauseUnit(dragon,true)
                        endif
                    endif
                else
                    set caster=null
                    set spawndummy=null
                    set dummy=null
                    set owner=null
                    set dragon=null
                    set fx=null
                    call deallocate()
                    set ic[i]=ic[ix]
                    set ix=ix-1
                    set i=i-1
                    if ix==0 then
                        call PauseTimer(tmr)
                    endif
                endif
                set i=i+1
            endloop
        endmethod
        private static method onCast takes nothing returns nothing
            local thistype this
            local unit u
            local unit d
            local real x1
            local real y1
            local real x2
            local real y2
            local integer lv
            local integer id
            local player p
            set u=GetTriggerUnit()
            set x1=GetUnitX(u)
            set y1=GetUnitY(u)
            set lv=GetUnitAbilityLevel(u,ABILITY_ID)
            set id=GetHandleId(u)
            set p=GetOwningPlayer(u)
            call ForGroup(LoadGroupHandle(DISTRIBUTOR_dummy.hash,id,0),function thistype.AddGroup)
            loop
                set d=FirstOfGroup(grp)
                exitwhen d==null
                set id=GetHandleId(d)
                set x2=GetUnitX(d)
                set y2=GetUnitY(d)
                if UnitAlive(d) and LoadBoolean(DISTRIBUTOR_dummy.hash,id,0) and DistanceBetweenXY(x2,y2,x1,y1)<=SEARCH then
                    set this=allocate()
                    set ix=ix+1
                    set ic[ix]=this
                    set caster=u
                    set dummy=d
                    set owner=p
                    set dragon=null
                    set duration=DURATION+(DURATIONLV*lv)
                    set spawninterval=SPAWN_INTER
                    set hatchinterval=HATCH_INTER
                    set spawndummy=CreateUnit(OWNER,DUMMY_ID,x2,y2,GetUnitFacing(dummy))
                    call SetUnitScale(spawndummy,0.10,0.10,0.10)
                    if LoadInteger(DISTRIBUTOR_dummy.hash,id,0)==1 then
                        set fx=AddSpecialEffectTarget(LIFE_MODEL,spawndummy,ATTACH)
                    else
                        set fx=AddSpecialEffectTarget(MANA_MODEL,spawndummy,ATTACH)
                    endif
                    call SaveBoolean(DISTRIBUTOR_dummy.hash,id,0,false)
                    if ix==1 then
                        call TimerStart(tmr,PERIODIC,true,function thistype.onLoop)
                    endif
                endif
                call GroupRemoveUnit(grp,d)
            endloop
            call GroupClear(grp)
        endmethod
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(ABILITY_ID,function thistype.onCast)
        endmethod
    endstruct
endscope
 
//TESH.scrollpos=21
//TESH.alwaysfold=0
scope DistributorReunion
    globals
//*****************************************************************
//
//  Determine the ability id of distributor reunion
//
//*****************************************************************
        private constant integer  ABILITY_ID    = 'A005'
//*****************************************************************
//
//  Determine the speed of ball
//      -Basing to range
//      -100 Max,could be heigher but plays unpleasing
//
//*****************************************************************
        private constant real       SPEED     = 5.0
    endglobals
    private struct reunion_cast extends array
        private static constant group grp=CreateGroup()
        private static method AddGroup takes nothing returns nothing
            call GroupAddUnit(grp, GetEnumUnit())
        endmethod
        private static method onCast takes nothing returns nothing
            local unit u
            local unit d
            local real x1
            local real y1
            local real x2
            local real y2
            local integer id
            set u=GetTriggerUnit()
            set x1=GetUnitX(u)
            set y1=GetUnitY(u)
            set id=GetHandleId(u)
            call ForGroup(LoadGroupHandle(DISTRIBUTOR_dummy.hash,id,0),function thistype.AddGroup)
            loop
                set d=FirstOfGroup(grp)
                exitwhen d==null
                set id=GetHandleId(d)
                if UnitAlive(d) and LoadBoolean(DISTRIBUTOR_dummy.hash,id,0) then
                    set x2=GetUnitX(u)
                    set y2=GetUnitY(u)
                    set y2=bj_RADTODEG*Atan2(y1-y2,x1-x2)
                    if y2<0.0 then
                        set y2=y2+360.0
                    endif
                    call DISTRIBUTOR_dummy.Add(d,"",null,600,SPEED,y2,50.0,1.0,true,false)
                endif
                call GroupRemoveUnit(grp,d)
            endloop
            call GroupClear(grp)
        endmethod
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(ABILITY_ID,function thistype.onCast)
        endmethod
    endstruct
endscope
 
//TESH.scrollpos=57
//TESH.alwaysfold=0
struct test
    private static constant integer Creeps_Amount = 5
    private static constant real Revive_Duration = 2.0
    private static constant real Periodic = 0.031250
    private static constant timer tmr = CreateTimer()
    private static integer ix = 0
    private static integer array ic
    private unit u
    private real d
    private static method onLoop takes nothing returns nothing
        local thistype this
        local integer i=1
        local real x
        local real y
        local real a
        loop
            exitwhen i>ix
            set this=ic[i]
            set d=d-Periodic
            if d<=0.0 then
                set x=GetStartLocationX(0)
                set y=GetStartLocationY(0)
                if IsUnitType(u,UNIT_TYPE_HERO) then
                    call ReviveHero(u,x,y,true)
                else
                    set a=GetRandomReal(0,360)
                    call CreateUnit(GetOwningPlayer(u),GetUnitTypeId(u),x+800*Cos(a*bj_DEGTORAD),y+800*Sin(a*bj_DEGTORAD),a)
                    call RemoveUnit(u)
                endif
                set u=null
                call deallocate()
                set ic[i]=ic[ix]
                set ix=ix-1
                set i=i-1
                if ix==0 then
                    call PauseTimer(tmr)
                endif
            endif
            set i=i+1
        endloop
    endmethod
    private static method onDeath takes nothing returns nothing
        local thistype this
        local unit u=GetTriggerUnit()
        if GetUnitAbilityLevel(u,'Aloc')==0 and not IsUnitType(u,UNIT_TYPE_SUMMONED) then
            set this=allocate()
            set ix=ix+1
            set ic[ix]=this
            set .u=u
            set d=Revive_Duration
            if ix==1 then
                call TimerStart(tmr,Periodic,true,function thistype.onLoop)
            endif
        endif
    endmethod
    private static method onInit takes nothing returns nothing
        local real x=GetStartLocationX(0)
        local real y=GetStartLocationY(0)
        local integer i=1
        local player p=Player(0)
        call CreateUnit(p,'Hblm',x,y,GetRandomReal(0,360))
        call CreateItem('ciri',x,y)
        set p=Player(PLAYER_NEUTRAL_AGGRESSIVE)
        loop
            exitwhen i>Creeps_Amount
            call CreateItem('ciri',x,y)
            call CreateUnit(p,ChooseRandomCreep(GetRandomInt(1,5)),x+800*Cos(0*bj_DEGTORAD),y+800*Sin(0*bj_DEGTORAD),GetRandomReal(1,360))
            call CreateUnit(p,ChooseRandomCreep(GetRandomInt(1,5)),x+800*Cos(90*bj_DEGTORAD),y+800*Sin(90*bj_DEGTORAD),GetRandomReal(1,360))
            call CreateUnit(p,ChooseRandomCreep(GetRandomInt(1,5)),x+800*Cos(180*bj_DEGTORAD),y+800*Sin(180*bj_DEGTORAD),GetRandomReal(1,360))
            call CreateUnit(p,ChooseRandomCreep(GetRandomInt(1,5)),x+800*Cos(270*bj_DEGTORAD),y+800*Sin(270*bj_DEGTORAD),GetRandomReal(1,360))
            set i=i+1
        endloop
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH,function thistype.onDeath)
        set p=null
    endmethod
endstruct