[Home] [Downloads] [Search] [Help/forum]

Gammon Forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Tips and tricks
. . -> [Subject]  Logitech G15 modifier keys
Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?

Logitech G15 modifier keys

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Posted by Ked   Russia  (524 posts)  [Biography] bio
Date Mon 01 Dec 2008 02:42 AM (UTC)
Message
This is for those of us who happen to own a Logitech G15 keyboard.

I've always found the default behaviour of the G keys to be rather limited, since there are only 18 of them, so you have to move your hand back and forth between the main qwerty set of keys and the macro one all the time. So instead, I use G keys as modifiers for the numpad. This gives me a much greater number of macros and lets me group commands according to the type of action.

For example, I can move in several different ways: leap, walk, sprint, fly. By assigning each method of movement to a G key (G13 for leaping, G14 for flying, etc) I can switch movement methods with those keys, while still using the numpad for actually moving around.

Previously, getting this to work involved some tedious and ugly hacking in G15's macro editor but the 2nd version of the firmware introduced Lua scripting, which makes this much simpler and more flexible.

All you have to do to set this up on the keyboard's side is copy/paste the following snippet into Logitech's script editor for your Mushclient profile:


function OnEvent(event, arg)
	--OutputLogMessage("event = %s, arg = %s\n", event, arg);
    if event == "G_PRESSED" then
        PressKey(0x1d, 0x38)
        PressAndReleaseKey("a")
        ReleaseKey(0x1d, 0x38)
        local m,g = tostring(GetMKeyState()), tostring(arg)
        PressAndReleaseKey("m", m, "k")
        string.gsub(g, "(%d)", function(mt) PressAndReleaseKey(mt) end)
        PressAndReleaseKey("enter")
        PressKey(0x1d, 0x38)
    elseif event == "G_RELEASED" then
        ReleaseKey(0x1d, 0x38)
        local m,g = tostring(GetMKeyState()), tostring(arg)
        PressAndReleaseKey("e", m, "k")
        string.gsub(g, "(%d)", function(mt) PressAndReleaseKey(mt) end)
        PressAndReleaseKey("enter")
        PressKey(0x1d, 0x38)
        PressAndReleaseKey("z")
        ReleaseKey(0x1d, 0x38)
    end
end


Save it and assign "Script" to all the G keys in the profile.

On Mushclient's side you need to install the plugin below and edit the modifier rule tables, as explained in the plugin's description.
[Go to top] top

Posted by Ked   Russia  (524 posts)  [Biography] bio
Date Reply #1 on Mon 01 Dec 2008 02:43 AM (UTC)

Amended on Mon 01 Dec 2008 02:49 AM (UTC) by Ked

Message
Plugin:


<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<muclient>
<plugin
   name="Keyboard"
   author="Keldar"
   id="3c3ef7503f44b4b76d89c99e"
   language="Lua"
   purpose="Logitech G15 macros"
   save_state="y"
   date_written="2008-11-30"
   requires="4.00"
   version="1.0"
   >
   
<description trim="y">
<![CDATA[
Commands:

  bind keys       -  bind all G modifiers
  unbind keys     -  unbind all G modifiers

Notes:
  
Replace the 'modes' table with your own. The 
keys in this table are strings describing G
modifiers, of the form "m#k#", where "m#" stands
for the M mode selected and "k#" - number of the
pressed G key. 

Values are tables keyed by strings describing 
numpad keys with values holding alias strings to
be executed when the corresponding numpad key is 
pressed.

To combine G modifiers together, concatenate their
labels with "+", placing them in the resulting 
string in ascending order wrt the G key's number.
For  example, to make G7 and G8 to work as a single 
modifier in M1 you'd use the string "m1k7+m1k8". 
The table containing rules for multiple modifiers 
is "multi_modes". It contains an example rule for 
G1+G2.

There are no limits on the number of G keys used
together in a single modifier, though 2 or 3 are 
probably the physically usable maximum. You should
also not mix M modes in multiple modifiers, meaning
that "m1k1+m2k2" isn't guaranteed to work.
]]>
</description>
</plugin>


<aliases>
  <alias
   script="BindKeys"
   match="^\s*bind\s+keys\s*$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
  <alias
   script="UnbindKeys"
   match="^\s*unbind\s+keys\s*$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
</aliases>
<aliases>
  <alias
   script="pressG15"
   match="^g15start$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
</aliases>
<aliases>
  <alias
   script="releaseG15"
   match="^g15end$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
</aliases>
<aliases>
  <alias
   script="BoundCall"
   match="^(NUM.)$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
</aliases>
<!--  Script  -->


