Is there a way to "stun" the unit without cancelling its channelling for the purpose of time stop?
I found this: [System] PreventOrders , but there are a couple of problems with it:
(1) A bug: I can't activate the unit back
(2) It does not stop immediate orders (berserk, mana shield)
I changed only Unit Indexer, so I don't think I fcked something up:
I found this: [System] PreventOrders , but there are a couple of problems with it:
(1) A bug: I can't activate the unit back
(2) It does not stop immediate orders (berserk, mana shield)
I changed only Unit Indexer, so I don't think I fcked something up:
JASS:
library PreventOrders initializer Init requires UnitIndexer
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 onUnitIndex takes nothing returns nothing
local Data d = Data[UnitIndexer.eventIndex]
call d.assign(UnitIndexer.eventUnit)
endfunction
private function onUnitDeindex takes nothing returns nothing
local Data d = Data[UnitIndexer.eventIndex]
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 UnitIndexer.GlobalEvent.ON_INDEX.register(Condition(function onUnitIndex))
call UnitIndexer.GlobalEvent.ON_DEINDEX.register(Condition(function onUnitDeindex))
endfunction
endlibrary
Last edited: