Closed thomas-crane closed 7 years ago
This kind of reminds me of a problem that I had at the start of my famebot when I was trying to send keystrokes thru a timer to simply move my character around. I noticed that I could send "D" for example to move right, but if I stopped sending D and tried A right after it wouldnt work.
Turns out I needed to release "D" in order to send "A" (same for W and S) Idk if this has anything to do with your code / if you release the keystrokes but maybe when it loses focus, the release flag isnt raised for that key?
The keyup flag that I used in keybd_event was public const int KEYEVENTF_KEYUP = 0x0002
The thing is, keybd_event required window focus while SendMessage can do it in the background. But I think it would be worth trying.
What I would do was release every key at the end of each "step" in my famebot just to be safe. So I released W A S D even if they weren't pressed before, because releasing a key has no side-effects, but can solve problems.
The movement system uses SendMessage
with the virtual key codes for WM_KEYUP (0x0101)
and WM_KEYDOWN (0x0100)
.
I don't think the issue is related to releasing a key before pressing the next one. If you look at the CalculateMovement
code, you can see it always releases the appropriate key before pressing the next one. E.g. if A needs to be pressed, D_PRESSED
will be set to false before A_PRESSED
is set to true.
I think the issue is that when the key properties (W_PRESSED, A_PRESSED, ...
) are set, the code to press/release the key is only run if the new state of the key is different to its current state. E.g. if A_PRESSED
is false and you try to set it to false, no SendMessage
will occur.
I implemented this because I was concerned that calling SendMessage
many times could have performance impacts, but now that the bot has been out for a long time and no one has reported performance issues, it's probably safe to say it's a very cheap operation. Changing the properties to always call SendMessage
regardless of the key's current state may not fix the issue, but considering the almost non-existent performance impact, it's probably a good idea.
It's also very unusual that some of the keys still work correctly (S and D as mentioned before) but the fact that W in particular stops working gives a lot of insight because (when testing in the Nexus) it is the key which is pressed when the Window loses focus.
This makes me think that the cause could be that when the window loses focus, any keys which were pressed get released by Windows, but that isn't reflected in the code. E.g. Windows releases the W key, but because W_PRESSED
is still true, the bot thinks it is still pressed and doesn't call SendMessage
again.
After some research, I am fairly confident that the way I implemented the key properties is the cause of the issue. Windows sends the WM_KILLFOCUS
message to a window "immediately before it loses the keyboard focus." I am guessing that this releases any pressed keys, but because this event isn't acknowledged by the bot, it still thinks the W key is pressed and so it doesn't call SendMessage
to press the key again.
Either:
SendMessage
I will start on a fix when I finish work, but feel free to make a pull request if you want to have a stab at fixing it 😊
(In Core/Plugin.cs, look at the code in the #region Keys
for the key press properties)
Fixed. See commit 944e1886dcd0cceb30703f6029b9dc77ad43371c for details.
The issue can be reproduced by following these steps
When the client window loses focus, some keystrokes don't get sent to the client. E.g. in the nexus, the client can still move sideways (S and D are fine) but cannot move forwards or backwards (W and D are not being sent).
So far this has only been tested in the nexus