lolautoaccept/src/lolautoaccept.cpp

328 lines
9.7 KiB
C++
Raw Normal View History

#include "lolautoaccept.h"
2022-07-04 22:59:48 +02:00
#include <algorithm>
#include <thread>
#include <Log.h>
2022-06-29 23:09:01 +02:00
LolAutoAccept::Stage::Stage() {}
2022-04-24 14:06:27 +02:00
LolAutoAccept::Stage::~Stage() {}
2022-07-04 22:59:48 +02:00
LolAutoAccept::LolAutoAccept(Config::RootConfig& config, DataDragon& dd, onposchange_func onposch) : config(config), dd(dd), onPoschange(onposch) {
2022-07-04 00:30:00 +02:00
std::lock_guard lock(stagesMutex);
2022-07-04 22:59:48 +02:00
stages.resize(3); // accept, ban, pick
2022-03-08 00:04:56 +01:00
}
2022-04-21 00:47:57 +02:00
LolAutoAccept::~LolAutoAccept() {
stopJoinThread();
}
2022-07-03 00:31:13 +02:00
void LolAutoAccept::setChamps(const std::vector<uint32_t>& champs, State s) {
2022-07-04 00:30:00 +02:00
if(s == State::LOBBY || s >= State::PICK) {
Log::warn << "setChamps() called on invalid State";
2022-04-26 21:44:16 +02:00
return;
2022-04-24 14:06:27 +02:00
}
2022-07-04 00:30:00 +02:00
{
std::lock_guard lock(stagesMutex);
2022-07-04 22:59:48 +02:00
stages.at((int) s).champids = champs;
stages.at((int) s).currentOffset = 0;
2022-07-04 00:30:00 +02:00
}
2022-07-03 00:31:13 +02:00
Log::info << "set champs on state: " << (int) s << " count: " << champs.size();
2022-04-21 00:47:57 +02:00
}
2022-04-24 14:06:27 +02:00
void LolAutoAccept::setEnabled(bool b, State s) {
2022-07-04 00:30:00 +02:00
if(s >= State::PICK) {
2022-04-24 14:06:27 +02:00
Log::warn << "setEnabled() called on invalid State";
2022-04-26 21:44:16 +02:00
return;
2022-04-24 14:06:27 +02:00
}
2022-04-21 00:47:57 +02:00
2022-07-04 00:30:00 +02:00
std::lock_guard lock(stagesMutex);
2022-07-04 22:59:48 +02:00
stages.at((int) s).enabled = b;
2022-04-21 00:47:57 +02:00
}
2022-04-20 00:54:10 +02:00
bool LolAutoAccept::init() {
2022-06-29 23:09:01 +02:00
if(clientapi) return true;
2022-06-29 23:09:01 +02:00
auto ca = ClientAccess::find();
if(ca) {
clientapi = std::make_shared<ClientAPI>(*ca.get());
2022-07-01 00:13:38 +02:00
auto selfinfo = clientapi->getSelf();
Log::info << "selfinfo: gameName: " << selfinfo.gameName << " name: " << selfinfo.name << " summonerid: " << selfinfo.summonerid << " statusMessage: " << selfinfo.statusMessage << " puuid: " << selfinfo.puuid << " level: " << selfinfo.level;
2022-06-29 23:09:01 +02:00
}
2022-03-12 20:56:07 +01:00
2022-06-29 23:09:01 +02:00
return (bool) clientapi;
2022-04-20 00:54:10 +02:00
}
2022-03-06 01:08:32 +01:00
2022-04-20 00:54:10 +02:00
void LolAutoAccept::run() {
2022-04-21 00:47:57 +02:00
// make sure its not running
stopJoinThread();
2022-06-29 23:09:01 +02:00
if(!clientapi) return; // no client api
2022-04-21 00:47:57 +02:00
lolaathread = std::thread(&LolAutoAccept::innerRun, this);
}
void LolAutoAccept::stop() {
shouldrun = false;
}
2022-07-04 22:59:48 +02:00
void LolAutoAccept::reload() {
Log::note << "reload LolAutoAccept";
loadPosition(currentPosition);
}
2022-07-09 01:01:51 +02:00
const std::vector<RuneAspekt>& LolAutoAccept::getRuneAspekts() {
if(runeaspekts.empty()) {
if(clientapi) {
runeaspekts = clientapi->getAllRuneAspekts();
Log::info << "Loaded " << runeaspekts.size() << " rune aspekts";
}
}
return runeaspekts;
}
void LolAutoAccept::applyRunes() {
// TODO
Log::warn << "LolAutoAccept::applyRunes() not implemented";
}
2022-04-21 00:47:57 +02:00
void LolAutoAccept::stopJoinThread() {
stop();
2022-03-12 20:56:07 +01:00
2022-04-21 00:47:57 +02:00
if(lolaathread.joinable()) {
lolaathread.join();
}
resetAllOffsets();
2022-04-21 00:47:57 +02:00
}
void LolAutoAccept::innerRun() {
2022-04-20 00:54:10 +02:00
shouldrun = true;
2022-03-12 20:56:07 +01:00
2022-04-20 00:54:10 +02:00
while(shouldrun) {
2022-07-04 00:30:00 +02:00
uint32_t extrasleep = 800;
2022-03-12 20:56:07 +01:00
auto start = std::chrono::high_resolution_clock::now();
2022-04-24 14:06:27 +02:00
2022-06-29 23:09:01 +02:00
auto phase = clientapi->getGameflowPhase();
2022-07-02 17:44:29 +02:00
Log::info << "current Gameflowphase: " << phase;
2022-06-29 23:09:01 +02:00
2022-07-01 00:13:38 +02:00
// do processing
2022-07-04 22:59:48 +02:00
if(phase == ClientAPI::GameflowPhase::MATCHMAKING) {
extrasleep = 200;
} else if(phase == ClientAPI::GameflowPhase::READYCHECK) {
if(stages.at(0).enabled) { // auto accept enabled
2022-06-29 23:09:01 +02:00
auto state = clientapi->getReadyCheckState();
Log::info << "readychack state: " << state;
if(state == ClientAPI::ReadyCheckState::INPROGRESS) {
Log::info << "auto accepting";
clientapi->acceptMatch();
}
2022-04-24 14:06:27 +02:00
}
2022-07-03 00:31:13 +02:00
resetAllOffsets();
2022-07-04 00:30:00 +02:00
extrasleep = 0; // no extra sleep
2022-07-01 00:13:38 +02:00
} else if(phase == ClientAPI::GameflowPhase::CHAMPSELECT) {
2022-07-02 13:21:09 +02:00
champSelect();
2022-07-04 00:30:00 +02:00
extrasleep = 0; // no extra sleep
} else if(phase == ClientAPI::GameflowPhase::INPROGRESS) {
extrasleep = 30000; // 30s bonus sleep
} else if(phase == ClientAPI::GameflowPhase::ENDOFGAME) {
extrasleep = 2000; // 2 s bonus sleep
} else if(phase == ClientAPI::GameflowPhase::PREENDOFGAME) {
extrasleep = 4000; // 4 s bonus sleep
} else if(phase == ClientAPI::GameflowPhase::WAITINGFORSTATS) {
extrasleep = 4000; // 4 s bonus sleep
} else if(phase == ClientAPI::GameflowPhase::NONE) {
2022-07-04 22:59:48 +02:00
extrasleep = 10000; // 10 s bonus sleep - no lobby
2022-07-02 13:21:09 +02:00
}
2022-07-02 12:36:38 +02:00
2022-07-02 13:21:09 +02:00
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> dur = (end-start);
//if(dur.count() > 1e-5)
2022-07-04 22:59:48 +02:00
Log::note << "iteration took: " << (dur.count() * 1000) << " ms extrasleep: " << extrasleep;
2022-07-02 12:36:38 +02:00
2022-07-04 00:30:00 +02:00
std::this_thread::sleep_for(std::chrono::milliseconds(400 + extrasleep));
2022-07-02 13:21:09 +02:00
}
}
2022-07-02 12:36:38 +02:00
2022-07-03 00:31:13 +02:00
void LolAutoAccept::resetAllOffsets() {
2022-07-04 22:59:48 +02:00
for(Stage& stage : stages) {
stage.currentOffset = 0;
2022-07-03 00:31:13 +02:00
}
2022-07-04 22:59:48 +02:00
currentPosition = Position::INVALID;
}
void LolAutoAccept::applyConfigToStage(Stage& stage, const Config::StageConfig& stageconf) {
stage.champids = dd.resolveChampIDs(stageconf.champs);
stage.enabled = stage.enabled;
stage.currentOffset = 0;
}
void LolAutoAccept::loadPosition(Position pos) {
Log::trace << __PRETTY_FUNCTION__ << " pos: " << pos;
// reinit the stages
std::lock_guard lock(stagesMutex);
stages.resize(1); // first stage does not change
stages.resize(3);
const Config::PositionConfig& posconf = config.getPositionConfig(pos);
applyConfigToStage(stages.at((int) State::BAN), posconf.ban);
applyConfigToStage(stages.at((int) State::PICK), posconf.pick);
currentPosition = pos;
2022-07-03 00:31:13 +02:00
}
uint32_t LolAutoAccept::getChampOfState(State s) {
2022-07-03 00:31:13 +02:00
assert(((int) s) >= 0 && s <= State::PICK);
2022-07-04 22:59:48 +02:00
Stage& stage = stages[(int) s];
uint32_t size = stage.champids.size();
if(stage.currentOffset >= size) {
2022-07-03 00:31:13 +02:00
// no champ to try left
Log::warn << "no champ left at stage: " << (int) s;
2022-07-04 22:59:48 +02:00
Log::warn << "stage size: " << stage.champids.size();
2022-07-03 00:31:13 +02:00
return 0;
}
2022-07-04 22:59:48 +02:00
return stage.champids[stage.currentOffset];
}
void LolAutoAccept::nextChampOfState(State s) {
2022-07-04 22:59:48 +02:00
assert(s > State::LOBBY && s <= State::PICK);
auto stage = stages[(int) s];
2022-07-04 22:59:48 +02:00
uint32_t size = stage.champids.size();
2022-07-04 22:59:48 +02:00
stage.currentOffset++;
2022-07-04 22:59:48 +02:00
if(stage.currentOffset >= size) {
// no champ to try left
Log::warn << "no champ left at stage: " << (int) s;
2022-07-04 22:59:48 +02:00
Log::warn << "stage size: " << stage.champids.size();
2022-07-04 22:59:48 +02:00
stage.currentOffset = 0;
return;
}
2022-07-03 00:31:13 +02:00
}
2022-07-03 14:50:43 +02:00
bool LolAutoAccept::isChampIntentofTeammate(uint32_t champid, const ClientAPI::ChampSelectSession& session) {
for(const ClientAPI::ChampSelectCell& player : session.myTeam) {
if(player.championID == (int32_t) champid || player.championPickIntentID == (int32_t) champid) {
Log::info << "player " << player.cellID << " @ " << player.position << " wants to play " << champid;
return true;
}
}
return false;
}
2022-07-04 22:59:48 +02:00
bool LolAutoAccept::isChampBanned(uint32_t champid, const ClientAPI::ChampSelectSession& session) {
for(const ClientAPI::ChampSelectAction& act : session.actions) {
if(act.type == ClientAPI::ChampSelectActionType::BAN && act.championID == (int32_t) champid && act.completed) {
return true;
}
}
return false;
}
2022-07-02 13:21:09 +02:00
LolAutoAccept::ownactions_t LolAutoAccept::getOwnActions(int32_t cellid, const std::vector<ClientAPI::ChampSelectAction> actions) {
ownactions_t out;
for(const auto& it : actions) {
if(it.actorCellID == cellid) {
Log::debug << "ownaction: id: " << it.id << " champid: " << it.championID << " completed: " << it.completed << " type: " << it.type;
if(!it.completed) { // completed cant be interacted anyways, so just ignore them.
out.push_back(it);
2022-07-02 12:36:38 +02:00
}
2022-07-02 13:21:09 +02:00
}
}
return out;
}
void LolAutoAccept::prepickPhase(const ownactions_t& ownactions) {
2022-07-04 00:30:00 +02:00
phase(ownactions, ClientAPI::ChampSelectActionType::PICK, State::PICK, false);
2022-07-02 13:21:09 +02:00
}
2022-07-03 14:50:43 +02:00
void LolAutoAccept::banPhase(const ownactions_t& ownactions, const ClientAPI::ChampSelectSession& session) {
phase(ownactions, ClientAPI::ChampSelectActionType::BAN, State::BAN, true, [session](uint32_t champid) {
2022-07-04 22:59:48 +02:00
return !isChampIntentofTeammate(champid, session) && !isChampBanned(champid, session);
2022-07-03 14:50:43 +02:00
});
2022-07-02 13:21:09 +02:00
}
void LolAutoAccept::pickPhase(const ownactions_t& ownactions) {
phase(ownactions, ClientAPI::ChampSelectActionType::PICK, State::PICK, true);
}
2022-07-02 13:21:09 +02:00
2022-07-03 14:50:43 +02:00
void LolAutoAccept::phase(const ownactions_t& ownactions, ClientAPI::ChampSelectActionType type, State s, bool complete, std::function<bool(uint32_t)> filter) {
2022-07-02 13:21:09 +02:00
for(auto it : ownactions) {
if(it.type == type) {
Log::info << type << " action anvailable: " << it.id << " champid: " << it.championID;
uint32_t champid = getChampOfState(s);
2022-07-03 14:50:43 +02:00
if(filter) {
// filter says no
if(!filter(champid)) {
2022-07-04 22:59:48 +02:00
Log::trace << "champid: " << champid << " filter says no - next champ";
2022-07-03 14:50:43 +02:00
nextChampOfState(s);
return;
}
}
if(it.championID != (int32_t) champid || !it.completed) {
2022-07-02 13:21:09 +02:00
// try to prepick a champion
Log::info << "try to pick champ: " << champid;
2022-07-03 14:50:43 +02:00
if(!clientapi->setChampSelectAction(it.id, champid, complete)) {
nextChampOfState(s);
}
2022-07-02 13:21:09 +02:00
return;
}
}
}
}
2022-04-24 14:06:27 +02:00
2022-07-02 13:21:09 +02:00
void LolAutoAccept::champSelect() {
auto session = clientapi->getChampSelectSession();
int32_t cellid = session.localPlayerCellId;
// find own cellid info
const ClientAPI::ChampSelectCell* me = nullptr;
for(const auto& it : session.myTeam) {
if(it.cellID == cellid) {
me = &it;
break;
2022-07-02 12:36:38 +02:00
}
2022-07-02 13:21:09 +02:00
}
2022-07-02 12:36:38 +02:00
2022-07-04 00:30:00 +02:00
Position pos = me ? me->position : Position::INVALID;
2022-07-04 22:59:48 +02:00
if(pos == Position::INVALID) {
pos = Position::UTILITY; // default: support TODO: make the default changeable? extra tab?
}
2022-07-02 13:21:09 +02:00
2022-07-04 22:59:48 +02:00
// reload config based on position if changed
if(pos != currentPosition) {
Log::note << "LolAutoAccept reloading config for position: " << pos << " because it was: " << currentPosition;
loadPosition(pos);
if(onPoschange) {
onPoschange(pos);
}
}
2022-07-02 13:21:09 +02:00
2022-07-04 22:59:48 +02:00
Log::debug << "cellid: " << cellid << " position: " << pos << " counter: " << session.counter << " timer: timeleftip: " << session.timer.adjustedTimeLeftInPhase << " totaltimephase: " << session.timer.totalTimeInPhase;
2022-07-02 13:21:09 +02:00
// find actions for own cell
auto ownactions = getOwnActions(cellid, session.actions);
2022-07-02 17:44:29 +02:00
Log::debug << "ownactions: " << ownactions.size();
2022-07-02 13:21:09 +02:00
// try to prepick champ
Log::info << "champselectphase: " << session.timer.phase;
2022-07-04 00:30:00 +02:00
std::lock_guard lock(stagesMutex);
2022-07-02 13:21:09 +02:00
if(session.timer.phase == ClientAPI::ChampSelectPhase::PLANNING) {
prepickPhase(ownactions);
} else if(session.timer.phase == ClientAPI::ChampSelectPhase::BAN_PICK) {
2022-07-03 14:50:43 +02:00
banPhase(ownactions, session);
2022-07-02 13:21:09 +02:00
pickPhase(ownactions);
} else if(session.timer.phase == ClientAPI::ChampSelectPhase::FINALIZATION) {
// trade?
}
2022-04-20 00:54:10 +02:00
}