• 🏆 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!

Hero Contest #7 - Classic

Status
Not open for further replies.
Hero Change; Gryphon Master

Q - Hammerfall
Throws a hammer to a target location, dealing 70/110/150 damage and slowing nearby enemies by 25/30/35% for 3 seconds. It remains on the ground afterwards for 3 seconds.

W - Cohesive Strike
Pulls enemies towards the Gryphon Master (or Hammerfall, if it is on the ground), allowing them to take 15/20/25% more damage for 3 seconds.

E - Shock Blast
Every 5 seconds, the Gryphon Master's attack becomes splash and deals 80/110/140% of Strength as bonus damage to the main target. The cooldown is reduced by attacks.

R - Skydive
Swoops to the ground below and takes flight once more, dragging enemies caught. Afterwards, the Gryphon Master gains 100% Attack Speed and a 20% damage resistance for 4 seconds.
 
Hero Change; Gryphon Master

Q - Hammerfall
Throws a hammer to a target location, dealing 70/110/150 damage and slowing nearby enemies by 25/30/35% for 3 seconds. It remains on the ground afterwards for 3 seconds.

W - Cohesive Strike
Pulls enemies towards the Gryphon Master (or Hammerfall, if it is on the ground), allowing them to take 15/20/25% more damage for 3 seconds.

E - Shock Blast
Every 5 seconds, the Gryphon Master's attack becomes splash and deals 80/110/140% of Strength as bonus damage to the main target. The cooldown is reduced by attacks.

R - Skydive
Swoops to the ground below and takes flight once more, dragging enemies caught. Afterwards, the Gryphon Master gains 100% Attack Speed and a 20% damage resistance for 4 seconds.

Why are you countering my hero!
 
Level 24
Joined
Feb 19, 2011
Messages
656
Hero Change; Gryphon Master

Q - Hammerfall
Throws a hammer to a target location, dealing 70/110/150 damage and slowing nearby enemies by 25/30/35% for 3 seconds. It remains on the ground afterwards for 3 seconds.

W - Cohesive Strike
Pulls enemies towards the Gryphon Master (or Hammerfall, if it is on the ground), allowing them to take 15/20/25% more damage for 3 seconds.

E - Shock Blast
Every 5 seconds, the Gryphon Master's attack becomes splash and deals 80/110/140% of Strength as bonus damage to the main target. The cooldown is reduced by attacks.

R - Skydive
Swoops to the ground below and takes flight once more, dragging enemies caught. Afterwards, the Gryphon Master gains 100% Attack Speed and a 20% damage resistance for 4 seconds.

RESPONSE:
So it's a flying hero? If so, I think that it would not fit into a basic Warcraft 3 hero criteria. That hero would be far to powerful at the start of the game. He would be able to easily harass enemy workers then hide in the trees before the enemy could even get the economy to make anti-air.

Otherwise, I like the ideas of your abilities. I makes it more fast-paced, and really take advantage of the short time effects that are bestowed upon the hero and penalize the enemy. But the 3rd ability (Shock Blast) doesn't really fit in my opinion. The whole stat-based abilities are not something that the heroes should utilize in a vanilla game.
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,501
Well actually I was looking at the D3 Wizard kit when I worked on this :p

Maybe I could make it so Polymastery deals less damage, but reduces the armor of any unit caught in the AoE.
Lol, well 'great minds think alike' I suppose.

(I'm curious how you would actually accomplish the armor debuffing...) Perhaps. But maybe a change in it's structure (= Role) entirely; remove the "damage" bit & have it do something entirely different. Maybe reflecting spells or polymorphing enemies who attack buffed friendlies or summat.

and WHY DO YOU KEEP CHANGING YOUR NAME?? I'm gonna have a hard time Crediting you since I can't decide which name to use. ;_;

Just remove the rule, it's that simple (I mean after you receive a response from whomever you asked). There's no need to "fix" the rule because it makes no sense in the first place. I don't recall seeing it in the year-long write-up. If I did, I would have warned you sooner.
Well the Rule(s) were there somewhere (2nd post I believe?), but the "this is going to be the Contest Thread" part didn't show up until near the end. Still, to be fair, that was a couple weeks of waiting yet.

So you're saying it shouldn't be fixed, simply removed. The result is anyone can use any system/spell/snippet/etc anywhere in existence, regardless of whether it has been created, submitted or approved before, during or after this Contest.

Then why even stop people from using Code they may have previously made?

good question, I could also use that beta Ranger skin found in War3.mpq to overwrite the present one. Can I do that?
I don't see why not. It already exists in the MPQs, right? If so, I think it'd be a nice creative choice to liven things up a bit. (Now, I don't know how you go about using it... Aside from importing it separately under the old texture's path??... I wonder if that should be Kosher...)

Well, I'm choosing over a Moonmage, a Moonkin, an Ancient and a Wisp. Please help me.
Oh man, another Night Elf?? That's crazy; usually it's Orcs & Undead that get all the love. I'm excited for the challenge. :p

What about Zoidberg?
Lawl.

Hero Change; Gryphon Master

Q - Hammerfall
Throws a hammer to a target location, dealing 70/110/150 damage and slowing nearby enemies by 25/30/35% for 3 seconds. It remains on the ground afterwards for 3 seconds.

W - Cohesive Strike
Pulls enemies towards the Gryphon Master (or Hammerfall, if it is on the ground), allowing them to take 15/20/25% more damage for 3 seconds.

E - Shock Blast
Every 5 seconds, the Gryphon Master's attack becomes splash and deals 80/110/140% of Strength as bonus damage to the main target. The cooldown is reduced by attacks.

R - Skydive
Swoops to the ground below and takes flight once more, dragging enemies caught. Afterwards, the Gryphon Master gains 100% Attack Speed and a 20% damage resistance for 4 seconds.
That's really interesting, & I'd love to see a good "Gryphon Rider" hero... However Wa666r has the right of it (on all counts); really can't have Flying Heroes. There's a reason (I believe) that Blizzard initially had them (flying PotM, flying Far Seer, etc), but then took them out.

Now, if you pull a "DotA" and create a "flying" Hero that is actually just 'hovering' along the ground... That wouldn't be too crazy, methinks (at least not for balance).

Anyways, Kyrbi0, will my score get reduced if I use a unit model for the same race?
I can't say that (not being a Judge). I would venture to say "No", or at least "Not Exactly"; if there's a better model you might get rated higher, but doing what you're doing won't necessarily rate you lower. At least I hope not.

If you do, try do 'mod' it so it looks different enough (tinting, item-art-attachment abilities, etc).

Well im going with a Primal Druid thing of some sort, using the Druid of the Claw model.
Hmm... Close but thankfully not too close... :p
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
So you're saying it shouldn't be fixed, simply removed. The result is anyone can use any system/spell/snippet/etc anywhere in existence, regardless of whether it has been created, submitted or approved before, during or after this Contest.

Then why even stop people from using Code they may have previously made?

I don't want to argue about this, but I'm just trying to say that you can't distinguish "systems" from "non-systems" with such fervor.

People should be disqualified for cheating (writing spells before the contest starts), and that should be at the discretion of the judges in a logical way.
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,501
I don't want to argue about this, but I'm just trying to say that you can't distinguish "systems" from "non-systems" with such fervor.
Nor am I trying to argue; this is merely a good discussion (maybe 'debate'). : )

Also, if you think this is 'fervor', you haven't seen me at my best/worst. :p Check out that Techtree Contest thread in the Arena Submissions forum... I care about this being done right, but it doesn't truly affect me greatly, so I'm more concerned in a detached, rational "want things done right" kinda way.

Cokemonkey11 said:
People should be disqualified for cheating (writing spells before the contest starts), and that should be at the discretion of the judges in a logical way.
It looks like that's somewhere we can agree (cheaters being disqualified ('cheating' being defined as "using code written before the Contest").

I suppose my issue with the last bit is "how shall the judges know"... But then that could be said of any other issue (pre-made Hero material, pre-made Map, pre-made OE stuff, etc).

I am not super-keen on changing things as I generally believe it was in the original for a reason (i.e. my original source); however, I can (and am, to an extent) being persuaded. I will endeavor to get word on the matter (still waiting, as I said), and if I don't get anything soon (week or two?) I'll go ahead & take your suggestion.

However, don't let this one issue stop you from entering or competing; I'm sure there's plenty of things that can be done without systems/spells/etc; map-creation, hero design, object-editor work, polish, etc...

In the meantime, I'd really like some other Coder's to chime in on their thoughts about this particular Rule & such. Almia, I know you're out there... : )
 
Last edited:
RESPONSE:
So it's a flying hero? If so, I think that it would not fit into a basic Warcraft 3 hero criteria. That hero would be far to powerful at the start of the game. He would be able to easily harass enemy workers then hide in the trees before the enemy could even get the economy to make anti-air.

Otherwise, I like the ideas of your abilities. I makes it more fast-paced, and really take advantage of the short time effects that are bestowed upon the hero and penalize the enemy. But the 3rd ability (Shock Blast) doesn't really fit in my opinion. The whole stat-based abilities are not something that the heroes should utilize in a vanilla game.
Ofc I will make it hover. D:

Flying heroes would really be insane. Okay, I will change the E.

[E - Shock Blast]
Every 5 seconds the Gryphon Master's attack will deal 40/60/80 + (4/6/8% of target's max health). Reduces cooldown per attack.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
I don't know about you guys. But I have finished the first two spells and some basic effects like freeze and slow. Yes, I decided to submit the ice one, not wind. The hero's name is Coldwraith. Using Sylvanas in banshee mode model. Joined as Undead race \o/
Has 7 proper names. But she is quite weak :(

EDIT:
Have just read the whole main post. Honestly, I never agreed with public poll. Not all users are able to give "precise" review and opinion, some will only vote based on their first impression. Just like me when voted at the past zephyr contest, Be My Angle by Bannar is the first entry I tried. And I'm quite impressed with it, and vote for him instantly without checking any other entries. Then after Dat-C3 asked me, have I tried his entry, I just answered yes whereas I haven't \o/
Then after that, I started to check every entry out :'D I'm not sure though, guess it's just me.

But I'm glad trigger/code gives a great score :D
 
Last edited:
Level 21
Joined
Nov 4, 2013
Messages
2,017
A big possible problem of this contest is that people might think with DotA mind and not with melee mind. That means, low duration of negative buffs, focusing on damage and ultimates which deal damage (if you look well to most of the ultimates of melee heroes, they are either summoning an ultimate monster or an AoE non-damaging spell)
With that being said, I'm afraid some people might go off-course and forget that this hero should be made for melee game, not for an AoS or Hero Arena
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
A big possible problem of this contest is that people might think with DotA mind and not with melee mind. That means, low duration of negative buffs, focusing on damage and ultimates which deal damage (if you look well to most of the ultimates of melee heroes, they are either summoning an ultimate monster or an AoE non-damaging spell)
With that being said, I'm afraid some people might go off-course and forget that this hero should be made for melee game, not for an AoS or Hero Arena

Balance has very little to do with durations, cooldowns, and costs when it comes to design. You could easily make a wc3 hero with 3 passives and an autocast ability and make it balanced wrt the rest of wc3.

Don't make the mistake of producing a bad design just because you think it might feel more like a wc3 hero. On the other extreme, there are many pitfalls related to hero design between rts and moba genres.

@kybri0: I don't want to argue about this (nor do I want to "discuss" or "debate". I don't have time for that) I encourage you to improve your verbosity in written communication, both in discussions and in more formal things like contest descriptions. Looking back at the formal rules (which I didn't read before since rules are usually the same and I don't have time to analyze a wall of text), there are many issues.

