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

[vJASS] BonusSpeed

So, I was making a map and was using MoveSpeedX so that I can make slows, hastes, and speed bonuses with it.The problem is whenever I modify the speed, I don't get the expected value and so it bugs.

This is the solution i have made:

JASS:
library BonusSpeed/*v1.1
*************************************************************************************
*
*   For handling movespeed bonus values much better
*
*************************************************************************************
*
*   */ requires /*
*
*       */ UnitIndexerGUI /* hiveworkshop.com/forums/spells-569/gui-unit-indexer-1-2-0-2-a-197329
*       */ MoveSpeedXGUI /* hiveworkshop.com/forums/spells-569/movespeedx-gui-v1-1-0-0-a-207607/
*
*************************************************************************************
*
*   API
*
*       function UnitAddMoveSpeed takes unit u, real value, boolean flat, boolean current returns nothing
*           - adds speed value to unit.
*           - "flat" determines whether or not the added value is a flat value or a scale.
*               - if false, "value" must not be less than 0.0
*           - "current" calculates the new value.
*               - if true, the scaled bonus will be multiplied to the sum of default 
*                 speed and flat bonus
*               - if false, the scaled bonus will be multiplied to the default speed, 
*                 then the product will be added to the flat bonus.
*
*       function UnitRemoveMoveSpeed takes unit u, real value, boolean flat, boolean current returns nothing
*           - removes speed value.
*       
*       function UnitGetMoveSpeed takes unit u returns real
*           - Gets the current move speed of the unit.
*
*       function UnitGetBonusSpeed takes unit u returns real
*           - gets the bonus speed the unit has.
*
*************************************************************************************
*
*   Credits
*       Bribe
*       PurgeandFire
*
**************************************************************************************/
    private module Init
        private static method onInit takes nothing returns nothing
            call init()
        endmethod
    endmodule
    
    struct BonusSpeed extends array
        private real flatBonus
        private real scaleBonus
        private real defspeed
        private real cspeed
        private method newSpeed takes unit u, boolean current returns nothing
            if current then
                set cspeed = (defspeed + flatBonus)*scaleBonus
            else
                set cspeed = defspeed*scaleBonus + flatBonus
            endif
            
            call SetUnitMoveSpeed(u, cspeed)
        endmethod
        
        static method add takes unit u, real value, boolean flat, boolean current returns nothing
            local thistype this = GetUnitUserData(u)
            if flat then
                set flatBonus = flatBonus + value
            else
                set scaleBonus = scaleBonus * (1 + value)
            endif
            call newSpeed(u, current)
        endmethod
        
        static method remove takes unit u, real value, boolean flat, boolean current returns nothing
            local thistype this = GetUnitUserData(u)
            if flat then
                set flatBonus = flatBonus - value
            else
                set scaleBonus = scaleBonus/(1 + value)
            endif
            call newSpeed(u, current)
        endmethod
        
        static method getCurrentSpeed takes unit u returns real
            return thistype(GetUnitUserData(u)).cspeed
        endmethod
        
        static method getBonus takes unit u returns real
            local thistype this = GetUnitUserData(u)
            return cspeed - defspeed
        endmethod
        
        private static method onDeindex takes nothing returns nothing
            local thistype this = udg_UDex
            set flatBonus = 0
            set scaleBonus = 0
            set defspeed = 0
        endmethod
        
        private static method onIndex takes nothing returns nothing
            local thistype this = GetIndexedUnitId()
            set flatBonus = 0
            set scaleBonus = 1.0
            set defspeed = GetUnitDefaultMoveSpeed(GetIndexedUnit())
            set cspeed = defspeed
        endmethod
        
        private static method init takes nothing returns nothing
            call OnUnitIndex(function thistype.onIndex)
            call OnUnitDeindex(function thistype.onDeindex)
        endmethod
        
        implement Init
    endstruct
    
    function UnitAddMoveSpeed takes unit u, real value, boolean flat, boolean current returns nothing
        call BonusSpeed.add(u, value, flat, current)
    endfunction
    
    function UnitRemoveMoveSpeed takes unit u, real value, boolean flat, boolean current returns nothing
        call BonusSpeed.remove(u, value, flat, current)
    endfunction
    
    function UnitGetMoveSpeed takes unit u returns real
        return BonusSpeed.getCurrentSpeed(u)
    endfunction
    
    function UnitGetBonusSpeed takes unit u returns real
        return BonusSpeed.getBonus(u)
    endfunction
    
endlibrary

