Пример #1
0
def updateInputs(inputs, scoring, ph):
    PROCESS_ALL_ACCESS = 0x1F0FFF

    rwm = ReadWriteMem.ReadWriteMem()
    pid = rwm.GetProcessIdByName("RocketLeague.exe")
    rocketLeagueBaseAddress = rwm.GetBaseAddress(pid)

    processHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)

    blueScore = None
    orangeScore = None
    blueDemo = None
    orangeDemo = None

    addresses = ph.GetAddressVector(processHandle, rocketLeagueBaseAddress)
    while (True):
        values = ph.GetValueVector(processHandle, addresses)

        # Process scoring to see if any new goals or demos
        if (blueScore == None):
            # Need to update values if don't already exist
            blueScore = values[1][0]
            orangeScore = values[1][1]
            blueDemo = values[1][2]
            orangeDemo = values[1][3]

        if (not blueScore == values[1][0]):
            print("Blue has scored! Waiting for ball and players to reset")
            blueScore = values[1][0]
            time.sleep(15)  # Sleep 15 seconds for goal and replay then ping for correct values
            addresses = ph.GetAddressVector(processHandle, rocketLeagueBaseAddress)
            while (ph.ping_refreshed_pointers(processHandle, addresses)):
                time.sleep(0.5)
                addresses = ph.GetAddressVector(processHandle, rocketLeagueBaseAddress)

        if (not orangeScore == values[1][1]):
            print("Orange has scored! Waiting for ball and players to reset")
            orangeScore = values[1][1]
            time.sleep(15)  # Sleep 15 seconds for goal and replay then ping for correct values
            addresses = ph.GetAddressVector(processHandle, rocketLeagueBaseAddress)
            while (ph.ping_refreshed_pointers(processHandle, addresses)):
                time.sleep(0.5)
                addresses = ph.GetAddressVector(processHandle, rocketLeagueBaseAddress)

        if (not blueDemo == values[1][2]):
            print("Orange has scored a demo on blue! Waiting for blue player to reset")
            blueDemo = values[1][2]
            time.sleep(4)  # Takes about 3 seconds to respawn for a demo
            addresses = ph.GetAddressVector(processHandle, rocketLeagueBaseAddress)

        if (not orangeDemo == values[1][3]):
            print("Blue has scored a demo on orange! Waiting for orange player to reset")
            orangeDemo = values[1][3]
            time.sleep(
                4)  # Takes about 3 seconds to respawn from demo. Even though blue can keep playing, for training I am just sleeping
            addresses = ph.GetAddressVector(processHandle, rocketLeagueBaseAddress)

        # Finally update input to values
        for i in range(len(values[0])):
            inputs[i] = values[0][i]
        for i in range(len(values[1])):
            scoring[i] = values[1][i]
        time.sleep(0.01)
Пример #2
0
from ctypes import *
from ctypes.wintypes import *
import ReadWriteMem
import time
import PlayHelper
import array
import xbox

OpenProcess = windll.kernel32.OpenProcess
CloseHandle = windll.kernel32.CloseHandle

PROCESS_ALL_ACCESS = 0x1F0FFF
LEARNING_RATE = 1e-4 # Need to fiddle with this to find what works well

rwm = ReadWriteMem.ReadWriteMem()
pid = rwm.GetProcessIdByName("RocketLeague.exe")
rocketLeagueBaseAddress = rwm.GetBaseAddress(pid)

processHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)

ph = PlayHelper.play_helper()
addresses = ph.GetAddressVector(processHandle,rocketLeagueBaseAddress)

blueScore = None
orangeScore = None
blueDemo = None
orangeDemo = None

