• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Devil Tornado v1.4

  • Like
Reactions: Doomlord
-------------------------------------------
D E V I L T O R N A D O

I/ Spell Information:
untitl22.jpg

II/ Spell Code:
JASS:
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//          D E V I L    T O R N A D O
//                                  - Spell Create By:
//                                                      + Elphis
//*************************************************************************************
library DevilTornadol /*                   
*/                                      requires /*
//                                              -*/ DelFX, /* http://www.hiveworkshop.com/forums/spells-569/delfx-delayed-effects-1-4-2-a-116064/?prev=search%3DDel%2520Effect%26d%3Dlist%26r%3D20%26c%3D112
//                                              -*/ AbilityPreload,/* http://www.wc3c.net/showthread.php?t=105279
//                                              -*/ TimerUtils, /* http://www.wc3c.net/showthread.php?t=101322
//                                              -*/ IsTerrainWalkable, /* I can't found this link of the library, so credits by Maker,anitarf
//                                              -*/ SpellEffectEvent, /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/
//                                              -*/ RegisterPlayerUnitEvent /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
//                                              -*/ xedamage /* http://www.wc3c.net/showthread.php?t=101150
//                                              -*/ SimError /* http://www.wc3c.net/showthread.php?t=101260 
//                                              -*/ SJS /* Spell Staus Library
//                                              -*/ IsDestructableTree /* Credits by PitzerMike
//                                              -*/ SpecialEffect /* Spell Staus Library */
//*************************************************************************************
                                               //! novjass
//          - Spell Information:
//                              - Instantly calling a powerful tornado hit a ground 
//                              tornado also blow caster too, when it hit a ground
/*                              the tornado protect all allies of caster in*/400/* range and blow away all enemies inside of it 
//                              and then, it calling more powerful ice rain hit a ground deals 
//                              */10/20/30/40 /*damages, tornado duration in */10/*seconds.*/
                                              //! endnovjass
