Compare commits

...

13 Commits

Author SHA1 Message Date
srose 117a2fc63e Fix callback found after finding spell 2024-10-12 15:05:54 -04:00
srose 154bdbbd9f Add humanReaction 2024-10-10 20:29:15 -04:00
srose 0b8d761a37 Add chatgpt test + recorder test 2024-10-08 22:24:08 -04:00
srose d939ade3be More hunter routine 2024-09-28 21:38:54 -04:00
srose 20b77c9168 Updated hunter mark routine 2024-09-28 18:51:47 -04:00
srose fe2d532dc1 Add routine for hunter mark first step 2024-09-28 14:40:11 -04:00
srose da1ba01120 Added hunter spells 2024-09-27 01:26:55 -04:00
srose c1bdce49a8 Added new cli parser 2024-09-22 20:07:09 -04:00
srose 9b0fe2183b Added debug mode + fighting agent class 2024-09-22 16:00:48 -04:00
srose 29f9ce5140 Added lang + findAndClick Function 2024-09-22 13:41:23 -04:00
srose cdcc70d7de New build script + bg farming bot v1 2024-09-15 22:36:12 -04:00
srose b8cd6a09ed bobber improvements 2024-09-14 23:52:23 -04:00
srose 3fffad6a99 Fix fishing agent 2024-09-12 10:05:08 -04:00
70 changed files with 502 additions and 54 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

+98
View File
@@ -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()
+27
View File
@@ -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()
+47
View File
@@ -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()
+30 -14
View File
@@ -6,26 +6,35 @@ import cv2 as cv
import pyautogui import pyautogui
from core.Logger import Logger from core.Logger import Logger
from core.Player import PLAYER_STATE from core.Player import PLAYER_STATE
from core.utils import addHumanReaction
class FishingAgent: class FishingAgent:
def __init__(self, monitor, player) -> None: def __init__(self, monitor, player) -> None:
self.fishingBobberImg = cv.imread("assets/fishing/Bobber.jpg", cv.IMREAD_GRAYSCALE) self.fishingBobberImg = cv.imread("assets/fishing/bobbers/Bobber2.jpg", cv.IMREAD_GRAYSCALE)
self.fishingIconImg = cv.imread("assets/fishing/FishIcon.jpg", cv.IMREAD_GRAYSCALE) self.fishingIconImg = cv.imread("assets/fishing/FishIcon.jpg", cv.IMREAD_GRAYSCALE)
self.fishingThread = None self.fishingThread = None
self.logger = Logger("Fishing Agent") self.logger = Logger("Fishing Agent", player.debug)
self.monitor = monitor
self.lureLoc = None self.lureLoc = None
self.monitor = monitor
self.player = player self.player = player
self.fail = 0
self.retry = 0 self.retry = 0
def startFishing(self): def startFishing(self):
self.player.checkConnection()
self.player.changeState(PLAYER_STATE.FISHING) self.player.changeState(PLAYER_STATE.FISHING)
while self.player.state is PLAYER_STATE.FISHING: while self.player.state is PLAYER_STATE.FISHING:
if (self.fail > 5):
self.fail = 0
self.logger.log("Fishing failed too many times. Stopping fishing thread...")
self.player.changeState(PLAYER_STATE.IDLE)
return
self.castLure() self.castLure()
def castLure(self): def castLure(self):
self.retry = 0 self.retry = 0
pyautogui.moveTo(2,3) self.lureLoc = None
pyautogui.moveTo(50,50)
self.logger.log("Casting Lure.") self.logger.log("Casting Lure.")
res = self.monitor.findMatchAndMoveToPosition(self.fishingIconImg) res = self.monitor.findMatchAndMoveToPosition(self.fishingIconImg)
if (res == -1): if (res == -1):
@@ -39,33 +48,40 @@ class FishingAgent:
self.logger.log("Moving cursor to Lure.") self.logger.log("Moving cursor to Lure.")
time.sleep(2) time.sleep(2)
res = self.monitor.findMatch(self.fishingBobberImg) res = self.monitor.findMatch(self.fishingBobberImg)
if (res == -1): if (res == -1):
if (self.retry > 4): if (self.retry > 4):
self.logger.log("Took too to find lure long, retrying fishing from the beginning") self.fail += 1
return self.logger.log("Took too long to find lure, retrying fishing from the beginning")
else: else:
self.logger.log("Trying again in 1 second...") self.logger.log("Trying again in 1 second...")
self.retry += 1 self.retry += 1
time.sleep(1) time.sleep(1)
self.findLure() self.findLure()
self.lureLoc = res else:
time.sleep(0.2) addHumanReaction()
pyautogui.moveTo(res[0], res[1]) pyautogui.moveTo(res[0], res[1])
self.watchLure() self.watchLure()
def watchLure(self): def watchLure(self):
self.retry = 0 self.retry = 0
self.logger.log("Waiting for fish...") self.logger.log("Waiting for fish...")
addHumanReaction()
res = self.monitor.findMatch(self.fishingBobberImg)
if (res != -1):
self.lureLoc = res
while True: while True:
self.retry += 1 self.retry += 1
time.sleep(0.1) addHumanReaction()
res = self.monitor.findMatch(self.fishingBobberImg) res = self.monitor.findMatch(self.fishingBobberImg)
print(res) print(res)
if (res != -1 and abs(res[1] - self.lureLoc[1]) > 20): if (res == -1 or abs(res[1] - self.lureLoc[1]) > 20):
addHumanReaction()
pyautogui.click() pyautogui.click()
time.sleep(0.5)
return return
elif (self.retry > 200): elif (self.retry > 150):
self.retry = 0
self.fail += 1
return return
def run(self): def run(self):
+7 -6
View File
@@ -1,20 +1,21 @@
import time import time
import pyautogui
from threading import Thread from threading import Thread
import pyautogui
from core.Logger import Logger from core.Logger import Logger
from core.Player import PLAYER_STATE from core.Player import PLAYER_STATE
class IdlingAgent: class IdlingAgent:
def __init__(self, playerAgent) -> None: def __init__(self, monitor, player) -> None:
self.logger = Logger("Idling Agent") self.logger = Logger("Idling Agent", player.debug)
self.idleTime = time.time() self.idleTime = time.time()
self.idleThread = None self.idleThread = None
self.player = playerAgent self.player = player
self.monitor = monitor
def checkIdleTime(self): 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 elapsedTime = time.time() - self.idleTime
if (elapsedTime > 10): if (elapsedTime > 60):
self.logger.log("Jumping to avoid being afk...") self.logger.log("Jumping to avoid being afk...")
pyautogui.press("space") pyautogui.press("space")
self.idleTime = time.time() self.idleTime = time.time()
+9
View File
@@ -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 ..;
+3
View File
@@ -1,5 +1,8 @@
{ {
"antiAfk": true, "antiAfk": true,
"class": "DRUID", "class": "DRUID",
"spe": "RESTORATION",
"debug": false,
"lang": "en",
"name": "Droïde" "name": "Droïde"
} }
+8
View File
@@ -0,0 +1,8 @@
{
"antiAfk": true,
"class": "HUNTER",
"spe": "MARKSMANSHIP",
"debug": false,
"lang": "en",
"name": "Aelyss"
}
+6
View File
@@ -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
+4 -3
View File
@@ -1,4 +1,5 @@
import json
class Config: class Config:
def __init__(self) -> None: def __init__(self, configName = "config") -> None:
## PASS JSON CONFIG HERE AND DECLARE IT TO THE MAIN AGENT with open(configName + ".json", encoding="utf-8") as jsonFile:
pass self.file = json.load(jsonFile)
+46
View File
@@ -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()
+8 -2
View File
@@ -1,9 +1,15 @@
import datetime; import datetime;
class Logger: class Logger:
def __init__(self, name = "Logger") -> None: def __init__(self, name = "Logger", debug = False) -> None:
self.isDebug = debug
self.name = name self.name = name
def log(self, message): def log(self, message):
ct = datetime.datetime.now() ct = datetime.datetime.now()
print(ct.strftime("%m/%d/%Y-%H:%M:%S:"), self.name, ">>", message) 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)
+20 -5
View File
@@ -1,21 +1,36 @@
from core.Config import Config
from core.Monitor import Monitor from core.Monitor import Monitor
from bots.battleground.battlegroundAgent import BattlegroundAgent
from bots.fishing.FishingAgent import FishingAgent from bots.fishing.FishingAgent import FishingAgent
from bots.fighting.FightingAgent import FightingAgent
from bots.idling.IdlingAgent import IdlingAgent from bots.idling.IdlingAgent import IdlingAgent
from core.Player import Player, PLAYER_STATE from core.Player import Player, PLAYER_STATE
class MainAgent: class MainAgent:
def __init__(self) -> None: def __init__(self, configName = "config ") -> None:
self.monitor = Monitor() self.config = Config(configName)
self.playerAgent = Player() self.monitor = Monitor(self.config)
self.idlingBot = IdlingAgent(self.playerAgent) 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.fishingBot = FishingAgent(self.monitor, self.playerAgent)
self.bgFarming = BattlegroundAgent(self.monitor, self.playerAgent)
self.monitor.startScreenCaptureThread() self.monitor.startScreenCaptureThread()
# Start idling agent at the construction of the mainAgent for now # Start idling agent at the construction of the mainAgent for now
self.idlingBot.run() self.idlingBot.run()
def startFishBot(self): def startFishBot(self):
self.playerAgent.changeState(PLAYER_STATE.FISHING) self.playerAgent.changeState(PLAYER_STATE.FISHING)
self.fishingBot.run() 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()
+35 -9
View File
@@ -1,16 +1,20 @@
import time import time
from threading import Thread from threading import Thread
from inspect import isfunction
from screeninfo import get_monitors from screeninfo import get_monitors
import pyautogui import pyautogui
import numpy as np import numpy as np
import cv2 as cv import cv2 as cv
from core.Logger import Logger from core.Logger import Logger
from core.utils import addHumanReaction
FPS_REPORT_DELAY = 3 FPS_REPORT_DELAY = 3
class Monitor: class Monitor:
def __init__(self): def __init__(self, config):
self.logger = Logger("Monitor") self.config = config
self.isDebug = self.config.file["debug"]
self.logger = Logger("Monitor", self.isDebug)
self.monitor = None self.monitor = None
self.screenThread = None self.screenThread = None
self.screenshot = None self.screenshot = None
@@ -33,7 +37,8 @@ class Monitor:
newScreenshot = cv.cvtColor(np.array(newScreenshot), cv.COLOR_RGB2BGR) newScreenshot = cv.cvtColor(np.array(newScreenshot), cv.COLOR_RGB2BGR)
grayScreenshot = cv.cvtColor(newScreenshot, cv.COLOR_BGR2GRAY) grayScreenshot = cv.cvtColor(newScreenshot, cv.COLOR_BGR2GRAY)
self.screenshot = grayScreenshot self.screenshot = grayScreenshot
cv.imwrite("assets/screenshot.jpg", self.screenshot) if (self.isDebug is True):
cv.imwrite("assets/screenshot.jpg", self.screenshot)
currTime = time.time() currTime = time.time()
if currTime - fpsPrintTime >= FPS_REPORT_DELAY: if currTime - fpsPrintTime >= FPS_REPORT_DELAY:
self.fps = 1 / (currTime - loopTime) self.fps = 1 / (currTime - loopTime)
@@ -45,6 +50,10 @@ class Monitor:
self.screenThread.start() self.screenThread.start()
self.logger.log("Main Agent: Thread started") self.logger.log("Main Agent: Thread started")
# TODO: GET IMAGE BEST MATCH RATIO FOR A WHOLE DIRECTORY OF ASSETS
def findBestMatchFromDir(self, dirPath):
pass
def findMatch(self, template, method = "TM_CCOEFF_NORMED"): def findMatch(self, template, method = "TM_CCOEFF_NORMED"):
methodInt = getattr(cv, method) methodInt = getattr(cv, method)
res = cv.matchTemplate(self.screenshot, template, methodInt) res = cv.matchTemplate(self.screenshot, template, methodInt)
@@ -52,9 +61,10 @@ class Monitor:
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res) min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
matchRatio = max_val * 100 matchRatio = max_val * 100
self.logger.log(matchRatio) self.logger.debug(matchRatio)
if (matchRatio < 55): # Consider a match if ratio is at least 50%
self.logger.log("Cannot find matching result...") if (matchRatio < 50):
self.logger.debug("Cannot find matching result...")
return -1 return -1
# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
@@ -69,10 +79,26 @@ class Monitor:
def findMatchAndMoveToPosition(self, template, method = "TM_CCOEFF_NORMED"): def findMatchAndMoveToPosition(self, template, method = "TM_CCOEFF_NORMED"):
point = self.findMatch(template, method) point = self.findMatch(template, method)
if (point == -1): if (point == -1):
return -1 return -1
time.sleep(0.2) addHumanReaction()
pyautogui.moveTo(point[0], point[1]) 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): def stopScreenCaptureThread(self):
if (self.screenThread): if (self.screenThread):
+30 -10
View File
@@ -1,22 +1,42 @@
import json
from enum import Enum from enum import Enum
import time
import cv2 as cv
from core.Logger import Logger from core.Logger import Logger
CONNECT_STATUS = Enum('CONNECT_STATUS', ["CONNECTED", "CONNECTING", "DISCONNECTED"]) CONNECT_STATUS = Enum('CONNECT_STATUS', ["CONNECTED", "CONNECTING", "DISCONNECTED"])
CLASSES = Enum('CLASSES', ['DRUID', 'MAGE', 'HUNTER', 'PRIEST']) 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: class Player:
def __init__(self) -> None: def __init__(self, monitor, config) -> None:
with open("config.json", encoding="utf-8") as jsonFile: self.config = config
self.config = json.load(jsonFile) self.isConnected = None
self.isConnected = CONNECT_STATUS.DISCONNECTED
self.idleThread = None self.idleThread = None
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.state = PLAYER_STATE.IDLE
self.playerClass = self.config["class"] self.monitor = monitor
self.playerName = self.config["name"] self.playerClass = self.config.file["class"]
self.logger.log("Connected with " + self.playerName + " (" + self.playerClass + ")") 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 connectButtonFound(self, _res):
self.isConnected = CONNECT_STATUS.DISCONNECTED
self.logger.log("Player not connected attempting to connect...")
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): def changeState(self, newState):
self.state = newState self.state = newState
+10 -4
View File
@@ -5,13 +5,16 @@ class CLIAgent:
def __init__(self, mainAgent) -> None: def __init__(self, mainAgent) -> None:
self.isRunning = False self.isRunning = False
self.logger = Logger("CliAgent") self.logger = Logger("CliAgent")
if (not mainAgent):
if (not mainAgent):
raise Exception("Main agent not found...") raise Exception("Main agent not found...")
self.mainAgent = mainAgent self.mainAgent = mainAgent
def printMenu(self): def printMenu(self):
print("Enter a command:") print("Enter a command:")
print("\tH\tHelp.") print("\tH\tHelp.")
print("\tBG\tStart the bg farming agent.")
print("\tC\tToggle fight mode ON/OFF.")
print("\tF\tStart the fishing agent.") print("\tF\tStart the fishing agent.")
print("\tQ\tQuit.") print("\tQ\tQuit.")
print("$>> ", end='') print("$>> ", end='')
@@ -24,8 +27,11 @@ class CLIAgent:
userInput = input() userInput = input()
userInput = str.lower(userInput).strip() userInput = str.lower(userInput).strip()
if (userInput == "f"): if (userInput == "bg"):
self.logger.log("Starting Fishing bot...") self.mainAgent.startBgBot()
elif (userInput == "c"):
self.mainAgent.toggleFightingAgent()
elif (userInput == "f"):
self.mainAgent.startFishBot() self.mainAgent.startFishBot()
elif (userInput == "h"): elif (userInput == "h"):
self.printMenu() self.printMenu()
@@ -33,7 +39,7 @@ class CLIAgent:
cv.destroyAllWindows() cv.destroyAllWindows()
self.logger.log("Exiting application...") self.logger.log("Exiting application...")
self.isRunning = False self.isRunning = False
else: else:
self.logger.log("Unknown Command.") self.logger.log("Unknown Command.")
self.printMenu() self.printMenu()
+1
View File
@@ -0,0 +1 @@
gptApiKey = "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"
+6
View File
@@ -0,0 +1,6 @@
import time
import random
def addHumanReaction():
delay = random.uniform(0.1, 0.4)
time.sleep(delay)
+36 -1
View File
@@ -1,9 +1,44 @@
import sys
from core.cli.CliAgent import CLIAgent from core.cli.CliAgent import CLIAgent
from core.MainAgent import MainAgent from core.MainAgent import MainAgent
def printLogo():
print("""
,--,
,--.'|
.---. ,---. | | :
/. ./| ' ,'\\ ,--, ,--, : : '
.-'-. ' | / / ||'. \\/ .`| ,---. | ' |
/___/ \\: |. ; ,. :' \\/ / ; / \\ ' | |
.-'.. ' ' .' | |: : \\ \\.' / / / || | :
/___/ \\: '' | .; : \\ ; ; . ' / |' : |__
. \\ ' .\\ | : | / \\ \\ \\ ' ; /|| | '.'|
\\ \\ ' \\ | \\ \\ /./__; ; \' | / |; : ;
\\ \\ |--" `----' | :/\\ \\ ;| : || , /
\\ \\ | `---' `--` \\ \\ / ---`-'
'---" `----'
""")
###### MAIN ######## ###### MAIN ########
if __name__ == "__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 = CLIAgent(mainAgent)
cliAgent.run() cliAgent.run()
+44
View File
@@ -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',
)