Before I cancelled my subscription (went on a vacation and now I'm debating whether I want to restart it or not...) I approached this problem by asking two different questions. Do I need to turn? Do I need to move closer?
My target going into this was either a mob if I had a hostile target and if there wasn't one then the next waypoint.
Do I need to turn was answered by this function, which was passed the angle (degrees) to the target, the angle (degrees) I was currently facing, and how far away the target actually was (meters). If I was more than 3 meters away and was within +/- 15 degrees of ideal I figured that was good enough and didn't need to turn, and if I was within 3 meters then the tolerance jumped to +/- 90 degrees so basically if I'm that close I'd turn only if the target is actually behind me.
Code:
Function NeedToTurn(ByVal decTargetR As Decimal, ByVal sngPlayerAngle As Single, ByVal sngDistanceToTarget As Single) As Boolean
Return _
(Math.Abs(decTargetR - sngPlayerAngle) > 90 And sngDistanceToTarget > 0 And sngDistanceToTarget <= 3) Or _
(Math.Abs(decTargetR - sngPlayerAngle) > 15 And sngDistanceToTarget > 0 And sngDistanceToTarget > 3)
End Function
This is the code that uses the function and actually does the turning. When this is called we could be already holding W down if we need to move closer:
Code:
If NeedToTurn(decAngleToTarget, sngPlayerAngle, sngDistanceToTarget) Then
Dim t As Decimal = (decAngleToTarget - sngPlayerAngle)
WriteLog("Facing " & sngPlayerAngle & " need " & decAngleToTarget & " : t = " & t)
Dim intTurn As Integer = 0
If (t > 0 And t < 180) Then
intTurn = Keys.A
Else
intTurn = Keys.D
End If
WriteLog("Turning...")
If Math.Abs(decAngleToTarget - sngPlayerAngle) > 100 Then
WriteLog("He's behind you!! Stop running!")
ReleaseKey(Keys.W)
End If
HoldKey(intTurn)
Do While NeedToTurn(decAngleToTarget, sngPlayerAngle, sngDistanceToTarget)
System.Threading.Thread.Sleep(100)
Application.DoEvents()
ReadProcessMemoryFloat(readHandle, intMemBasePlayer + &H114, sngPlayerAngle, 4, Nothing)
WriteLog("Facing " & sngPlayerAngle & " need " & decAngleToTarget)
Loop
ReleaseKey(intTurn)
End If
End If
For moving closer, it was a simple comparison of how far we are from the target versus how far we want to be. If we want to be closer then start holding down W and if we're close enough then release it. There's also a simple check to make sure we're actually moving if we think we are.
Code:
If sngDistanceToTarget > FightingRange And Not hshKeysHeld.ContainsKey(CInt(Keys.W)) Then
WriteLog("Start walking - distance " & sngDistanceToTarget & "m")
HoldKey(Keys.W)
ElseIf sngDistanceToTarget <= FightingRange And hshKeysHeld.ContainsKey(CInt(Keys.W)) Then
ReleaseKey(Keys.W)
ElseIf hshKeysHeld.ContainsKey(CInt(Keys.W)) And decLastRunX = fltPlayerX And decLastRunY = fltPlayerY Then
ReleaseKey(Keys.W)
Else
decLastRunX = fltPlayerX
decLastRunY = fltPlayerY
End If
One other piece was my calculation for getting the angle to the target. It works, but it's messy. I'm sure somebody who isn't as rusty with trigonometry as I am could make it work in much fewer steps :-)
Code:
Function CalculateAngleToTarget(ByVal fltPlayerX As Single, ByVal fltPlayerY As Single, ByVal fltTargetX As Single, ByVal fltTargetY As Single) As Decimal
Dim decTargetR As Decimal
decTargetR = Math.Atan2(fltTargetY - fltPlayerY, fltTargetX - fltPlayerX)
If decTargetR < 0 Then decTargetR = decTargetR + (Math.PI * 2)
decTargetR = (decTargetR * 180) / Math.PI
decTargetR = decTargetR + 90
If decTargetR > 360 Then decTargetR = decTargetR - 360
If decTargetR > 180 Then decTargetR = 180 - (decTargetR - 180) Else decTargetR = -1 * decTargetR
Return decTargetR
End Function