1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Choose your means of doom in the 17th Mini Mapping Contest Poll.
    Dismiss Notice
  3. A slave to two rhythms, the 22nd Terraining Contest is here.
    Dismiss Notice
  4. The heavens smile on the old faithful. The 16th Techtree Contest has begun.
    Dismiss Notice
  5. The die is cast - the 6th Melee Mapping Contest results have been announced. Onward to the Hive Cup!
    Dismiss Notice
  6. The glory of the 20th Icon Contest is yours for the taking!
    Dismiss Notice
  7. Shoot to thrill, play to kill. Sate your hunger with the 33rd Modeling Contest!
    Dismiss Notice
  8. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Shadow Leap v1.0.0.3

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


http://www.youtube.com/watch?v=7BQjyn8-VuU&feature=youtu.be

Code (vJASS):

/******************************************************************************************************
*  Shadow Leap v1.0.0.3
*  by Maker
*  
*  ~--------------------------------------------------~
*  ~ The caster leaps to the targeted point and then  ~
*  ~ on nearby enemy land units several times. The    ~
*  ~ target is randomized. In the end the hero leaps  ~
*  ~ to the point where he casted the spell. The hero ~
*  ~ gains 100% evasion and spell immunity.           ~
*  ~--------------------------------------------------~
*
*  Importing
*  ------------
*
*  ¤ Copy Shadow Leap, Evasion, Spell immunity and the spell book abilities into your map
*  ¤ Make sure the Evasion and Spell immunity abilities are in the spell book
*  ¤ Copy the spell trigger and the resources folder into your map
*  ¤ Set the AID and SBID variables in this spell, in globals to match the raw codes of
*    the abilities in your map. You can check raw codes by pressing Ctrl + D in object editor
*
*  Requirements
*  ------------
*  ShadowTrail by Maker
*   - http://www.hiveworkshop.com/forums/spells-569/shadow-trail-system-v1-1-1-7-a-230421/
*  Jump by Maker
*   - http://www.hiveworkshop.com/forums/spells-569/jump-system-v-1-0-1-4-a-230294/
*  CTL by Nestharus
*   - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-constant-timer-loop-32-a-201381/
*  Table by Bribe
*   - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*  IsTerrainWalkable by anitarf and Vexorian
*   - http://pastebin.com/0zjeaBc7
*  SimError by Vexorian
*   - http://www.wc3c.net/showthread.php?t=101260
*
*  Optional
*  -----------
*  GetUnitCollision by Nestharus
*   - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-getunitcollision-180495/
*  Knockback3D by Cokemonkey11
*   - http://www.hiveworkshop.com/forums/jass-resources-412/system-knockback3d-217056/
*  SpellEffectEvent by Bribe
*   - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/
*  RegisterPlayerUnitEvent by Magtheridon
*   - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
*  IsDestructableTree by PitzerMike
*   - http://www.wc3c.net/showthread.php?t=103927
*
*  Other
*  -----------
*  Icon:    BTNThunderClap by Mr.Goblin
*  Effect:  Dirt Explosion by WILLTHEALMIGHTY
*
******************************************************************************************************/



scope ShadowLeap

    globals
        // Effect for landing
        private constant string     EFFECT              ="war3mapImported\\NewDirtEXNofire.mdx"
        // Error message for invalid location
        private constant string     ERROR               = "Can't leap there."
        // The Shadow Leap ability
        private constant integer    AID                 = 'A000'
        // The Shadow Leap Spell Book ability
        private constant integer    SBID                = 'A003'
        // Order id for the ability
        private constant integer    OID                 = 852121
        // How many times the unit leaps
        private constant integer    LEAPS_BASE          = 3
        // How many times the unit leaps, bonus per lvl
        private constant integer    LEAPS_BONUS         = 1
        // Leap animation index for the caster
        private constant integer    ANIM_INDEX          = 12
        // Leap animation index for the dummies
        private constant integer    ANIM_INDEX_DUMMY    = 6
        // How quickly the shadow trail fades
        private constant integer    FADE_RATE           = 5
        // How often a new shadow unit is created
        private constant real       SHADOW_INTERVAL     = 0.06250
        // How much gravity affects the unit when leaping
        private constant real       GRAVITY             = 100
        // How fast the leap moves
        private constant real       SPEED               = 500
        // Max height of the leap
        private constant real       MAX_HEIGHT          = 350
        // Area of effect when the leap lands
        private constant real       AOE                 = 200
        // Minimum duration of the leap in seconds
        private constant real       MIN_DUR             = 0.4
        // How much the leap distance affects the duration, a multiplier
        private constant real       DISTANCE_FACTOR     = 0.1
        // How far the leaper detects new targets
        private constant real       LEAP_RANGE          = 500
        // The base damage of the spell
        private constant real       DMG_BASE            = 50.
        // Bonus damage per lvl, not applied at lvl 1
        private constant real       DMG_BONUS           = 35.
        // Knockback velocity
        private constant real       KB_VEL              = 650.
        // Does the ability destroy trees
        private constant boolean    CUT_TREES           = true
        // Does the ability knock back units
        private constant boolean    KNOCKBACK           = true
       
        private constant attacktype ATY                 = ATTACK_TYPE_NORMAL
        private constant damagetype DTY                 = DAMAGE_TYPE_NORMAL
        private constant weapontype WTY                 = WEAPON_TYPE_ROCK_HEAVY_BASH
       
        private group ENU = CreateGroup()
        private rect REC = Rect(0, 0, 0, 0)
        private Table TAB
    endglobals

    struct JumpingStomp extends array
   
        private real x          // X of where spell was casted first
        private real y          // Y of where spell was caster first
        private unit u          // The caster
        private unit l          // Last targeted unit
        private real dmg        // How much damage the leap does
        private integer leaps   // How many leaps are left
        private ShadowTrail st  // The shadow trail attached to the caster
       
        private static unit array un
        private static integer array rn
        private static integer ic = 0
   
        static if LIBRARY_IsDestructableTree and CUT_TREES then
        private static method DestructableFilter takes nothing returns boolean
            if IsDestructableTree(GetFilterDestructable()) then
                call KillDestructable(GetFilterDestructable())
            endif
            return false
        endmethod
        endif
       
        private method destroy takes nothing returns nothing
            call UnitRemoveAbility(this.u, SBID)
            set this.u = null
            set this.l = null
            call TAB.remove(GetHandleId(this.u))
            set rn[this] = rn[0]
            set rn[0] = this
        endmethod
   
        private static method onFinish takes nothing returns boolean
            local real x0
            local real y0
            local real x1
            local real y1
            local real time
            local unit t
            local player p
            local integer i
            local integer k
            local Jump j
            local ShadowTrail st
            local thistype this = TAB[GetHandleId(EVENT_JUMP_UNIT)]
           
            call this.st.remove() // Destroys the shadow trail
           
            if not (IsUnitType(EVENT_JUMP_UNIT, UNIT_TYPE_DEAD) or GetUnitTypeId(EVENT_JUMP_UNIT) == 0) then
                set x0 = GetUnitX(EVENT_JUMP_UNIT)
                set y0 = GetUnitY(EVENT_JUMP_UNIT)
                call DestroyEffect(AddSpecialEffect(EFFECT, x0, y0))
                static if LIBRARY_IsDestructableTree and CUT_TREES then
                    call SetRect(REC, x0-AOE, y0-AOE, x0+AOE, y0+AOE)
                    call EnumDestructablesInRect(REC, function thistype.DestructableFilter, null)
                endif
                set p = GetOwningPlayer(this.u)
                call GroupEnumUnitsInRange(ENU, x0, y0, LEAP_RANGE, null)
               
                set i = -1  // Counts valid targets
                loop
                    set t = FirstOfGroup(ENU)
                    exitwhen t == null
                    if  not             (                                /*
                    */
 IsUnitType      (t, UNIT_TYPE_STRUCTURE)    or   /*
                    */
 IsUnitType      (t, UNIT_TYPE_DEAD)         or   /*
                    */
 IsUnitType      (t, UNIT_TYPE_FLYING)       or   /*
                    */
 IsUnitHidden    (t)                         )    /*
                    */
 and IsUnitEnemy (t, p)                      then
                   
                        /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~/
                        /~  This block puts valid targets in to an array ~/
                        /~  and counts how many there are. This is done  ~/
                        /~  to randomize the next target                 */

                        if this.leaps > 0 then
                            set i = i + 1
                            set un[i] = t
                        endif
                        /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
                       
                        if IsUnitInRange(EVENT_JUMP_UNIT, t, AOE) then
                            call UnitDamageTarget(this.u, t, this.dmg, true, false, ATY, DTY, WTY)
                            static if LIBRARY_Knockback3D and KNOCKBACK then
                                call print("kb", 5)
                                call Knockback3D_add(t, KB_VEL, Atan2(GetUnitY(t)-y0, GetUnitX(t)-x0), 0)
                            endif
                        endif
                    endif
                    call GroupRemoveUnit(ENU, t)
                endloop
               
                if this.leaps > 0 then
                    set st = ShadowTrail.add(this.u, TRAIL_TYPE_STATIC, 0)
                    call st.setInterval(SHADOW_INTERVAL)
                    call st.setColor(150, 150, 150, 150)
                    call st.setAnimationIndex(ANIM_INDEX_DUMMY)
                    call st.setFadeRate(FADE_RATE, true)
                    call st.setPlayerColor(ConvertPlayerColor(15))
                    set this.st = st
                   
                    call SetUnitAnimationByIndex(this.u, ANIM_INDEX)
                   
                    set this.leaps = this.leaps - 1
                   
                    // Get new random target if there are leaps left
                    // and there is a valid target nearby
                    if this.leaps != 0 and i != -1 then
                        // Randomize a unit from the array of valid targets
                        set k = GetRandomInt(0, i)
                        // If the randomized target is the same unit that
                        // was targeted for the last jump and there is at
                        // least one other valid target, randomize new target
                        if un[k] == this.l and i > 0 then
                            set un[k] = un[i]
                            set this.l = un[GetRandomInt(0, i-1)]
                        else
                            set this.l = un[k]
                        endif
                        set x1 = GetUnitX(this.l)
                        set y1 = GetUnitY(this.l)
                    else
                        set x1 = this.x
                        set y1 = this.y
                        set this.leaps = 0
                    endif
                   
                    call SetUnitFacing(u, Atan2(y1-y0, x1-x0)*bj_RADTODEG)
                    set time = MIN_DUR + DISTANCE_FACTOR * SquareRoot( (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) ) / SPEED
                    set j = Jump.start(u, x1, y1, MAX_HEIGHT, time, GRAVITY)
                    call j.setUnitCollisionHeight(0)
                    call j.setDestructableCollisionDistance(0)
                else
                    call IssueImmediateOrderById(this.u, 851972) // Stop
                    call this.destroy()
                endif
            else
                call this.destroy()
            endif
            return false
        endmethod
       
        private static method create takes nothing returns thistype
            local Jump j
            local unit u = GetTriggerUnit()
            local real x0 = GetUnitX(u)
            local real y0 = GetUnitY(u)
            local real x1 = GetSpellTargetX()
            local real y1 = GetSpellTargetY()
            local real time = MIN_DUR + DISTANCE_FACTOR * SquareRoot( (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) ) / SPEED
            local ShadowTrail st
           
            local thistype this = rn[0]
            if this == 0 then
                set ic = ic + 1
                set this = ic
            else
                set rn[0] = rn[this]
            endif
           
            /* --------- Static Shadow Trail ---------- */
            set st = ShadowTrail.add(u, TRAIL_TYPE_STATIC, 0)
            call st.setInterval(SHADOW_INTERVAL)
            call st.setColor(150, 150, 150, 150)
            call st.setAnimationIndex(ANIM_INDEX_DUMMY)
            call st.setFadeRate(FADE_RATE, true)
            call st.setPlayerColor(ConvertPlayerColor(15))
            /* ---------------------------------------- */
           
            set this.u = u
            set this.x = x0
            set this.y = y0
            set this.st = st
            set this.leaps = (GetUnitAbilityLevel(u, AID) - 1)*LEAPS_BONUS + LEAPS_BASE
            set this.dmg = (GetUnitAbilityLevel(u, AID) - 1)*DMG_BONUS + DMG_BASE
           
            set TAB[GetHandleId(u)] = this
            call UnitAddAbility(u, SBID)
            set j = Jump.start(u, x1, y1, MAX_HEIGHT, time, GRAVITY)
            call j.setUnitCollisionHeight(0)
            call j.setDestructableCollisionDistance(0)
           
            set u = null
            return this
        endmethod
       
        private static method onOrder takes nothing returns boolean
            if GetIssuedOrderId() == OID and not IsPointJumpable(GetOrderPointX(), GetOrderPointY()) then
                call PauseUnit(GetTriggerUnit(), true)
                call IssueImmediateOrderById(GetTriggerUnit(), 851972)
                call PauseUnit(GetTriggerUnit(), false)
                call SimError(GetTriggerPlayer(), ERROR)
            endif
            return false
        endmethod
       
        static if not LIBRARY_SpellEffectEvent then
        private static method castCondition takes nothing returns boolean
            if GetSpellAbilityId() == AID then
                call thistype.create()
            endif
            return false
        endmethod
        endif
       
        private static method onInit takes nothing returns nothing
            local integer i
            local trigger t = CreateTrigger()
            call TriggerRegisterVariableEvent(t, "EVENT_JUMP_FINISH", EQUAL, 1)
            call TriggerAddCondition(t, function thistype.onFinish)
           
            static if LIBRARY_RegisterPlayerUnitEvent then
                call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, function thistype.onOrder)
            else
                set t = CreateTrigger()
                call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
                call TriggerAddCondition(t, function thistype.onOrder)
            endif
           
            static if LIBRARY_SpellEffectEvent then
                call RegisterSpellEffectEvent(AID, function thistype.create)
            else
                set t = CreateTrigger()
                call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                call TriggerAddCondition(t, function thistype.castCondition)
            endif
           
            set TAB = Table.create()
           
            set i = 0
            loop
                call SetPlayerAbilityAvailable(Player(i), SBID, false)
                exitwhen i == 15
                set i = i + 1
            endloop
        endmethod
    endstruct
endscope
 


Change log

v1.0.0.0 uploaded @ 04.06.2013
v1.0.0.1 uploaded @ 05.06.2013
-Destroys the instance if the caster dies during the spell
v1.0.0.2 uploaded @ 08.06.2013
-Small code improvements
-The caster no longer keeps the ability order after finishing the spell
-Some previously required libraries are now optional
v1.0.0.3 uploaded @ 09.11.2013
-No longer checks unit type id of targets
-Knckback was not applied ever, fixed
-Added a boolean to enable/disable knockback


Keywords:
leap, jump, shadow, maker, stomp
Contents

Shadow Leap v1.0.0.3 (Map)

Reviews
Moderator
20:58, 7th Jun 2013 PurgeandFire: All changes made. Approved! :) A great spell with wonderful effects. Plus, it makes all the necessary checks for playable maps!
  1. 20:58, 7th Jun 2013
    PurgeandFire: All changes made. Approved! :) A great spell with wonderful effects. Plus, it makes all the necessary checks for playable maps!
     
  2. EmoBrother

    EmoBrother

    Joined:
    Dec 15, 2012
    Messages:
    559
    Resources:
    0
    Resources:
    0
    Seems awesome :thumbs_up:
    Will the last jump(back to the point where the caster casted the spell) do damage ? (effect created but no sound ? I watched it from your video :p)
     
  3. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    Yes, it deals damage also :)
     
  4. EmoBrother

    EmoBrother

    Joined:
    Dec 15, 2012
    Messages:
    559
    Resources:
    0
    Resources:
    0
    Hmmm, your spells just like Jass course, teach me the Jass....... >.<
    I should call you "Jass Teacher" exactly.
     
  5. HammerFist132

    HammerFist132

    Joined:
    Mar 22, 2012
    Messages:
    1,317
    Resources:
    17
    Models:
    11
    Icons:
    2
    Maps:
    2
    Spells:
    2
    Resources:
    17
    Hey maker really nice looking. Is it possible to edit it so he jumps only once and then come back?(how hard will be I dont know jass)
     
  6. Lambdadelta

    Lambdadelta

    Joined:
    Jul 6, 2009
    Messages:
    721
    Resources:
    1
    Maps:
    1
    Resources:
    1
    LOL. That looks awesome.
     
  7. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    Sorry, but I'm not available for teaching.

    Thanks. Edit these
    Code (vJASS):
            // How many times the unit leaps
            private constant integer    LEAPS_BASE          = 3
            // How many times the unit leaps, bonus per lvl
            private constant integer    LEAPS_BONUS         = 1


    Set base to 1 and bonus to 0, then it should jump only once.

    Thanks.
     
  8. Chaosy

    Chaosy

    Tutorial Reviewer

    Joined:
    Jun 9, 2011
    Messages:
    11,041
    Resources:
    18
    Icons:
    1
    Maps:
    1
    Spells:
    10
    Tutorials:
    6
    Resources:
    18
    great looking spell 5/5 :eek:
    However the dust remains for quie a long time I think that should be reduced if possible
     
  9. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    Yeah, it does. A different effect could be used.
     
  10. Losam

    Losam

    Joined:
    Mar 27, 2011
    Messages:
    258
    Resources:
    8
    Spells:
    8
    Resources:
    8
    What program you used to shoot the screen?
     
  11. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    I took the screenshots with Print Screen button and recorded the video with Fraps.
     
  12. Kaizer

    Kaizer

    Joined:
    May 12, 2012
    Messages:
    618
    Resources:
    0
    Resources:
    0
    and then I was like
    This is Spartaaaa!!!!
    [​IMG]


    awesome spell maker, pretty wild :grin:

    one question, does the caster becomes vulnerable when he slams the ground? because "while leaping" :ogre_icwydt:
     
  13. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    :)

    It has the evasion and spell immunity from the very start of the first leap to the very end of the last leap, the whole time.
     
  14. Almia

    Almia

    Joined:
    Apr 24, 2012
    Messages:
    4,842
    Resources:
    35
    Spells:
    30
    Tutorials:
    4
    JASS:
    1
    Resources:
    35
  15. EmoBrother

    EmoBrother

    Joined:
    Dec 15, 2012
    Messages:
    559
    Resources:
    0
    Resources:
    0
    You misunderstood, I meant I learn many things from you :3 :ogre_hurrhurr:
     
  16. defskull

    defskull

    Joined:
    Mar 27, 2008
    Messages:
    7,978
    Resources:
    17
    Spells:
    17
    Resources:
    17
    What happens if the unit dies during the spell ?
    I know you gain magic immunity and 100% evasion but still, what happen if the unit dies ?
     
  17. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    @Almia, thanks.
    @Xian, alright then :)
    @defskull, the current jump will finish, but I forgot to destroy the instance if the unit is dead. Updated now. Thanks.
     
  18. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,429
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    This has really awesome effects. :) Fun to cast too.

    Review:
    • After the spell is over, the unit is still under the order of the ability and his animation is paused. It seems that you issue the stop order, but perhaps you should try issuing the order by it's ID instead. (
      851972
      )
    • SpellEffectEvent
      and
      RegisterPlayerUnitEvent
      should probably be optional requirements since there are already quite a few requirements. Just use
      static if LIBRARY_SpellEffectEvent then
      or whatever the syntax is.
    • In
      static method create
      :
      GetPlayerColor(Player(15))
      is equivalent to
      ConvertPlayerColor(15)
      . Same thing for
      static method onFinish
      .
    • In
      static method create
      : Use u in
      ShadowTrail.add
      instead of
      GetTriggerUnit()
    • In
      static method onFinish
      : You can inline
      local player p
      since you only use it once.
    • In
      static method onFinish
      : This:
      Code (vJASS):
      set x1 = GetUnitX(t)
      set y1 = GetUnitY(t)
      if (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) <= AOE2 then

      Can be reduced to:
      Code (vJASS):
      if IsUnitInRange(EVENT_JUMP_UNIT, t, AOE) then

      And you'll also be able to eliminate the variable
      AOE2
      .
      For the line with the knockback 3D, just change y1 and x1 to GetUnitX/Y(t)
    • In
      static method onFinish
      : You don't seem to use the variable
      f
      .

    One those changes are made it will be approved. Great job with this, it is a great spell and I admire the conditions you check (whether it is flying, hidden, etc.) which make this very portable. :)
     
  19. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    Many thanks for the review, Purge. Updated.

    Comments

    Ordering by id did the trick. I was so blind not seeing the order being still on because I did give the "stop" order, and thought that would do the trick.

    Done, IsDestructableTree is now also optional.

    Done.

    Didn't change this, the p might be used multiple times, once per unit inside the AoE.