- Joined
- Dec 14, 2005
- Messages
- 10,532
I did this system a while ago for someone, and I guess I may as well post it, as such a thing seems to be in demand from time to time.
I haven't found any bugs with it, but that does not guarantee that there are none (if any could be reported, it would be appreciated).
Comments at the top of the code document how to use this system.
Also, if you guys could give some reviews for me to base my work on, it would be appreciated, because I'm not sure that anyone else does much moderating here at the moment, and approving one's own systems by one's own standards is a definite no.
I haven't found any bugs with it, but that does not guarantee that there are none (if any could be reported, it would be appreciated).
Comments at the top of the code document how to use this system.
Also, if you guys could give some reviews for me to base my work on, it would be appreciated, because I'm not sure that anyone else does much moderating here at the moment, and approving one's own systems by one's own standards is a definite no.
1.06
1.05
1.04
1.03
1.02
1.01
1.00
- Fixed a bug which caused attempted destruction of null structs.
- Fixed a bug with Push()
1.05
- SetLooping method for cleaner code
- OrderQueues now destroy orders by default when they are destroyed. This can be changed by a boolean flag on the struct.
1.04
- Naming tweaks, reversed queue direction
1.03
- Added static constant common OrderIds
1.02
- Lots of renaming
- SetUnitOrderQueue added, called automatically upon OrderQueue.create()
- Removed destruct in favor of destroy
- Pop() added
1.01
- Orders are now independent from OrderQueues
- Efficiency tweaks
- Constants for usability
- More powerful options
- Support for permanent orders and looping order sequences
1.00
- Initial release
JASS:
//*****************************************************************************
//* OrderQueue Library v1.06 *
//* By: PurplePoot *
//*****************************************************************************
//=============================================================================
//The first step in using this system is to make sure that every unit which
//is to have an order queue has an instance of the OrderQueue struct attached to them.
//You'll have to edit the GetUnitOrderQueue function so that it can retrieve
//things with your specific storage system.
//=============================================================================
//To handle orders, there are several options in OrderQueue.
//The Concat method concatenates a new order - it is added to the end of the queue.
//The Push method pushes the new order under the stack - it is added to the front.
//The Remove method allows you to remove an indefinite order from an indefinite
//position in the queue.
//The Pop method removes the front order from the queue and returns it.
//The PopLast method removes the back order from the queue and returns it.
//=============================================================================
//A queue may be turned on and off without destroying it via SetActive
//=============================================================================
//For efficiency or precision reasons, you may want to change the speed on the enum.
//This is listed in a constant in the globals section. (ENUM_TIMER_INTERVAL)
//=============================================================================
//There are some useful OrderID constants in Order.
//They are named ID_<ordername>
//Included are: ATTACK, ATTACKGROUND, ATTACKONCE, CANCEL, STOP,
//PATROL, HOLDPOSITION, MOVE, SMART
//=============================================================================
//If <Order>.looping is set to true, the order will be sent to the end of
//a Queue instead of even being removed completely, allowing for repeating
//sequences of orders. Alternatively, <Order>.SetLooping(boolean) may be used
//so as to allow cleaner code, ex oq.Push(Order.create(..).SetLooping(true))
//=============================================================================
//******SYSTEM STARTS******
library OrderQueue
globals
private timer tim = CreateTimer()
private group queuedUnits = CreateGroup()
private constant real ENUM_TIMER_INTERVAL = .25
endglobals
function GetUnitOrderQueue takes unit u returns OrderQueue
return GetUnitUserData(u)//return whatever way you store your order queue
endfunction
function SetUnitOrderQueue takes unit u, OrderQueue oq returns nothing
call SetUnitUserData(u,oq)//set whatever way you store your order queue
endfunction
private function CheckOrders_Child takes nothing returns nothing
local unit u = GetEnumUnit()
local OrderQueue dat = GetUnitOrderQueue(u)
if GetUnitCurrentOrder(u) == 0 and dat.last != 0 then
call dat.last.Issue(u)
if not dat.last.looping then
call dat.last.destroy()
else
call dat.Push(dat.Pop())
endif
endif
set u = null
endfunction
private function CheckOrders takes nothing returns nothing
call ForGroup(queuedUnits,function CheckOrders_Child)
endfunction
struct Order
static constant integer NO_TARGET = 0
static constant integer POINT_TARGET = 1
static constant integer WIDGET_TARGET = 2
static constant integer ID_MOVE = 851986
static constant integer ID_STOP = 851972
static constant integer ID_PATROL = 851990
static constant integer ID_SMART = 851971
static constant integer ID_HOLDPOSITION = 851993
static constant integer ID_CANCEL = 851976
static constant integer ID_ATTACK = 851983
static constant integer ID_ATTACKONCE = 851985
static constant integer ID_ATTACKGROUND = 851984
private integer orderType = Order.NO_TARGET
private integer orderId
private real x
private real y
private widget w
Order next = 0
Order prev = 0
OrderQueue queue = 0
boolean looping = false
static method createNoTarget takes integer orderId returns Order
local Order o = Order.allocate()
set o.orderId = orderId
return o
endmethod
static method createWidgetTarget takes integer orderId, widget target returns Order
local Order o = Order.allocate()
set o.orderId = orderId
set o.orderType = Order.WIDGET_TARGET
set o.w = target
debug if target == null then
debug call BJDebugMsg("Target is null!")
debug endif
return o
endmethod
static method createPointTarget takes integer orderId, real x, real y returns Order
local Order o = Order.allocate()
set o.orderId = orderId
set o.orderType = Order.POINT_TARGET
set o.x = x
set o.y = y
return o
endmethod
method Issue takes unit subject returns nothing
if this.orderType == Order.NO_TARGET then
call IssueImmediateOrderById(subject,this.orderId)
elseif this.orderType == Order.POINT_TARGET then
call IssuePointOrderById(subject,this.orderId,this.x,this.y)
elseif this.orderType == Order.WIDGET_TARGET then
call IssueTargetOrderById(subject,this.orderId,this.w)
debug else
debug call BJDebugMsg("Stop editing the system code!")
endif
endmethod
method SetLooping takes boolean looping returns Order
set this.looping = looping
return this
endmethod
method onDestroy takes nothing returns nothing
call this.queue.Remove(this)
endmethod
endstruct
struct OrderQueue
private unit holder
Order first = 0
Order last = 0
boolean active = false
boolean clean = true
method SetOwner takes unit owner, boolean activate returns OrderQueue
set this.holder = owner
call SetUnitOrderQueue(owner,this)
call this.SetActive(activate)
return this
endmethod
method Concat takes Order o returns nothing
set o.queue = this
if this.first == 0 then
set this.first = o
else
set this.last.next = o
set o.prev = this.last
endif
set this.last = o
endmethod
method Push takes Order o returns nothing
set o.queue = this
if this.first != 0 then
set o.next = this.first
set this.first.prev = o
endif
if this.last == 0 then
set this.last = o
endif
set this.first = o
set o.prev = 0
endmethod
method Remove takes Order o returns nothing
set o.queue = 0
if o.prev != 0 and o.next != 0 then
set o.prev.next = o.next
set o.next.prev = o.prev
elseif o.prev != 0 and o.next == 0 then
set o.prev.next = 0
elseif o.prev == 0 and o.next != 0 then
set o.next.prev = 0
endif
if o == this.first then
set this.first = o.next
endif
if o == this.last then
set this.last = o.prev
endif
endmethod
method PopLast takes nothing returns Order
local Order o = this.first
set this.first = o.next
set this.first.prev = 0
return o
endmethod
method Pop takes nothing returns Order
local Order o = this.last
set this.last = o.prev
set this.last.next = 0
return o
endmethod
method SetActive takes boolean activate returns nothing
set this.active = activate
if activate then
if FirstOfGroup(queuedUnits) == null then
call TimerStart(tim,ENUM_TIMER_INTERVAL,true,function CheckOrders)
endif
call GroupAddUnit(queuedUnits,this.holder)
else
call GroupRemoveUnit(queuedUnits,this.holder)
if FirstOfGroup(queuedUnits) == null then
call PauseTimer(tim)
endif
endif
endmethod
method onDestroy takes nothing returns nothing
if this.clean then
loop
exitwhen this.last == 0
call this.last.destroy()
endloop
endif
endmethod
endstruct
endlibrary
//******SYSTEM ENDS******
Last edited: