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.

Shattering Frost - v2.0.1

Submitted by Mr_Bean
This bundle is marked as approved. It works and satisfies the submission rules.
[​IMG]

Introduction


Back in the day while learning vJASS, I coded this for one of my maps and decided to upload it.

Spell Description
Active: Encases a unit in ice, dealing damage and disabling it. After a short duration the ice explodes, slowing the

target by 50% and sending shards of ice to all nearby enemies, dealing damage and stunning them for 3 seconds.

Level 1: 75 target damage; 0.5 second freeze; 50 shard damage
Level 2: 125 target damage; 0.75 second freeze; 75 shard damage
Level 3: 175 target damage; 1 second freeze; 100 shard damage

Cooldown: 15 seconds.
Mana cost: 125.

Screenshots


Images
Target a unit:
[​IMG]

For a short period the target is frozen in ice:
[​IMG]

The ice explodes, sending shards to nearby enemies:
[​IMG]

Units hit by ice shards are damaged and stunned:
[​IMG]

Requirements


- JASS NewGen Pack
- BeanDummyCaster by me (a simple library to help with dummy casting)
- SpellEffectEvent by Bribe
- TimerUtils by Vexorian
- xemissile by Vexorian

Links for the above systems can be found in the spell's code (below)

The Code



vJASS
Code (vJASS):
library ShatteringFrost /*
****************************************************************************************************
*
*   S H A T T E R I N G    F R O S T
*
*       ~ version 2.0.1
*       ~ coded by Mr_Bean
*
****************************************************************************************************
*
*    */
requires /*
*       ¯¯¯¯¯¯¯¯
*           */
BeanDummyCaster,     /* (not uploaded; available in demo map)
*           */
SpellEffectEvent,    /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193
*           */
TimerUtils           /* http://www.wc3c.net/showthread.php?t=101322
*           */
xemissile            /* http://www.wc3c.net/showthread.php?t=101150
*
****************************************************************************************************
*
*       Installation
*       ¯¯¯¯¯¯¯¯¯¯¯¯
*   - Make sure you've got (and installed properly) the above systems.
*   - Copy the 4 custom abilities. Scroll down to the "RAW IDS" section and set their raw IDs.
*   - Copy the 2 custom buffs (or make your own):
*       > Set the buff fields of "Slow [Shattering Frost]" to the "Shattering Frost" buff
*       > Set the buff fields of "Pause [Shattering Frost]" to the "Shattering Frost [paused]" buff.
*   - Go through the configurables section below and change what you want to.
*
****************************************************************************************************
*
*       Adding Ability Levels
*       ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*   If you would like to add more levels to the ability, you will need to add the same amount of
*   levels to the 3 dummy abilities (Pause, Stun and Slow). Configure the stun and slow values as
*   desired. For the Stun and Pause dummy abilities, make sure the for each level you added:
*       - Damage is set to 0.
*       - Cast range is set to 99999.
*       - Cooldown is set to 0.
*       - Mana cost is set to 0.
*       - Targets allowed is BLANK (don't worry, the code makes sure only valid targets are chosen).
*
*   For the Slow dummy ability, make sure the for each level you added:
*       - Cast range is set to 99999.
*       - Cooldown is set to 0.
*       - Mana cost is set to 0.
*       - Targets allowed is BLANK (don't worry, the code makes sure only valid targets are chosen).
*
****************************************************************************************************
*
*       Configuration
*       ¯¯¯¯¯¯¯¯¯¯¯¯¯
*/

    globals
   
        //==================================================
        //=== RAW IDS
        private constant integer SPELL_ID       = 'A002'    // "Shattering Frost" ability.
        private constant integer PAUSE_ID       = 'A003'    // "Pause [Shattering Frost]" ability.
        private constant integer STUN_ID        = 'A000'    // "Stun [Shattering Frost]" ability.
        private constant integer SLOW_ID        = 'A001'    // "Slow [Shattering Frost]" ability.
       
        //==================================================
        //=== PAUSE CONFIGURATION
        private constant real    PAUSE_DELAY    = 1.0       // Delay between target effect creation and pause starting.
       
        // Effect created on target while paused:
        private constant string  TARGET_EFFECT  = "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl"
       
        private constant string  TARGET_ATTACH  = "origin"
       
        //==================================================
        //=== EXPLOSION CONFIGURATION
        private constant real    EXPLODE_AOE    = 400.0     // All enemies within this range of the target get a frost shard.
       
        // Effect created at target when ice explodes:
        private constant string  EXPLODE_EFFECT = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
       
        //==================================================
        //=== ICE SHARD CONFIGURATION
        private constant real    SHARD_SCALE    = 1.0       // Model scale.
        private constant real    SHARD_SPEED    = 800.0     // Speed.
        private constant real    SHARD_ARC      = 0.2       // Arc.
        private constant real    SHARD_HEIGHT   = 50.0      // Height.
       
        // Model:
        private constant string  SHARD_ART      = "Abilities\\Spells\\Other\\FrostBolt\\FrostBoltMissile.mdl"
       
    endglobals
   
    //==================================================
    //=== PRIMARY TARGET DAMAGE PER LEVEL
    private function GetTargetDamage takes integer level returns real
        return (50.0 * level) + 25.0
    endfunction
   
    //==================================================
    //=== PRIMARY TARGET PAUSE PER LEVEL:
    private function GetPauseDuration takes integer level returns real
        return (0.25 * level) + 0.25
    endfunction
   
    //==================================================
    //=== SHARD DAMAGE PER LEVEL:
    private function GetShardDamage takes integer level returns real
        return 50.0 * level
    endfunction
   
    //==================================================
    //=== DAMAGE FUNCTION SETUP
    // This is if you want to change attack/damage types or if you use a custom
    // function for damage detection or something similar.
    private function DealDamage takes unit source, unit target, real amount returns nothing
        call UnitDamageTarget(source, target, amount, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
    endfunction
   
/***************************************************************************************************
*
*       END OF CONFIGURATION AND DOCUMENTATION
*
***************************************************************************************************/

   
    private struct IceShard extends xemissile
        unit    source
        integer level
        //-----
       
        /**
         * Damages the target and stuns it if it's still alive.
         */

        private method onHit takes nothing returns nothing
            call DealDamage(source, targetUnit, GetShardDamage(level))
           
            if (not IsUnitType(targetUnit, UNIT_TYPE_DEAD)) then
                call BeanDummyCaster_SetAbility(STUN_ID, level, "thunderbolt")
                call BeanDummyCaster_TargetOrder(targetUnit)
            endif
           
            set source = null
        endmethod
       
        /**
         * Creates a new instance and launches the missile.
         */

        static method create takes unit s, real x, real y, unit t, integer l returns thistype
            local thistype this = allocate(x, y, SHARD_HEIGHT, GetUnitX(t), GetUnitY(t), SHARD_HEIGHT)
           
            set source = s
            set level = l
            set targetUnit = t
            set fxpath = SHARD_ART
            set scale = SHARD_SCALE
            call launch(SHARD_SPEED, SHARD_ARC)
           
            return this
        endmethod
   
    endstruct
   
    private struct ShatteringFrost
        static group enumG = CreateGroup()
        static unit  temp
        //-----
        unit    caster
        unit    target
        player  owner
        integer level
        effect  fx
        //-----
       
        /**
         * Cleans up and dellocates the instance.
         */

        private method destroy takes nothing returns nothing
            set caster = null
            set target = null
            set owner = null
            set fx = null
            call deallocate()
        endmethod
       
        /**
         * This is the filter applied to units that are in range of the target.
         */

        private method filterUnit takes unit u returns boolean
            return IsUnitEnemy(u, owner)                         /* Enemy of caster.
                */
and not IsUnitType(u, UNIT_TYPE_DEAD)         /* Alive
                */
and     GetUnitTypeId(u) != 0                 /* Alive
                */
and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) /* Not magic immune.
                */
and not IsUnitType(u, UNIT_TYPE_STRUCTURE)    /* Not a structure. */
        endmethod
       
        /**
         * Unpauses the target and sends ice shards to all enemies in range.
         * Also slows the target and destroys the effect.
         */

        private static method explode takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            local real x = GetUnitX(target)
            local real y = GetUnitY(target)
           
            call ReleaseTimer(GetExpiredTimer())
            call DestroyEffect(fx)
            call DestroyEffect(AddSpecialEffect(EXPLODE_EFFECT, x, y))
            call BeanDummyCaster_SetAbility(SLOW_ID, level, "slow")
            call BeanDummyCaster_TargetOrder(target)
            call GroupEnumUnitsInRange(enumG, x, y, EXPLODE_AOE, null)
            call GroupRemoveUnit(enumG, target)
           
            loop
                set temp = FirstOfGroup(enumG)
                exitwhen temp == null
                call GroupRemoveUnit(enumG, temp)
                if (filterUnit(temp)) then
                    call IceShard.create(caster, x, y, temp, level)
                endif
            endloop
           
            call destroy()
        endmethod
       
        /**
         * Pauses the target and deals damage. Waits until the pause is
         * over.
         */

        private static method pause takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
           
            call BeanDummyCaster_SetAbility(PAUSE_ID, level, "thunderbolt")
            call BeanDummyCaster_TargetOrder(target)
            call DealDamage(caster, target, GetTargetDamage(level))
            call TimerStart(GetExpiredTimer(), GetPauseDuration(level), false, function thistype.explode)
        endmethod
       
        /**
         * Creates a new instance. Creates the effect on the target and
         * waits until PAUSE_DELAY expires.
         */

        private static method create takes nothing returns thistype
            local thistype this = allocate()
           
            set caster = GetTriggerUnit()
            set owner = GetTriggerPlayer()
            set level = GetUnitAbilityLevel(caster, SPELL_ID)
            set target = GetSpellTargetUnit()
            set fx = AddSpecialEffectTarget(TARGET_EFFECT, target, TARGET_ATTACH)
            call TimerStart(NewTimerEx(this), PAUSE_DELAY, false, function thistype.pause)
           
            return this
        endmethod
   
        /**
         * Registers the spell and preloads effects and abilities.
         */

        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(SPELL_ID, function thistype.create)
            call Preload(TARGET_EFFECT)
            call Preload(EXPLODE_EFFECT)
            call Preload(SHARD_ART)
            set temp = CreateUnit(Player(0), 'hpea', 0.0, 0.0, 0.0)
            call UnitAddAbility(temp, PAUSE_ID)
            call UnitAddAbility(temp, STUN_ID)
            call UnitAddAbility(temp, SLOW_ID)
            call RemoveUnit(temp)
        endmethod
   
    endstruct

endlibrary

Changelog


v2.0.1
- Removed an unused local variable.
- Fixed the unit filter to check properly for dead units.
- The original target is now stunned instead of paused (because pausing a unit pauses its buffs).

v2.0
- Completely rewrote everything from scratch. It made me want to cry when I saw how badly I used to code.

Old
v1.1.0
- Further improved and optimized the code.
- You can now change the delay between the casting of the spell and the stun. It is initially set to 0.5/0.4/0.3 seconds.
- You can now change the range of the stun per level. It is initially set to 200/250/300.

1.0.1
- Fixed a few issues with the code.
- Fixed a few things with the dummy caster.
- In the demo map, if you kill a ghoul, you will now get gold.
- You can now configure the delay between when the spell is cast and when the units are stunned.

1.0.0
- Initial release.

Credits


For Code Improvements:
- Maker
- OxygenD
- Ruke
- Bribe

Keywords:
Mr_Bean, Frost, Shatter, Ice, Shard
Contents

Shattering Frost v2.0.1 (Map)

Reviews
Moderator
16 Dec 2011 Bribe: The changes look much better. Rating changed to 4/5 (Recommended).
  1. 16 Dec 2011
    Bribe: The changes look much better. Rating changed to 4/5 (Recommended).
     
  2. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Update:
    - Fixed a few issues with the code.
    - Fixed a few things with the dummy caster.
    - In the demo map, if you kill a ghoul, you will now get gold.
    - You can now configure the delay between when the spell is cast and when the units are stunned.

    The player did not get credit because I didn't turn the Gives Bounty flag on. I have changed that now :)
     
    Last edited: Dec 15, 2011
  3. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    What I meant with the credit was the actual kill. Try displaying unit name of killing unit.

    This is important if there is kill count for heroes. You don't have to change it, but I prefer to have the hero deal all the damage.
     
  4. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Surely if there is a kill count they would count all the kills made by the player, not just by the hero? Like if the hero can summon an Infernal, for example. The Infernal can kill units, which would ideally add to the kill count.
     
  5. OxygenD

    OxygenD

    Joined:
    Dec 10, 2010
    Messages:
    101
    Resources:
    0
    Resources:
    0
    Code (vJASS):

        private function Timer_Actions takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local Data D = Data(GetTimerData(t))
            local real x = GetUnitX(D.target)
            local real y = GetUnitY(D.target)
            local unit u
            call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, RANGE, Condition(function Group_Conditions))
            loop
                set u = FirstOfGroup(bj_lastCreatedGroup)
                exitwhen u == null
                if (u != D.target) then
                    set bj_lastCreatedUnit = CreateUnit(GetOwningPlayer(D.caster), DUMMY_ID, x, y, 0)
                    call UnitAddAbility(bj_lastCreatedUnit, DUMMY_SPELL_ID)
                    call SetUnitAbilityLevel(bj_lastCreatedUnit, DUMMY_SPELL_ID, D.level)
                    call IssueTargetOrder(bj_lastCreatedUnit, "thunderbolt", u)
                    call UnitApplyTimedLife(bj_lastCreatedUnit, 'BTLF', 5)
                endif
                call GroupRemoveUnit(bj_lastCreatedGroup, u)
            endloop
            call ReleaseTimer(t)
            set t = null
            call D.destroy()
        endfunction
     


    Dont use bj_lastCreatedUnit and bj_lastCreatedGroup its just globals variables. In your variant you can use just local group GroupName. Create this local group and change all bj_lastCreatedGroup to GroupName. Do the same with the unit.
     
  6. Ruke

    Ruke

    Joined:
    Sep 19, 2011
    Messages:
    517
    Resources:
    7
    Tools:
    1
    Spells:
    5
    Wurst:
    1
    Resources:
    7
    Code (vJASS):
    library ShatteringFrost requires TimerUtils
        globals
            // Important Configurables:
            private constant integer SPELL_ID = 'A000'          // Change A000 to the raw code of the "Shattering Frost" spell.
            private constant integer DUMMY_SPELL_ID = 'A001'    // Change A001 to the raw code of "Shattering Frost [dummy]" spell.
            private constant integer DUMMY_ID = 'h001'          // Change h001 to the raw code of your dummy unit.
           
            // Other Configurables:
            private constant real RANGE = 250                   // Area of effect (how close units have to be to the target to get stunned).
            private constant real SHARD_DELAY = 0.5             // The delay between the ice blast and when the units get stunned. I wouldn't make it higher than 0.5 seconds.
        endglobals
       
        private function Group_Conditions takes unit target, unit caster returns boolean
            return (IsUnitEnemy(target, GetOwningPlayer(caster))) and (IsUnitType(target, UNIT_TYPE_DEAD) == false)
        endfunction
       
        // End Of Configurables.
        // Don't change anything past this point!
       
        private struct Data
            unit caster
            unit target
            integer level
           
            method destroy takes nothing returns nothing
                set this.caster = null
                set this.target = null
                call this.deallocate()
            endmethod
           
            static method Timer_Actions takes nothing returns nothing
                local timer t = GetExpiredTimer()
                local thistype D = GetTimerData(t)
                local real x = GetUnitX(D.target)
                local real y = GetUnitY(D.target)
                local unit u
                local unit dummy
               
                call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, RANGE, null)
               
                loop
                    set u = FirstOfGroup(bj_lastCreatedGroup)
                    exitwhen u == null
                   
                    if (u != D.target and Group_Conditions(u, D.caster)) then
                        set dummy = CreateUnit(GetOwningPlayer(D.caster), DUMMY_ID, x, y, 0)
                       
                        call UnitAddAbility(dummy, DUMMY_SPELL_ID)
                        call SetUnitAbilityLevel(dummy, DUMMY_SPELL_ID, D.level)
                        call IssueTargetOrder(dummy, "thunderbolt", u)
                        call UnitApplyTimedLife(dummy, 'BTLF', 5)
                       
                        set dummy = null
                    endif
                   
                    call GroupRemoveUnit(bj_lastCreatedGroup, u)
                endloop
               
                call ReleaseTimer(t)
                set t = null
                call D.destroy()
            endmethod

            static method create takes nothing returns thistype
                local timer t = NewTimer()
                local thistype D = thistype.allocate()
               
                set D.caster = GetTriggerUnit()
                set D.target = GetSpellTargetUnit()
                set D.level = GetUnitAbilityLevel(D.caster, SPELL_ID)
               
                call SetTimerData(t, D)
                call TimerStart(t, SHARD_DELAY, true, function thistype.Timer_Actions)
                set t = null
               
                return D
            endmethod
           
            static method Conditions takes nothing returns boolean
                if (GetSpellAbilityId() == SPELL_ID) then
                    call thistype.create()
                endif
               
                return false
            endmethod
           
            static method onInit takes nothing returns nothing
                local trigger t = CreateTrigger()
                call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                call TriggerAddCondition(t, Condition(function thistype.Conditions))
            endmethod
        endstruct    
    endlibrary


    • Use library instead scope (then, make it requires TimerUtils or the libraries that you will use later :)).
    • The "Actions" function is unnesesary, you can make all of these actions into the create method.
    • Use the "destroy" method to null your variables (only who really needs null) and then, use deallocate (if you're using allocate).
    • Use "thistype" keyword instead the name of the struct (is the same, but better e_e).
    • Don't use "bj_lastCreatedUnit" like this.
    • When you enumerate units into a group, don't put a filter condition, make the filter in the loop :).

    call TimerStart(t, SHARD_DELAY, true, function Timer_Actions)


    Why true? the actions only executes one time.

    local Data D = Data(GetTimerData(t))


    ->

    local Data D = GetTimerData(t)


    You will never (in this case) destroy the trigger, so, what's the point?

    ---

    Nice spell :).

    Greetings :D
     
    Last edited: Dec 15, 2011
  7. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,003
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    It's actually the opposite. I encourage using the global group instead of creating and destroying a group in the same thread. It's cleaner and more efficient ;)

    There's no need to use bj_lastCreatedUnit though.
    Creating a local variable for that is faster (Locals are theoretically faster than globals and they don't get slower with more characters as much as globals do).

    If u is a global and v is a local, u is faster and v is slower.
    If uu is a global and vv is a local, vv is faster and uu is slower.

    You can imagine the following formulas:
    This is only an example.

    globalLookup = 3x + 5
    localLookup = x + 8

    x is the number of characters.

    With 1 character, globalLookup = 8 and localLookup = 9 (globalLookup is faster)
    With any other number of characters, the localLookup would be faster.

    This is purely an example that shows a special case when globals are faster than locals.

    This still doesn't give you a reason to use dynamic group handles in any function because function calls are DRASTICALLY slow relative to any variable lookup ;)

    But, I wouldn't recommend using one-character long names for global variables, so locals are technically always going to be faster than globals.

    ----------
    TL;DR?

    Use a local unit; Keep the bj_lastCreatedGroup.
     
    Last edited: Dec 15, 2011
  8. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Thanks guys!

    Update:
    - Replaced bj_lastCreatedUnit with a local variable.
    - Used Ruke's suggestions.
    - You can now change the delay between the casting of the spell and the stun. It is initially set to 0.5/0.4/0.3 seconds (suggested by Bribe).
    - You can now change the range of the stun per level. It is initially set to 200/250/300 (suggested by Bribe).
     
    Last edited: Dec 16, 2011
  9. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    - I suggest put "thunderbolt" as a global so that it can be easily adjusted if the user doesnt want that...
    - I never tried this spell but I think T32 is a good option than TimerUtils...
    - I dont think it's necessary to put the destroy method...call thig.deallocate() is fine...
     
  10. Ruke

    Ruke

    Joined:
    Sep 19, 2011
    Messages:
    517
    Resources:
    7
    Tools:
    1
    Spells:
    5
    Wurst:
    1
    Resources:
    7
    Do you have a problem with the destroy method? xD

    As did you say in your spell, if it's not a requirement (I have questions about this) but it's recomended, why shouldn't we do it?
     
  11. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    I posted in the other thread...
    EDIT: SOrry for double posting...

    EDIT2: New test 3000 units...

    Ram 134396 = no nulling
    Ram 134664 = nulls with your method
     
  12. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Update - v2.0:
    - Completely rewrote everything from scratch. It made me want to cry when I saw how badly I used to code.
     
  13. Lambdadelta

    Lambdadelta

    Joined:
    Jul 6, 2009
    Messages:
    721
    Resources:
    1
    Maps:
    1
    Resources:
    1
    ^ Lol :3

    New code is very readable. Well done on presentation.
     
  14. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    :D
    Thanks. I was very shocked when I looked at the old code, because I thought I would have done something slightly better back then :S
     
  15. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    -Method onHit has unused local unit dummy variable
    -I think dead units can have over 0.405 life. Use
    not(IsUnitType(unit, UNIT_TYPE_DEAD) or GetUnitTypeId(unit) == 0)

    -Increase follow through time so the caster completes the cast animation
    -Pausing a unit should be avoided, it pauses buffs
     
  16. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    When I saw it, I was thinking like: "I saw this a long time ago"

    than I saw the upload date... XD...

    anyway, it was really nice for you to rewrite the code and make it better... :)
     
  17. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Haha, you actually remembered it? :O
     
  18. Losam

    Losam

    Joined:
    Mar 27, 2011
    Messages:
    258
    Resources:
    8
    Spells:
    8
    Resources:
    8
    Nice

    Great job, it was well written, developed (not to mention that the description of the spell was well done).
    In my opinion deserves 5/5.

     
  19. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    yeah, there's only quite a few spells of this idea here on hive....