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
|
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/bobbers/Bobber2.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.fail = 0
|
||||||
self.retry = 0
|
self.retry = 0
|
||||||
@@ -52,32 +53,33 @@ class FishingAgent:
|
|||||||
if (self.retry > 4):
|
if (self.retry > 4):
|
||||||
self.fail += 1
|
self.fail += 1
|
||||||
self.logger.log("Took too long to find lure, retrying fishing from the beginning")
|
self.logger.log("Took too long to find lure, retrying fishing from the beginning")
|
||||||
return
|
|
||||||
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()
|
||||||
time.sleep(0.5)
|
else:
|
||||||
self.lureLoc = res
|
addHumanReaction()
|
||||||
pyautogui.moveTo(self.lureLoc[0], self.lureLoc[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(self.lureLoc)
|
|
||||||
print(res)
|
print(res)
|
||||||
if (res != -1 and abs(res[1] - self.lureLoc[1]) > 10):
|
if (res == -1 or abs(res[1] - self.lureLoc[1]) > 20):
|
||||||
time.sleep(0.2)
|
addHumanReaction()
|
||||||
pyautogui.click()
|
pyautogui.click()
|
||||||
time.sleep(0.5)
|
|
||||||
return
|
return
|
||||||
elif (self.retry > 200):
|
elif (self.retry > 150):
|
||||||
self.retry = 0
|
self.retry = 0
|
||||||
self.fail += 1
|
self.fail += 1
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ from core.Logger import Logger
|
|||||||
from core.Player import PLAYER_STATE
|
from core.Player import PLAYER_STATE
|
||||||
|
|
||||||
class IdlingAgent:
|
class IdlingAgent:
|
||||||
def __init__(self, monitor, 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
|
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()
|
||||||
|
|||||||
@@ -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,
|
"antiAfk": true,
|
||||||
"class": "DRUID",
|
"class": "DRUID",
|
||||||
|
"spe": "RESTORATION",
|
||||||
|
"debug": false,
|
||||||
|
"lang": "en",
|
||||||
"name": "Droïde"
|
"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:
|
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)
|
||||||
@@ -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;
|
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)
|
||||||
@@ -1,14 +1,20 @@
|
|||||||
|
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)
|
self.monitor = Monitor(self.config)
|
||||||
|
self.playerAgent = Player(self.monitor, self.config)
|
||||||
self.idlingBot = IdlingAgent(self.monitor, self.playerAgent)
|
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()
|
||||||
@@ -17,4 +23,14 @@ class MainAgent:
|
|||||||
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()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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,6 +37,7 @@ 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
|
||||||
|
if (self.isDebug is True):
|
||||||
cv.imwrite("assets/screenshot.jpg", self.screenshot)
|
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:
|
||||||
@@ -45,6 +50,7 @@ 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):
|
def findBestMatchFromDir(self, dirPath):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -55,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 < 60):
|
# 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
|
||||||
@@ -73,9 +80,25 @@ class Monitor:
|
|||||||
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):
|
||||||
|
|||||||
@@ -1,42 +1,42 @@
|
|||||||
import json
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import time
|
import time
|
||||||
import cv2 as cv
|
import cv2 as cv
|
||||||
import pyautogui
|
|
||||||
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, monitor) -> 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 = None
|
||||||
self.idleThread = None
|
self.idleThread = None
|
||||||
self.enterWorldButton = cv.imread("assets/menus/EnterWorldButton.jpg", cv.IMREAD_GRAYSCALE)
|
self.antiAfk = self.config.file["antiAfk"]
|
||||||
self.logger = Logger("Player Agent")
|
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.monitor = monitor
|
self.monitor = monitor
|
||||||
self.playerClass = self.config["class"]
|
self.playerClass = self.config.file["class"]
|
||||||
self.playerName = self.config["name"]
|
self.playerSpe = self.config.file["spe"]
|
||||||
self.logger.log("Connected with " + self.playerName + " (" + self.playerClass + ")")
|
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):
|
def connectButtonFound(self, _res):
|
||||||
res = self.monitor.findMatch(self.enterWorldButton)
|
|
||||||
if (res == -1):
|
|
||||||
self.isConnected = CONNECT_STATUS.CONNECTED
|
|
||||||
else:
|
|
||||||
self.isConnected = CONNECT_STATUS.DISCONNECTED
|
self.isConnected = CONNECT_STATUS.DISCONNECTED
|
||||||
self.logger.log("Player not connected attempting to connect...")
|
self.logger.log("Player not connected attempting to connect...")
|
||||||
pyautogui.move(res[0], res[1])
|
time.sleep(30)
|
||||||
time.sleep(0.4)
|
|
||||||
pyautogui.click()
|
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
@@ -5,6 +5,7 @@ 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
|
||||||
@@ -12,6 +13,8 @@ class CLIAgent:
|
|||||||
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()
|
||||||
|
|||||||
@@ -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.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()
|
||||||
@@ -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',
|
||||||
|
)
|
||||||