- Joined
- Aug 3, 2008
- Messages
- 2,345
A simple script I wrote because I needed it in a spell, this simply provides a way of preventing specific orders. It also provides a CancelOrders function which can be used externally and simply clears any orders the unit has, and works in response to SpellCast or IssuedOrder events, unlike simply issuing a "stop" order. Without any further ado, here's the code:
Requires:
AutoIndex by grim001
The following is an add-on for PreventOrders which uses hooks to make the system ignore any triggered issued orders.
Requires:
AutoIndex by grim001
JASS:
/***********************************************************
* PreventOrders
* by Element of Water
************************************************************
* Requirements:
* - AutoIndex by grim001
* - JassHelper by Vexorian (for vJass)
************************************************************
* What is it?
*
* PreventOrders is a simple library which provides a few
* useful functions to do with the preventing and
* cancelling of certain orders. Whenever an order is
* "prevented", the unit will carry on with its previous
* order as usual (but if it has multiple orders queued
* up, it will not continue with those).
*
* CancelOrders immediately cancels a unit's orders. It
* is different to simply issuing a "stop" order, because
* it works even in response to SpellCast or IssuedOrder
* events. It takes just a single unit parameter. Call
* it like this:
*
* call CancelOrders(myUnit)
*
* It's that simple!
*
* PreventCurrentOrder immediately stops the unit from
* performing its current order and returns it to its
* previous order. The syntax for calling it is as follows:
*
* call PreventCurrentOrder(myUnit)
*
* Simplez!
*
* PreventOrders permanently stops a unit from responding
* to immediate, point and/or target orders. Call it like
* this:
*
* call PreventOrders(myUnit, immediate, point, target)
*
* immediate, point and target are booleans. These should
* be true if you want to disable immediate, point or
* target orders respectively. If you want to re-enable
* a type of order, simply call the function again with
* the desired parameters as false, and the unit will be
* able to recieve orders again
*
* PreventSpecificOrder permanently stops a unit from
* responding to a specific order, such as "move", "smart",
* "channel", "acidbomb", etc. Call it like this:
*
* call PreventSpecificOrder(myUnit, order, prevent)
*
* order is the order string which determines which order
* is prevented, and prevent is a boolean. prevent should
* be true if you want to disable the order, and false if
* you want to re-enable it. Also, if it is false it will
* bypass the blocking of all orders just for this order.
* You can call ClearSpecificOrderPrevention(myUnit, order)
* to reset for one specific order, or call
* ClearAllSpecificOrderPrevention(myUnit) to reset all
* orders for that unit.
*
* There is a variation of this function,
* PreventSpecificOrderById, which takes an integer instead
* of a string for if you prefer to work with order ids.
* You may also use ClearSpecificOrderPreventionById.
*
* AllowNextOrder allows a unit to respond to the next order
* it is issued, whatever that may be. Even if the order
* would not be blocked anyway, this is cleared immediately
* after the next order issued to the unit. The syntax to
* call it is as follows:
*
* call AllowNextOrder(myUnit)
*
* This function is useful for when you want to control the
* unit through triggers, but make it unresponsive to
* player control. The PreventOrdersHooks add-on utilises
* this function to allow all triggered orders via hooks.
***********************************************************/
library PreventOrders initializer Init requires AutoIndex
private keyword Data
globals
private timer Tim = CreateTimer()
private Data array CancelStack
private integer CancelCount = 0
private hashtable Hash = InitHashtable()
private constant integer ORDER_STOP = 851972
// Purely for debugging purposes, this displays when an order is prevented
private constant boolean DISPLAY_PREVENTED_ORDERS = false
// Set this to true to make units keep their old orders rather than simply stopping when an order is prevented
private constant boolean RETAIN_PREVIOUS_ORDERS = false
endglobals
private function DebugMsg takes string unitName, string orderType, string orderString returns nothing
debug static if DISPLAY_PREVENTED_ORDERS then
debug call BJDebugMsg("PreventOrders: Prevented " + unitName + " from being issued a" + orderType + " " + orderString + " order")
debug endif
endfunction
private struct Data extends array
static constant integer IMMEDIATE = 1
static constant integer POINT = 2
static constant integer TARGET = 3
unit u
boolean i
boolean p
boolean t
boolean doNext
integer lastOrderType
integer lastOrderId
widget lastOrderTargetW
real lastOrderTargetX
real lastOrderTargetY
boolean cancel
method lastImmediateOrder takes integer id returns nothing
set lastOrderType = IMMEDIATE
set lastOrderId = id
endmethod
method lastPointOrder takes integer id, real x, real y returns nothing
set lastOrderType = POINT
set lastOrderId = id
set lastOrderTargetX = x
set lastOrderTargetY = y
endmethod
method lastTargetOrder takes integer id, widget target returns nothing
set lastOrderType = TARGET
set lastOrderId = id
set lastOrderTargetW = target
endmethod
method doLastOrder takes nothing returns nothing
if cancel then
set doNext = true
call IssueImmediateOrderById(u, ORDER_STOP)
else
if lastOrderType == IMMEDIATE then
set doNext = true
call IssueImmediateOrderById(u, lastOrderId)
elseif lastOrderType == POINT then
set doNext = true
call IssuePointOrderById(u, lastOrderId, lastOrderTargetX, lastOrderTargetY)
elseif lastOrderType == TARGET then
set doNext = true
call IssueTargetOrderById(u, lastOrderId, lastOrderTargetW)
else
set doNext = true
call IssueImmediateOrderById(u, ORDER_STOP)
endif
endif
endmethod
method assign takes unit whichUnit returns nothing
set u = whichUnit
endmethod
method destroy takes nothing returns nothing
call FlushChildHashtable(Hash, this)
set u = null
set i = false
set p = false
set t = false
set doNext = false
set lastOrderType = 0
set cancel = false
endmethod
endstruct
private function Cancel takes nothing returns nothing
loop
set CancelCount = CancelCount - 1
static if RETAIN_PREVIOUS_ORDERS then
call CancelStack[CancelCount].doLastOrder()
else
set CancelStack[CancelCount].doNext = true
call IssueImmediateOrderById(CancelStack[CancelCount].u, ORDER_STOP)
endif
exitwhen CancelCount == 0
endloop
endfunction
private function PreventCurrentOrderFromData takes Data d returns nothing
if CancelCount == 0 then
call TimerStart(Tim, 0., false, function Cancel)
endif
set CancelStack[CancelCount] = d
set CancelCount = CancelCount + 1
endfunction
function PreventCurrentOrder takes unit u returns nothing
call PreventCurrentOrderFromData(Data[GetUnitId(u)])
endfunction
function CancelOrders takes unit u returns nothing
local Data d = Data[GetUnitId(u)]
static if RETAIN_PREVIOUS_ORDERS then
set d.cancel = true
endif
call PreventCurrentOrderFromData(d)
endfunction
function PreventOrders takes unit u, boolean i, boolean p, boolean t returns nothing
local Data d = Data[GetUnitId(u)]
if i or p or t then
set d.i = i
set d.p = p
set d.t = t
endif
endfunction
function PreventSpecificOrderById takes unit u, integer orderId, boolean prevent returns nothing
local Data d = Data[GetUnitId(u)]
if orderId != 0 then
if prevent then
call SaveBoolean(Hash, d, orderId, true)
elseif d != 0 then
call SaveBoolean(Hash, d, orderId, false)
endif
endif
endfunction
function PreventSpecificOrder takes unit u, string order, boolean prevent returns nothing
call PreventSpecificOrderById(u, OrderId(order), prevent)
endfunction
function ClearSpecificOrderPreventionById takes unit u, integer orderId returns nothing
local Data d = Data[GetUnitId(u)]
if orderId != 0 and orderId != ORDER_STOP then
call RemoveSavedBoolean(Hash, d, orderId)
endif
endfunction
function ClearSpecificOrderPrevention takes unit u, string order returns nothing
call ClearSpecificOrderPreventionById(u, OrderId(order))
endfunction
function ClearAllSpecificOrderPrevention takes unit u returns nothing
local Data d = Data[GetUnitId(u)]
call FlushChildHashtable(Hash, d)
endfunction
function AllowNextOrder takes unit u returns nothing
local Data d = Data[GetUnitId(u)]
set d.doNext = true
endfunction
private function ImmediateOrder takes nothing returns boolean
local unit u = GetTriggerUnit()
local Data d = Data[GetUnitId(u)]
local integer i = GetIssuedOrderId()
if d.doNext then
set d.doNext = false
call d.lastImmediateOrder(i)
else
if d.i then
if (not HaveSavedBoolean(Hash, d, i)) or (LoadBoolean(Hash, d, i)) then
call PreventCurrentOrderFromData(d)
debug call DebugMsg(GetUnitName(u), "n immediate", OrderId2String(i))
else
static if RETAIN_PREVIOUS_ORDERS then
call d.lastImmediateOrder(i)
endif
endif
elseif LoadBoolean(Hash, d, i) then
call PreventCurrentOrderFromData(d)
debug call DebugMsg(GetUnitName(u), "n immediate", OrderId2String(i))
else
static if RETAIN_PREVIOUS_ORDERS then
call d.lastImmediateOrder(i)
endif
endif
endif
set u = null
return false
endfunction
private function PointOrder takes nothing returns boolean
local unit u = GetTriggerUnit()
local Data d = Data[GetUnitId(u)]
local integer i = GetIssuedOrderId()
if d.doNext then
set d.doNext = false
call d.lastPointOrder(i, GetOrderPointX(), GetOrderPointY())
else
if d.p then
if (not HaveSavedBoolean(Hash, d, i)) or (LoadBoolean(Hash, d, i)) then
call PreventCurrentOrderFromData(d)
debug call DebugMsg(GetUnitName(u), " point", OrderId2String(i))
else
static if RETAIN_PREVIOUS_ORDERS then
call d.lastPointOrder(i, GetOrderPointX(), GetOrderPointY())
endif
endif
elseif LoadBoolean(Hash, d, i) then
call PreventCurrentOrderFromData(d)
debug call DebugMsg(GetUnitName(u), " point", OrderId2String(i))
else
static if RETAIN_PREVIOUS_ORDERS then
call d.lastPointOrder(i, GetOrderPointX(), GetOrderPointY())
endif
endif
endif
set u = null
return false
endfunction
private function TargetOrder takes nothing returns boolean
local unit u = GetTriggerUnit()
local Data d = Data[GetUnitId(u)]
local integer i = GetIssuedOrderId()
if d.doNext then
set d.doNext = false
call d.lastTargetOrder(i, GetOrderTarget())
else
if d.t then
if (not HaveSavedBoolean(Hash, d, i)) or (LoadBoolean(Hash, d, i)) then
call PreventCurrentOrderFromData(d)
debug call DebugMsg(GetUnitName(u), " target", OrderId2String(i))
else
static if RETAIN_PREVIOUS_ORDERS then
call d.lastTargetOrder(i, GetOrderTarget())
endif
endif
elseif LoadBoolean(Hash, d, i) then
call PreventCurrentOrderFromData(d)
debug call DebugMsg(GetUnitName(u), " target", OrderId2String(i))
else
static if RETAIN_PREVIOUS_ORDERS then
call d.lastTargetOrder(i, GetOrderTarget())
endif
endif
endif
set u = null
return false
endfunction
private function UnitIndexed takes unit u returns nothing
local Data d = Data[GetUnitId(u)]
call d.assign(u)
endfunction
private function UnitDeindexed takes unit u returns nothing
local Data d = Data[GetUnitId(u)]
call d.destroy()
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
call TriggerAddCondition(t, Condition(function ImmediateOrder))
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerAddCondition(t, Condition(function PointOrder))
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerAddCondition(t, Condition(function TargetOrder))
call OnUnitIndexed(UnitIndexed)
call OnUnitDeindexed(UnitDeindexed)
endfunction
endlibrary
JASS:
/*********************************************************
* PreventOrdersHooks *
* by Element of Water *
**********************************************************
* Requirements: *
* - PreventOrders by Element of Water *
* - JassHelper by Vexorian (for Zinc) *
**********************************************************
* What is it? *
* *
* PreventOrdersHooks is a simple add-on library for *
* PreventOrders which makes every order issued by *
* triggers bypass the system. It does this at the cost *
* a minor efficiency hit for EVERY call in GUI, JASS, *
* whatever, to ANY function which issues an order to a *
* unit. Don't use it if you issue lots of orders to *
* units and notice lag. This library is completely *
* automatic, so you don't have to worry about calling *
* any functions. *
*********************************************************/
library PreventOrdersHooks requires PreventOrders
globals
private constant integer ORDER_STOP = 851972
endglobals
function IssueBuildOrder_hook takes unit u, string s, real x, real y returns nothing
call AllowNextOrder(u)
endfunction
function IssueBuildOrderById_hook takes unit u, integer i, real x, real y returns nothing
call AllowNextOrder(u)
endfunction
function IssueBuildOrderByIdLocBJ_hook takes unit u, integer i, location l returns nothing
call AllowNextOrder(u)
endfunction
function IssueHauntOrderAtLocBJ_hook takes unit u, location l returns nothing
call AllowNextOrder(u)
endfunction
function IssueImmediateOrder_hook takes unit u, string s returns nothing
call AllowNextOrder(u)
endfunction
function IssueImmediateOrderById_hook takes unit u, integer i returns nothing
if i != ORDER_STOP then
call AllowNextOrder(u)
endif
endfunction
function IssueInstantPointOrder_hook takes unit u, string s, real x, real y, widget w returns nothing
call AllowNextOrder(u)
endfunction
function IssueInstantPointOrderById_hook takes unit u, integer i, real x, real y, widget w returns nothing
call AllowNextOrder(u)
endfunction
function IssueInstantTargetOrder_hook takes unit u, string s, widget w, widget w2 returns nothing
call AllowNextOrder(u)
endfunction
function IssueInstantTargetOrderById_hook takes unit u, integer i, widget w, widget w2 returns nothing
call AllowNextOrder(u)
endfunction
function IssueNeutralImmediateOrder_hook takes player p, unit u, string s returns nothing
call AllowNextOrder(u)
endfunction
function IssueNeutralImmediateOrderById_hook takes player p, unit u, integer i returns nothing
call AllowNextOrder(u)
endfunction
function IssueNeutralPointOrder_hook takes player p, unit u, string s, real x, real y returns nothing
call AllowNextOrder(u)
endfunction
function IssueNeutralPointOrderById_hook takes player p, unit u, integer i, real x, real y returns nothing
call AllowNextOrder(u)
endfunction
function IssueNeutralTargetOrder_hook takes player p, unit u, string s, widget w returns nothing
call AllowNextOrder(u)
endfunction
function IssueNeutralTargetOrderById_hook takes player p, unit u, integer i, widget w returns nothing
call AllowNextOrder(u)
endfunction
function IssuePointOrderLoc_hook takes unit u, string s, location l returns nothing
call AllowNextOrder(u)
endfunction
function IssueTargetOrder_hook takes unit u, string s, widget w returns nothing
call AllowNextOrder(u)
endfunction
function IssueTargetOrderById_hook takes unit u, integer i, widget w returns nothing
call AllowNextOrder(u)
endfunction
hook IssueBuildOrder IssueBuildOrder_hook
hook IssueBuildOrderById IssueBuildOrderById_hook
hook IssueBuildOrderByIdLocBJ IssueBuildOrderByIdLocBJ_hook
hook IssueHauntOrderAtLocBJ IssueHauntOrderAtLocBJ_hook
hook IssueImmediateOrder IssueImmediateOrder_hook
hook IssueImmediateOrderBJ IssueImmediateOrder_hook
hook IssueImmediateOrderById IssueImmediateOrderById_hook
hook IssueInstantPointOrder IssueInstantPointOrder_hook
hook IssueInstantPointOrderById IssueInstantPointOrderById_hook
hook IssueInstantTargetOrder IssueInstantTargetOrder_hook
hook IssueInstantTargetOrderById IssueInstantTargetOrderById_hook
hook IssueNeutralImmediateOrder IssueNeutralImmediateOrder_hook
hook IssueNeutralImmediateOrderById IssueNeutralImmediateOrderById_hook
hook IssueNeutralPointOrder IssueNeutralPointOrder_hook
hook IssueNeutralPointOrderById IssueNeutralPointOrderById_hook
hook IssueNeutralTargetOrder IssueNeutralTargetOrder_hook
hook IssueNeutralTargetOrderById IssueNeutralTargetOrderById_hook
hook IssuePointOrder IssueBuildOrder_hook
hook IssuePointOrderById IssueBuildOrderById_hook
hook IssuePointOrderByIdLoc IssueBuildOrderByIdLocBJ_hook
hook IssuePointOrderLoc IssuePointOrderLoc_hook
hook IssuePointOrderLocBJ IssuePointOrderLoc_hook
hook IssueTargetDestructableOrder IssueTargetOrder_hook
hook IssueTargetItemOrder IssueTargetOrder_hook
hook IssueTargetOrder IssueTargetOrder_hook
hook IssueTargetOrderBJ IssueTargetOrder_hook
hook IssueTargetOrderById IssueTargetOrderById_hook
hook IssueTrainOrderByIdBJ IssueImmediateOrderById_hook
hook IssueUpgradeOrderByIdBJ IssueImmediateOrderById_hook
endlibrary
Last edited: