[Bot] movement other than CTM menu

User Tag List

Page 2 of 3 FirstFirst 123 LastLast
Results 16 to 30 of 43
  1. #16
    mongoosed's Avatar Member
    Reputation
    1
    Join Date
    Feb 2007
    Posts
    55
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes Main that is what i did awhile back when I was doing navigation without writing to memory. I tested the pi radians per sec and then used timed key sends to navigate. It worked pretty well but it took a lot of work to work the bugs and incorrect math out of.

    [Bot] movement other than CTM
  2. #17
    klucky's Avatar Member
    Reputation
    1
    Join Date
    Jun 2009
    Posts
    11
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Mhh maybe you can make your own klick to move by klicking on the screen.

    If you set the Camera to "never adjust" and look on your character from the top you can calculate (with the angle and actual position) where you mouse must click on the screen to move to a specific point (which is not too far away).

  3. #18
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This actually brings up an interesting question. What is the consensus on the best turning system for Wow?

    I currently use instant turns, and obviously it's great from the perspective that I have no concept of "angular velocity" whatsoever -- I just point in the "right" direction. I have carefully crafted routines to make sure I don't turn "too" often (esp. to avoid path flapping, which looks very bot-like). I've never heard of anyone being banned for this (?) since I don't know how they could detect it (without a player observing it and complaining, which I'm also careful to avoid) -- AFAIK, turns are almost entirely handled client-side.

    That being said, do most people use CTM? I've considered moving to a blend of CTM and insta-facing; I like CTM because of the smooth, human-like splines it produces. I suppose I could reverse-engineer the splining algorithm, but if I'm going to reintroduce the complexity of turning speed into my algorithm, I'd rather just do CTM and let the game do the math.

    Thoughts?
    Don't believe everything you think.

  4. #19
    BoogieManTM's Avatar Active Member
    Reputation
    52
    Join Date
    May 2008
    Posts
    193
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I always used instant facing via MSG_MOVE_SET_FACING. seemed to work the best, and that's how facing with the mouse works anyways (which is almost always how i changed orientation when playing the game as well)

  5. #20
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah I pretty much assumed that since mouse-look uses a series of small instant-turns, you're pretty safe doing perfect turns. I still wish I could figure out how to spline-move.
    Don't believe everything you think.

  6. #21
    SKU's Avatar Contributor
    Reputation
    306
    Join Date
    May 2007
    Posts
    565
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Build 2 natural/clamped cubic splines from the waypoint data generated by your navmesh/whatever and then do small instant-turns at each newly interpolated location (depending on the implementation [ BLAS, e.g. BLAS ] you should be able to get a very smooth path without performance hits).

  7. #22
    JRockwater's Avatar Private
    Reputation
    1
    Join Date
    Dec 2010
    Posts
    4
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    For a relatively primitive bot I wrote for a different MMO, I did this exactly how you are envisioning. Using the turn left/right and move-forward keys in conjunction with the "press to slow walk" key I was able to pretty much land directly on the world unit I wished with pretty razor accuracy. Even with Speed 5 (it was DAOC, okay?) going the bot could navigate and land within a tiny radius of it's target without overshooting the theta angle and hunting back and forth.

    At the risk of being thoroughly derided... I'll post the movement calculation code anyhow. It's VB.net (I know... I know...) but is clear enough that you can just follow it as pseudo-code.

    Note: I absconded with the source to AutoIt's keyboard library and translated it to VB for this project. (This was three years ago or so.) So the notation for key codes is in AutoIt form, which is to say using braces {}.

    Code:
        Private Sub DoMovementActions()
    
            CheckToggleOffWhileMoving()
    
            dX = WPDestCoords.X - GF.PlayerCoordinates.X
            dY = WPDestCoords.Y - GF.PlayerCoordinates.Y
            dZ = WPDestCoords.Z - GF.PlayerCoordinates.Z
    
            ' flat distance
            WPDistance = Math.Sqrt((dX * dX) + (dY * dY))
    
            'adjust South-origin 4096 unit facing to unit circle pi-based radians
            thetaCurr = GF._myFacingNative
    
            ' dx and dy define our vector as a right triangle from the player's position as the origin
            thetaDest = Math.Atan2(-dX, dY)
    
            ' this order matters!
            deltaFacing = -thetaDest + thetaCurr
    
            ' determine what our delta facing should be such that it's the shortest measurement
            If deltaFacing < -Math.PI Then
                deltaFacing = (2 * Math.PI) + deltaFacing
            ElseIf deltaFacing > Math.PI Then
                deltaFacing = -(2 * Math.PI) + deltaFacing
            End If
    
            ' ============================================================
            ' do steering only - except for "big turn" while moving
            ' ============================================================
    
            If doMovement Then
    
                If Math.Abs(deltaFacing) > Math.PI / 180 Then
    
                    ' steer when
                    ' 180 = 1 degree of tolerance
    
                    WPTurning = True
    
                    If deltaFacing > 0 Then
                        ' turn left
    
                        If WPDistance < SLOWTOWALKDISTANCE And Math.Abs(deltaFacing) > Math.PI / 8 Then
    
                            ' always stop and steer when in close
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            GF.SendKeyString("{" & myAI.key_turnleft & " down}")
                            WPHairpinTurn = True
    
                        ElseIf WPDistance < SLOWTOWALKDISTANCE And Math.Abs(deltaFacing) <= Math.PI / 16 Then
    
                            ' in close, but facing is correct
                            WPHairpinTurn = False
    
                        ElseIf WPDistance < SLOWTOWALKDISTANCE And Math.Abs(deltaFacing) <= Math.PI / 8 Then
    
                            ' always stop and steer when in close
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            GF.SendKeyString("{" & myAI.key_turnleft & " down}")
                            Thread.Sleep(100)
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            ' stop for hairpin turns
                            WPHairpinTurn = True
    
                        ElseIf Math.Abs(deltaFacing) < Math.PI / 16 Then
    
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            GF.SendKeyString("{" & myAI.key_turnleft & " down}")
                            Thread.Sleep(50)
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            WPHairpinTurn = False
    
                        ElseIf Math.Abs(deltaFacing) < Math.PI / 8 Then
    
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            GF.SendKeyString("{" & myAI.key_turnleft & " down}")
                            Thread.Sleep(100)
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            WPHairpinTurn = False
    
                        ElseIf Math.Abs(deltaFacing) < Math.PI / 4 Then
    
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            GF.SendKeyString("{" & myAI.key_turnleft & " down}")
                            Thread.Sleep(200)
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            WPHairpinTurn = False
    
                        ElseIf Math.Abs(deltaFacing) < Math.PI / 2 Then
    
                            ' slow down for big turns
                            If WPRunning Then
                                GF.SendKeyString("{" & myAI.key_walk & " down}")
                                WPRunning = False
                                WPWalking = True
                            End If
                            WPHairpinTurn = False
    
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            GF.SendKeyString("{" & myAI.key_turnleft & " down}")
                            Thread.Sleep(300)
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
    
                        Else
    
                            ' hairpin turn - stop
                            WPHairpinTurn = True
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            GF.SendKeyString("{" & myAI.key_turnleft & " down}")
    
                        End If
    
                    Else
                        ' turn right
                        If WPDistance < SLOWTOWALKDISTANCE And Math.Abs(deltaFacing) > Math.PI / 8 Then
    
                            ' always stop and steer when in close
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            GF.SendKeyString("{" & myAI.key_turnright & " down}")
                            WPHairpinTurn = True
    
                        ElseIf WPDistance < SLOWTOWALKDISTANCE And Math.Abs(deltaFacing) <= Math.PI / 16 Then
    
                            ' in close, but facing is correct
                            WPHairpinTurn = False
    
                        ElseIf WPDistance < SLOWTOWALKDISTANCE And Math.Abs(deltaFacing) <= Math.PI / 8 Then
                            ' always stop and steer when in close
    
                            WPHairpinTurn = True
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            GF.SendKeyString("{" & myAI.key_turnright & " down}")
                            Thread.Sleep(100)
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
    
                        ElseIf Math.Abs(deltaFacing) < Math.PI / 16 Then
    
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            GF.SendKeyString("{" & myAI.key_turnright & " down}")
                            Thread.Sleep(50)
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            WPHairpinTurn = False
    
                        ElseIf Math.Abs(deltaFacing) < Math.PI / 8 Then
    
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            GF.SendKeyString("{" & myAI.key_turnright & " down}")
                            Thread.Sleep(100)
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            WPHairpinTurn = False
    
                        ElseIf Math.Abs(deltaFacing) < Math.PI / 4 Then
    
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            GF.SendKeyString("{" & myAI.key_turnright & " down}")
                            Thread.Sleep(200)
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
                            WPHairpinTurn = False
    
                        ElseIf Math.Abs(deltaFacing) < Math.PI / 2 Then
                            ' big turn - slow down
    
                            If WPRunning Then
                                GF.SendKeyString("{" & myAI.key_walk & " down}")
                                WPRunning = False
                                WPWalking = True
                            End If
                            WPHairpinTurn = False
    
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            GF.SendKeyString("{" & myAI.key_turnright & " down}")
                            Thread.Sleep(300)
                            GF.SendKeyString("{" & myAI.key_turnright & " up}")
    
                        Else
                            ' hairpin turn - stop
                            GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                            GF.SendKeyString("{" & myAI.key_turnright & " down}")
                            WPHairpinTurn = True
                        End If
                    End If
    
                Else
                    WPHairpinTurn = False
                    ' stop turning
                    If WPTurning Then
                        WPTurning = False
                        GF.SendKeyString("{" & myAI.key_turnright & " up}")
                        GF.SendKeyString("{" & myAI.key_turnleft & " up}")
                    End If
                End If
    
    
                ' ============================================================
                ' do adjustments to velocity
                ' ============================================================
    
    
                If WPRunning Then
    
                    ' I'm running already
    
                    If WPHairpinTurn Then
                        ' hairpin turn, stop moving while we steer
                        WPRunning = False ' we'll fall through this next time as the "Else" walking case
                        WPWalking = False
                        GF.SendKeyString("{up up}")
                    End If
    
                    If Not WPSlowDownAtEnd Then
                        ' not in slow down state at this point
    
                        ' so we check to see if we're close enough to turn it on
                        If WPDistance < SLOWTOWALKDISTANCE Then
    
                            If WPDistance >= 25 Then
                                GF.SendKeyString("{up down}")
                            End If
    
                            ' close to target, slow down
                            GF.SendKeyString("{" & myAI.key_walk & " down}")
                            WPSlowDownAtEnd = True
                            WPRunning = False ' we'll fall through this next to as the "Else" walking case
                            WPWalking = True
    
                        End If
    
                    End If
    
                    ' already WPRunning, no special cases, just keep on keepin' on
    
                Else
    
                    ' walking or stopped currently
    
                    If WPDistance > 25 Then
                        ' don't bother moving forward when this close
    
                        If WPHairpinTurn Then
    
                            If WPWalking Then
                                ' stop - doing a hairpin turn
                                WPRunning = False
                                WPWalking = False
                                GF.SendKeyString("{up up}")
                            End If
    
                            ' already stopped, do nothing
    
                        Else
                            ' not a hairpin turn, so lets boogie
                            If WPDistance < SLOWTOWALKDISTANCE Then
    
                                ' check to see if we're already going slow
                                If Not WPSlowDownAtEnd Or Not WPWalking Then
    
                                    ' slow down, less than SLOWTOWALKDISTANCE units to go
                                    GF.SendKeyString("{up down}")
                                    GF.SendKeyString("{" & myAI.key_walk & " down}")
                                    WPSlowDownAtEnd = True
                                    WPRunning = False
                                    WPWalking = True
    
                                End If
    
                                ' otherwise we continue forward at walking pace
    
                            Else
                                ' check to see if we're walking or stopped
                                If WPWalking Then
    
                                    ' normal run - greater than SLOWTOWALKDISTANCE units from target
                                    GF.SendKeyString("{" & myAI.key_walk & " up}")
                                    WPSlowDownAtEnd = False
                                    WPRunning = True
                                    WPWalking = False
    
                                Else
                                    ' we're stopped - get moving at full speed
                                    GF.SendKeyString("{up down}")
                                    GF.SendKeyString("{" & myAI.key_walk & " up}")
                                    WPSlowDownAtEnd = False
                                    WPRunning = True
                                    WPWalking = False
    
                                End If
    
                            End If
    
                        End If
                    Else
                        ' inside 25 units... stop moving
                        GF.SendKeyString("{up up}")
    
                    End If
    
    
    
                    ' ============================================================
                    ' swim up or down if we're at WP, yet not at same Z location
                    ' ============================================================
                    ' we should check somehow to see if we're swimming or not
                    If (WPDistance < 75 And dZ > 50) Or (WPDistance < 400 And dZ > 400) Then
                        ' below target
    
                        If swimdown Then
                            GF.SendKeyString("{" & GetBaseKeyString(myAI.key_swim_down) & " up}")
                            swimdown = False
                        End If
    
                        If Not swimup Then
                            GF.SendKeyString("{" & GetBaseKeyString(myAI.key_jump) & " down}")
                            swimup = True
                        End If
    
    
                    ElseIf (WPDistance < 75 And dZ < -50) Or (WPDistance < 400 And dZ < -400) Then
                        ' above target
    
                        If swimup Then
                            GF.SendKeyString("{" & GetBaseKeyString(myAI.key_jump) & " up}")
                            swimup = False
                        End If
    
                        If Not swimdown Then
                            GF.SendKeyString("{" & GetBaseKeyString(myAI.key_swim_down) & " down}")
                            swimdown = True
                        End If
    
                    Else
                        ' stop up/down swimming
                        If swimdown Then
                            GF.SendKeyString("{" & GetBaseKeyString(myAI.key_swim_down) & " up}")
                            swimdown = False
                        End If
    
                        If swimup Then
                            GF.SendKeyString("{" & GetBaseKeyString(myAI.key_jump) & " up}")
                            swimup = False
                        End If
    
                    End If
    
    
    
                End If
    
    
                ' ============================================================
                ' check if we're hung up and not moving
                ' ============================================================
    
    
    
                If WPHairpinTurn Then
                    ' don't monitor time spent in hairpin turns
                    WPDistTimer.Reset()
                    WPDistTimer.Start()
                End If
    
                If Math.Abs(WPLastDistance - WPDistance) < 8 Then
    
                    If WPDistTimer.ElapsedMilliseconds > 4000 Then
                        ' try sidestepping to get un-hung... we've not moved much in 4 seconds
    
                        StuckCount += 1
    
                        WPRunning = False ' set to false to force pressing of {down} key if not pressed for some reason.
    
    
                        GF.SendKeyString("{" & GetBaseKeyString(myAI.key_swim_down) & " up}")
                        swimdown = False
    
                        GF.SendKeyString("{" & GetBaseKeyString(myAI.key_jump) & " up}")
                        swimup = False
    
    
                        GF.SendKeyString(myAI.key_jump)
    
                        Select Case RandGen.Next(1, 10)
                            Case 1, 2, 3, 4, 5
                                GF.SendKeyString("{left down}")
                                Thread.Sleep(750)
                                GF.SendKeyString("{left up}")
                            Case 6, 7, 8, 9, 10
                                GF.SendKeyString("{right down}")
                                Thread.Sleep(750)
                                GF.SendKeyString("{right up}")
                        End Select
    
                    End If
    
                Else
                    ' we've moved enough to not be stuck... go ahead and reset timer
                    WPDistTimer.Reset()
                    WPDistTimer.Start()
    
                End If
    
                WPLastDistance = WPDistance
    
            End If
    
    
        End Sub
    A quick description of the rules:

    1. If the bot has to turn more than 90 degrees, stop moving forward. This prevents a curved path that might get you hung up on geometry if the waypoints thread a tight opening.

    2. If the bot has to turn between 90 and 45 degrees, press the walk key so that the arc size is small. Same reason as #1.

    3. As you get finer and finer adjustments with smaller theta angles, switch to different amounts of key tapping. The bot shouldn't have to hunt for a satisfactorily close heading.

    4. As the bot approaches the destination, press the walk key to slow down, giving the bot a finer ability to stop exactly where it needs to.

    5. I would have put in better Z navigation had I the ability to find where DAOC stored the "swimming" flag. I minimized the amount of Z navigation until the end of a movement leg, as otherwise the toon would bunny-hop up slopes.

    6. Random hopping & sliding is totally sub-optimal for dealing with getting hung up on geometry, but I never went to the length of developing a good world waypoint mesh. Hell, my first version that dealt with capturing coordinates did so by reading the player marker off the map on the screen. (God that was horrific.)

    Anyhow, it works well. Can't say that I'd do it the same way should I write a new bot from scratch. I'd really much rather directly tap client functions than try to emulate a user at the keyboard and mouse.

  8. #23
    Megamike55's Avatar Active Member
    Reputation
    23
    Join Date
    Oct 2010
    Posts
    49
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just wanted to let anyone reading this thread for advice that I got my key-press-only bot turning to within 5 degrees of accuracy. The key presser thread still operates at 100 ms for presses, but checks every 10 ms or so to see whether it should de-press a key or not. If you'd like to see the code (which is not complex -at all-) I can post it.

  9. #24
    xochi's Avatar Member
    Reputation
    10
    Join Date
    Jul 2009
    Posts
    6
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Megamike55 View Post
    Just wanted to let anyone reading this thread for advice that I got my key-press-only bot turning to within 5 degrees of accuracy. The key presser thread still operates at 100 ms for presses, but checks every 10 ms or so to see whether it should de-press a key or not. If you'd like to see the code (which is not complex -at all-) I can post it.
    I'd actually be interested in seeing it.

  10. #25
    Megamike55's Avatar Active Member
    Reputation
    23
    Join Date
    Oct 2010
    Posts
    49
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This is c# code. I tried to clean it up all pretty like. It is really nothing much, but its encapsulates the movement keys well, as well as provide an interface for pressing any other key (for example, the number keys, for attacks), as well as user chatting. Below this code you can see my altered SendText code. Note that my class here does not handle arrow keys / special keys very well. You'll have to program those yourself. There is some nice code to help you with that at www.shynd.com/code/PostMessage.cs

    As for using this code, just create a new wKeyManager object, and start calling functions like startTurningLeft(). It will handle the appropriate keypresses based on the key bindings you gave it when you created the object. My bot monitors the player's rotation and calls the stop functions of my wKeyManager, which it handles within 5 milliseconds, thus giving me accuracy up to 5 degrees or so, while still keeping key-presses at 100 ms intervals while the bot wants to hold a key down. Note that this class will eternally send key presses unless told to stop with the Stop(..) functions

    Hope this is helpful to someone, anyway.

    Code:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using System.Diagnostics;
    using com.ms.win32; //Add a reference to "vjslib" for this to work. Or just export the Win32 functions yourself
    
    namespace LetsReadWin
    {
        class wKeyManager
        {
            private struct wMovementKeyState
            {
                public string keyName;  //this is used for debug output (optional)
                public bool hold;
                public bool release;
                public bool releaseOK;
                public short VKey;
                public void SetKeyBind(short virtualKeyCode, string keyDescription)
                {
                    keyName = keyDescription;
                    VKey = virtualKeyCode;
                }
            }
    
            #region Variables
    
            //DEBUG tools:
            private System.Windows.Forms.TextBox debugConsole;
            string debugStr = "";
    
            //Some simple windows constants:
            const int WM_KEYDOWN = 0x0100;
            const int WM_KEYUP = 0x0101;
            const int WM_CHAR = 0x0102;
    
            //movement keys:
            private const int numKeys = 4;
            private const int fwd = 0;
            private const int bck = 1;
            private const int left = 2;
            private const int right = 3;
            //private const int st_left = 4;        //strafe keys are not implemented right now
            //private cons tint st_right = 5;       //strafe keys are not implemented right now
            private wMovementKeyState[] key = new wMovementKeyState[numKeys];
            //other special key sequences we can do:
            bool jumpBack = false;
    
            //Text (Chat) that the user wants to send:
            private int txtSentIndex = -1;
            private List<char> txtToSend = new List<char>();
    
            //The targeted windows:
            Process focusWind;
            private bool destroying = false;
            private Thread doKeysThread;
    
            #endregion
    
            #region Static Functions
    
            public static void holdKey(short vkey, ref Process targProc)
            {
                int ScanCode = User32.MapVirtualKey(vkey, 0);
                User32.PostMessage(targProc.MainWindowHandle.ToInt32(), WM_KEYDOWN, vkey, (ScanCode << 16) | 0x00100001);
            }
    
            public static void releaseKey(short vkey, ref Process targProc)
            {
                uint ScanCode = (uint)User32.MapVirtualKey(vkey, 0);
                User32.PostMessage(targProc.MainWindowHandle.ToInt32(), WM_KEYUP, vkey, (ScanCode << 16) | 0xC1000001);
            }
    
            #endregion
    
            #region Public Functions
    
            ~wKeyManager()
            {
                Destroy();
            }
    
            /// <summary>
            /// The only constructor for this class.
            /// Starts a thread on private function DoKeys()
            /// </summary>
            /// <param name="fWind">a process object representing the process we want to send keystrokes to.</param>
            /// <param name="fProf">gives us key bindings for forward, back, left, right, strafe left, and strafe right</param>
            public wKeyManager(Process fWind, wProfile fProf)
            {
                if (fWind == null) throw new Exception("Process object is null (wKeyManager constructor).");
                if (fProf == null) throw new Exception("Profile object is null (wKeyManager constructor).");
    
                focusWind = fWind;
                SetNewKeybinds(fProf);
                //setup the doKeysThread:
                doKeysThread = new Thread(new ThreadStart(this.doKeys));
                doKeysThread.Priority = ThreadPriority.Highest;
                //Start it up. It won't actually do anything at all until a startMoving(..) function, etc. is called:
                doKeysThread.Start();
            }
    
            public void SetNewKeybinds(wProfile fProf)
            {
                key[fwd].SetKeyBind(fProf.GetKeyBind(wActions.Forward).key, "FORWARD");
                key[bck].SetKeyBind(fProf.GetKeyBind(wActions.Backward).key, "BACKWARD");
                key[left].SetKeyBind(fProf.GetKeyBind(wActions.Left).key, "TURNLEFT");
                key[right].SetKeyBind(fProf.GetKeyBind(wActions.Right).key, "TURNRIGHT");
            }
    
            /// <summary>
            /// This will stop the thread that was created and render this object un-usable
            /// </summary>
            public void Destroy()
            {
                destroying = true;
            }
    
            /// <summary>
            /// Tells the thread to perform one small jump backward (only once).
            /// Calling this function many times at once will still only result in one jump.
            /// </summary>
            public void JumpBackward()
            {
                jumpBack = true;
            }
    
            public void SetDebugOutput(System.Windows.Forms.TextBox txtKeyboard)
            {
                debugConsole = txtKeyboard;
            }
    
            public void QueueTextForChat(string p)
            {
                //put each char in the string into a list of chars
                //The thread will go through each char one at a time, later, and send the appropriate message
                foreach (char cc in p)
                    txtToSend.Add(cc);
            }
    
            #region Start Movement Functions
    
            public void startMovingForward()
            {
                key[fwd].hold = true;
                key[fwd].release = false;
            }
    
            public void startMovingBack()
            {
                key[bck].hold = true;
                key[bck].release = false;
            }
    
            /// <summary>
            /// This function will do nothing if stopTurningLeft or stopAllMovement was called in the last 10 ms
            /// </summary>
            public void startTurningLeft()
            {
                if (key[left].release == false)
                {
                    key[left].hold = true;
                    if (key[right].hold == true)
                        stopTurningRight();
                }
            }
    
            /// <summary>
            /// This function will do nothing if stopTurningRight or stopAllMovement was called in the last 10 ms
            /// </summary>
            public void startTurningRight()
            {
                if (key[right].release == false)
                {
                    key[right].hold = true;
                    if (key[left].hold == true)
                        stopTurningLeft();
                }
            }
    
            #endregion
    
            #region Stop Movement Functions
    
            public void stopMovingForward()
            {
                key[fwd].release = true;
                key[fwd].hold = false;
            }
    
            public void stopMovingBack()
            {
                key[bck].release = true;
                key[bck].hold = false;
            }
            public void stopTurningLeft()
            {
                key[left].release = true;
                key[left].hold = false;
            }
            public void stopTurningRight()
            {
                key[right].release = true;
                key[right].hold = false;
            }
    
            /// <summary>
            /// This is the same as calling all of the StopMoving(...) functions all at once
            /// </summary>
            public void stopAllMovement()
            {
                stopTurningLeft();
                stopTurningRight();
                stopMovingBack();
                stopMovingForward();
                //stopStrafingLeft();
                //stopStrafingRight();
            }
    
            #endregion
    
            #region Is Moving Functions
    
            public bool IsMovingForward()
            {
                return ((key[fwd].hold) && (key[fwd].releaseOK));
            }
    
            public bool IsMovingBackward()
            {
                return ((key[bck].hold) && (key[bck].releaseOK));
            }
    
            public bool IsTurningLeft()
            {
                return ((key[left].hold) && (key[left].releaseOK));
            }
    
            public bool IsTurningRight()
            {
                return ((key[right].hold) && (key[right].releaseOK));
            }
    
            #endregion
    
            /// <summary>
            /// PressKey will send a WM_KEYDOWN and WM_KEYUP message to our target process immediately. 
            /// This function will NOT queue the key press and wait for the thread to deliver it.
            /// </summary>
            /// <param name="key">A single character to send</param>
            /// <returns></returns>
            public bool pressKey(char key)
            {
                return pressKey(User32.VkKeyScan(key));
            }
    
            /// <summary>
            /// PressKey will send a WM_KEYDOWN and WM_KEYUP message to our target process immediately. 
            /// This function will NOT queue the key press and wait for the thread to deliver it.
            /// </summary>
            /// <param name="vKey">The virtual key code for a single character to send</param>
            /// <returns></returns>
            public bool pressKey(short vKey)
            {
                if (vKey == -1)
                {
                    //MessageBox.Show("Error in [pressKey(short vKey);] no such key.");
                    return false;
                }
                else
                {
                    holdKey(vKey, ref focusWind);
                    releaseKey(vKey, ref focusWind);
                    return true;
                }
            }
    
            #endregion
    
            #region Private Functions
    
            private void keyChecking(bool holdOK, ref wMovementKeyState mks)
            {
                //add a line to our debug string:
                debugStr += (mks.keyName + "=[H: " + mks.hold + ", R: " + mks.release + ", R-ok: " + mks.releaseOK + "] ... ");
    
                //the logic of this function:
                //If the user wants to hold this key down, then check to see if it is OK to actually send a Message.
                //If it is ok to actually send a message to our target window, then set the "releaseOK" variable
                //"releaseOK" is set so that when we no longer want to hold down this key, we can send (or not send) the 
                //appropriate message
    
                if (mks.hold == true)
                {
                    debugStr += ("Holding " + mks.keyName);
                    if (holdOK)
                    {
                        //We are told it is OK to actually send a message, so do that
                        holdKey(mks.VKey, ref focusWind);
                        mks.releaseOK = true;
                    }
                }
                else if (mks.release == true)
                {
                    debugStr += ("Releasing " + mks.keyName);
                    if (mks.releaseOK == true)
                    {
                        //We are told it is OK to actually send a release key message, so do that
                        //(If "releaseOK" is not true, then the key was never Actually pressed in the first place)
                        releaseKey(mks.VKey, ref focusWind);
                    }
                    mks.release = false;
                    mks.releaseOK = false;
                }
                else
                    //The user doesn't care about this key right now, not trying to hold or release it.
                    mks.releaseOK = false;
    
                debugStr += ("\r\n");
            }
    
            /// <summary>
            /// This function checks to see if any new text has been added to our buffer "txtToSend" since the last
            /// time we looked at the buffer. If there is, we de-press all currently pressed keys, send the text,
            /// Then press down the appropriate keys again.
            /// </summary>
            private void HandleChatMessages()
            {
                if (txtToSend.Count > txtSentIndex + 1)
                {
                    if ((key[fwd].releaseOK) && (key[fwd].hold)) releaseKey(key[fwd].VKey, ref focusWind);
                    if ((key[bck].releaseOK) && (key[bck].hold)) releaseKey(key[bck].VKey, ref focusWind);
                    if ((key[left].releaseOK) && (key[left].hold)) releaseKey(key[left].VKey, ref focusWind);
                    if ((key[right].releaseOK) && (key[right].hold)) releaseKey(key[right].VKey, ref focusWind);
                    //dont change any variables
    
                    if (txtToSend.Count > txtSentIndex)
                    {
                        string strToSend = "";
                        for (txtSentIndex = txtSentIndex + 1; txtSentIndex < txtToSend.Count; txtSentIndex++)
                        {
                            strToSend += txtToSend[txtSentIndex].ToString();
    
                            //System.Windows.Forms.SendKeys.SendWait(strToSend);
                            //releaseKey(User32.VkKeyScan(txtToSend[txtSentIndex]), ref focusWind); 
                        }
                        txtSentIndex--; //for loops always add an extra one on the end. we want this to be the index of the last completed index.
                        if (strToSend != "")
                            PostMessageFuncs.PostMessage.SendKeys(focusWind.MainWindowHandle.ToInt32(), strToSend);
                        
    
                        //NOTE ON SENDKEYS:
                        //PostMessageFuncs namespace
                        //PostMessage class
                        //Base code obtained from: www.shynd.com/code/PostMessage.cs
                        //And modified slightly to match this implementation
                    }
                    if ((key[fwd].releaseOK) && (key[fwd].hold)) holdKey(key[fwd].VKey, ref focusWind);
                    if ((key[bck].releaseOK) && (key[bck].hold)) holdKey(key[bck].VKey, ref focusWind);
                    if ((key[left].releaseOK) && (key[left].hold)) holdKey(key[left].VKey, ref focusWind);
                    if ((key[right].releaseOK) && (key[right].hold)) holdKey(key[right].VKey, ref focusWind);
                }
            }
            
            /// <summary>
            /// this function automatically releases forward if it was being pressed, then jumps a short distance backward
            /// </summary>
            private void HandleJumpBack()
            {
                if (jumpBack == true)
                {
                    debugStr += "Jumping backward. Ignoring other forward and backward variables.\n";
                    if (debugConsole != null)
                        debugConsole.Text = debugStr;
    
                    //turn off the jump back switch:
                    jumpBack = false;
    
                    //Release the forward key if it was being pressed:
                    if (key[fwd].releaseOK == true)
                        releaseKey(key[fwd].VKey, ref focusWind);
                    key[fwd].hold = false;
                    key[fwd].release = false;
                    key[fwd].releaseOK = false;
    
                    //Execute the jump-back:
                    holdKey(key[bck].VKey, ref focusWind);
                    Thread.Sleep(100);
                    holdKey(key[bck].VKey, ref focusWind);
                    Thread.Sleep(100);
                    holdKey(key[bck].VKey, ref focusWind);
                    Thread.Sleep(100);
                    pressKey((short)VK.VK_SPACE);
                    Thread.Sleep(30);
                    holdKey(key[bck].VKey, ref focusWind);
                    Thread.Sleep(70);
                    holdKey(key[bck].VKey, ref focusWind);
                    Thread.Sleep(100);
                    releaseKey(key[bck].VKey, ref focusWind);
                }
            }
    
            private void doKeys()
            {
                try
                {
                    long next_key_check = DateTime.Now.Ticks;
                    while (destroying == false)
                    {
                        //this loop needs to check all the keys,
                        //it should only hold down a key every 100 ms
    
                        Thread.Sleep(5);
                        debugStr = "";
    
                        HandleChatMessages();
                        HandleJumpBack();
    
                        bool hOK = (DateTime.Now.Ticks >= next_key_check);
                        if (hOK) next_key_check = DateTime.Now.Ticks + (wCooldownManager.TicksPerMillisecond * 100); //100 ms, or 1000000 ticks.
                        //TicksPerMillisecond = 10000;
    
                        keyChecking(hOK, ref key[fwd]);
                        keyChecking(hOK, ref key[bck]);
                        if (key[left].release && !key[right].release)
                        {
                            keyChecking(hOK, ref key[left]);
                            keyChecking(hOK, ref key[right]);
                        }
                        else
                        {
                            keyChecking(hOK, ref key[right]);
                            keyChecking(hOK, ref key[left]);
                        }
    
                        if ((debugConsole != null) && (debugStr != ""))
                            debugConsole.Text = debugStr; //the debug output here is NOT thread safe
                    }
    
                }
                catch
                {
                    //clean up!
                }
    
    
            }
            #endregion
    
        }
    
    }

    Code:
            [DllImport("user32.dll", EntryPoint = "PostMessage")]
            private static extern int _PostMessage(int hWnd, int msg, int wParam, uint lParam);
            [DllImport("user32.dll", EntryPoint = "MapVirtualKey")]
            private static extern int _MapVirtualKey(int uCode, int uMapType);
    
            /// <summary>
            /// Sends keystrokes to the specified window
            /// </summary>
            /// <param name="hWnd">Window's hWnd</param>
            /// <param name="keys">String of keys to send</param>
            /// <returns>Returns number of keystrokes sent, -1 if an error occurs</returns>
            public static int SendKeys(int hWnd, string keys)
            {
                if (hWnd <= 0 || keys.Length == 0)
                    return -1;
    
                int ret = 0, i = 0;
    
                System.Text.StringBuilder str = new System.Text.StringBuilder(keys.ToUpper());
                
    
                str.Replace(Convert.ToChar("`"), Convert.ToChar(0xC0));
                str.Replace(Convert.ToChar("~"), Convert.ToChar(0xC0));
                str.Replace(Convert.ToChar("-"), Convert.ToChar(0xBD));
                str.Replace(Convert.ToChar("="), Convert.ToChar(0xBB));
                str.Replace(Convert.ToChar("/"), Convert.ToChar(System.Windows.Forms.Keys.Oem2));
                str.Replace(Convert.ToChar("."), Convert.ToChar(System.Windows.Forms.Keys.OemPeriod));
                str.Replace(Convert.ToChar(";"), Convert.ToChar(System.Windows.Forms.Keys.Oemplus));
    
                //int map1 = _MapVirtualKey(Convert.ToInt32(Convert.ToChar(")")), 1);
                //int map2 = _MapVirtualKey(Convert.ToInt32(Convert.ToChar("(")), 1);
                
                //str.Replace(Convert.ToChar("("), Convert.ToChar(LetsReadWin.VK.VK_LEFTPAREN)); //186   should be 40 and 41 though...
                //str.Replace(Convert.ToChar(")"), Convert.ToChar(LetsReadWin.VK.VK_RIGHTPAREN)); //243            
    
                str.Replace("{TAB}", Convert.ToChar(0x9).ToString());
                str.Replace("{ENTER}", Convert.ToChar(0xD).ToString());
                str.Replace("{ESC}", Convert.ToChar(0x1B).ToString());
                str.Replace("{F1}", Convert.ToChar(0x70).ToString());
                str.Replace("{F2}", Convert.ToChar(0x71).ToString());
                str.Replace("{F3}", Convert.ToChar(0x72).ToString());
                str.Replace("{F4}", Convert.ToChar(0x73).ToString());
                str.Replace("{F5}", Convert.ToChar(0x74).ToString());
                str.Replace("{F6}", Convert.ToChar(0x75).ToString());
                str.Replace("{F7}", Convert.ToChar(0x76).ToString());
                str.Replace("{F8}", Convert.ToChar(0x77).ToString());
                str.Replace("{F9}", Convert.ToChar(0x78).ToString());
                str.Replace("{F10}", Convert.ToChar(0x79).ToString());
                str.Replace("{F11}", Convert.ToChar(0x7A).ToString());
                str.Replace("{F12}", Convert.ToChar(0x7B).ToString());
                str.Replace("{SHIFTD}", Convert.ToChar(0xC1).ToString());
                str.Replace("{SHIFTU}", Convert.ToChar(0xC2).ToString());
    
                for (int ix = 1; ix <= str.Length; ++ix)
                {
                    char chr = str[i];
    
                    if (Convert.ToInt32(chr) == 0xC1)
                    {
                        _PostMessage(hWnd, 0x100, 0x10, 0x002A0001);
                        _PostMessage(hWnd, 0x100, 0x10, 0x402A0001);
                        Thread.Sleep(1);
                    }
                    else if (Convert.ToInt32(chr) == 0xC2)
                    {
                        _PostMessage(hWnd, 0x101, 0x10, 0xC02A0001);
                        Thread.Sleep(1);
                    }
                    if (Convert.ToInt32(chr) == 0x28) // ( = 0x38 ?
                    {
                        Thread.Sleep(65);
                        _PostMessage(hWnd, 0x102, 0x28, 0x00090001);
                        Thread.Sleep(1);
                    }
                    else if (Convert.ToInt32(chr) == 0x29) // ) = 0x39 ?
                    {
                        Thread.Sleep(65);
                        _PostMessage(hWnd, 0x102, 0x29, 0x000A0001);
                        Thread.Sleep(1);
                    }
                    else
                    {
                        if (Convert.ToInt32(chr) == 0xD)
                        {
                            Thread.Sleep(300); //This is the ENTER key. Wow needs a lot of time to process it... apparently
                        }
    
                        ret = _MapVirtualKey(Convert.ToInt32(chr), 0);
                        if (_PostMessage(hWnd, 0x100, Convert.ToInt32(chr), MakeLong(1, ret)) == 0)
                            return -1;
    
                        Thread.Sleep(5);
    
                        if (_PostMessage(hWnd, 0x101, Convert.ToInt32(chr), (MakeLong(1, ret) + 0xC0000000)) == 0)
                            return -1;
    
                        if (Convert.ToInt32(chr) == 0xD)
                        {
                            Thread.Sleep(300); //This is the ENTER key. Wow needs a lot of time to process it...
                        }
    
                    }
                    i++;
                }
                return i;
            }
    Last edited by Megamike55; 12-21-2010 at 10:11 PM.

  11. #26
    suicidity's Avatar Contributor
    Reputation
    207
    Join Date
    Oct 2006
    Posts
    1,439
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Only thing I hate about key pressing or emulation it it's too unreliable for my tastes..


  12. #27
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by suicidity View Post
    Only thing I hate about key pressing or emulation it it's too unreliable for my tastes..
    I agree. Not to mention, it just feels so 'dirty'.

  13. #28
    suicidity's Avatar Contributor
    Reputation
    207
    Join Date
    Oct 2006
    Posts
    1,439
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Cypher View Post
    I agree. Not to mention, it just feels so 'dirty'.
    Yes.. Very very very hack-ish, not a very clean solution by any means.


  14. #29
    Megamike55's Avatar Active Member
    Reputation
    23
    Join Date
    Oct 2010
    Posts
    49
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's true. I don't think anyone will disagree with you.

  15. #30
    krylonClear's Avatar Private
    Reputation
    1
    Join Date
    Dec 2010
    Posts
    6
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    I think mouse movement is best

    Simulating mouse movement in the most realistic way possible without writing to memory would be doable simply using

    SetCursorPos(1146,372);

    int x;
    int y;

    mouse_event(MOUSEEVENTF_RIGHTDOWN, x, y, 0, 0); //Click Down
    mouse_event(MOUSEEVENTF_RIGHTUP, x, y, 0, 0); //Click Up


    and for the cursor position, having variables which would gradually change toward a goal cursor position using acceleration that matches the acceleration of the human hand moving their mouse across the screen. Also, of course, you would click down on the right mouse and keep that held for the duration of navigating until you need the mouse to click on a node or whatever. Perhaps you could even set up a short program that records how many pixels your mouse travels per 5ms or whatever from start to finish and measure the acceleration you naturally use. Then, using this velocity curve, you can effectively give your mouse movement on the bot a 100% accurate match of the movement you naturally use with your mouse by hand. Throw in some jumping and you will have the most realistic bot ever... would NEVER get reported for botting as such humanlike movement is unheard of... click to move looks darn good though, but this could be made to look even better!



    Note: I actually messed with using similar mouse cursor positioning code to move my character and noticed that the character would insta turn overly fast some of the times and turn less other times depending I bet on my ping... the game cannot register a fake mouse movement that moves the mouse instantly like 100pixels to the right... this would be the equivalent of punching your mouse across the mousepad... you simply can't even move the mouse that fast... it won't register a smooth movement... At the time I overlooked that fact and got frustrated and gave up... but looking back, had I moved the mouse cursor gradually bit by bit in the code, it would have made a smooth movement... and of course, adding in code to give it a proper acceleration and deceleration like human movement would be icing on the cake
    Last edited by krylonClear; 12-23-2010 at 04:15 PM.

Page 2 of 3 FirstFirst 123 LastLast

Similar Threads

  1. Other good options for botting other than HB?
    By LifeIsOP in forum WoW Bots Questions & Requests
    Replies: 8
    Last Post: 03-01-2013, 04:36 AM
  2. Something Other Than Wow-v Plz.....
    By Snailz in forum World of Warcraft Emulator Servers
    Replies: 7
    Last Post: 12-31-2007, 08:38 AM
  3. Anywhere other than STV?
    By giantman in forum World of Warcraft General
    Replies: 3
    Last Post: 01-27-2007, 07:18 AM
  4. any thomg other than wowglider?
    By raceboy404 in forum World of Warcraft General
    Replies: 1
    Last Post: 01-21-2007, 02:57 PM
All times are GMT -5. The time now is 01:08 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search