Unit Move API
Script Type : JASS
Requires :
Code and description :
An example could be downloaded here, or from attachment below.
===============================================
Reminder for self :
- return timer thing, which probably much faster.
- Cache the GetTriggeringTrigger() etc.
- Reduce unused calculations and conversion. (bj_DEGTORAD)
- Replace the StringHash with traditional integer.
- Library form.
Script Type : JASS
Requires :
JASS:
globals
hashtable udg_SkillTable = InitHashtable()
real udg_updateSpeed = 0.04 //Default value
endglobals
Code and description :
JASS:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//
//
// Move Unit API
//
// by SECTION
//
// Requires :
// udg_SkillTable : Hashtable
// udg_updateSpeed: real
//
// What API?
//
// This API is used to make a unit moves via trigger, which is Linear or Circular.
//
// What features/benefits?
//
// See that some functions returned trigger?
// This is used for controlling the movement. You can manipulate a unit's movement which is moving
// via included functions, so you could increase or decrease its speed, change its destination, and
// even stop or force done the movement.
//
// Also, because of return trigger, you could attach one or more values to it via Hashtable so
// you may transport some values from any trigger to next another trigger.
//
// What bug/leak?
//
// I have tested some and it did well, although the use of the function is a bit "difficult".
// But it still works well and fast. I still don't see any leak or memory inefficient.
// If you might see some unusefulness of function, please report it.
//
// What for?
//
// You could use this system for :
// - Missile
// - Dash
// - Some spell mechanics
//
//
// What's next?
//
// If you have something to say (lets say it... a bug? new feature? some requests? or.. signature? XD)
// Just post your comment here, or e-mail those things to [email][email protected][/email]
// Prior signature >_<
//
//
// Here is the list of function that could be used :
//
//
////////////trigger MoveUnitXY( unit wUnit, real speed, real X, real Y, trigger exec )
//
// This trigger will move wUnit to target X,Y which travels speed units per second.
// After wUnit arrives at destination point, trigger exec will be executed.
// wUnit : Specifies which unit is being to be moved.
// speed : Specifies how fast the moving will be. (in units)
// X : Specifies where the X coordinate of destination point.
// Y : Specifies where the Y coordinate of destination point.
// exec : Specifies what trigger will be run after the movement is done.
// Returns a trigger, which is the control of the movement.
//
////////////trigger MoveUnitToUnit( unit wUnit, real speed, unit wTarget, trigger exec )
//
// This trigger will move wUnit to target wTarget which travels speed units per second.
// wUnit : Specifies which unit is being to be moved.
// speed : Specifies how fast the moving will be. (in units)
// wTarget : Specifies which unit is to be the destination target.
// exec : Specifies what trigger will be run after the movement is done.
// Returns a trigger, which is the control of the movement.
//
////////////trigger MoveUnitCircular( unit wUnit, real degreeSpeed, real radius, real X, real Y, real degreeInit )
//
// This trigger will make wUnit rotates toward X,Y, which rotates degreeSpeed angle per second, rotates in
// a radius distance of pivot point, and will start moving from angle of degreeInit.
// wUnit : Specifies which unit is being to be moved.
// degreeSpeed : Specifies the angle of rotation movement size per second (in degrees)
// X,Y : Specifies the target X, Y of pivot point of rotation.
// degreeInit : Specifies the initial angle of unit position towards pivot point.
// Returns a trigger, which is the control of the movement.
//
//////////trigger MoveUnitCircularUnit( unit wUnit, real degreeSpeed, real radius, unit wTarget, real degreeInit )
//
// This trigger will make wUnit rotates toward wTarget unit, which rotates degreeSpeed angle per second,
// rotates in a radius distance of pivot point, and will start moving from angle of degreeInit.
// wUnit : Specifies which unit is being to be moved.
// degreeSpeed : Specifies the angle of rotation movement size per second (in degrees)
// wTarget : Specifies the unit target of pivot point of rotation.
// degreeInit : Specifies the initial angle of unit position towards pivot point.
//
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
////////Control Functions
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//
//
// Control functions are used for manipulate unit's movement, such as increase or decrease the speed,
// changes the destination, or many more.
// real XYDist(real X1, real Y1, real X2, real Y2)
// Function List :
//
//
////////////void StopMovingUnitXY( trigger t )
//
// This function will force stop the unit's movement.
// t : Specifies the trigger control.
//
////////////void UpdateMoveUnitSpeed( trigger t, real newSpeed)
//
// This function will modifies the unit's movement speed.
// t : Specifies the trigger control.
// newSpeed : Specifies the new speed of movement.
//
////////////void UpdateMoveUnitXY( trigger t, real newX, real newY )
//
// This function will modifies the destination point in X,Y.
// t : Specifies the trigger control.
// newX: Specifies the new X coordinate of destination point.
// newY: Specifies the new Y coordinate of destination point.
//
////////////void UpdateMoveUnitTarget ( trigger t, unit newTarget )
//
// This function will modifies the unit which is target of the movement.
// t : Specifies the trigger control.
// newTarget: Specifies the new target unit of movement.
//
////////////void UpdateMoveUnitRadius ( trigger t, real newRadius )
//
// This function will modifies the distance of circular movement.
// t : Specifies the trigger control.
// newRadius: Specifies the new distance of circular movement.
//
// NOTE: This function is specialized for Circular Movement.
//
////////////void UpdateMoveUnitDegreeSpeed ( trigger t, real newDegreeSpeed )
//
// This function will modifies the angle speed of circular movement.
// t : Specifies the trigger control.
// newDegreeSpeed: Specifies the new angle speed in degrees.
//
// NOTE: This function is specialized for Circular Movement.
//
////////////void UpdateMoveUnitDegreePosition ( trigger t, real newCurrentDegree )
//
// This function will forcely modifies the angle position of circular movement.
// t : Specifies the trigger control.
// newCurrentDegree: Specifies the new angle position in degrees.
//
// NOTE: This function is specialized for Circular Movement.
//
////////////void ForceExecute ( trigger t )
//
// This function will forcely execute the trigger exec of trigger control.
// t : Specifies the trigger control.
//
////////////unit GetMovingUnit( trigger t )
//
// This function will return the unit that specified in movement.
// t : Specifies the trigger control.
//
// This function will returns a unit.
//
////////////void SetUnitPosEx( unit wUnit, real moveSize, real tgtX, real tgtY )
//
// This function will instantly move (or set the new position) wUnit towards tgtX,tgtY location
// and moves moveSize units.
// wUnit : Specifies the unit that want to be moved.
// moveSize: Specifies the distance of movement in units.
// tgtX : Specifies the X coordinate of destination facing point.
// tgtY : Specifies the Y coordinate of destination facing point.
//
//
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//END OF DESCRIPTION
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//========================================================================
//========================================================================
//Control and Other Function
//========================================================================
//========================================================================
function ForceExecute takes trigger t returns nothing
call TriggerExecute(LoadTriggerHandle(udg_SkillTable, GetHandleId(t), StringHash("Exec") ))
endfunction
function GetMovingUnit takes trigger t returns unit
return LoadUnitHandle(udg_SkillTable, GetHandleId(t), StringHash("wUnit") )
endfunction
function XYDist takes real X1, real Y1, real X2, real Y2 returns real
local real dx = X2 - X1
local real dy = Y2 - Y1
return SquareRoot(dx * dx + dy * dy)
endfunction
function SetUnitPosEx takes unit wUnit, real moveSize, real tgtX, real tgtY returns nothing
local real getAngle = bj_RADTODEG * Atan2(tgtY - GetUnitY(wUnit), tgtX - GetUnitX(wUnit))
local real x = GetUnitX(wUnit) + moveSize * Cos(getAngle * bj_DEGTORAD)
local real y = GetUnitY(wUnit) + moveSize * Sin(getAngle * bj_DEGTORAD)
call SetUnitPosition(wUnit, x,y)
call SetUnitFacing(wUnit, getAngle)
endfunction
function StopMovingUnitXY takes trigger t returns nothing
call FlushChildHashtable(udg_SkillTable, GetHandleId(t) )
call DestroyTrigger(t)
endfunction
function UpdateMoveUnitSpeed takes trigger t, real newSpeed returns nothing
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("speed"), newSpeed)
endfunction
function UpdateMoveUnitXY takes trigger t, real newX, real newY returns nothing
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("X"), newX)
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("Y"), newY)
endfunction
function UpdateMoveUnitRadius takes trigger t, real newRadius returns nothing
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("radius"), newRadius)
endfunction
function UpdateMoveUnitDegreeSpeed takes trigger t, real newDegreeSpeed returns nothing
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("degreeSpeed"), newDegreeSpeed)
endfunction
function UpdateMoveUnitDegreePosition takes trigger t, real newCurrentDegree returns nothing
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("currentDegree"), newCurrentDegree)
endfunction
function UpdateMoveUnitTarget takes trigger t, unit newTarget returns nothing
call SaveUnitHandle(udg_SkillTable, GetHandleId(t), StringHash("wTarget"), newTarget)
endfunction
//========================================================================
//========================================================================
//Hardcore Action Function
//========================================================================
//========================================================================
function MoveProc takes nothing returns nothing
//Unpack the load
local unit wUnit = LoadUnitHandle (udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("wUnit") )
local real speed = LoadReal (udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("speed") )
local real X = LoadReal (udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("X") )
local real Y = LoadReal (udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("Y") )
local trigger exec= LoadTriggerHandle(udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("Exec") )
//Let's process the movement
//First, check if UnitX is bigger than target X (also Y), to determine the upside/downside.
//Oh, we can use XYDist!
call SetUnitPosEx( wUnit, speed * udg_updateSpeed, X, Y )
//Check!
if XYDist(GetUnitX(wUnit), GetUnitY(wUnit), X, Y ) <= speed * udg_updateSpeed then
//Finish touch here!
//Note that we can't create new listener. Therefore, we use Trigger!
//call ExecuteFunc(exec)
call SetUnitPosition(wUnit, X, Y)
call TriggerExecute(exec)
//Clean this mess and let it tingle
call StopMovingUnitXY(GetTriggeringTrigger())
call FlushChildHashtable(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ) )
endif
//Trying to Nullify the allocated pointer
//Because even pointer takes 4 byte for declaration, right?
set wUnit = null
set exec = null //don't destroy! it won't work...
endfunction
function MoveProcUnit takes nothing returns nothing
local unit wUnit = LoadUnitHandle (udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("wUnit") )
local real speed = LoadReal (udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("speed") )
local unit wTarget=LoadUnitHandle (udg_SkillTable, GetHandleId(GetTriggeringTrigger()),StringHash("wTarget"))
local trigger exec= LoadTriggerHandle(udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("Exec") )
call SetUnitPosEx( wUnit, speed * udg_updateSpeed, GetUnitX(wTarget), GetUnitY(wTarget) )
if XYDist(GetUnitX(wUnit), GetUnitY(wUnit), GetUnitX(wTarget), GetUnitY(wTarget) ) <= speed * udg_updateSpeed then
call SetUnitPosition(wUnit, GetUnitX(wTarget), GetUnitY(wTarget))
call TriggerExecute(exec)
call StopMovingUnitXY(GetTriggeringTrigger())
call FlushChildHashtable(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ) )
endif
set wUnit = null
set exec = null
endfunction
function MoveProcCircular takes nothing returns nothing
local real sourceX = LoadReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("X") )
local real sourceY = LoadReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("Y") )
local unit wUnit = LoadUnitHandle(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("wUnit") )
local real Angle = LoadReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("currentDegree") )
local real radius = LoadReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("radius") )
local real degreeSpeed = LoadReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("degreeSpeed") )
//
//
local real x = sourceX + radius * Cos((Angle + degreeSpeed) * bj_DEGTORAD)
local real y = sourceY + radius * Sin((Angle + degreeSpeed) * bj_DEGTORAD)
call SetUnitPosition(wUnit,x,y)
call SetUnitFacing(wUnit, ((RAbsBJ(degreeSpeed)/degreeSpeed) * 90) + Angle )
if (Angle) >= 360 then
set Angle = RAbsBJ(360 - Angle)
endif
call SaveReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("currentDegree"), Angle + degreeSpeed)
set wUnit = null
endfunction
function MoveProcCircularUnit takes nothing returns nothing
local unit target = LoadUnitHandle(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("wTarget") )
local unit wUnit = LoadUnitHandle(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("wUnit") )
local real Angle = LoadReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("currentDegree") )
local real radius = LoadReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("radius") )
local real degreeSpeed = LoadReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger() ), StringHash("degreeSpeed") )
local real x = GetUnitX(target) + radius * Cos((Angle + degreeSpeed) * bj_DEGTORAD)
local real y = GetUnitY(target) + radius * Sin((Angle + degreeSpeed) * bj_DEGTORAD)
call SetUnitPosition(wUnit,x,y)
call SetUnitFacing(wUnit, ((RAbsBJ(degreeSpeed)/degreeSpeed) * 90) + Angle )
if (Angle) >= 360 then
set Angle = RAbsBJ(360 - Angle)
endif
call SaveReal(udg_SkillTable, GetHandleId(GetTriggeringTrigger()), StringHash("currentDegree"), Angle + degreeSpeed)
set wUnit = null
endfunction
//========================================================================
//========================================================================
//Main Move Function
//========================================================================
//========================================================================
function MoveUnitXY takes unit wUnit, real speed, real X, real Y, trigger exec returns trigger
local trigger t = CreateTrigger()
//Packing before expanding
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("X"), X)
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("Y"), Y)
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("speed"), speed)
call SaveUnitHandle(udg_SkillTable, GetHandleId(t), StringHash("wUnit"), wUnit)
call SaveTriggerHandle( udg_SkillTable, GetHandleId(t), StringHash("Exec"), exec )
//Trigger Session
call TriggerRegisterTimerEvent(t, udg_updateSpeed, true)
call TriggerAddAction(t,function MoveProc)
//Return huff... w00t with return trigger? ooo...
return t
endfunction
function MoveUnitToUnit takes unit wUnit, real speed, unit wTarget, trigger exec returns trigger
local trigger t = CreateTrigger()
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("speed"), speed)
call SaveUnitHandle(udg_SkillTable, GetHandleId(t), StringHash("wUnit"), wUnit)
call SaveUnitHandle(udg_SkillTable, GetHandleId(t), StringHash("wTarget"), wTarget)
call SaveTriggerHandle( udg_SkillTable, GetHandleId(t), StringHash("Exec"), exec )
call TriggerRegisterTimerEvent(t, udg_updateSpeed, true)
call TriggerAddAction(t,function MoveProcUnit)
return t
endfunction
function MoveUnitCircular takes unit wUnit, real degreeSpeed, real radius, real X, real Y, real degreeInit returns trigger
local trigger t = CreateTrigger()
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("degreeSpeed"), degreeSpeed)
call SaveUnitHandle(udg_SkillTable, GetHandleId(t), StringHash("wUnit"), wUnit)
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("X"), X)
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("Y"), Y)
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("radius"), radius)
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("degreeInit"), degreeInit)
call TriggerRegisterTimerEvent(t, udg_updateSpeed, true)
call TriggerAddAction(t, function MoveProcCircular)
//Init Position
call SetUnitPosition(wUnit, X + radius * Cos(degreeInit * bj_DEGTORAD) , Y + radius * Sin(degreeInit * bj_DEGTORAD) )
return t
endfunction
function MoveUnitCircularUnit takes unit wUnit, real degreeSpeed, real radius, unit wTarget, real degreeInit returns trigger
local trigger t = CreateTrigger()
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("degreeSpeed"), degreeSpeed)
call SaveUnitHandle(udg_SkillTable, GetHandleId(t), StringHash("wUnit"), wUnit)
call SaveUnitHandle(udg_SkillTable, GetHandleId(t), StringHash("wTarget"), wTarget)
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("radius"), radius)
call SaveReal(udg_SkillTable, GetHandleId(t), StringHash("currentDegree"), degreeInit)
call TriggerRegisterTimerEvent(t, udg_updateSpeed, true)
call TriggerAddAction(t, function MoveProcCircularUnit)
call SetUnitPosition(wUnit, GetUnitX(wTarget) + radius * Cos(degreeInit * bj_DEGTORAD) , GetUnitY(wTarget) + radius * Sin(degreeInit * bj_DEGTORAD) )
return t
endfunction
An example could be downloaded here, or from attachment below.
===============================================
Reminder for self :
- return timer thing, which probably much faster.
- Cache the GetTriggeringTrigger() etc.
- Reduce unused calculations and conversion. (bj_DEGTORAD)
- Replace the StringHash with traditional integer.
- Library form.
Attachments
Last edited: