library PauseLibrary
globals
// This serves as the main setup for pausing/unpausing a unit.
// Pause Ability ID
public constant integer PAUSE_ID = 'A00A' // Based on 'Infinite Channel Ability'
public constant integer PAUSE_ORDER_ID = 852055
/*
OBJECT DATA IMPORTS ARE 'OPTIONAL' BELOW
I've discovered that infinite channel ability alone is not enough for some rare cases.
So if you don't care about these rare cases you can simply set the booleans to FALSE. (<-NO IMPORT REQUIRED)
If the infinite channel ability doesn't get implemented to a unit, the pause method adapts to a new method.
These are some of the rare cases where infinite channel ability method breaks: */
/*
Case #1: Militia - for unknown reason, we can only put aura abilities to them,
so we can't implement this method to militia units as it's considered using an active ability...
In order to pause them, we can DISARM them. */
public constant boolean DISARM = true
// Disarm Ability ID
public constant integer DISARM_ID = 'A001' // Based on 'Cargo Hold Ability'
/*
Case #2: Same as #1 but the unit has abilities, therefore DISARM is not enough.
In order to pause them, we can DISABLE (DISARM + SILENCE) them.
So you should set DISARM to false and set DISABLE to true instead.
Note that this DISABLE method requires and creates a global dummy unit to
cast the Disable Ability on a unit. It also shows on the unit's status bar.
Make sure you set the 'Stats - Buffs' field of the Disable Ability to Disable <- (Buff) in OE. */
public constant boolean DISABLE = false
// Dummy Unit ID
public constant integer DISABLE_CASTER = 'dumi' // Based on 'DummyRecycler Library'
// Disable Ability ID
public constant integer DISABLE_ID = 'A004' // Based on 'Drunken Haze Ability'
public constant integer DISABLE_ORDER_ID = 852585
// Disable Buff ID
public constant integer DISABLE_BUFF = 'B000' // Based on 'Drunken Haze Buff'
/* If you have Breath Of Fire ability that ignites the units having the Drunken Haze Buff in your map,
You must specify the Drunken Haze buff and the Breath of Fire buff that is related to each other.
In this way, Breath Of Fire ability will not ignite the units that are paused using the DISABLE method. */
// Drunken Haze Buff ID
public constant integer DRUNKEN_HAZE_BUFF = 'BNdh'
// Breath Of Fire Buff ID
public constant integer BREATH_OF_FIRE_BUFF = 'BNbf'
/*
Case #3: Silenced - for obvious reason, we can't implement the method to a silenced unit.
In order to pause them, the silence must be removed from the unit first before pausing it. */
public constant boolean SILENCE = true
// Silence Buff ID
public constant integer SILENCE_BUFF = 'BNsi'
/*
Case #4: Polymorphed - for obvious reason, we can't implement the method to a polymorphed unit.
In order to pause them, periodic polymorph checking, disabling its movement, and re-enable pause. */
public constant boolean POLYMORPH = true
/*
Case #5: Sleeping - for obvious reason, we can't implement the method to a sleeping unit.
In order to pause them, the unit must wake up first so we can order it to execute the pause. */
public constant boolean SLEEPING = true
public constant real PERIODIC_INTERVAL = 0.05
endglobals
struct PauseSystem extends array
private static hashtable table = InitHashtable()
private static method periodic takes nothing returns nothing
local unit target = LoadUnitHandle(table,0,GetHandleId(GetExpiredTimer()))
local thistype this = GetHandleId(target)
local integer count = LoadInteger(table,this,0)
static if DISABLE then
if GetUnitAbilityLevel(target,BREATH_OF_FIRE_BUFF) > 0 and GetUnitAbilityLevel(target,DRUNKEN_HAZE_BUFF) == 0 then
call UnitRemoveAbility(target,BREATH_OF_FIRE_BUFF)
endif
endif
static if SILENCE then
if GetUnitAbilityLevel(target,SILENCE_BUFF) > 0 then
static if DISARM then
if GetUnitAbilityLevel (target,DISARM_ID) == 0 then
call UnitAddAbility(target,DISARM_ID)
endif
elseif DISABLE then
if GetUnitAbilityLevel(target,DISABLE_BUFF) == 0 then
call SetUnitX( disabler,GetUnitX(target) )
call SetUnitY( disabler,GetUnitY(target) )
call UnitAddAbility(disabler,DISABLE_ID)
call IssueTargetOrderById(disabler,DISABLE_ORDER_ID,target)
call UnitRemoveAbility(disabler,DISABLE_ID)
endif
else
call UnitRemoveAbility(target,SILENCE_BUFF)
endif
endif
endif
if GetUnitTypeId(target) != LoadInteger(table,this,2) then
call BJDebugMsg("|cffff0000Attempting to pause a changed unit type of target!|r A handle id of: " + I2S(this) + "(" + GetObjectName(GetUnitTypeId(target) ) + ")" + " is paused with a count of: " + I2S(count) )
call SaveInteger( table,this,2,GetUnitTypeId(target) )
call UnitRemoveAbility(target,PAUSE_ID)
call SetUnitTurnSpeed(target,0)
call SetUnitPropWindow(target,0)
if UnitAddAbility(target,PAUSE_ID) and IssueImmediateOrderById(target,PAUSE_ORDER_ID) then
endif
if GetUnitAbilityLevel(target,PAUSE_ID) == 0 or GetUnitCurrentOrder(target) != PAUSE_ORDER_ID then
static if DISARM then
if GetUnitAbilityLevel (target,DISARM_ID) == 0 then
call UnitAddAbility(target,DISARM_ID)
endif
elseif DISABLE then
if GetUnitAbilityLevel(target,DISABLE_BUFF) == 0 then
call SetUnitX( disabler,GetUnitX(target) )
call SetUnitY( disabler,GetUnitY(target) )
call UnitAddAbility(disabler,DISABLE_ID)
call IssueTargetOrderById(disabler,DISABLE_ORDER_ID,target)
call UnitRemoveAbility(disabler,DISABLE_ID)
endif
endif
endif
endif
static if POLYMORPH then
if not IsUnitType(target,UNIT_TYPE_POLYMORPHED) and LoadBoolean(table,this,3) then
call BJDebugMsg("|cffff0000Attempting to pause a non-polymorphed target!|r A handle id of: " + I2S(this) + "(" + GetObjectName(GetUnitTypeId(target) ) + ")" + " is paused with a count of: " + I2S(count) )
call SetUnitTurnSpeed(target,0)
call SetUnitPropWindow(target,0)
static if SILENCE then
if GetUnitAbilityLevel(target,SILENCE_BUFF) > 0 then
call UnitRemoveAbility(target,SILENCE_BUFF)
endif
endif
call IssueImmediateOrderById(target,PAUSE_ORDER_ID)
call RemoveSavedBoolean(table,this,3)
elseif IsUnitType(target,UNIT_TYPE_POLYMORPHED) then
call BJDebugMsg("|cffff0000Attempting to pause a polymorphed target!|r A handle id of: " + I2S(this) + "(" + GetObjectName(GetUnitTypeId(target) ) + ")" + " is paused with a count of: " + I2S(count) )
call SetUnitTurnSpeed(target,0)
call SetUnitPropWindow(target,0)
call SaveBoolean( table,this,3,true )
endif
endif
set target = null
endmethod
static method pause takes unit target returns nothing
local thistype this = GetHandleId(target)
local integer count = LoadInteger(table,this,0)
local timer time
if count == 0 then
set time = CreateTimer()
call SaveUnitHandle(table,0,GetHandleId(time),target)
call TimerStart(time,PERIODIC_INTERVAL,true,function thistype.periodic)
call SaveTimerHandle(table,this,1,time)
call SaveInteger( table,this,2,GetUnitTypeId(target) )
if count == 0 then
call BJDebugMsg("A handle id of: " + I2S(this) + "(" + GetObjectName(GetUnitTypeId(target) ) + ")" + " is paused with a count of: " + I2S(count) + " (normal)")
else
call BJDebugMsg("A handle id of: " + I2S(this) + "(" + GetObjectName(GetUnitTypeId(target) ) + ")" + " is paused with a count of: " + I2S(count) + " (|cffff0000error|r)")
endif
static if SLEEPING then
if IsUnitType(target,UNIT_TYPE_SLEEPING) then
call UnitWakeUp(target)
endif
endif
static if SILENCE then
if GetUnitAbilityLevel(target,SILENCE_BUFF) > 0 then
call UnitRemoveAbility(target,SILENCE_BUFF)
endif
endif
call SetUnitTurnSpeed(target,0)
call SetUnitPropWindow(target,0)
if UnitAddAbility(target,PAUSE_ID) and IssueImmediateOrderById(target,PAUSE_ORDER_ID) then
endif
if GetUnitAbilityLevel(target,PAUSE_ID) == 0 or GetUnitCurrentOrder(target) != PAUSE_ORDER_ID then
static if DISARM then
call UnitAddAbility(target,DISARM_ID)
elseif DISABLE then
call SetUnitX( disabler,GetUnitX(target) )
call SetUnitY( disabler,GetUnitY(target) )
call UnitAddAbility(disabler,DISABLE_ID)
call IssueTargetOrderById(disabler,DISABLE_ORDER_ID,target)
call UnitRemoveAbility(disabler,DISABLE_ID)
endif
endif
static if POLYMORPH then
if IsUnitType(target,UNIT_TYPE_POLYMORPHED) then
call BJDebugMsg("Is the paused unit polymorphed? YES")
call SaveBoolean( table,this,3,true )
else
call BJDebugMsg("Is the paused unit polymorphed? NO")
call SaveBoolean( table,this,3,false )
endif
/* temporarily disabling suspicious part
call SaveBoolean( table,this,3,IsUnitType(target,UNIT_TYPE_POLYMORPHED) ) */
endif
set time = null
else
call BJDebugMsg("|cffff0000Attempting to pause a unit again!|r A handle id of: " + I2S(this) + "(" + GetObjectName(GetUnitTypeId(target) ) + ")" + " is paused with a count of: " + I2S(count) )
endif
call SaveInteger(table,this,0,count + 1)
endmethod
static method unpause takes unit target returns nothing
local timer time
local thistype this = GetHandleId(target)
local integer count = LoadInteger(table,this,0)
set count = count - 1
call SaveInteger(table,this,0,count)
if count == 0 then
static if DISARM then
call UnitRemoveAbility(target,DISARM_ID)
endif
static if DISABLE then
call UnitRemoveAbility(target,DISABLE_BUFF)
endif
call UnitRemoveAbility(target,PAUSE_ID)
call SetUnitTurnSpeed(target,GetUnitDefaultTurnSpeed(target) )
call SetUnitPropWindow(target,GetUnitDefaultPropWindow(target)*bj_RADTODEG)
if count == 0 then
call BJDebugMsg("A handle id of: " + I2S(this) + "(" + GetObjectName(GetUnitTypeId(target) ) + ")" + " is unpaused with a count of: " + I2S(count) + " (normal)")
else
call BJDebugMsg("A handle id of: " + I2S(this) + "(" + GetObjectName(GetUnitTypeId(target) ) + ")" + " is unpaused with a count of: " + I2S(count) + " (|cfffff0000error|r)")
endif
set time = LoadTimerHandle(table,this,1)
call DestroyTimer(time)
call RemoveSavedHandle( table,0,GetHandleId(time) )
call FlushChildHashtable(table,this)
set time = null
else
call BJDebugMsg("|cffff0000Attempting to unpause a unit again!|r A handle id of: " + I2S(this) + "(" + GetObjectName(GetUnitTypeId(target) ) + ")" + " is unpaused with a count of: " + I2S(count) )
endif
endmethod
static if DISABLE then
private static unit disabler = null
private static method onInit takes nothing returns nothing
set disabler = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA),DISABLE_CASTER,0,0,0)
endmethod
endif
endstruct
endlibrary