• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Wild Horde v1.3

  • Like
Reactions: IRoILaurentiu
Wild Horde by msongyyy

Spell Description:
Calls in a Horde of Wild kodos that charge into random locations around Rexxar. Kodos will knockback and deal damage upon contact with enemies. 1 Target per Kodo.

Creates 4/8/12 Kodos per second. Kodos will deal 30/40/50 initial contact damage and 10/15/20 damage per second during knockback.

Knockback lasts 1.00/1.30/1.60 second and pushes units over 125/150/175 distance.

Wild Horde lasts 6/8/10 seconds. Knockback effects stack.

Requires:
- RegisterPlayerUnitEvent + SpellEffectEvent (Magtheridon96, Bribe)
- JNGP 1.5e +
- TT by Cohadar
- Knockback system by KRICZ (which requires 4 other systems) - His system makes this spell so much better, so HUGE thanks to him

Changelog:
1.3 - Basically cleaned up more crap, now uses SpellEffectEvent/RegisterPlayerUnitEvent
1.2 - Took out unneeded bj_DEGTORAD, no longer pauses units, dead unit < .405 hp
1.1 - Movement of all kodos is tracked by one timer instead of each instancing creating a new one.
1.0 - Initial release
JASS:
scope WildHorde

I will continuously upgrade this spell.

/************************************************************************************/
/*                                                                                  */
/*                            Wild Horde v1.3                                       */
/*                                 by: msongyyy                                     */
/*                                                                                  */
/*   HOW TO IMPORT:                                                                 */
/*        1. Import all the triggers in Libraries and this Trigger                  */
/*        2. Import the 'Wild Horde Dummy' and 'Wild Horde' spell                   */
/*        3. Set ABIL_ID to the rawcode ID of Wild Horde spell                      */
/*        4. Set R_ID to the rawcode ID of Wild Horde Dummy unit                    */
/*        5. Change configurables to your liking                                    */
/*                                                                                  */
/*        ENJOY ^^                                                                  */
/*                                                                                  */
/*    THANKS TO:                                                                    */
/*        1. Cohadar for TT system and vJASS compiler                               */
/*        2. Bribe for SpellEffectEvent                                             */
/*        3. Magtheridon96 for RegisterPlayerUnitEvent                              */
/*        4. Vexorian for BoundSentinel system, GroupUtils, and vJASS compiler      */
/*        5. Kenny/Jesus4lyf for ListModule system                                  */
/*        6. Rising_Dusk for TerrainPathability system                              */
/*        7. KRICZ for Knockback system                                             */
/*        8. Everyone at hiveworkshop.com for their support and guidance            */
/*                                                                                  */
/*                                                                                  */
/************************************************************************************/

    globals
        private constant integer ABIL_ID = 'A000'                         // Rawcode ID of Wild Horde ability
        private constant integer R_ID = 'h000'                            // Rawcode ID of Wild Horde Dummy unit
        private constant string FX = "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl"
    endglobals
    
/************************************************************************************/
/*            START OF CONFIGURABLES                                                */
/************************************************************************************/
    globals
        private constant boolean KB_SM           = true                   // Does knockback stop unit from moving? (Sets unit prop window to 0.00)
        
        private constant real PERIOD             = .025                   // How often kodos move
        private constant real TOUCH_AOE          = 135.00                 // Distance required for a target to be hit by a kodo
        private constant real KODO_SPEED         = 350.  * PERIOD         // Speed of Kodos
        private constant real MAX_DIST           = 500.                   // Max distance traveled by kodos
        
        private constant attacktype ATTACK_TYPE     = ATTACK_TYPE_MAGIC
        private constant weapontype WEAPON_TYPE     = null
        private constant damagetype DAMAGE_TYPE     = DAMAGE_TYPE_NORMAL
        
        private constant integer KRED               = 155
        private constant integer KGREEN             = 155
        private constant integer KBLUE              = 155
        private constant integer TRANS              = 100
    endglobals       
    
    // Damage taken over knockback time
    private constant function KB_DMG takes integer i returns real              
        return i * 5.00 + 5.00     
    endfunction
    
    // Initial damage taken on knockback
    private constant function INIT_DMG takes integer i returns real          
        return i * 20. + 10.
    endfunction

    // Duration of knockback
    private constant function KB_DUR takes integer i returns real
        return i * .3 + .7
    endfunction
    
    // Distance knockedback
    private constant function KB_DIST takes integer i returns real 
        return i * 25.00 + 100.
    endfunction
    
    // Kodos summoned per second
    private constant function KPS takes integer i returns integer
        return i * 4
    endfunction
    
    // Duration of the spell
    private constant function DURA takes integer i returns integer
        return i * 2 + 4 
    endfunction
    
/************************************************************************************/
/*            END OF CONFIGURABLES                                                  */
/************************************************************************************/
    
    globals
        KnockbackType HordeKb
        
        private constant hashtable H    = InitHashtable()
        private constant timer TMR      = CreateTimer()
        
        private group g                 = CreateGroup()
        private unit fog
    endglobals
    
    
    private struct data2 extends array
        private unit caster
        private unit rhino
        private real ang
        private real dist
        private real x
        private real y
        private real kbDmg
        private real initDmg
        private real kbDur
        private real kbDist
        private player play
    
        private static integer array prev
        private static integer array next
        private static integer array rn
        private static integer ic = 0
        
        static method Move takes nothing returns nothing
            local thistype this = next[0]
            
            loop
                exitwhen this == 0
                
                if .dist >= 400 then
                    call RemoveUnit(.rhino)
                    set .caster = null
                    set .rhino = null
                    set .play = null
                    set prev[next[this]] = prev[this]
                    set next[prev[this]] = next[this]
                    set rn[this] = rn[0]
                    set rn[0] = this
                else
                    call SetUnitX(.rhino, GetUnitX(.rhino) + .x)
                    call SetUnitY(.rhino, GetUnitY(.rhino) + .y)
                    call GroupEnumUnitsInRange(g, GetUnitX(.rhino), GetUnitY(.rhino), TOUCH_AOE, null)
                    loop
                        set fog = FirstOfGroup(g)
                        if IsUnitEnemy(fog, .play) and GetUnitState(fog, UNIT_STATE_LIFE) > .405 then
                            set .dist = 400
                            call Knockback.create(.caster, fog, KB_DIST(GetUnitAbilityLevel(.caster, ABIL_ID)), KB_DUR(GetUnitAbilityLevel(.caster, ABIL_ID)),  Atan2(GetUnitY(fog) - GetUnitY(.rhino), GetUnitX(fog) - GetUnitX(.rhino)) * bj_RADTODEG, HordeKb)
                            call SaveReal(H, GetHandleId(fog), 0, GetUnitPropWindow(fog))
                        endif
                        exitwhen fog == null or IsUnitEnemy(fog, .play)
                        call GroupRemoveUnit(g, fog)
                    endloop
                    set .dist = .dist + KODO_SPEED
                endif
                
                set this = next[this]
                
                if next[0] == 0 then
                    call PauseTimer(TMR)
                endif
            endloop
        endmethod
                
        static method Start takes unit caster, unit rhino, real r returns nothing
            local thistype this = rn[0]
            
            if this == 0 then
                set ic = ic + 1
                set this = ic
            else
                set rn[0] = rn[this]
            endif
            
            set .caster = caster
            set .rhino = rhino
            set .play = GetOwningPlayer(caster)
            set .ang = r
            set .dist = 0.
            set .x = KODO_SPEED * Cos(ang)
            set .y = KODO_SPEED * Sin(ang)
            set .kbDmg = KB_DMG(GetUnitAbilityLevel(.caster, ABIL_ID))
            set .kbDur = KB_DUR(GetUnitAbilityLevel(.caster, ABIL_ID))
            set .initDmg = INIT_DMG(GetUnitAbilityLevel(.caster, ABIL_ID))
            set .kbDist = KB_DIST(GetUnitAbilityLevel(.caster, ABIL_ID))
            
            set prev[this] = prev[0]
            set next[this] = 0
            set next[prev[0]] = this
            set prev[0] = this
            
            if prev[this] == 0 then
                call TimerStart(TMR, PERIOD, true, function thistype.Move)
            endif
        endmethod
    endstruct
    
    // 
    private struct data extends array
        private unit caster
        private player play
        private integer count
        
        private static integer array prev
        private static integer array next
        private static integer array rn
        private static integer ic = 0
        
        static method Rhinos takes nothing returns boolean
            local thistype this = TT_GetData()
            local real rdist = GetRandomReal(250, 400) 
            local real rang = GetRandomReal(0, 360) * bj_DEGTORAD
            local real x = GetUnitX(.caster) + rdist * Cos(rang)
            local real y = GetUnitY(.caster) + rdist * Sin(rang)
            local unit rhino
                
            if .count == 0 then
                set .caster = null
                set .play = null
                set rn[this] = rn[0]
                set rn[0] = this
                return true
            else
                set .count = .count - 1
                set rang = GetRandomReal(0, 360) 
                set rhino = CreateUnit(.play, R_ID, x, y, rang * bj_RADTODEG)
                call data2.Start(.caster, rhino, rang)
                call SetUnitVertexColor(rhino, KRED, KGREEN, KBLUE, TRANS)
                call SetUnitAnimationByIndex(rhino, 7)
                set rhino = null
            endif
            
            return false
        endmethod
        
        static method Start takes nothing returns nothing   
            local thistype this = rn[0]
            
            if this == 0 then
                set ic = ic + 1
                set this = ic
            else
                set rn[0] = rn[this]
            endif
            
            set .caster = GetTriggerUnit()
            set .play = GetOwningPlayer(.caster)
            set .count = (KPS(GetUnitAbilityLevel(.caster, ABIL_ID))) * DURA(GetUnitAbilityLevel(.caster, ABIL_ID))
            
            call TT_StartEx(function thistype.Rhinos, this, 1./KPS(GetUnitAbilityLevel(.caster, ABIL_ID)))
        endmethod
        
        // Knockback Struct stuff
        //
        static method DamageLoop takes Knockback kb returns nothing
            call UnitDamageTarget(kb.caster, kb.target, KB_DMG(GetUnitAbilityLevel(kb.caster, ABIL_ID)) * Knockback_TIMER_INTERVAL, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, null)
        endmethod
        
        static method InitialDamage takes Knockback kb returns nothing
            call UnitDamageTarget(kb.caster, kb.target, INIT_DMG(GetUnitAbilityLevel(kb.caster, ABIL_ID)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
            call DestroyEffect(AddSpecialEffectTarget(FX, kb.target, "origin"))
            if KB_SM then
                call SetUnitPropWindow(kb.target, 0.00)
            endif
        endmethod
        
        static method EndResetUnit takes Knockback kb returns nothing
            call SetUnitPropWindow(kb.target, LoadReal(H, GetHandleId(kb.target), 0))
            call FlushChildHashtable(H, GetHandleId(kb.target))
        endmethod
        //
        
        // Init stuff
        //
        static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(ABIL_ID, function thistype.Start)
            
            set HordeKb = KnockbackType.create()
            set HordeKb.onLoopAction = DamageLoop
            set HordeKb.onStartAction = InitialDamage
            set HordeKb.onEndAction = EndResetUnit
        endmethod
        //
        
    endstruct
endscope

Keywords:
Wild, Horde, orc, charge, rampage, ownage, stomp, knockback, rexxar, kodos, stampede
Contents

Wild Horde v1.3 (Map)

Reviews
Wild Horde v1.2 | Reviewed by Maker | 2nd Oct 2013 APPROVED The ability works and it is MUI, it just needs a bit polishing You could use Spell Effect Event, make it optional You don't need a unit variable in Cond...

Moderator

M

Moderator


Wild Horde v1.2 | Reviewed by Maker | 2nd Oct 2013
APPROVED


126248-albums6177-picture66521.png


  • The ability works and it is MUI, it just needs a bit polishing
126248-albums6177-picture66523.png


  • You could use Spell Effect Event, make it optional
  • You don't need a unit variable in Cond
  • You do not properly reset prop window. Store it before setting
    it to 0
  • Attack/damage/weapon types could be configurable, so could the rhino speed
  • Store the speed * Cos(ang) value, also the sin so you do not calculate those
    over and over again
  • Instead of checking life, use IsUnitType(unit, UNIT_TYPE_DEAD)
  • if KB_SM == true then -> if KB_SM then
  • GetAtan is just a wrapper for Atan2. It offers nothing really
    so you could get rid of it
  • Units with Locust do not need invulnerability ability, Locust makes units immune to damage
  • Remove structures built and upgrades used from the dummy unit type
  • The ability could have a bit of follow through time so the casting animation
    has time to complete
  • The rhinos could fade in/out
  • There could be some cast sound
126248-albums6177-picture66524.png
  • Spell Effect Event
[tr]
 
Instead of taking a unit for your configuration functions, you could take an integer instead. Saves a lot of GetUnitAbilityLevel calls. Also, configuration functions can be constant functions.

GetAtan function is unneeded. Just use Atan2 directly.

For FirstOfGroup loops, use bj_lastCreatedGroup for the enumeration. Saves you from creating a group.

ATTACK_TYPE and DAMAGE_TYPE should be configurable.
 
Top