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

triggered slow

Status
Not open for further replies.
Level 12
Joined
Jan 2, 2016
Messages
973
Usually when I need a skill to apply "slow", I make a dummy, give it slow (the sorceresss spell) and I make the dummy cast the slow onto the target.
However, if I do all of the slows on my map based on the sorceress' slow - they wouldn't be stacking with eachother.

Is there a way to make a stacking slow?
And.. are there any other good 'slow' spells I can use?

And what about the function for setting the target's movespeed? Is it any good for making slowing skills? Some ideas how to use it efficiently (and making it MUI) will be apreciated :p

EDIT: Is that any good?
JASS:
    private function EndSpeedReduction takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local unit u = LoadUnitHandle(udg_Table, GetHandleId(t), 'unit' )
        local integer l = LoadInteger(udg_Table, GetHandleId(t), 'dplv' )
        call SetUnitMoveSpeed( u, GetUnitMoveSpeed(u)/(0.85-0.05*l))
        call FlushChildHashtable(udg_Table, GetHandleId(t))
        call DestroyTimer(t)
        set t = null
        set u = null
    endfunction


            set time = CreateTimer()
            call SetUnitMoveSpeed( u, GetUnitMoveSpeed(u)*(0.85-0.05*l))
            call SaveInteger(udg_Table, GetHandleId(time), 'dplv', l)
            call SaveUnitHandle(udg_Table, GetHandleId(time), 'unit', u )
            call TimerStart( time, 3.00, false, function EndSpeedReduction )
            set time = null
 
Fairly sure this has been done, but I cannot find it. I assume you would change the units movement speed and animation, but I'm not sure how you would change attack speed.

What about the function for setting the target's speed? There is a function to do this. Use it?

I don't see why you couldn't create the spell like any other GUI spell.

Unit casts slow.
reduce animation speed by x%
reduce movement speed by x%
reduce attack speed (still not sure how to do this without an OE ability)

Count the time. Reset unit.

Also if you do it this way, you can make it stack. Use dynamic indexing to make it MUI.

Some good slow spells are earthquake, orb of slow, slow poison, banish, frost nova, frost shield, .. and then the reverse spells (set increase to a negative), berserker, bloodlust, potion of speed, rune of speed, chemical rage, roaR, drums, unholy frenzy, unholy aura, and so on.

I guess you could probably use them to stack. For example you make a slow variable array. Slow[x]. and then set it to all of the slows that would work. For example Slow[1] = frost arrow. Slow[2] = Slow Poison, etc. Then index instances by target unit.
 
Level 12
Joined
Jan 2, 2016
Messages
973
Well, Legal_Ease, your suggestion isn't bad, but if I have 100 skills, each decreasing the speed by different amount - I'd need to make 500-600 abilities for all of the slows to be MUI...

I took my time and made a little library... What do you think? xP
EDIT: Improved the trigger a bit.
JASS:
library SpeedChange requires TimerFunctions
    
    globals
        constant real SpeedRefreshRate = 0.2
    endglobals

    private function EndSpeedModifying takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local unit u = LoadUnitHandle(udg_Table, GetHandleId(t), 'unit')
        call SetUnitMoveSpeed( u , GetUnitMoveSpeed(u) / LoadReal(udg_Table, GetHandleId(t), 'sped') )
        call RecTimer(t)
        set t = null
        set u = null
    endfunction
    
    private function PeriodicCheck takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer id = GetHandleId(t)
        local integer buff_id = LoadInteger(udg_Table, id, 'buff')
        local integer buff_ab = LoadInteger(udg_Table, id, 'babi')
        local unit u = LoadUnitHandle(udg_Table, id, 'unit')
        local real r = LoadReal(udg_Table, id, 'rtim') - SpeedRefreshRate
        if GetUnitAbilityLevel(u, buff_id) == 0 or r <= 0 then
            call SetUnitMoveSpeed( u , GetUnitMoveSpeed(u) / LoadReal(udg_Table, id, 'sped') )
            call UnitRemoveAbility( u , buff_ab )
            call RecTimer(t)
        else
            call SaveReal(udg_Table, id, 'rtim', r)
        endif
        set t = null
        set u = null
    endfunction
    
    function ChangeUnitSpeed takes unit u, real speed_modifier, real duration, integer buff_ability, integer buff_icon returns nothing
        local timer t = GetFreeTimer()
        local integer id = GetHandleId(t)
        call SetUnitMoveSpeed( u , GetUnitMoveSpeed(u) * speed_modifier )
        call SaveUnitHandle(udg_Table, id, 'unit', u )
        call SaveReal(udg_Table, id, 'sped', speed_modifier )
        if buff_ability != 0 then
            call UnitAddAbility( u , buff_ability )
            call SaveInteger(udg_Table, id, 'babi', buff_ability )
            call SaveInteger(udg_Table, id, 'buff', buff_icon)
            call SaveReal(udg_Table, id, 'rtim', duration )
            call TimerStart( t, SpeedRefreshRate, true, function PeriodicCheck )
        else
            call TimerStart( t, duration, false, function EndSpeedModifying )
        endif
        set t = null
        set u = null
    endfunction
    