# make / open outfiles
x_file = open('x.csv', 'a')
y_file = open('y.csv', 'a')        
Пример #3
0
class play_helper:

    rwm = ReadWriteMem.ReadWriteMem()

    timeStamp = None
    x = None
    y = None
    z = None
    ballx = None
    bally = None
    ballz = None
    botx = None
    boty = None
    botz = None

    def GetAddressVector(self, processHandle, rocketLeagueBaseAddress):
        addressList = array.array('i',
                                  (0, ) * 41)  # Create a tuple with 41 values

        addressList[0] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x019FCF34, 0xCC, 0x30, 0x54
             ])  # Blue Boost address (Updated August 5, 2017)
        addressList[1] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x018DB9C4, 0x4, 0x20, 0x44])  # Player z address
        addressList[2] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x018DB9C4, 0x8, 0x20, 0x44])  # Ball z address
        addressList[3] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x018DB9C4, 0x0, 0x20, 0x44])  # Bot (orange) z address

        self.verifyPlayerPointers(
            processHandle, addressList
        )  # Still need to deal with demolitions being wacky pointers but that can be done later if possible

        addressList[4] = addressList[1] + 4  # Player y address
        addressList[5] = addressList[1] - 4  # Player x address
        addressList[6] = addressList[2] + 4  # Ball y address
        addressList[7] = addressList[2] - 4  # Ball x address
        addressList[8] = addressList[4] + 8  # Player rot1
        addressList[9] = addressList[8] + 4  # Player rot2
        addressList[10] = addressList[9] + 4  # Player rot3
        addressList[11] = addressList[10] + 8  # Player rot4
        addressList[12] = addressList[11] + 4  # Player rot5
        addressList[13] = addressList[12] + 4  # Player rot6
        addressList[14] = addressList[13] + 8  # Player rot7
        addressList[15] = addressList[14] + 4  # Player rot8
        addressList[16] = addressList[15] + 4  # Player rot9
        addressList[17] = addressList[3] + 4  # Bot y address (orange)
        addressList[18] = addressList[3] - 4  # Bot x address
        addressList[19] = addressList[17] + 8  # Bot rot1
        addressList[20] = addressList[19] + 4  # Bot rot2
        addressList[21] = addressList[20] + 4  # Bot rot3
        addressList[22] = addressList[21] + 8  # Bot rot4
        addressList[23] = addressList[22] + 4  # Bot rot5
        addressList[24] = addressList[23] + 4  # Bot rot6
        addressList[25] = addressList[24] + 8  # Bot rot7
        addressList[26] = addressList[25] + 4  # Bot rot8
        addressList[27] = addressList[26] + 4  # Bot rot9
        addressList[28] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x019A3BA0, 0x8, 0x228, 0x20C])  # Blue score address
        addressList[29] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x019A3BA0, 0x10, 0x228, 0x20C])  # Orange score address
        addressList[30] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x019A3BA0, 0x8, 0x310])  # Blue "Score" address
        addressList[31] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x019A3BA0, 0x10, 0x310])  # Orange "Score" address
        addressList[32] = addressList[30] + 4  # Blue goals
        addressList[33] = addressList[32] + 12  # Blue saves
        addressList[34] = addressList[32] + 16  # Blue shots
        addressList[35] = addressList[31] + 4  # Orange goals
        addressList[36] = addressList[35] + 12  # Orange saves
        addressList[37] = addressList[35] + 16  # Orange shots
        addressList[38] = addressList[37] + 4  # Demos by orange
        addressList[39] = addressList[34] + 4  # Demos by blue
        addressList[40] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x0192F0A4, 0x688, 0x8, 0x30C])  # Orange Boost address

        return addressList

    def getKey(self, item):
        return item[1]

    def verifyPlayerPointers(self, processHandle, addressVect):
        # So after a goal, we have pointers to blue, white, orange, but not necessarily that correct order. Check values and reorganize.
        tupleList = [(addressVect[1],
                      self.rwm.ReadFloatFromAddress(processHandle,
                                                    addressVect[1])),
                     (addressVect[2],
                      self.rwm.ReadFloatFromAddress(processHandle,
                                                    addressVect[2])),
                     (addressVect[3],
                      self.rwm.ReadFloatFromAddress(processHandle,
                                                    addressVect[3]))]
        sortedList = sorted(tupleList, key=self.getKey)
        # Now assign
        addressVect[1] = sortedList[0][0]
        addressVect[2] = sortedList[1][0]
        addressVect[3] = sortedList[2][0]

    def ping_refreshed_pointers(self, processHandle, addressVect):
        # Make sure pointers after goal are pointing to z values that make sense
        tupleList = [(addressVect[1],
                      self.rwm.ReadFloatFromAddress(processHandle,
                                                    addressVect[1])),
                     (addressVect[2],
                      self.rwm.ReadFloatFromAddress(processHandle,
                                                    addressVect[2])),
                     (addressVect[3],
                      self.rwm.ReadFloatFromAddress(processHandle,
                                                    addressVect[3]))]
        sortedList = sorted(tupleList, key=self.getKey)
        value1 = sortedList[0][1]
        value2 = sortedList[1][1]
        value3 = sortedList[2][1]
        if (value1 < -100 or value1 > -30):
            print("Ping failed blue z value check")
            return True
        if (value2 < -5 or value2 > 5):
            print("Ping failed ball z value check")
            return True
        if (value3 < 30 or value3 > 100):
            print("Ping failed orng z value check")
            return True

        # Check boost values are reset
        if (not float(
                self.rwm.ReadIntFromAddress(processHandle, addressVect[0]))
                == 33):
            print("Ping failed blue boost check")
            return True
        if (not float(
                self.rwm.ReadIntFromAddress(processHandle, addressVect[40]))
                == 33):
            print("Ping failed orange boost check")
            return True

        return False

    def GetValueVector(self, processHandle, addressVect):
        neuralInputs = array.array('f', (0, ) *
                                   38)  # Create a tuple with 38 float values
        scoring = array.array('f', (0, ) *
                              14)  # Create a tuple with 14 float values
        # Need to read 28 values for neural inputs and calculate 9 velocities

        # Boost is an int so different case
        neuralInputs[0] = float(
            self.rwm.ReadIntFromAddress(processHandle, addressVect[0]))
        neuralInputs[37] = float(
            self.rwm.ReadIntFromAddress(processHandle, addressVect[40]))
        for i in range(1, 28):
            neuralInputs[i] = self.rwm.ReadFloatFromAddress(
                processHandle, addressVect[i])

        if (self.timeStamp == None):
            # Need to set values for first time reading
            self.timeStamp = time.time()
            self.x = neuralInputs[5]
            self.y = neuralInputs[4]
            self.z = neuralInputs[1]
            self.ballx = neuralInputs[7]
            self.bally = neuralInputs[6]
            self.ballz = neuralInputs[2]
            self.botx = neuralInputs[18]
            self.boty = neuralInputs[17]
            self.botz = neuralInputs[3]

        # Calculate velocities
        curTime = time.time(
        )  # Shouldn't really matter where I put this so long as it is equally spaced apart
        timeDiff = curTime - self.timeStamp
        if (timeDiff == 0):
            timeDiff = 1
        neuralInputs[28] = (neuralInputs[5] - self.x) / timeDiff
        neuralInputs[29] = (neuralInputs[4] - self.y) / timeDiff
        neuralInputs[30] = (neuralInputs[1] - self.z) / timeDiff
        neuralInputs[31] = (neuralInputs[7] - self.ballx) / timeDiff
        neuralInputs[32] = (neuralInputs[6] - self.bally) / timeDiff
        neuralInputs[33] = (neuralInputs[2] - self.ballz) / timeDiff
        neuralInputs[34] = (neuralInputs[18] - self.botx) / timeDiff
        neuralInputs[35] = (neuralInputs[17] - self.boty) / timeDiff
        neuralInputs[36] = (neuralInputs[3] - self.botz) / timeDiff

        # Also create tuple of scoring changes/demos so I can know when reset is necessary
        scoring[0] = float(
            self.rwm.ReadIntFromAddress(processHandle,
                                        addressVect[28]))  # Blue Score
        scoring[1] = float(
            self.rwm.ReadIntFromAddress(processHandle,
                                        addressVect[29]))  # Orange Score
        scoring[2] = float(
            self.rwm.ReadIntFromAddress(processHandle,
                                        addressVect[38]))  # Demos on blue
        scoring[3] = float(
            self.rwm.ReadIntFromAddress(processHandle,
                                        addressVect[39]))  # Demos on orange

        # Now fill in the other scoring values
        for i in range(30, 38):
            scoring[i - 26] = float(
                self.rwm.ReadIntFromAddress(processHandle, addressVect[i]))

        # Now update to old values
        self.timeStamp = curTime
        self.x = neuralInputs[5]
        self.y = neuralInputs[4]
        self.z = neuralInputs[1]
        self.ballx = neuralInputs[7]
        self.bally = neuralInputs[6]
        self.ballz = neuralInputs[2]
        self.botx = neuralInputs[18]
        self.boty = neuralInputs[17]
        self.botz = neuralInputs[3]

        return neuralInputs, scoring

    def reset_contollers(self):
        p1 = pyvjoy.VJoyDevice(1)
        p2 = pyvjoy.VJoyDevice(2)

        p1.data.wAxisX = 16383
        p1.data.wAxisY = 16383
        p1.data.wAxisYRot = 16383
        p1.data.wAxisXRot = 16383
        p1.data.wAxisZ = 0
        p1.data.wAxisZRot = 0
        p1.data.lButtons = 0

        p2.data.wAxisX = 16383
        p2.data.wAxisY = 16383
        p2.data.wAxisYRot = 16383
        p2.data.wAxisXRot = 16383
        p2.data.wAxisZ = 0
        p2.data.wAxisZRot = 0
        p2.data.lButtons = 0

        #send data to vJoy device
        p1.update()
        p2.update()

    def update_controllers(self, output1, output2):
        # Update controller buttons for both players

        # TODO: Sanitize input players give
        p1 = pyvjoy.VJoyDevice(1)
        p2 = pyvjoy.VJoyDevice(2)

        p1.data.wAxisX = output1[0]
        p2.data.wAxisX = output2[0]

        p1.data.wAxisY = output1[1]
        p2.data.wAxisY = output2[1]

        p1.data.wAxisZRot = output1[2]
        p2.data.wAxisZRot = output2[2]

        p1.data.wAxisZ = output1[3]
        p2.data.wAxisZ = output2[3]

        p1.data.lButtons = (1 * output1[4]) + (2 * output1[5]) + (4 *
                                                                  output1[6])
        p2.data.lButtons = (1 * output2[4]) + (2 * output2[5]) + (4 *
                                                                  output2[6])

        p1.data.wAxisXRot = 16383
        p2.data.wAxisXRot = 16383

        p1.data.wAxisYRot = 16383
        p2.data.wAxisYRot = 16383

        #send data to vJoy device
        p1.update()
        p2.update()