TimedSpeed (BonusSpeed extension)
JASS:
library TimedSpeed/*
*************************************************************************************
*
*   Adding timed movespeed bonuses to units
*
**************************************************************************************
*
*   */ uses /*
*
*       */ BonusSpeed /*
*       */ UnitIndexerGUI /*
*
*************************************************************************************
*
*   API
*   
*   struct TimedSpeed
*
*       static method haste takes unit tg, real bonus, boolean flat, boolean current, real time returns thistype
*           - increase the movespeed of the unit for a short duration
*
*       static method slow takes unit tg, real bonus, boolean flat, boolean current, real time returns thistype 
*           - decrease the movespeed of the unit for a short duration
*
*       static method accelerate takes unit tg, real bonus, boolean flat, boolean current, real time, boolean permanent returns thistype
*           - accelerate the movespeed of the unit from it's movespeed(current or base) to the given
*             bonus over time. if permanent is false, the bonus will be removed after time ends.
*       
*       static method decelerate takes unit tg, real bonus, boolean flat, boolean current, real time returns thistype
*           - decelerate the movespeed of the unit from it's movespeed(current or base) to the given
*             bonus over time. if permanent is false, the bonus will be removed after time ends.
*
*
*************************************************************************************/
    globals
        private constant real TIMEOUT = 0.03125
    endglobals
    
    struct TimedSpeed
        private unit u
        private real dur
        private real amount
        
        private boolean permanent
        private real growth
        
        private boolean flat
        private boolean current
        private boolean positive
        
        private static thistype array p
        private static thistype array n
        
        private static constant timer t = CreateTimer()
        
        method destroy takes nothing returns nothing
            set n[p[this]] = n[this]
            set p[n[this]] = p[this]
            
            if n[0] == 0 then
                call PauseTimer(t)
            endif
            if not permanent then
                if positive then
                    call UnitRemoveMoveSpeed(u, amount, flat, current)
                else
                    call UnitAddMoveSpeed(u, amount, flat, current)
                endif
            endif
            set u = null
            set dur = 0
            set amount = 0
            set growth = 0
            set flat = false
            set current = false
            
            call deallocate()
        endmethod
        
        private static method pr takes nothing returns nothing
            local thistype this = n[0]
            loop
                exitwhen 0 == this
                if dur > 0 and UnitAlive(u) then
                    if growth > 0 then
                        if positive then
                            call UnitRemoveMoveSpeed(u, amount, flat, current)
                        else
                            call UnitAddMoveSpeed(u, amount, flat, current)
                        endif
                        set amount = amount + growth
                        if positive then
                            call UnitAddMoveSpeed(u, amount, flat, current)
                        else
                            call UnitRemoveMoveSpeed(u, amount, flat, current)
                        endif
                    endif
                    
                    set dur = dur - TIMEOUT
                else
                    call destroy()
                endif
                set this = n[this]
            endloop
        endmethod
        
        private method insert takes nothing returns nothing
            set n[this] = 0
            set p[this] = p[0]
            set n[p[0]] = this
            set p[0] = this
            
            if p[this] == 0 then
                call TimerStart(t, TIMEOUT, true, function thistype.pr)
            endif
        endmethod
        
        static method haste takes unit tg, real bonus, boolean flat, boolean current, real time returns thistype
            local thistype this = allocate()
            set u = tg
            set amount = bonus
            set this.flat = flat
            set this.current = current
            set this.permanent = false
            set dur = time
            set positive = true
            call UnitAddMoveSpeed(u, amount, flat, current)
            call insert()
            return this
        endmethod
        
        static method slow takes unit tg, real bonus, boolean flat, boolean current, real time returns thistype 
            local thistype this = allocate()
            set u = tg
            set amount = bonus
            set this.flat = flat
            set this.current = current
            set this.permanent = false
            set dur = time
            set positive = false
            call UnitRemoveMoveSpeed(u, amount, flat, current)
            call insert()
            return this
        endmethod
        
        static method accelerate takes unit tg, real bonus, boolean flat, boolean current, real time, boolean permanent returns thistype
            local thistype this = allocate()
            set u = tg
            set growth = (bonus/time)*TIMEOUT
            set amount = 0
            set this.flat = flat
            set this.current = current
            set this.permanent = permanent
            set dur = time
            set positive = true
            call insert()
            return this
        endmethod
        
        static method decelerate takes unit tg, real bonus, boolean flat, boolean current, real time, boolean permanent returns thistype
            local thistype this = allocate()
            set u = tg
            set growth = (bonus/time)*TIMEOUT
            set amount = 0
            set this.flat = flat
            set this.current = current
            set this.permanent = permanent
            set dur = time
            set positive = false
            call insert()
            return this
        endmethod
    endstruct
endlibrary

will add test map soon, after I finished the package for this resource :)
 

Attachments

  • MoveSpeed.w3x
    26.9 KB · Views: 75
Last edited:
Sorry I can't follow this description "For handling movespeed bonus values much better" when using PnF's system.

Could you elaborate in detail what PnF fails to handle and why you made this? It represents a wrapper snippet around PnF's code for more comfort?

This also irritates me:
The problem is whenever I modify the speed, I don't get the expected value and so it bugs.
Please update the thread and clarify things. :)

This is could be part of MoveSpeedX, tho IDK what Purge will say.
Is there still a goal you to collaborate with purge? What did he say?
 
Top