Skip to content

Instantly share code, notes, and snippets.

@ZerothAngel
Created July 1, 2024 13:26
Show Gist options
  • Select an option

  • Save ZerothAngel/4f54c776fe22e551d86b7dfe145eb6db to your computer and use it in GitHub Desktop.

Select an option

Save ZerothAngel/4f54c776fe22e551d86b7dfe145eb6db to your computer and use it in GitHub Desktop.

Revisions

  1. ZerothAngel created this gist Jul 1, 2024.
    119 changes: 119 additions & 0 deletions Mouselook2.ahk
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,119 @@
    #Requires AutoHotKey v2.0
    #SingleInstance Force
    SendMode "Input"

    ;;; Generic mouse look script, aka action camera
    ;;; * Should work on any game that requires you to hold down a key (such as
    ;;; the right mouse button) to move the camera
    ;;; * By default, caps lock will toggle mouse look mode on or off
    ;;; * When mouse look is enabled, you can press RMB to temporarily release
    ;;; mouse look and get your cursor back. Great for mouseover targeting!
    ;;; * Whenever mouse look is engaged, you can have it center the mouse cursor
    ;;; before it holds down the RMB.
    ;;; * See below if you want to reconfigure things. You might want the AHKv2
    ;;; docs nearby for key names, etc.
    ;;;
    ;;; - ZerothAngel

    ; Keybinds
    MouseLook := "RButton" ; Key to hold down for mouse look. Typically right mouse button (RButton)
    MouseLookToggle := "CapsLock" ; Key to toggle mouse look mode (when on, RMB is inverted)
    AutoCenterToggle := "AppsKey" ; Key to toggle auto-center (auto-centering only happens right before mouse look is toggled on)

    ; Config
    GameWindow := "ahk_class FFXIVGAME" ; How the game window is identified. Use AHK's Window Spy
    AutoCenterState := true ; Current state of auto-center. Nowadays, I like it on by default. Set to false if you don't.
    CenterOffsetX := 100 ; Horizontal pixel offset when centering, positive is toward right
    CenterOffsetY := 200 ; Vertical pixel offset when centering, positive is toward bottom

    ; Note: Whatever offsets you choose above, if you actually do use auto-centering, make sure you can still move the camera
    ; with whatever is under the mouse at that point, i.e. don't choose offsets that place the mouse pointer over UI elements

    ; State
    MouseLookState := false ; true if RMB is currently inverted
    PhysicalMouseLookState := false ; For keeping track of physical RMB state (when not inverted)
    MouseLookCounter := 0 ; Send RMB down on 0 -> 1 only, similarly RMB up on 1 -> 0 only

    ; Hotkeys
    HotIfWinActive GameWindow
    Hotkey AutoCenterToggle, ToggleAutoCenter
    Hotkey MouseLook, PhysicalMouseLookDown
    Hotkey MouseLook " Up", PhysicalMouseLookUp
    Hotkey MouseLookToggle, ToggleMouseLook

    ; Functions
    ToggleAutoCenter(ThisHotKey) {
    global AutoCenterState

    AutoCenterState := !AutoCenterState
    }

    ToggleMouseLook(ThisHotKey) {
    global MouseLookState

    if (MouseLookState) {
    SendMouseLookUp()
    } else {
    CenterMouse()
    SendMouseLookDown()
    }
    MouseLookState := !MouseLookState
    SetCapsLockState false
    }

    CenterMouse() {
    if (AutoCenterState && !PhysicalMouseLookState) {
    BlockInput "MouseMove"
    WinGetPos ,,&WinWidth,&WinHeight,GameWindow
    MouseMove CenterOffsetX+WinWidth/2, CenterOffsetY+WinHeight/2, 1
    BlockInput "MouseMoveOff"
    }
    }

    PhysicalMouseLookDown(ThisHotKey) {
    global PhysicalMouseLookState

    if (MouseLookState) {
    ; Currently inverted, so "release" mouselook
    SendMouseLookUp()
    } else {
    ; Not currently inverted, just behave normally
    SendMouseLookDown()
    ; But also keep track of this click
    PhysicalMouseLookState := true
    }
    }

    PhysicalMouseLookUp(ThisHotKey) {
    global PhysicalMouseLookState

    if (MouseLookState) {
    CenterMouse()
    ; Currently inverted, re-enable mouselook
    SendMouseLookDown()
    } else {
    ; Not currently inverted, just behave normally
    SendMouseLookUp()
    }
    PhysicalMouseLookState := false
    }

    SendMouseLookDown() {
    global MouseLookCounter

    ; Send only on edge between 0 -> 1
    if (++MouseLookCounter == 1) {
    Send "{" MouseLook " down}"
    }
    MouseLookCounter := Min(MouseLookCounter, 1) ; Saturate at 1
    }

    SendMouseLookUp() {
    global MouseLookCounter

    ; Send only on edge between 1 -> 0
    if (--MouseLookCounter == 0) {
    Send "{" MouseLook " up}"
    }
    MouseLookCounter := Max(MouseLookCounter, 0) ; Sanity
    }