Compare commits
11 Commits
b8cd6a09ed
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 117a2fc63e | |||
| 154bdbbd9f | |||
| 0b8d761a37 | |||
| d939ade3be | |||
| 20b77c9168 | |||
| fe2d532dc1 | |||
| da1ba01120 | |||
| c1bdce49a8 | |||
| 9b0fe2183b | |||
| 29f9ce5140 | |||
| cdcc70d7de |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,98 @@
|
||||
from threading import Thread
|
||||
from enum import Enum
|
||||
import time
|
||||
import cv2 as cv
|
||||
import pyautogui
|
||||
from core.Logger import Logger
|
||||
from core.Player import PLAYER_STATE
|
||||
|
||||
BG_STATUS = Enum('BG_STATUS', ['IDLE', 'IN_QUEUE', 'IN_BG', 'LOADING'])
|
||||
|
||||
class BattlegroundAgent:
|
||||
def __init__(self, monitor, player) -> None:
|
||||
self.battlegroundThread = None
|
||||
self.player = player
|
||||
self.logger = Logger("Battleground Agent")
|
||||
self.groupFinderIcon = cv.imread("assets/icons/GroupFinder.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.pvpTab = cv.imread("assets/" + player.lang + "/menus/PlayerVsPlayerTab.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.randomEpicBgButton = cv.imread("assets/" + player.lang + "/menus/RandomEpicBGButton.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.joinBattleButton = cv.imread("assets/" + player.lang + "/menus/JoinBattleButton.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.deserterIcon = cv.imread("assets/icons/Deserter.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.joinBgWindow = cv.imread("assets/" + player.lang + "/menus/JoinBGWindow.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.enterBgButton = cv.imread("assets/" + player.lang + "/menus/EnterBgButton.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.leaveBgButton = cv.imread("assets/" + player.lang + "/menus/LeaveMatchButton.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.status = BG_STATUS.IDLE
|
||||
self.monitor = monitor
|
||||
|
||||
def startBGFarming(self):
|
||||
while self.player.state is PLAYER_STATE.BG_FARMING:
|
||||
self.player.checkConnection()
|
||||
self.status = BG_STATUS.IDLE
|
||||
if (self.isDeserter() is False):
|
||||
self.tagInBg()
|
||||
else:
|
||||
self.logger.log("Deserter debuff found, waiting for debuff to disapear before tagging to bg...")
|
||||
time.sleep(3)
|
||||
self.logger.log("Battleground bg farming ended.")
|
||||
|
||||
def isDeserter(self):
|
||||
res = self.monitor.findMatch(self.deserterIcon)
|
||||
if (res == -1):
|
||||
return False
|
||||
return True
|
||||
|
||||
def tagInBg(self):
|
||||
pyautogui.moveTo(50,50)
|
||||
self.logger.log("Tagging in random epic bg...")
|
||||
time.sleep(0.2)
|
||||
self.monitor.findMatchAndClickIfAvailable(self.groupFinderIcon)
|
||||
self.monitor.findMatchAndClickIfAvailable(self.pvpTab)
|
||||
self.monitor.findMatchAndClickIfAvailable(self.randomEpicBgButton)
|
||||
self.monitor.findMatchAndClickIfAvailable(self.joinBattleButton)
|
||||
self.status = BG_STATUS.IN_QUEUE
|
||||
self.waitForBg()
|
||||
|
||||
def waitForBg(self):
|
||||
self.logger.log("Waiting for bg to start...")
|
||||
while self.status == BG_STATUS.IN_QUEUE:
|
||||
res = self.monitor.findMatch(self.joinBgWindow)
|
||||
if (res != -1):
|
||||
self.logger.log("Bg started joining the game...")
|
||||
self.monitor.findMatchAndClickIfAvailable(self.enterBgButton)
|
||||
self.status = BG_STATUS.LOADING
|
||||
time.sleep(1)
|
||||
self.inBgRoutine()
|
||||
|
||||
|
||||
def foundEndOfBg(self, _res):
|
||||
self.logger.log("End of bg detected, leaving...")
|
||||
self.status = BG_STATUS.IDLE
|
||||
time.sleep(25)
|
||||
|
||||
def checkEndOfBg(self):
|
||||
self.monitor.findMatchAndClickIfAvailable(self.leaveBgButton, self.foundEndOfBg)
|
||||
|
||||
def inBgRoutine(self):
|
||||
self.logger.log("BG in progress...")
|
||||
self.status = BG_STATUS.IN_BG
|
||||
while self.status == BG_STATUS.IN_BG:
|
||||
pyautogui.keyDown("up")
|
||||
self.checkEndOfBg()
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
|
||||
def run(self):
|
||||
self.logger.log("Starting battlegroung thread in 3 seconds...")
|
||||
time.sleep(1)
|
||||
self.logger.log("Starting battlegroung thread in 2 seconds...")
|
||||
time.sleep(1)
|
||||
self.logger.log("Starting battlegroung thread in 1 seconds...")
|
||||
time.sleep(1)
|
||||
|
||||
self.battlegroundThread = Thread(
|
||||
target=self.startBGFarming,
|
||||
args=(),
|
||||
name="battleground thread",
|
||||
daemon=True)
|
||||
self.battlegroundThread.start()
|
||||
@@ -0,0 +1,27 @@
|
||||
import time
|
||||
import cv2 as cv
|
||||
import pyautogui
|
||||
from core.Logger import Logger
|
||||
class Spell:
|
||||
def __init__(self, monitor, path, name, castTime = 0, cooldown = 2) -> None:
|
||||
self.spellName = name
|
||||
self.castTime = castTime
|
||||
self.logger = Logger("Spell")
|
||||
self.cooldown = cooldown
|
||||
self.monitor = monitor
|
||||
self.spellIcon = cv.imread("assets/spells/" + path, cv.IMREAD_GRAYSCALE)
|
||||
self.lastUsed = None
|
||||
|
||||
def isOnCooldown(self):
|
||||
if self.lastUsed is None:
|
||||
return False
|
||||
return time.time() - self.lastUsed <= self.cooldown
|
||||
|
||||
def cast(self):
|
||||
if self.isOnCooldown() is False:
|
||||
self.logger.log("Casting " + self.spellName)
|
||||
lastCursorPosition = pyautogui.position()
|
||||
self.monitor.findMatchAndClickIfAvailable(self.spellIcon)
|
||||
time.sleep(self.castTime)
|
||||
pyautogui.moveTo(lastCursorPosition)
|
||||
self.lastUsed = time.time()
|
||||
@@ -0,0 +1,47 @@
|
||||
import time
|
||||
from threading import Thread
|
||||
from core.Logger import Logger
|
||||
from core.Player import CLASSES, SPE
|
||||
|
||||
class FightingAgent:
|
||||
def __init__(self, monitor, player) -> None:
|
||||
self.isCombatModeEnabled = False
|
||||
self.monitor = monitor
|
||||
self.player = player
|
||||
self.classRoutine = None
|
||||
self.logger = Logger("Combat Agent", player.debug)
|
||||
self.hasTarget = False
|
||||
self.combatClass = self.loadCombatClass()
|
||||
|
||||
def loadCombatClass(self):
|
||||
return 42
|
||||
|
||||
def getRoutine(self):
|
||||
if (self.player.playerClass == CLASSES.HUNTER.name and self.player.playerSpe == SPE.MARKSMANSHIP.name):
|
||||
from bots.fighting.hunter.marksmanship.Routine import Routine
|
||||
self.classRoutine = Routine(self.monitor, self.player)
|
||||
else:
|
||||
self.logger.log("Cannot find a Routine for your class and spe")
|
||||
|
||||
def startFighting(self):
|
||||
self.getRoutine()
|
||||
self.player.checkConnection()
|
||||
if self.classRoutine is not None:
|
||||
self.isCombatModeEnabled = True
|
||||
while self.isCombatModeEnabled is True :
|
||||
self.classRoutine.start()
|
||||
time.sleep(0.1)
|
||||
self.logger.log("Combat mode is now disabled...")
|
||||
|
||||
def stopFighting(self):
|
||||
self.isCombatModeEnabled = False
|
||||
|
||||
def run(self):
|
||||
self.logger.log("Combat mode is now enabled...")
|
||||
|
||||
fightingThread = Thread(
|
||||
target=self.startFighting,
|
||||
args=(),
|
||||
name="fighting thread",
|
||||
daemon=True)
|
||||
fightingThread.start()
|
||||
@@ -0,0 +1,27 @@
|
||||
from bots.components.spell import Spell
|
||||
|
||||
class Routine:
|
||||
def __init__(self, monitor, player) -> None:
|
||||
self.player = player
|
||||
self.monitor = monitor
|
||||
self.aimedShotSpell = Spell(monitor, "hunter/marksmanship/AimedShot.jpg", "Aimed Shot", 2, 11)
|
||||
self.arcaneShotSpell = Spell(monitor, "hunter/general/ArcaneShot.jpg", "Arcane shot")
|
||||
self.blackArrowSpell = Spell(monitor, "hunter/marksmanship/BlackArrow.jpg", "Black Arrow", 0, 30)
|
||||
self.killShotSpell = Spell(monitor, "hunter/general/KillShot.jpg", "Kill Shot", 0, 10)
|
||||
self.explosiveShotSpell = Spell(monitor, "hunter/general/ExplosiveShot.jpg", "Explosive Shot", 0, 30)
|
||||
self.hunterMarkSpell = Spell(monitor, "hunter/general/HuntersMark.jpg", "Hunter's Mark", 0, 20)
|
||||
self.rapidFireSpell = Spell(monitor, "hunter/marksmanship/RapidFire.jpg", "Rapid Fire", 2, 20)
|
||||
self.trueShotSpell = Spell(monitor, "hunter/marksmanship/TrueShot.jpg", "True Shot", 0, 120)
|
||||
|
||||
def hasTarget(self):
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
self.hunterMarkSpell.cast()
|
||||
self.trueShotSpell.cast()
|
||||
self.aimedShotSpell.cast()
|
||||
self.blackArrowSpell.cast()
|
||||
self.killShotSpell.cast()
|
||||
self.rapidFireSpell.cast()
|
||||
self.explosiveShotSpell.cast()
|
||||
self.arcaneShotSpell.cast()
|
||||
@@ -6,15 +6,16 @@ import cv2 as cv
|
||||
import pyautogui
|
||||
from core.Logger import Logger
|
||||
from core.Player import PLAYER_STATE
|
||||
from core.utils import addHumanReaction
|
||||
|
||||
class FishingAgent:
|
||||
def __init__(self, monitor, player) -> None:
|
||||
self.fishingBobberImg = cv.imread("assets/fishing/bobbers/Bobber2.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.fishingIconImg = cv.imread("assets/fishing/FishIcon.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.fishingThread = None
|
||||
self.logger = Logger("Fishing Agent")
|
||||
self.monitor = monitor
|
||||
self.logger = Logger("Fishing Agent", player.debug)
|
||||
self.lureLoc = None
|
||||
self.monitor = monitor
|
||||
self.player = player
|
||||
self.fail = 0
|
||||
self.retry = 0
|
||||
@@ -52,32 +53,33 @@ class FishingAgent:
|
||||
if (self.retry > 4):
|
||||
self.fail += 1
|
||||
self.logger.log("Took too long to find lure, retrying fishing from the beginning")
|
||||
return
|
||||
else:
|
||||
self.logger.log("Trying again in 1 second...")
|
||||
self.retry += 1
|
||||
time.sleep(1)
|
||||
self.findLure()
|
||||
time.sleep(0.5)
|
||||
self.lureLoc = res
|
||||
pyautogui.moveTo(self.lureLoc[0], self.lureLoc[1])
|
||||
else:
|
||||
addHumanReaction()
|
||||
pyautogui.moveTo(res[0], res[1])
|
||||
self.watchLure()
|
||||
|
||||
def watchLure(self):
|
||||
self.retry = 0
|
||||
self.logger.log("Waiting for fish...")
|
||||
addHumanReaction()
|
||||
res = self.monitor.findMatch(self.fishingBobberImg)
|
||||
if (res != -1):
|
||||
self.lureLoc = res
|
||||
while True:
|
||||
self.retry += 1
|
||||
time.sleep(0.1)
|
||||
addHumanReaction()
|
||||
res = self.monitor.findMatch(self.fishingBobberImg)
|
||||
print(self.lureLoc)
|
||||
print(res)
|
||||
if (res != -1 and abs(res[1] - self.lureLoc[1]) > 10):
|
||||
time.sleep(0.2)
|
||||
if (res == -1 or abs(res[1] - self.lureLoc[1]) > 20):
|
||||
addHumanReaction()
|
||||
pyautogui.click()
|
||||
time.sleep(0.5)
|
||||
return
|
||||
elif (self.retry > 200):
|
||||
elif (self.retry > 150):
|
||||
self.retry = 0
|
||||
self.fail += 1
|
||||
return
|
||||
|
||||
@@ -5,17 +5,17 @@ from core.Logger import Logger
|
||||
from core.Player import PLAYER_STATE
|
||||
|
||||
class IdlingAgent:
|
||||
def __init__(self, monitor, playerAgent) -> None:
|
||||
self.logger = Logger("Idling Agent")
|
||||
def __init__(self, monitor, player) -> None:
|
||||
self.logger = Logger("Idling Agent", player.debug)
|
||||
self.idleTime = time.time()
|
||||
self.idleThread = None
|
||||
self.player = playerAgent
|
||||
self.player = player
|
||||
self.monitor = monitor
|
||||
|
||||
def checkIdleTime(self):
|
||||
while self.player.state is PLAYER_STATE.IDLE:
|
||||
while self.player.state in (PLAYER_STATE.IDLE, PLAYER_STATE.BG_FARMING):
|
||||
elapsedTime = time.time() - self.idleTime
|
||||
if (elapsedTime > 10):
|
||||
if (elapsedTime > 60):
|
||||
self.logger.log("Jumping to avoid being afk...")
|
||||
pyautogui.press("space")
|
||||
self.idleTime = time.time()
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
pyinstaller --clean -y -n "wowxel" --add-data="assets;assets" --add-data="config.json;." main.py;
|
||||
cd dist/wowxel/;
|
||||
mv ./_internal/assets .;
|
||||
mv ./_internal/config.json .;
|
||||
cd ..;
|
||||
rm ./wowxel.zip;
|
||||
Compress-Archive -Path ./wowxel -DestinationPath ./wowxel.zip;
|
||||
explorer .;
|
||||
cd ..;
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"antiAfk": true,
|
||||
"class": "DRUID",
|
||||
"spe": "RESTORATION",
|
||||
"debug": false,
|
||||
"lang": "en",
|
||||
"name": "Droïde"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"antiAfk": true,
|
||||
"class": "HUNTER",
|
||||
"spe": "MARKSMANSHIP",
|
||||
"debug": false,
|
||||
"lang": "en",
|
||||
"name": "Aelyss"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
from core.constants import gptApiKey
|
||||
|
||||
class ChatGptAgent:
|
||||
def __init__(self, name = "Logger", debug = False) -> None:
|
||||
self.isDebug = debug
|
||||
self.name = name
|
||||
@@ -1,4 +1,5 @@
|
||||
import json
|
||||
class Config:
|
||||
def __init__(self) -> None:
|
||||
## PASS JSON CONFIG HERE AND DECLARE IT TO THE MAIN AGENT
|
||||
pass
|
||||
def __init__(self, configName = "config") -> None:
|
||||
with open(configName + ".json", encoding="utf-8") as jsonFile:
|
||||
self.file = json.load(jsonFile)
|
||||
@@ -0,0 +1,46 @@
|
||||
import time
|
||||
from pynput import keyboard, mouse
|
||||
import pyautogui
|
||||
from ast import literal_eval
|
||||
|
||||
# Classe pour enregistrer les événements
|
||||
class InputRecorder:
|
||||
def __init__(self, file_name="events_log.txt"):
|
||||
self.events = []
|
||||
self.file_name = file_name
|
||||
|
||||
# Fonction pour gérer les événements du clavier
|
||||
def on_press_key(self, key):
|
||||
try:
|
||||
self.events.append(('keyboard', 'press', key.char, time.time()))
|
||||
except AttributeError:
|
||||
self.events.append(('keyboard', 'press', key.name, time.time()))
|
||||
|
||||
def on_release_key(self, key):
|
||||
print(key, "############ key released", keyboard.Key.esc)
|
||||
self.events.append(('keyboard', 'release', key, time.time()))
|
||||
if key == keyboard.Key.esc:
|
||||
return False
|
||||
|
||||
# Fonction pour gérer les événements de la souris
|
||||
def on_click(self, x, y, button, pressed):
|
||||
if pressed:
|
||||
self.events.append(('mouse', 'click', button.name, (x, y), time.time()))
|
||||
|
||||
# Fonction pour démarrer l'enregistrement
|
||||
def start_recording(self):
|
||||
print("Appuie sur Échap pour arrêter l'enregistrement...")
|
||||
with keyboard.Listener(on_press=self.on_press_key, on_release=self.on_release_key) as kl, mouse.Listener(on_click=self.on_click) as ml:
|
||||
kl.join()
|
||||
ml.join()
|
||||
|
||||
# Sauvegarder les événements dans un fichier
|
||||
with open(self.file_name, "w") as f:
|
||||
for event in self.events:
|
||||
f.write(str(event) + "\n")
|
||||
print(f"Les événements ont été sauvegardés dans {self.file_name}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Enregistrement des événements
|
||||
recorder = InputRecorder()
|
||||
recorder.start_recording()
|
||||
@@ -1,9 +1,15 @@
|
||||
import datetime;
|
||||
|
||||
class Logger:
|
||||
def __init__(self, name = "Logger") -> None:
|
||||
def __init__(self, name = "Logger", debug = False) -> None:
|
||||
self.isDebug = debug
|
||||
self.name = name
|
||||
|
||||
def log(self, message):
|
||||
ct = datetime.datetime.now()
|
||||
print(ct.strftime("%m/%d/%Y-%H:%M:%S:"), self.name, ">>", message)
|
||||
|
||||
def debug(self, message):
|
||||
if (self.isDebug is True):
|
||||
ct = datetime.datetime.now()
|
||||
print(ct.strftime("%m/%d/%Y-%H:%M:%S:"), self.name, ">>", message)
|
||||
@@ -1,14 +1,20 @@
|
||||
from core.Config import Config
|
||||
from core.Monitor import Monitor
|
||||
from bots.battleground.battlegroundAgent import BattlegroundAgent
|
||||
from bots.fishing.FishingAgent import FishingAgent
|
||||
from bots.fighting.FightingAgent import FightingAgent
|
||||
from bots.idling.IdlingAgent import IdlingAgent
|
||||
from core.Player import Player, PLAYER_STATE
|
||||
|
||||
class MainAgent:
|
||||
def __init__(self) -> None:
|
||||
self.monitor = Monitor()
|
||||
self.playerAgent = Player(self.monitor)
|
||||
def __init__(self, configName = "config ") -> None:
|
||||
self.config = Config(configName)
|
||||
self.monitor = Monitor(self.config)
|
||||
self.playerAgent = Player(self.monitor, self.config)
|
||||
self.idlingBot = IdlingAgent(self.monitor, self.playerAgent)
|
||||
self.fightingAgent = FightingAgent(self.monitor, self.playerAgent)
|
||||
self.fishingBot = FishingAgent(self.monitor, self.playerAgent)
|
||||
self.bgFarming = BattlegroundAgent(self.monitor, self.playerAgent)
|
||||
self.monitor.startScreenCaptureThread()
|
||||
# Start idling agent at the construction of the mainAgent for now
|
||||
self.idlingBot.run()
|
||||
@@ -17,4 +23,14 @@ class MainAgent:
|
||||
self.playerAgent.changeState(PLAYER_STATE.FISHING)
|
||||
self.fishingBot.run()
|
||||
|
||||
def startBgBot(self):
|
||||
self.playerAgent.changeState(PLAYER_STATE.BG_FARMING)
|
||||
self.bgFarming.run()
|
||||
|
||||
def toggleFightingAgent(self):
|
||||
if (self.fightingAgent is True):
|
||||
self.fightingAgent.stopFighting()
|
||||
else:
|
||||
self.fightingAgent.run()
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import time
|
||||
from threading import Thread
|
||||
from inspect import isfunction
|
||||
from screeninfo import get_monitors
|
||||
import pyautogui
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
from core.Logger import Logger
|
||||
from core.utils import addHumanReaction
|
||||
|
||||
FPS_REPORT_DELAY = 3
|
||||
|
||||
class Monitor:
|
||||
def __init__(self):
|
||||
self.logger = Logger("Monitor")
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self.isDebug = self.config.file["debug"]
|
||||
self.logger = Logger("Monitor", self.isDebug)
|
||||
self.monitor = None
|
||||
self.screenThread = None
|
||||
self.screenshot = None
|
||||
@@ -33,6 +37,7 @@ class Monitor:
|
||||
newScreenshot = cv.cvtColor(np.array(newScreenshot), cv.COLOR_RGB2BGR)
|
||||
grayScreenshot = cv.cvtColor(newScreenshot, cv.COLOR_BGR2GRAY)
|
||||
self.screenshot = grayScreenshot
|
||||
if (self.isDebug is True):
|
||||
cv.imwrite("assets/screenshot.jpg", self.screenshot)
|
||||
currTime = time.time()
|
||||
if currTime - fpsPrintTime >= FPS_REPORT_DELAY:
|
||||
@@ -45,6 +50,7 @@ class Monitor:
|
||||
self.screenThread.start()
|
||||
self.logger.log("Main Agent: Thread started")
|
||||
|
||||
# TODO: GET IMAGE BEST MATCH RATIO FOR A WHOLE DIRECTORY OF ASSETS
|
||||
def findBestMatchFromDir(self, dirPath):
|
||||
pass
|
||||
|
||||
@@ -55,9 +61,10 @@ class Monitor:
|
||||
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
|
||||
|
||||
matchRatio = max_val * 100
|
||||
self.logger.log(matchRatio)
|
||||
if (matchRatio < 60):
|
||||
self.logger.log("Cannot find matching result...")
|
||||
self.logger.debug(matchRatio)
|
||||
# Consider a match if ratio is at least 50%
|
||||
if (matchRatio < 50):
|
||||
self.logger.debug("Cannot find matching result...")
|
||||
return -1
|
||||
|
||||
# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
|
||||
@@ -73,9 +80,25 @@ class Monitor:
|
||||
point = self.findMatch(template, method)
|
||||
if (point == -1):
|
||||
return -1
|
||||
time.sleep(0.2)
|
||||
addHumanReaction()
|
||||
pyautogui.moveTo(point[0], point[1])
|
||||
time.sleep(0.15)
|
||||
addHumanReaction()
|
||||
|
||||
def findMatchAndClickIfAvailable(self, template, onFound = None, onNotFound = None):
|
||||
res = self.findMatchAndMoveToPosition(template)
|
||||
|
||||
if (res == -1):
|
||||
addHumanReaction()
|
||||
if onNotFound is not None:
|
||||
return onNotFound(res)
|
||||
else:
|
||||
addHumanReaction()
|
||||
pyautogui.click()
|
||||
addHumanReaction()
|
||||
print(isfunction(onFound))
|
||||
if (onFound is not None):
|
||||
return onFound(res)
|
||||
|
||||
|
||||
def stopScreenCaptureThread(self):
|
||||
if (self.screenThread):
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
import json
|
||||
from enum import Enum
|
||||
import time
|
||||
import cv2 as cv
|
||||
import pyautogui
|
||||
from core.Logger import Logger
|
||||
|
||||
CONNECT_STATUS = Enum('CONNECT_STATUS', ["CONNECTED", "CONNECTING", "DISCONNECTED"])
|
||||
CLASSES = Enum('CLASSES', ['DRUID', 'MAGE', 'HUNTER', 'PRIEST'])
|
||||
PLAYER_STATE = Enum('STATE', ['IDLE', 'FISHING', 'FARMING'])
|
||||
SPE = Enum('SPE', ['MARKSMANSHIP'])
|
||||
PLAYER_STATE = Enum('STATE', ['IDLE', 'FISHING', 'FARMING', 'BG_FARMING'])
|
||||
|
||||
class Player:
|
||||
def __init__(self, monitor) -> None:
|
||||
with open("config.json", encoding="utf-8") as jsonFile:
|
||||
self.config = json.load(jsonFile)
|
||||
def __init__(self, monitor, config) -> None:
|
||||
self.config = config
|
||||
self.isConnected = None
|
||||
self.idleThread = None
|
||||
self.enterWorldButton = cv.imread("assets/menus/EnterWorldButton.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.logger = Logger("Player Agent")
|
||||
self.antiAfk = self.config.file["antiAfk"]
|
||||
self.debug = self.config.file["debug"]
|
||||
self.lang = self.config.file["lang"]
|
||||
self.logger = Logger("Player Agent", self.debug)
|
||||
self.state = PLAYER_STATE.IDLE
|
||||
self.monitor = monitor
|
||||
self.playerClass = self.config["class"]
|
||||
self.playerName = self.config["name"]
|
||||
self.logger.log("Connected with " + self.playerName + " (" + self.playerClass + ")")
|
||||
self.playerClass = self.config.file["class"]
|
||||
self.playerSpe = self.config.file["spe"]
|
||||
self.playerName = self.config.file["name"]
|
||||
self.enterWorldButton = cv.imread("assets/" + self.lang + "/menus/EnterWorldButton.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.reconnectButton = cv.imread("assets/" + self.lang + "/menus/Reconnect.jpg", cv.IMREAD_GRAYSCALE)
|
||||
self.logger.log("Connected with " + self.playerName + " (" + self.playerClass + " - " + self.playerSpe + ")")
|
||||
|
||||
def checkConnection(self):
|
||||
res = self.monitor.findMatch(self.enterWorldButton)
|
||||
if (res == -1):
|
||||
self.isConnected = CONNECT_STATUS.CONNECTED
|
||||
else:
|
||||
def connectButtonFound(self, _res):
|
||||
self.isConnected = CONNECT_STATUS.DISCONNECTED
|
||||
self.logger.log("Player not connected attempting to connect...")
|
||||
pyautogui.move(res[0], res[1])
|
||||
time.sleep(0.4)
|
||||
pyautogui.click()
|
||||
time.sleep(5)
|
||||
|
||||
time.sleep(30)
|
||||
|
||||
def connectButtonNotFound(self, _res):
|
||||
self.isConnected = CONNECT_STATUS.CONNECTED
|
||||
|
||||
def checkConnection(self):
|
||||
self.monitor.findMatchAndClickIfAvailable(self.enterWorldButton, self.connectButtonFound, self.connectButtonNotFound)
|
||||
self.monitor.findMatchAndClickIfAvailable(self.reconnectButton, self.connectButtonFound, self.connectButtonNotFound)
|
||||
|
||||
def changeState(self, newState):
|
||||
self.state = newState
|
||||
@@ -5,6 +5,7 @@ class CLIAgent:
|
||||
def __init__(self, mainAgent) -> None:
|
||||
self.isRunning = False
|
||||
self.logger = Logger("CliAgent")
|
||||
|
||||
if (not mainAgent):
|
||||
raise Exception("Main agent not found...")
|
||||
self.mainAgent = mainAgent
|
||||
@@ -12,6 +13,8 @@ class CLIAgent:
|
||||
def printMenu(self):
|
||||
print("Enter a command:")
|
||||
print("\tH\tHelp.")
|
||||
print("\tBG\tStart the bg farming agent.")
|
||||
print("\tC\tToggle fight mode ON/OFF.")
|
||||
print("\tF\tStart the fishing agent.")
|
||||
print("\tQ\tQuit.")
|
||||
print("$>> ", end='')
|
||||
@@ -24,8 +27,11 @@ class CLIAgent:
|
||||
userInput = input()
|
||||
userInput = str.lower(userInput).strip()
|
||||
|
||||
if (userInput == "f"):
|
||||
self.logger.log("Starting Fishing bot...")
|
||||
if (userInput == "bg"):
|
||||
self.mainAgent.startBgBot()
|
||||
elif (userInput == "c"):
|
||||
self.mainAgent.toggleFightingAgent()
|
||||
elif (userInput == "f"):
|
||||
self.mainAgent.startFishBot()
|
||||
elif (userInput == "h"):
|
||||
self.printMenu()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
gptApiKey = "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"
|
||||
@@ -0,0 +1,6 @@
|
||||
import time
|
||||
import random
|
||||
|
||||
def addHumanReaction():
|
||||
delay = random.uniform(0.1, 0.4)
|
||||
time.sleep(delay)
|
||||
@@ -1,9 +1,44 @@
|
||||
import sys
|
||||
from core.cli.CliAgent import CLIAgent
|
||||
from core.MainAgent import MainAgent
|
||||
|
||||
def printLogo():
|
||||
print("""
|
||||
,--,
|
||||
,--.'|
|
||||
.---. ,---. | | :
|
||||
/. ./| ' ,'\\ ,--, ,--, : : '
|
||||
.-'-. ' | / / ||'. \\/ .`| ,---. | ' |
|
||||
/___/ \\: |. ; ,. :' \\/ / ; / \\ ' | |
|
||||
.-'.. ' ' .' | |: : \\ \\.' / / / || | :
|
||||
/___/ \\: '' | .; : \\ ; ; . ' / |' : |__
|
||||
. \\ ' .\\ | : | / \\ \\ \\ ' ; /|| | '.'|
|
||||
\\ \\ ' \\ | \\ \\ /./__; ; \' | / |; : ;
|
||||
\\ \\ |--" `----' | :/\\ \\ ;| : || , /
|
||||
\\ \\ | `---' `--` \\ \\ / ---`-'
|
||||
'---" `----'
|
||||
""")
|
||||
|
||||
###### MAIN ########
|
||||
if __name__ == "__main__":
|
||||
mainAgent = MainAgent()
|
||||
configName = "config"
|
||||
length = len(sys.argv)
|
||||
for i in range(1, length):
|
||||
arg = sys.argv[i]
|
||||
if (arg == "-c" or arg == "--config"):
|
||||
configName = sys.argv[i + 1]
|
||||
elif (arg == "-h" or arg == "--help"):
|
||||
printLogo()
|
||||
print("usage: wowxel [-h] -c CONFIG_FILE_NAME")
|
||||
print("wowxel: A pixel bot for World of Warcraft")
|
||||
print("optional arguments:")
|
||||
print("-h, --help show this help message and exit")
|
||||
print("-c CONFIG_FILE_NAME, --config CONFIG_FILE_NAME Specify the path to the configuration file (config by default)")
|
||||
print("\n")
|
||||
quit()
|
||||
|
||||
|
||||
mainAgent = MainAgent(configName)
|
||||
cliAgent = CLIAgent(mainAgent)
|
||||
|
||||
cliAgent.run()
|
||||
@@ -0,0 +1,44 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['main.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[('assets', 'assets'), ('config.json', '.')],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='wowxel',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name='wowxel',
|
||||
)
|
||||