//                              
//*************************************************************************************
//          - Installation:
//                                - Import/copy the required libraries and Devil Tornado code to your map
//                                - Import/copy the custom ability and unit to your map and change the SPELL_ID if needed
//                                - You may view the raw ID of the objects by pressing CTRL+D in the object editor
//                                - You may play with the configurables below
//*************************************************************************************
    globals
        //==================================CONFIGURABLES=============================================//
        //Time run every function called
        private         constant            real            LOOP_TIMER          =           0.031250000
        //Jump speed when caster casted ability
        private         constant            real            SPEED_JUMPING       =           30.
        //Scale of Tornado
        private         constant            real            TORNADO_MAX_SIZE    =           1.5
        //Range of protection tornado when enemy come nearly
        private         constant            real            MINIMUM_RANGE       =           400.
        //Speed of mini tornado when it fly around tornado
        private         constant            real            TOR_CALLER_SP       =           10.
        //Duration of Tornado
        private         constant            real            TORNADO_LIFE_TIME   =           10.
        //Mini tornado calling delay
        private         constant            real            DELAY_MINI_TOR      =           1.5
        //Damage radius when mini tornado hit unit
        private         constant            real            MINIMUM_DAMAGE_RA   =           100.
        //Damage per mini tornado slashed unit
        private         constant            real            DAMAGE_PER_SLASH    =           10.
        //Speed of special effect created around tornadol
        private         constant            real            DUST_SPEED          =           15.
        //Height of Special Effect increase every function called
        private         constant            real            DUST_HEIGHT_PER_S   =           15.
        //Max height of Special Effect
        private         constant            real            DUST_MAX_HEIGHT     =           400.
        //Distance of Special Effect around tornado
        private         constant            real            DUST_EFFECT         =           200.
        //Tornado activator range
        private         constant            real            ACTIVE_TOR_RANGE    =           100.
        //Blow unit minimum range
        private         constant            real            ENEMY_BLOW_MIN_RA   =           300.
        //Blow unit maximum range
        private         constant            real            ENEMY_BLOCK_RANGE   =           800.
        //Blow unit speed
        private         constant            real            ENEMY_BLOW_SPEED    =           30.
        //This value is optional, delay nova effect when the rain hit a ground
        private         constant            real            NOVA_DELAY          =           0.8
        //Rain created intevar, if you want more rain fall per seconds, just decrease this value
        private         constant            real            RAIN_INTEVAR        =           0.1
        //Damage when rain hit a ground
        private         constant            real            DAMAGE_RAIN_HIT_G   =           10.
        //Damage radius when rain hit a ground
        private         constant            real            RADIUS_RAIN_HIT_G   =           200.
        //Auto active tornado power when caster can't leap this region
        private         constant            real            AUTO_ACTIVE         =           1.5
        //=======================================================================================
        //Rawcode of Spell, change if needed
        private         constant            integer         SPELL_ID            =           'A000'
        //=======================================================================================
        //Model of Tornado
        private         constant            string          TORNADO_MODEL       =           "Abilities\\Spells\\Other\\Tornado\\TornadoElementalSmall.mdl"
        //Attach the model Tornado on dummy 
        private         constant            string          ATTACH_MODEL        =           "origin"
        //Effect when mini tornado hit unit
        private         constant            string          EFFECT_SLASHED      =           ""
        //Effect blow unit away from circle (start blow)
        private         constant            string          BLOW_EFFECT_S       =           ""
        //Effect blow unit away from circle (finish blow)
        private         constant            string          BLOW_EFFECT_E       =           ""
        //Displayed messages when you can't caller tornado
        private         constant            string          ERROR               =           "Can't call TORNADO here"
        //Special effect around tornado
        private         constant            string          EFFECT_ON_TOR       =           "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl"
        //Effect of the rain fall when tornado calling
        private         constant            string          RAIN_EFFECT         =           "Abilities\\Spells\\Human\\Blizzard\\BlizzardTarget.mdl"
        //Effect of nova when rain hit a ground
        private         constant            string          NOVA_GROUND         =           "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
        //Special effect when rain hit enemy
        private         constant            string          ENEMY_HIT_EFFECT    =           "Abilities\\Spells\\Undead\\FrostArmor\\FrostArmorDamage.mdl"
        //Attach the special effect on enemy
        private         constant            string          ENEMY_ATTACH_EFFECT =           "chest"
        //=======================================================================================
        //Allow deals damage to destructable
        private         constant            boolean         DAMAGE_TREE         =           true
        //=======================================================================================
        private         constant            attacktype      ATTACKTYPE          =           ATTACK_TYPE_HERO
        private         constant            damagetype      DAMAGETYPE          =           DAMAGE_TYPE_COLD
        private         constant            weapontype      WEAPONTYPE          =           WEAPON_TYPE_METAL_HEAVY_BASH
        //==================================NON - CONFIGURABLES=============================================//
        private         constant            group           GROUP               =           CreateGroup()
        //==================================CONFIGURABLES=============================================//
    endglobals
    //
    struct DevilTORNADO
        //unit
        unit u
        unit dummy
        //real
        real h
        real ar
        real anglez01
        real anglez02
        real intevar
        real targetx
        real targety
        real atac
        boolean fade
        boolean ac
        effect e
        group g
        //xedamage installing
        xedamage xed
        //Check Unit
        static method filterUnit takes unit caster, unit u returns boolean
        return /*
        */ IsUnitEnemy(u, GetOwningPlayer(caster)) and /* Target is an enemy of caster
        */ not IsUnitType(u, UNIT_TYPE_DEAD) and GetUnitTypeId(u) != 0 and /* Target is alive
        */ not IsUnitType(u, UNIT_TYPE_STRUCTURE) /* Target is not a structure
        */
        endmethod
        //Damage per slash settings
        static method onDamage takes unit u returns real
            return DAMAGE_PER_SLASH // Damage when mini tornado hit enemy
        endmethod
        //Damage when rain hit a ground settings
        static method rainDamage takes unit u returns real
            return DAMAGE_RAIN_HIT_G*GetUnitAbilityLevel(u,SPELL_ID) // Damage when rain hit the ground to enemy
        endmethod
        //Check terrain can casting this spell
        private static method terrainCheck takes nothing returns nothing
            local unit u = GetTriggerUnit()
            if GetSpellAbilityId() != SPELL_ID then
                set u = null
                return
            endif
            //
            if IsTerrainWalkable(GetSpellTargetX(),GetSpellTargetY()) == false then
                call PauseUnit(u, true)
                call IssueImmediateOrderById(u, 851972)
                call PauseUnit(u, false)
                call SimError(GetTriggerPlayer(), ERROR)
            endif
            set u = null
        endmethod
        //
        static method onPeriodic takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = GetTimerData(t)
            local real x
            local real y
            local real d
            local real a
            local unit f
            //Special Effect Optional
            if ac == true then
                //
                if fade == false then
                    set h = h + DUST_HEIGHT_PER_S
                    //
                    if h >= DUST_MAX_HEIGHT then
                        set fade = true
                    endif
                else
                    set h = h - DUST_HEIGHT_PER_S
                    //
                    if h <= 0. then
                        set fade = false
                    endif
                endif
                //
                set anglez01 = anglez01 + DUST_SPEED
                set x = targetx + DUST_EFFECT * Cos(anglez01*0.01747)
                set y = targety + DUST_EFFECT * Sin(anglez01*0.01747)
                //
                call CreateDelayedEffectZ(EFFECT_ON_TOR,x,y,h,0.,0.)
                //
                set anglez02 = anglez02 - DUST_SPEED
                set x = targetx + DUST_EFFECT * Cos(anglez02*0.01747)
                set y = targety + DUST_EFFECT * Sin(anglez02*0.01747)
                //
                call CreateDelayedEffectZ(EFFECT_ON_TOR,x,y,h,0.,0.)
                //====================================================
                //Rain caller
                if intevar >= RAIN_INTEVAR then
                    set intevar = 0.
                    set a = GetRandomReal(0, 6.283185)
                    set d = GetRandomReal(ENEMY_BLOW_MIN_RA,ENEMY_BLOCK_RANGE)
                    set x = targetx + d * Cos(a)
                    set y = targety + d * Sin(a)
                    call DestroyEffect(AddSpecialEffect(RAIN_EFFECT,x,y))
                    call CreateDelayedEffect(NOVA_GROUND,x,y,NOVA_DELAY,0.)
                    //
                    call xed.useSpecialEffect(ENEMY_HIT_EFFECT,ENEMY_ATTACH_EFFECT)
                    call xed.damageAOE(u,x,y,RADIUS_RAIN_HIT_G,onDamage(u))
                else
                    set intevar = intevar + LOOP_TIMER
                endif
                //
                call GroupEnumUnitsInRange(GROUP,targetx,targety,ENEMY_BLOCK_RANGE,null)
                loop
                    set f = FirstOfGroup(GROUP)
                    exitwhen f == null
                    //
                    if IsUnitInRange(f,dummy,MINIMUM_RANGE) and filterUnit(u,f) then
                        if IsUnitInGroup(f,g) == false then
                            call GroupAddUnit(g,f)
                            set a = Angle(x,y,GetUnitX(f),GetUnitY(f))
                            set d = GetRandomReal(ENEMY_BLOW_MIN_RA,ENEMY_BLOCK_RANGE)
                            set x = GetUnitX(f) + d * Cos(a*0.01747)
                            set y = GetUnitY(f) + d * Sin(a*0.01747)
                            call J.JumpTarget(f,x,y,ENEMY_BLOW_SPEED,BLOW_EFFECT_S,BLOW_EFFECT_E,false,false)
                        endif
                    else
                        if IsUnitInGroup(f,g) == true then
                            call GroupRemoveUnit(g,f)
                        endif
                    endif
                    call GroupRemoveUnit(GROUP,f)
                endloop
                //
                if IsUnitType(dummy, UNIT_TYPE_DEAD) and GetUnitTypeId(dummy) != 0 then
                    call ReleaseTimer(t)
                    set u = null
                    call DestroyGroup(g)
                    call DestroyEffect(e)
                    set e = null
                    call RemoveUnit(dummy)
                    set dummy = null
                    call xed.destroy()
                    call destroy()
                endif
            else
                if atac > 0 then
                    set atac = atac - LOOP_TIMER
                else
                    set ac = true
                endif
                //
                if IsUnitInRangeXY(u,targetx,targety,ACTIVE_TOR_RANGE) then
                    set ac = true
                endif
            endif
            //
            set t = null
        endmethod
        //Spell cast settings
        static method onCast takes nothing returns nothing
            local thistype this = allocate()
            local real x
            local real y
            local unit d
            local player p = GetTriggerPlayer()
            //
            set targetx = GetSpellTargetX()
            set targety = GetSpellTargetY()
            set g = CreateGroup()
            set u = GetTriggerUnit()
            set x = GetUnitX(u)
            set y = GetUnitY(u)
            set xed = xedamage.create()
            set xed.dtype = DAMAGETYPE
            set xed.atype = ATTACKTYPE
            set xed.wtype = WEAPONTYPE
            set xed.damageEnemies = true
            set xed.damageTrees   = DAMAGE_TREE
            set intevar = 0.
            set anglez01 = 0.
            set anglez02 = 0.
            set atac = AUTO_ACTIVE
            set fade = false
            set ac = false
            set h = 0.
            set dummy = CreateUnit(p,'xeca',x,y,GetUnitFacing(u))
            call SetUnitScale(dummy,TORNADO_MAX_SIZE,0,0)
            set e = AddSpecialEffectTarget(TORNADO_MODEL,dummy,ATTACH_MODEL)
            call J.JumpTarget(dummy,targetx,targety,SPEED_JUMPING,"","",false,false)
            call J.JumpTarget(u,targetx,targety,SPEED_JUMPING,"","",false,false)
            set x = targetx + MINIMUM_RANGE * Cos(GetUnitFacing(u)*0.01747)
            set y = targety + MINIMUM_RANGE * Sin(GetUnitFacing(u)*0.01747)
            set d = CreateUnit(p,'xeca',x,y,0.)
            call Effect.Around(0.,dummy,d,MINIMUM_RANGE,MINIMUM_DAMAGE_RA,TOR_CALLER_SP,TORNADO_LIFE_TIME,true,true,onDamage(u),EFFECT_ON_TOR,0.,EFFECT_SLASHED)
            call UnitApplyTimedLife(dummy,'BTLF',TORNADO_LIFE_TIME)
            //
            call TimerStart(NewTimerEx(this),LOOP_TIMER,true,function thistype.onPeriodic)
            //
            set d = null
        endmethod
        //
        static method onInit takes nothing returns nothing
            call AbilityPreload(SPELL_ID) // Preload this ability before casting
            call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST,function thistype.terrainCheck)
            call RegisterSpellEffectEvent(SPELL_ID,function thistype.onCast)
        endmethod
    endstruct
endlibrary
[/HIDDEN]
JASS:
//! zinc
//
library SJS requires TimerUtils,AaD,IsTerrainWalkable
{
        constant                real                            time            =           .0325;
        //
        public struct J
        {
            real Reach;
            real Fly;
            real Dis;
            real Angle;
            real sp;
            boolean kill;
            unit U;
            real High;
            real d;
            real Highsettings;
            real Timer;
            real ag;
            boolean Jumpag;
            boolean rem;
            string EfEnd;
//
    static method onPeriodic()
    {
        real x;
        real y;
        thistype this = GetTimerData(GetExpiredTimer());
        if(IsUnitType(U,UNIT_TYPE_DEAD) == false && GetUnitTypeId(U) != 0)
        {
            if (Reach < Dis)
            {
                     x = GetUnitX(U) + sp * Cos(Angle * 0.01747);
                     y = GetUnitY(U) + sp * Sin(Angle * 0.01747);
                     if(IsTerrainWalkable(x,y) && GetUnitAbilityLevel(U,'Aloc') == 0)
                        SetUnitPosition(U,x,y);
                     else if(GetUnitAbilityLevel(U,'Aloc') >= 1)
                        SetUnitPosition(U,x,y);
                     Reach = Reach + sp;
                     Timer = Timer + 180/(Dis / sp);
                     Fly   = Sin(Timer*bj_DEGTORAD)*Highsettings*1.3;
                     SetUnitFlyHeight(U,Fly,0.);
            }
                else
                {
                     if(kill && !rem)
                        KillUnit(U);
                     if(!kill && rem)
                        RemoveUnit(U);
                     DestroyEffect(AddSpecialEffect(EfEnd,GetUnitX(U),GetUnitY(U)));
                     SetUnitPathing(U,true);
                     UnitAddAbility(U,'Amrf');
                     UnitRemoveAbility(U,'Amrf');
                     SetUnitFlyHeight(U,0.,GetUnitDefaultFlyHeight(U));
                     if(rem)
                        RemoveUnit(U);
                     EfEnd = null;
                     ReleaseTimer(GetExpiredTimer());
                     U = null;
                     destroy();
                }
        }
                else
                {
                     if(kill && !rem)
                        KillUnit(U);
                     if(!kill && rem)
                        RemoveUnit(U);
                     SetUnitPathing(U,true);
                     UnitAddAbility(U,'Amrf');
                     UnitRemoveAbility(U,'Amrf');
                     SetUnitFlyHeight(U,0.,GetUnitDefaultFlyHeight(U));
                     if(rem)
                        RemoveUnit(U);
                     EfEnd = null;
                     ReleaseTimer(GetExpiredTimer());
                     U = null;
                     destroy();
                }
    }
        static method JumpTarget(unit whatunit,real xj,real yj,real speed,string XJ,string EJ,boolean rems,boolean kills) 
        {
             thistype this;
             if(IsUnitType(whatunit,UNIT_TYPE_DEAD) == false && GetUnitTypeId(whatunit) != 0)
             {
                 this = allocate();
                 U = whatunit;
                 Reach = 0.;
                 Timer = 0.;
                 rem = rems;
                 kill = kills;
                 rem = rems;
                 sp = speed;
                 Fly = 0.;
                 EfEnd = EJ;
                 Dis = Distance(GetUnitX(whatunit),GetUnitY(whatunit),xj,yj);
                 Angle = Angle(GetUnitX(whatunit),GetUnitY(whatunit),xj,yj);
                 High = .35;
                 Highsettings = Dis*High;
                 DestroyEffect(AddSpecialEffect(XJ,GetUnitX(U),GetUnitY(U)));
                 SetUnitPathing(U,false);
                 UnitAddAbility(U,'Amrf');
                 UnitRemoveAbility(U,'Amrf');
                 TimerStart(NewTimerEx(this),time,true,function thistype.onPeriodic);
            }
        }
            
    }
}
//
library AaD
{
    public function Distance(real xa,real ya,real xb,real yb) -> real
    {
        real dx = xb - xa;
        real dy = yb - ya;
        return SquareRoot(dx * dx + dy * dy);
    }
    //
    public function Angle(real xa,real ya,real xb,real yb) -> real
    {
        return bj_RADTODEG * Atan2(yb - ya, xb - xa);
    }
}
//
library SpecialEffect requires TimerUtils,xedamage
{
    public struct Effect
    {
        unit u;
        unit tg;
        string ef;
        real dura;
        effect E;
        real a;
        real Area;
        real Dl;
        real run;
        string w;
        real wai;
        real dma;
        boolean RM;
        boolean dmg;
        real within;
        real sp;
        string whentaken;
        destructable dest;
        xedamage dam;
        //
        static method arLoop()
        {
            thistype this = GetTimerData(GetExpiredTimer());
            real x;
            real y;
            group g;
            unit f;
            if(!IsUnitType(u, UNIT_TYPE_DEAD) && !IsUnitType(tg, UNIT_TYPE_DEAD) && GetUnitTypeId(u) != 0 && GetUnitTypeId(tg) != 0)
            {
                if(wai > 0)
                    wai = wai - .03250000;
                else
                {
                    a = a + sp;
                    x = GetUnitX(u) + Area * Cos(a*0.01747);
                    y = GetUnitY(u) + Area * Sin(a*0.01747);
                    SetUnitX(tg,x);
                    SetUnitY(tg,y);
                    if(run < Dl)
                        run = run + .032500000;
                    else
                    {
                        run = 0.;
                        DestroyEffect(AddSpecialEffect(ef,GetUnitX(tg),GetUnitY(tg)));
                    }
                    if(dmg)
                    {
                        dam.useSpecialEffect(whentaken,"chest");
                        dam.damageAOE(u,x,y,within,dma);
                    }
                    if(dura > 0)
                        dura = dura - .03250000;
                    if(dura <= 0 || GetWidgetLife(tg) < 0.425 || GetWidgetLife(u) < 0.425)
                    {
                        if(RM)
                            RemoveUnit(tg);
                        ReleaseTimer(GetExpiredTimer());
                        u = null;
                        tg = null;
                        destroy();
                    }
                }
            }
            else
            {
                if(RM)
                    RemoveUnit(tg);
                ReleaseTimer(GetExpiredTimer());
                u = null;
                tg = null;
                destroy();
            }
        }
        //
        static method Around(real wait,unit aro,unit tgs,real AOE,real withinn,real speed,real dur,boolean rms,boolean DMGs,real dmgg,string effe,real Delay,string effwhentaken) 
        {
            thistype this;
            if(!IsUnitType(tgs, UNIT_TYPE_DEAD) && !IsUnitType(aro, UNIT_TYPE_DEAD) && GetUnitTypeId(tgs) != 0 && GetUnitTypeId(aro) != 0)
            {
                this = allocate();
                u = aro;
                whentaken = effwhentaken;
                tg = tgs;
                wai = wait;
                dura = dur;
                ef = effe;
                dma = dmgg;
                within = withinn;
                dmg = DMGs;
                a = Angle(GetUnitX(aro),GetUnitY(aro),GetUnitX(tgs),GetUnitY(tgs));
                run = 0.;
                Dl = Delay;
                RM = rms;
                sp = speed;
                Area = AOE;
                dam = xedamage.create();   
                dam.dtype = DAMAGE_TYPE_FIRE;
                dam.atype = ATTACK_TYPE_NORMAL;
                dam.damageEnemies = true;
                dam.damageTrees   = false;
                TimerStart(NewTimerEx(this),.0325000,true,function thistype.arLoop);
            }
            
        }
    }
}
//! endzinc
[/HIDDEN]
III/ Spell Look Like:
IV/ Credits:
Click to view library DelFX
Click to view library Ability Preload
Click to view Timer Utils
Click to view library SpellEffectEvent
Click to view RegisterPlayerUnitEvent
Click to view library xedamage
Click to view library SimError
-------------------------------------------