<script>
<![CDATA[

modes = {

m1k7 = {
    desc = "Axethrow",
    ["NUM8"]   = "thn",
    ["NUM9"]   = "thne",
    ["NUM7"]   = "thnw",
    ["NUM4"]   = "thw",
    ["NUM6"]   = "the",
    ["NUM1"]   = "thsw",
    ["NUM2"]   = "ths",
    ["NUM3"]   = "thse",
    ["NUM-"]   = "thup",
    ["NUM+"]   = "thd",
    ["NUM/"]   = "thi",
    ["NUM*"]   = "tho",
    ["NUM5"]   = "thp"
},
}

multi_modes = {

["m1k1+m1k2"] = {
    desc = "Test",
    ["NUM7"]         = "cl nw",
    ["NUM8"]         = "cl n",
    ["NUM9"]         = "cl ne",
    ["NUM4"]         = "cl w",
    ["NUM6"]         = "cl e",
    ["NUM1"]         = "cl sw",
    ["NUM2"]         = "cl s",
    ["NUM3"]         = "cl se",
    ["NUM/"]         = "cl in",
    ["NUM*"]         = "cl out",
    ["NUM-"]         = "cl up",
    ["NUM+"]         = "cl down",
    ["NUM5"]         = "rl",
},

}



keypad = {
  ["Divide"]             = "NUM/",
  ["Multiply"]           = "NUM*",
  ["Subtract"]           = "NUM-",
  ["Add"]                = "NUM+",
  ["Numpad7"]            = "NUM7",
  ["Numpad8"]            = "NUM8",
  ["Numpad9"]            = "NUM9",
  ["Numpad4"]            = "NUM4",
  ["Numpad5"]            = "NUM5",
  ["Numpad6"]            = "NUM6",
  ["Numpad1"]            = "NUM1",
  ["Numpad2"]            = "NUM2",
  ["Numpad3"]            = "NUM3",
  ["Numpad0"]            = "NUM0",
  ["Decimal"]            = "NUM."
}

function BindKeys()
    AcceleratorTo("Ctrl+Alt+a", "", 0)
    AcceleratorTo("Ctrl+Alt+a", "g15start", sendto.execute)
    AcceleratorTo("Ctrl+Alt+z", "g15end", sendto.execute)

  	for k,v in pairs(keypad) do
  		AcceleratorTo("Ctrl+Alt+" .. k, "", 0)
		AcceleratorTo("Ctrl+Alt+" .. k, v, sendto.execute) 
  	end
  	print("All keybindings set.")
end

function UnbindKeys()
    AcceleratorTo("Ctrl+Alt+a", "", 0)
    AcceleratorTo("Ctrl+Alt+z", "", 0)
  	for k,v in pairs(keypad) do
  		AcceleratorTo("Ctrl+Alt+" .. k, "", 0)
  	end
    print("All keybindings cleared.")
end

input = ""
state = {}
state.pressed = 0

function saveInput()
    if state.pressed == 1 then
        SelectCommand()
        input = PasteCommand("")    
        OnPluginCommandEntered = opce
    end
end

function restoreInput()
    if state.pressed == 0 then
        SelectCommand()
        PasteCommand(input)
        OnPluginCommandEntered = opceNull
    end
end


function pressG15()
    state.pressed = state.pressed + 1
    saveInput()
end

function releaseG15()
    state.pressed = state.pressed - 1
    restoreInput()
end

function g15command(wildcs)
    if wildcs[2] == "m" then
        state[wildcs[1]] = true
    elseif wildcs[2] == "e" then
        state["m" .. wildcs[3] .. "k" .. wildcs[4]] = nil
    end
end

function modString()
    local t = {}
    for k,_ in pairs(state) do
        if k ~= "pressed" then
            table.insert(t, k)
        end
    end
    local sorter = function(a,b) 
        local sa,ea,ka = string.find(a, "^m%dk(%d+)$")
        local sb,eb,kb = string.find(b, "^m%dk(%d+)$")
        if sa and sb then
            return tonumber(ka) < tonumber(kb)
        end
    end
    table.sort(t,sorter)
    return t
end

function BoundCall(name, outp,wildcs)
    local mods = table.concat(modString(), "+")
    if state.pressed > 1 then
        if multi_modes[mods] then
            Execute(multi_modes[mods][wildcs[0]])
        end
    else
        if modes[mods] then
            Execute(modes[mods][wildcs[0]])
        end
    end
end

function clearInput()
    SelectCommand()
    PushCommand("")
end

function opce(stxt)
    local s,e,w1,w2,w3,w4 = string.find(stxt, "^(([me])([1-3])k(%d+))")
    if s then g15command({w1,w2,w3,w4}) end
    clearInput()
    return "\t"
end

function opceNull(stxt)
    return stxt
end

OnPluginCommandEntered = opceNull

BindKeys()
]]>
</script>

</muclient>
[Go to top] top

Posted by Nick Gammon   Australia  (21,402 posts)  [Biography] bio   Forum Administrator
Date Reply #2 on Mon 01 Dec 2008 03:15 AM (UTC)
Message
Lua scripting on the G15? Wow!

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


7,304 views.

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at FutureQuest]