• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Twister and Storm Spiral v1.5

  • Like
Reactions: Axarion
Wind Spellpack

Information
+GUI/JASS/vJASS: vJASS.
+MUI: Yes, of course.
+Leakless: (Maybe) Yes.
+Lagless: (Maybe) Yes.
+Requires:
  1. JASS NewGen Pack v1.5d
  2. TimerUtils
  3. Damage Over Time
  4. GroupUtils
  5. xe 0.8 ( xebasic, xecast, xepreload )
  6. OID


Spells

images

Twister
Type Point Area of Effect
Target Allowed Enemy
Mana Cost 150
Cooldown 12 seconds

I can't write description for this spellpack because i can't think anything to write and I'm very bad in English :banghead:. Someone can help me ?

Level 1 200 damage on ground, 100 damage and 3 seconds stun afterward.
Level 2 200 damage on ground, 150 damage and 3 seconds stun afterward.
Level 3 200 damage on ground, 185 damage and 3 seconds stun afterward.
Level 4 200 damage on ground, 250 damage and 3 seconds stun afterward.

-Screenshot:
attachment.php

attachment.php


-Code:

JASS:
//===============================================================
//|                      game_war48 Presents
//|                           Twister
//|                           ¯¯¯¯¯¯¯
//|  Requires:
//| - JassNewGen v1.5d
//| - TimerUtils
//|
//|  How to Import:
//| - Copy ability: "Twister" (A002)
//| - Copy unit: Dummy Unit - Twister and Storm Spiral (n001)
//| - Copy trigger: Twister and TimerUtils (if you don't have it)
//| - Changes the raw id of abilities, units,... in the globals.
//| - And MUST remember to change the raw id of XE Dummy in "xebasic"
//|
//| Modification:
//| - Values in the globals block and functions below it
//|
//|  Credit
//| - Thanks Vexorian for TimerUtils and xe
//| - Thanks Cohadar for OID
//| - Thanks Tom_Kazansky for helping me
//| - Thanks Tink3 for his template map
//| - Thanks Rising_Dusk for GroupUtils
//===============================================================

scope Twister initializer InitTW

    globals
        private constant integer ABILITYID = 'A002' // Rawcode of the ability
        private constant integer DUMMYID = 'n001' // Rawcode of the "wind" dummy
        private constant integer DAMAGEID = 'A001' // Rawcode of the damage ability
        private constant integer DAMAGEORDERID = OID_thunderbolt // Order ID of the damage ability from OID Library by Cohadar(important, needed to cast damage ability)
        
        private constant string EFFECTDAMAGE = "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl" // Path effect when damage on ground
        
        private constant real FLYHEIGHT = 500. // Maximum height to "fly"
        
        //------------------------------
        
        private constant real PERIOD = 0.04 // period of time, but i think that shouldn't edit this

    endglobals
    
    private function GetDamage takes integer lvl returns real
        return 200. + 0. * lvl // Damage deals when touching enemy units on ground, configurable
    endfunction
    
//=============================================================================
    globals
        private integer I
    endglobals
    