v1.0: First Release Version
v1.1: Add static if to ShadowTrail.
v1.2: Optimize code, remove stuff.
v1.3: Fixed bugs, remove library Shadow Trail.
v1.4: Optimized.


Keywords:
tornado,devil
Contents

Devil Tornado (Map)

Reviews
19:18, 1st Oct 2013 PurgeandFire: Approved. (Old) Review: http://www.hiveworkshop.com/forums/2425107-post18.html

Moderator

M

Moderator

19:18, 1st Oct 2013
PurgeandFire: Approved.

(Old) Review:
http://www.hiveworkshop.com/forums/2425107-post18.html
 
REVIEW
TRIGGER FIXES
  • This should be stored and passed to the FilterUnit function rather than called every time. GetOwningPlayer(caster)
  • Anything used twice or more should be stored. Example: GetTriggerUnit()
  • You should Enumerate destructables in range rather than in rect.
FINAL RATING
  • Needs Fix
[/TD][/tr]
If you have any questions or problems with my review please tell me. Original Review Template by Doomlord.
 
REVIEW
TRIGGER FIXES
  • This should be stored and passed to the FilterUnit function rather than called every time. GetOwningPlayer(caster)
  • Anything used twice or more should be stored. Example: GetTriggerUnit()
  • You should Enumerate destructables in range rather than in rect.
FINAL RATING
  • Needs Fix
[/TD][/tr]
If you have any questions or problems with my review please tell me. Original Review Template by Doomlord.

Thanks a lot, i can't check IsUnitInGroup with GetFilterUnit()
 
Sure.
JASS:
globals
group gr = CreateGroup()
endglobals
struct A
          group g
//
static method filter takes nothing returns nothing

call GroupAddUnit(g,GetFilterUnit()) ???
//It will cause error

endmethod
static method onPeriodic takes nothing returns nothing
local timer t = GetExpiredTimer()
//
call GroupEnumUnitsInRange(Gr,..,..,..,..,...,function thistype.filter)
endmethod
//
static method onCast takes nothing returns nothing
local thistype this = allocate()
set g = CreateGroup()
//
call TimerStart(NewTimerEx(this),0.,true,function thistype.onPeriodic)
endmethod
//
endstruct
 
Review:
  • Fix what Maker said in the post above me^.
  • In "onCast", you can remove local real cos and local real sin.
  • set a = GetRandomReal(0,360)*0.01747
    When you want to calculate a random angle in radians, just use:
    set a = GetRandomReal(0, 2 * bj_PI)
    Or:
    set a = GetRandomReal(0, 6.283185)
  • In "onPeriodic", you can remove local unit df.

Other than that, it looks good. Nice job.
 
Level 4
Joined
Apr 19, 2013
Messages
86
Can you show me an example of how to configure this spell so the caster does not jump to the target point?

I just want to cast it from anywhere within the cast-range without the jump.

Thank you!
 
Top