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

Sub Zero v4.0.0.0

This spell will create a nova of icy missiles around the caster to damage all units in range.

JASS:
/*********************************************************************
*
*   Sub Zero v4.0.0.0
*   By Magtheridon96
*
*   Description:
*   ------------
*
*       - This spell is a nova spell that creates projectiles of ice 
*       that emerge from the center of the casting unit even while he 
*       is moving.
*
*   Requirements:
*   -------------
*
*       - CTL                           [By Nestharus]
*       - WorldBounds                   [By Nestharus]
*       - SpellEffectEvent              [By Bribe]
*       - Table                         [By Bribe]
*
*   Implementation:
*   ---------------
*
*       - Implement all the required systems
*       - Copy this code into a new trigger
*       - Paste all the object data from the Object editor into your map
*       - Configure the system
*       - Done!
*
*********************************************************************/
library SubZero requires CTL, WorldBounds, SpellEffectEvent
    globals
        // Ability Code
        private constant integer    ABIL_CODE       = 'A000'
        // Dummy Code
        private constant integer    DUMMY           = 'h000'
        // Projectile Speed
        private constant real       VELOCITY        = 18.0
        // Attack Type
        private constant attacktype ATTACK_TYPE     = ATTACK_TYPE_NORMAL
        // Damage Type
        private constant damagetype DAMAGE_TYPE     = DAMAGE_TYPE_MAGIC
        // Max Collision size in Map
        private constant real       MAX_COLLISION   = 197.0
        // Missile Damage Radius
        private constant real       PROJ_DMG_RADIUS = 175.0
    endglobals
     
    private function GetMissiles takes integer level returns integer
        return 6 + level * 2
    endfunction
    
    private function GetDamage takes integer level returns real
        return level * 70.0
    endfunction
    
    private function GetRange takes integer level returns real
        return 550. + level * 50.
    endfunction
    
    private function TargetFilter takes unit u, player p, real x, real y returns boolean
        return IsUnitEnemy(u, p) and not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) and IsUnitInRangeXY(u, x, y, PROJ_DMG_RADIUS)
    endfunction
    
    private struct Spell extends array
    
        static Table data
        static Table array missiles
        static Table array hit
        static player array owner
        static unit array caster
        static real array distance
        static real array damage
        
        // You mad Jesus4Lyf?
        implement CTL
            
            local integer k
            local integer i
            local unit u
            local unit v
            local real x
            local real y
            
        implement CTLExpire
        
            set distance[this] = distance[this] + VELOCITY
            set i = 0
            
            loop
                set u = missiles[this].unit[i]
                exitwhen null == u
                
                set k = GetHandleId(u)
                
                set x = GetUnitX(caster[this]) + distance[this] * data.real[k * 2]
                set y = GetUnitY(caster[this]) + distance[this] * data.real[k * 2 + 1]
                
                if x < WorldBounds.maxX and x > WorldBounds.minX and y < WorldBounds.maxY and y > WorldBounds.minY and GetWidgetLife(u)>0.405 then
                
                    call SetUnitX(u, x)
                    call SetUnitY(u, y)
                    
                    // You mad Rising_Dusk?
                    call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, PROJ_DMG_RADIUS + MAX_COLLISION, null)
                    
                    loop
                        set v = FirstOfGroup(bj_lastCreatedGroup)
                        exitwhen null == v
                        
                        set k = GetHandleId(v)
                        
                        if not hit[this].boolean.has(k) then
                            if TargetFilter(v, owner[this], x, y) then
                                call UnitDamageTarget(caster[this], v, damage[this], false, false, ATTACK_TYPE, DAMAGE_TYPE, null)
                                set hit[this].boolean[k] = true
                            endif
                        endif
                        
                        call GroupRemoveUnit(bj_lastCreatedGroup, v)
                    endloop
                    
                else
                    call destroy()
                    set caster[this] = null
                    set owner[this] = null
                    call hit[this].destroy()
                    
                    set i = 0
                    loop
                        set u = missiles[this].unit[i]
                        exitwhen null == u
                        call KillUnit(u)
                        set i = i + 1
                    endloop
                    
                    call missiles[this].destroy()
                    exitwhen true
                endif
                set i = i + 1
            endloop
            
        implement CTLNull
        implement CTLEnd
        
        static method start takes unit u, integer lvl returns nothing
            local thistype this = create()
            
            local integer m = GetMissiles(lvl)
            local integer i = m - 1
            local integer k = 0
            
            local real x = GetUnitX(u)
            local real y = GetUnitY(u)
            local real r = 0.03125 * GetRange(lvl) / VELOCITY
            
            set caster[this] = u
            set owner[this] = GetTriggerPlayer()
            set distance[this] = 0.0
            set damage[this] = GetDamage(lvl)
            
            set missiles[this] = Table.create()
            set hit[this] = Table.create()
            
            loop
                set u = CreateUnit(owner[this], DUMMY, x, y, i * 360.0 / m)
                set k = GetHandleId(u)
                
                set data.real[k*2] = Cos(i * 6.2831853 / m)
                set data.real[k*2+1] = Sin(i * 6.2831853 / m)
                
                call UnitApplyTimedLife(u, 'BTLF', r)
                set missiles[this].unit[i] = u
                
                // You mad Nestharus?
                exitwhen i == 0
                set i = i - 1
            endloop
            
            set u = null
        endmethod
        
        static method run takes nothing returns nothing
            call start(GetTriggerUnit(), GetUnitAbilityLevel(GetTriggerUnit(), ABIL_CODE))
        endmethod
        
        static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(ABIL_CODE, function thistype.run)
            // You mad Vexorian?
            set data = Table.create()
        endmethod
    endstruct
endlibrary

Latest Update:
- Now using CTL and SpellEffectEvent
- Now much faster
- Extremely readable
- Did I mention it's faster?

Keywords:
Nova, Ice, Frost, Zero, Below, Sub, Sub-zero, Subzero, Sub zero, Cold, Frost Nova, Ice Nova, Below Zero, Magtheridon96, vJASS.
Contents

Sub Zero (Map)

Reviews
19 October 2011 Bribe: Another great spell, well-made, but you need to link to the required libraries (for your other spells as well).
The new one on xbox/ps3 is so tight. If you haven't played it, play it asap. It is ridiculously over the top, and 4 player makes it uber fun. And my fav is scorpion, which makes my second favorite an icy recolring of my first :D

My PS3 is actually broken at the moment :p
I played and finished Mortal Kombat years ago on the PS2 though xD
 
Level 15
Joined
Jul 6, 2009
Messages
889
1. Damage collision radius should be configurable.
2. Parametres in the damage function should be configurable.
3. Creating/destroying groups. BAD BOY.
4. local thistype this = TEMPDATA - BAD BOY. Just use TEMPDATA.var. Readability can go eat itself, you already destroyed it.
5. Why not just use BoundSentinel?
6. I don't really like how the spell is configured by time.
7. Could be more, got bored :(
 
#4 - Good point :p I think I'm going to kill readability even more xD
#6 - I guess I'll make it configurable by time and distance (Speed will vary)
#5 - It's more efficient to do it my way because using BoundSentinel will be like adding TriggerEvaluations after every SetUnitX/Y that takes a unit outside the bounds :p (LOL)
#3 - OMG I DID? D:
#2 - M'Kay :p
#1 - M'Kay :p (again)
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Doesn't this give you a syntax error? Fail.

JASS:
call RegisterSpellEffectEvent(ABIL_CODE, function thistype.run)

->

JASS:
static method run takes nothing returns nothing

->
JASS:
static method run takes nothing returns boolean

-The Start method shouldn't take any parameters and just call .start() instead. And btw isn't it possible to just create().start() at the run method?

-Missile dmg radius not being a priv function, shame on you!
 
Doesn't this give you a syntax error? Fail.

Nope.

The Start method shouldn't take any parameters and just call .start() instead. And btw isn't it possible to just create().start() at the run method?

Well, I set it up this way because I didn't want to create lots of useless locals, set the caster[this] to the triggering unit and THEN set the locals :p

Missile dmg radius not being a priv function, shame on you!

Doesn't really matter actually :p
 
Level 20
Joined
Jul 12, 2010
Messages
1,717
LOL IT'S OVER NINE THOUSAAAAAAAAAAAAAAAAND!! xD
and don't double post pls :)

ontopic:
well this is pretty good, too bad im not a vJasser to give good critism...
maybe (just maybe) you could make a GUI ver and include both in the spell ;)
that way both GUIers and vJassers can use this ;p

anyway gj 5/5 from me, happy coding :)
 
and don't double post pls :)

It's not a double post since the time difference between both posts is over 48 hours.

maybe (just maybe) you could make a GUI ver and include both in the spell ;)
that way both GUIers and vJassers can use this ;p

I haven't touched the GUI interface in months :p
Plus, coding this in GUI would make it much slower :eek:
As you can see, iteration has an O(k*n) complexity here D: (That means I'm looping n*k times where n is the number of casts and k is the number of missiles)
That would lag like hell in GUI with a certain number of missiles and casts.
 
Level 20
Joined
Jul 12, 2010
Messages
1,717
It's not a double post since the time difference between both posts is over 48 hours.
if you say so o_O

I haven't touched the GUI interface in months :p
Plus, coding this in GUI would make it much slower :eek:
As you can see, iteration has an O(k*n) complexity here D: (That means I'm looping n*k times where n is the number of casts and k is the number of missiles)
That would lag like hell in GUI with a certain number of missiles and casts.
well still, most ppl (including me) don't know vJass, i just don't feel like learning vJass after being for about 7-8 months a GUIer *_*
some things that im interested in learning are some more helpful custom scripts...
 
If you want those, just open the Warcraft III mpq file, and search for common.j
It has all the 'custom scripts' you need.

native CreateUnit takes player id, integer unitId, real x, real y, real facing returns unit
native RemoveLocation takes location loc returns nothing
native DestroyGroup takes group g returns nothing
native CreateTimer takes nothing returns timer
native UnitAddAbility takes unit u returns boolean
native TimerStart takes timer t, real interval, boolean periodic, code callback returns nothing

There are close to a thousand native functions.
 
xorkatoss said:
i just don't feel like learning vJass after being for about 7-8 months a GUIer *_*

I was a GUIer for about more than 1 year, then when I stumbled upon vJASS, oh it was awesome...

and you could just copy-paste it and just minimal editing, really no need for such vJASS knowledge...

anyway, really nice spell... this is one of your early uploads here right? or am I mistaking it for some other spell... haha
 
Top