//=============================================================================
    
    private struct eo
        unit c
        unit array d[6]
        
        boolean array inc[6]
        boolean b = false
        boolean b2 = false
        
        real dx
        real dy
        real tx
        real ty
        real df
        real array hs[6]
        real h = 100.
        real hb = 150
        real dist
        real height = 500
        real ang
        real array a[6]
        real dam
        
        integer tick
        integer tk
        integer toss
        integer lvl
        
        group g
    endstruct
    
    private function TwisterG takes nothing returns nothing
        local eo d = I
        local unit e = GetEnumUnit()
        local real x = GetUnitX(e)
        local real y = GetUnitY(e) 
        local real dist = DistanceXY( d.dx, d.dy, x, y )
    
        if not d.b2 then
            if GetUnitFlyHeight(e) < FLYHEIGHT then
                call SetUnitZ( e, d.height * Sin( (90/d.tk) * d.tick * bj_DEGTORAD ) )
            endif
        endif
        
        set e = null
    endfunction
    
    private function TwisterUP takes nothing returns nothing
        local eo d = I
        local xecast xe
        
        local unit e = GetEnumUnit()
        
        local real x = GetUnitX(e)
        local real y = GetUnitY(e)
        local real z = GetUnitDefaultFlyHeight(e)
        
        set xe = xecast.createBasicA( DAMAGEID, DAMAGEORDERID, GetOwningPlayer( d.c ) )
        call xe.setSourcePoint( x, y, 0. )
        call xe.castOnTarget( e, d.lvl )
                
        call SetUnitX( e, x )
        call SetUnitY( e, y )
        //call SetUnitPosition( e, x, y )
        call SetUnitZ( e, z )
        
        call DestroyTreesInCircle( x, y, 200 )
        
        set e = null
    endfunction
    
    private function TwisterM takes nothing returns nothing
        local eo d = I
        local unit e = GetEnumUnit()
        
        local real sinr = 90 / 25 * d.tick
        local real r1 = d.dist * Sin(sinr * bj_DEGTORAD)
        local real dx = GetPPX( d.dx, r1, d.df )
        local real dy = GetPPY( d.dy, r1, d.df )
        
        call SetUnitX( e, dx )
        call SetUnitY( e, dy )
        //call SetUnitPosition( e, dx, dy ) 
        
        call DestroyTreesInCircle( dx, dy, 200. )
        call DestroyEffect( AddSpecialEffect( EFFECTDAMAGE, GetUnitX(e), GetUnitY(e) ) )
        
        set e = null
    endfunction
    
    private function TwisterF takes nothing returns boolean
        local eo d = I
        local unit u = GetFilterUnit()
        local boolean ok = false
        
        if      IsUnitEnemy    (u, GetOwningPlayer(d.c)) /*
      */and     IsUnitVisible  (u, GetOwningPlayer(d.c)) /*
      */and not IsUnitType     (u, UNIT_TYPE_MAGIC_IMMUNE) /*
      */and not IsUnitType     (u, UNIT_TYPE_STRUCTURE) /*
      */and not IsUnitType     (u, UNIT_TYPE_DEAD) /*
      */and not IsUnitInGroup  (u, d.g) then
            set ok = true
        endif
        
        set u = null
        
        return ok
    endfunction
    
    private function TwisterT takes nothing returns nothing
        local timer ti = GetExpiredTimer()
        local eo d = GetTimerData(ti)
        
        local group g
        local unit p
        
        local integer i
        local integer j
        local integer k      

        local real dx
        local real dy
        local real h
        local real sinr 
        local real r1
        
        if d.toss == 2 then
            if d.tick < 0 then
                set j = 0
                loop
                    exitwhen j > 5
                    call KillUnit(d.d[j])
                    set j = j + 1
                endloop
                
                set I = d
                call ForGroup(d.g, function TwisterUP)
                
                call ReleaseGroup(d.g)
                call ReleaseTimer(ti)
                set ti = null
                call d.destroy()
                return
            endif
        endif
        
        if d.toss == 0 then
            if d.tick > 25 then
                set d.dx = d.tx
                set d.dy = d.ty
                
                call GroupEnumUnitsInArea(d.g, d.dx, d.dy, 300., Condition(function TwisterF) )
                
                set k = 0
                loop
                    exitwhen k > 5
                    set d.a[k] = 60 * k
                    set k = k + 1
                endloop
                set d.tick = 0
                set d.toss = 2
                set d.hb = 0
                set p = null
            endif
        endif
        
        if d.toss == 0 then
            set sinr = 90 / 25 * d.tick
            set r1 = d.dist * Sin(sinr * bj_DEGTORAD)
            set dx = GetPPX( d.dx, r1, d.df )
            set dy = GetPPY( d.dy, r1, d.df )
        endif
        
        set i = 0
        loop
            set i = i + 1
            exitwhen i > 8
            set j = 0
            loop
                exitwhen j > 5
                if d.toss == 0 then
                //*****************************************************
                    if d.inc[j] and d.hs[j] == 1 then
                        set d.inc[j] = false
                    endif
                    
                    if not d.inc[j] and d.hs[j] == -1 then
                        set d.inc[j] = true
                    endif
                    
                    if d.inc[j] then
                        set d.hs[j] = d.hs[j] + 0.05
                    else
                        set d.hs[j] = d.hs[j] - 0.05
                    endif
            
                    call SetUnitX(d.d[j],GetPPX( dx, d.h * d.hs[j], d.df - 90. ) )
                    call SetUnitY(d.d[j],GetPPY( dy, d.h * d.hs[j], d.df - 90. ) )
                    call DestroyTreesInCircle( dx, dy, 200. )
                    set h = SquareRoot( d.h * d.h - d.h * d.hs[j] * d.h * d.hs[j]  )
                    
                    if d.inc[j] then
                        call SetUnitZ(d.d[j], d.hb + h )
                    else
                        call SetUnitZ(d.d[j], d.hb - h )
                    endif
            //*****************************************************    
                endif
                
                set j = j + 1
                
            endloop
        endloop
        
        set j = 0
        loop
            exitwhen j > 5
            if d.toss == 2 then
            
                if d.tick >= 50 then
                    set d.height = 0
                    set d.tk = 5
                    set d.tick = 5
                    set d.b2 = true
                else
                    set d.height = FLYHEIGHT
                    set d.tk = 50
                endif
                        
                if d.a[j] >= 360 then
                    set d.a[j] = 0.
                else
                    set d.a[j] = d.a[j] + 10.
                endif
                        
                if not d.b2 then
                    call SetUnitX(d.d[j],GetPPX( d.dx, 250., d.a[j] ) )
                    call SetUnitY(d.d[j],GetPPY( d.dy, 250., d.a[j] ) )
                    call SetUnitZ(d.d[j], d.height * Sin( (90/d.tk) * d.tick * bj_DEGTORAD ) )
                else
                    call SetUnitZ(d.d[j], d.height * Sin( (90/d.tk) * d.tick * bj_DEGTORAD ) + 10 )
                endif
                        
                call DestroyTreesInCircle( d.dx, d.dy, 200. )
                        
                set I = d
                call ForGroup(d.g, function TwisterG)
            endif
            set j = j + 1
        endloop
        
        
        if d.toss == 0 then
            set g = NewGroup()
            set I = d
            call GroupEnumUnitsInArea(g, dx, dy, 200., Condition(function TwisterF) )
            
            loop
                set p = FirstOfGroup(g)
                exitwhen p == null
                
                call GroupRemoveUnit(g, p)
                call GroupAddUnit(d.g, p)
                call UnitDamageTarget(d.c, p, d.dam, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, null)
            endloop
            
            call ReleaseGroup(g)
            set g = null
            
            set I = d
            call ForGroup(d.g, function TwisterM)
        endif
        
        if d.b2 then
            set d.tick = d.tick - 1
        else
            set d.tick = d.tick + 1
        endif
        
        //set ti = null
    endfunction
        
    private function Twister takes nothing returns nothing
        local eo d = eo.create()
        local timer ti = NewTimer()
        
        set d.c = GetTriggerUnit()
        set d.dx = GetUnitX(d.c)
        set d.dy = GetUnitY(d.c)
        set d.tx = GetSpellTargetX()
        set d.ty = GetSpellTargetY()
        set d.df = AngleXY( d.dx, d.dy, d.tx, d.ty )
        set d.dist = DistanceXY( d.dx, d.dy, d.tx, d.ty )
        
        set d.hs[0] = 1
        set d.d[0] = CreateUnit(GetOwningPlayer(d.c),DUMMYID,GetPPX(d.dx,d.h*d.hs[0],d.df-90.),GetPPY(d.dy,d.h*d.hs[0],d.df-90.),d.df-90)
        call SetUnitZ(d.d[0],d.hb)
        call SetUnitVertexColor(d.d[0], 255, 255, 255, 0)
        set d.inc[0] = true
        
        set d.hs[1] = -1
        set d.d[1] = CreateUnit(GetOwningPlayer(d.c),DUMMYID,GetPPX(d.dx,d.h*d.hs[1],d.df+90.),GetPPY(d.dy,d.h*d.hs[1],d.df+90.),d.df+90)
        call SetUnitZ(d.d[1],d.hb)
        call SetUnitVertexColor(d.d[1], 255, 255, 255, 0)
        set d.inc[1] = false
    
        set d.hs[2] = 0.
        set d.d[2] = CreateUnit(GetOwningPlayer(d.c),DUMMYID,GetPPX(d.dx,d.h*d.hs[2],d.df+90.),GetPPY(d.dy,d.h*d.hs[2],d.df+90.),d.df+90)
        call SetUnitZ(d.d[2],d.hb+d.h)
        call SetUnitVertexColor(d.d[2], 255, 255, 255, 0)
        set d.inc[2] = true
    
        set d.hs[3] = 0.
        set d.d[3] = CreateUnit(GetOwningPlayer(d.c),DUMMYID,GetPPX(d.dx,d.h*d.hs[3],d.df+90.),GetPPY(d.dy,d.h*d.hs[3],d.df+90.),d.df+90)
        call SetUnitZ(d.d[3],d.hb-d.h)
        call SetUnitVertexColor(d.d[3], 255, 255, 255, 0)
        set d.inc[3] = false
        
        set d.hs[4] = 0.5
        set d.d[4] = CreateUnit(GetOwningPlayer(d.c),DUMMYID,GetPPX(d.dx,d.h*d.hs[4],d.df-90.),GetPPY(d.dy,d.h*d.hs[4],d.df-90.),d.df-90)
        call SetUnitZ(d.d[4],d.hb)
        call SetUnitVertexColor(d.d[4], 255, 255, 255, 0)
        set d.inc[4] = true
        
        set d.hs[5] = -0.5
        set d.d[5] = CreateUnit(GetOwningPlayer(d.c),DUMMYID,GetPPX(d.dx,d.h*d.hs[5],d.df+90.),GetPPY(d.dy,d.h*d.hs[5],d.df+90.),d.df+90)
        call SetUnitZ(d.d[5],d.hb)
        call SetUnitVertexColor(d.d[5], 255, 255, 255, 0)
        set d.inc[5] = false
        
        set d.lvl = GetUnitAbilityLevel( d.c, ABILITYID )
        set d.toss = 0
        set d.tick = 0
        set d.dam = GetDamage( d.lvl )
        
        set d.g = NewGroup()
        call SetTimerData( ti, d )
        call TimerStart( ti, PERIOD, true, function TwisterT )

        //set ti = null
    endfunction

    private function TwisterC takes nothing returns boolean
        return GetSpellAbilityId() == ABILITYID
    endfunction
    
//===========================================================================
    private function InitTW takes nothing returns nothing
        local trigger TrigTW = CreateTrigger(  )
        local integer index
        
        set index = 0
        loop
            call TriggerRegisterPlayerUnitEvent( TrigTW, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)

            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop
        
        call TriggerAddCondition( TrigTW, Condition( function TwisterC ) )
        call TriggerAddAction( TrigTW, function Twister )
    
        call XE_PreloadAbility( DAMAGEID )
        
        //set TrigTW = null
    endfunction
endscope


images

Storm Spiral
Type Point Area of Effect
Target Allowed Enemy
Mana Cost 300
Cooldown 25 seconds

I can't write description for this spellpack because i can't think anything to write and I'm very bad in English :banghead:. Someone can help me ?

Level 1 400 damage.
Level 2 500 damage.
Level 3 600 damage.

-Screenshot:
attachment.php

attachment.php


-Code:
JASS:
//===============================================================
//|                      game_war48 Presents
//|                           Storm Spiral
//|                           ¯¯¯¯¯¯¯¯¯¯¯¯
//|  Requires:
//| - JassNewGen v1.5d
//| - TimerUtils (red+blue+orange flavors for 1.24b+) by Vexorian
//| - Damage Over Time v1.7 by Dynasti on hiveworkshop.com
//|
//|  How to Import:
//| - Copy ability: "Storm Spiral" (A000)
//| - Copy unit: Dummy Unit - Twister and Storm Spiral (n001)
//| - Copy trigger: Storm Spiral and TimerUtils, DOT (if you don't have it)
//| - Changes the raw id of abilities, units,... in the globals.
//|
//| Modification:
//| - Values in the globals block and functions below it
//|
//|  Credit
//| - Thanks Vexorian for TimerUtils
//| - Thanks Tom_Kazansky for helping me
//| - Thanks Tink3 for his template map
//| - Thanks Dynasti for his system
//| - Thanks Rising_Dusk for his system
//===============================================================

