donutsorelse
Published © GPL3+

Turning Palworld Into a Workout App with Memes and Code

For every bit of damage, you owe a pushup. The code keeps track of the number of times you take damage and keeps your pushup tally for you.

IntermediateFull instructions provided2 hours75
Turning Palworld Into a Workout App with Memes and Code

Story

Read more

Code

getRippedInPalworld

Python
import cv2
import pytesseract
import pyautogui
from gtts import gTTS
import pygame
import time
import keyboard
import os
import re
from playsound import playsound
from datetime import datetime



# Set the working directory to the location of the script
script_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(script_dir)

# Set the path to the Tesseract executable
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

# Initialize Pygame mixer for audio playback
pygame.mixer.init()


# Function to capture a screenshot of the game screen
def capture_screenshot():
    screenshot = pyautogui.screenshot()
    screenshot_path = "screenshot.png"
    screenshot.save(screenshot_path)
    print(f"Screenshot captured and saved as {screenshot_path}")

# Function to check if the player has taken damage
def check_damage(text, previous_health):
    # You may need to adjust the text recognition logic based on the health bar's format
    try:
        current_health = int(text)
        if current_health < previous_health:
            return True, current_health
    except ValueError:
        pass
    return False, previous_health

# Function to perform the action when damage is taken
def perform_action(pushup_count):
    pushup_count += 1
    print(pushup_count)
    message = f"You've taken damage! You owe {pushup_count} pushup(s)."
    print(message)
    # Use text-to-speech (TTS) to say the prompt
    tts = gTTS(message)
    tts.save("pushup_prompt.mp3")
    pygame.mixer.music.load("pushup_prompt.mp3")
    pygame.mixer.music.play()
    return pushup_count


# Function to reset pushup count and announcement flag
def reset_pushup_count():
    global pushup_count
    global pushup_announced
    pushup_count = 0
    # pushup_announced = False
    
                
    date_string = datetime.now().strftime("%d%m%Y%H%M%S")
    filename = f"pushup_prompt{date_string}.mp3"
    play_audio_and_delete(f"Pushup count reset", filename)
    return pushup_count


# Main loop
pushup_count = 0
previous_health = -1
unlock_add_pushups = True
max_health=500


def extract_health_info(text):
    substitutions = {'s': '5', 'S': '5', '/S': '/5', 'O': '0', 'o': '0', 'i':'1', 'I':'1', 'l':'1','L':'1', 'B':'8', '%':'8'}
    print("text pre substitutioN: ")
    print(text)
    for key, value in substitutions.items():
        text = text.replace(key, value)

    print("text after substitution: ")
    print(text)
    match = re.search(r'(\d+)\s*[/\\-]\s*(\d+)', text)    
   
    if match:
        current_health = int(match.group(1))
        max_health = int(match.group(2))
        print(current_health)
        print(max_health)
        return current_health, max_health
    else:
        return None, None

#Todo keep expanding list as I get bad results (regex is slow - no more regex)
def contains_special_chars(text, special_chars=['T', "'", '"']):
    return any(char in text for char in special_chars)

# Function to delete the audio file if it exists
def delete_audio_file(file_path):
    if os.path.exists(file_path):
        os.remove(file_path)


def extract_text_from_screenshot(image_path):
    # Read the image
    image = cv2.imread(image_path)

    # Define the region to crop (x, y, width, height) for the health bar
    x, y, width, height = 70, 975, 220, 30  # Adjust these values based on your game's UI

    # Crop the region of interest
    cropped_region = image[y:y+height, x:x+width]

    # Convert the image to grayscale
    gray = cv2.cvtColor(cropped_region, cv2.COLOR_BGR2GRAY)

    # Apply thresholding to get a binary image
    _, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)

    # Apply Gaussian blur to smooth the image
    blur = cv2.GaussianBlur(thresh, (5, 5), 0)

    # Save the pre-processed image for debugging
    cv2.imwrite("preprocessed.png", blur)

    # Extract text using pytesseract
    text = pytesseract.image_to_string(blur, config='--psm 6')
    print(f"Extracted text from screenshot: {text}")
    return text

def extract_numbers_and_slash(text):
    if len(text) > 0:
        # Use regular expression to extract numbers and '/'
        text = re.sub(r'[^0-9/]', '', text)
    return text

max_health_range = 500
current_health = 221222
# Function to play audio using gTTS and delete the file after playing
def play_audio_and_delete(message, filename):
    tts = gTTS(message)
    tts.save(filename)
    playsound(filename)
    os.remove(filename)

while True:
    try:
        # Capture a screenshot of the game screen
        capture_screenshot()
        
        # Extract text from the health bar region of the screenshot
        extracted_text = extract_text_from_screenshot("screenshot.png")
        
        # Extract health information from the recognized text
        health_info = extract_health_info(extracted_text)


        if health_info is not None:
            temp_current_health, temp_max_health = health_info

            #palworld doesnt have 0 for health shown - this means it missed the first digit
            if temp_current_health is not None and temp_current_health >0 :
                current_health = temp_current_health
            if temp_max_health is not None:
                max_health = temp_max_health


            if previous_health == -1 and current_health is not None and current_health !=221222:
                previous_health = current_health
            if max_health is not None:
                if 500 <= max_health <= 2000:
                    max_health_range = max_health

            # Convert integers to strings before concatenation
            previous_health_str = str(previous_health) if previous_health is not None else 'None'
            current_health_str = str(current_health) if current_health is not None else 'None'
            max_health_range_str = str(max_health_range) if max_health_range is not None else 'None'

            print("Previous health: " + previous_health_str + 
                "  Current health: " + current_health_str + 
                "  max_health_range:  " + max_health_range_str)

            if current_health is not None and previous_health is not None:
                if current_health <= max_health_range and current_health < previous_health:
                    print("In pushup check - should make me do one")
                    try:
                        pushup_count+=1
                        
                        date_string = datetime.now().strftime("%d%m%Y%H%M%S")
                        filename = f"pushup_prompt{date_string}.mp3"
                        play_audio_and_delete(f"You owe {pushup_count} pushup(s).", filename)
                        previous_health = current_health
                    except Exception as e:
                        pushup_count-=1 #don't spam increase pushup count if something goes wrong
                        print(f"An error occurred while playing audio: {e}")
            previous_health = current_health

        health_info = extract_health_info(extracted_text)
        
        
        # Check if the reset hotkey is pressed (e.g., Ctrl + R)
        if keyboard.is_pressed('ctrl+r'):
            print("Resetting pushup count!")
            reset_pushup_count()
        # Get the current pushup count
        if keyboard.is_pressed('ctrl+p'):
            date_string = datetime.now().strftime("%d%m%Y%H%M%S")
            filename = f"pushup_prompt{date_string}.mp3"
            play_audio_and_delete(f"You owe {pushup_count} pushup(s).", filename)

        # Adjust the frequency of checking the game screen (e.g., every 5 seconds)
        time.sleep(5)
    except Exception as e:
        print(f"An error occurred: {str(e)}")

Credits

donutsorelse

donutsorelse

16 projects • 15 followers
I make different stuff every week of all kinds. Usually I make funny yet useful inventions.

Comments