1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Seek unity between the elements in the 22nd Terraining Contest Poll.
    Dismiss Notice
  3. Seize the moment! The 18th Mini Mapping Contest has commenced.
    Dismiss Notice
  4. The heavens smile on the old faithful. The 16th Techtree Contest has begun.
    Dismiss Notice
  5. 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.

[vJASS] Wrath of Zeus

Submitted by Prince.Zero
This bundle is marked as approved. It works and satisfies the submission rules.
Credits Distribution: Vexorian (dummy.mdx model), Pharaoh_ suggestions and support, RisingDusk GroupUtils (OPTIONAL!)

For GroupUtils click -> http://www.wc3c.net/showthread.php?t=104464

Version 1.3
Wrath of Zeus
Dedicated to Pharaoh_ from Greece! Show some love for the Greek Gods!
haha :)

Documentation

Here
Unleashes a static thunder bolt towards a target enemy unit, dealing moderate damage. Upon impact, the bolt unleashes several lightning bolts towards all directions dealing secondary damage to units in their wake.
-------
Requires the JNGP to compile
You need the dummy.mdx model included in if you don't have it!
If you don't have a universal dummy unit i suggest you copy mine! (e001)
-------
Unfortunately i've dissalowed the user to config some vital code because i thought it would be better not to mess it up.
-------
Copy the map code and paste it on your map
Create the spell based on channel ability
If you don't have a dummy then make one
Configure the script at the top (globals)
Enjoy


