This is a learning project in my Rust journey.
The objective of this script is to automate the gameplay of an incremental game called NGU.
NGU is a complex game with many unwrapping features and playing it optimally requires constant user input. Note that this is still under active development and is not meant to be used by the public.
- Script finds the game anywhere on display with template matching
- Rust Type System prevents clicking on wrong coordinates
- Check for ready skills with image processing
- Check for Boss encounters with image processing
- User input termination through concurrency
- X Connection issue in
display-info
- Feature request for
screenshots
- X Memory leak fix in
display-info
- X Memory leak fix in
screenshots
finding_corner.mp4
The script takes a screenshot of the display and searches for the upper left corner image
on the screen using template matching. It then stores the coordinates into CORNER constant, which is then used for clicking on in-game items.
All click-related functions receive a specific type, which represents in-game coordinates. The only way to create this type is by passing absolute coordinates, which are then
transformed into in-game ones (using the CORNER
constant above, which was defined on script startup).
The script will give preference to the strongest adventure skills. It checks to see which skills are on cooldown (by looking ta pre-determined pixels and colors).
adventure_skills_priority.mp4
After using a skill, such as "Ultimate Buff," the script will not attempt to do so again while it is on cooldown. It checks the corresponding pixel, sees that the color is "darker-blue," and thus knows it is on cooldown.
boss_encounter.mp4
Boss enemies have a yellow crown beside their names. By checking if it is present, the script can choose to only kill bosses. (Bosses are the only enemies which drop items, skipping regular enemies is more efficient for item farming).
As the script takes control of the mouse and keyboard, trying to stop it manually can be a pain. To solve this problem, the script is always listening for keyboard events: As soon as it sees a "z" pressed, it terminates. To handle the above, a new thread is spawned to work on the actual scripting (e.g., killing enemies), and the main thread keeps listening for keyboard events. Related, the user may terminate the script while it is in the middle of some action (e.g., pressing "y" for an "Ultimate Attack"). In that case, after termination, the "y" would STILL keep being pressed and would never be released. To solve this potential case, the script tracks all of the current pressed (and not released) inputs and will release all of them before terminating.
xorg-dev
libdbus-1-dev
pkg-config
libxcb-randr0-dev
libxcb-shm0-dev
- Some years ago, I wrote a similar script with Python.
- Back then, I had the help of a discord user called Satyric, which also wrote a (much better) script.