Пример #4
0
class play_helper:

    W_CODE = 0x11
    A_CODE = 0x1E
    S_CODE = 0x1F
    D_CODE = 0x20
    LSHIFT_CODE = 0x2A
    J_CODE = 0x24
    K_CODE = 0x25

    rwm = ReadWriteMem.ReadWriteMem()

    timeStamp = None
    x = None
    y = None
    z = None
    ballx = None
    bally = None
    ballz = None
    botx = None
    boty = None
    botz = None

    # Key presses
    W = False
    A = False
    S = False
    D = False
    LSHIFT = False
    J = False
    K = False

    def GetAddressVector(self, processHandle, rocketLeagueBaseAddress):
        addressList = array.array('i',
                                  (0, ) * 42)  # Create a tuple with 42 values

        addressList[0] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x017379B8, 0x34, 0x294, 0x1CC, 0x1AC, 0x144
             ])  # Boost address (Need to update these for v1.27)
        addressList[1] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x016D50A8, 0x4, 0x54, 0x18, 0xF0, 0x44])  # Player z address
        addressList[2] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x0160D4F4, 0x8, 0x20, 0x44])  # Ball z address
        addressList[3] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x01731340, 0x114, 0x14, 0x1BC, 0xF0, 0x44
             ])  # Bot (orange) z address
        addressList[4] = addressList[1] + 4  # Player y address
        addressList[5] = addressList[1] - 4  # Player x address
        addressList[6] = addressList[2] + 4  # Ball y address
        addressList[7] = addressList[2] - 4  # Ball x address
        addressList[8] = addressList[4] + 8  # Player rot1
        addressList[9] = addressList[8] + 4  # Player rot2
        addressList[10] = addressList[9] + 4  # Player rot3
        addressList[11] = addressList[10] + 8  # Player rot4
        addressList[12] = addressList[11] + 4  # Player rot5
        addressList[13] = addressList[12] + 4  # Player rot6
        addressList[14] = addressList[13] + 8  # Player rot7
        addressList[15] = addressList[14] + 4  # Player rot8
        addressList[16] = addressList[15] + 4  # Player rot9
        addressList[17] = addressList[3] + 4  # Bot y address
        addressList[18] = addressList[3] - 4  # Bot x address
        addressList[19] = addressList[17] + 8  # Bot rot1
        addressList[20] = addressList[19] + 4  # Bot rot2
        addressList[21] = addressList[20] + 4  # Bot rot3
        addressList[22] = addressList[21] + 8  # Bot rot4
        addressList[23] = addressList[22] + 4  # Bot rot5
        addressList[24] = addressList[23] + 4  # Bot rot6
        addressList[25] = addressList[24] + 8  # Bot rot7
        addressList[26] = addressList[25] + 4  # Bot rot8
        addressList[27] = addressList[26] + 4  # Bot rot9
        addressList[28] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x016D5090, 0x8, 0x318, 0x130, 0x0, 0x1F0])  # Blue score address
        addressList[29] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x01732F00, 0x178, 0x84, 0x28, 0x84, 0x1F0
             ])  # Orange score address
        addressList[30] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x016D5084, 0xF8, 0x8, 0x28, 0x5B4, 0x2F4
             ])  # Blue "Score" address
        addressList[31] = self.rwm.GetFinalAddress(
            processHandle, rocketLeagueBaseAddress,
            [0x016D5090, 0x10, 0xA8, 0x1E4, 0x35C, 0x2F4
             ])  # Orange "Score" address
        addressList[32] = addressList[30] + 4  # Blue goals
        addressList[33] = addressList[32] + 8  # Blue assists
        addressList[34] = addressList[32] + 12  # Blue saves
        addressList[35] = addressList[32] + 16  # Blue shots
        addressList[36] = addressList[31] + 4  # Orange goals
        addressList[37] = addressList[36] + 8  # Orange assists
        addressList[38] = addressList[36] + 12  # Orange saves
        addressList[39] = addressList[36] + 16  # Orange shots
        addressList[40] = addressList[39] + 4  # Demos by orange
        addressList[41] = addressList[35] + 4  # Demos by blue

        return addressList

    def GetValueVector(self, processHandle, addressVect):
        neuralInputs = array.array('f', (0, ) *
                                   43)  # Create a tuple with 43 float values
        scoring = array.array('f',
                              (0, ) * 4)  # Create a tuple with 4 float values
        # scoring = modify this with what I want to return for scoring function
        # Need to read 28 values for neural inputs and calculate 9 velocities and 6 relative positions

        # Boost is an int so different case
        neuralInputs[0] = float(
            self.rwm.ReadIntFromAddress(processHandle, addressVect[0]))
        for i in range(1, 28):
            neuralInputs[i] = self.rwm.ReadFloatFromAddress(
                processHandle, addressVect[i])

        if (self.timeStamp == None):
            # Need to set values for first time reading
            self.timeStamp = time.time()
            self.x = neuralInputs[5]
            self.y = neuralInputs[4]
            self.z = neuralInputs[1]
            self.ballx = neuralInputs[7]
            self.bally = neuralInputs[6]
            self.ballz = neuralInputs[2]
            self.botx = neuralInputs[18]
            self.boty = neuralInputs[17]
            self.botz = neuralInputs[3]

        # Calculate velocities
        curTime = time.time(
        )  # Shouldn't really matter where I put this so long as it is equally spaced apart
        timeDiff = curTime - self.timeStamp
        if (timeDiff == 0):
            timeDiff = 1
        neuralInputs[28] = (neuralInputs[5] - self.x) / timeDiff
        neuralInputs[29] = (neuralInputs[4] - self.y) / timeDiff
        neuralInputs[30] = (neuralInputs[1] - self.z) / timeDiff
        neuralInputs[31] = (neuralInputs[7] - self.ballx) / timeDiff
        neuralInputs[32] = (neuralInputs[6] - self.bally) / timeDiff
        neuralInputs[33] = (neuralInputs[2] - self.ballz) / timeDiff
        neuralInputs[34] = (neuralInputs[18] - self.botx) / timeDiff
        neuralInputs[35] = (neuralInputs[17] - self.boty) / timeDiff
        neuralInputs[36] = (neuralInputs[3] - self.botz) / timeDiff

        # Calculate relative positions
        neuralInputs[37] = neuralInputs[7] - neuralInputs[
            5]  # Relative x position to ball
        neuralInputs[38] = neuralInputs[6] - neuralInputs[
            4]  # Relative y position to ball
        neuralInputs[39] = neuralInputs[2] - neuralInputs[
            1]  # Relative z position to ball
        neuralInputs[40] = neuralInputs[18] - neuralInputs[
            5]  # Relative x position to bot
        neuralInputs[41] = neuralInputs[17] - neuralInputs[
            4]  # Relative y position to bot
        neuralInputs[42] = neuralInputs[3] - neuralInputs[
            1]  # Relative z position to bot

        # Also create tuple of scoring changes/demos so I can know when reset is necessary
        scoring[0] = float(
            self.rwm.ReadIntFromAddress(processHandle,
                                        addressVect[28]))  # Blue Score
        scoring[1] = float(
            self.rwm.ReadIntFromAddress(processHandle,
                                        addressVect[29]))  # Orange Score
        scoring[2] = float(
            self.rwm.ReadIntFromAddress(processHandle,
                                        addressVect[40]))  # Demos on blue
        scoring[3] = float(
            self.rwm.ReadIntFromAddress(processHandle,
                                        addressVect[41]))  # Demos on orange

        # Now update to old values
        self.timeStamp = curTime
        self.x = neuralInputs[5]
        self.y = neuralInputs[4]
        self.z = neuralInputs[1]
        self.ballx = neuralInputs[7]
        self.bally = neuralInputs[6]
        self.ballz = neuralInputs[2]
        self.botx = neuralInputs[18]
        self.boty = neuralInputs[17]
        self.botz = neuralInputs[3]

        return neuralInputs, scoring

    def update_keys(self, output):
        # Need to press keys that need to be pressed and aren't already pressed
        # Need to unpress keys that are pressed and need to be unpressed

        # If output[0] < -1 decelerate, > 1 accelerate, otherwise don't move
        if output[0] < -1.0:
            if (not self.S):
                SendKeys.PressKey(self.S_CODE)
                self.S = True
            if (self.W):
                SendKeys.ReleaseKey(self.W_CODE)
                self.W = False
        elif output[0] > 1.0:
            if (not self.W):
                SendKeys.PressKey(self.W_CODE)
                self.W = True
            if (self.S):
                SendKeys.ReleaseKey(self.S_CODE)
                self.S = False
        else:
            if (self.W):
                SendKeys.ReleaseKey(self.W_CODE)
                self.W = False
            if (self.S):
                SendKeys.ReleaseKey(self.S_CODE)
                self.S = False

        # output[1], check for left, none, right
        if output[1] < -1.0:
            if (not self.A):
                SendKeys.PressKey(self.A_CODE)
                self.A = True
            if (self.D):
                SendKeys.ReleaseKey(self.D_CODE)
                self.D = False
        elif output[1] > 1.0:
            if (not self.D):
                SendKeys.PressKey(self.D_CODE)
                self.D = True
            if (self.A):
                SendKeys.ReleaseKey(self.A_CODE)
                self.A = False
        else:
            if (self.D):
                SendKeys.ReleaseKey(self.D_CODE)
                self.D = False
            if (self.A):
                SendKeys.ReleaseKey(self.A_CODE)
                self.A = False

        # output[2], dift key off/on
        if output[2] < 0.0:
            if (self.LSHIFT):
                SendKeys.ReleaseKey(self.LSHIFT_CODE)
                self.LSHIFT = False
        else:
            if (not self.LSHIFT):
                SendKeys.PressKey(self.LSHIFT_CODE)
                self.LSHIFT = True

        # output[3], boost key off/on
        if output[3] < 0.0:
            if (self.J):
                SendKeys.ReleaseKey(self.J_CODE)
                self.J = False
        else:
            if (not self.J):
                SendKeys.PressKey(self.J_CODE)
                self.J = True

        # output[4], jump key off/on
        if output[4] < 0.0:
            if (self.K):
                SendKeys.ReleaseKey(self.K_CODE)
                self.K = False
        else:
            if (not self.K):
                SendKeys.PressKey(self.K_CODE)
                self.K = True

    def release_keys(self):
        # Make sure to unpress all keys when done
        if (self.W):
            SendKeys.ReleaseKey(self.W_CODE)
        if (self.A):
            SendKeys.ReleaseKey(self.A_CODE)
        if (self.S):
            SendKeys.ReleaseKey(self.S_CODE)
        if (self.D):
            SendKeys.ReleaseKey(self.D_CODE)
        if (self.LSHIFT):
            SendKeys.ReleaseKey(self.LSHIFT_CODE)
        if (self.J):
            SendKeys.ReleaseKey(self.J_CODE)
        if (self.K):
            SendKeys.ReleaseKey(self.K_CODE)