- Joined
- Jan 11, 2009
- Messages
- 3,414
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:
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.
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.