lolautoaccept/src/lolautoaccept.cpp
2022-04-24 21:04:36 +02:00

203 lines
4.6 KiB
C++

#include "lolautoaccept.h"
#include <thread>
#include <Log.h>
#include "util.h"
#include "fakescreen.h"
// set to 1 to use the test screenshot feature
#define TESTSCREEN 0
void debugImage(cv::Mat img, const std::string& name) {
if(img.channels() > 3) {
std::vector<cv::Mat> channels(4);
cv::split(img, channels);
channels.resize(3); // drop alpha channel
cv::merge(channels, img);
}
time_t t = time(0);
cv::imwrite("debugimages/" + name + std::to_string(t) + ".png", img);
}
LolAutoAccept::Stage::Stage(const std::string& matchertmpl) : matcher(matchertmpl) {}
LolAutoAccept::Stage::~Stage() {}
bool LolAutoAccept::Stage::process(LolAutoAccept& lolaa, cv::Mat& img) {
if(enabled) {
auto match = matcher.match(img);
if(match.doesMatch) {
action(lolaa);
return true;
}
}
return false;
}
LolAutoAccept::CooldownStage::CooldownStage(const std::string& matchertmpl) : Stage(matchertmpl) {}
bool LolAutoAccept::CooldownStage::process(LolAutoAccept& lolaa, cv::Mat& img) {
if((time(0) - lastused) > cooldown) {
if(Stage::process(lolaa, img)) {
lastused = time(0);
return true;
}
}
return false;
}
void LolAutoAccept::performClick(uint32_t nr, bool movemouseaway) {
inputs.setOffset(screen->getXOffset(), screen->getYOffset());
inputs.setScale(screen->getXScale(), screen->getYScale());
auto p = inputs.get(nr);
Log::info << "click " << nr << " @ " << p.x << " " << p.y;
sim.mouseMoveTo(p.x, p.y);
std::this_thread::sleep_for(std::chrono::milliseconds(170));
sim.mouseClick(XIS::LEFT_MOUSE_BUTTON);
// move mouse away
if(movemouseaway) {
std::this_thread::sleep_for(std::chrono::milliseconds(170));
p = inputs.get(0);
sim.mouseMoveTo(p.x, p.y);
}
}
void LolAutoAccept::enterSearch(const std::string& text) {
performClick(2, false); // click searchbox
Log::debug << "enter text: " << text;
sim.keySequence(text);
std::this_thread::sleep_for(std::chrono::milliseconds(750));
}
void LolAutoAccept::pickFirst(const std::string& search) {
enterSearch(search);
performClick(3, false); // first champion
}
LolAutoAccept::LolAutoAccept() : sim(XInputSimulator::getInstance()) {
// click positions in 1280x720 scale
inputs.addPoint({0, 0}); // zero zero
inputs.addPoint({645, 560}); // accept game
inputs.addPoint({775, 105}); // search box
inputs.addPoint({380, 160}); // first champ
inputs.addPoint({638, 608}); // pick/ban champ
stages.reserve(4);
stages.push_back(new AcceptStage());
stages.push_back(new PrePickStage());
stages.push_back(new BanStage());
stages.push_back(new PickStage());
}
LolAutoAccept::~LolAutoAccept() {
stopJoinThread();
for(auto s : stages) {
delete s;
}
delete screen;
screen = nullptr;
}
void LolAutoAccept::setChamp(const std::string& champ, State s) {
if(s == State::LOBBY || s >= State::GAME) {
Log::warn << "setChamp() called on invalid State";
}
stages.at((int) s)->champ = champ;
}
void LolAutoAccept::setEnabled(bool b, State s) {
if(s >= State::GAME) {
Log::warn << "setEnabled() called on invalid State";
}
stages.at((int) s)->enabled = b;
}
bool LolAutoAccept::init() {
if(screen)
return true;
// get window
#if TESTSCREEN == 0
auto wins = ScreenShot::getWindows("League of Legends");
if(wins.size() != 1) {
Log::fatal << "invalid count of windows found: " << wins.size();
for(auto w : wins) {
delete w;
}
return false;
}
screen = (wins.at(0)); // just take the first
#else
// testing whole screen, but take a part of it, so it behaves like a focused screenshot
screen = new FakeScreen(1, 683, 1280, 720);
#endif
// testing: whole screen:
// screen = new ScreenShot();
return true;
}
void LolAutoAccept::run() {
// make sure its not running
stopJoinThread();
if(!screen) return;
lolaathread = std::thread(&LolAutoAccept::innerRun, this);
}
void LolAutoAccept::stop() {
shouldrun = false;
}
void LolAutoAccept::stopJoinThread() {
stop();
if(lolaathread.joinable()) {
lolaathread.join();
}
}
void LolAutoAccept::innerRun() {
shouldrun = true;
while(shouldrun) {
auto start = std::chrono::high_resolution_clock::now();
cv::Mat img;
screen->take(img);
cv::resize(img, img, cv::Size(ScreenShot::DEFAULTWIDTH, ScreenShot::DEFAULTHEIGHT));
for(size_t i = 0; i < stages.size(); ++i) {
// Log::trace << "processing stage " << i;
Stage* stage = stages.at(i);
if(stage->process(*this, img)) {
Log::debug << "stage successful: " << i;
break;
}
}
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> dur = (end-start);
if(dur.count() > 1e-5)
Log::info << "iteration took: " << (dur.count() * 1000) << " ms";
std::this_thread::sleep_for(std::chrono::milliseconds(800));
}
}