I've decided to just produce a hero, and if it gets disqualified over some minutiae, I'll have to just live with it.
 
He thought my Gryphon Master wouldn't Hover. :O

Anyways Kyrbi0 is it okay if we resize models by Y/Z in Model Editor? The Scaling Native does not allow Y/Z. :(

Hero Change for the fifth time. Damn, reusing some ability titles. I didn't even bother starting the last hero because of uncomfortability with the model.

Mystic Wyvern

Q - Spirit Strike
Fires spirit lightning from the tail towards a target area, dealing 80/120/160 damage to enemies hit and reducing their armor by 2/3/4.

W - Skydive
Dives towards a target area, dealing 40/60/80 damage and knocking up enemies hit for 1 second.

E - Withering Aura
Enemies within 600 range take 12/16/20 initial damage and half that amount as DPS for 3 seconds. Afterwards, they can be dealt the initial damage again.

R - Spirit Form
Resets all ability cooldowns, adds 25% physical damage reduction and 25% movement speed for 5 seconds. Abilities in this form have bonus effects.

[Q - Also reduces magic resistance.
W - knockup duration is doubled.
E - Doubles up with a reverse version for allies.]
 
Last edited:
Well, here are my latest WIP's:
2w2rblk.jpg
2cfzl1u.png
2j3rv9k.png
34sj7gk.png
2qn458l.png


Ranger abilities:
Flaming Arrows, Cold Arrows, Swiftness Aura and Black Arrow. (All from alpha)

PS: Some icons such as swiftness aura, black arrow are temporary.
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
Well, here are my latest WIP's:
2w2rblk.jpg
2cfzl1u.png
2j3rv9k.png
34sj7gk.png
2qn458l.png


Ranger abilities:
Flaming Arrows, Cold Arrows, Swiftness Aura and Black Arrow. (All from alpha)

PS: Some icons such as swiftness aura, black arrow are temporary.

I guess my idea isn't very original after all =/

My hero:
Blessed Ranger

Abilities:
Arcane Arrows, Forrestwalk, Holy Sigil, Pure Dexterity

more to come later :3
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
The abilities are different so it's original. :wink:
lol, I think he is not being serious at all :D

Anyway, I think this is the last WIP I will post here:
JASS:
   /*
    *              FROZEN SPELLPACK
    *                          v1.0
   
    *   This spellpack cosists of 4 active spells.
    *   They  are  Cold Addict,  Frostwave,  Frost
    *   Phase, and Hailstorm (ultimate).
    *   Their  codes  are packed into one  library
    *   means  that they are requiring each other.
    
    *   !This spellpack requires JNGP to work!
   
    *   How to install:
    *   - Install  and  configure   all   external
    *     dependecies properly.
    *   - Copy all abilities (OE) in Undead group.
    *   - Copy dummy unit (OE) and it's model to
    *     your map.
    *   - Configure the spells.
   
    *   External Dependencies:
    *       Required:
    *       - CTL
    *       - Dummy
    *       - IsTerrainWalkable
    *       - WorldBounds
    *       - UnitIndexer
    *
    *       Optional:
    *       - SpellEffectEvent
    *       - AutoFly
   
    *   Credits:
    *   - Nestharus
    *   - Bribe
    *   - Cokemonkey11
    *   - Magtheridon96
    
    */
scope FrozenSpellpack

   /*
    *              CONFIGURATION
    
    *   Configuration  is  separated  into  several
    *   parts. Each part is reserved for one spell.
    
    */
    
    /* A. Global */
    globals
        /* Dummy unit's rawcode at Object Editor */
        private constant integer    DUMMY_ID        = 'h000'
        
        /* General decay time for all created sfx */
        private constant real       SFX_DECAY_TIME  = 2.0
    endglobals
    
    /* B. Slow */
    private module SlowData
        /* Slow ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A004'
        
        /* Slow buff's rawcode at Object Editor */
        static constant integer     BUFF_ID         = 'B001'
        
        /* Slow order id */
        static constant integer     SLOW_ORDER      = 852096 /* thunderclap */
        
        /* Attached sfx on slow targets */
        static constant string      SLOW_SFX        = "Abilities\\Spells\\Other\\FrostDamage\\FrostDamage.mdl"
        static constant string      SLOW_SFX_PT     = "chest"
        
        /* Duration is stackable */
        static constant boolean     STACKABLE       = true
        
        /* Will reset the duration if not stacked */
        static constant boolean     RESETABLE       = false
    endmodule
    
    /* C. Freeze */
    private module FreezeData
        /* Freeze ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A008'
        
        /* Freeze buff's rawcode at Object Editor */
        static constant integer     BUFF_ID         = 'B000'
        
        /* Freeze order id */
        static constant integer     FREEZE_ORDER    = 852127 /* stomp */
        
        /* Attached sfx on freeze targets */
        static constant string      FREEZE_SFX      = "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl"
        static constant string      FREEZE_SFX_PT   = "origin"
        
        /* Duration is stackable */
        static constant boolean     STACKABLE       = false
        
        /* Will reset the duration if not stacked */
        static constant boolean     RESETABLE       = false
    endmodule
    
   /*
    *              COLD ADDICT
    
    *   Inflicts frost magic at a  target,  slowing
    *   it's movement and attack rate, and stopping
    *   any mana regeneration.  All  damages  taken
    *   from  caster's  spell  will  be  amplified.
   
    */
    private module ColdAddictData
        /* Main ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A001'
        
        /* Attached sfx on targets */
        static constant string      TARGET_SFX      = "Abilities\\Spells\\Items\\AIob\\AIobTarget.mdl"
        static constant string      TARGET_SFX_PT   = "overhead"
        
        /* Damage amplification is stackable */
        static constant boolean     STACKABLE_BUFF  = false
        
        /* Duration is stackable */
        static constant boolean     STACKABLE_DUR   = false
        
        /* Will reset the duration if not stacked */
        static constant boolean     RESETABLE       = false
        
        /* Damage amplification amount */
        static constant method amount takes integer l returns real
            return -5.0 + 15.0 * l
        endmethod
        
        /* Buff duration on normal units */
        static constant method durationNormal takes integer l returns real
            return 6.0
        endmethod
        
        /* Buff duration on hero units */
        static constant method durationHero takes integer l returns real
            return 4.0
        endmethod
    endmodule
    
   /*
    *              FROSTWAVE
    
    *   Sends a lance of ice  shards  wave  to  the
    *   target point, dealing damage to land  units
    *   in a  line and  slowing  them  for a  short
    *   duration.
   
    */
    private module FrostwaveData
        /* Main ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A000'
        
        /* Total of created missiles on every cast */
        static constant integer     SHARD_COUNT     = 23
        
        /* Normal height z for every missile */
        static constant real        LAUNCH_Z        = 64.0
        
        /* Initial speed of every missile */
        static constant real        SPEED_MIN       = 20.0
        
        /* Maximum speed of every missile */
        static constant real        SPEED_MAX       = 40.0
        
        /* Acceleration rate of every missile */
        static constant real        ACCELERATION    = 0.25
        
        /* Turning rate of every missile */
        static constant real        TURN_RATE       = 12.5 * bj_DEGTORAD
        
        /* Missile model path */
        static constant string      MISSILE_PATH    = "Abilities\\Weapons\\LichMissile\\LichMissile.mdl"
        
        /* Attached sfx on targets */
        static constant string      TARGET_SFX      = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
        static constant string      TARGET_SFX_PT   = "origin"
        
        /* Dealt damage configuration */
        static constant attacktype  ATTACK_TYPE     = ATTACK_TYPE_NORMAL
        static constant damagetype  DAMAGE_TYPE     = DAMAGE_TYPE_NORMAL
        static constant weapontype  WEAPON_TYPE     = WEAPON_TYPE_WHOKNOWS
        
        /* Max distance from missile to hits a target */
        static constant method aoe takes integer l returns real
            return 75.0
        endmethod
        
        /* Dealt damage amount */
        static constant method damage takes integer l returns real
            return 60.0 * l
        endmethod
        
        /* Travel distance of every missile */
        static constant method distance takes integer l returns real
            return 1000.0
        endmethod
        
        /* Slow duration for normal units */
        static constant method durationNormal takes integer l returns real
            return 2.75
        endmethod
        
        /* Slow duration for hero units */
        static constant method durationHero takes integer l returns real
            return 1.325
        endmethod
        
        /* Configure the targets */
        static method filter takes unit u, player p returns boolean
            return not(IsUnitAlly(u, p) or IsUnitType(u, UNIT_TYPE_FLYING) or IsUnitType(u, UNIT_TYPE_STRUCTURE) or IsUnitType(u, UNIT_TYPE_MECHANICAL) or IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE))
        endmethod
    endmodule
    
   /*
    *              FROST PHASE
    
    *   Instantly vanishes  to  the  target  point.
    *   Leaving  ice explosion behind  and  at  the
    *   target  point.  Freezes  nearby enemy units
    *   for a short duration and deals minor damage
   
    */
    private module FrostPhaseData
        /* Main ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A007'
        
        /* How often the spell will check terrain's pathability */
        static constant real        ACCURACY        = 20.0 /* pixel */
        
        /* Explosion sfx */
        static constant real        EXPLODE_SIZE    = 2.0
        static constant string      EXPLODE_SFX     = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
        
        /* Only damage once for each target */
        static constant boolean     DAMAGE_ONCE     = false
        
        /* Dealt damage configuration */
        static constant attacktype  ATTACK_TYPE     = ATTACK_TYPE_NORMAL
        static constant damagetype  DAMAGE_TYPE     = DAMAGE_TYPE_NORMAL
        static constant weapontype  WEAPON_TYPE     = WEAPON_TYPE_WHOKNOWS
        
        /* Dealt damage amount */
        static constant method damage takes integer l returns real
            return 20.0 + 10.0 * l
        endmethod
        
        /* Max range from the center of explosion to hit a target */
        static constant method aoe takes integer l returns real
            return 250.0
        endmethod
        
        /* Max teleport distance */
        static constant method distance takes integer l returns real
            return 300.0 + 100.0 * l
        endmethod
        
        /* Freeze duration for normal units */
        static constant method durationNormal takes integer l returns real
            return 0.9 + 0.45 * l
        endmethod
        
        /* Freeze duration for hero units */
        static constant method durationHero takes integer l returns real
            return 0.45 + 0.225 * l
        endmethod
        
        /* Configure the targets */
        static method filter takes unit u, player p returns boolean
            return not(IsUnitAlly(u, p) or IsUnitType(u, UNIT_TYPE_STRUCTURE) or IsUnitType(u, UNIT_TYPE_MECHANICAL) or IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE))
        endmethod
    endmodule
    
    private module HailstormData
        static constant integer     SPELL_ID        = 'A003'
        static constant real        TARGET_Z        = 350.0
        static constant real        LAUNCH_Z        = 64.0
        static constant boolean     FAIL_STOP       = false
        static constant string      MISSILE_PATH    = "Abilities\\Weapons\\LichMissile\\LichMissile.mdl"
        static constant string      CHANNEL_ORDER   = "blizzard"
        
        static constant method count takes integer l returns integer
            return 1
        endmethod
        
        static constant method accuracy takes integer l returns real
            return 4.5
        endmethod
        
        static constant method turning takes integer l returns real
            return 5.0 * bj_DEGTORAD
        endmethod
        
        static constant method cdelay takes integer l returns real
            return 0.2
        endmethod
        
        static constant method cdelayv takes integer l returns real
            return 0.2
        endmethod
        
        static constant method cduration takes integer l returns real
            return 10.0
        endmethod
        
        static constant method cradius takes integer l returns real
            return 225.0
        endmethod
        
        static constant method fdamage takes integer l returns real
            return 110.0
        endmethod
        
        static constant method faoe takes integer l returns real
            return 75.0
        endmethod
        
        static constant method fdelay takes integer l returns real
            return 0.1
        endmethod
        
        static constant method fduration takes integer l returns real
            return 1.25
        endmethod
    endmodule
    
    native UnitAlive takes unit id returns boolean
    
    /* Function that returns distance between coordinates */
    private function getDistance takes real x, real y, real xt, real yt returns real
        return SquareRoot((xt - x) * (xt - x) + (yt - y) * (yt - y))
    endfunction
    
    /* Function that returns angle between coordinates */
    private function getAngle takes real x, real y, real xt, real yt returns real
        return Atan2(yt - y, xt - x)
    endfunction
    
    private function isInBound takes real x, real y returns boolean
        return x >= WorldBounds.minX and x <= WorldBounds.maxX and y >= WorldBounds.minY and y <= WorldBounds.maxY
    endfunction

    private struct Slow extends array
    
        implement SlowData
        
        unit u
        real d /* duration */
        effect s
        
        static unit c
        static boolean array b
        static thistype array dex
        
        implement CTLExpire
        if .d > 0 then
            set .d = .d - .03125
            if .d <= 0 or not UnitAlive(.u) then
                call DestroyEffect(.s)
                call UnitRemoveAbility(.u, BUFF_ID)
                set b[GetUnitUserData(.u)] = false
                call destroy()
            endif
        endif
        
        implement CTLEnd
        
        static method apply takes unit u, real d returns nothing
        
            local thistype this
            local integer i = GetUnitUserData(u)
            
            if b[i] then
                set this = dex[i]
                /* Stack */
                static if thistype.STACKABLE then
                    set .d = .d + d
                else
                    /* Reset */
                    static if thistype.RESETABLE then
                        set .d = d
                    endif
                endif
            else
                call SetUnitX(c, GetUnitX(u))
                call SetUnitY(c, GetUnitY(u))
                call IssueImmediateOrderById(c, SLOW_ORDER)
                call SetUnitX(c, WorldBounds.maxX)
                call SetUnitY(c, WorldBounds.maxY)
                
                /* Check if the target is successfully buffed */
                if GetUnitAbilityLevel(u, BUFF_ID) > 0 then
                    set this = create()
            
                    set .u = u
                    set .d = d
                    set .s = AddSpecialEffectTarget(SLOW_SFX, u, SLOW_SFX_PT)
                        
                    set b[i] = true
                    set dex[i] = this
                endif
            endif
            
        endmethod
        
        static method onInit takes nothing returns nothing
            set c = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), DUMMY_ID, WorldBounds.maxX, WorldBounds.maxY, 0)
            call UnitAddAbility(c, SPELL_ID)
        endmethod
        
    endstruct

    private struct Freeze extends array
    
        implement FreezeData
        
        unit u
        real d /* duration */
        effect s
        
        static unit c
        static boolean array b
        static thistype array dex
        
        implement CTLExpire
        if .d > 0 then
            set .d = .d - .03125
            if .d <= 0 or not UnitAlive(.u) then
                call DestroyEffect(.s)
                call UnitRemoveAbility(.u, BUFF_ID)
                set b[GetUnitUserData(.u)] = false
                call destroy()
            endif
        endif
        
        implement CTLEnd
        
        static method apply takes unit u, real d returns nothing
        
            local thistype this
            local integer i = GetUnitUserData(u)
            
            if b[i] then
                set this = dex[i]
                /* Stack */
                static if thistype.STACKABLE then
                    set .d = .d + d
                else
                    /* Reset */
                    static if thistype.RESETABLE then
                        set .d = d
                    endif
                endif
            else
                call SetUnitX(c, GetUnitX(u))
                call SetUnitY(c, GetUnitY(u))
                call IssueImmediateOrderById(c, FREEZE_ORDER)
                call SetUnitX(c, WorldBounds.maxX)
                call SetUnitY(c, WorldBounds.maxY)
                
                /* Check if the target is successfully buffed */
                if GetUnitAbilityLevel(u, BUFF_ID) > 0 then
                    set this = create()
                
                    set .u = u
                    set .d = d
                    set .s = AddSpecialEffectTarget(FREEZE_SFX, u, FREEZE_SFX_PT)
                        
                    set b[i] = true
                    set dex[i] = this
                endif
            endif
            
        endmethod
        
        private static method onInit takes nothing returns nothing
            set c = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), DUMMY_ID, WorldBounds.maxX, WorldBounds.maxY, 0)
            call UnitAddAbility(c, SPELL_ID)
        endmethod
    endstruct
        
    /* Destroying Dummy after certain duration */
    private struct RecycleBin extends array
    
        real d /* duration */
        Dummy u
        
        implement CTLExpire
        set .d = .d - .03125
        if .d <= 0 then
            call .u.destroy()
            call destroy()
        endif
        
        implement CTLEnd
        
        static method add takes Dummy u returns nothing
            
            local thistype this = create()
            
            set .d = SFX_DECAY_TIME
            set .u = u
                
        endmethod
    endstruct
    
    /* Cold Addict spell*/
    scope ColdAddict
    
        private struct ColdAddict extends array
        
            implement ColdAddictData
            
            unit u
            real d /* duration */
            real m /* mana */
            effect s
            
            static real array a /* amount */
            static boolean array b
            static thistype array dex
            
            implement CTLExpire
            set .d = .d - .03125
            /* Stops mana regeneration */
            call SetUnitState(.u, UNIT_STATE_MANA, .m)
            if .d <= 0 or not UnitAlive(.u) then
                call DestroyEffect(.s)
                set b[GetUnitUserData(.u)] = false
                call destroy()
            endif
            
            implement CTLEnd
            
            static method onCast takes nothing returns boolean
                
                local thistype this = create()
                local unit t = GetSpellTargetUnit()
                local integer i = GetUnitUserData(t)
                local integer l = GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID)
                
                
                if b[i] then
                    set this = dex[i]
                    static if thistype.STACKABLE_DUR then
                        if IsUnitType(t, UNIT_TYPE_HERO) then
                            set .d = .d + durationHero(l)
                        else
                            set .d = .d + durationNormal(l)
                        endif
                        
                       /*
                        *   Prevent slow buff from being removed before
                        *   cold addict has expired
                        */
                        if Slow.dex[i].d < .d then
                            set Slow.dex[i].d = .d
                        endif
                    else
                        static if thistype.RESETABLE then
                            if IsUnitType(t, UNIT_TYPE_HERO) then
                                set .d = .d + durationHero(l)
                            else
                                set .d = .d + durationNormal(l)
                            endif
                            
                           /*
                            *   Prevent slow buff from being removed before
                            *   cold addict has expired
                            */
                            if Slow.dex[i].d < .d then
                                set Slow.dex[i].d = .d
                            endif
                        endif
                    endif
                    
                    /* Stack amplification amount */
                    static if thistype.STACKABLE_BUFF then
                        set a[i] = a[i] + amount(l)
                    endif
                else
                    set this = create()
            
                    set .u = t
                    set .m = GetUnitState(.u, UNIT_STATE_MANA)
                    
                    if IsUnitType(.u, UNIT_TYPE_HERO) then
                        set .d = .d + durationHero(l)
                    else
                        set .d = .d + durationNormal(l)
                    endif
                    
                    set a[i] = amount(l)
                    set b[i] = true
                    set dex[i] = this
                
                    call Slow.apply(.u, .d)
                    set .s = AddSpecialEffectTarget(TARGET_SFX, .u, TARGET_SFX_PT)
                endif
                set t = null
                
                return false
            endmethod
        
            static if not LIBRARY_SpellEffectEvent then
                private static method check takes nothing returns boolean
                    if GetSpellAbilityId() == SPELL_ID then
                        call thistype.onCast()
                    endif
                    return false
                endmethod
            endif
            
            static method onInit takes nothing returns nothing

                local trigger t
                
                static if LIBRARY_SpellEffectEvent then
                    call RegisterSpellEffectEvent(SPELL_ID, function thistype.onCast)
                else
                    set t = CreateTrigger()
                    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                    call TriggerAddCondition(t, Condition(function thistype.check))
                endif
                
            endmethod
        endstruct
        
    endscope
    
    /* Frostwave spell*/
    scope Frostwave
        
        private struct data extends array
            implement FrostwaveData
            static constant real ANGLE_ADD = (bj_PI * 2)/data.SHARD_COUNT
        endstruct
        
        private module KillShard
            call SetUnitX(i.m.u[j].unit, i.tX)
            call SetUnitY(i.m.u[j].unit, i.tY)
            
            call DestroyEffect(i.m.e[j])
            call RecycleBin.add(i.m.u[j])
            
            set i.m.e[j] = null
            set i.m.b[j] = false
            set i.m.c = i.m.c - 1
            
            if i.m.c < 0 then
                call i.m.destroy()
                set b = true
            endif
        endmodule
            
        private keyword Frostwave
        
        private struct IceShard
            
            integer c
            
            real array a[data.SHARD_COUNT]
            real array s[data.SHARD_COUNT]
            real array x[data.SHARD_COUNT]
            real array y[data.SHARD_COUNT]
            
            Dummy array u[data.SHARD_COUNT]
            boolean array b[data.SHARD_COUNT]
            effect array e[data.SHARD_COUNT]
            
            /* For FoG looping */
            static group t = CreateGroup()
            
            /* Function to compare two distances */
            static method inRadius takes real x, real y, real xt, real yt, real r returns boolean
                return (x - xt) * (x - xt) + (y - yt) * (y - yt) <= r * r
            endmethod
            
            static method move takes Frostwave i returns boolean
                
                local integer j = 0
                local boolean b = false
                local real a
                local unit u
                
                loop
                    exitwhen j > data.SHARD_COUNT - 1
                    
                    if i.m.b[j] then
                        set i.m.x[j] = i.m.x[j] + i.m.s[j] * Cos(i.m.a[j])
                        set i.m.y[j] = i.m.y[j] + i.m.s[j] * Sin(i.m.a[j])
                        
                        if isInBound(i.m.x[j], i.m.y[j]) then
                            /* If has reached the destination */
                            if inRadius(i.m.x[j], i.m.y[j], i.tX, i.tY, i.m.s[j]) then
                                implement KillShard
                            else
                                set a = getAngle(i.m.x[j], i.m.y[j], i.tX, i.tY)
                                
                                call SetUnitX(i.m.u[j].unit, i.m.x[j])
                                call SetUnitY(i.m.u[j].unit, i.m.y[j])
                                call SetUnitFacing(i.m.u[j].unit, i.m.a[j] * bj_RADTODEG)
                               
                               call GroupEnumUnitsInRange(t, i.m.x[j], i.m.y[j], i.a, null)
                                loop
                                    set u = FirstOfGroup(t)
                                    exitwhen u == null
                                    if UnitAlive(u) and not IsUnitInGroup(u, i.g) and data.filter(u, i.p) then
                                        if IsUnitType(u, UNIT_TYPE_HERO) then
                                            call Slow.apply(u, data.durationHero(i.l))
                                        else
                                            call Slow.apply(u, data.durationNormal(i.l))
                                        endif
                                        call UnitDamageTarget(i.c, u, i.d, false, false, data.ATTACK_TYPE, data.DAMAGE_TYPE, data.WEAPON_TYPE)
                                        call DestroyEffect(AddSpecialEffectTarget(data.TARGET_SFX, u, data.TARGET_SFX_PT))
                                        call GroupAddUnit(i.g, u)
                                    endif
                                    call GroupRemoveUnit(t, u)
                                endloop
                                
                               /*
                                *   Turn the missile slowly to face the target
                                *   point based on TURN_RATE
                                */
                                if data.TURN_RATE != 0 and Cos(i.m.a[j] - a) < Cos(data.TURN_RATE) then
                                    if Sin(a - i.m.a[j]) >= 0 then
                                        set i.m.a[j] = i.m.a[j] + data.TURN_RATE
                                    else
                                        set i.m.a[j] = i.m.a[j] - data.TURN_RATE
                                    endif
                                else
                                    set i.m.a[j] = a
                                    /* Accelerate if has faced the target point correctly */
                                    set i.m.s[j] = i.m.s[j] + data.ACCELERATION
                                    if i.m.s[j] > data.SPEED_MAX then
                                        set i.m.s[j] = data.SPEED_MAX
                                    endif
                                endif
                            endif
                        else
                            implement KillShard
                        endif
                    endif
                    
                    set j = j + 1
                endloop
                
                return b
            endmethod
            
            static method create takes real x, real y, real f returns thistype
                
                local thistype this = allocate()
                local integer i = 0
                
                /* Determine the lowest angle */
                set f = f - data.ANGLE_ADD * (data.SHARD_COUNT/2)
                set .c = data.SHARD_COUNT - 1
                
                loop
                    exitwhen i > .c
                    
                    set .s[i] = data.SPEED_MIN
                    set .a[i] = f
                    set .b[i] = true
                    
                    set .x[i] = x
                    set .y[i] = y
                    set .u[i] = Dummy.create(x, y, f * bj_RADTODEG)
                    set .e[i] = AddSpecialEffectTarget(data.MISSILE_PATH, .u[i].unit, "origin")
                    
                    if not LIBRARY_AutoFly then
                        if UnitAddAbility(.u[i].unit, 'Amrf') and UnitRemoveAbility(.u[i].unit, 'Amrf') then
                        endif
                    endif
                    call SetUnitFlyHeight(.u[i].unit, data.LAUNCH_Z, 0)
                    
                    set f = f + data.ANGLE_ADD
                    set i = i + 1
                endloop
                
                return this
            endmethod
            
        endstruct
        
        private struct Frostwave extends array
            
            real tX
            real tY
            
            real a  /* AoE */
            real d  /* damage */
            
            group g
            player p
            unit c
            
            integer l /* level */
            IceShard m /* missile */
            
            implement CTL
            local boolean b
                
            implement CTLExpire
            set b = IceShard.move(this)
            if b then
                call DestroyGroup(.g)
                call destroy()
            endif
            
            implement CTLEnd
            
            static method onCast takes nothing returns boolean
                
                local thistype this = create()
                local real a
                local real x
                local real y
                
                set .c = GetTriggerUnit()
                set .p = GetTriggerPlayer()
                set .g = CreateGroup()
                
                set x = GetUnitX(.c)
                set y = GetUnitY(.c)
                set .tX = GetSpellTargetX()
                set .tY = GetSpellTargetY()
                
                set .l = GetUnitAbilityLevel(.c, data.SPELL_ID)
                /* If target point is the same as cast point */
                if x == .tX and y == .tY then
                    set a = GetUnitFacing(.c) * bj_DEGTORAD
                else
                    set a = getAngle(x, y, .tX, .tY)
                endif
                
                set .m = IceShard.create(x, y, a)
                set .tX = x + data.distance(.l) * Cos(a)
                set .tY = y + data.distance(.l) * Sin(a)
                
                set .d = data.damage(.l)
                set .a = data.aoe(.l)
                
                return false
            endmethod
        
            static if not LIBRARY_SpellEffectEvent then
                private static method check takes nothing returns boolean
                    if GetSpellAbilityId() == data.SPELL_ID then
                        call thistype.onCast()
                    endif
                    return false
                endmethod
            endif
            
            static method onInit takes nothing returns nothing

                local trigger t
                
                static if LIBRARY_SpellEffectEvent then
                    call RegisterSpellEffectEvent(data.SPELL_ID, function thistype.onCast)
                else
                    set t = CreateTrigger()
                    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                    call TriggerAddCondition(t, Condition(function thistype.check))
                endif
                
            endmethod
            
        endstruct
    endscope
    
    scope FrostPhase
    
        private struct FrostPhase extends array
        
            implement FrostPhaseData
            
            real a /* AoE */
            real r /* angle */
            real d /* distance */
            real dmg
            
            real x
            real y
            
            group g
            player p
            unit c
            
            integer l /* level */
            
            static group t = CreateGroup()
            
            implement CTL
            local unit u
            local unit d
            local real c = 0
                
            implement CTLExpire
           /* 
            *   Check terrain pathability between cast and
            *   target point
            */
            set c = 0
            loop
                exitwhen c >= .d or not IsTerrainWalkable(.x, .y)
                set .x = .x + ACCURACY * Cos(.r)
                set .y = .y + ACCURACY * Sin(.r)
                set c = c + ACCURACY
            endloop
            
            call SetUnitPosition(.c, .x, .y)
            set .x = GetUnitX(.c)
            set .y = GetUnitY(.c)
            
            call GroupEnumUnitsInRange(t, .x, .y, .a, null)
            loop
                set u = FirstOfGroup(t)
                exitwhen u == null
                
                if UnitAlive(u) and filter(u, .p) then
                    if not IsUnitInGroup(u, .g) then
                        /* If only deal damage for once per unit*/
                        static if DAMAGE_ONCE then
                            call GroupAddUnit(.g, u)
                        endif
                        
                        if IsUnitType(u, UNIT_TYPE_HERO) then
                            call Freeze.apply(u, durationHero(.l))
                        else
                            call Freeze.apply(u, durationNormal(.l))
                        endif
                        call UnitDamageTarget(.c, u, .dmg, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
                    endif
                endif
                call GroupRemoveUnit(t, u)
            endloop
            
            /* Create scaled sfx at target point */
            set d = CreateUnit(.p, DUMMY_ID, .x, .y, 0)
            call SetUnitScale(d, EXPLODE_SIZE, 1, 1)
            call DestroyEffect(AddSpecialEffectTarget(EXPLODE_SFX, d, "origin"))
            call UnitApplyTimedLife(d, 'BTLF', SFX_DECAY_TIME)
            
            static if DAMAGE_ONCE then
                call DestroyGroup(.g)
            endif
            
            call destroy()
            set d = null
            
            implement CTLEnd
            
            static method onCast takes nothing returns boolean
                
                local thistype this = create()
                local integer l
                local real xt
                local real yt
                local unit u
                local unit d
                
                set .c = GetTriggerUnit()
                set .p = GetTriggerPlayer()
                set .g = CreateGroup()
                
                set .x = GetUnitX(.c)
                set .y = GetUnitY(.c)
                set xt = GetSpellTargetX()
                set yt = GetSpellTargetY()
                
                set .l = GetUnitAbilityLevel(.c, SPELL_ID)
                set .r = getAngle(.x, .y, xt, yt)
                
                set .d = getDistance(.x, .y, xt, yt)
                if .d > distance(.l) then
                    set .d = distance(.l)
                endif
                
                set .dmg = damage(.l)
                set .a = aoe(.l)
                
                call GroupEnumUnitsInRange(t, .x, .y, .a, null)
                loop
                    set u = FirstOfGroup(t)
                    exitwhen u == null
                    
                    if UnitAlive(u) and filter(u, .p) then
                        if not IsUnitInGroup(u, .g) then
                            /* If only deal damage for once per unit*/
                            static if DAMAGE_ONCE then
                                call GroupAddUnit(.g, u)
                            endif
                            
                            if IsUnitType(u, UNIT_TYPE_HERO) then
                                call Freeze.apply(u, durationHero(.l))
                            else
                                call Freeze.apply(u, durationNormal(.l))
                            endif
                            call UnitDamageTarget(.c, u, .dmg, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
                        endif
                    endif
                    
                    call GroupRemoveUnit(t, u)
                endloop
                
                /* Create scaled sfx at cast point */
                set d = CreateUnit(.p, DUMMY_ID, .x, .y, 0)
                call SetUnitScale(d, EXPLODE_SIZE, 1, 1)
                call DestroyEffect(AddSpecialEffectTarget(EXPLODE_SFX, d, "origin"))
                call UnitApplyTimedLife(d, 'BTLF', SFX_DECAY_TIME)
                set d = null
                
                return false
            endmethod
            
            static if not LIBRARY_SpellEffectEvent then
                private static method check takes nothing returns boolean
                    if GetSpellAbilityId() == SPELL_ID then
                        call thistype.onCast()
                    endif
                    return false
                endmethod
            endif
            
            static method onInit takes nothing returns nothing

                local trigger t
                
                static if LIBRARY_SpellEffectEvent then
                    call RegisterSpellEffectEvent(SPELL_ID, function thistype.onCast)
                else
                    set t = CreateTrigger()
                    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                    call TriggerAddCondition(t, Condition(function thistype.check))
                endif
                
            endmethod
        endstruct
    endscope
    
    scope Hailstorm
        
        /*private struct Hailstorm extends array
        
            static method onInit takes nothing returns nothing

                local trigger t
                
                static if LIBRARY_SpellEffectEvent then
                    call RegisterSpellEffectEvent(data.SPELL_ID, function thistype.onCast)
                else
                    set t = CreateTrigger()
                    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                    call TriggerAddCondition(t, Condition(function thistype.check))
                endif
                
            endmethod
            
        endstruct*/
        
    endscope
    
endscope
Still too lazy to work on the ultimate ability, it's gonna be quite complicated :(
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
lol, I think he is not being serious at all :D

Anyway, I think this is the last WIP I will post here:
JASS:
   /*
    *              FROZEN SPELLPACK
    *                          v1.0
   
    *   This spellpack cosists of 4 active spells.
    *   They  are  Cold Addict,  Frostwave,  Frost
    *   Phase, and Hailstorm (ultimate).
    *   Their  codes  are packed into one  library
    *   means  that they are requiring each other.
    
    *   !This spellpack requires JNGP to work!
   
    *   How to install:
    *   - Install  and  configure   all   external
    *     dependecies properly.
    *   - Copy all abilities (OE) in Undead group.
    *   - Copy dummy unit (OE) and it's model to
    *     your map.
    *   - Configure the spells.
   
    *   External Dependencies:
    *       Required:
    *       - CTL
    *       - Dummy
    *       - IsTerrainWalkable
    *       - WorldBounds
    *       - UnitIndexer
    *
    *       Optional:
    *       - SpellEffectEvent
    *       - AutoFly
   
    *   Credits:
    *   - Nestharus
    *   - Bribe
    *   - Cokemonkey11
    *   - Magtheridon96
    
    */
scope FrozenSpellpack

   /*
    *              CONFIGURATION
    
    *   Configuration  is  separated  into  several
    *   parts. Each part is reserved for one spell.
    
    */
    
    /* A. Global */
    globals
        /* Dummy unit's rawcode at Object Editor */
        private constant integer    DUMMY_ID        = 'h000'
        
        /* General decay time for all created sfx */
        private constant real       SFX_DECAY_TIME  = 2.0
    endglobals
    
    /* B. Slow */
    private module SlowData
        /* Slow ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A004'
        
        /* Slow buff's rawcode at Object Editor */
        static constant integer     BUFF_ID         = 'B001'
        
        /* Slow order id */
        static constant integer     SLOW_ORDER      = 852096 /* thunderclap */
        
        /* Attached sfx on slow targets */
        static constant string      SLOW_SFX        = "Abilities\\Spells\\Other\\FrostDamage\\FrostDamage.mdl"
        static constant string      SLOW_SFX_PT     = "chest"
        
        /* Duration is stackable */
        static constant boolean     STACKABLE       = true
        
        /* Will reset the duration if not stacked */
        static constant boolean     RESETABLE       = false
    endmodule
    
    /* C. Freeze */
    private module FreezeData
        /* Freeze ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A008'
        
        /* Freeze buff's rawcode at Object Editor */
        static constant integer     BUFF_ID         = 'B000'
        
        /* Freeze order id */
        static constant integer     FREEZE_ORDER    = 852127 /* stomp */
        
        /* Attached sfx on freeze targets */
        static constant string      FREEZE_SFX      = "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl"
        static constant string      FREEZE_SFX_PT   = "origin"
        
        /* Duration is stackable */
        static constant boolean     STACKABLE       = false
        
        /* Will reset the duration if not stacked */
        static constant boolean     RESETABLE       = false
    endmodule
    
   /*
    *              COLD ADDICT
    
    *   Inflicts frost magic at a  target,  slowing
    *   it's movement and attack rate, and stopping
    *   any mana regeneration.  All  damages  taken
    *   from  caster's  spell  will  be  amplified.
   
    */
    private module ColdAddictData
        /* Main ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A001'
        
        /* Attached sfx on targets */
        static constant string      TARGET_SFX      = "Abilities\\Spells\\Items\\AIob\\AIobTarget.mdl"
        static constant string      TARGET_SFX_PT   = "overhead"
        
        /* Damage amplification is stackable */
        static constant boolean     STACKABLE_BUFF  = false
        
        /* Duration is stackable */
        static constant boolean     STACKABLE_DUR   = false
        
        /* Will reset the duration if not stacked */
        static constant boolean     RESETABLE       = false
        
        /* Damage amplification amount */
        static constant method amount takes integer l returns real
            return -5.0 + 15.0 * l
        endmethod
        
        /* Buff duration on normal units */
        static constant method durationNormal takes integer l returns real
            return 6.0
        endmethod
        
        /* Buff duration on hero units */
        static constant method durationHero takes integer l returns real
            return 4.0
        endmethod
    endmodule
    
   /*
    *              FROSTWAVE
    
    *   Sends a lance of ice  shards  wave  to  the
    *   target point, dealing damage to land  units
    *   in a  line and  slowing  them  for a  short
    *   duration.
   
    */
    private module FrostwaveData
        /* Main ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A000'
        
        /* Total of created missiles on every cast */
        static constant integer     SHARD_COUNT     = 23
        
        /* Normal height z for every missile */
        static constant real        LAUNCH_Z        = 64.0
        
        /* Initial speed of every missile */
        static constant real        SPEED_MIN       = 20.0
        
        /* Maximum speed of every missile */
        static constant real        SPEED_MAX       = 40.0
        
        /* Acceleration rate of every missile */
        static constant real        ACCELERATION    = 0.25
        
        /* Turning rate of every missile */
        static constant real        TURN_RATE       = 12.5 * bj_DEGTORAD
        
        /* Missile model path */
        static constant string      MISSILE_PATH    = "Abilities\\Weapons\\LichMissile\\LichMissile.mdl"
        
        /* Attached sfx on targets */
        static constant string      TARGET_SFX      = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
        static constant string      TARGET_SFX_PT   = "origin"
        
        /* Dealt damage configuration */
        static constant attacktype  ATTACK_TYPE     = ATTACK_TYPE_NORMAL
        static constant damagetype  DAMAGE_TYPE     = DAMAGE_TYPE_NORMAL
        static constant weapontype  WEAPON_TYPE     = WEAPON_TYPE_WHOKNOWS
        
        /* Max distance from missile to hits a target */
        static constant method aoe takes integer l returns real
            return 75.0
        endmethod
        
        /* Dealt damage amount */
        static constant method damage takes integer l returns real
            return 60.0 * l
        endmethod
        
        /* Travel distance of every missile */
        static constant method distance takes integer l returns real
            return 1000.0
        endmethod
        
        /* Slow duration for normal units */
        static constant method durationNormal takes integer l returns real
            return 2.75
        endmethod
        
        /* Slow duration for hero units */
        static constant method durationHero takes integer l returns real
            return 1.325
        endmethod
        
        /* Configure the targets */
        static method filter takes unit u, player p returns boolean
            return not(IsUnitAlly(u, p) or IsUnitType(u, UNIT_TYPE_FLYING) or IsUnitType(u, UNIT_TYPE_STRUCTURE) or IsUnitType(u, UNIT_TYPE_MECHANICAL) or IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE))
        endmethod
    endmodule
    
   /*
    *              FROST PHASE
    
    *   Instantly vanishes  to  the  target  point.
    *   Leaving  ice explosion behind  and  at  the
    *   target  point.  Freezes  nearby enemy units
    *   for a short duration and deals minor damage
   
    */
    private module FrostPhaseData
        /* Main ability's rawcode at Object Editor */
        static constant integer     SPELL_ID        = 'A007'
        
        /* How often the spell will check terrain's pathability */
        static constant real        ACCURACY        = 20.0 /* pixel */
        
        /* Explosion sfx */
        static constant real        EXPLODE_SIZE    = 2.0
        static constant string      EXPLODE_SFX     = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
        
        /* Only damage once for each target */
        static constant boolean     DAMAGE_ONCE     = false
        
        /* Dealt damage configuration */
        static constant attacktype  ATTACK_TYPE     = ATTACK_TYPE_NORMAL
        static constant damagetype  DAMAGE_TYPE     = DAMAGE_TYPE_NORMAL
        static constant weapontype  WEAPON_TYPE     = WEAPON_TYPE_WHOKNOWS
        
        /* Dealt damage amount */
        static constant method damage takes integer l returns real
            return 20.0 + 10.0 * l
        endmethod
        
        /* Max range from the center of explosion to hit a target */
        static constant method aoe takes integer l returns real
            return 250.0
        endmethod
        
        /* Max teleport distance */
        static constant method distance takes integer l returns real
            return 300.0 + 100.0 * l
        endmethod
        
        /* Freeze duration for normal units */
        static constant method durationNormal takes integer l returns real
            return 0.9 + 0.45 * l
        endmethod
        
        /* Freeze duration for hero units */
        static constant method durationHero takes integer l returns real
            return 0.45 + 0.225 * l
        endmethod
        
        /* Configure the targets */
        static method filter takes unit u, player p returns boolean
            return not(IsUnitAlly(u, p) or IsUnitType(u, UNIT_TYPE_STRUCTURE) or IsUnitType(u, UNIT_TYPE_MECHANICAL) or IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE))
        endmethod
    endmodule
    
    private module HailstormData
        static constant integer     SPELL_ID        = 'A003'
        static constant real        TARGET_Z        = 350.0
        static constant real        LAUNCH_Z        = 64.0
        static constant boolean     FAIL_STOP       = false
        static constant string      MISSILE_PATH    = "Abilities\\Weapons\\LichMissile\\LichMissile.mdl"
        static constant string      CHANNEL_ORDER   = "blizzard"
        
        static constant method count takes integer l returns integer
            return 1
        endmethod
        
        static constant method accuracy takes integer l returns real
            return 4.5
        endmethod
        
        static constant method turning takes integer l returns real
            return 5.0 * bj_DEGTORAD
        endmethod
        
        static constant method cdelay takes integer l returns real
            return 0.2
        endmethod
        
        static constant method cdelayv takes integer l returns real
            return 0.2
        endmethod
        
        static constant method cduration takes integer l returns real
            return 10.0
        endmethod
        
        static constant method cradius takes integer l returns real
            return 225.0
        endmethod
        
        static constant method fdamage takes integer l returns real
            return 110.0
        endmethod
        
        static constant method faoe takes integer l returns real
            return 75.0
        endmethod
        
        static constant method fdelay takes integer l returns real
            return 0.1
        endmethod
        
        static constant method fduration takes integer l returns real
            return 1.25
        endmethod
    endmodule
    
    native UnitAlive takes unit id returns boolean
    
    /* Function that returns distance between coordinates */
    private function getDistance takes real x, real y, real xt, real yt returns real
        return SquareRoot((xt - x) * (xt - x) + (yt - y) * (yt - y))
    endfunction
    
    /* Function that returns angle between coordinates */
    private function getAngle takes real x, real y, real xt, real yt returns real
        return Atan2(yt - y, xt - x)
    endfunction
    
    private function isInBound takes real x, real y returns boolean
        return x >= WorldBounds.minX and x <= WorldBounds.maxX and y >= WorldBounds.minY and y <= WorldBounds.maxY
    endfunction

    private struct Slow extends array
    
        implement SlowData
        
        unit u
        real d /* duration */
        effect s
        
        static unit c
        static boolean array b
        static thistype array dex
        
        implement CTLExpire
        if .d > 0 then
            set .d = .d - .03125
            if .d <= 0 or not UnitAlive(.u) then
                call DestroyEffect(.s)
                call UnitRemoveAbility(.u, BUFF_ID)
                set b[GetUnitUserData(.u)] = false
                call destroy()
            endif
        endif
        
        implement CTLEnd
        
        static method apply takes unit u, real d returns nothing
        
            local thistype this
            local integer i = GetUnitUserData(u)
            
            if b[i] then
                set this = dex[i]
                /* Stack */
                static if thistype.STACKABLE then
                    set .d = .d + d
                else
                    /* Reset */
                    static if thistype.RESETABLE then
                        set .d = d
                    endif
                endif
            else
                call SetUnitX(c, GetUnitX(u))
                call SetUnitY(c, GetUnitY(u))
                call IssueImmediateOrderById(c, SLOW_ORDER)
                call SetUnitX(c, WorldBounds.maxX)
                call SetUnitY(c, WorldBounds.maxY)
                
                /* Check if the target is successfully buffed */
                if GetUnitAbilityLevel(u, BUFF_ID) > 0 then
                    set this = create()
            
                    set .u = u
                    set .d = d
                    set .s = AddSpecialEffectTarget(SLOW_SFX, u, SLOW_SFX_PT)
                        
                    set b[i] = true
                    set dex[i] = this
                endif
            endif
            
        endmethod
        
        static method onInit takes nothing returns nothing
            set c = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), DUMMY_ID, WorldBounds.maxX, WorldBounds.maxY, 0)
            call UnitAddAbility(c, SPELL_ID)
        endmethod
        
    endstruct

    private struct Freeze extends array
    
        implement FreezeData
        
        unit u
        real d /* duration */
        effect s
        
        static unit c
        static boolean array b
        static thistype array dex
        
        implement CTLExpire
        if .d > 0 then
            set .d = .d - .03125
            if .d <= 0 or not UnitAlive(.u) then
                call DestroyEffect(.s)
                call UnitRemoveAbility(.u, BUFF_ID)
                set b[GetUnitUserData(.u)] = false
                call destroy()
            endif
        endif
        
        implement CTLEnd
        
        static method apply takes unit u, real d returns nothing
        
            local thistype this
            local integer i = GetUnitUserData(u)
            
            if b[i] then
                set this = dex[i]
                /* Stack */
                static if thistype.STACKABLE then
                    set .d = .d + d
                else
                    /* Reset */
                    static if thistype.RESETABLE then
                        set .d = d
                    endif
                endif
            else
                call SetUnitX(c, GetUnitX(u))
                call SetUnitY(c, GetUnitY(u))
                call IssueImmediateOrderById(c, FREEZE_ORDER)
                call SetUnitX(c, WorldBounds.maxX)
                call SetUnitY(c, WorldBounds.maxY)
                
                /* Check if the target is successfully buffed */
                if GetUnitAbilityLevel(u, BUFF_ID) > 0 then
                    set this = create()
                
                    set .u = u
                    set .d = d
                    set .s = AddSpecialEffectTarget(FREEZE_SFX, u, FREEZE_SFX_PT)
                        
                    set b[i] = true
                    set dex[i] = this
                endif
            endif
            
        endmethod
        
        private static method onInit takes nothing returns nothing
            set c = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), DUMMY_ID, WorldBounds.maxX, WorldBounds.maxY, 0)
            call UnitAddAbility(c, SPELL_ID)
        endmethod
    endstruct
        
    /* Destroying Dummy after certain duration */
    private struct RecycleBin extends array
    
        real d /* duration */
        Dummy u
        
        implement CTLExpire
        set .d = .d - .03125
        if .d <= 0 then
            call .u.destroy()
            call destroy()
        endif
        
        implement CTLEnd
        
        static method add takes Dummy u returns nothing
            
            local thistype this = create()
            
            set .d = SFX_DECAY_TIME
            set .u = u
                
        endmethod
    endstruct
    
    /* Cold Addict spell*/
    scope ColdAddict
    
        private struct ColdAddict extends array
        
            implement ColdAddictData
            
            unit u
            real d /* duration */
            real m /* mana */
            effect s
            
            static real array a /* amount */
            static boolean array b
            static thistype array dex
            
            implement CTLExpire
            set .d = .d - .03125
            /* Stops mana regeneration */
            call SetUnitState(.u, UNIT_STATE_MANA, .m)
            if .d <= 0 or not UnitAlive(.u) then
                call DestroyEffect(.s)
                set b[GetUnitUserData(.u)] = false
                call destroy()
            endif
            
            implement CTLEnd
            
            static method onCast takes nothing returns boolean
                
                local thistype this = create()
                local unit t = GetSpellTargetUnit()
                local integer i = GetUnitUserData(t)
                local integer l = GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID)
                
                
                if b[i] then
                    set this = dex[i]
                    static if thistype.STACKABLE_DUR then
                        if IsUnitType(t, UNIT_TYPE_HERO) then
                            set .d = .d + durationHero(l)
                        else
                            set .d = .d + durationNormal(l)
                        endif
                        
                       /*
                        *   Prevent slow buff from being removed before
                        *   cold addict has expired
                        */
                        if Slow.dex[i].d < .d then
                            set Slow.dex[i].d = .d
                        endif
                    else
                        static if thistype.RESETABLE then
                            if IsUnitType(t, UNIT_TYPE_HERO) then
                                set .d = .d + durationHero(l)
                            else
                                set .d = .d + durationNormal(l)
                            endif
                            
                           /*
                            *   Prevent slow buff from being removed before
                            *   cold addict has expired
                            */
                            if Slow.dex[i].d < .d then
                                set Slow.dex[i].d = .d
                            endif
                        endif
                    endif
                    
                    /* Stack amplification amount */
                    static if thistype.STACKABLE_BUFF then
                        set a[i] = a[i] + amount(l)
                    endif
                else
                    set this = create()
            
                    set .u = t
                    set .m = GetUnitState(.u, UNIT_STATE_MANA)
                    
                    if IsUnitType(.u, UNIT_TYPE_HERO) then
                        set .d = .d + durationHero(l)
                    else
                        set .d = .d + durationNormal(l)
                    endif
                    
                    set a[i] = amount(l)
                    set b[i] = true
                    set dex[i] = this
                
                    call Slow.apply(.u, .d)
                    set .s = AddSpecialEffectTarget(TARGET_SFX, .u, TARGET_SFX_PT)
                endif
                set t = null
                
                return false
            endmethod
        
            static if not LIBRARY_SpellEffectEvent then
                private static method check takes nothing returns boolean
                    if GetSpellAbilityId() == SPELL_ID then
                        call thistype.onCast()
                    endif
                    return false
                endmethod
            endif
            
            static method onInit takes nothing returns nothing

                local trigger t
                
                static if LIBRARY_SpellEffectEvent then
                    call RegisterSpellEffectEvent(SPELL_ID, function thistype.onCast)
                else
                    set t = CreateTrigger()
                    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                    call TriggerAddCondition(t, Condition(function thistype.check))
                endif
                
            endmethod
        endstruct
        
    endscope
    
    /* Frostwave spell*/
    scope Frostwave
        
        private struct data extends array
            implement FrostwaveData
            static constant real ANGLE_ADD = (bj_PI * 2)/data.SHARD_COUNT
        endstruct
        
        private module KillShard
            call SetUnitX(i.m.u[j].unit, i.tX)
            call SetUnitY(i.m.u[j].unit, i.tY)
            
            call DestroyEffect(i.m.e[j])
            call RecycleBin.add(i.m.u[j])
            
            set i.m.e[j] = null
            set i.m.b[j] = false
            set i.m.c = i.m.c - 1
            
            if i.m.c < 0 then
                call i.m.destroy()
                set b = true
            endif
        endmodule
            
        private keyword Frostwave
        
        private struct IceShard
            
            integer c
            
            real array a[data.SHARD_COUNT]
            real array s[data.SHARD_COUNT]
            real array x[data.SHARD_COUNT]
            real array y[data.SHARD_COUNT]
            
            Dummy array u[data.SHARD_COUNT]
            boolean array b[data.SHARD_COUNT]
            effect array e[data.SHARD_COUNT]
            
            /* For FoG looping */
            static group t = CreateGroup()
            
            /* Function to compare two distances */
            static method inRadius takes real x, real y, real xt, real yt, real r returns boolean
                return (x - xt) * (x - xt) + (y - yt) * (y - yt) <= r * r
            endmethod
            
            static method move takes Frostwave i returns boolean
                
                local integer j = 0
                local boolean b = false
                local real a
                local unit u
                
                loop
                    exitwhen j > data.SHARD_COUNT - 1
                    
                    if i.m.b[j] then
                        set i.m.x[j] = i.m.x[j] + i.m.s[j] * Cos(i.m.a[j])
                        set i.m.y[j] = i.m.y[j] + i.m.s[j] * Sin(i.m.a[j])
                        
                        if isInBound(i.m.x[j], i.m.y[j]) then
                            /* If has reached the destination */
                            if inRadius(i.m.x[j], i.m.y[j], i.tX, i.tY, i.m.s[j]) then
                                implement KillShard
                            else
                                set a = getAngle(i.m.x[j], i.m.y[j], i.tX, i.tY)
                                
                                call SetUnitX(i.m.u[j].unit, i.m.x[j])
                                call SetUnitY(i.m.u[j].unit, i.m.y[j])
                                call SetUnitFacing(i.m.u[j].unit, i.m.a[j] * bj_RADTODEG)
                               
                               call GroupEnumUnitsInRange(t, i.m.x[j], i.m.y[j], i.a, null)
                                loop
                                    set u = FirstOfGroup(t)
                                    exitwhen u == null
                                    if UnitAlive(u) and not IsUnitInGroup(u, i.g) and data.filter(u, i.p) then
                                        if IsUnitType(u, UNIT_TYPE_HERO) then
                                            call Slow.apply(u, data.durationHero(i.l))
                                        else
                                            call Slow.apply(u, data.durationNormal(i.l))
                                        endif
                                        call UnitDamageTarget(i.c, u, i.d, false, false, data.ATTACK_TYPE, data.DAMAGE_TYPE, data.WEAPON_TYPE)
                                        call DestroyEffect(AddSpecialEffectTarget(data.TARGET_SFX, u, data.TARGET_SFX_PT))
                                        call GroupAddUnit(i.g, u)
                                    endif
                                    call GroupRemoveUnit(t, u)
                                endloop
                                
                               /*
                                *   Turn the missile slowly to face the target
                                *   point based on TURN_RATE
                                */
                                if data.TURN_RATE != 0 and Cos(i.m.a[j] - a) < Cos(data.TURN_RATE) then
                                    if Sin(a - i.m.a[j]) >= 0 then
                                        set i.m.a[j] = i.m.a[j] + data.TURN_RATE
                                    else
                                        set i.m.a[j] = i.m.a[j] - data.TURN_RATE
                                    endif
                                else
                                    set i.m.a[j] = a
                                    /* Accelerate if has faced the target point correctly */
                                    set i.m.s[j] = i.m.s[j] + data.ACCELERATION
                                    if i.m.s[j] > data.SPEED_MAX then
                                        set i.m.s[j] = data.SPEED_MAX
                                    endif
                                endif
                            endif
                        else
                            implement KillShard
                        endif
                    endif
                    
                    set j = j + 1
                endloop
                
                return b
            endmethod
            
            static method create takes real x, real y, real f returns thistype
                
                local thistype this = allocate()
                local integer i = 0
                
                /* Determine the lowest angle */
                set f = f - data.ANGLE_ADD * (data.SHARD_COUNT/2)
                set .c = data.SHARD_COUNT - 1
                
                loop
                    exitwhen i > .c
                    
                    set .s[i] = data.SPEED_MIN
                    set .a[i] = f
                    set .b[i] = true
                    
                    set .x[i] = x
                    set .y[i] = y
                    set .u[i] = Dummy.create(x, y, f * bj_RADTODEG)
                    set .e[i] = AddSpecialEffectTarget(data.MISSILE_PATH, .u[i].unit, "origin")
                    
                    if not LIBRARY_AutoFly then
                        if UnitAddAbility(.u[i].unit, 'Amrf') and UnitRemoveAbility(.u[i].unit, 'Amrf') then
                        endif
                    endif
                    call SetUnitFlyHeight(.u[i].unit, data.LAUNCH_Z, 0)
                    
                    set f = f + data.ANGLE_ADD
                    set i = i + 1
                endloop
                
                return this
            endmethod
            
        endstruct
        
        private struct Frostwave extends array
            
            real tX
            real tY
            
            real a  /* AoE */
            real d  /* damage */
            
            group g
            player p
            unit c
            
            integer l /* level */
            IceShard m /* missile */
            
            implement CTL
            local boolean b
                
            implement CTLExpire
            set b = IceShard.move(this)
            if b then
                call DestroyGroup(.g)
                call destroy()
            endif
            
            implement CTLEnd
            
            static method onCast takes nothing returns boolean
                
                local thistype this = create()
                local real a
                local real x
                local real y
                
                set .c = GetTriggerUnit()
                set .p = GetTriggerPlayer()
                set .g = CreateGroup()
                
                set x = GetUnitX(.c)
                set y = GetUnitY(.c)
                set .tX = GetSpellTargetX()
                set .tY = GetSpellTargetY()
                
                set .l = GetUnitAbilityLevel(.c, data.SPELL_ID)
                /* If target point is the same as cast point */
                if x == .tX and y == .tY then
                    set a = GetUnitFacing(.c) * bj_DEGTORAD
                else
                    set a = getAngle(x, y, .tX, .tY)
                endif
                
                set .m = IceShard.create(x, y, a)
                set .tX = x + data.distance(.l) * Cos(a)
                set .tY = y + data.distance(.l) * Sin(a)
                
                set .d = data.damage(.l)
                set .a = data.aoe(.l)
                
                return false
            endmethod
        
            static if not LIBRARY_SpellEffectEvent then
                private static method check takes nothing returns boolean
                    if GetSpellAbilityId() == data.SPELL_ID then
                        call thistype.onCast()
                    endif
                    return false
                endmethod
            endif
            
            static method onInit takes nothing returns nothing

                local trigger t
                
                static if LIBRARY_SpellEffectEvent then
                    call RegisterSpellEffectEvent(data.SPELL_ID, function thistype.onCast)
                else
                    set t = CreateTrigger()
                    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                    call TriggerAddCondition(t, Condition(function thistype.check))
                endif
                
            endmethod
            
        endstruct
    endscope
    
    scope FrostPhase
    
        private struct FrostPhase extends array
        
            implement FrostPhaseData
            
            real a /* AoE */
            real r /* angle */
            real d /* distance */
            real dmg
            
            real x
            real y
            
            group g
            player p
            unit c
            
            integer l /* level */
            
            static group t = CreateGroup()
            
            implement CTL
            local unit u
            local unit d
            local real c = 0
                
            implement CTLExpire
           /* 
            *   Check terrain pathability between cast and
            *   target point
            */
            set c = 0
            loop
                exitwhen c >= .d or not IsTerrainWalkable(.x, .y)
                set .x = .x + ACCURACY * Cos(.r)
                set .y = .y + ACCURACY * Sin(.r)
                set c = c + ACCURACY
            endloop
            
            call SetUnitPosition(.c, .x, .y)
            set .x = GetUnitX(.c)
            set .y = GetUnitY(.c)
            
            call GroupEnumUnitsInRange(t, .x, .y, .a, null)
            loop
                set u = FirstOfGroup(t)
                exitwhen u == null
                
                if UnitAlive(u) and filter(u, .p) then
                    if not IsUnitInGroup(u, .g) then
                        /* If only deal damage for once per unit*/
                        static if DAMAGE_ONCE then
                            call GroupAddUnit(.g, u)
                        endif
                        
                        if IsUnitType(u, UNIT_TYPE_HERO) then
                            call Freeze.apply(u, durationHero(.l))
                        else
                            call Freeze.apply(u, durationNormal(.l))
                        endif
                        call UnitDamageTarget(.c, u, .dmg, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
                    endif
                endif
                call GroupRemoveUnit(t, u)
            endloop
            
            /* Create scaled sfx at target point */
            set d = CreateUnit(.p, DUMMY_ID, .x, .y, 0)
            call SetUnitScale(d, EXPLODE_SIZE, 1, 1)
            call DestroyEffect(AddSpecialEffectTarget(EXPLODE_SFX, d, "origin"))
            call UnitApplyTimedLife(d, 'BTLF', SFX_DECAY_TIME)
            
            static if DAMAGE_ONCE then
                call DestroyGroup(.g)
            endif
            
            call destroy()
            set d = null
            
            implement CTLEnd
            
            static method onCast takes nothing returns boolean
                
                local thistype this = create()
                local integer l
                local real xt
                local real yt
                local unit u
                local unit d
                
                set .c = GetTriggerUnit()
                set .p = GetTriggerPlayer()
                set .g = CreateGroup()
                
                set .x = GetUnitX(.c)
                set .y = GetUnitY(.c)
                set xt = GetSpellTargetX()
                set yt = GetSpellTargetY()
                
                set .l = GetUnitAbilityLevel(.c, SPELL_ID)
                set .r = getAngle(.x, .y, xt, yt)
                
                set .d = getDistance(.x, .y, xt, yt)
                if .d > distance(.l) then
                    set .d = distance(.l)
                endif
                
                set .dmg = damage(.l)
                set .a = aoe(.l)
                
                call GroupEnumUnitsInRange(t, .x, .y, .a, null)
                loop
                    set u = FirstOfGroup(t)
                    exitwhen u == null
                    
                    if UnitAlive(u) and filter(u, .p) then
                        if not IsUnitInGroup(u, .g) then
                            /* If only deal damage for once per unit*/
                            static if DAMAGE_ONCE then
                                call GroupAddUnit(.g, u)
                            endif
                            
                            if IsUnitType(u, UNIT_TYPE_HERO) then
                                call Freeze.apply(u, durationHero(.l))
                            else
                                call Freeze.apply(u, durationNormal(.l))
                            endif
                            call UnitDamageTarget(.c, u, .dmg, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
                        endif
                    endif
                    
                    call GroupRemoveUnit(t, u)
                endloop
                
                /* Create scaled sfx at cast point */
                set d = CreateUnit(.p, DUMMY_ID, .x, .y, 0)
                call SetUnitScale(d, EXPLODE_SIZE, 1, 1)
                call DestroyEffect(AddSpecialEffectTarget(EXPLODE_SFX, d, "origin"))
                call UnitApplyTimedLife(d, 'BTLF', SFX_DECAY_TIME)
                set d = null
                
                return false
            endmethod
            
            static if not LIBRARY_SpellEffectEvent then
                private static method check takes nothing returns boolean
                    if GetSpellAbilityId() == SPELL_ID then
                        call thistype.onCast()
                    endif
                    return false
                endmethod
            endif
            
            static method onInit takes nothing returns nothing

                local trigger t
                
                static if LIBRARY_SpellEffectEvent then
                    call RegisterSpellEffectEvent(SPELL_ID, function thistype.onCast)
                else
                    set t = CreateTrigger()
                    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                    call TriggerAddCondition(t, Condition(function thistype.check))
                endif
                
            endmethod
        endstruct
    endscope
    
    scope Hailstorm
        
        /*private struct Hailstorm extends array
        
            static method onInit takes nothing returns nothing

                local trigger t
                
                static if LIBRARY_SpellEffectEvent then
                    call RegisterSpellEffectEvent(data.SPELL_ID, function thistype.onCast)
                else
                    set t = CreateTrigger()
                    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                    call TriggerAddCondition(t, Condition(function thistype.check))
                endif
                
            endmethod
            
        endstruct*/
        
    endscope
    
endscope
Still too lazy to work on the ultimate ability, it's gonna be quite complicated :(

IsTerrainWalkable isn't my resource, so no need to credit me.

And I was serious about my hero being similar - I'm also making an alliance ranger.
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,501
EDIT:
Have just read the whole main post. Honestly, I never agreed with public poll. Not all users are able to give "precise" review and opinion, some will only vote based on their first impression. Just like me when voted at the past zephyr contest, Be My Angle by Bannar is the first entry I tried. And I'm quite impressed with it, and vote for him instantly without checking any other entries. Then after Dat-C3 asked me, have I tried his entry, I just answered yes whereas I haven't \o/
Then after that, I started to check every entry out :'D I'm not sure though, guess it's just me.

But I'm glad trigger/code gives a great score :D
No, it's not just you. No offense, but the behavior you described is exactly the kind of thing I want to stamp out for future Contests (this one included). Worry not; measures are being taken.

For one, the 'weight' of the Poll results (relative to the Judging) is the lowest I've seen at the Hive (25%), and I don't think it should go any higher. Moreover, like the Modeling Contest #25 I hosted, we will be removing any Votes that don't conform to the requirements (specifically "did you bother to test more than 1 hero" and "did you have something to say about your vote & the other entries").
For three, I'm actually studying up on various voting methods; I'm currently trying to figure out how to implement either Borda Count or the Schulze Method. Both of these offer "preferential" voting rather than stock "first-past-the-post" voting, where Voters will rank the Entrants in order of preference.

A big possible problem of this contest is that people might think with DotA mind and not with melee mind. That means, low duration of negative buffs, focusing on damage and ultimates which deal damage (if you look well to most of the ultimates of melee heroes, they are either summoning an ultimate monster or an AoE non-damaging spell)
With that being said, I'm afraid some people might go off-course and forget that this hero should be made for melee game, not for an AoS or Hero Arena
That is exactly what I have aimed to avoid in this Contest; past Contests did a poor job of indicating which was being made (seemingly accepting anything, from Melee to AoS to Hero Arena to TD...), and I feel that went a long way towards making those previous Contests fundamentally flawed (basically, "comparing apples to oranges"; see my posts on the Techtree Contest Submission thread for more of this).

So that in mind, do you feel the First Post of this Contest doesn't do an adequate job of getting this across? It's splashed all over the Rules & Guidelines. Moreover, we have tons of active posters on the thread who are auto-correcting each other when they see issues of that nature.

That's not to say I don't think AoS-style Heroes don't have a place; I'd love to see someone set up a Contest of that sort. I don't personally prefer them, so I'll keep suggesting, submitting (and if necessary) Hosting these kind.

~~

On a side note, I've done some mildly extensive documentation on this matter, actually, and I'm glad to see you pointing it out. I'll argue that while not too many (~9 out of 24) Hero Ultimates deal DD/DoT in an AoE either primarily or secondarily, that is actually a pretty common route to take (in one form or another); "Summons" make up only ~6(7) out of 24 by comparison.

A warlock for the horde; does it fit or not? WC3 Horde is more on shamanism.
Unfortunately, probably not. Then again, that's just my two cents; we're not going to dictate matters of "Theme" so much; but expect to suffer in the Judging, plausibly.

Balance has very little to do with durations, cooldowns, and costs when it comes to design. You could easily make a wc3 hero with 3 passives and an autocast ability and make it balanced wrt the rest of wc3.

Don't make the mistake of producing a bad design just because you think it might feel more like a wc3 hero. On the other extreme, there are many pitfalls related to hero design between rts and moba genres.
I would argue otherwise. Balance, if defined as "winning & losing roughly the same amount of matches/match-ups", has a lot to do with durations, cooldowns, and (mana?) costs. Imagine if Bash or Storm Bolt's stuns lasted for a full minute? Or if the Infernal could be summoned every 5 seconds? Or if Mana Burn costed 10 mana? Definitely problematic.

I suppose it's possible (a Hero with 3 passives & an autocast (heck, the Tauren Chieftain has an astounding 2 passives, one of them even being his Ultimate!))... But I'd be really surprised to see that work. That strikes me as a Hero designed with a lot more passive-gameplay (no pun intended) in mind (or alternatively, one with tons of Macro & very little Micro; perhaps a TD or Hero Arena?), whereas true Melee involves a decent mix of both (strategy & tactics, macro & micro, etc).

Cokemonkey11 said:
@kyrbi0: ... Looking back at the formal rules (which I didn't read before since rules are usually the same and I don't have time to analyze a wall of text), there are many issues.
Ooook... Well I tried to do a good job of warning people that "times change" (lol), but regardless... I'd really like to know where I have failed in communicating. I tried to strike a balance between the "bare essentials" to ensure a good, fair, fun Contest & providing reasonable explanations & examples in places. I also re-worked the Criteria to be more sensical (<- not a word but you get what I mean).

Cokemonkey11 said:
I've decided to just produce a hero, and if it gets disqualified over some minutiae, I'll have to just live with it.
Well we're all glad to have another Contestant, though I wish I could address your despondent attitude. :< Don't worry, if there's some "minutiae" you end up stumbling across people are here to help & point it out.

Anyways Kyrbi0 is it okay if we resize models by Y/Z in Model Editor? The Scaling Native does not allow Y/Z. :(

Hero Change for the fifth time. Damn, reusing some ability titles. I didn't even bother starting the last hero because of uncomfortability with the model.

Mystic Wyvern
We're gonna have to say "no", unfortunately.

Using the "spirit wyvern" model? Not bad. : )

Well, here are my latest WIP's:
2w2rblk.jpg
2cfzl1u.png
2j3rv9k.png
34sj7gk.png
2qn458l.png


Ranger abilities:
Flaming Arrows, Cold Arrows, Swiftness Aura and Black Arrow. (All from alpha)

PS: Some icons such as swiftness aura, black arrow are temporary.
Ah, I'm glad to see someone using the Ranger; looking cool. Also, glad to see someone deriving inspiration from Beta (you're not alone... >:p)

I must admit, though, if your Flaming/Cold/Black Arrow abilities are the same (or even too similar) to what's already in the game, you'll really want to consider modifying/replacing them. No Hero has the abilities of any other Hero (aside from NE PotM & Warden sharing "Hide", but that doesn't count); besides, 3 Arrow abilities? She's essentially only able to use 1 ability at a time (plus the passive), making her a pretty boring Hero (aside from the tactical choice of "which arrow to use in which situation").

Also, while the Beta Ranger skin is in use (& I believe appropriately (I hope)), I don't seem to recall the fitting Beta Ranger Icon being in the game. If it's not in the MPQs & you had to import it, that's unfortunately not Kosher.

Still thinking about any sheep-related spells I can use for my Arcanists' ultimate.
Hrm...
Mass Polymorph
Sheep-Ball (Bomb) (i.e. Katamari Damacy-style :p)
Homing Flying Sheep (i.e. Magic Missile-style)
Mega-Sheep
Summon Arcane Ovine (i.e. Infernal-style massive death sheep)
Wooly Destruction

Wait, do you need "names" or "mechanics"?

I guess my idea isn't very original after all =/

My hero:
Blessed Ranger

Abilities:
Arcane Arrows, Forrestwalk, Holy Sigil, Pure Dexterity

more to come later :3
Noice. I really wanted to do a Ranger hero (that & Garithos), so I'm glad to see someone handling it.

Also, there's no problem with a few people using the same model; that lets us more easily compare between the two for implementation! I personally like the sound of yours a lot, though it's a little... off ("Arcane" arrows, but a Druidic "Forestwalk", coupled with a Divine "Holy Sigil"?? "Pure Dexterity" sounds interesting, but also a little lackluster. Maybe pick thematic "source of magick" (Arcane, Nature, Divine, etc) & just rename the other abilities.

Ok, another WiP of his ulti in action. All his abilities are finished and I think he's finally balanced. Not much I know SFX wise but it's still useful.
Very cool! Glad to see more WIPs, and glad to see someone using Garithos; I really wanted to use him as well. :p

Of course, I'll be honest; you don't even show us the tooltip. With so much going on on the screen, there's no way to tell what that spell does. :< I respect keeping secrets, though (it's sorta what I'm doing... :p).
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
I would argue otherwise. Balance, if defined as "winning & losing roughly the same amount of matches/match-ups", has a lot to do with durations, cooldowns, and (mana?) costs. Imagine if Bash or Storm Bolt's stuns lasted for a full minute? Or if the Infernal could be summoned every 5 seconds? Or if Mana Burn costed 10 mana? Definitely problematic.

Balancing a set of skills requires adjusting variables like durations and mana costs, but producing a balanced hero design is something different.

I suppose it's possible (a Hero with 3 passives & an autocast (heck, the Tauren Chieftain has an astounding 2 passives, one of them even being his Ultimate!))... But I'd be really surprised to see that work. That strikes me as a Hero designed with a lot more passive-gameplay (no pun intended) in mind (or alternatively, one with tons of Macro & very little Micro; perhaps a TD or Hero Arena?), whereas true Melee involves a decent mix of both (strategy & tactics, macro & micro, etc).

Passive abilities don't necessarily correspond with passive gameplay
 
Level 5
Joined
Oct 10, 2012
Messages
109
Still have this idea and already making some of this spells

Shadow
Cunning hero, specializing in confusing enemy with illusion.

Shadow Blade
Slow the enemy and summon one illusion of Shadow to attack the enemy. Shadow Blade Illusion have Shadow Dodge ability.

Shadow Dodge
When Shadow attacked there is a 5/10/15% chance to summon an illusion of Shadow. Shadow Dodge illusions have Shadow Dodge Ability but only 2/4/6% and Shadow Grace ability but only 1/2/3% (i still think to remove this ability for its Shadow illusions). When Shadow has low health 100/125/150 hp and Shadow still have 100/80/60 mana then he will turn invisible. (still balancing this turning invisible thing i think i use it a lot to cheat death)

Shadow Grace
Give shadow a chance to do a critical strike or evade (still cant decide only one or both) and give him a chance to parry enemy attack with fan of knives 3/6/9% deal 50 damage up to 7?? nearby enemies.

Illusion Dance
Create 2 (or 3?) illusions of Shadow that have all Shadow abilities and deal 100% damage but receive 300% damage

Maybe you can give me some critics or comment how to balance this hero or improve it?
 
You should expand your vocabulary, use more words for darkness than 'shadow'.

The names should also be worked on. Try something like... Lan Blackrend, or something along those lines. Try looking at other ingame heroes and take a look at their names.

The kit overall seems kind of... Off, or stale. Why not diversify his spells? Like for one of his spells, you could set it up so that your hero turns invisible, and summons an identical clone, that explodes if an enemy comes near it, slowing them. Your shadows shouldn't all be simple clones.
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
Probably asked before but:

Can we modify vanila icons borders? As in add a passive variant of an active existing icon or vice versa.

There is a tool that does this in about 5 seconds so it isn't a unfair advantage and it's still resources available to all (wc3 icons).
 
Level 17
Joined
Jul 17, 2011
Messages
1,864
i think thats the idea becuz the hero's name is shadow


well here is what i currently have:

Hero Goblin War Engeneer

Cunning hero adept at offensive abilities as well as defending locations, augmenting troops and controlling the flow of battles. Can learn Machine Gun Turret, Goblin Support Station(Turret)

Attacks land and air units.

208257-albums5313-picture88699.jpg


so far only 2 abilities:

208257-albums5313-picture88697.jpg


This is not finished but the idea is that the hero creates a turret which attacks enemies. The turret becomes stronger with each level and the

hero's ultimate passively upgrades it even more allowing it to always target the unit with the least hp in its range. The ultimate also increases

its attack speed if cast on it.


208257-albums5313-picture88696.jpg


this ability allows the hero to create a support building that helps nearby friendly troops. At first it will only heal them for a small amount but

later will also provide armor (this will most likely be changed...) and finally absorb some of the damage nearby units take, making them take

less damage. If the turret is about to die from the damage it will stop absorbing and only provide the other abilities. The turret can be

healed. The hero's ultimate will also passively increase the radius of the damage absorbtion aura and when cast on the turret will make it

absorb 80% of all damage nearby units take and give it a lot of hp regen.




third skill will probly just increase duration of these buildings
 
Level 21
Joined
Nov 4, 2013
Messages
2,017
Still have this idea and already making some of this spells

Shadow
Cunning hero, specializing in confusing enemy with illusion.

Shadow Blade
Slow the enemy and summon one illusion of Shadow to attack the enemy. Shadow Blade Illusion have Shadow Dodge ability.

Shadow Dodge
When Shadow attacked there is a 5/10/15% chance to summon an illusion of Shadow. Shadow Dodge illusions have Shadow Dodge Ability but only 2/4/6% and Shadow Grace ability but only 1/2/3% (i still think to remove this ability for its Shadow illusions). When Shadow has low health 100/125/150 hp and Shadow still have 100/80/60 mana then he will turn invisible. (still balancing this turning invisible thing i think i use it a lot to cheat death)

Shadow Grace
Give shadow a chance to do a critical strike or evade (still cant decide only one or both) and give him a chance to parry enemy attack with fan of knives 3/6/9% deal 50 damage up to 7?? nearby enemies.

Illusion Dance
Create 2 (or 3?) illusions of Shadow that have all Shadow abilities and deal 100% damage but receive 300% damage

Maybe you can give me some critics or comment how to balance this hero or improve it?

What a shadowy hero! Maybe you can make an ability with my name :wink:
 
Level 25
Joined
Jul 30, 2013
Messages
2,678
Nah, will be doing an ancient hero instead, NE is full of NE heroes already, so I decided. Who will lead the beasts who allies the NE? I thought, KotG? Maybe, but I will choose to make a Wildmaster(or Wild Master if I could decide), like the Beastmaster but completely different and uses the Corrupted Ancient of War model.
 
Status
Not open for further replies.
Top