library MPTS initializer Init requires GroupUtils, LinkedList, xefx, xepreload
//Issues: multiple click sounds, don't like lockout method, effects don't show in FoW
globals
private constant integer MAIN_AID = 'A004'
private constant integer NEXT_AID = 'A005'
private constant integer CNCL_AID = 'A003'
private constant integer BUFF_AID = 'A001'
private constant integer BUFF_BID = 'B000'
private integer NEXT_ORD //= OrderId("rainoffire")
private integer CNCL_ORD //= OrderId("taunt")
private integer BUFF_ORD //= OrderId("cripple")
private constant string NEXT_HKY = "j" //always lowercase
private constant string CNCL_HKY = "l"
private constant string INDICATOR_EFFECT = "Objects\\InventoryItems\\BattleStandard\\BattleStandard.mdl"
private constant real INDICATOR_FACING = 270.00*bj_PI/180.00
private constant real CheckInterval = 0.05
private constant real LOCKOUT = 1.00
private constant real CastHotkeyPressDelay = 0.05
private constant integer METHOD_TSA = 0
private constant integer METHOD_TIMER_0 = 1
private constant integer METHOD_TIMER = 2
private constant integer METHOD_EXECUTE = 3
private constant integer METHOD_NEW = 4
@private constant integer USED_METHOD = METHOD_NEW @
private group Casting
private integer array NumCasting
private integer LP //GetLocalPlayer() stored
private timer CancelTimer
private List Instances
private hashtable HT
private constant integer INSTANCE_STRUCT = 0
endglobals
//constant function Flare_DummyUnitId takes nothing returns integer
// return 'h000' //Must have 0 cast point and cast backswing
//endfunction
private struct target
unit u
real x
real y
real z
xefx f
method onDestroy takes nothing returns nothing
call .f.hiddenDestroy()
endmethod
static method create takes unit u, real x, real y, real z, string fx returns target
local target t = target.allocate()
set t.u = u
set t.x = x
set t.y = y
set t.z = z
set t.f = xefx.create(x,y,INDICATOR_FACING)
set t.f.fxpath = fx
return t
endmethod
endstruct
private struct CastData
unit u
integer p
integer lvl
boolean unp
string fxp
List tgts
integer xNoDetect
static CastData TMP
static method CancelCheck takes nothing returns nothing
local integer i = 0
local Link l = Instances.first
local CastData cd
loop
exitwhen l == 0
set cd = CastData(l.data)
if cd.NoDetect > 0 then
set cd.NoDetect = cd.NoDetect-1
endif
set l = l.next
endloop
if NumCasting[LP] > 0 then
call ForceUIKey(CNCL_HKY)
endif
endmethod
static method ForceKeyCallback takes nothing returns nothing
local timer t = GetExpiredTimer()
local CastData cd = CastData(GetTimerData(t))
//set cd.NoDetect = R2I(LOCKOUT/CheckInterval+0.50)
if LP == cd.p then
call ForceUIKey(NEXT_HKY)
endif
call ReleaseTimer(t)
set t = null
endmethod
static method ForceKeyCallbackEx takes nothing returns nothing
local CastData cd = TMP
//set cd.NoDetect = R2I(LOCKOUT/CheckInterval+0.50)
//call TriggerSleepAction(0.00)
//call PauseUnit(cd.u, true)
//call IssueImmediateOrder(cd.u, "stop")
//call PauseUnit(cd.u, false)
if LP == cd.p then
call ForceUIKey(NEXT_HKY)
endif
endmethod
method AddTargetXY takes real x, real y returns nothing
call Link.create(.tgts, target.create(null, x, y, 0.00, .fxp))
call BJDebugMsg("Target "+I2S(.tgts.size)+": ("+R2S(target(.tgts.first.data).x)+", "+R2S(target(.tgts.first.data).y)+")")
endmethod
@method SelectXY takes integer how returns nothing@
set .NoDetect = R2I(LOCKOUT/CheckInterval+0.50)
if how == METHOD_TSA then
call TriggerSleepAction(0.00)
if LP == .p then
call ForceUIKey(NEXT_HKY)
endif
elseif how == METHOD_TIMER_0 then
//set .NoDetect = R2I(LOCKOUT/CheckInterval+0.50)
call TimerStart(NewTimerEx(this), 0.00, false, function CastData.ForceKeyCallback)
elseif how == METHOD_TIMER then
call TimerStart(NewTimerEx(this), CastHotkeyPressDelay, false, function CastData.ForceKeyCallback)
elseif how == METHOD_EXECUTE then
set TMP = this
call CastData.ForceKeyCallbackEx.execute()
// call ExecuteFunc(CastData.ForceKeyCallbackEx.name)
elseif how == METHOD_NEW then
if LP == .p then
call ForceUIKey(NEXT_HKY)
endif
endif
@endmethod@
// method AddTargetUnit takes unit u returns nothing
// endmethod
method operator NoDetect takes nothing returns integer
return .xNoDetect
endmethod
method operator NoDetect= takes integer i returns nothing
local integer prev = .xNoDetect
set .xNoDetect = i
if i > prev then
if prev == 0 then
call .RemoveFromStack()
endif
elseif i < prev and i >= 0 then
if i == 0 then
call .AddToStack()
endif
endif
endmethod
method AddToStack takes nothing returns nothing
if .NoDetect == 0 then
set NumCasting[.p] = NumCasting[.p]+1
endif
if Instances.size == 1 then
call TimerStart(CancelTimer, CheckInterval, true, function CastData.CancelCheck)
endif
endmethod
method RemoveFromStack takes nothing returns nothing
if .NoDetect == 0 then
set NumCasting[.p] = NumCasting[.p]-1
endif
if Instances.size == 0 then
call PauseTimer(CancelTimer)
call GroupRefresh(Casting)
endif
endmethod
method AddAbilities takes nothing returns nothing
call SaveInteger(HT, INSTANCE_STRUCT, GetHandleId(.u), this)
call GroupAddUnit(Casting, .u)
// call UnitAddAbility(.u, NEXT_AID)
// call UnitAddAbility(.u, CNCL_AID)
call SetPlayerAbilityAvailable(Player(.p), NEXT_AID, true)
call SetPlayerAbilityAvailable(Player(.p), CNCL_AID, true)
endmethod
method RemoveAbilities takes nothing returns nothing
call RemoveSavedInteger(HT, INSTANCE_STRUCT, GetHandleId(.u))
call GroupRemoveUnit(Casting, .u)
// call UnitRemoveAbility(.u, NEXT_AID)
// call UnitRemoveAbility(.u, CNCL_AID)
// call SetPlayerAbilityAvailable(Player(.p), NEXT_AID, false)
// call SetPlayerAbilityAvailable(Player(.p), CNCL_AID, false)
endmethod
method RefreshMain takes nothing returns nothing
// call SetPlayerAbilityAvailable(Player(.p), MAIN_AID, false)
// call SetPlayerAbilityAvailable(Player(.p), MAIN_AID, true)
call UnitRemoveAbility(.u, MAIN_AID)
call UnitAddAbility(.u, MAIN_AID)
call SetUnitAbilityLevel(.u, MAIN_AID, .lvl)
call UnitMakeAbilityPermanent(.u, true, MAIN_AID)
// call SetUnitState(.u, UNIT_STATE_MANA, GetUnitState(U, UNIT_STATE_MANA)+Flare_ManaCost(Level))
endmethod
method RemoveInstance takes nothing returns nothing
local Link l = .tgts.first
call .RemoveAbilities()
call .RefreshMain()
// if .unp then //could be simpler
// call PauseUnit(.u, false)
// endif
loop
exitwhen l == 0
call target(l.data).destroy()
set l = l.next
endloop
call .tgts.destroy()
call Instances.search(this).destroy()
call .RemoveFromStack()
endmethod
static method CreateInstance takes unit u, string fx, boolean pause returns CastData
local CastData cd = CastData.allocate()
set cd.u = u
set cd.p = GetPlayerId(GetOwningPlayer(u))
set cd.lvl = GetUnitAbilityLevel(cd.u, MAIN_AID)
set cd.unp = pause
set cd.tgts = List.create()
if LP == cd.p then
set cd.fxp = fx
else
set cd.fxp = ""
endif
//call UnitRemoveAbility(cd.u, MAIN_AID)
//call UnitAddAbility(cd.u, MAIN_AID)
//call SetUnitAbilityLevel(cd.u, MAIN_AID, cd.lvl)
//call UnitMakeAbilityPermanent(.u, true, MAIN_AID)
//call IssueImmediateOrder(cd.u,"stop")
//call ForceUIKey(NEXT_HKY)
// if cd.unp then //could be simpler
// call PauseUnit(cd.u, true)
// endif
call Link.create(Instances, cd)
call cd.AddAbilities()
call cd.AddToStack()
return cd
endmethod
endstruct
private function CancelCast takes nothing returns nothing
local unit u = GetTriggerUnit()
local CastData cd
call BJDebugMsg("None order: "+I2S(GetIssuedOrderId())+OrderId2String(GetIssuedOrderId()))
if GetIssuedOrderId() == CNCL_ORD and IsUnitInGroup(u, Casting) then
set cd = CastData(LoadInteger(HT, INSTANCE_STRUCT, GetHandleId(u)))
if cd.NoDetect == 0 then
call cd.RemoveInstance()
endif
endif
set u = null
endfunction
private function NextPointCast takes nothing returns nothing
local unit u = GetTriggerUnit()
local CastData cd
call BJDebugMsg("Point order: "+I2S(GetIssuedOrderId())+OrderId2String(GetIssuedOrderId()))
if GetIssuedOrderId() == NEXT_ORD and IsUnitInGroup(u, Casting) then
set cd = CastData(LoadInteger(HT, INSTANCE_STRUCT, GetHandleId(u)))
call IssueImmediateOrder(cd.u,"stop")
call cd.AddTargetXY(GetOrderPointX(), GetOrderPointY())
call cd.SelectXY(USED_METHOD)
endif
endfunction
private function MainCast takes nothing returns nothing
local integer Aid = GetSpellAbilityId()
local CastData cd
if Aid == MAIN_AID then
set cd = CastData.CreateInstance(GetTriggerUnit(), INDICATOR_EFFECT, false)
call cd.AddTargetXY(GetSpellTargetX(),GetSpellTargetY())//GetOrderPointX(),GetOrderPointY())
call cd.SelectXY(USED_METHOD)
endif
endfunction
function Death takes nothing returns nothing
local unit u = GetTriggerUnit()
local CastData cd
if IsUnitInGroup(u, Casting) then
set cd = CastData(LoadInteger(HT, INSTANCE_STRUCT, GetHandleId(u)))
call cd.RemoveInstance()
endif
endfunction
private function TEST2 takes nothing returns nothing
call ForceUIKey(NEXT_HKY)
endfunction
private function TEST takes nothing returns nothing
local unit u = GetTriggerUnit()
call UnitRemoveAbility(u, MAIN_AID)
call UnitAddAbility(u, NEXT_AID)
// call TriggerSleepAction(0.00)
// call ForceUIKey(NEXT_HKY)
call TimerStart(NewTimer(), 0.025, false, function TEST2)
endfunction
private function Init takes nothing returns nothing
local trigger T = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(T, EVENT_PLAYER_UNIT_SPELL_CAST)//_EFFECT)
call TriggerAddAction(T, function MainCast)
// set T = CreateTrigger()
// call TriggerRegisterAnyUnitEventBJ(T, EVENT_PLAYER_UNIT_SPELL_EFFECT)
// call TriggerAddAction(T, function TEST)
set T = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(T, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerAddAction(T, function NextPointCast)
set T = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(T, EVENT_PLAYER_UNIT_ISSUED_ORDER)//EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddAction(T, function CancelCast)
set T = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(T, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddAction(T, function Death)
set T = null
set Casting = NewGroup()
set LP = GetPlayerId(GetLocalPlayer())
set Instances = List.create()
set HT = InitHashtable()
set CancelTimer = NewTimer()
call XE_PreloadAbility(MAIN_AID)
call XE_PreloadAbility(CNCL_AID)
call XE_PreloadAbility(NEXT_AID)
set CNCL_ORD = OrderId("taunt")
set NEXT_ORD = OrderId("rainoffire")
set BUFF_ORD = OrderId("cripple")
endfunction
endlibrary