Skip to content

Instantly share code, notes, and snippets.

@joaoescribano
Created December 31, 2018 16:56
Show Gist options
  • Save joaoescribano/778ce80d4867b11bcc7d2c000d6a2208 to your computer and use it in GitHub Desktop.
Save joaoescribano/778ce80d4867b11bcc7d2c000d6a2208 to your computer and use it in GitHub Desktop.
A Tibia 12 bot
#! python3
from PIL import Image
import pyautogui, sys, time, random, pytesseract, os
print('At any time, press Ctrl-C to quit the bot.\n')
clientDetected = False
clientPlaying = False
accountName = 'account' # Account
accountPass = 'password' # Password
accountChar = 'Character Name' # Desired character to login
accountPremium = False # Auto detected, just a variable
accountTotalChars = 4 # Total chars at account (still need to find a way to do it better)
accountChars = []
acctountLoggedChar = None
def getDirectionAxis(fromX, fromY, toX, toY):
if (toX == fromX):
if (toY < fromY):
return 0
else:
return 4
else:
if (toY == fromY):
if (toX < fromX):
return 6
else:
return 2
else:
if (toX < fromX):
if (toY < fromY):
return 7
else:
return 5
else:
if (toY < fromY):
return 1
else:
return 3
def getDirName(directionAxis):
return {
0: 'N',
1: 'NE',
2: 'E',
3: 'SE',
4: 'S',
5: 'SW',
6: 'W',
7: 'NW',
}[directionAxis]
def getPid(program):
os.system('(pidof ' + program + ') > .tmp')
pid = open('.tmp', 'r').read()
return pid.strip()
def getWindow(pid):
os.system('(xdotool search --pid ' + pid + ') > .tmp')
window = open('.tmp', 'r').read()
return window.strip()
def getActualDesktop():
os.system('(xdotool get_desktop) > .tmp')
desktop = open('.tmp', 'r').read()
return desktop.strip()
def goToDesktop(desktop):
os.system('(xdotool set_desktop ' + desktop + ') > .tmp')
return True
def getWindowDesktop(window):
os.system('(xdotool get_desktop_for_window ' + window + ') > .tmp')
windowDesktop = open('.tmp', 'r').read()
return windowDesktop.strip()
def setFocus(window):
os.system('(xdotool windowfocus ' + window + ') > .tmp')
window = open('.tmp', 'r').read()
return True
def maximizeWindow(window):
os.system('(xdotool windowmove ' + window + ' 0 0) > .tmp')
os.system('(xdotool windowsize ' + window + ' $(xdotool getdisplaygeometry)) > .tmp')
os.system('(xdotool windowactivate ' + window + ') > .tmp')
return True
def minimizeWindow(window):
os.system('(xdotool windowminimize ' + window + ') > .tmp')
return True
def setWindowPos(window, x, y):
os.system('(xdotool windowmove ' + window + ' ' + str(x) + ' ' + str(y) +') > .tmp')
return True
return True
def resizeWindow(window, x, y):
os.system('(xdotool windowsize ' + window + ' ' + str(x) + ' ' + str(y) + ') > .tmp')
return True
def getWindowTitle(window):
os.system('(xdotool getwindowname ' + window + ') > .tmp')
windowTitle = open('.tmp', 'r').read()
return windowTitle.strip()
def clearImage(image):
pixels = image.load()
for i in range(image.size[0]):
for j in range(image.size[1]):
x,y,z = pixels[i,j][0],pixels[i,j][1],pixels[i,j][2]
x,y,z = abs(x-255), abs(y-255), abs(z-255)
# Black Range
if (x >= 100 and x <= 254):
if (y >= 100 and y <= 254):
if (y >= 100 and y <= 254):
x,y,z=255,255,255
pixels[i,j] = (x,y,z)
width, height = image.size
image = image.resize(((width * 2), (height * 2)), Image.NEAREST)
return image
def accountLogin():
global clientDetected, clientPlaying, accountPremium, accountChars, acctountLoggedChar
dialog = pyautogui.locateOnScreen('./images/client_login.png');
if (dialog != None):
dialogX = dialog[0]
dialogY = dialog[1]
delay = (random.randint(1, 25) / 100)
# Account Name
pyautogui.moveTo(dialogX + random.randint(170, 255), dialogY + random.randint(35, 45))
pyautogui.click(button='left', clicks=2, interval=delay)
time.sleep(delay)
pyautogui.press('backspace')
time.sleep(delay)
pyautogui.typewrite(accountName, delay)
time.sleep((random.randint(3,10) / 100))
delay = (random.randint(1, 25) / 100)
# Account Password
pyautogui.moveTo(dialogX + random.randint(170, 255), dialogY + random.randint(65, 75))
pyautogui.click(button='left', clicks=2, interval=delay)
time.sleep(delay)
pyautogui.press('backspace')
time.sleep(delay)
pyautogui.typewrite(accountPass, delay)
time.sleep((random.randint(3,10) / 100))
delay = (random.randint(1, 25) / 100)
# Login Button
pyautogui.moveTo(dialogX + random.randint(170, 255), dialogY + random.randint(145, 161))
pyautogui.click(button='left')
time.sleep(1 + (random.randint(2,5) / 100))
delay = (random.randint(1, 25) / 100)
dialogError = pyautogui.locateOnScreen('./images/login_error.png')
if (dialogError != None):
print('Account login erro detected, trying again.')
dialogErrorX = dialogError[0]
dialogErrorY = dialogError[1]
delay = (random.randint(1, 25) / 100)
pyautogui.moveTo(dialogX + random.randint(243, 280), dialogY + random.randint(66, 84))
pyautogui.click(button='left', clicks=1, interval=delay)
time.sleep((random.randint(3,10) / 100))
delay = (random.randint(1, 25) / 100)
return False
else:
print('Login successfully.')
dialogChars = pyautogui.locateOnScreen('./images/client_characters.png');
if (dialogChars != None):
charactersImg = pyautogui.screenshot(region=(dialogChars[0], dialogChars[1], (dialogChars[0] + 635), (dialogChars[1] + 430)))
showOutfit = pyautogui.locate('./images/active_show_outfit.png', charactersImg)
if (showOutfit != None):
delay = (random.randint(1, 25) / 100)
pyautogui.moveTo(dialogChars[0] + 215, dialogChars[1] + 404)
pyautogui.click(button='left', clicks=1, interval=delay)
time.sleep(1)
charactersImg = pyautogui.screenshot(region=(dialogChars[0], dialogChars[1], (dialogChars[0] + 635), (dialogChars[1] + 430)))
premium = pyautogui.locate('./images/premium.png', charactersImg)
if (premium != None):
print("Detected that this account is a Premium Account.");
accountPremium = True;
for x in range(0, accountTotalChars):
charName = charactersImg.crop((17,(47 + (x * 29)),294,(76 + (x * 29))))
charName = clearImage(charName)
charNameTxt = pytesseract.image_to_string(charName);
charLvl = charactersImg.crop((296,(47 + (x * 29)),339,(76 + (x * 29))))
charLvl = clearImage(charLvl)
charLvlTxt = pytesseract.image_to_string(charLvl);
charClasse = charactersImg.crop((341,(47 + (x * 29)),454,(76 + (x * 29))))
charClasse = clearImage(charClasse)
charClasseTxt = pytesseract.image_to_string(charClasse);
selectedChar = False
if (charNameTxt == accountChar):
selectedChar = True
accountChars.insert(x, (charNameTxt, charClasseTxt, charLvlTxt, selectedChar))
print('Char: ' + charNameTxt + ' - ' + charClasseTxt + ' (' + charLvlTxt + ') ', ("","[Playing]")[selectedChar == True])
for charIdx, char in enumerate(accountChars):
if (char[3] == True):
delay = (random.randint(1, 25) / 100)
pyautogui.moveTo(dialogChars[0] + random.randint(341,454), dialogChars[1] + random.randint((47 + (charIdx * 29)), (76 + (charIdx * 29))))
pyautogui.click(button='left', clicks=2, interval=delay)
time.sleep(1)
clientPlaying = True
acctountLoggedChar = charIdx
print("Account logged successfully")
return True
else:
print('No character selection dialog detected, trying again.')
time.sleep(10)
return False
def detectGameOpen():
global clientDetected, clientPlaying, accountChars, acctountLoggedChar
clientDetected = False
clientPlaying = False
pid = getPid('Tibia/client')
if (pid != False and pid != ""):
window = getWindow(pid)
if (window != False and window != ""):
clientDetected = True
title = getWindowTitle(window).split(" - ")
if (len(title) == 2):
clientPlaying = True
accountChars.insert(0, (title[1], "Unknow", "00", True))
acctountLoggedChar = 0
def detectAlreadyLoggedCharacter():
return True; # TODO
def start():
try:
while True:
if (clientDetected == False):
print('Detecting Tibia Client')
detectGameOpen()
if (clientDetected == False and clientPlaying == False):
print('Could not find the Tibia Client');
time.sleep(15)
if (clientDetected == True and clientPlaying == False):
print('Logging into Tibia account')
accountLogin()
if (clientDetected == True and clientPlaying == True):
# if (acctountLoggedChar == None):
# detectAlreadyLoggedCharacter()
return False
except KeyboardInterrupt:
print('\n\nBot stoped...\n\n')
# main start
start();
if (clientDetected == True and clientPlaying == True):
char = accountChars[acctountLoggedChar]
x, y = pyautogui.position()
positionStr = '\n\nCharacter: ' + char[0] + '\n' + 'Profession: ' + char[1] + '\n' + 'Level: ' + char[2] + '\n\nMouse Position:\nX: ' + str(x).rjust(4) + '\nY: ' + str(y).rjust(4) + '\nDir: ' + getDirName(getDirectionAxis(x,y,2925,191)).ljust(2, ' ')
print(positionStr, end='')
print('\b' * len(positionStr), end='', flush=True)
@Kirattus
Copy link

PyautoGUI é muito bom, porem o FASTGRAB não se compara na performance...
Vlw por compartilhar jovem!

@joaoescribano
Copy link
Author

Opa, valew por compartilhar essa informação! não conhecia o FASTGRAB, provavelmente utilize em outras aplicações.
Valew

@Kirattus
Copy link

Kirattus commented Aug 26, 2021

from fastgrab import screenshot
import pyautogui
import time


inicio = time.time()
for x in range(0,100):
    img = screenshot.Screenshot().capture()
fim = time.time()
print(fim - inicio)

inicio = time.time()
for x in range(0,100):
    img = pyautogui.screenshot()
fim = time.time()
print(fim - inicio)

Output:
1.085~
10.25~

eu gostei foi do seu projeto "pyxdotool-wrapper", aproveitei ele todo, performance 100x melhor que do meu projeto.
Não sei se você percebeu nos seus testes(se testou já haha), mas o PyAutoGUI freeza o jogo (.5sec~ no linux) quando faz interações (click e Hotkeys). O pynput (keyboard) já não tive esse problema...
Nunca trabalhei com programação, mas fico brincando com python pra desenvolver minha logica haha
Espero ter compartilhado algo de útil também... tmj

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment