Skip to content

Instantly share code, notes, and snippets.

@asaf400
Last active August 17, 2023 23:46
Show Gist options
  • Save asaf400/0b238b9ea567c6096f8b666888d6705c to your computer and use it in GitHub Desktop.
Save asaf400/0b238b9ea567c6096f8b666888d6705c to your computer and use it in GitHub Desktop.
Elite Dangerous Fire Groups keybinding with AutoHotKey
; written by https://github.com/asaf400
; version 0.3
; Settings
gameLocation := "H:\SteamLibrary\steamapps\common\Elite Dangerous"
; Change log file location
global LogFile := "H:\SteamLibrary\steamapps\common\Elite Dangerous\AX.log"
; in-game next group button
global nextButton := "n"
global targetButton := "t"
global modeButton := "m"
; game window Title
global gameTitle := "Elite - Dangerous (CLIENT)"
#Persistent
SetKeyDelay, 50
#SingleInstance Force
I_Icon = %gameLocation%\ED.ico
IfExist, %I_Icon%
Menu, Tray, Icon, %I_Icon%
;return
global supportedActionsConfig := {}
supportedActionsConfig.Collector := {type: "Click", target: "None", mode: "Either"}
supportedActionsConfig.Decontamination := {type: "Click", target: "None", mode: "Either"}
supportedActionsConfig.Research := {type: "Click", target: "Preselected", mode: "Either"}
supportedActionsConfig.Repair := {type: "Click", target: "None", mode: "Either"}
supportedActionsConfig.XenoScanner := {type: "Hold", target: "Preselected", hold: 10000, mode: "Either"}
supportedActionsConfig.FieldNeuralyzer := {type: "Click", target: "None", mode: "Combat"}
supportedActionsConfig["D-Scanner"] := {type: "Hold", target: "Preselected", hold: 5500, mode: "Analysis"}
supportedActionsConfig["Comp.Scanner"] := {type: "Hold", target: "Preselected", hold: 5000, mode: "Analysis"}
; Change these values according to your game's settings
global fireGroups := []
fireGroups.Insert({Primary: "Weapon", Secondary: "Weapon"})
fireGroups.Insert({Primary: "Collector", Secondary: "Decontamination"})
fireGroups.Insert({Primary: "Research", Secondary: "Repair"})
fireGroups.Insert({Primary: "XenoScanner", Secondary: "FieldNeuralyzer"})
fireGroups.Insert({Primary: "D-Scanner", Secondary: "Comp.Scanner"})
global currentFireGroup := 1
global currentMode := "Combat"
; Caculate how many times to press 'next group' button (defaults n)
DistanceFromGroup(action)
{
Loop, % fireGroups.Length()
{
index := A_Index
For key, value in fireGroups[index]
{
if (value == action)
{
return, {index: index, key: key}
}
}
}
}
; Press the 'next group' button N amount
MoveToGroup(presses)
{
Loop, % presses
{
Send % nextButton
Sleep, 100
}
}
; Caculate overflow location for returning back (used for debugging only)
LoopAround(change)
{
newGroup := currentFireGroup+change
if (newGroup == fireGroups.Length()+1)
{
currentFireGroup := 1
FileAppend currentFireGroup '%currentFireGroup%' `n, % LogFile
}
else
{
FileAppend, unknown condition `n, % LogFile
FileAppend, %newGroup% `n, % LogFile
}
}
ChangeMode(mode){
if (mode != currentMode and mode != "Either")
{
Send % modeButton
}
}
PerformFire(clickType)
{
clickb := ""
if (clickType == "Primary")
{
FileAppend, Clicking LMB `n, % LogFile
clickb := "left"
}
else if (clickType == "Secondary")
{
FileAppend, Clicking RMB `n, % LogFile
clickb := "right"
}
MouseClick, %clickb%
}
PerformHold(clickType, groupIndex, action)
{
delay := supportedActionsConfig[action].hold
mode := supportedActionsConfig[action].mode
FileAppend, Holding click for '%delay%' `n, % LogFile
clickb := ""
if (clickType == "Primary")
{
FileAppend, Clicking LMB `n, % LogFile
clickb := "Left"
}
else if (clickType == "Secondary")
{
FileAppend, Clicking RMB `n, % LogFile
clickb := "Right"
}
ChangeMode(mode)
Click, %clickb%, , , , Down
Sleep, % delay
Click, %clickb%, , , , Up
ChangeMode(mode)
}
PerformAction(action)
{
; Sadly, it seems that ControlClick which should allow sending keys\clicks to a non-active window
; doesn't work with ED, most likely the devs have blocked non-raw device input maybe, or maybe DirectX has..
; Any ways, this makes sure that at least the keys are not doing anything if ED is not active, but it must remain the active window during action execution!
if not WinActive(gameTitle)
{
return
}
FileAppend, Searching Firegroup for '%action%' `n, % LogFile
moveTo := DistanceFromGroup(action)
moveToIndex := moveTo.index
moveToKey := moveTo.key
moveToPresses := moveToIndex - 1
FileAppend, Scrolling to Firegroup '%moveToIndex%' by pressing 'n' '%moveToPresses%' times `n, % LogFile
MoveToGroup(moveToPresses)
currentFireGroup += moveToPresses
FileAppend, Mouseclicking on currentFireGroup '%currentFireGroup%' `n, % LogFile
if (supportedActionsConfig[action].target == "None")
{
Send % targetButton
}
actionType := supportedActionsConfig[action].type
if (actionType == "Click")
{
PerformFire(moveToKey)
}
else if (actionType == "Hold")
{
PerformHold(moveToKey, moveToIndex, action)
}
FileAppend, returning to DefaultFireGroup `n, % LogFile
moveBack := FireGroups.Length() - moveToIndex + 1
MoveToGroup(moveBack)
LoopAround(moveBack)
return
}
; define hotkeys as actions
~5::
PerformAction("Collector")
return
~6::
PerformAction("Decontamination")
return
~7::
PerformAction("Repair")
return
~8::
PerformAction("Research")
return
~9::
PerformAction("XenoScanner")
return
~0::
PerformAction("FieldNeuralyzer")
return
~\::
PerformAction("D-Scanner")
return
@asaf400
Copy link
Author

asaf400 commented Aug 11, 2023

0.2:
Added active window protection - will only perform the actions if the ED window is focused.

Added ability to hold-down a button,
like for Discovery-Scanner or Comp.Scanner

fixed logging, for some reason, it didn't want to use the gameLocation vairable..

@asaf400
Copy link
Author

asaf400 commented Aug 17, 2023

0.3:
A more generic and easily modifable settings has been introduced in: supportedActionsConfig
Supporting action type, targeting*, mode selection.

* targeting is a bit flawed since there's no in-game button to untarget, so it's up to the user to look in space to an empty region,
in order to deploy limpets that conflict with selected target.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment