Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import socket
- from enum import IntEnum
- from time import sleep, time
- from typing import List
- import struct
- import sys
- IP = "127.0.0.1"
- PORT = 51914
- # How long a button is pressed down for a normal "press and release" button press
- PRESS_DURATION = 0.05
- # For a "default" button press, how long to wait afterwards before moving on
- DEFAULT_WAIT = 0.7
- class Ps3Controls(IntEnum):
- LEFT_STICK_X = 0
- LEFT_STICK_Y = 1
- RIGHT_STICK_X = 2
- RIGHT_STICK_Y = 3
- FINGER1_X = 4
- FINGER1_Y = 5
- FINGER2_X = 6
- FINGER2_Y = 7
- SELECT = 128
- START = 129
- PS = 130
- UP = 131
- RIGHT = 132
- DOWN = 133
- LEFT = 134
- TRIANGLE = 135
- CIRCLE = 136
- CROSS = 137
- SQUARE = 138
- L1 = 139
- R1 = 140
- L2 = 141
- R2 = 142
- L3 = 143
- R3 = 144
- # Convenience shorthand
- CROSS = Ps3Controls.CROSS
- CIRCLE = Ps3Controls.CIRCLE
- TRIANGLE = Ps3Controls.TRIANGLE
- SQUARE = Ps3Controls.SQUARE
- LEFT = Ps3Controls.LEFT
- DOWN = Ps3Controls.DOWN
- UP = Ps3Controls.UP
- R2 = Ps3Controls.R2
- R3 = Ps3Controls.R3
- class ButtonState(IntEnum):
- RELEASED = 0
- PRESSED = 255
- # Initial state of everything being released. This global state will be modified and sent with each button press.
- state = {
- Ps3Controls.LEFT_STICK_X : 0,
- Ps3Controls.LEFT_STICK_Y : 0,
- Ps3Controls.RIGHT_STICK_X : 0,
- Ps3Controls.RIGHT_STICK_Y : 0,
- Ps3Controls.FINGER1_X : 0,
- Ps3Controls.FINGER1_Y : 0,
- Ps3Controls.FINGER2_X : 0,
- Ps3Controls.FINGER2_Y : 0,
- Ps3Controls.SELECT : ButtonState.RELEASED,
- Ps3Controls.START : ButtonState.RELEASED,
- Ps3Controls.PS : ButtonState.RELEASED,
- Ps3Controls.UP : ButtonState.RELEASED,
- Ps3Controls.RIGHT : ButtonState.RELEASED,
- Ps3Controls.DOWN : ButtonState.RELEASED,
- Ps3Controls.LEFT : ButtonState.RELEASED,
- Ps3Controls.TRIANGLE : ButtonState.RELEASED,
- Ps3Controls.CIRCLE : ButtonState.RELEASED,
- Ps3Controls.CROSS : ButtonState.RELEASED,
- Ps3Controls.SQUARE : ButtonState.RELEASED,
- Ps3Controls.L1 : ButtonState.RELEASED,
- Ps3Controls.R1 : ButtonState.RELEASED,
- Ps3Controls.L2 : ButtonState.RELEASED,
- Ps3Controls.R2 : ButtonState.RELEASED,
- Ps3Controls.L3 : ButtonState.RELEASED,
- Ps3Controls.R3 : ButtonState.RELEASED,
- }
- # Check that I can talk to the GIMX server. Return non-zero on failure
- def check_status():
- packet = bytearray([0x00, 0x00])
- sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- sock.connect((IP, PORT))
- sock.send(packet)
- timeval = struct.pack('ll', 1, 0) # seconds and microseconds
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
- try:
- data, (address, port) = sock.recvfrom(2)
- response = bytearray(data)
- if (response[0] != 0x00):
- print("Invalid reply code: {0}".format(response[0]))
- return 1
- except socket.error as err:
- print(err)
- return 0
- def send_message(changes):
- packet = bytearray([0x01, len(changes)]) # type + axis count
- for axis, value in changes.items():
- # axis + value (network byte order)
- packet.extend([axis, (value & 0xff000000) >> 24, (value & 0xff0000) >> 16, (value & 0xff00) >> 8, (value & 0xff)])
- sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- sock.sendto(packet, (IP, PORT))
- def send_key(button: Ps3Controls, button_state: ButtonState):
- """ Updates the state of a single button. """
- global state
- state[button] = button_state
- send_message(state)
- # Press & release a single button at the common press interval. Will wait for 1s after pressing by default
- # but this can be configured with the after_wait argument
- def press(button: Ps3Controls, after_wait: float = DEFAULT_WAIT, press_duration: float = PRESS_DURATION):
- """ Press & release a single button at the common press interval. """
- send_key(button, ButtonState.PRESSED)
- sleep(press_duration)
- send_key(button, ButtonState.RELEASED)
- sleep(after_wait)
- def press_sequence(buttons: List[Ps3Controls]):
- """ Presses a sequence of buttons in order, with the default wait time between them. """
- for button in buttons:
- press(button)
- def hold(button: Ps3Controls, hold_duration: float, after_wait: float = DEFAULT_WAIT):
- """ Hold a button down for a period of time before releasing. """
- press(button, after_wait, hold_duration)
- def repeat_duration(button: Ps3Controls, repeat_duration: float, time_between_presses: float = 0.3):
- """ Presses & releases a single button quickly & repeatedly for a period of time. """
- start_time = time()
- while time() - start_time < repeat_duration:
- press(button, time_between_presses)
- def repeat(button: Ps3Controls, repeats: int, time_between_presses: float = 0.3):
- """ Presses & releases a single button quickly & repeatedly a set number of times. """
- for _ in range(repeats):
- press(button, time_between_presses)
- def wake_controller():
- """ The very first command sent will "wake" the controller but not make it through for action
- If it's already awake then this will actually do something. Therefor I am just pressing
- R3 as worst case scenario it will centre the camera.
- """
- press(R3, 2.0)
- def reset():
- """Just press circle a bunch as a crude "reset" that I can slam in when necessary."""
- repeat_duration(CIRCLE, 15)
- def colosseum_battle(character_from_top: int, enemy_from_bottom: int):
- """ Do a colosseum battle. Requires character to be standing in front of the receptionist & battle skill on R2 button
- Args:
- character_from_top (int): How many times to press 'down' during character select
- enemy_from_bottom (int): How many times to press 'up' after scrolling to the bottom of the enemy list
- """
- # Get to character select
- press_sequence([CROSS, CROSS, CROSS])
- sleep(2)
- # Select the character
- repeat(DOWN, character_from_top)
- press(CROSS)
- # Select the enemy
- hold(R2, 1)
- repeat(UP, enemy_from_bottom)
- press_sequence([CROSS, CROSS, CROSS, LEFT, CROSS])
- sleep(2)
- press(CROSS)
- sleep(4)
- # Skip through pre-match commentary
- repeat(CROSS, 4)
- # Perform battle
- repeat_duration(R2, 20) # This is on for a long time because it will be pressed during the battle loading/intro too
- # Battle victory screen to end can just spam Circle
- repeat_duration(CIRCLE, 15)
- def main():
- if check_status():
- sys.exit(-1)
- wake_controller()
- # reset()
- battles = 0
- while True:
- colosseum_battle(5, 0)
- battles += 1
- if battles % 5 == 0:
- print(f"Completed {battles} battles.")
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement