1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  3. Participate in Blizzard's Public Test Realm to give them feedback on the upcoming patches. Info is here.
    Dismiss Notice
  4. Take part in forum poll and decide the winner of Icon Contest #16!
    Dismiss Notice
  5. Congratulate the winners of the first ATC contest!
    Dismiss Notice
  6. Zwiebelchen is hosting a special UI texturing contest. Whomever wins will get a $150 reward through paypal! Come along and draw your texturing tools for the Fantastic Adventurer UI contest.
    Dismiss Notice
  7. Sneak, pickpocket and assassinate! Create a stealth map in Mini-Mapping Contest #14!
    Dismiss Notice
  8. Music Contest #8 - Hive Soundtrack is up! Create the soundtrack for the upcoming videos of Hive Workshop's YouTube Channel.
    Dismiss Notice

[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. Moderator

    Moderator

    Resources:
    0
    Resources:
    0
    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 convention which is used for constants.
    • You don't need to null struct members if each time a new instance is created the variable is going to get overwritten. So your onDestroy methods are useless.
    • IIRC boolexprs are stored in a table so they don't actually leak if they are used multiple times. Even if I am wrong why do you create a new boolexpr each time when you could just create a global one and re-use it?
    • You really should use group recycling.
    • You should have a custom .create method which sets all the struct data per instance instead of doing it directly. This allows for better organization and makes it easier for people to understand what's going on while reading your code.

    I've only looked at about half the code.

    17:16, 24th Aug 2010
    The_Reborn_Devil:

    The code looks good now ^^
    0/5 :D?


    Status: Approved
    Rating Highly Recommended [0+Gender Bonus(5)]
     
  2. BoringEquations

    BoringEquations

    Joined:
    Aug 17, 2010
    Messages:
    10
    Resources:
    0
    Resources:
    0
    holy shit this looks impossible
     
  3. Prince.Zero

    Prince.Zero

    Joined:
    Jun 6, 2010
    Messages:
    217
    Resources:
    3
    Spells:
    3
    Resources:
    3
    Nah... just some patience and a fan to cool you down from the damn heat!!
     
  4. BoringEquations

    BoringEquations

    Joined:
    Aug 17, 2010
    Messages:
    10
    Resources:
    0
    Resources:
    0
    very awesome work man, gj...
    5/5
     
  5. watermelon_1234

    watermelon_1234

    Joined:
    Nov 18, 2007
    Messages:
    1,068
    Resources:
    9
    Spells:
    9
    Resources:
    9
    This is a pretty awesome-looking spell.

    I didn't really look at the code thoroughly, but I have some things I want to point out:

    • You should make your angles radians by default. Converting to degrees is only used for setting the unit's facing which happens less often then moving the unit.
    • Destroying boolexprs is bad. Just do
      Code (vJASS):
      call  GroupEnumUnitsInRange(Group, data.x, data.y, 125, Condition(function  SparkEnum))
      According to grim001 (#5) you don't need to use a variable (local/global) for that either.
    • Any reason for putting minus signs in front of the zeroes here?
      Code (vJASS):
      call SetUnitPosition(.mis[i], -0, -0)
    • You're could have simplified some of your ifs:
      Code (vJASS):
              if IsUnitInGroup(e, this.damaged) then
                  ...
              else
                  if (not(IsUnitType(e, UNIT_TYPE_STRUCTURE))) and (GetWidgetLife(e)>.405) and (IsUnitEnemy(e, GetOwningPlayer(this.u))) then
                      ...
                  endif    
              endif  
      ->
      Code (vJASS):
              if not IsUnitInGroup(e, this.damaged) then            
                  if (not(IsUnitType(e, UNIT_TYPE_STRUCTURE))) and  (GetWidgetLife(e)>.405) and (IsUnitEnemy(e, GetOwningPlayer(this.u)))  then
                      ...
                  endif    
              endif
      Code (vJASS):
                  if GetSpellAbilityId()!= Ability_Id then
                       return false
                  else
                      ...
                  endif
      ->
      Code (vJASS):
                  if GetSpellAbilityId()== Ability_Id then
                      ...
                  endif
      Code (vJASS):
                      if GetWidgetLife(this.u)<.405 then
                          ...
                      elseif GetWidgetLife(this.u)>=.405 and this.dead then
                           ...
                       endif
      ->
      Code (vJASS):
                      if GetWidgetLife(this.u)<.405 then
                          ...
                      elseif this.dead then
                           ...
                       endif
    There also seems to be a bug with the revolving balls. If the caster casts the spell multiple times, one of the balls never gets back in the correct position.

    Edit:
    I've attached two pictures, one where the balls are correctly placed while the second one shows what I mean.
     

    Attached Files:

  6. Prince.Zero

    Prince.Zero

    Joined:
    Jun 6, 2010
    Messages:
    217
    Resources:
    3
    Spells:
    3
    Resources:
    3
    yeah i'm used to blizzard's method, i feel safer by doing so

    -edit
    editx : we both said hasty things lol
    nvm
    ♥ kisses
     
    Last edited: Aug 23, 2010
  7. Pharaoh_

    Pharaoh_

    Joined:
    Nov 6, 2008
    Messages:
    8,125
    Resources:
    10
    Icons:
    3
    Skins:
    1
    Spells:
    6
    Resources:
    10
    Even better than the edition you sent me! :infl_thumbs_up:
    Well done and thank you :D
     
  8. Prince.Zero

    Prince.Zero

    Joined:
    Jun 6, 2010
    Messages:
    217
    Resources:
    3
    Spells:
    3
    Resources:
    3
    my test maps are always ugly =P
    i wonder where i could get a template.
     
  9. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,228
    Resources:
    14
    Spells:
    14
    Resources:
    14
    The safe x and y functions, aren't they as same as you would have Vexorians BoundSentinel library?

    Who am I to judge the code but wouldn't it be better to use a group recycler like GroupUtils instead of destroying?

    I think also that attack type, damage type and weapon type should be changeable in the globals.

    This is way much code for my head right now, giving me headdicks looking at it 500+ lines.

    Looking good so far, guess the mods will find some more.
     
  10. Prince.Zero

    Prince.Zero

    Joined:
    Jun 6, 2010
    Messages:
    217
    Resources:
    3
    Spells:
    3
    Resources:
    3
    no? Obvious functions, anyone can write one.
    isn't damaage type lightning quite the obvious?
    Using grouputils would make it much slower since i gotta allocate, clear, sort a new group for each lightning instance. Trust me, i did my homework before even starting to think about this spell.
     
  11. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,228
    Resources:
    14
    Spells:
    14
    Resources:
    14
    Dunno, but why rewrite it instead of just using another library. Well doesn't matter.

    Maybe but how about attack type?

    That's true, just an option :)

    Like I said, vJASS isn't my best side, only knows the basics.
     
  12. Prince.Zero

    Prince.Zero

    Joined:
    Jun 6, 2010
    Messages:
    217
    Resources:
    3
    Spells:
    3
    Resources:
    3
    your statements and answers were ok, i just had to answer.
    but right now i need some feedback on to make this spell look cooler :p
    and my target is to give it a directors cut because of it's awesomeness
     
  13. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,228
    Resources:
    14
    Spells:
    14
    Resources:
    14
    heh coooler? :p good luck with taht ! :D
     
  14. Prince.Zero

    Prince.Zero

    Joined:
    Jun 6, 2010
    Messages:
    217
    Resources:
    3
    Spells:
    3
    Resources:
    3
    my imagination is quite constructive =P
    to think of, this is a spell i wanted to tribute to a guy because of a misunderstanding. Let's hope it turns to be a hell of a spell.
     
  15. Patio_111

    Patio_111

    Joined:
    Oct 24, 2007
    Messages:
    87
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Wow, nice job! I learned a lot with this spell's code, too. I'm sort of new to vJass. Awesome spell, I love the effects (I'm an effect spamming freak) and the initial bzzzz epic sound of it. Once again, good work... and patience.
     
  16. Weep

    Weep

    Joined:
    Jul 12, 2009
    Messages:
    312
    Resources:
    3
    Models:
    2
    Spells:
    1
    Resources:
    3
    Attempting to play the demo map just takes me back to the menu. Did you forget to process it with JassHelper before uploading?
     
  17. Prince.Zero

    Prince.Zero

    Joined:
    Jun 6, 2010
    Messages:
    217
    Resources:
    3
    Spells:
    3
    Resources:
    3
    does it?
    I'll take a look...
     
  18. Lambdadelta

    Lambdadelta

    Joined:
    Jul 6, 2009
    Messages:
    842
    Resources:
    12
    Maps:
    1
    Spells:
    11
    Resources:
    12
    I think he means having constant configurables at the top with all your other global variables =)

    The ability is nice visually =) But is there an option to allow the user to change how many links are made o_O"? Like, the orbs rotating. =) Hehe, I love the lightning beind used a missile itself. <3
     
  19. Prince.Zero

    Prince.Zero

    Joined:
    Jun 6, 2010
    Messages:
    217
    Resources:
    3
    Spells:
    3
    Resources:
    3
    you mean how many lightnings are created when the orb crashes? yea there's a way because all it does is a loop

    it loops 8 times and creates a lightning into a struct each time giving it the proper angle.

    45 * i = angle