Name | Type | is_array | initial_value |
library ClickAndHoldMovement initializer Init
/*
===========================================================================================
Click-And-Hold Movement
by Antares
Enable click-and-hold movement (hold the right mouse-button to move your hero) for hero maps
like aeon of strife, hero arenas, or rpgs.
===========================================================================================
*/
globals
//====================================================
//Config
//====================================================
private constant real IGNORE_MOUSE_SPELL_DURATION = 0.5 //Disables the click-and-hold trigger for this many seconds when a unit in the selected group casts a spell. This enables the user to cast a spell without releasing the right mouse-button.
private constant real IGNORE_MOUSE_CLICK_DURATION = 0.25 //Disables the click-and-hold trigger for this many seconds right after the right mouse-button is pressed. This prevents the trigger from firing on a simple right-click.
private constant real MOUSE_MOVE_COOLDOWN_DURATION = 0.1 //Duration of the cooldown on the click-and-hold trigger on giving orders.
private constant boolean DISABLE_IF_MULTIPLE_SELECTED = false
private constant boolean STOP_MOVING_ON_RELEASE = false //The commanded units will stop moving as soon as the right mouse-button is released. They will also ignore pathing blockers between the mouse-cursor and the unit.
private constant boolean CUSTOM_CALLBACK = false //Enable if you want to write your own callback function for the click-and-hold trigger. Otherwise, it will be a replaced by a simple smart command.
//====================================================
private trigger array mouseMoveTrigger
real array mouseX
real array mouseY
private boolean array rightClickOn
private timer array ignoreMouseTimer
private group array selectedUnits
private boolean array setGroup
private boolean array noOrders
endglobals
//====================================================
private function CustomCallback takes unit whichUnit, real x, real y returns nothing
//Define your custom callback code here.
endfunction
//====================================================
private function SetAndCheckSelection takes integer P returns boolean
local boolean invalidSelection
local unit first
local player whichPlayer = Player(P)
set selectedUnits[P] = CreateGroup()
call GroupEnumUnitsSelected(selectedUnits[P] , whichPlayer , null)
static if DISABLE_IF_MULTIPLE_SELECTED then
set invalidSelection = BlzGroupGetSize(selectedUnits[P]) != 1
else
set invalidSelection = BlzGroupGetSize(selectedUnits[P]) == 0
endif
set setGroup[P] = false
if invalidSelection then
call DestroyGroup(selectedUnits[P])
return false
else
set first = FirstOfGroup(selectedUnits[P])
if GetOwningPlayer(first) == whichPlayer or (IsUnitAlly(first,whichPlayer) and GetPlayerAlliance(GetOwningPlayer(first),whichPlayer,ALLIANCE_SHARED_CONTROL)) then
set first = null
return true
else
call DestroyGroup(selectedUnits[P])
set first = null
return false
endif
endif
endfunction
private function CommandGroup takes integer P returns nothing
local integer i = BlzGroupGetSize(selectedUnits[P]) - 1
local unit u
local real angle
loop
exitwhen i < 0
static if CUSTOM_CALLBACK then
call CustomCallback( BlzGroupUnitAt(selectedUnits[P] , i) , mouseX[P] , mouseY[P] )
elseif STOP_MOVING_ON_RELEASE then
set u = BlzGroupUnitAt(selectedUnits[P] , i)
set angle = Atan2( mouseY[P] - GetUnitY(u) , mouseX[P] - GetUnitX(u) )
call IssuePointOrderById( BlzGroupUnitAt(selectedUnits[P] , i) , 851971 , GetUnitX(u) + 50*Cos(angle) , GetUnitY(u) + 50*Sin(angle) )
else
call IssuePointOrderById( BlzGroupUnitAt(selectedUnits[P] , i) , 851971 , mouseX[P] , mouseY[P] )
endif
set i = i - 1
endloop
set u = null
endfunction
private function Enable takes nothing returns nothing
local integer i
local integer P = 0
local timer t = GetExpiredTimer()
loop
exitwhen t == ignoreMouseTimer[P]
set P = P + 1
endloop
set noOrders[P] = false
if rightClickOn[P] then
if setGroup[P] then
if SetAndCheckSelection(P) then
call CommandGroup(P)
endif
else
call CommandGroup(P)
endif
endif
set t = null
endfunction
private function MouseSpellIgnore takes nothing returns nothing
local unit whichUnit = GetSpellAbilityUnit()
local integer P = GetPlayerId(GetOwningPlayer(whichUnit))
if IsUnitInGroup(whichUnit , selectedUnits[P]) then
set noOrders[P] = true
call TimerStart( ignoreMouseTimer[P] , IGNORE_MOUSE_SPELL_DURATION , false , function Enable )
endif
set whichUnit = null
endfunction
private function MouseMove takes nothing returns nothing
local integer i
local integer P = GetPlayerId(GetTriggerPlayer())
local real mX = BlzGetTriggerPlayerMouseX()
local real mY = BlzGetTriggerPlayerMouseY()
if mY != 0 or mX != 0 then
set mouseX[P] = mX
set mouseY[P] = mY
endif
if noOrders[P] then
return
endif
if MOUSE_MOVE_COOLDOWN_DURATION > 0 then
set noOrders[P] = true
call TimerStart( ignoreMouseTimer[P] , MOUSE_MOVE_COOLDOWN_DURATION , false , function Enable )
endif
call CommandGroup(P)
endfunction
private function MouseRightClick takes nothing returns nothing
local integer A
local integer P
if BlzGetTriggerPlayerMouseButton() == MOUSE_BUTTON_TYPE_RIGHT then
set P = GetPlayerId(GetTriggerPlayer())
set rightClickOn[P] = true
set noOrders[P] = true
set setGroup[P] = true
set mouseX[P] = BlzGetTriggerPlayerMouseX()
set mouseY[P] = BlzGetTriggerPlayerMouseY()
call TimerStart( ignoreMouseTimer[P] , IGNORE_MOUSE_CLICK_DURATION , false , function Enable )
call EnableTrigger(mouseMoveTrigger[P])
endif
endfunction
private function MouseRightRelease takes nothing returns nothing
local integer P
if BlzGetTriggerPlayerMouseButton() == MOUSE_BUTTON_TYPE_RIGHT then
set P = GetPlayerId(GetTriggerPlayer())
call DestroyGroup(selectedUnits[P])
set rightClickOn[P] = false
call DisableTrigger(mouseMoveTrigger[P])
endif
endfunction
private function At0s takes nothing returns nothing
local integer P = 0
local trigger trigDown = CreateTrigger()
local trigger trigUp = CreateTrigger()
local trigger trigIgnore = CreateTrigger()
local trigger trigStore = CreateTrigger()
loop
exitwhen P > 23
if GetPlayerSlotState(Player(P)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(P)) == MAP_CONTROL_USER then
set mouseMoveTrigger[P] = CreateTrigger()
call TriggerRegisterPlayerEvent( trigDown, Player(P), EVENT_PLAYER_MOUSE_DOWN )
call TriggerRegisterPlayerEvent( trigUp, Player(P), EVENT_PLAYER_MOUSE_UP )
call TriggerRegisterPlayerEvent( mouseMoveTrigger[P], Player(P), EVENT_PLAYER_MOUSE_MOVE )
call TriggerAddCondition( mouseMoveTrigger[P] , function MouseMove )
call DisableTrigger(mouseMoveTrigger[P])
set ignoreMouseTimer[P] = CreateTimer()
endif
set P = P + 1
endloop
call DestroyTrigger(GetTriggeringTrigger())
call TriggerAddCondition( trigDown , function MouseRightClick )
call TriggerAddCondition( trigUp , function MouseRightRelease )
call TriggerRegisterAnyUnitEventBJ( trigIgnore, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( trigIgnore , function MouseSpellIgnore )
set trigDown = null
set trigUp = null
set trigIgnore = null
set trigStore = null
endfunction
private function Init takes nothing returns nothing
local trigger at0sTrigger = CreateTrigger()
call TriggerRegisterTimerEvent( at0sTrigger , 0.0 , false )
call TriggerAddAction( at0sTrigger , function At0s )
set at0sTrigger = null
endfunction
endlibrary