endlibrary
 
Last edited:
Well, Legal_Ease, your suggestion isn't bad, but if I have 100 skills, each decreasing the speed by different amount - I'd need to make 500-600 abilities for all of the slows to be MUI...

I took my time and made a little library... What do you think? xP

Well ya, I agree, it doesn't sound like the best idea, but I'm not sure you would need so many abilities. 5-10 should do it. Each instance would be another ability. Instances would be checked by the unit.

But, regardless, I think you have something better here now. I always liked the fully triggered solution better anyway. I'm not great with Jass and I don't know hashtables, but it looks to me like you are indexing units and triggering the slow manually. How does it work? Have you tested it? Also, were you able to find a way to reduce the attack speed?
 
Level 12
Joined
Jan 2, 2016
Messages
973
Well, I had to edit it a bit for the "buff version" to work. I added a link to the library/resource version in my signature (tho I will expand the library with 2-3 more functions soon).
From my tests so far, it seems to work okay.

But no, changing their attack speed wasn't my objective in the 1-st place, so I haven't really looked for a way to do that xP
Otherwise I think I'd have to look at how it's done in the Bonus Mod and apply it to my system (but not planing to do that for now).
 
Level 7
Joined
Oct 19, 2015
Messages
286
The easiest way to solve this particular problem is to give the unit a modified tornado slow aura that only targets self for the duration of the buff. Other speed auras would work too but tornado slow aura has the advantage of not showing an icon on the command card. Multiple auras will stack if they use different buffs, even if they are all based on the same aura, so you can make any number of slow spells based on this approach.

As far as code goes, you just add the ability when spell is cast and start a timer for the duration of the buff. You need to attach the unit to the timer so you know which unit to remove the buff from when the timer expires, you also need to attach the timer to the unit so if the spell is recast on the unit during the buff duration you can restart the existing timer instead of creating a new one.
 
Level 12
Joined
Jan 2, 2016
Messages
973
Well, that's pretty much what my library is doing, with the difference that I don't need to make different abilities for different slow %s in the object editor, I just 'manually' slow units down.

At the moment the slow is hyperbolic - if the 1-st slow is for 50%, the 2-nd will be for 25% (75% total). I'll make more functions to have a linear version too. And I'll make 2 functions for a non-stacking, but refreshing version (always the same slow %, but the duration refreshes OR stacks up)
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
The easiest way to solve this particular problem is to give the unit a modified tornado slow aura that only targets self for the duration of the buff. Other speed auras would work too but tornado slow aura has the advantage of not showing an icon on the command card. Multiple auras will stack if they use different buffs, even if they are all based on the same aura, so you can make any number of slow spells based on this approach.

As far as code goes, you just add the ability when spell is cast and start a timer for the duration of the buff. You need to attach the unit to the timer so you know which unit to remove the buff from when the timer expires, you also need to attach the timer to the unit so if the spell is recast on the unit during the buff duration you can restart the existing timer instead of creating a new one.
Yes you can do that, but be aware that the tornado aura triggers a damage event with
a damage amount of 0. Just in case your DDS doesn't detect that seperate to normal damage events.
Of course only if you use damage detection at all.
 
Level 7
Joined
Oct 19, 2015
Messages
286
It can be avoided by using a different aura, but then you'd need to put it in a disabled spellbook in order to hide the icon on the command card, which is more trouble than making your damage detection system ignore 0.0 damage events (which it should do regardless).
 
Status
Not open for further replies.
Top