Guest User

Legend of Grimrock 2 hotkey script

a guest
Jan 8th, 2026
28
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Autohotkey 10.32 KB | Gaming | 0 0
  1. ; Legend of Grimrock 2
  2. ;  Ultimate keyboard macros v 0.1
  3. ; Autohotkey Script
  4. ;    by Ben Staniford
  5. ; Original Grimrock 1 script by d32, techzen, Adakos
  6. ; Download Autohotkey at: http://www.autohotkey.com/
  7. #SingleInstance force
  8. SetTitleMatchMode, 2
  9. CoordMode, Mouse,
  10.  
  11. ; This must be set >0 or grimrock won't process the commands properly
  12. SetDefaultMouseSpeed, 2
  13.  
  14. ; ====================================================================================
  15. ; | Global Constants - these should be valid for all screen resolutions              |
  16. ; ====================================================================================
  17.  
  18. ; Workaround.. For some reason, grimrock 2 doesn't register mouseclicks unless you do them multiple times..  8 seems to work reliably
  19. clickMultiplier := 8
  20.  
  21. ; Weapon lock after swap (imposed by grimrock 2)
  22. weaponLockTime := 1000
  23.  
  24. ; relative positions of weapon slots and character bars
  25. dx1l := 0.14 ; X position of 1st and 3rd char left hand
  26. dx2l := 0.62 ; X position of 2nd and 4th char left hand
  27. dx1r := 0.34 ; X position of 1st and 3rd char right hand
  28. dx2r := 0.81 ; X position of 2nd and 4th char right hand
  29. dy1  := 0.32 ; Y position of 1st and 2nd char hands
  30. dy2  := 0.79 ; Y position of 3rd and 4th char hands
  31.  
  32. ; spell book run buttons
  33. xSpellButton7 := 0
  34. ySpellButton7 := 0
  35. xSpellButton4 := 0
  36. ySpellButton4 := 0
  37. xSpellButton1 := 0
  38. ySpellButton1 := 0
  39. xSpellButton8 := 0
  40. ySpellButton8 := 0
  41. xSpellButton5 := 0
  42. ySpellButton5 := 0
  43. xSpellButton2 := 0
  44. ySpellButton2 := 0
  45. xSpellButton9 := 0
  46. ySpellButton9 := 0
  47. xSpellButton6 := 0
  48. ySpellButton6 := 0
  49. xSpellButton3 := 0
  50. ySpellButton3 := 0
  51. xSpellCastingButton := 0
  52. ySpellCastingButton := 0
  53.  
  54. ; character portraits locations
  55. dy1b  := 0.15 ; Y position of 1st and 2nd char portrait
  56. dy2b  := 0.63 ; Y position of 3rd and 4th char portrait
  57.  
  58. ; Hand and position enumerations used as short hand by functions
  59. Left := 1
  60. Right := 2
  61. TopLeft := 1
  62. TopRight := 2
  63. BottomLeft := 3
  64. BottomRight := 4
  65.  
  66. ; ====================================================================================
  67. ; | Helper Functions                                                                 |
  68. ; ====================================================================================
  69.  
  70. ; reads the resolution, determins the corner of characters' rectangle
  71. Init()
  72. {
  73.    global
  74.    sysget, resX, 0
  75.    sysget, resY, 1
  76.    characterHeight := resY * 0.39
  77.    characterWidth := characterHeight / 0.90
  78.    
  79.    characterX := resX-characterWidth
  80.    characterY := resY-characterHeight
  81.  
  82.    ; First rune row in spell book (assuming wizard in bottom left)
  83.    xSpellButton7 := characterX+(characterWidth*dx1l)
  84.    ySpellButton7 := characterY+(characterHeight*(dy2 - 0.1))
  85.    xSpellButton4 := characterX+(characterWidth*dx1l)
  86.    ySpellButton4 := characterY+(characterHeight*dy2)
  87.    xSpellButton1 := characterX+(characterWidth*dx1l)
  88.    ySpellButton1 := characterY+(characterHeight*(dy2 + 0.1))
  89.    
  90.    ; Second row in spell book
  91.    xSpellButton8 := characterX+(characterWidth*(dx1l + 0.09))
  92.    ySpellButton8 := characterY+(characterHeight*(dy2 - 0.1))
  93.    xSpellButton5 := characterX+(characterWidth*(dx1l + 0.09))
  94.    ySpellButton5 := characterY+(characterHeight*dy2)
  95.    xSpellButton2 := characterX+(characterWidth*(dx1l + 0.09))
  96.    ySpellButton2 := characterY+(characterHeight*(dy2 + 0.1))
  97.    
  98.    ; Third row in spell book
  99.    xSpellButton9 := characterX+(characterWidth*(dx1l + 0.18))
  100.    ySpellButton9 := characterY+(characterHeight*(dy2 - 0.1))
  101.    xSpellButton6 := characterX+(characterWidth*(dx1l + 0.18))
  102.    ySpellButton6 := characterY+(characterHeight*dy2)
  103.    xSpellButton3 := characterX+(characterWidth*(dx1l + 0.18))
  104.    ySpellButton3 := characterY+(characterHeight*(dy2 + 0.1))
  105.    
  106.    ; Casting button in spell book
  107.    xSpellCastingButton := characterX+(characterWidth*(dx1l + 0.24))
  108.    ySpellCastingButton := characterY+(characterHeight*dy2)
  109. }
  110.  
  111. Init()
  112.  
  113. StoreMousePos()
  114. {
  115.    global
  116.    MouseGetPos, mX, mY
  117. }
  118.  
  119. RestoreMousePos()
  120. {
  121.    global
  122.    MouseMove, mX, mY
  123. }
  124.  
  125. RightClickAndReturn(x, y)
  126. {
  127.    global
  128.    StoreMousePos()
  129.    MouseClick, right, x, y, clickMultiplier, 2, D
  130.    MouseClick, right, x, y, clickMultiplier, 2, U
  131.    RestoreMousePos()
  132. }
  133.  
  134. SwapAtX(xPos)
  135. {
  136.    global
  137.    BlockInput On
  138.  
  139.    srcX := xPos
  140.    srcY := characterY+(characterHeight*dy2b)
  141.    dstX := xPos
  142.    dstY := characterY+(characterHeight*dy1b)
  143.  
  144.    ; Click, drag and unclick
  145.    MouseMove, srcX, srcY
  146.    MouseClick, left, srcX, srcY, clickMultiplier, 2, D
  147.    MouseClickDrag, left, srcX, srcY, dstX, dstY
  148.    MouseClick, left, dstX, dstY, clickMultiplier, 2, U
  149.  
  150.    BlockInput Off
  151. }
  152.  
  153. AttackWithHand(Hand, Position)
  154. {
  155.     global
  156.     xPos := 0
  157.     yPos := 0
  158.  
  159.     StoreMousePos()
  160.  
  161.     if (Hand = Right)
  162.     {
  163.         if (Position = TopLeft)
  164.         {
  165.             xPos := dx1l
  166.             yPos := dy1
  167.         }
  168.         else if (Position = TopRight)
  169.         {
  170.             xPos := dx2l
  171.             yPos := dy1
  172.         }
  173.         else if (Position = BottomLeft)
  174.         {
  175.             xPos := dx1l
  176.             yPos := dy2
  177.         }
  178.         else if (Position = BottomRight)
  179.         {
  180.             xPos := dx2l
  181.             yPos := dy2
  182.         }
  183.     }
  184.     else
  185.     {
  186.         if (Position = TopLeft)
  187.         {
  188.             xPos := dx1r
  189.             yPos := dy1
  190.         }
  191.         else if (Position = TopRight)
  192.         {
  193.             xPos := dx2r
  194.             yPos := dy1
  195.         }
  196.         else if (Position = BottomLeft)
  197.         {
  198.             xPos := dx1r
  199.             yPos := dy2
  200.         }
  201.         else if (Position = BottomRight)
  202.         {
  203.             xPos := dx2r
  204.             yPos := dy2
  205.         }
  206.     }
  207.  
  208.     RightClickAndReturn(characterX+(characterWidth*xPos),  characterY+(characterHeight*yPos))
  209.     RestoreMousePos()
  210. }
  211.  
  212. CharacterSwapWeapons(Position)
  213. {
  214.     global
  215.  
  216.     xPos := 0
  217.     yPos := 0
  218.  
  219.     if (Position = TopLeft)
  220.     {
  221.         xPos := dx1r
  222.         yPos := dy1
  223.     }
  224.     else if (Position = TopRight)
  225.     {
  226.         xPos := dx2r
  227.         yPos := dy1
  228.     }
  229.     else if (Position = BottomLeft)
  230.     {
  231.         xPos := dx1r
  232.         yPos := dy2
  233.     }
  234.     else if (Position = BottomRight)
  235.     {
  236.         xPos := dx2r
  237.         yPos := dy2
  238.     }
  239.  
  240.     xPix := characterX+(characterWidth*xPos)
  241.     yPix := characterY+(characterHeight*yPos)
  242.  
  243.     StoreMousePos()
  244.     MouseMove, xPix, yPix
  245.     Send {x}
  246.     Sleep 100
  247.     RestoreMousePos()
  248. }
  249.  
  250. Swap(Side)
  251. {
  252.    global
  253.    StoreMousePos()
  254.  
  255.    if (Side = Left)
  256.    {
  257.       SwapAtX(characterX+(characterWidth*dx1r))
  258.    }
  259.    else
  260.    {
  261.       SwapAtX(characterX+(characterWidth*dx2r))
  262.    }
  263.  
  264.    RestoreMousePos()
  265. }
  266.  
  267. SwapAndAttack(Side)
  268. {
  269.    global
  270.  
  271.    Swap(Side)
  272.    Sleep weaponLockTime
  273.  
  274.    if (Side = Left)
  275.    {
  276.       AttackWithHand(Right, TopLeft)
  277.    }
  278.    else
  279.    {
  280.       AttackWithHand(Right, TopRight)
  281.    }
  282. }
  283.  
  284. ClickSpellRune(KeyPadNumber)
  285. {
  286.     global
  287.  
  288.     xPos := 0
  289.     yPos := 0
  290.  
  291.     if (KeyPadNumber = 1)
  292.     {
  293.         xPos := xSpellButton1
  294.         yPos := ySpellButton1
  295.     }
  296.     else if (KeyPadNumber = 2)
  297.     {
  298.         xPos := xSpellButton2
  299.         yPos := ySpellButton2
  300.     }
  301.     else if (KeyPadNumber = 3)
  302.     {
  303.         xPos := xSpellButton3
  304.         yPos := ySpellButton3
  305.     }
  306.     else if (KeyPadNumber = 4)
  307.     {
  308.         xPos := xSpellButton4
  309.         yPos := ySpellButton4
  310.     }
  311.     else if (KeyPadNumber = 5)
  312.     {
  313.         xPos := xSpellButton5
  314.         yPos := ySpellButton5
  315.     }
  316.     else if (KeyPadNumber = 6)
  317.     {
  318.         xPos := xSpellButton6
  319.         yPos := ySpellButton6
  320.     }
  321.     else if (KeyPadNumber = 7)
  322.     {
  323.         xPos := xSpellButton7
  324.         yPos := ySpellButton7
  325.     }
  326.     else if (KeyPadNumber = 8)
  327.     {
  328.         xPos := xSpellButton8
  329.         yPos := ySpellButton8
  330.     }
  331.     else if (KeyPadNumber = 9)
  332.     {
  333.         xPos := xSpellButton9
  334.         yPos := ySpellButton9
  335.     }
  336.     else if (KeyPadNumber = 0)
  337.     {
  338.         xPos := xSpellCastingButton
  339.         yPos := ySpellCastingButton
  340.     }
  341.  
  342.     RightClickAndReturn(xPos, yPos)
  343. }
  344.  
  345. ; Should draw a box around all 4 characters
  346. RunCharacterBoxTest()
  347. {
  348.    global
  349.    StoreMousePos()
  350.    MouseMove, characterX, resY-10, 6
  351.    MouseMove, characterX, characterY, 6
  352.    MouseMove, resX-10, characterY, 6
  353.    MouseMove, resX-10, resY-10, 6
  354.    MouseMove, characterX, resY-10, 6
  355.    RestoreMousePos()
  356. }
  357.  
  358. ; Should visit all the runes on the spell book
  359. RunSpellBookTest()
  360. {
  361.    global
  362.  
  363.    StoreMousePos()
  364.    
  365.    ; Up the first row
  366.    MouseMove, xSpellButton1, ySpellButton1, 6
  367.    MouseMove, xSpellButton4, ySpellButton4, 6
  368.    MouseMove, xSpellButton7, ySpellButton7, 6
  369.  
  370.    ; Down the second row
  371.    MouseMove, xSpellButton8, ySpellButton8, 6
  372.    MouseMove, xSpellButton5, ySpellButton5, 6
  373.    MouseMove, xSpellButton2, ySpellButton2, 6
  374.  
  375.    ; Up the third row
  376.    MouseMove, xSpellButton3, ySpellButton3, 6
  377.    MouseMove, xSpellButton6, ySpellButton6, 6
  378.    MouseMove, xSpellButton9, ySpellButton9, 6
  379.  
  380.    MouseMove, xSpellCastingButton, ySpellCastingButton, 6
  381.  
  382.    RestoreMousePos()
  383. }
  384.  
  385. ; ====================================================================================
  386. ; | Key mappings                                                                     |
  387. ; ====================================================================================
  388. #IfWinActive Grimrock ahk_class EWindowClass
  389.  
  390. ; Bring up the inventory
  391. i::1
  392.  
  393. ; Attack commands for all character/hand combinations
  394. j::AttackWithHand(Right, TopLeft)
  395. k::AttackWithHand(Right, TopRight)
  396. m::AttackWithHand(Right, BottomLeft)
  397. ,::AttackWithHand(Right, BottomRight)
  398. l::AttackWithHand(Left, TopLeft)
  399. `;::AttackWithHand(Left, TopRight)
  400. .::AttackWithHand(Left, BottomLeft)
  401. /::AttackWithHand(Left, BottomRight)
  402.  
  403. ; Swap characters
  404. 9::Swap(Left)
  405. 0::Swap(Right)
  406.  
  407. ; Swap characters and attack on either side
  408. o::SwapAndAttack(Left)
  409. p::SwapAndAttack(Right)
  410.  
  411. ; Swap both left and right chars
  412. Capslock::
  413. {
  414.    Swap(Left)
  415.    Swap(Right)
  416.    return
  417. }
  418.  
  419. ; Weapon set swap keys
  420. f1::CharacterSwapWeapons(TopLeft)
  421. f2::CharacterSwapWeapons(TopRight)
  422. f3::CharacterSwapWeapons(BottomLeft)
  423. f4::CharacterSwapWeapons(BottomRight)
  424.  
  425. ; Num pad open the spell book by pressing +
  426. NumpadAdd::AttackWithHand(Right, BottomLeft)
  427. ; Num pad access to the spell book (assumes wizard is bottom left and is using left hand for spells)
  428. Numpad1::ClickSpellRune(1)
  429. Numpad2::ClickSpellRune(2)
  430. Numpad3::ClickSpellRune(3)
  431. Numpad4::ClickSpellRune(4)
  432. Numpad5::ClickSpellRune(5)
  433. Numpad6::ClickSpellRune(6)
  434. Numpad7::ClickSpellRune(7)
  435. Numpad8::ClickSpellRune(8)
  436. Numpad9::ClickSpellRune(9)
  437. ; Pressing 0 casts the spell
  438. Numpad0::ClickSpellRune(0)
  439.  
  440. ; Hit control-t to check that the character box constants are correct for your monitor (This will move the mouse around your character box)
  441. ^t::RunCharacterBoxTest()
  442.  
  443. ; Hit control-s to check that the spell book constants are correct for your monitor (This will move the mouse around the spell book assuming your wizard is bottom left)
  444. ^s::RunSpellBookTest()
  445.  
  446. #IfWinActive
  447.  
Add Comment
Please, Sign In to add comment