scope StormSpiral initializer InitSS

    globals
    
        private constant integer ABILITYID = 'A000' // Rawcode of the ability
        private constant integer DUMMYID = 'n001' // Rawcode of the dummy
        
        private constant string EFFECTDAMAGE1 = "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl" // Path effect when damage
        private constant string EFFECTDAMAGE2 = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" // Path effect when damage, too
        private constant string EFFECTDAMAGE1ATTACH = "chest" // EffectDamage1 attachment point on unit
        private constant string EFFECTDAMAGE2ATTACH = "chest" // EffectDamage2 attachment point on unit

        //----------------------------
        
        private constant real PERIOD = 0.04 // period of time, but i think that shouldn't edit this

    endglobals
        
        
    private function GetDamage takes integer lvl returns real
        return 300. + 100. * lvl // spell's damage, configurable
    endfunction
//=====================================================================    

    globals
        private group GROUP
        private integer I
        private integer I2
    endglobals

    private struct ss
        unit c
        unit d
        unit d2
        
        group gc
                
        real dx
        real dy
        
        real tx
        real ty
        real height
        real dis
        real ang
        real a
        real a2
        real dam
        real dps
        
        integer tick
        integer toss
    endstruct
    
    private function StormSpiralF takes nothing returns boolean
        local ss d = I
        local unit u = GetFilterUnit()
        local boolean ok = false
        
        if      IsUnitEnemy(u, GetOwningPlayer(d.c)) /*
     */ and     IsUnitVisible(u, GetOwningPlayer(d.c)) /*
     */ and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) /*
     */ and not IsUnitType(u, UNIT_TYPE_STRUCTURE) /*
     */ and not IsUnitType(u, UNIT_TYPE_DEAD) /*
     */ and not IsUnitInGroup(u, GROUP) then
            set ok = true
        endif
        
        set u = null
        return ok
    endfunction
    
    private function StormSpiralD takes nothing returns nothing
        local unit e = GetEnumUnit()
        
        call GroupRemoveUnit( GROUP, e )
        
        set e = null
    endfunction

    private function StormSpiralG takes nothing returns nothing
        local ss d = I
        local unit e = GetEnumUnit()
        
        call SetUnitX( e, GetPPX( GetUnitX( e ), 15., d.ang ) )
        call SetUnitY( e, GetPPY( GetUnitY( e ), 15., d.ang ) )
        
        call DestroyEffect( AddSpecialEffectTarget( EFFECTDAMAGE1, e, EFFECTDAMAGE1ATTACH ) )
        call DestroyEffect( AddSpecialEffectTarget( EFFECTDAMAGE2, e, EFFECTDAMAGE2ATTACH ) )
        
        set e = null
    endfunction
    
    private function StormSpiralT takes nothing returns nothing
        local timer ti = GetExpiredTimer()
        local ss d = GetTimerData(ti)
        
        local real x
        local real y
        
        local unit v
        
        if d.toss == 1 then
            if d.tick <= 0 then
                
                call ForGroup( d.gc, function StormSpiralD )
                
                if GROUP != null then
                    call ReleaseGroup( GROUP )
                    set GROUP = null
                endif
                
                call KillUnit( d.d )
                call KillUnit( d.d2 )
                
                call ReleaseGroup( d.gc )
                
                call ReleaseTimer(ti)
                set ti = null
                call d.destroy()
                return
                
            endif
        endif
        
        if d.toss == 0 then
            if d.tick < 0 then
            
                call SetUnitZ( d.d, 0. )
                
                set d.d2 = CreateUnit( GetOwningPlayer( d.c ), DUMMYID, GetUnitX( d.d ), GetUnitY( d.d ), 0. )
                call SetUnitVertexColor( d.d2, 255, 255, 255, 0 )
                
                set d.dx = GetPPX( d.tx, 50., d.ang )
                set d.dy = GetPPY( d.ty, 50., d.ang )
                set d.a = 0.
                set d.a2 = 180.
                
                set d.toss = 1
                set d.tick = 50
                
            endif
        endif
        
        if d.toss == 0 then
        
            set d.height = d.height - 22.5
            set d.dis = d.dis - 15.
            set d.a = d.a - 9.

            set x = GetPPX( d.tx, d.dis, d.a )
            set y = GetPPY( d.ty, d.dis, d.a )
            
            call SetUnitX( d.d, x )
            call SetUnitY( d.d, y )
            call SetUnitZ( d.d, d.height )
        
        elseif d.toss == 1 then
            set d.a = d.a + 30.
            set x = GetPPX( d.dx, 50., d.a )
            set y = GetPPY( d.dy, 50., d.a )
            call SetUnitX( d.d, x )
            call SetUnitY( d.d, y )
            
            set d.a2 = d.a2 + 30.
            set x = GetPPX( d.dx, 50., d.a2 )
            set y = GetPPY( d.dy, 50., d.a2 )
            call SetUnitX( d.d2, x )
            call SetUnitY( d.d2, y )
                
            set I = d
            set v = GetNearestUnit( d.dx, d.dy, 100., Condition( function StormSpiralF ) )
            
            if v != null then
                call DamageOverTime( d.c, v, d.dam, d.tick * PERIOD, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_DIVINE )
                call GroupAddUnit( GROUP, v )
                call GroupAddUnit( d.gc, v )
            endif
                
            set I = d
            call ForGroup( d.gc, function StormSpiralG )
            
            set d.dx = GetPPX( d.dx, 10., d.ang )
            set d.dy = GetPPY( d.dy, 10., d.ang )

        endif
        
        set d.tick = d.tick - 1
        
        //set ti = null
    endfunction
    
    private function StormSpiral takes nothing returns nothing
        local ss d
        local timer ti
        local integer i
        local real x
        local real y
        
        set GROUP = NewGroup()
        
        set i = 0
        loop
            exitwhen i > 17
            
            set d = ss.create()
            set d.c = GetTriggerUnit()
            
            set d.tx = GetSpellTargetX()
            set d.ty = GetSpellTargetY()
            
            set d.a = 20 * i
            set d.ang = d.a
            set d.dx = GetPPX( d.tx, 600., d.a )
            set d.dy = GetPPY( d.ty, 600., d.a )
            
            set d.height = 950.
            set d.dis = 600.
            
            set d.d = CreateUnit( GetOwningPlayer( d.c ), DUMMYID, d.dx, d.dy, 0. )
            call SetUnitVertexColor( d.d, 255, 255, 255, 0 )
            call SetUnitZ( d.d, d.height )
            
            set d.gc = NewGroup()
            
            set d.toss = 0
            set d.tick = 40
            
            set d.dam = GetDamage( GetUnitAbilityLevel( d.c, ABILITYID  ) )
            
            set ti = NewTimer()
            call SetTimerData( ti, d )
            call TimerStart( ti, PERIOD, true, function StormSpiralT )
            //set ti = null
            
            set i = i + 1
        endloop
        
    endfunction
    
    private function StormSpiralC takes nothing returns boolean
        return GetSpellAbilityId() == ABILITYID
    endfunction

//===========================================================================
    private function InitSS takes nothing returns nothing
        local trigger TrigSS = CreateTrigger(  )
        local integer index

        set index = 0
        loop
            call TriggerRegisterPlayerUnitEvent( TrigSS, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null )

            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop        
        call TriggerAddCondition( TrigSS, Condition( function StormSpiralC ) )
        call TriggerAddAction( TrigSS, function StormSpiral )
        
        //set TrigSS = null
    endfunction
endscope

[Spellpack] Twister and Storm Spiral v1.5

Credits
-Tom_Kazansky for helping me very very much.
-Vexorian for TimerUtils and xe.
-Rising_Dusk for GroupUtils.
-Cohadar for OID.
-Tink3 for template map.
-Dynasti for Damage Over Time.

Changelog
v1.0: Release spellpack.
v1.1: Fix filter function.
v1.2: Fix group problem.
v1.3: Edit Storm Spiral's effect.
v1.4: Capitalizing constant global variables and fix some filters.
v1.5: Add preload ability.

P/s: Please help me the description of both, thank you so much:p.

Keywords:
Wind, Druid, Boreas, Twister, Storm, Spiral, Elemental
Contents

Untitled (Map)

Reviews
09:32, 27th May 2010 TriggerHappy: Overall, it's good enough to get approved. Don't inline the spell event. Instead of group recycling you could be using a global group. You should find an alternative to FOG loops.

Moderator

M

Moderator

09:32, 27th May 2010
TriggerHappy:

Overall, it's good enough to get approved.

  • Don't inline the spell event.
  • Instead of group recycling you could be using a global group.
  • You should find an alternative to FOG loops.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
I have not tested these spells yet; I've only checked them online. I also apologize if my code looks strange since I'm on a different computer.

  • JASS:
    if GetUnitFlyHeight(e) < 500 then
    Shouldn't 500 be configurable? You should also make any other numbers like that easier to change by using constant globals or functions. (Like damage for instance)
  • JASS:
    call PauseUnit( e, true )
    Pausing a unit isn't really good. Besides that, it's a waste to declare e when you use it once. Just use GetEnumUnit() directly.
  • Instead of
    JASS:
    local boolean ok = falsei
    if IsUnitEnemy(u, GetOwningPlayer(d.c)) /*
          */and     IsUnitVisible  (u, GetOwningPlayer(d.c)) /*
          */and not IsUnitType     (u, UNIT_TYPE_MAGIC_IMMUNE) /*
          */and not IsUnitType     (u, UNIT_TYPE_STRUCTURE) /*
          */and     GetWidgetLife  (u) > 0.405 /*
          */and not IsUnitInGroup  (u, d.g) then
                set ok = true
    endif
    you could just do
    JASS:
    local boolean ok =   IsUnitEnemy    (u, GetOwningPlayer(d.c)) and     IsUnitVisible  (u, GetOwningPlayer(d.c)) and not IsUnitType     (u, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType     (u, UNIT_TYPE_STRUCTURE) and     GetWidgetLife  (u) > 0.405 and not IsUnitInGroup  (u, d.g)
    I also hope you know that GetWidgetLife(u) can bug and it would be better to use the native UnitAlive or check if a unit is alive with not IsUnitType(u,UNIT_TYPE_DEAD)
  • Using a loop is much more efficient for creating your dummy units.
  • It's better to set the variable as you declare them. Ex:
    JASS:
    local timer ti = NewTimer()
  • You're using GroupUtils; it's better to use GroupEnumUnitsInArea instead of GroupEnumUnitsInRange. Make sure the library is updated to be able to use that function.
  • You could preload your dummy unit.
  • You don't need to inline TriggerRegisterAnyUnitEventBJ.
  • This is kind of a standard: capitalizing constant global variables. It's not that important for you to do this but I thought I might as well as mention that.
I'll edit this post if I test these spells.
 
Level 4
Joined
Apr 15, 2009
Messages
6
1. Ok, I will use the globals for it.
2. Will remove pause. But I belive had someone tell me "Use GetEnumUnit() directly will leak and isn't faster than use variable instead". I will edit it when all things considered.
3. Oh, I do it deliberately. Because changing it is easier than do
JASS:
local boolean ok =   IsUnitEnemy    (u, GetOwningPlayer(d.c)) and     IsUnitVisible  (u, GetOwningPlayer(d.c)) and not IsUnitType     (u, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType     (u, UNIT_TYPE_STRUCTURE) and     GetWidgetLife  (u) > 0.405 and not IsUnitInGroup  (u, d.g)
And I will use not IsUnitType(u,UNIT_TYPE_DEAD) instead of GetWidgetLife.
4. Where ? Twister or Storm Spiral ? If it's Twister, I can't use loop for creating dummys because it doesn't according to any laws, it's just random.
5. Nothing to comment (of course, agreed with you).
6. Oh, I totally forgot it. Thanks you.
7. I will.
8. I really hate BJ, so I don't use that (sorry, just my taste :grin: ).
9. I will do it soon.

Over at all, thanks you so much :thumbs_up:.

EDIT: UPDATE v1.4.
EDIT2: UPDATE v1.5.
 
Last edited:
Level 4
Joined
Apr 15, 2009
Messages
6
^^: I can test it normally, don't have any problem. Also, just do the things xBlackRose told.

Is your time at 8.15 AM (morning) ? I'm from Vietnamese and the time is 3:32 PM (afternoon). Well, what a long difference ! (Just a joke, nevermind it).
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
1,084
Okay I tested the spells and the effects are generally nice though it does lag if you use them too much. (Most likely because of the mass special effects that was also mentioned by Axarion.)
  • You need to compile the map since I had to save it myself before I could test it. (In other words, save it again with JNGP)
  • I don't think you should have OID since it only provides information. Just take the order id you need for the spell and put it as a global in your spell. (You could still give credits to Cohadar though for providing them in the first place.)
  • You didn't mention that your spells need MiscScript. If you made that library by yourself, I think you should also provide the code here as well.
  • In addition to that, you may want to fix your spell descriptions since they don't state all the requirements they need. Example: Twister doesn't say it needs GroupUtils though it credits it.
  • I want to see more things configurable in your spells. =P Such as the area of the spell and attacktype/damagetype/weapontype. Also, the number for the dummy unit creation should be configurable as well.
  • You can still use a loop for certain aspects of your dummy unit creation. A formula could be derived by using modulo.
    JASS:
    local integer i = 0
    local integer mod
    local integer multi
    loop
        //Every fifth one, 90 should be negative, yes? However, i goes by 0 so we'll look for multiples of 4
        set mod = i - (i/4)*4
        if mod == 0 then //mod should be 0 if i is divisible by 4.
            set multi = -1    
        else
            set multi = 1    
        endif
        set d.d[i] = CreateUnit(GetOwningPlayer(d.c),DUMMYID,GetPPX(d.dx,d.h*d.hs[i],d.df+multi*90.),GetPPY(d.dy,d.h*d.hs[i],d.df+multi*90.),d.df+multi*90)
        call SetUnitZ(d.d[i],d.hb)
        call SetUnitVertexColor(d.d[i], 255, 255, 255, 0)
        //If i is divisble by 2 then we should set d.inc[i] to true. Else, set it to false
        set mod = i - (i/2)*2
        if mod == 0 then
            set d.inc[i] = true
        else
            set d.inc[i] = false
        endif
        exitwhen i == 5 //5 should be configurable
        set i = i + 1
    endloop
    I didn't do this for d.hs though since it seemed random as you said. It would be good if you could though since it makes it much easier to modify that spell.
 
Top