• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Unit acceleration in warcraft?

Status
Not open for further replies.
I'm trying to make a system to have units accelerate towards their maximum speed once they have been ordered to move. The max acceleration and acceleration rate will be stored in a struct variable.

My problem is that i'm having a hard time figuring out how to integrate it with an existing system already in the map, the Unit Acceleration System by Diehard@Azeroth:

JASS:
library Acceleration initializer Init
    
    globals
        private timer t = CreateTimer()
        private group accelUnits = CreateGroup()
        private location Zloc = Location(0.,0.)
        private integer maxAccel = 0
        private constant real checkDist = 10. 
        private timer d = CreateTimer()
        private constant group dragGroup = CreateGroup()
        private integer maxDrag = 0
        private hashtable ht = InitHashtable()
        private boolexpr kbBoolexpr
        private unit draggedUnit = null
        private unit tempFilter = null
        private boolexpr True
        private rect r = null
        private constant real DEGTORAD = 3.14159/180
        
        // CONFIGURABLES
        
        private constant real NoDrag = 5. //maximum difference in Z that cannot cause any drag, basically, the higher this value is, the lower
        // a terrain infront of the unit will be needed to drag the unit down, and vice versa. Values less than 0 wont work.
        
        private constant real dragIteration = 0.03 // drag timer periodic iteration
        private constant real tIteration = 0.45 // timer periodic iteration
        
        private constant real gravity = -12.21 // gravity's real value, make it lower to lower the acceleration/deacceleration change
        // END CONFIGURABLES
        
        private constant real dragGravity = gravity*dragIteration*-1
        private DN dat
    endglobals
    
    
    private function GetLocZ takes real x, real y returns real
        call MoveLocation(Zloc, x, y)
        return GetLocationZ(Zloc)
    endfunction
    
    private function returnTrue takes nothing returns boolean
        return true
    endfunction
    
    private function returnBoolean takes nothing returns boolean
        set tempFilter = GetFilterUnit()
        return GetUnitFlyHeight(tempFilter) <= 25 and IsUnit(tempFilter, draggedUnit) == false
    endfunction
    
    struct DN // Destructable detection
    integer dN = 0

        private static method returnValue takes nothing returns nothing
            set dat.dN = dat.dN + 1
        endmethod
    
        static method DestructablesNearby takes real x, real y returns boolean
            set dat = DN.allocate()
            set r = Rect(x-100, y-100, x+100, y+100)
            call EnumDestructablesInRect(r, True, function DN.returnValue)
            call RemoveRect(r)
            if dat.dN > 0 then
                return true
            else
                return false
            endif
        endmethod
    
    endstruct
    
    private function UnitsNearby takes real x, real y, unit dragged returns boolean
        local group nGroup = CreateGroup()
        local unit n
        set draggedUnit = dragged
        call GroupEnumUnitsInRange(nGroup, x, y, 60, kbBoolexpr)
        set n = FirstOfGroup(nGroup)
        call DestroyGroup(nGroup)
        set nGroup = null
        set draggedUnit = null
        if n == null then
            return false
        else
            set n = null
            return true
        endif
    endfunction
    
    private function coreDrag takes nothing returns nothing
        local unit e = GetEnumUnit()
        local integer i = GetHandleId(e)
        local real a = LoadReal(ht, i, 2)
        local real x = GetUnitX(e)
        local real y = GetUnitY(e)
        local real x2 = x+checkDist*Cos(a)
        local real y2 = y+checkDist*Sin(a)
        local real diffZ = GetLocZ(x2,y2)-GetLocZ(x,y)
        local real drag = LoadReal(ht, i, 1)
        local real x3 = x+drag*Cos(a)
        local real y3 = y+drag*Sin(a)
        if diffZ < -NoDrag and UnitsNearby(x2, y2, e) == false and DN.DestructablesNearby(x2, y2) == false and IsTerrainPathable(x3,y3, PATHING_TYPE_WALKABILITY) == false then
            set drag = drag + dragGravity
            call SaveReal(ht, i, 1, drag)
            call SetUnitX(e, x3)
            call SetUnitY(e, y3)
        else
            call GroupRemoveUnit(dragGroup, e)
            call SaveBoolean(ht, i, 0, false)
            set maxDrag = maxDrag - 1
            if maxDrag == 0 then
                call PauseTimer(d)
            endif
        endif
        set e = null
    endfunction
    
    private function DragUnits takes nothing returns nothing
        call ForGroup(dragGroup, function coreDrag)
    endfunction
    
    private function coreAccel takes nothing returns nothing
        local unit e = GetEnumUnit()
        local integer i = GetHandleId(e)
        local real f = GetUnitFacing(e)*DEGTORAD
        local real x = GetUnitX(e)
        local real y = GetUnitY(e)
        local real x2 = x+checkDist*Cos(f)
        local real y2 = y+checkDist*Sin(f)
        local real defaultSpeed = GetUnitDefaultMoveSpeed(e)
        local real diffZ = GetLocZ(x2,y2)-GetLocZ(x,y)
        local real newSpeed = defaultSpeed+(gravity*diffZ)
        if diffZ < -NoDrag and IsTerrainPathable(x2,y2, PATHING_TYPE_WALKABILITY) == false then
            if LoadBoolean(ht, i, 0) == false then
                call SaveBoolean( ht, i, 0, true )
                call SaveReal( ht, i, 1, dragGravity )
                call SaveReal( ht, i, 2, f )
                set maxDrag = maxDrag + 1
                call GroupAddUnit(dragGroup, e)
                call TimerStart(d, dragIteration, true, function DragUnits)
            endif
        else
            if LoadBoolean( ht, i, 0 ) == false then
                call SetUnitMoveSpeed(e, newSpeed)
            else
                call SetUnitMoveSpeed(e, defaultSpeed)
            endif
        endif
        set e = null
    endfunction
    
    private function AccelerateUnits takes nothing returns nothing
        call ForGroup(accelUnits, function coreAccel)
    endfunction
    
    function AddUnitAcceleration takes unit u returns nothing
        if u == null then
            return
        endif
        call GroupAddUnit(accelUnits, u)
        set maxAccel = maxAccel + 1
        call TimerStart(t, tIteration, true, function AccelerateUnits)
    endfunction

    function RemoveUnitAcceleration takes unit u returns nothing
        if u == null then
            return
        endif
        call GroupRemoveUnit(accelUnits, u)
        call SetUnitMoveSpeed( u, GetUnitDefaultMoveSpeed(u) )
        set maxAccel = maxAccel - 1
        if maxAccel == 0 then
            call PauseTimer(t)
        endif
    endfunction
    
    //-----------------------------------------------------------------
    private function Init takes nothing returns nothing
        set kbBoolexpr = Condition(function returnBoolean)
        set True = Condition(function returnTrue)
    endfunction
    
endlibrary

This system already uses a periodic timer like the one i need, and it also modifies the units speed based on the height difference of the terrain infront of it. I'd like this to include increasing/resetting a units acceleration.

To detect when a unit has stopped, i'm using the ability "carrion swarm" which is automatically casted to the target order point when a unit is ordered to move.

To me this sounds pretty simple, but everyone i talk to about it claims that it is very complicated and that there are many things that could go wrong.
Could anyone explain to me what it is that i have to do, and what i should do to make it efficient?

Thanks.
 
Well, i understand how his system works and where i should implement things, but i want to know the basics on how to create a system for acceleration.

My idea on it is to simply have one constant for acceleration rate, a counter for each time the timer loops, and a variable for deafult speed +max speed (by own means of propelling). I would then take deafult speed + acceleration speed*counter (if acceleration speed*counter < MaxSpeed) and use that instead of deafult speed in the elevation based acceleration system (the one i posted). I just get that feeling of "is it really just that simple?" though, and want to ask on what i need to make a system like this, and maybe an example on how it is done in other games.
 
Level 11
Joined
May 31, 2008
Messages
698
just use v = v0 + a*t
v = velocity
v0 = initial velocity (which would probably just be zero for this)
a = acceleration
t = time
every time the loop runs, set t = t + whatever the time interval is on the loop
Just be sure to set t = 0 whenever the unit comes to a stop.
 
Status
Not open for further replies.
Top