Map Code
Spoiler!
Code (vJASS):
library WrathOfZeus initializer init requires optional GroupUtils

    globals
        private constant integer ABILITY_ID = 'A000'  //Raw code of the triggering ability
        private constant integer DUMMY_ID = 'e001' //The dummy unit, please import dummy.mdl and make a proper dummy unit
        private constant integer STATIC_LINKS = 32 //The links that are created when the orb crashes
        private constant integer CHARGED_BOLTS_AMOUNT = 3 //The amount of orbiting missiles that are created around the caster when the ability is learned
        private constant real CHARGED_BOLTS_SIZE = .88 //The scale value of the orbiting missiles
        private constant real PRIMARY_BASE_DAMAGE = 130 //The base damage when the orb crashes
        private constant real PRIMARY_INC_DAMAGE = 75 // The increment damage of the orb
        private constant real SECONDARY_BASE_DAMAGE = 50 //The damage each static link deals
        private constant real SECONDARY_INC_DAMAGE = 25 // The increment damage of each static link
        private constant real BOLT_SCALE = 2.75 //The scale of the lightning bolt
        private constant real NORMAL_OFFSET = 145 //The default rotating offset of the orbiting bolts
        private constant real MAX_OFFSET = 425 //The maximum rotating offset the bolts can reach when overloading
        private constant real ENUM_OFFSET = 75 //the range that units are checked from each static link. You should decrease this if you use a LOT of static links!
        private constant string BALL_ART = "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl" //The missiles that rotate around the cast
        private constant string TAIL_LIGHTNING = "CLPB" //The lightning tail of the bolt
        private constant string CHARGED_LIGHTNING = "CLSB" //The lightning tail of the secondary static links
        private constant string ORBITAL_LIGHTNING = "DRAB" //The lightning that links all the orbital missiles
        private constant string BOLT_LIGHTNING = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl" //The lightning bolt art
        private constant string PRIMARY_EFFECT = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl" //The effect that is created upon impact
        private constant string SECONDARY_EFFECT = "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldBuff.mdl" //The effect that is created on damaged units of secondary effect
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
        private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
        ///
        private constant boolean USE_GROUPUTILS = true //Whether to use Group utils library, if the library isn't found, it will CreateGroup() instead
        ///
    endglobals
   
   
    ////===============
   
   
    globals
        private location loc = Location(0, 0)
        private location loc2 = Location(0, 0)
        private integer instance = 0
        private boolexpr BE
        private constant group Group = CreateGroup()
        private constant integer Cbolts = CHARGED_BOLTS_AMOUNT - 1
        private real MINX
        private real MINY
        private real MAXX
        private real MAXY
    endglobals
   
    /////=================
    //Extra functions
   
    //
    private function SafeX takes real x returns real
       local real rx=MINX+50
       if(x<rx)then
           return rx
       endif
       set rx=MAXX-50
       if(x>rx)then
           return rx
       endif
       return x
    endfunction

    private function SafeY takes real y returns real
       local real ry=MINY+50
       if(y<ry)then
           return ry
       endif
       set ry=MAXY-50
       if(y>ry)then
           return ry
       endif
       return y
    endfunction
   
    /////////=======================================
   
    private struct spark
        unit u
        lightning l        
        real ang
        real sx
        real sy
        real x
        real y
        real time = 1.5
        real time2 = 2
        real dmg
        group damaged
        static integer tot = 0
        static spark array ar
        static timer stim = CreateTimer()
         
         static method SecondaryEffects takes unit u, unit t, real x, real y returns nothing
             local integer i = 1
             local spark data
             loop
             exitwhen i > STATIC_LINKS
                set data = spark.create()
                set data.u = u
                set data.sx = x
                set data.sy = y
                set data.x = x
                set data.y = y
                set data.ang = (360 / STATIC_LINKS) * i
                static if USE_GROUPUTILS then
                    static if LIBRARY_GroupUtils then
                        set data.damaged = NewGroup()
                    else
                        set data.damaged = CreateGroup()
                        debug call BJDebugMsg(LIBRARY_PREFIX+": Could not find GroupUtils")
                    endif
                else    
                    set data.damaged = CreateGroup()
                endif    
                if t != null then
                   call GroupAddUnit(data.damaged, t)
                endif  
                set data.dmg = SECONDARY_BASE_DAMAGE + (SECONDARY_INC_DAMAGE * (GetUnitAbilityLevel(data.u, ABILITY_ID) - 1))
                set data.l = AddLightning(CHARGED_LIGHTNING, true, x, y, x+5, y+5)
                call SetLightningColor(data.l, .7, .7, 1, .7)
                if spark.tot == 0 then
                    call TimerStart(spark.stim, .042, true, function spark.Loop)
                endif
                set spark.ar[spark.tot] = data
                set spark.tot = spark.tot + 1
                set i = i + 1
                endloop        
        endmethod
   
        static method Enum takes nothing returns boolean
            local spark data = instance
            local unit e = GetFilterUnit()
            if IsUnitInGroup(e, data.damaged) then
                set e = null
                return false
            else
                if (not(IsUnitType(e, UNIT_TYPE_STRUCTURE))) and (GetWidgetLife(e)>.405) and (IsUnitEnemy(e, GetOwningPlayer(data.u))) then
                    call DestroyEffect(AddSpecialEffectTarget(SECONDARY_EFFECT, e, "origin"))
                    call UnitDamageTarget(data.u, e, data.dmg, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
                    call GroupAddUnit(data.damaged, e)
                endif    
            endif  
            set e = null
            return false
        endmethod
   
        static method Loop takes nothing returns nothing
            local spark data
            local integer i = 0
            local real p
            loop
            exitwhen i >= spark.tot
                set data = spark.ar[i]
                if data.time > 0 then
                    set data.time = data.time - .042
                    set data.x = SafeX(data.x + 30 * Cos(data.ang * bj_DEGTORAD))
                    set data.y = SafeX(data.y + 30 * Sin(data.ang * bj_DEGTORAD))
                    set p = SquareRoot((data.x - data.sx) * (data.x - data.sx) + (data.y - data.sy) * (data.y - data.sy))
                    if p > 450 then
                        set data.sx = data.sx + 30 * Cos(data.ang * bj_DEGTORAD)
                        set data.sy = data.sy + 30 * Sin(data.ang * bj_DEGTORAD)
                    endif
                    set instance = data
                    call GroupEnumUnitsInRange(Group, data.x, data.y, ENUM_OFFSET, BE)
                    call MoveLocation(loc, data.sx, data.sy)
                    call MoveLocation(loc2, data.x, data.y)
                    call MoveLightningEx(data.l, true, data.sx, data.sy, GetLocationZ(loc), data.x, data.y, GetLocationZ(loc2))
                else
                    if (SquareRoot((data.x - data.sx) * (data.x - data.sx) + (data.y - data.sy) * (data.y - data.sy)) > 50) and data.time2 > 0 then
                        set data.sx = data.sx + 30 * Cos(data.ang * bj_DEGTORAD)
                        set data.sy = data.sy + 30 * Sin(data.ang * bj_DEGTORAD)
                        call MoveLocation(loc, data.sx, data.sy)
                        call MoveLocation(loc2, data.x, data.y)
                        call MoveLightningEx(data.l, true, data.sx, data.sy, GetLocationZ(loc), data.x, data.y, GetLocationZ(loc2))
                        set instance = data
                        call GroupEnumUnitsInRange(Group, data.sx, data.sy, 125, BE)
                        set data.time2 = data.time2 - .04            
                    else
                        call data.destroy()
                        set spark.tot = spark.tot - 1
                        set spark.ar[i] = spark.ar[spark.tot]
                    endif
                endif
                set i = i + 1
            endloop
            if spark.tot == 0 then
                call PauseTimer(spark.stim)
            endif
        endmethod
       
        method onDestroy takes nothing returns nothing
            call DestroyLightning(.l)
            static if USE_GROUPUTILS then
                static if LIBRARY_GroupUtils then
                    call ReleaseGroup(.damaged)
                else
                    call DestroyGroup(.damaged)
                    debug call BJDebugMsg(LIBRARY_PREFIX+": Could not find GroupUtils")
                endif
            else    
                call DestroyGroup(.damaged)
            endif    
        endmethod    
    endstruct    
   
   
    private struct bolt
        unit u
        unit t
        unit d
        real damage
        lightning l
        effect art
        static integer total = 0
        static bolt array arr
        static timer tim = CreateTimer()
   
        static method create takes unit u, unit t returns bolt        
            local bolt data = bolt.allocate()
            local real x
            local real y
            local real x2
            local real y2
            local sound snd
            local string array s
            local integer r = GetRandomInt(0, 1)
            set s[0] = "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.wav"
            set s[1] = "Abilities\\Spells\\Orc\\LightningBolt\\LightningBolt.wav"
            set data.u = u
            set snd = CreateSound(s[r], false, false, true, 12700, 12700, "")
            set x = GetUnitX(data.u) + 100 * Cos(GetUnitFacing(data.u) * bj_DEGTORAD)
            set y = GetUnitY(data.u) + 100 * Sin(GetUnitFacing(data.u) * bj_DEGTORAD)
            set data.d = CreateUnit(GetOwningPlayer(data.u), DUMMY_ID, x, y, 0)
            call AttachSoundToUnit(snd, data.d)
            set x2 = GetUnitX(data.d) + 200 * Cos((GetUnitFacing(data.u)-180) * bj_DEGTORAD)
            set y2 = GetUnitY(data.d) + 200 * Sin((GetUnitFacing(data.u)-180) * bj_DEGTORAD)
            set data.t = t
            call UnitAddAbility(data.d, 'Amrf')
            call UnitRemoveAbility(data.d, 'Amrf')
            call SetUnitFlyHeight(data.d, 90, 550)
            call SetUnitTimeScale(data.d, 0)
            call SetUnitScale(data.d, BOLT_SCALE, BOLT_SCALE, BOLT_SCALE)
            set data.l = AddLightning(TAIL_LIGHTNING, true, x2, y2, x, y)
            call StartSound(snd)
            call KillSoundWhenDone(snd)
            set snd = null
            set data.damage = PRIMARY_BASE_DAMAGE + (PRIMARY_INC_DAMAGE * (GetUnitAbilityLevel(data.u, ABILITY_ID)-1))
            set data.art = AddSpecialEffectTarget(BOLT_LIGHTNING, data.d, "origin")
            if bolt.total == 0 then
                call TimerStart(bolt.tim, .0303, true, function bolt.Loop)
            endif
            set bolt.arr[bolt.total] = data
            set bolt.total = bolt.total + 1
            call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\StormBolt\\StormBoltMissile.mdl", data.u, "weapon,right"))
            call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl", data.d, "origin"))
            return data
        endmethod
   
        static method Loop takes nothing returns nothing
            local bolt data
            local integer i = 0
            local real p = 0
            local real a=0
            local real x=0
            local real y=0
            local real x2=0
            local real y2=0
            local real z=0
            local real d=0
            local real dx=0
            local real dy=0
            loop
            exitwhen i >= bolt.total
                set data = bolt.arr[i]
                set x = GetUnitX(data.d)
                set y = GetUnitY(data.d)
                set x2 = GetUnitX(data.t)
                set y2 = GetUnitY(data.t)
                set a = bj_RADTODEG * Atan2(y2 - y, x2 - x)
                call SetUnitFacing(data.d, a)
                if IsUnitInRange(data.d, data.t, 50) then
                    call DestroyEffect(data.art)
                    call KillUnit(data.d)
                    call DestroyEffect(AddSpecialEffectTarget(PRIMARY_EFFECT, data.t, "origin"))
                    call UnitDamageTarget(data.u, data.t, data.damage, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
                    call spark.SecondaryEffects(data.u, data.t, x2, y2)
                    call DestroyLightning(data.l)
                    set data.d = CreateUnit(Player(12), DUMMY_ID, x2, y2, 0)
                    call SetUnitScale(data.d, 3.5, 3.5, 3.5)
                    call SetUnitVertexColor(data.d, 170, 170, 255, 255)
                    call DestroyEffect(AddSpecialEffectTarget(PRIMARY_EFFECT, data.d, "origin"))
                    call KillUnit(data.d)
                    call data.destroy()
                    set bolt.total = bolt.total - 1
                    set bolt.arr[i] = bolt.arr[bolt.total]
                else    
                    set p = SquareRoot((x - x2) * (x - x2) + (y - y2) * (y - y2))
                    set d = 17 + (p * .012)
                ///------------------------------------
                    set dx = SafeX(x + d * Cos(a * bj_DEGTORAD))
                    set dy = SafeY(y + d * Sin(a * bj_DEGTORAD))
                    call SetUnitX(data.d, dx)
                    call SetUnitY(data.d, dy)
                ////-----------------------------------
                    set x = GetUnitX(data.d)
                    set y = GetUnitY(data.d)
                    set a = (a-180)
                    set dx = x + 200 * Cos(a * bj_DEGTORAD)
                    set dy = y + 200 * Sin(a * bj_DEGTORAD)
                    call MoveLocation(loc, dx, dy)
                    call MoveLocation(loc2, x, y)
                    call MoveLightningEx(data.l, true, dx, dy, (GetLocationZ(loc)+90), x, y, (GetLocationZ(loc2)+GetUnitFlyHeight(data.d)))
                endif
                set i = i + 1
            endloop
            if bolt.total == 0 then
                call PauseTimer(bolt.tim)
            endif
        endmethod  
   
    endstruct  
   
    // Charged bolts //
    private struct Charged
        unit u
        unit array mis[CHARGED_BOLTS_AMOUNT]
        real array fh[CHARGED_BOLTS_AMOUNT]
        real array fi[CHARGED_BOLTS_AMOUNT]
        real array x[CHARGED_BOLTS_AMOUNT]
        lightning array l[CHARGED_BOLTS_AMOUNT]
        lightning array l2[CHARGED_BOLTS_AMOUNT]
        boolean array fb[CHARGED_BOLTS_AMOUNT]
        effect array fx[CHARGED_BOLTS_AMOUNT]
        boolean dead = false //If the flag is turned on, the charged bolts dissapear until the hero is alive again
        real tick = 0
        real xtick = .94 //Defines the duration of the lightning rotation
        real rat = SquareRoot(NORMAL_OFFSET) / bj_PI
        real limit = NORMAL_OFFSET
        boolean charged = false
        static thistype array arr
        static integer total = 0
        static timer tim = CreateTimer()
        ////
        private static string str1 = "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldBuff.mdl"
        ////
        static method create takes unit u returns thistype
            local thistype this = thistype.allocate()
            local integer i = 0
            local trigger t = CreateTrigger()
            local real x
            local real y
            local real cx = GetUnitX(u)
            local real cy = GetUnitY(u)
            set this.u = u
            loop
            exitwhen i > Cbolts
                set this.mis[i] = CreateUnit(GetOwningPlayer(u), 'e001', GetUnitX(u), GetUnitY(u), 0)
                set this.fx[i] = AddSpecialEffectTarget(BALL_ART , this.mis[i], "origin")
                set x = cx + 60 * Cos(( (360 / (Cbolts+1)) * (i+1) )  * bj_DEGTORAD)
                set y = cy + 60 * Sin(( (360 / (Cbolts+1)) * (i+1) )  * bj_DEGTORAD)
                call SetUnitX(this.mis[i], x)
                call SetUnitY(this.mis[i], y)
                call UnitAddAbility(this.mis[i], 'Amrf')
                call SetUnitTimeScale(this.mis[i], 0)
                call UnitRemoveAbility(this.mis[i], 'Amrf')
                set this.fh[i] = 30 * i
                call SetUnitFlyHeight(this.mis[i], this.fh[i], 0)
                call SetUnitScale(this.mis[i], CHARGED_BOLTS_SIZE, CHARGED_BOLTS_SIZE, CHARGED_BOLTS_SIZE)
                set this.fb[i] = true
                set this.x[i] = bj_RADTODEG * Atan2(y - cy, x - cx)
                set i = i + 1
            endloop    
            call TriggerAddCondition(t, Condition(function Charged.ready))
            call TriggerRegisterUnitEvent(t, u, EVENT_UNIT_SPELL_CAST)
            if thistype.total == 0 then
                call TimerStart(thistype.tim, .047, true, function Charged.fly)
            endif
            set thistype.total = thistype.total + 1
            set thistype.arr[thistype.total - 1] = this
            return this
        endmethod
       
        static method ready takes nothing returns boolean
            local thistype this
            local integer i = 0
            local integer k = 0
            local sound snd
            if GetSpellAbilityId()!= ABILITY_ID then
                return false
            else
                set this = thistype.GetInstance(GetTriggerUnit())
                if this.charged then
                    return false
                endif    
                set snd = CreateSound("Units\\Orc\\StasisTotem\\StasisTotem.wav", false, false, true, 12700, 12700, "")
                call AttachSoundToUnit(snd, GetTriggerUnit())
                set this.charged = true
                set this.xtick = .8
                set this.rat = this.rat + SquareRoot(MAX_OFFSET)
                set this.limit = MAX_OFFSET
                call StartSound(snd)
                call KillSoundWhenDone(snd)
                set snd = null
                loop
                exitwhen i>Cbolts
                    set k = i + 1
                    if k > Cbolts then
                        set k = 0
                    endif        
                    set this.l[i] = AddLightning(CHARGED_LIGHTNING, true, GetUnitX(this.mis[i]), GetUnitY(this.mis[i]), GetUnitX(this.u), GetUnitY(this.u))
                    call SetLightningColor(this.l[i], 1, 1, 1, .6)
                    set this.l2[i] = AddLightning(ORBITAL_LIGHTNING, true, GetUnitX(this.mis[i]), GetUnitY(this.mis[i]),  GetUnitX(this.mis[k]), GetUnitY(this.mis[k]))
                    call SetLightningColor(this.l2[i], .3, .1, 1, 1)  
                    set i = i + 1            
                endloop    
            endif
            return false
        endmethod
       
        static method GetInstance takes unit u returns integer
            local thistype this
            local integer i = 0
            loop
            exitwhen i >= thistype.total
                set this = thistype.arr[i]
                if IsUnit(u, this.u) then
                    return this
                endif
                set i = i + 1
            endloop
            return 0
        endmethod    
                   
        static method fly takes nothing returns nothing
            local thistype this
            local integer i = 0
            local integer k = 0
            local real x =0
            local real y =0
            local real cx
            local real cy
            local integer j = 0
            loop
            exitwhen i >= thistype.total
                set this = thistype.arr[i]
                set k = 0
                set j = 0
                set cx = GetUnitX(this.u)
                set cy = GetUnitY(this.u)
                loop
                exitwhen k > Cbolts
                    set j = k + 1
                    if j > Cbolts then
                        set j = 0
                    endif  
                    if (not(this.dead)) and this.mis[k] != null then
                        if this.fb[k] then            
                            set this.fh[k] = this.fh[k] + 3
                        else
                            set this.fh[k] = this.fh[k] - 3
                        endif
                        if GetUnitFlyHeight(this.mis[k])<50 then
                            set this.fb[k] = true
                        elseif GetUnitFlyHeight(this.mis[k]) > 275 then
                            set this.fb[k] = false
                        endif    
                        set this.tick = this.tick + .047
                        call SetUnitFlyHeight(this.mis[k], this.fh[k], 530)
                        set this.x[k] = this.x[k] + 4
                        if this.rat < this.limit then
                            set this.rat = this.rat + 2
                        elseif this.rat > this.limit then
                            set this.rat = this.rat - .5
                        endif    
                        set x = cx + this.rat * Cos(this.x[k] * bj_DEGTORAD)
                        set y = cy + this.rat * Sin(this.x[k] * bj_DEGTORAD)
                        call SetUnitX(this.mis[k], x)
                        call SetUnitY(this.mis[k], y)
                        if this.charged then
                            if this.xtick > 0 then
                                set this.x[k] = this.x[k] + 6
                                call MoveLocation(loc, x, y)
                                call MoveLocation(loc2, GetUnitX(this.u), GetUnitY(this.u))
                                call MoveLightningEx(this.l[k], true, x, y, (GetLocationZ(loc)+GetUnitFlyHeight(this.mis[k])), cx, cy, (GetLocationZ(loc2)+GetUnitFlyHeight(this.u)+20))
                                call MoveLocation(loc2, GetUnitX(this.mis[j]), GetUnitY(this.mis[j]))
                                call MoveLightningEx(this.l2[k], true, x, y, (GetLocationZ(loc)+GetUnitFlyHeight(this.mis[k])), GetUnitX(this.mis[j]), GetUnitY(this.mis[j]), (GetLocationZ(loc2)+GetUnitFlyHeight(this.mis[j])))
                            else
                                call DestroyLightning(this.l[k])
                                call DestroyLightning(this.l2[k])
                            endif
                        endif    
                        if this.tick > 1.75 then
                            set this.tick = 0
                            call DestroyEffect(AddSpecialEffectTarget(thistype.str1 , this.mis[k], "origin"))
                        endif    
                    endif  
                    set k = k + 1
                endloop
                if this.charged then
                    if this.xtick > 0 then
                        set this.xtick = this.xtick - .05
                    else
                        set this.charged = false
                        set this.limit = NORMAL_OFFSET
                    endif
                endif    
                if GetWidgetLife(this.u)<.405 then
                    call this.hide()
                    set this.dead = true
                elseif GetWidgetLife(this.u)>=.405 and this.dead then
                     set this.dead = false
                     call this.show()
                 endif    
                set i = i + 1
            endloop
        endmethod
       
        method hide takes nothing returns nothing
            local integer i = 0
            loop
            exitwhen i > Cbolts
                if .mis[i] != null then
                    //call UnitRemoveAbility(.mis[i], 'Aloc')
                    call ShowUnit(.mis[i], false)
                endif
                set i = i + 1
            endloop
        endmethod    
       
        method show takes nothing returns nothing
            local integer i = 0
            loop
            exitwhen i > Cbolts
                if .mis[i] != null then
                    call ShowUnit(.mis[i], true)
                    call UnitAddAbility(.mis[i], 'Aloc')
                endif
                set i = i + 1
            endloop
        endmethod      
    endstruct    
   
    ///////===================\\\\\\\
   
    private function BoltStart takes nothing returns nothing
        call bolt.create(GetTriggerUnit(), GetSpellTargetUnit())
    endfunction
   
    private function IsBolt takes nothing returns boolean
        return GetSpellAbilityId() == ABILITY_ID
    endfunction
   
    private function BoltCharge takes nothing returns boolean
        if GetLearnedSkill() == ABILITY_ID then
            if GetUnitAbilityLevel(GetTriggerUnit(), ABILITY_ID)<2 then
                call Charged.create(GetTriggerUnit())
            endif
        endif
        return false
    endfunction    
   
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger ( )
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t, Condition(function IsBolt))
        call TriggerAddAction(t, function BoltStart)
        set t = CreateTrigger( )
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_SKILL)
        call TriggerAddCondition(t, Condition(function BoltCharge))
        set t = null
        set BE = Condition(function spark.Enum)
        set MINX = GetRectMinX(bj_mapInitialPlayableArea)
        set MINY = GetRectMinY(bj_mapInitialPlayableArea)
        set MAXX = GetRectMaxX(bj_mapInitialPlayableArea)
        set MAXY = GetRectMaxY(bj_mapInitialPlayableArea)
    endfunction
endlibrary  


I suggest you turn the sound on if you haven't.

Keywords:
zeus, bolt, lightning, storm, spark, wrath, of, static, charge, charged
Contents

Wrath of Zeus (Map)

Reviews
Moderator
00:04, 24th Aug 2010 TriggerHappy: Why is the trigger entitled Thundergod Bolt when the spells name is Wrath of Zeus? Your constant variables should be in all caps (LIKE_THIS). In programming langauges and even in blizzards jass that is the...
  1. Demongrip

    Demongrip

    Joined:
    Sep 8, 2009
    Messages:
    80
    Resources:
    6
    Spells:
    6
    Resources:
    6
    Was just bored these days and I decided to check the hive when I noticed this spell.Nice sound effects ;)
    Can`t say anything for the coding since I don`t understand jass but from what I`ve seen its pretty nice spell.I`ll give it 5/5 + rep because of it and because some of the effects remind me of my old arcane bolt spell.Mighta start making GUI junk spells again :)
     
  2. light bolt30

    light bolt30

    Joined:
    Jan 31, 2009
    Messages:
    1,839
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Good job on the spell, looking very good in coding and the spells aesthetics.
     
  3. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,379
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    I had a gigantic post telling you a lot of great advice on how to optimize this map and the server gave me a "hiccupping" error. Long story short, I have made a TON of VERY NEEDED optimizations and I strongly recommend you implement this version I've cut out for you (sorry it's uncommented);

    It is less code but with the exact same functionality.

    Code (vJASS):

    library WrathOfZeus initializer init requires optional GroupUtils, optional Recycle

        globals
            private constant integer ABILITY_ID = 'A000'        //Raw code of the triggering ability
            private constant integer DUMMY_ID = 'e001'          //The dummy unit, please import dummy.mdl and make a proper dummy unit
            private constant integer STATIC_LINKS = 32          //The links that are created when the orb crashes
            private constant integer CHARGED_BOLTS_AMOUNT = 3   //The amount of orbiting missiles that are created around the caster when the ability is learned
            private constant real CHARGED_BOLTS_SIZE = 0.88     //The scale value of the orbiting missiles
            private constant real PRIMARY_BASE_DAMAGE = 130.0   //The base damage when the orb crashes
            private constant real PRIMARY_INC_DAMAGE = 75.0     // The increment damage of the orb
            private constant real SECONDARY_BASE_DAMAGE = 50.0  //The damage each static link deals
            private constant real SECONDARY_INC_DAMAGE = 25.0   // The increment damage of each static link
            private constant real BOLT_SCALE = 2.75             //The scale of the lightning bolt
            private constant real NORMAL_OFFSET = 145.0         //The default rotating offset of the orbiting bolts
            private constant real MAX_OFFSET = 425.0            //The maximum rotating offset the bolts can reach when overloading
            private constant real ENUM_OFFSET = 75.0            //the range that units are checked from each static link. You should decrease this if you use a LOT of static links!
            private constant string BALL_ART = "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl"                             //The missiles that rotate around the caster
            private constant string TAIL_LIGHTNING = "CLPB"     //The lightning tail of the bolt
            private constant string CHARGED_LIGHTNING = "CLSB"  //The lightning tail of the secondary static links
            private constant string ORBITAL_LIGHTNING = "DRAB"  //The lightning that links all the orbital missiles
            private constant string BOLT_LIGHTNING = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"   //The lightning bolt art
            private constant string PRIMARY_EFFECT = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"                                     //The effect that is created upon impact
            private constant string SECONDARY_EFFECT = "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldBuff.mdl"           //The effect that is created on damaged units of secondary effect
            private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC
            private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
            private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
            ///
        endglobals
       
       
        ////===============
       
            native UnitAlive takes unit id returns boolean
       
        ////===============
       
       
        globals
            private location loc = Location(0.00, 0.00)
            private boolexpr BE
            private constant group GROUP = CreateGroup()
            private constant integer CHARGED_BOLTS = CHARGED_BOLTS_AMOUNT - 1
            private real MINX
            private real MINY
            private real MAXX
            private real MAXY
        endglobals
       
        /////=================
        //Extra functions
       
        //
        private function SafeX takes real x returns real
           if (x < MINX) then
               set x = MINX
           elseif (x > MAXX) then
               set x = MAXX
           endif
           return x
        endfunction

        private function SafeY takes real y returns real
           if (y < MINY) then
               set y = MINY
           elseif (y > MAXY) then
               set y = MAXY
           endif
           return y
        endfunction
       
        /////////=======================================
       
        private struct spark
            unit u
            lightning l        
            real ang
            real sx
            real sy
            real x
            real y
            real time = 1.5
            real time2 = 2.0
            real dmg
            group damaged
            static spark instance
            static integer tot = 0
            static spark array ar
            static code LoopCode
            static timer stim = CreateTimer()
             
             static method SecondaryEffects takes unit u, unit t, real x, real y returns nothing
                 local integer i = 1
                 local spark dat
                 loop
                    set dat = spark.create()
                    set dat.u = u
                    set dat.sx = x
                    set dat.sy = y
                    set dat.x = x
                    set dat.y = y
                    set dat.ang = (6.28319 / STATIC_LINKS) * i
                    static if (LIBRARY_GroupUtils) then
                        set dat.damaged = NewGroup()
                    elseif (LIBRARY_Recycle) then
                        set dat.damaged = Group.get()
                    else
                        set dat.damaged = CreateGroup()
                    endif    
                    if t != null then
                       call GroupAddUnit(dat.damaged, t)
                    endif  
                    set dat.dmg = SECONDARY_BASE_DAMAGE + SECONDARY_INC_DAMAGE * (GetUnitAbilityLevel(dat.u, ABILITY_ID) - 1)
                    set dat.l = AddLightning(CHARGED_LIGHTNING, true, x, y, x + 5.0, y + 5.0)
                    call SetLightningColor(dat.l, 0.70, 0.70, 1.00, 0.70)
                    if (spark.tot == 0) then
                        call TimerStart(spark.stim, 0.042, true, LoopCode)
                    endif
                    set spark.ar[spark.tot] = dat
                    set spark.tot = spark.tot + 1
                    exitwhen i == STATIC_LINKS
                    set i = i + 1
                endloop        
            endmethod
       
            static method Enum takes nothing returns boolean
                local unit e = GetFilterUnit()
                if (not IsUnitInGroup(e, instance.damaged) and not IsUnitType(e, UNIT_TYPE_STRUCTURE) and UnitAlive(e) and IsUnitEnemy(e, GetOwningPlayer(instance.u))) then
                    call DestroyEffect(AddSpecialEffectTarget(SECONDARY_EFFECT, e, "origin"))
                    call UnitDamageTarget(instance.u, e, instance.dmg, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
                    call GroupAddUnit(instance.damaged, e)
                endif  
                set e = null
                return false
            endmethod
       
            static method Loop takes nothing returns nothing
                local spark dat
                local integer i = 0
                local real p
                local real tempReal
                loop
                    exitwhen i >= spark.tot
                    set dat = spark.ar[i]
                    if dat.time > 0 then
                        set dat.time = dat.time - 0.042
                        set dat.x = SafeX(dat.x + 30.0 * Cos(dat.ang))
                        set dat.y = SafeY(dat.y + 30.0 * Sin(dat.ang))
                        set p = SquareRoot((dat.x - dat.sx) * (dat.x - dat.sx) + (dat.y - dat.sy) * (dat.y - dat.sy))
                        if (p > 450.0) then
                            set dat.sx = dat.sx + 30.0 * Cos(dat.ang)
                            set dat.sy = dat.sy + 30.0 * Sin(dat.ang)
                        endif
                        set instance = dat
                        call GroupEnumUnitsInRange(GROUP, dat.x, dat.y, ENUM_OFFSET, BE)
                        call MoveLocation(loc, dat.sx, dat.sy)
                        set tempReal = GetLocationZ(loc)
                        call MoveLocation(loc, dat.x, dat.y)
                        call MoveLightningEx(dat.l, true, dat.sx, dat.sy, tempReal, dat.x, dat.y, GetLocationZ(loc))
                       
                    elseif (SquareRoot((dat.x - dat.sx) * (dat.x - dat.sx) + (dat.y - dat.sy) * (dat.y - dat.sy)) > 50.0) and dat.time2 > 0.00 then
                        set dat.sx = dat.sx + 30.0 * Cos(dat.ang)
                        set dat.sy = dat.sy + 30.0 * Sin(dat.ang)
                        call MoveLocation(loc, dat.sx, dat.sy)
                        set tempReal = GetLocationZ(loc)
                        call MoveLocation(loc, dat.x, dat.y)
                        call MoveLightningEx(dat.l, true, dat.sx, dat.sy, tempReal, dat.x, dat.y, GetLocationZ(loc))
                        set instance = dat
                        call GroupEnumUnitsInRange(GROUP, dat.sx, dat.sy, 125.0, BE)
                        set dat.time2 = dat.time2 - 0.040
                    else
                        call dat.destroy()
                        set spark.tot = spark.tot - 1
                        set spark.ar[i] = spark.ar[spark.tot]
                    endif
                    set i = i + 1
                endloop
                if (spark.tot == 0) then
                    call PauseTimer(spark.stim)
                endif
            endmethod
           
            private static method onInit takes nothing returns nothing
                set LoopCode = function spark.Loop
            endmethod
           
            private method onDestroy takes nothing returns nothing
                call DestroyLightning(this.l)
                static if (LIBRARY_GroupUtils) then
                    call ReleaseGroup(this.damaged)
                elseif (LIBRARY_Recycle) then
                    call Group.release(this.damaged)
                else
                    call GroupClear(this.damaged)
                    call DestroyGroup(this.damaged)
                endif    
            endmethod    
        endstruct    
       
       
        private struct bolt
            unit u
            unit t
            unit d
            real damage
            lightning l
            effect art
            static integer total = 0
            static bolt array arr
            static timer tim = CreateTimer()
       
            static method Loop takes nothing returns nothing
                local bolt dat
                local integer i = 0
                local real a
                local real x
                local real y
                local real x2
                local real y2
                local real distance
                local real tempReal
                loop
                    exitwhen i >= bolt.total
                    set dat = bolt.arr[i]
                    set x = GetUnitX(dat.d)
                    set y = GetUnitY(dat.d)
                    set x2 = GetUnitX(dat.t)
                    set y2 = GetUnitY(dat.t)
                    set a = Atan2(y2 - y, x2 - x)
                    call SetUnitFacing(dat.d, a * bj_RADTODEG)
                    if (IsUnitInRange(dat.d, dat.t, 50.0)) then
                        call DestroyEffect(dat.art)
                        call KillUnit(dat.d)
                        call DestroyEffect(AddSpecialEffectTarget(PRIMARY_EFFECT, dat.t, "origin"))
                        call UnitDamageTarget(dat.u, dat.t, dat.damage, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
                        call spark.SecondaryEffects(dat.u, dat.t, x2, y2)
                        call DestroyLightning(dat.l)
                        set dat.d = CreateUnit(Player(15), DUMMY_ID, x2, y2, 0)
                        call SetUnitScale(dat.d, 3.5, 3.5, 3.5)
                        call SetUnitVertexColor(dat.d, 170, 170, 255, 255)
                        call DestroyEffect(AddSpecialEffectTarget(PRIMARY_EFFECT, dat.d, "origin"))
                        call KillUnit(dat.d)
                        call dat.destroy()
                        set bolt.total = bolt.total - 1
                        set bolt.arr[i] = bolt.arr[bolt.total]
                    else    
                        set distance = 17.0 + SquareRoot((x - x2) * (x - x2) + (y - y2) * (y - y2)) * 0.012
                    ///------------------------------------
                        set x2 = SafeX(x + distance * Cos(a))
                        set y2 = SafeY(y + distance * Sin(a))
                        call SetUnitX(dat.d, x2)
                        call SetUnitY(dat.d, y2)
                    ////-----------------------------------
                        set x = GetUnitX(dat.d)
                        set y = GetUnitY(dat.d)
                        set a = (a - bj_PI)
                        set x2 = x + 200.0 * Cos(a)
                        set y2 = y + 200.0 * Sin(a)
                        call MoveLocation(loc, x2, y2)
                        set tempReal = GetLocationZ(loc) + 90.0
                        call MoveLocation(loc, x, y)
                        call MoveLightningEx(dat.l, true, x2, y2, tempReal, x, y, GetLocationZ(loc) + GetUnitFlyHeight(dat.d))
                    endif
                    set i = i + 1
                endloop
                if (bolt.total == 0) then
                    call PauseTimer(bolt.tim)
                endif
            endmethod  
       
            static method create takes unit u returns bolt        
                local bolt dat = bolt.allocate()
                local real angle = GetUnitFacing(u) * bj_DEGTORAD
                local real x
                local real y
                local real x2
                local real y2
                local sound snd
                local string s
                if (GetRandomInt(0, 1) == 1) then
                    set s = "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.wav"
                else
                    set s = "Abilities\\Spells\\Orc\\LightningBolt\\LightningBolt.wav"
                endif
                set snd = CreateSound(s, false, false, true, 12700, 12700, "")
                set dat.u = u
                set x = GetUnitX(u) + 100.0 * Cos(angle)
                set y = GetUnitY(u) + 100.0 * Sin(angle)
                set dat.d = CreateUnit(GetTriggerPlayer(), DUMMY_ID, x, y, 0)
                call AttachSoundToUnit(snd, dat.d)
                call StartSound(snd)
                call KillSoundWhenDone(snd)
                set snd = null
                set x2 = GetUnitX(dat.d) + 200.0 * Cos(angle - bj_PI)
                set y2 = GetUnitY(dat.d) + 200.0 * Sin(angle - bj_PI)
                set dat.t = GetSpellTargetUnit()
                call UnitAddAbility(dat.d, 'Amrf')
                call UnitRemoveAbility(dat.d, 'Amrf')
                call SetUnitFlyHeight(dat.d, 90.0, 550.0)
                call SetUnitTimeScale(dat.d, 0.00)
                call SetUnitScale(dat.d, BOLT_SCALE, BOLT_SCALE, BOLT_SCALE)
                set dat.l = AddLightning(TAIL_LIGHTNING, true, x2, y2, x, y)
                set dat.damage = PRIMARY_BASE_DAMAGE + PRIMARY_INC_DAMAGE * (GetUnitAbilityLevel(u, ABILITY_ID) - 1)
                set dat.art = AddSpecialEffectTarget(BOLT_LIGHTNING, dat.d, "origin")
                if bolt.total == 0 then
                    call TimerStart(bolt.tim, 0.0303, true, function bolt.Loop)
                endif
                set bolt.arr[bolt.total] = dat
                set bolt.total = bolt.total + 1
                call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\StormBolt\\StormBoltMissile.mdl", u, "weapon,right"))
                call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl", dat.d, "origin"))
                return dat
            endmethod
       
        endstruct  
       
        // Charged bolts //
        private struct Charged
            unit u
            unit array mis[CHARGED_BOLTS_AMOUNT]
            real array fh[CHARGED_BOLTS_AMOUNT]
            real array fi[CHARGED_BOLTS_AMOUNT]
            real array x[CHARGED_BOLTS_AMOUNT]
            lightning array l[CHARGED_BOLTS_AMOUNT]
            lightning array l2[CHARGED_BOLTS_AMOUNT]
            boolean array fb[CHARGED_BOLTS_AMOUNT]
            effect array fx[CHARGED_BOLTS_AMOUNT]
            boolean dead = false //If the flag is turned on, the charged bolts dissapear until the hero is alive again
            real tick = 0.00
            real xtick = 0.94 //Defines the duration of the lightning rotation
            real rat = SquareRoot(NORMAL_OFFSET) / bj_PI
            real limit = NORMAL_OFFSET
            boolean charged = false
            static thistype array arr
            static integer total = 0
            static timer tim = CreateTimer()
           
            static method GetInstance takes unit u returns thistype
                local integer i = 0
                loop
                    exitwhen i >= thistype.total
                    if (u == thistype.arr[i].u) then
                        return thistype.arr[i]
                    endif
                    set i = i + 1
                endloop
                return 0
            endmethod
           
            static method ready takes nothing returns boolean
                local thistype dat
                local integer i = 0
                local integer k
                local sound snd
                local real x
                local real y
                if (GetSpellAbilityId() == ABILITY_ID) then
                    set dat = GetInstance(GetTriggerUnit())
                    if (not dat.charged) then
                        set snd = CreateSound("Units\\Orc\\StasisTotem\\StasisTotem.wav", false, false, true, 12700, 12700, "")
                        call AttachSoundToUnit(snd, GetTriggerUnit())
                        call StartSound(snd)
                        call KillSoundWhenDone(snd)
                        set snd = null
                        set dat.charged = true
                        set dat.xtick = 0.80
                        set dat.rat = dat.rat + SquareRoot(MAX_OFFSET)
                        set dat.limit = MAX_OFFSET
                        loop
                            set k = i + 1
                            if (k > CHARGED_BOLTS) then
                                set k = 0
                            endif
                            set x = GetUnitX(dat.mis[i])
                            set y = GetUnitY(dat.mis[i])
                            set dat.l[i] = AddLightning(CHARGED_LIGHTNING, true, x, y, GetUnitX(dat.u), GetUnitY(dat.u))
                            call SetLightningColor(dat.l[i], 1.00, 1.00, 1.00, 0.60)
                            set dat.l2[i] = AddLightning(ORBITAL_LIGHTNING, true, x, y,  GetUnitX(dat.mis[k]), GetUnitY(dat.mis[k]))
                            call SetLightningColor(dat.l2[i], 0.30, 0.10, 1.00, 1.00)  
                            exitwhen i == CHARGED_BOLTS
                            set i = i + 1            
                        endloop    
                    endif
                endif
                return false
            endmethod
           
            method hide takes nothing returns nothing
                local integer i = 0
                loop
                    if this.mis[i] != null then
                        //call UnitRemoveAbility(.mis[i], 'Aloc')
                        call ShowUnit(this.mis[i], false)
                    endif
                    exitwhen i == CHARGED_BOLTS
                    set i = i + 1
                endloop
            endmethod    
           
            method show takes nothing returns nothing
                local integer i = 0
                loop
                    if this.mis[i] != null then
                        call ShowUnit(this.mis[i], true)
                        call UnitAddAbility(this.mis[i], 'Aloc')
                    endif
                    exitwhen i == CHARGED_BOLTS
                    set i = i + 1
                endloop
            endmethod
           
            static method fly takes nothing returns nothing
                local thistype this
                local integer i = 0
                local integer k = 0
                local real x =0
                local real y =0
                local real cx
                local real cy
                local real tempReal
                local real tempX
                local real tempY
                local integer j = 0
                loop
                    exitwhen i >= thistype.total
                    set this = thistype.arr[i]
                    set k = 0
                    set j = 0
                    set cx = GetUnitX(this.u)
                    set cy = GetUnitY(this.u)
                    loop
                        set j = k + 1
                        if j > CHARGED_BOLTS then
                            set j = 0
                        endif  
                        if (not(this.dead)) and this.mis[k] != null then
                            if this.fb[k] then            
                                set this.fh[k] = this.fh[k] + 3.00
                            else
                                set this.fh[k] = this.fh[k] - 3.00
                            endif
                            set tempReal = GetUnitFlyHeight(this.mis[k])
                            if tempReal < 50.0 then
                                set this.fb[k] = true
                            elseif tempReal > 275.0 then
                                set this.fb[k] = false
                            endif    
                            set this.tick = this.tick + .047
                            call SetUnitFlyHeight(this.mis[k], this.fh[k], 530.0)
                            set this.x[k] = this.x[k] + 0.0698
                            if (this.rat < this.limit) then
                                set this.rat = this.rat + 2.00
                            elseif (this.rat > this.limit) then
                                set this.rat = this.rat - 0.50
                            endif    
                            set x = cx + this.rat * Cos(this.x[k])
                            set y = cy + this.rat * Sin(this.x[k])
                            call SetUnitX(this.mis[k], x)
                            call SetUnitY(this.mis[k], y)
                            if (this.charged) then
                                if (this.xtick > 0.00) then
                                    set this.x[k] = this.x[k] + 0.10472
                                    call MoveLocation(loc, x, y)
                                    set tempReal = GetLocationZ(loc) + GetUnitFlyHeight(this.mis[k])
                                    call MoveLocation(loc, cx, cy)
                                    call MoveLightningEx(this.l[k], true, x, y, tempReal, cx, cy, GetLocationZ(loc) + GetUnitFlyHeight(this.u) + 20.0)
                                    set tempX = GetUnitX(this.mis[j])
                                    set tempY = GetUnitY(this.mis[j])
                                    call MoveLocation(loc, tempX, tempY)
                                    call MoveLightningEx(this.l2[k], true, x, y, tempReal, tempX, tempY, GetLocationZ(loc) + GetUnitFlyHeight(this.mis[j]))
                                else
                                    call DestroyLightning(this.l[k])
                                    call DestroyLightning(this.l2[k])
                                endif
                            endif    
                            if this.tick > 1.75 then
                                set this.tick = 0
                                call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Orc\\LightningShield\\LightningShieldBuff.mdl", this.mis[k], "origin"))
                            endif    
                        endif
                        exitwhen k == CHARGED_BOLTS
                        set k = k + 1
                    endloop
                    if this.charged then
                        if this.xtick > 0.00 then
                            set this.xtick = this.xtick - 0.05
                        else
                            set this.charged = false
                            set this.limit = NORMAL_OFFSET
                        endif
                    endif
                    if not UnitAlive(this.u) then
                        call this.hide()
                        set this.dead = true
                    elseif this.dead then
                        set this.dead = false
                        call this.show()
                    endif
                    set i = i + 1
                endloop
            endmethod
                 
            static method create takes unit u returns thistype
                local thistype dat = thistype.allocate()
                local integer i = 0
                local real x
                local real y
                local real cx = GetUnitX(u)
                local real cy = GetUnitY(u)
                set dat.u = u
                loop
                    set dat.mis[i] = CreateUnit(GetTriggerPlayer(), 'e001', cx, cy, 0.00)
                    set dat.fx[i] = AddSpecialEffectTarget(BALL_ART , dat.mis[i], "origin")
                    set x = cx + 60.0 * Cos(6.2831853 / (CHARGED_BOLTS + 1) * (i + 1))
                    set y = cy + 60.0 * Sin(6.2831853 / (CHARGED_BOLTS + 1) * (i + 1))
                    call SetUnitX(dat.mis[i], x)
                    call SetUnitY(dat.mis[i], y)
                    call UnitAddAbility(dat.mis[i], 'Amrf')
                    call SetUnitTimeScale(dat.mis[i], 0.00)
                    call UnitRemoveAbility(dat.mis[i], 'Amrf')
                    set dat.fh[i] = 30.0 * i
                    call SetUnitFlyHeight(dat.mis[i], dat.fh[i], 0.00)
                    call SetUnitScale(dat.mis[i], CHARGED_BOLTS_SIZE, CHARGED_BOLTS_SIZE, CHARGED_BOLTS_SIZE)
                    set dat.fb[i] = true
                    set dat.x[i] = Atan2(y - cy, x - cx)
                    exitwhen i == CHARGED_BOLTS
                    set i = i + 1
                endloop
                if thistype.total == 0 then
                    call TimerStart(thistype.tim, 0.047, true, function Charged.fly)
                endif
                set thistype.total = thistype.total + 1
                set thistype.arr[thistype.total - 1] = dat
                return dat
            endmethod
                 
        endstruct    
       
        ///////===================\\\\\\\
       
        private function OnCast takes nothing returns boolean
            if (GetSpellAbilityId() == ABILITY_ID) then
                call bolt.create(GetTriggerUnit())
            endif
            return false
        endfunction
       
        private function BoltCharge takes nothing returns boolean
            if (GetLearnedSkill() == ABILITY_ID and GetLearnedSkillLevel() == 1) then
                call Charged.create(GetTriggerUnit())
            endif
            return false
        endfunction    
       
        private function init takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t, Condition(function OnCast))
            set t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CAST)
            call TriggerAddCondition(t, Condition(function Charged.ready))
            set t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_SKILL)
            call TriggerAddCondition(t, Condition(function BoltCharge))
            set BE = Condition(function spark.Enum)
            set MINX = GetRectMinX(bj_mapInitialPlayableArea) + 50.0
            set MINY = GetRectMinY(bj_mapInitialPlayableArea) + 50.0
            set MAXX = GetRectMaxX(bj_mapInitialPlayableArea) - 50.0
            set MAXY = GetRectMaxY(bj_mapInitialPlayableArea) - 50.0
        endfunction
    endlibrary

     
     
  4. indomitable1319

    indomitable1319

    Joined:
    Jan 22, 2010
    Messages:
    2,278
    Resources:
    0
    Resources:
    0
    This skill is... Too epic!
    It's detail is truly awesome.
    This deserves a 1.00x102168748954354135165498764541351351365479876543154698753168765436513212/5 from me. It deserves congratulatory Rep. :ogre_rage:
     
  5. jk2pach

    jk2pach

    Joined:
    Mar 19, 2009
    Messages:
    352
    Resources:
    50
    Models:
    43
    Packs:
    1
    Maps:
    4
    Tutorials:
    2
    Resources:
    50
    May I suggest to improve the spell with TimerUtils?

    Used in Restricted Complex 601 - nice spell.
     
  6. zadelim

    zadelim

    Joined:
    Oct 31, 2008
    Messages:
    538
    Resources:
    20
    Icons:
    10
    Packs:
    2
    Skins:
    8
    Resources:
    20
    What version of warcraft you all using to create those spell?
     
  7. jk2pach

    jk2pach

    Joined:
    Mar 19, 2009
    Messages:
    352
    Resources:
    50
    Models:
    43
    Packs:
    1
    Maps:
    4
    Tutorials:
    2
    Resources:
    50
    The normal. But as editor, it can be done with any hack of the editor using a preprocessor. There, it is VJass (Vexorian Jass) through JassHelper as preprocessor (included in the Jass new gen pack, the most used hack of the editor).
     
  8. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,379
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    vJass stands for VeryJass.

    Zinc is Zinc Is Not C.

    etc.
     
  9. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    Yes it does but it is a common mistake to say VexorianJASS because of the maker :p

    doesnt zinc got a c-like syntax or am I thinking of cJASS? ^^
     
  10. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,379
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Code (vJASS):

    // jass

    function foo takes nothing returns boolean
        return true
    endfunction

    // Zinc

    function foo() -> boolean
    {
        return true;
    }

    // cJass

    bool foo()
    {
        return true
    }
     


    Do note that cJass is deprecated. It cannot compile in current vJass (no textmacros, no Zinc, no many other features).
     
  11. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
  12. zadelim

    zadelim

    Joined:
    Oct 31, 2008
    Messages:
    538
    Resources:
    20
    Icons:
    10
    Packs:
    2
    Skins:
    8
    Resources:
    20
    Hmm.. Im not mean that. I mean the Warcraft Version.
     
  13. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    This spell should be able to run on RoC, but I believe most of us use TFT : ).

    As for the patch, just about all code resources were created with the latest wc3 patch.

    You can look through the natives used to see its compatibility with previous patches.
     
  14. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,379
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Reign Of Chaos does not support a huge amount of JASS code, last I checked.
     
  15. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    RoC supports the same JASS as TFT...

    I only say it might not support all scripts because of the limits in Object Editor for RoC. Still, this limitability is made less limited by wc3o.
     
  16. Prince.Zero

    Prince.Zero

    Joined:
    Jun 6, 2010
    Messages:
    217
    Resources:
    3
    Spells:
    3
    Resources:
    3
    spell won't work under roc

    locust ability was implemented on TFT ( Crypt Lord <Locust Swarm> )
    And some other tft jass functions....

    but jass is a syntax, almost identical to LUA :>
     
  17. PrinceYaser

    PrinceYaser

    Joined:
    May 7, 2016
    Messages:
    1,925
    Resources:
    205
    Models:
    2
    Icons:
    183
    Skins:
    10
    Maps:
    3
    Template:
    7
    Resources:
    205
    This is a very very very nice spell. I really love it!:) Good work!
    Voted 5/5!;)