Executor
I see you
- Reaction score
- 57
ForceKeySystem v1.1
by Executor
- Language = vJass
- Requires = Event;
- MPI
ForceKey?
This system allows you to activate a ForceKey-mode for each player which means that aslong as the mode is active he will always have selected only a dummy unit. The user is forced to send a hotkey signal to the dummy unit preparing it all the time to cast a dummy spell. This means if you click with left click somewhere on the map it will be recognized as an order you may react to.
Screenshot:
Interface and Documentation:
JASS:
// This system provides the possibility to react to left mouse clicks.
// Therefore when turned on, a dummy will permanently be selected and
// a hotkey for a 'selection' spell gets issued. This way you are
// permanently in 'targeting' mode (cursor => target cross) and leftclicking
// leads to ordering the dummy to cast. I block the cast and process the
// information given by it, ( x , y , player ).
// Additional to that you may force that your next click is 'special', the
// special click ability may have different target settings than the normal ability.
// For example, normal leftclicking (on ground) leads to blizzards being casted
// but hitting escape before clicking allows you to target units and will affect
// with a stormbolt
// IMPORTANT: I use the unituserdata of my dummy units.
// ForceKey Interface ( slower "pure" JASS version)
function TriggerRegisterForceKeyClickEvent takes trigger t returns EventReg
// which trigger shall fire on click?
function EnableForceKeyForPlayer takes player p returns nothing
// turn on forcekey mode for specific player
function DisableForceKeyForPlayer takes player p returns nothing
// turn off forcekey mode for specific player
function ForceSpecialClick takes player p returns nothing
// next click will use the 'special' ability
// 'Normal' event responses
function GetClickX takes nothing returns real
function GetClickY takes nothing returns real
function GetClickingPlayer takes nothing returns player
function GetClickedUnit takes nothing returns unit
function GetClickedItem takes nothing returns item
function GetClickedDestructable takes nothing returns destructable
function IsObjectClicked takes nothing returns boolean
// click on the ground or a object?
function IsGroundClicked takes nothing returns boolean
// click on the ground or a object?
function SpecialClicked takes nothing returns boolean
// special or normal?
function NormalClicked takes nothing returns boolean
// special or normal?
// ForceKey Interface ( faster vJASS version)
ForceKey.anyClick.register( trigger ) => EventReg
// trigger will fire on click (EventReg is return value of Event)
ForceKey.InitPlayer( player ) => ForceKey - Instance
// you want to activate the forcekey mode for this player sometime
// so first of all initialize the player
// Event responses
ForceKey.TrigX => real
ForceKey.TrigY => real
ForceKey.TrigPlayer => player
ForceKey.TrigUnit => unit
ForceKey.TrigItem => item
ForceKey.TrigDestructable => destructable
ForceKey.Object => boolean
ForceKey.Special => boolean
ForceKey.Normal => boolean
ForceKey[ player ] => ForceKey - Instance
// if you don't want to save the instance id
Instance.forceSpecialOnce() => nothing // Next click will be a special click
Instance.start() => nothing // Start ForceKey mode
Instance.pause() => nothing // Pause ForceKey mode
Instance.switch() => nothing // Start/Pause ForceKey mode
System Code:
JASS:
library ForceKey requires Event
// ======================================================
// = ForceKeySystem made by Executor =
// ======================================================
// ======================================================
// = Credits =
// = Azlier: Idea =
// = Jesus4Lyf: Event =
// ======================================================
//! textmacro CreateForceKeyDummy takes ID SPELL ABORT
//! external ObjectMerger w3u hpea $ID$ uabi Apiv,$SPELL$,$ABORT$ umvh 9999 umvs -50 upgr "" ubui "" utyp tree ufoo 0 ubba 0 ubsi 0 ubdi 0 ugol 0 uibo 1 ubdg 1 ufle 0 uhpm 1000000000 uhom 1 usin 0 usid 0 uhpr 9999 ucol -5 uine 0 usnd "" ussc -50 uslz -50 umdl "None.mdl" ushu "" usca 0 uaen 0 uacq 99999 unam " " unsf "Force Key Dummy" utip " " utub " "
//! endtextmacro
//! textmacro CreateForceKeyDummyAbility takes ID, HOTKEY
//! external ObjectMerger w3a Asdg $ID$ aart "Textures\Black32" auar "Textures\Black32" ansf "" anam "ForceKeyNormal" ahky $HOTKEY$ atar 1 "none" aut1 1 "" auu1 1 "" atp1 1 "" aub1 1 "" aran 1 99999
//! endtextmacro
//! textmacro CreateForceKeyDummySpecial takes ID, HOTKEY
//! external ObjectMerger w3a Asds $ID$ aart "Textures\Black32" auar "Textures\Black32" ansf "" anam "ForceKeySpecial" ahky $HOTKEY$ atar 1 "tree,ground,bridge,decoration,item,structure,debris,invulnerable,vulnerable,debris,wall,ward" aut1 1 "" auu1 1 "" atp1 1 "" aub1 1 "" aran 1 99999
//! endtextmacro
//! textmacro CreateForceKeyDummyAbortAbility takes ID
//! external ObjectMerger w3a Afsh $ID$ flk5 1 0 flk2 1 0 flk4 1 0 flk1 1 0 flk3 1 0 areq "" arac creeps aare 1 0 abpx 3 abpy 2 aart "ReplaceableTextures\CommandButtons\BTNCancel.blp" anam "ForceKeyCancel" atp1 1 "Abort" aub1 1 ""
//! endtextmacro
struct ForceKey
// if you want to modify the hotkey used, modify the 2 lines beneath + the var HOTKEY
// if you want to modify the ability rawcodes don't forget to modify also
// "CreateForceKeyDummy", aswell as the 3 vars beneath.
//! runtextmacro CreateForceKeyDummySpecial("mfks","T")
//! runtextmacro CreateForceKeyDummyAbility("mfka","T")
//! runtextmacro CreateForceKeyDummyAbortAbility("mfkc")
//! runtextmacro CreateForceKeyDummy("mfkd","mfka","mfkc")
private static constant boolean INVERT_ABILITIES = false
private static string HOTKEY = "T"
private static integer ORDER = 852040
private static integer NORMAL_ABIL = 039;mfka039;
private static integer SPECIAL_ABIL = 039;mfks039;
private static constant integer DUM_ID = 039;mfkd039;
private static constant real DUM_X = 0.
private static constant real DUM_Y = 0.
private static constant real PERIOD = 0.05
public static player TrigPlayer = null
public static real TrigX = 0.
public static real TrigY = 0.
public static boolean Special = false
public static boolean Normal = false
public static boolean Object = false
public static Event NormalClick = 0
public static Event SpecialClick = 0
public static Event anyClick = 0
private static timer Timer = CreateTimer()
private static trigger GroundOrder = CreateTrigger()
private static trigger ObjectOrder = CreateTrigger()
private static hashtable Typecaster = InitHashtable()
private static thistype front = -1
private static thistype back = -1
private static thistype array Reference
private unit dummy
private boolean active
private boolean reset
private player user
private thistype next
private thistype last
private boolean special
static method InitPlayer takes player p returns thistype
local thistype this = thistype.allocate()
set .dummy = CreateUnit(p, DUM_ID, DUM_X, DUM_Y, 0.)
set .user = p
set .active = false
set .next = -1
set .last = -1
set .active = false
set .reset = false
set .special = false
set .NormalClick = Event.create()
set .SpecialClick = Event.create()
set .Reference[GetPlayerId(p)] = this
if ForceKey.INVERT_ABILITIES then
call UnitRemoveAbility(.dummy, .SPECIAL_ABIL)
call UnitAddAbility(.dummy, .NORMAL_ABIL)
endif
call UnitRemoveAbility(.dummy, 039;Amov039;)
call SetUnitUserData(.dummy, this)
call ShowUnit(.dummy, false)
call TriggerRegisterUnitEvent(GroundOrder, .dummy, EVENT_UNIT_ISSUED_POINT_ORDER)
call TriggerRegisterUnitEvent(ObjectOrder, .dummy, EVENT_UNIT_ISSUED_TARGET_ORDER)
return this
endmethod
method start takes nothing returns nothing
if .active then
return
endif
set .active = true
if .back == -1 then
set .back = this
set .front = this
else
set .back.next = this
set .last = .back
set .back = this
endif
if .front == this then
call TimerStart(.Timer, .PERIOD, true, function thistype.TimerEx)
endif
call ShowUnit(.dummy, true)
if GetLocalPlayer() == .user then
call SelectUnit(.dummy, true)
call EnableSelect(false, false)
endif
endmethod
method pause takes nothing returns nothing
if not .active then
return
endif
set .active = false
if this == .front then
set .front = .next
else
set .last.next = .next
endif
if this == .back then
set .back = .last
else
set .next.last = .last
endif
if .front == -1 then
call PauseTimer(.Timer)
endif
set .next = -1
set .last = -1
call ShowUnit(.dummy, false)
if GetLocalPlayer() == .user then
call EnableSelect(true, true)
endif
endmethod
method switch takes nothing returns nothing
if .active then
call .pause()
else
call .start()
endif
endmethod
method forceSpecialOnce takes nothing returns nothing
set .reset = true
set .special = true
call UnitRemoveAbility(.dummy, .NORMAL_ABIL )
call UnitAddAbility(.dummy,.SPECIAL_ABIL )
endmethod
private static method ObjectOrderEx takes nothing returns boolean
local thistype this = GetUnitUserData( GetTriggerUnit() )
if not (GetIssuedOrderId() == .ORDER) then
return false
endif
set .Normal = not .special
set .Special = .special
if .reset then
set .special = false
set .reset = false
call UnitAddAbility(.dummy, .NORMAL_ABIL)
call UnitRemoveAbility(.dummy, .SPECIAL_ABIL)
endif
call PauseUnit( .dummy, true)
call IssueImmediateOrder(.dummy, "stop")
call PauseUnit( .dummy, false)
if GetLocalPlayer() == .TrigPlayer then
call ForceUIKey(.HOTKEY)
endif
set .TrigPlayer = .user
set .Object = true
call SaveAgentHandle(.Typecaster,0,0, GetOrderTarget())
call .anyClick.fire()
if .Special then
call .SpecialClick.fire()
else
call .NormalClick.fire()
endif
return false
endmethod
private static method GroundOrderEx takes nothing returns boolean
local thistype this = GetUnitUserData( GetTriggerUnit() )
local integer OrderID = GetIssuedOrderId()
if not (OrderID == .ORDER) then
return false
endif
set .Normal = not .special
set .Special = .special
if .reset then
set .reset = false
set .special = false
call UnitAddAbility(.dummy, .NORMAL_ABIL)
call UnitRemoveAbility(.dummy, .SPECIAL_ABIL)
endif
call PauseUnit( .dummy, true)
call IssueImmediateOrder(.dummy, "stop")
call PauseUnit( .dummy, false)
if GetLocalPlayer() == .TrigPlayer then
call ForceUIKey(.HOTKEY)
endif
set .TrigPlayer = .user
set .TrigX = GetOrderPointX()
set .TrigY = GetOrderPointY()
set .Object = false
call .anyClick.fire()
if .special then
call .SpecialClick.fire()
else
call .NormalClick.fire()
endif
return false
endmethod
private static method TimerEx takes nothing returns nothing
local thistype this = .front
loop
exitwhen this == -1
if GetLocalPlayer() == .user then
call ForceUIKey(.HOTKEY)
call SelectUnit(.dummy, true)
endif
set this = .next
endloop
endmethod
static method operator [] takes player p returns thistype
return .Reference[GetPlayerId(p)]
endmethod
static method operator TrigUnit takes nothing returns unit
return LoadUnitHandle(.Typecaster,0,0)
endmethod
static method operator TrigItem takes nothing returns item
return LoadItemHandle(.Typecaster,0,0)
endmethod
static method operator TrigDestructable takes nothing returns destructable
return LoadDestructableHandle(.Typecaster,0,0)
endmethod
private static method onInit takes nothing returns nothing
local integer i = .NORMAL_ABIL
if ForceKey.INVERT_ABILITIES then
set .NORMAL_ABIL = .SPECIAL_ABIL
set .SPECIAL_ABIL = i
endif
set .front = -1
set .back = -1
set .anyClick = Event.create()
call TriggerAddCondition(.GroundOrder, Condition(function thistype.GroundOrderEx))
call TriggerAddCondition(.ObjectOrder, Condition(function thistype.ObjectOrderEx))
endmethod
private method onDestroy takes nothing returns nothing
// A ForceKey Struct is not meant to be destroyed but if you want ..
call .pause()
call RemoveUnit( .dummy )
endmethod
endstruct
public function TriggerRegisterForceKeyClickEvent takes trigger t returns EventReg
return ForceKey.anyClick.register( t )
endfunction
public function EnableForceKeyForPlayer takes player p returns nothing
local ForceKey F = ForceKey[p]
if F == 0 then
call ForceKey.InitPlayer(p).start()
return
endif
call F.start()
endfunction
public function DisableForceKeyForPlayer takes player p returns nothing
call ForceKey[p].pause()
endfunction
public function ForceSpecialClick takes player p returns nothing
call ForceKey[p].forceSpecialOnce()
endfunction
public function GetClickX takes nothing returns real
return ForceKey.TrigX
endfunction
public function GetClickY takes nothing returns real
return ForceKey.TrigY
endfunction
public function GetClickPlayer takes nothing returns player
return ForceKey.TrigPlayer
endfunction
public function GetClickedUnit takes nothing returns unit
return ForceKey.TrigUnit
endfunction
public function GetClickedItem takes nothing returns item
return ForceKey.TrigItem
endfunction
public function GetClickedDestructable takes nothing returns destructable
return ForceKey.TrigDestructable
endfunction
public function IsObjectClicked takes nothing returns boolean
return ForceKey.Object
endfunction
public function IsGroundClicked takes nothing returns boolean
return not ForceKey.Object
endfunction
public function SpecialClicked takes nothing returns boolean
return ForceKey.Special
endfunction
public function NormalClicked takes nothing returns boolean
return ForceKey.Normal
endfunction
endlibrary
Example:
JASS:
scope ForceKeyUse initializer INIT
globals
private player PLAYER = Player(0)
endglobals
private function onClickEx takes nothing returns boolean
local string s = ""
if ForceKey.Special then
set s = "special-"
else
set s = "normal-"
endif
if ForceKey.Object then
if ForceKey.TrigUnit != null then
call BJDebugMsg("JASS ForceKey: You "+s+"clicked " + GetUnitName(ForceKey.TrigUnit))
elseif ForceKey.TrigDestructable != null then
call BJDebugMsg("JASS ForceKey: You "+s+"clicked " + GetDestructableName(ForceKey.TrigDestructable))
elseif ForceKey.TrigItem != null then
call BJDebugMsg("JASS ForceKey: You "+s+"clicked " + GetItemName(ForceKey.TrigItem))
else
call BJDebugMsg("Unknown Object")
endif
return false
endif
call BJDebugMsg("JASS ForceKey: You "+s+"clicked " + R2S(ForceKey.TrigX) + "/" + R2S(ForceKey.TrigY))
return false
endfunction
private function onChatEx takes nothing returns boolean
call ForceKey[PLAYER].switch()
return false
endfunction
private function EscEx takes nothing returns boolean
call ForceKey[PLAYER].forceSpecialOnce()
return true
endfunction
private function INIT takes nothing returns nothing
local trigger onChat = CreateTrigger()
local trigger onClick = CreateTrigger()
local trigger onEsc = CreateTrigger()
// Force a "special click" by hitting escape
call TriggerRegisterPlayerEvent(onEsc, PLAYER, EVENT_PLAYER_END_CINEMATIC)
call TriggerAddCondition(onEsc,Condition(function EscEx))
// Enable and disable the mode by typing "-StartJASS" and "-StopJASS"
call TriggerRegisterPlayerChatEvent(onChat, Player(0), "-StartJASS", true)
call TriggerRegisterPlayerChatEvent(onChat, Player(0), "-StopJASS", true)
call TriggerAddCondition(onChat , Condition( function onChatEx))
// On click ...
call ForceKey.InitPlayer(PLAYER)
call ForceKey.anyClick.register( onClick )
call TriggerAddCondition( onClick, Condition( function onClickEx ) )
// some other stuff
call BJDebugMsg("Use 039;-StartJASS039;,039;-StopJASS039;, the escape and your left mouse button to test my sys")
set onChat = null
set onClick = null
endfunction
endscope
[/SPOILER]
Changelog:
11-06-2009 Release v1.0
11-13-2009 Big Update: +Special +Design enhanced
11-14-2009 Update: Recoded few things
11-13-2009 Big Update: +Special +Design enhanced
11-14-2009 Update: Recoded few things
Credits to
- Azlier: Idea
- Jesus4Lyf: Event
Criticism is welcome.
Greetings.