Spell Phantom Dash


WEHZ Helper
Reaction score
Phantom Dash
Created By: WolfieeifloW

Requires NewGen and TimerUtils
Optionally can use GTrigger

Spell editing, idea, and triggers were created by WolfieeifloW.

If you take the time to download / look at these, please at least leave a comment.
Don't forget to rate also (using the stars
) !

Screenshots serve no justice, try the spell out ingame.


Spell Description
Dash to a target point, dealing damage to all enemies hit. Leaves an image at each enemy behind to confuse opponents.
Level 1: 50 damage.
Level 2: 100 damage.
Level 3: 150 damage.
Level 4: 200 damage.
Cooldown: 20/18/16/14 seconds.

Spell Code
// +---------------------------------------------------+
// |          -=-=- Phantom Dash [v1.0] -=-=-          |
// |            -=-=- By WolfieeifloW -=-=-            |
// |        Requires JASS NewGen and TimerUtils        |
// |            Optionally can use GTrigger            |
// +---------------------------------------------------+
// |   Dash to a target point, dealing damage and      |
// |    creating an illusion for each enemy hit        |
// +---------------------------------------------------+
// |   -=-=- How To Implement -=-=-                    |
// |      1. Copy TimerUtils into your map             |
// |       b. Copy GTrigger into your map              |
// |      2. Copy this trigger into your map           |
// |      3. Copy the Phantom Dash, and Phantom Dash   |
// |          (Dummy) abilities into your map          |
// |      4. Make sure the 'Rawcodes' in the trigger   |
// |          match your codes in the Object Editor    |
// |      5. Customize the spell                       |
// |      6. Enjoy!                                    |
// +---------------------------------------------------+
// |   -=-=- Credits -=-=-                             |
// |      Credits are not needed, but appreciated      |
// |       Just don't claim this as yours              |
// +---------------------------------------------------+
// |   -=-=- Version History -=-=-                     |
// |      Version 1.0                                  |
// |       - Initial release                           |
// +---------------------------------------------------+

library PhantomDash initializer Init requires TimerUtils optional GTrigger

// +-----------------------------------+
// |      -=-=- MODIFY HERE -=-=-      |
// |      -=-=- MODIFY HERE -=-=-      |
// |      -=-=- MODIFY HERE -=-=-      |
// +-----------------------------------+
        private constant integer ABILITY_ID = 'PHAN' //Rawcode of the "Phantom Dash" ability
        private constant integer ILLUSION_ID = 'ILLU' //Rawcode of the "Phantom Dash (Dummy)" ability
        private constant integer DUMMY_ID = 'dUMM' //Rawcode of the dummy unit
        private constant integer ORDER_ID = 852274 //Order Id of the "Wand of Illusion" item
        private constant real SPEED = 1500. //Speed the unit moves at during the dash
        private constant real RADIUS = 125. //Radius the unit hits units in - Don't go below 100
        private constant string EFFECT = "Abilities\\Spells\\Items\\AIam\\AIamTarget.mdl"
        private constant string ATTACH = "origin"
        private constant string ANIMATION = "walk" //Animation to play during Phantom Dash
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MELEE //Attack Type of Phantom Dash
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL //Damage Type of Phantom Dash
        private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS //Weapon Type of Phantom Dash
    private function Damage takes integer level returns real
        return level * 50. //Damage that Phantom Dash deals
// +----------------------------------------------+
// |      -=-=- DO NOT TOUCH PAST HERE -=-=-      |
// |      -=-=- DO NOT TOUCH PAST HERE -=-=-      |
// |      -=-=- DO NOT TOUCH PAST HERE -=-=-      |
// +----------------------------------------------+    
    struct data
        unit caster
        real casterX
        real casterY
        real targetX
        real targetY
        real facing
        effect sfx
        group hit = CreateGroup()
        timer t
        method destroy takes nothing returns nothing
            call ReleaseTimer(.t)
            call GroupClear(.hit)
            call .deallocate()
        private constant integer HIT_RANGE = 50
        private constant real PERIOD = 0.03125
        private constant real DSPEED = SPEED * PERIOD
        private group GROUP = CreateGroup()
        private location loc
        private real x
        private real y
        private integer CurrentInstance
    private function Conditions takes nothing returns boolean
        local unit u = GetFilterUnit()
        local unit dummy
        local data d = CurrentInstance
        if IsUnitType(u, UNIT_TYPE_STRUCTURE) == false and GetWidgetLife(u) >= 0.405 and IsUnitEnemy(u, GetOwningPlayer(d.caster)) and IsUnitInGroup(u, d.hit) == false then
            call UnitDamageTarget(d.caster, u, Damage(GetUnitAbilityLevel(d.caster, ABILITY_ID)), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
            set dummy = CreateUnit(GetOwningPlayer(d.caster), DUMMY_ID, GetUnitX(u), GetUnitY(u), bj_UNIT_FACING)
            call UnitAddAbility(dummy, ILLUSION_ID)
            call SetUnitAbilityLevel(dummy, ILLUSION_ID, GetUnitAbilityLevel(d.caster, ABILITY_ID))
            call IssueTargetOrderById(dummy, ORDER_ID, d.caster)
            call UnitApplyTimedLife(dummy, 'BTLF', 1.)
            call GroupAddUnit(d.hit, u)
        set dummy = null
        set u = null
        return false
    private function Callback takes nothing returns nothing
        local data d = GetTimerData(GetExpiredTimer())
        set d.casterX = GetUnitX(d.caster)
        set d.casterY = GetUnitY(d.caster)
        set x = d.targetX - d.casterX
        set y = d.targetY - d.casterY
        if SquareRoot(x * x + y * y) >= HIT_RANGE then
            set d.facing = Atan2(d.targetY - d.casterY, d.targetX - d.casterX)
            set d.casterX = d.casterX + DSPEED * Cos(d.facing)
            set d.casterY = d.casterY + DSPEED * Sin(d.facing)
            call SetUnitX(d.caster, d.casterX)
            call SetUnitY(d.caster, d.casterY)
            set CurrentInstance = d
            call GroupEnumUnitsInRange(GROUP, GetUnitX(d.caster), GetUnitY(d.caster), RADIUS, Condition(function Conditions))
            call SetUnitAnimation(d.caster, "stand")
            call PauseUnit(d.caster, false)
            call DestroyEffect(d.sfx)
            call d.destroy()
    private function Actions takes nothing returns boolean
        local data d
        if GetSpellAbilityId() == ABILITY_ID then
            set d = data.create()
            set d.caster = GetTriggerUnit()
            set loc = GetSpellTargetLoc()
            set d.casterX = GetUnitX(d.caster)
            set d.casterY = GetUnitY(d.caster)
            set d.targetX = GetLocationX(loc)
            set d.targetY = GetLocationY(loc)
            set d.sfx = AddSpecialEffectTarget(EFFECT, d.caster, ATTACH)
            set d.t = NewTimer()
            call SetTimerData(d.t, d)
            call SetUnitAnimation(d.caster, ANIMATION)
            call PauseUnit(d.caster, true)
            call TimerStart(d.t, PERIOD, true, function Callback)
            set loc = null
        return false
    private function Init takes nothing returns nothing
        local trigger trig = CreateTrigger()
        static if(LIBRARY_GTrigger) then
            call TriggerAddCondition(GT_RegisterStartsEffectEvent(trig, ABILITY_ID), Condition(function Actions))
            call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(trig, Condition(function Actions))
        set trig = null

Test map included.
Constructive criticism is welcomed, flaming is not.
This spell will only be submitted to TH.net.
Do not redistribute or modify without permission.
Credits are not needed but are appreciated.
Just don't claim the spell as yours.

Hope you enjoy it!​

- Initial release



Forum User
Reaction score
[LJASS]private constant real RADIUS = 125. //Radius the unit hits units in - Don't go below 100[/LJASS]
Some explanation would be nice. I've seen your other thread, but a simple statement explaining why users shouldn't go below the 100 radius value is nice.

• You don't comment the EFFECT and ATTACH globals? I have no idea what effect it is for.
• Function Damage should be a constant function so it is inlineable.
• You are leaking groups. You are creating them on every spell cast, but you aren't destroying them - only clearing them. May I suggest you use GroupUtils or recycle them properly?
• You should make use of the create method that structs provide. That way, you can avoid the use of having to a local integer. Also, it's better encapsulation practice.
• In some patch, I can't remember, natives [LJASS]GetSpellTargetX[/LJASS] and [LJASS]GetSpellTargetY[/LJASS] were added. You should make use of them instead of using locations.
• Why are variables x and y not local to the Callback function? Any speed difference should be neglible. In addition, you're only using them within that function.
• In function Callback, that distance comparison line should square both sides of the equation, so you don't have to call a [LJASS]SquareRoot[/LJASS]. That is, it should be [LJASS](x * x + y * y) >= HIT_RANGE * HIT_RANGE[/LJASS] - However, [LJASS]HIT_RANGE * HIT_RANGE[/LJASS] should be a new constant variable.
• You should perform the GroupEnum call before you offset d.casterX. That way, you won't have to call GetUnitX and GetUnitY twice in that function. Alternatively, if you want the GroupEnum to be centered directly on the caster, store the caster's x into a variable.
• Pausing units for spells isn't recommended. What if another script unpauses it during operation?
• You have x and y as globals, but you don't have u or dummy in Conditions as a global? What is this. Pick one.
• You don't need to declare data d, just use CurrentInstance directly, saves a local integer declaration.
• The spell will adjust to the casting unit's ability level for stats (like damage). It should take the level at the time of casting as it's argument. Store level as a struct member, or store damage as a struct member.
• Speed and radius should also be configurable functions. Users may want leveling Phantom Dash to increase the movement speed.
• HIT_RANGE should be configurable. Users may make the Phantom Dash have a ranged effect once the dash is nearby. Consider all scenarios.
• Consider using Jesus4Lyf's DummyCaster. Don't create a dummy caster each time.

[DEL]I haven't actually tested your spell out, so I can't say anything on that.[/DEL]

EDIT: I have now tested the spell out. My comments are as follows:
• As a suggestion, you should trigger automatic selection of the hero on map initialization. This is for convenience
• The visual effects are not very well executed. I have considered that things are configurable - but I still wish to comment on what you have presented. The hero doesn't dash towards the targeted point as the spell tooltip says. What happens instead is the hero is simply being moved across in a straight line. It doesn't look like a dash at all. I mean, the hero even plays it's random stand animations during it's so called "dash". In addition, the attached effect does not last on the caster; the visual effect ends before the caster is done moving for slower speeds. Also, the "spell" animation the hero throws doesn't particularly look good too. If it's a Phantom Dash, why does the hero lift his arms up?
• Going back on a previous point, the pause mechanic of the spell is horrible! What if I wanted to cast something like Thunder Clap during that dash? I wouldn't be able to because of the pause from the code and the pause from Channel. In your ability in the Object Editor, "Data - Disable Other Abilities" is true, how come?
• Why are the illusions being summoned really far with lots of variation from the targets hit? I'm getting illusions spawned from all angles on the targets when the hero dashes through them. This is due to the "Stats - Area of Effect" field in the Wand of Illusion ability in the Object Editor. It's offsetting the illusions by that amount.
• The "Stats - Target Allowed" field in the Phantom Dash (Dummy) ability should be changed so that it can target all types of units. I broke Phantom Dash by making the caster invulnerable; no illusions were being made when I used Phantom Dash.
• My hero died when I cast Phantom Dash, but it kept moving. This looks weird, I suggest you stop the dash if the caster dies/is removed by other code. I don't know about if the hero is to be hidden with [LJASS]ShowUnit[/LJASS], it would look weird if upon showing it again, it was suddenly displaced from the point it was hidden.
• The ability tooltip could do with a bit more - the numerical stat values could be added, but I don't think it's too important.


You can change this now in User CP.
Reaction score
Where did you get this "•" ?? It's very nice for pointing things.

• Spell Effect is lost during movement, I meant you should kill it when your target reaches final point, the trails left from effect will only cover 500 wc3 meter units and not the whole distance. Find another more eye candy effect.
• Give more time to illusions as you can predict easily who is the real deal.
• On demo map give less hp to units, users like to kill creeps :D

• Don't initialize the kind of non-static struct members, you create about 8000 empty and useless and leakful groups now on map initialization.
Use "set local.hit = CreateGroup" on struct create method and use "call DestroyGroup(this.hit)" on destroy method
• Use onDestroy method omg to avoid any struct instance problem.


Well-Known Member
Reaction score
I like it! :D
I think its quite cool :thup:

But I did notice that it doesn't cast if you try to "shift+cast" (action queue).

But nice gj :)
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    Happy Sunday!
  • The Helper The Helper:
    I will be out of town until Sunday evening
  • The Helper The Helper:
    I am back! Did you miss me LOL
  • jonas jonas:
    where did you go?
  • The Helper The Helper:
    Jefferson TX on a Paranormal Investigation of a haunted bed and breakfast - I got some friends that are paranormal investigators and they have an RV and do YouTubes
  • The Helper The Helper:
    It was a lot of fun. The RV was bad ass
  • jonas jonas:
    That sounds like fun!
  • The Helper The Helper:
    it was a blast!
  • The Helper The Helper:
    I am going to post the Youtube of the investigation in the forums when it is ready
  • jonas jonas:
  • vypur85 vypur85:
    Sounds cool TH.
  • tom_mai78101 tom_mai78101:
    I was on a Legend of Zelda marathon...
  • tom_mai78101 tom_mai78101:
    Am still doing it now
  • jonas jonas:
    which one(s) are you playing?
  • jonas jonas:
    I played a little bit of the switch title two weeks ago and found it quite boring
  • The Helper The Helper:
    just got back from San Antonio this weekend had the best Buffalo Chicken Cheesesteak sandwhich in Universal City, TX - place was called Yous Guys freaking awesome! Hope everyone had a fantastic weekend!
  • The Helper The Helper:
    Happy Tuesday!
  • The Helper The Helper:
    We have been getting crazy numbers reported by the forum of people online the bots are going crazy on us I think it is AI training bots going at it at least that is what it looks like to me.
  • The Helper The Helper:
    Most legit traffic is tracked on multiple Analytics and we have Cloud Flare setup to block a ton of stuff but still there is large amount of bots that seem to escape detection and show up in the user list of the forum. I have been watching this bullshit for a year and still cannot figure it out it is drving me crazy lol.
  • Ghan Ghan:
    Beep boop
  • The Helper The Helper:
    hears robot sounds while 250 bots are on the forum lol
  • The Helper The Helper:
    Happy Saturday!
  • The Helper The Helper:
    and then it was Thursday...

    The Helper Discord

    Members online


    Hive Workshop NUON Dome World Editor Tutorials

    Network Sponsors

    Apex Steel Pipe - Buys and sells Steel Pipe.