前言
我以前寫過類似功能的腳本泌辫,可以使一個鍵發(fā)揮多個鍵的功能,但是代碼較為瑣碎九默,拓展功能時較為麻煩震放,所以這次趁著有空重新整理一下,分享給有需要的朋友荤西。
效果
相信很多朋友都玩過moba類的游戲澜搅,這類游戲中大部分都集成有快速發(fā)信號的功能,即按下一個預設鍵后不要松開邪锌,拖動鼠標到四個不同的方向就可以發(fā)送四種對應的信號勉躺,比如援助、堅守觅丰、危險等饵溅。這種轉盤形式的信號系統(tǒng)簡單直觀,熟悉之后下意識即可完成操作妇萄,而這也正是本篇文章中腳本的靈感來源蜕企。
啟用腳本后按下預設鍵位不要松開咬荷,此時保持不動、向上轻掩、向下幸乒、向左或向右移動鼠標后松開預設鍵即可觸發(fā)五種不同的功能。搭配ctrl
或ctrl
+alt
可以再分別拓展五種功能唇牧,總計15種不同的功能罕扎。理論上配合各種修飾鍵的組合可以實現(xiàn)更多的功能,但是我個人認為沒有必要丐重,一是記不住腔召,二是可能產生鍵位沖突。
實現(xiàn)
編輯鍵位
確保自己的鼠標上有至少一個不用的按鍵扮惦,在對應的配置中將該鍵位禁用臀蛛。此處也可以不禁用,但是后續(xù)在修改腳本模板時需要將鼠標原地不動對應的功能留空崖蜜。
修改腳本
首先給出一個腳本模板:
-- 轉盤移動方向判定的最小鼠標位移
local TURNTABLE_MIN_DISTANCE = 20
-- 修飾鍵狀態(tài)查詢時間間隔
local TURNTABLE_MODIFIER_HEARTBEAT = 10
-- 轉盤兩次觸發(fā)最小時間間隔
local TURNTABLE_MIN_INTERVAL = 50
local turntableLastTriggerTime = GetRunningTime()
local funcs = {
function()
OutputLogMessage("test")
end,
"test",
function()
OutputLogMessage("test")
end,
}
funcs[6] = "test2"
funcs[15] = "test3"
EnablePrimaryMouseButtonEvents(true)
function OnEvent(event, arg)
if (event == "MOUSE_BUTTON_PRESSED" and arg == 7) then
x1, y1 = GetMousePosition()
-- OutputLogMessage("Mouse pressed at %d, %d\n", x1, y1)
end
if (event == "MOUSE_BUTTON_RELEASED" and arg == 7) then
x2, y2 = GetMousePosition()
-- OutputLogMessage("Mouse released at %d, %d\n", x2, y2)
Turntable(x1, y1, x2, y2, funcs)
end
end
function Turntable(x1, y1, x2, y2, funcs)
-- 核驗轉盤上次觸發(fā)時間
if (GetRunningTime() - turntableLastTriggerTime < TURNTABLE_MIN_INTERVAL) then
return
end
-- 定義局部變量
local dx, dy, direction, func
-- 計算鼠標指針位移
dx = x2 - x1
dy = y2 - y1
-- 鼠標移動方向浊仆,1-5分別對應原地、上纳猪、下氧卧、左桃笙、右
direction = 1
if (math.abs(dx) < math.abs(dy) and dy <= -TURNTABLE_MIN_DISTANCE) then
direction = 2
elseif (math.abs(dx) < math.abs(dy) and dy >= TURNTABLE_MIN_DISTANCE) then
direction = 3
elseif (math.abs(dx) > math.abs(dy) and dx <= -TURNTABLE_MIN_DISTANCE) then
direction = 4
elseif (math.abs(dx) > math.abs(dy) and dx >= TURNTABLE_MIN_DISTANCE) then
direction = 5
end
-- 根據(jù)按住修飾鍵的不同修改direction的數(shù)值氏堤,將按鍵功能由5拓展為15
if IsModifierPressed("ctrl") and IsModifierPressed("alt") then
direction = direction + 10
elseif IsModifierPressed("ctrl") then
direction = direction + 5
end
-- 輪詢修飾鍵狀態(tài),所有修飾鍵松開后開始執(zhí)行對應功能
while (IsModifierPressed("ctrl") or IsModifierPressed("alt")) do
Sleep(TURNTABLE_MODIFIER_HEARTBEAT)
end
-- 根據(jù)direction數(shù)值查找對應的功能并觸發(fā)
func = funcs[direction]
-- OutputLogMessage(direction)
if (type(func) == "function") then
func()
elseif (type(func) == "string") then
PlayMacro(func)
end
-- 更新上次觸發(fā)時間
turntableLastTriggerTime = GetRunningTime()
end
具體需要修改的部分見下圖:
代碼解讀
本部分內容可以跳過搏明,只是記錄一下寫代碼時的思路和解決方法鼠锈,對于有興趣自己編寫羅技Lua腳本的朋友可以隨便看看。
羅技的G HUB驅動雖然支持Lua腳本星著,但是這么多年過去了也沒啥突破购笆,還是一個半成品,各種問題很多虚循。
首先要吐槽的一點就是字符串不支持中文同欠,所有定義到變量中的字符串都會被識別為“?”,這一點可以通過sting.byte函數(shù)來驗證横缔。這就直接導致我想要將中文轉為unicode編碼通過WinCompose軟件直接輸出到文本編輯器中的計劃破滅铺遂。雖然羅技驅動中通過編寫宏的方式也可以直接輸出中文字符,但是這就少了在代碼中即時生成字符串的靈活性茎刚。而且實測該種方法輸出的字符在WPS軟件中會出現(xiàn)未知錯誤襟锐,輸出的字符串皆為第一個字符的重復。
羅技的腳本是單線程運行的膛锭,希望各位在編寫腳本時牢記心頭粮坞。其實之前看到過一篇文章蚊荣,該作者自己寫了一個包實現(xiàn)了并行的效果,但我沒仔細研究莫杈,一是懶互例,二是覺得真沒必要,寫個鼠標腳本不必如此深入筝闹。單線程帶來的最大問題就是Sleep函數(shù)以及while循環(huán)要慎用敲霍。以我上面的代碼為例,我為了防止按下修飾鍵對轉盤功能的影響丁存,將功能響應放在了松開所有修飾鍵后肩杈。這樣設計主要是考慮到如下場景:將按下ctrl
并按住轉盤鍵向上滑動的功能設置為按一下S
,如果沒有上面的設計解寝,就會變?yōu)?code>ctrl+S
這一保存的快捷鍵扩然。這樣設計的初衷是好的,但是會帶來一個問題聋伦,那就是如果我在按住ctrl
后多次按下轉盤鍵夫偶,就會因為代碼中輪詢修飾鍵狀態(tài)而使所有的按鍵事件卡在一起結算。換個說法觉增,第一次轉盤鍵松開后進入while循環(huán)兵拢,之后的每次按鍵都會等待該while循環(huán)結束后再依次執(zhí)行,表現(xiàn)出來的效果就是只有第一次按鍵執(zhí)行了正確的功能逾礁,后面的每一次按鍵功能都會變?yōu)閒uncs[1]说铃。為了解決這一弊端,我不得不又引入了執(zhí)行間隔嘹履,也就是轉盤鍵在觸發(fā)一次后必須等待固定時間間隔后才能再次觸發(fā)腻扇。上面兩個操作會帶來一個弊端,就是按下修飾鍵后無法在不松開修飾鍵的情況下觸發(fā)多個不同的功能砾嫉,不過為了兼容性我覺得這點代價還是可以接受的幼苛。如果沒有鍵位沖突的顧慮可以自行將模板中對應的兩部分代碼刪除。
應用
游戲發(fā)言
僅需一個鍵就可以在游戲中實現(xiàn)快速噴人溝通的所有語句焕刮。玩外服時可以將一些類似good try舶沿、we can win、have fun的短句綁定在轉盤鍵上配并,瞬間化身社交達人括荡,帶領團隊走向勝利。
文檔編輯
類似ctrl
+C
荐绝、ctrl
+V
一汽、ctrl
+A
、ctrl
+Z
等常用快捷鍵。
后記
本篇文章并不是針對一無所知的小白編寫的召夹,所有只是簡單寫了下關鍵步驟岩喷,如果看不太懂的話可以先看看我前兩篇文章,里面配圖多一些监憎,可能好懂一點纱意。實在看不明白又有強烈使用需求的朋友可以留言或者私信我,如果你的需求很有意思或者使用場景很經典的話鲸阔,我可能會以你的需求額外寫一篇文章偷霉。