#Persistent #NoEnv #SingleInstance force #include xix.ahk #include jphelper.ahk ; ----- xtravar's dragon age 2 gamepad autohotkey script ; Version: 2011.3.31 ; Author: xtravar@yahoo.com ; License: GPLv2 (http://www.gnu.org/licenses/gpl-2.0.html) ; Requires: AutoHotkey_L http://www.autohotkey.com/download/ ; Notes: I'm new at autohotkey AND dragon age so this probably isn't perfect. ; Feel free to send enhancements or suggestions my way. ; You will need to tweak settings below to get things working the way you want. ; If your gamepad does not support XInput, change to WinMM in the settings below. ; Disclaimer: There is no warranty. This has only been tested on Windows 7 64-bit. ; ------------------------------------------------------------------------ ;------------------------------------------------ ; INSTALLATION ;----------------------------------------------- ; 1. Install AutoHotkey_L http://www.autohotkey.com/download/ ; 2. Run this script (da2-gamepad.ahk) ; 3. Copy da2-gamepad-example.ini to da2-gamepad.ini and make changes if necessary. Reload script. ;---------------------------- ; CONFIGURATION INI ;---------------------------- ; There are a few mouse settings - invert axes, speed, etc. ; Then there is the button mapping section if you do not have an XInput gamepad. ; ------------------------------------------------ ; BUTTONS ; ------------------------------------------------ ; THIS SCRIPT ASSUMES THE DEFAULT DA2 KEYS ; ; BUTTONS ; Left Trigger - left mouse button / (LB+RB) Quick Save ; Right Trigger - right mouse button / (LB+RB) Quick Load ; Left Bumper - Hold to change button meanings ; Right Bumper - Hold to change button meanings ; Left Thumb Click - Toggle showing names (holds tab) ; Right Thumb Click - Toggle between gamepad mode 0 and 1 ; DPad - Switch character ; Left Thumb Axis - Moves character (wqse) - wasd in mode 0 ; Right Thumb Axis (Mode 0) - Move the mouse cursor ; Right Thumb Axis (Mode 1) - Look around (right click drag) ; A - Attack/loot nearest ; X, Y, B - Skills 1, 2 3 / (LB) 4, 5, 6 / (RB) 7, 8, 9 / (LB+RB) 0, quick heal, quick mana ; Back - Main Menu (escape) / (LB) Journal / (RB) Map / (LB+RB) Tactics ; Start - Pause / (LB) Character / (RB) Inventory / (LB+RB) Abilities ;----------------------------------------------- ; Changes ;----------------------------------------------- ; Release 2011.3.31 ; - Add: INI file support ; - Add: Automatically detect gamepad API, guess what buttons to map ; - Add: Support non-analog triggers ; - Clean up some mouse stuff, remove sendmouse.ahk ; - Change some variable/function names ; Release 2011.3.28 ; - Add: Support non-XInput gamepads via WinMM ; - Fix: documentation on DPAD was incorrect ; - Change: inverse of mode 1 ; - Change: default mouse sensitivity of mode 0 ; - Fix: change to mode 0 when going to char/map/etc but not reverse and not menu/pause ; - Add: Quick Save and Quick Load ; Release 2011.3.27 ; - Initial release ; ----------------------------------------------- ; Non-programmers should not go below this line ; -------------------------------------- GPMODES := 2 GPMODE := 0 AMODE := 0 DA2_ACTIVE := 0 DA2_ReadINI("da2-gamepad.ini") XIX_ReadINI("da2-gamepad.ini") SetTimer, DA2_Watch, 250 if(0) { DA2_Watch: active := WinActive("Dragon Age II") if(active == DA2_ACTIVE) { return } if(active) { JP_Init() XIX_BeginWatching(10) WinGetActiveStats, t, RES_X, RES_Y, x, y POSX_0 := RES_X / 2 POSY_0 := RES_Y / 2 POSX_1 := RES_X / 2 POSY_1 := RES_Y } else { XIX_EndWatching() } DA2_ACTIVE := active return } ToMode(mode) { global if(mode == -1) { mode = LASTMODE } else { mode := mod(mode,GPMODES) } if(GPMODE == mode) { return } LASTMODE := GPMODE ; uncomment to save mode 0 pos ;if(GPMODE == 0) { ; MouseGetPos, POSX_0, POSY_0 ;} GPMODE := mode x := POSX_%GPMODE% y := POSY_%GPMODE% MouseMove, x, y, 0 } XIX_ButtonDPadUp(state) { global JP_PressKey(state,"F3") } XIX_ButtonDPadDown(state) { global JP_PressKey(state,"F1") } XIX_ButtonDPadLeft(state) { global JP_PressKey(state,"F2") } XIX_ButtonDPadRight(state) { global JP_PressKey(state,"F4") } ;cjipm/ XIX_ButtonStart(state) { global AMODE,GPMODE mode := GPMODE if(AMODE == 0) { key := "Space" } else if(AMODE == 1) { key := "c" mode := 0 } else if(AMODE == 2) { key := "i" mode := 0 } else if(AMODE == 3) { key := "p" mode := 0 } JP_PressKey(state,key) ToMode(mode) } XIX_ButtonBack(state) { global AMODE,GPMODE mode := GPMODE if(AMODE == 0) { key := "Escape" } else if(AMODE == 1) { key := "j" mode := 0 } else if(AMODE == 2) { key := "m" mode := 0 } else if(AMODE == 3) { key := "\" mode := 0 } JP_PressKey(state,key) ToMode(mode) } XIX_ButtonLeftThumb(state) { static tabState := 0 if(state != 0) { return } dir := tabState ? "Up" : "Down" Send {Tab %dir%} tabState := !tabState } XIX_ButtonRightThumb(state) { global if(state != 0) { return } ToMode(GPMODE + 1) } XIX_ButtonLeftShoulder(state) { global AMODE if(state == 0) { AMODE := AMODE | 1 } else if(state == 2) { AMODE := AMODE & 2 } } XIX_ButtonRightShoulder(state) { global AMODE if(state == 0) { AMODE := AMODE | 2 } else if(state == 2) { AMODE := AMODE & 1 } } XIX_ButtonA(state) { JP_PressKey(state,"r") } XIX_ButtonX(state) { global AMODE if(AMODE == 0) { key := "1" } else if(AMODE == 1) { key := "4" } else if(AMODE == 2) { key := "7" } else if(AMODE == 3) { key := "0" } JP_PressNow(state, key) } XIX_ButtonY(state) { global AMODE if(AMODE == 0) { key := "2" } else if(AMODE == 1) { key := "5" } else if(AMODE == 2) { key := "8" } else if(AMODE == 3) { key := "-" } JP_PressNow(state, key) } XIX_ButtonB(state) { global AMODE if(AMODE == 0) { key := "3" } else if(AMODE == 1) { key := "6" } else if(AMODE == 2) { key := "9" } else if(AMODE == 3) { key := "=" } JP_PressNow(state, key) } XIX_LeftTrigger(state,value) { global if(AMODE == 3) { JP_PressNow(state, "F5") } else { JP_Click(state,"Left") } } XIX_RightTrigger(state,value) { global if(AMODE == 3) { JP_PressNow(state, "F9") } else { JP_Click(state,"Right") } } XIX_LeftThumb(state,x,y) { global GPMODE static CurKeyLX, CurKeyLY if(GPMODE) { JP_KeyXY(CurKeyLX, CurKeyLY, x, y, "q", "s", "e", "w") } else { JP_KeyXY(CurKeyLX, CurKeyLY, x, y, "a", "s", "d", "w") } } RT_Mode0(state,x,y) { global if(x > 0) { x := x - XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE } else if(x < 0) { x := x + XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE } if(y > 0) { y := y - XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE } else if(y < 0) { y := y + XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE } x := x / 24078 y := y / 24078 SPEED := AMODE ? _da2_0RS : _da2_0RF JP_MouseMove(state, _da2_0RXI * x * SPEED, _da2_0RYI * y * SPEED) } RT_Mode1(state,x,y) { global stepX := JP_NegClamp(x*_da2_1RXI,_da2_RSZ,_da2_1RS,_da2_1RF) stepY := JP_NegClamp(y*_da2_1RYI,_da2_RSZ,_da2_1RS,_da2_1RF) JP_MouseMove(state,stepX,stepY,"Right") if(state == 2) { MouseMove, POSX_1, POSY_1, 0 } } XIX_RightThumb(state,x,y) { global GPMODE RT_Mode%GPMODE%(state,x,y) } IniReadInvert(file, name, def) { val := IniRead(file, name, def) return val == 0 ? 1 : -1 } IniRead(file, name, def) { IniRead, var, %file%, DA2_Gamepad_Settings, %name%, %def% return var } DA2_ReadINI(file) { global _da2_0RXI := IniReadInvert(file, "Mode0_RightThumb_InvertX", 0) _da2_0RYI := IniReadInvert(file, "Mode0_RightThumb_InvertY", 1) _da2_0RS := IniRead(file, "Mode0_RightThumb_SlowSpeed", 1) _da2_0RF := IniRead(file, "Mode0_RightThumb_FastSpeed", 15) _da2_1RXI := IniReadInvert(file, "Mode1_RightThumb_InvertX", 0) _da2_1RYI := IniReadInvert(file, "Mode1_RightThumb_InvertY", 0) _da2_1RS := IniRead(file, "Mode1_RightThumb_SlowSpeed", 2) _da2_1RF := IniRead(file, "Mode1_RightThumb_FastSpeed", 8) _da2_RSZ := IniRead(file, "RightThumbSlowThreshold", XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE * 3) }