using System; using System.Drawing; using System.Collections.Generic; public static class VoiceBotScript { private const string ScriptSettingName = "joystick_mouse"; // The deadzone of the mouse movement, in pixels private const int DeadZone = 20; private static int DeadZoneSquared = DeadZone * DeadZone; // The speed at which the script runs. Each loop will wait for // this many milliseconds (33 is ~30 times a second) private const int IntervalMS = 33; // A enum to keep track of held down keys [Flags] public enum PositionEnum { None = 0, Up = 1 << 0, Down = 1 << 1, Left = 1 << 2, Right = 1 << 3, } // A list to map the index that was calculated by // the angle of the mouse to a joystick position // DO NOT MODIFY THIS public static List IndexToPositionMap = new List() { PositionEnum.Up | PositionEnum.Right, PositionEnum.Right, PositionEnum.Down | PositionEnum.Right, PositionEnum.Down, PositionEnum.Down | PositionEnum.Left, PositionEnum.Left, PositionEnum.Up | PositionEnum.Left, PositionEnum.Up, }; // A dictionary to map the position enum to keys. If you don't want some of these keys to be held // down, leave an empty string as the key ie. {PositionEnum.Up, ""}, but DO NOT REMOVE THE ENTRY! public static Dictionary PositionToKeyMap = new Dictionary() { {PositionEnum.Up, "{UP}"}, {PositionEnum.Down, "{DOWN}"}, {PositionEnum.Left, "{LEFT}"}, {PositionEnum.Right, "{RIGHT}"}, }; private static PositionEnum PressedButtons = PositionEnum.None; public static void Run(IntPtr windowHandle) { // If the script is running, this will set the script to // stop running, and then exit if (BFS.ScriptSettings.ReadValueBool(ScriptSettingName)) { BFS.ScriptSettings.WriteValueBool(ScriptSettingName, false); return; } // If we got this far, that means the script is running BFS.ScriptSettings.WriteValueBool(ScriptSettingName, true); // Check where the mouse was when we started the script int originX = BFS.Input.GetMousePositionX(); int originY = BFS.Input.GetMousePositionY(); // Run the loop while the script should be running while (BFS.ScriptSettings.ReadValueBool(ScriptSettingName)) { // Check how far the mouse is from the origin int x = BFS.Input.GetMousePositionX(); int y = BFS.Input.GetMousePositionY(); int dx = Math.Abs(x - originX); int dy = Math.Abs(y - originY); int m = dx*dx + dy*dy; // If we're inside the dead zone then disable all of the buttons if(m < DeadZoneSquared) { foreach(PositionEnum position in Enum.GetValues()) { // Ignore this value if(position == PositionEnum.None) continue; // Ignore this pass if the button isn't pressed if((PressedButtons & position) != position) continue; // Check if we have a button mapped string key = PositionToKeyMap[position]; if(string.IsNullOrEmpty(key)) continue; // Unpress this button BFS.Input.SendKeyUp(key); } // Set the currently held buttons to none PressedButtons = PositionEnum.None; // Wait for the specified time BFS.General.ThreadWait(IntervalMS); continue; } // Find the angle the cursor is from the origin float theta = MathF.Atan2(y - originY, x - originX); // Fix the angle while (theta < 0) theta += (MathF.PI * 2); // Find the index from the angle int index = ((int)(4f * theta / MathF.PI + 3 / 2f)) % IndexToPositionMap.Count; // Get the position from the index PositionEnum currentPosition = IndexToPositionMap[index]; // Don't bother with anything if we've already held down these buttons if(currentPosition == PressedButtons) { BFS.General.ThreadWait(IntervalMS); continue; } // Fix the held buttons foreach(PositionEnum position in Enum.GetValues()) { if(position == PositionEnum.None) continue; bool isPressed = ((PressedButtons & position) == position); bool shouldBePressed = ((currentPosition & position) == position); // Keep this button held down if(isPressed && shouldBePressed) continue; // Check to see if a button is mapped string key = PositionToKeyMap[position]; if(string.IsNullOrEmpty(key)) continue; // Press this button if(shouldBePressed && !isPressed) BFS.Input.SendKeyDown(key); // Let go of this button if(isPressed && !shouldBePressed) BFS.Input.SendKeyUp(key); } // Store the PressedButtons = currentPosition; // Wait for the specified time BFS.General.ThreadWait(IntervalMS); } // If we got here that means the script has exited. Let go of any held buttons. foreach(PositionEnum position in Enum.GetValues()) { // Ignore this value if(position == PositionEnum.None) continue; // Ignore this pass if the button isn't pressed if((PressedButtons & position) != position) continue; // Check to see if we have a button mapped string key = PositionToKeyMap[position]; if(string.IsNullOrEmpty(key)) continue; // Unpress this button BFS.Input.SendKeyUp(key); } // Set the currently held buttons to none PressedButtons = PositionEnum.None; } }