So I have a Python script which I have been working on for some time and I am coming across a small issue and I can’t seem to figure it out.
So for a small debrief, this basically what the functionality needs to be:
- Click on the Spirit Attraction Potion 1 (Dose 1).
- Set the end time for 15 minutes later.
- Click on the Seren Stones in a random sequence within the 15 minutes.
- After 15 minutes, stop clicking Seren Stones and click on the next dose of the potion.
- Repeat until all doses of the potion are used.
- Move to the next potion and repeat the process.
So here are the logs that are produced:
07:59:19 - Initial delay of 10 seconds before first click.
07:59:29 - Clicked on Spirit Attraction Potion 1 (Dose 1). Total clicks: 1
07:59:32 - Current time: 07:59:32, End time set to 08:14:32
07:59:32 - Clicked on Seren stone. Total clicks: 2
08:05:37 - Clicked on Seren stone. Total clicks: 3
08:11:52 - Clicked on Seren stone. Total clicks: 4
08:17:03 - 15 minutes interval completed for Potion 1, Dose 1.
08:17:04 - Clicked on Spirit Attraction Potion 1 (Dose 2). Total clicks: 5
Question:
As we can see, the end time was set at 08:14:32, which was 15 mins after 07:59:32, however for some reason, the 15 minute interval did not complete until 08:17:03, it should have completed at 08:14:32. I have tried everything and I can’t seem to figure out what is wrong so I could use some assistance.
Here is the code:
import time
import random
import logging
import sys
import threading
import pyautogui
from pynput.keyboard import Listener, KeyCode
# Setup logging to output to the console
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%H:%M:%S',
stream=sys.stdout
)
# Activation keys
START_STOP_KEY = KeyCode(char='-')
EXIT_KEY = KeyCode(char='+')
# Configuration
INITIAL_DELAY = 10 # Initial delay before the first click (seconds)
SEREN_CLICK_INTERVAL_MIN = 300 # Minimum interval between Seren stone clicks (seconds)
SEREN_CLICK_INTERVAL_MAX = 600 # Maximum interval between Seren stone clicks (seconds)
POST_CLICK_DELAY = 3 # Delay after each click (seconds)
# Global state
running = False
click_count = 0
click_thread = None
lock = threading.Lock()
def on_press(key):
global running, click_thread
try:
if key == START_STOP_KEY:
with lock:
running = not running
if running:
logging.info("Script started.")
click_thread = threading.Thread(target=click_loop)
click_thread.start()
else:
logging.info("Script stopped.")
elif key == EXIT_KEY:
logging.info(f"Exiting script. Total clicks made: {click_count}")
with lock:
running = False
if click_thread:
click_thread.join()
listener.stop()
except Exception as e:
logging.error(f"Error in on_press: {e}")
def click_loop():
global click_count, running
try:
logging.info(f"Initial delay of {INITIAL_DELAY} seconds before first click.")
time.sleep(INITIAL_DELAY)
while running:
try:
perform_click_sequence()
except Exception as e:
logging.error(f"Error during click loop iteration: {e}")
with lock:
running = False
except Exception as e:
logging.error(f"Error in click_loop: {e}")
with lock:
running = False
def perform_click_sequence():
global click_count
try:
# Define coordinate ranges for each potion (example ranges)
potion_coordinate_ranges = [
((1560, 1576), (838, 860)), # Potion 1 (Row 3)
((1602, 1622), (838, 860)), # Potion 2 (Row 3)
((1645, 1664), (838, 860)), # Potion 3 (Row 3)
((1686, 1708), (838, 860)), # Potion 4 (Row 3)
((1560, 1576), (874, 896)), # Potion 1 (Row 4)
((1602, 1622), (874, 896)), # Potion 2 (Row 4)
((1645, 1664), (874, 896)), # Potion 3 (Row 4)
((1686, 1708), (874, 896)), # Potion 4 (Row 4)
((1560, 1576), (908, 930)), # Potion 1 (Row 5)
((1602, 1622), (908, 930)), # Potion 2 (Row 5)
((1645, 1664), (908, 930)), # Potion 3 (Row 5)
((1686, 1708), (908, 930)), # Potion 4 (Row 5)
((1560, 1576), (946, 968)), # Potion 1 (Row 6)
((1602, 1622), (946, 968)), # Potion 2 (Row 6)
((1645, 1664), (946, 968)), # Potion 3 (Row 6)
((1686, 1708), (946, 968)), # Potion 4 (Row 6)
# ... add coordinate ranges for all 26 potions
]
for potion_number in range(1, 16): # Loop through 26 potions
for dose in range(4): # Each potion has 4 doses
if not running:
logging.info("Script is not running. Exiting click sequence.")
return
# Get the coordinate range for the current potion
x_range, y_range = potion_coordinate_ranges[potion_number - 1]
# Generate random coordinates within the specified range
x = random.randint(x_range[0], x_range[1])
y = random.randint(y_range[0], y_range[1])
# Click on the current potion
click(f"Clicked on Spirit Attraction Potion {potion_number} (Dose {dose + 1})", x, y)
time.sleep(POST_CLICK_DELAY)
# Calculate the end time for the 15-minute interval
end_time = time.time() + 15 * 60
logging.info(f"Current time: {time.strftime('%H:%M:%S', time.localtime(time.time()))}, End time set to {time.strftime('%H:%M:%S', time.localtime(end_time))}")
# Click Seren stones in a random sequence within the 15 minutes
while time.time() < end_time:
if not running:
logging.info("Script is not running. Exiting click sequence.")
return
click("Clicked on Seren stone", random.randint(780, 965), random.randint(335, 380))
# Sleep for a random interval between clicks on Seren stone
time.sleep(random.uniform(SEREN_CLICK_INTERVAL_MIN, SEREN_CLICK_INTERVAL_MAX))
time.sleep(POST_CLICK_DELAY)
logging.info(f"15 minutes interval completed for Potion {potion_number}, Dose {dose + 1}.")
except Exception as e:
logging.error(f"Error in perform_click_sequence: {e}")
def click(description, x, y):
global click_count
pyautogui.moveTo(x, y)
pyautogui.click()
click_count += 1
logging.info(f"{description}. Total clicks: {click_count}")
try:
with Listener(on_press=on_press) as listener: # Start the keyboard listener
logging.info("Listener started. Press '-' to start/stop and '+' to exit.")
listener.join() # Wait for the listener to stop
except Exception as e:
logging.error(f"Error starting listener: {e}")
Thanks all!