Ejemplo n.º 1
0
    def __handle_slippstream_events(self, event_bytes, gamestate):
        """ Handle a series of events, provided sequentially in a byte array """
        gamestate.menu_state = enums.Menu.IN_GAME
        while len(event_bytes) > 0:
            event_size = self.eventsize[event_bytes[0]]
            if len(event_bytes) < event_size:
                print("WARNING: Something went wrong unpacking events. Data is probably missing")
                print("\tDidn't have enough data for event")
                return False
            if EventType(event_bytes[0]) == EventType.PAYLOADS:
                cursor = 0x2
                payload_size = event_bytes[1]
                num_commands = (payload_size - 1) // 3
                for i in range(0, num_commands):
                    command, command_len = unpack(">bH", event_bytes[cursor:cursor+3])
                    self.eventsize[command] = command_len+1
                    cursor += 3
                event_bytes = event_bytes[payload_size + 1:]

            elif EventType(event_bytes[0]) == EventType.FRAME_START:
                event_bytes = event_bytes[event_size:]

            elif EventType(event_bytes[0]) == EventType.GAME_START:
                event_bytes = event_bytes[event_size:]

            elif EventType(event_bytes[0]) == EventType.GAME_END:
                event_bytes = event_bytes[event_size:]

            elif EventType(event_bytes[0]) == EventType.PRE_FRAME:
                event_bytes = event_bytes[event_size:]

            elif EventType(event_bytes[0]) == EventType.POST_FRAME:
                gamestate.frame = unpack(">i", event_bytes[0x1:0x1+4])[0]
                controller_port = unpack(">B", event_bytes[0x5:0x5+1])[0] + 1

                gamestate.player[controller_port].x = unpack(">f", event_bytes[0xa:0xa+4])[0]
                gamestate.player[controller_port].y = unpack(">f", event_bytes[0xe:0xe+4])[0]

                gamestate.player[controller_port].character = enums.Character(unpack(">B", event_bytes[0x7:0x7+1])[0])
                try:
                    gamestate.player[controller_port].action = enums.Action(unpack(">H", event_bytes[0x8:0x8+2])[0])
                except ValueError:
                    gamestate.player[controller_port].action = enums.Action.UNKNOWN_ANIMATION

                # Melee stores this in a float for no good reason. So we have to convert
                facing_float = unpack(">f", event_bytes[0x12:0x12+4])[0]
                gamestate.player[controller_port].facing = facing_float > 0

                gamestate.player[controller_port].percent = int(unpack(">f", event_bytes[0x16:0x16+4])[0])
                gamestate.player[controller_port].stock = unpack(">B", event_bytes[0x21:0x21+1])[0]
                gamestate.player[controller_port].action_frame = int(unpack(">f", event_bytes[0x22:0x22+4])[0])

                # Extract the bit at mask 0x20
                bitflags2 = unpack(">B", event_bytes[0x27:0x27+1])[0]
                gamestate.player[controller_port].hitlag = bool(bitflags2 & 0x20)

                try:
                    gamestate.player[controller_port].hitstun_frames_left = int(unpack(">f", event_bytes[0x2b:0x2b+4])[0])
                except ValueError:
                    gamestate.player[controller_port].hitstun_frames_left = 0
                gamestate.player[controller_port].on_ground = not bool(unpack(">B", event_bytes[0x2f:0x2f+1])[0])
                gamestate.player[controller_port].jumps_left = unpack(">B", event_bytes[0x32:0x32+1])[0]
                gamestate.player[controller_port].invulnerable = int(unpack(">B", event_bytes[0x34:0x34+1])[0]) != 0

                try:
                    gamestate.player[controller_port].speed_air_x_self = unpack(">f", event_bytes[0x35:0x35+4])[0]
                except error:
                    gamestate.player[controller_port].speed_air_x_self = 0

                try:
                    gamestate.player[controller_port].speed_y_self = unpack(">f", event_bytes[0x39:0x39+4])[0]
                except error:
                    gamestate.player[controller_port].speed_y_self = 0

                try:
                    gamestate.player[controller_port].speed_x_attack = unpack(">f", event_bytes[0x3d:0x3d+4])[0]
                except error:
                    gamestate.player[controller_port].speed_x_attack = 0

                try:
                    gamestate.player[controller_port].speed_y_attack = unpack(">f", event_bytes[0x41:0x41+4])[0]
                except error:
                    gamestate.player[controller_port].speed_y_attack = 0

                try:
                    gamestate.player[controller_port].speed_ground_x_self = unpack(">f", event_bytes[0x45:0x45+4])[0]
                except error:
                    gamestate.player[controller_port].speed_ground_x_self = 0

                # Keep track of a player's invulnerability due to respawn or ledge grab
                gamestate.player[controller_port].invulnerability_left = max(0, self._prev_gamestate.player[controller_port].invulnerability_left - 1)
                if gamestate.player[controller_port].action == Action.ON_HALO_WAIT:
                    gamestate.player[controller_port].invulnerability_left = 120
                # Don't give invulnerability to the first descent
                if gamestate.player[controller_port].action == Action.ON_HALO_DESCENT and gamestate.frame > 150:
                    gamestate.player[controller_port].invulnerability_left = 120
                if gamestate.player[controller_port].action == Action.EDGE_CATCHING and gamestate.player[controller_port].action_frame == 1:
                    gamestate.player[controller_port].invulnerability_left = 36

                # The pre-warning occurs when we first start a dash dance.
                if gamestate.player[controller_port].action == Action.DASHING and \
                        self._prev_gamestate.player[controller_port].action not in [Action.DASHING, Action.TURNING]:
                    gamestate.player[controller_port].moonwalkwarning = True

                # Take off the warning if the player does an action other than dashing
                if gamestate.player[controller_port].action != Action.DASHING:
                    gamestate.player[controller_port].moonwalkwarning = False

                # "off_stage" helper
                if (abs(gamestate.player[controller_port].x) > stages.EDGE_GROUND_POSITION[gamestate.stage] or \
                        gamestate.player[controller_port].y < -6) and not gamestate.player[controller_port].on_ground:
                    gamestate.player[controller_port].off_stage = True
                else:
                    gamestate.player[controller_port].off_stage = False

                event_bytes = event_bytes[event_size:]

            elif EventType(event_bytes[0]) == EventType.GECKO_CODES:
                event_bytes = event_bytes[event_size:]

            elif EventType(event_bytes[0]) == EventType.FRAME_BOOKEND:
                self._prev_gamestate = gamestate

                # Calculate helper distance variable
                #   This is a bit kludgey.... :/
                i = 0
                player_one_x, player_one_y, player_two_x, player_two_y = 0, 0, 0, 0
                for _, player_state in gamestate.player.items():
                    if i == 0:
                        player_one_x, player_one_y = player_state.x, player_state.y
                    if i == 1:
                        player_two_x, player_two_y = player_state.x, player_state.y
                    i += 1
                xdist = player_one_x - player_two_x
                ydist = player_one_y - player_two_y
                gamestate.distance = math.sqrt((xdist**2) + (ydist**2))
                event_bytes = event_bytes[event_size:]
                return True

            elif EventType(event_bytes[0]) == EventType.ITEM_UPDATE:
                projectile = Projectile()
                projectile.x = unpack(">f", event_bytes[0x14:0x14+4])[0]
                projectile.y = unpack(">f", event_bytes[0x18:0x18+4])[0]
                projectile.x_speed = unpack(">f", event_bytes[0x0c:0x0c+4])[0]
                projectile.y_speed = unpack(">f", event_bytes[0x10:0x10+4])[0]
                try:
                    projectile.owner = unpack(">B", event_bytes[0x2A:0x2A+1])[0] + 1
                    if projectile.owner > 4:
                        projectile.owner = -1
                except error:
                    projectile.owner = -1
                try:
                    projectile.subtype = enums.ProjectileSubtype(unpack(">H", event_bytes[0x05:0x05+2])[0])
                except ValueError:
                    projectile.subtype = enums.ProjectileSubtype.UNKNOWN_PROJECTILE
                # Add the projectile to the gamestate list
                gamestate.projectiles.append(projectile)

                event_bytes = event_bytes[event_size:]

            else:
                print("WARNING: Something went wrong unpacking events. " + \
                    "Data is probably missing")
                print("\tGot invalid event type: ", event_bytes[0])
                return False

        return False
Ejemplo n.º 2
0
    def __post_frame(self, gamestate, event_bytes):
        gamestate.stage = self._current_stage
        gamestate.frame = np.ndarray((1,), ">i", event_bytes, 0x1)[0]
        controller_port = np.ndarray((1,), ">B", event_bytes, 0x5)[0] + 1

        if controller_port not in gamestate.players:
            gamestate.players[controller_port] = PlayerState()
        playerstate = gamestate.players[controller_port]

        # Is this Nana?
        if np.ndarray((1,), ">B", event_bytes, 0x6)[0] == 1:
            playerstate.nana = PlayerState()
            playerstate = playerstate.nana

        playerstate.position.x = np.ndarray((1,), ">f", event_bytes, 0xa)[0]
        playerstate.position.y = np.ndarray((1,), ">f", event_bytes, 0xe)[0]

        playerstate.x = playerstate.position.x
        playerstate.y = playerstate.position.y

        playerstate.character = enums.Character(np.ndarray((1,), ">B", event_bytes, 0x7)[0])
        try:
            playerstate.action = enums.Action(np.ndarray((1,), ">H", event_bytes, 0x8)[0])
        except ValueError:
            playerstate.action = enums.Action.UNKNOWN_ANIMATION

        # Melee stores this in a float for no good reason. So we have to convert
        playerstate.facing = np.ndarray((1,), ">f", event_bytes, 0x12)[0] > 0

        playerstate.percent = int(np.ndarray((1,), ">f", event_bytes, 0x16)[0])
        playerstate.shield_strength = np.ndarray((1,), ">f", event_bytes, 0x1A)[0]
        playerstate.stock = np.ndarray((1,), ">B", event_bytes, 0x21)[0]
        playerstate.action_frame = int(np.ndarray((1,), ">f", event_bytes, 0x22)[0])

        try:
            playerstate.hitstun_frames_left = int(np.ndarray((1,), ">f", event_bytes, 0x2B)[0])
        except TypeError:
            playerstate.hitstun_frames_left = 0
        except ValueError:
            playerstate.hitstun_frames_left = 0
        try:
            playerstate.on_ground = not bool(np.ndarray((1,), ">B", event_bytes, 0x2F)[0])
        except TypeError:
            playerstate.on_ground = True
        try:
            playerstate.jumps_left = np.ndarray((1,), ">B", event_bytes, 0x32)[0]
        except TypeError:
            playerstate.jumps_left = 1

        try:
            playerstate.invulnerable = int(np.ndarray((1,), ">B", event_bytes, 0x34)[0]) != 0
        except TypeError:
            playerstate.invulnerable = False

        try:
            playerstate.speed_air_x_self = np.ndarray((1,), ">f", event_bytes, 0x35)[0]
        except TypeError:
            playerstate.speed_air_x_self = 0

        try:
            playerstate.speed_y_self = np.ndarray((1,), ">f", event_bytes, 0x39)[0]
        except TypeError:
            playerstate.speed_y_self = 0

        try:
            playerstate.speed_x_attack = np.ndarray((1,), ">f", event_bytes, 0x3D)[0]
        except TypeError:
            playerstate.speed_x_attack = 0

        try:
            playerstate.speed_y_attack = np.ndarray((1,), ">f", event_bytes, 0x41)[0]
        except TypeError:
            playerstate.speed_y_attack = 0

        try:
            playerstate.speed_ground_x_self = np.ndarray((1,), ">f", event_bytes, 0x45)[0]
        except TypeError:
            playerstate.speed_ground_x_self = 0

        try:
            playerstate.hitlag_left = int(np.ndarray((1,), ">f", event_bytes, 0x49)[0])
        except TypeError:
            playerstate.hitlag_left = 0

        # Keep track of a player's invulnerability due to respawn or ledge grab
        if controller_port in self._prev_gamestate.players:
            playerstate.invulnerability_left = max(0, self._invuln_start[controller_port][1] - (gamestate.frame - self._invuln_start[controller_port][0]))
        if playerstate.action == Action.ON_HALO_WAIT:
            playerstate.invulnerability_left = 120
            self._invuln_start[controller_port] = (gamestate.frame, 120)
        # Don't give invulnerability to the first descent
        if playerstate.action == Action.ON_HALO_DESCENT and gamestate.frame > 150:
            playerstate.invulnerability_left = 120
            self._invuln_start[controller_port] = (gamestate.frame, 120)
        if playerstate.action == Action.EDGE_CATCHING and playerstate.action_frame == 1:
            playerstate.invulnerability_left = 36
            self._invuln_start[controller_port] = (gamestate.frame, 36)
        # First frame of the game
        if gamestate.frame == -123:
            playerstate.invulnerability_left = 0
            self._invuln_start[controller_port] = (gamestate.frame, 0)

        # The pre-warning occurs when we first start a dash dance.
        if controller_port in self._prev_gamestate.players:
            if playerstate.action == Action.DASHING and \
                    self._prev_gamestate.players[controller_port].action not in [Action.DASHING, Action.TURNING]:
                playerstate.moonwalkwarning = True

        # Take off the warning if the player does an action other than dashing
        if playerstate.action != Action.DASHING:
            playerstate.moonwalkwarning = False

        # "off_stage" helper
        try:
            if (abs(playerstate.position.x) > stages.EDGE_GROUND_POSITION[gamestate.stage] or \
                    playerstate.y < -6) and not playerstate.on_ground:
                playerstate.off_stage = True
            else:
                playerstate.off_stage = False
        except KeyError:
            playerstate.off_stage = False

        # ECB top edge, x
        ecb_top_x = 0
        ecb_top_y = 0
        try:
            ecb_top_x = np.ndarray((1,), ">f", event_bytes, 0x4D)[0]
        except TypeError:
            ecb_top_x = 0
        # ECB Top edge, y
        try:
            ecb_top_y = np.ndarray((1,), ">f", event_bytes, 0x51)[0]
        except TypeError:
            ecb_top_y = 0
        playerstate.ecb.top = collections.namedtuple("Position", ['x', 'y'])
        playerstate.ecb.top.x = ecb_top_x
        playerstate.ecb.top.y = ecb_top_y
        playerstate.ecb_top = (ecb_top_x, ecb_top_y)

        # ECB bottom edge, x coord
        ecb_bot_x = 0
        ecb_bot_y = 0
        try:
            ecb_bot_x = np.ndarray((1,), ">f", event_bytes, 0x55)[0]
        except TypeError:
            ecb_bot_x = 0
        # ECB Bottom edge, y coord
        try:
            ecb_bot_y = np.ndarray((1,), ">f", event_bytes, 0x59)[0]
        except TypeError:
            ecb_bot_y = 0
        playerstate.ecb.bottom = collections.namedtuple("Position", ['x', 'y'])
        playerstate.ecb.bottom.x = ecb_bot_x
        playerstate.ecb.bottom.y = ecb_bot_y
        playerstate.ecb_bottom = (ecb_bot_x, ecb_bot_y)

        # ECB left edge, x coord
        ecb_left_x = 0
        ecb_left_y = 0
        try:
            ecb_left_x = np.ndarray((1,), ">f", event_bytes, 0x5D)[0]
        except TypeError:
            ecb_left_x = 0
        # ECB left edge, y coord
        try:
            ecb_left_y = np.ndarray((1,), ">f", event_bytes, 0x61)[0]
        except TypeError:
            ecb_left_y = 0
        playerstate.ecb.left = collections.namedtuple("Position", ['x', 'y'])
        playerstate.ecb.left.x = ecb_left_x
        playerstate.ecb.left.y = ecb_left_y
        playerstate.ecb_left = (ecb_left_x, ecb_left_y)

        # ECB right edge, x coord
        ecb_right_x = 0
        ecb_right_y = 0
        try:
            ecb_right_x = np.ndarray((1,), ">f", event_bytes, 0x65)[0]
        except TypeError:
            ecb_right_x = 0
        # ECB right edge, y coord
        try:
            ecb_right_y = np.ndarray((1,), ">f", event_bytes, 0x69)[0]
        except TypeError:
            ecb_right_y = 0
        playerstate.ecb.right = collections.namedtuple("Position", ['x', 'y'])
        playerstate.ecb.right.x = ecb_right_x
        playerstate.ecb.right.y = ecb_right_y
        playerstate.ecb_right = (ecb_right_x, ecb_right_y)
        if self._use_manual_bookends:
            self._frame = gamestate.frame
Ejemplo n.º 3
0
    def __handle_slippstream_events(self, event_bytes, gamestate):
        """ Handle a series of events, provided sequentially in a byte array """
        lastmessage = EventType.GAME_START
        while len(event_bytes) > 0:
            lastmessage = EventType(event_bytes[0])
            event_size = self.eventsize[event_bytes[0]]
            if len(event_bytes) < event_size:
                print(
                    "WARNING: Something went wrong unpacking events. Data is probably missing"
                )
                print("\tDidn't have enough data for event")
                return False
            if (EventType(event_bytes[0]) == EventType.PAYLOADS):
                cursor = 0x2
                payload_size = event_bytes[1]
                num_commands = (payload_size - 1) // 3
                for i in range(0, num_commands):
                    command, command_len = unpack(
                        ">bH", event_bytes[cursor:cursor + 3])
                    self.eventsize[command] = command_len + 1
                    cursor += 3
                event_bytes = event_bytes[payload_size + 1:]
                continue

            elif (EventType(event_bytes[0]) == EventType.FRAME_START):
                self.frame_num = unpack(">i", event_bytes[1:5])[0]
                event_bytes = event_bytes[event_size:]
                continue

            elif (EventType(event_bytes[0]) == EventType.GAME_START):
                event_bytes = event_bytes[event_size:]
                continue

            elif (EventType(event_bytes[0]) == EventType.GAME_END):
                event_bytes = event_bytes[event_size:]
                continue

            elif (EventType(event_bytes[0]) == EventType.PRE_FRAME):
                event_bytes = event_bytes[event_size:]
                continue

            elif (EventType(event_bytes[0]) == EventType.POST_FRAME):
                gamestate.frame = unpack(">i", event_bytes[0x1:0x1 + 4])[0]
                controller_port = unpack(">B", event_bytes[0x5:0x5 + 1])[0] + 1

                gamestate.player[controller_port].x = unpack(
                    ">f", event_bytes[0xa:0xa + 4])[0]
                gamestate.player[controller_port].y = unpack(
                    ">f", event_bytes[0xe:0xe + 4])[0]

                gamestate.player[controller_port].character = enums.Character(
                    unpack(">B", event_bytes[0x7:0x7 + 1])[0])
                try:
                    gamestate.player[controller_port].action = enums.Action(
                        unpack(">H", event_bytes[0x8:0x8 + 2])[0])
                except ValueError:
                    gamestate.player[
                        controller_port].action = enums.Action.UNKNOWN_ANIMATION

                # Melee stores this in a float for no good reason. So we have to convert
                facing_float = unpack(">f", event_bytes[0x12:0x12 + 4])[0]
                gamestate.player[controller_port].facing = facing_float > 0

                gamestate.player[controller_port].percent = int(
                    unpack(">f", event_bytes[0x16:0x16 + 4])[0])
                gamestate.player[controller_port].stock = unpack(
                    ">B", event_bytes[0x21:0x21 + 1])[0]
                gamestate.player[controller_port].action_frame = int(
                    unpack(">f", event_bytes[0x22:0x22 + 4])[0])

                # Extract the bit at mask 0x20
                bitflags2 = unpack(">B", event_bytes[0x27:0x27 + 1])[0]
                gamestate.player[controller_port].hitlag = bool(bitflags2
                                                                & 0x20)

                gamestate.player[controller_port].hitstun_frames_left = int(
                    unpack(">f", event_bytes[0x2b:0x2b + 4])[0])
                gamestate.player[controller_port].on_ground = not bool(
                    unpack(">B", event_bytes[0x2f:0x2f + 1])[0])
                gamestate.player[controller_port].jumps_left = unpack(
                    ">B", event_bytes[0x32:0x32 + 1])[0]

                event_bytes = event_bytes[event_size:]
                continue

            elif (EventType(event_bytes[0]) == EventType.GECKO_CODES):
                event_bytes = event_bytes[event_size:]
                continue

            elif (EventType(event_bytes[0]) == EventType.FRAME_BOOKEND):
                event_bytes = event_bytes[event_size:]
                return True

            elif (EventType(event_bytes[0]) == EventType.ITEM_UPDATE):
                # TODO projectiles
                projectile = Projectile()
                projectile.x = unpack(">f", event_bytes[0x14:0x14 + 4])[0]
                projectile.y = unpack(">f", event_bytes[0x18:0x18 + 4])[0]
                projectile.x_speed = unpack(">f",
                                            event_bytes[0x0c:0x0c + 4])[0]
                projectile.y_speed = unpack(">f",
                                            event_bytes[0x10:0x10 + 4])[0]
                try:
                    projectile.subtype = enums.ProjectileSubtype(
                        unpack(">H", event_bytes[0x05:0x05 + 2])[0])
                except ValueError:
                    projectile.subtype = enums.UNKNOWN_PROJECTILE
                # Add the projectile to the gamestate list
                gamestate.projectiles.append(projectile)

                event_bytes = event_bytes[event_size:]
                continue

            else:
                print("WARNING: Something went wrong unpacking events. " + \
                    "Data is probably missing")
                print("\tGot invalid event type: ", event_bytes[0])
                return False

        return False
Ejemplo n.º 4
0
    def update(self, mem_update):
        label = self.locations[mem_update[0]][0]
        player_int = int(self.locations[mem_update[0]][1])
        if label == "frame":
            self.frame = unpack('<I', mem_update[1])[0]
            self.newframe = True
            #Now that the frame is ready, let's calculate some derived information
            #   These are not stored inside Melee anywhere, but are nonetheless
            #   important pieces of information that we don't want to make the
            #   user have to re-calculate on their own
            for i in self.player:
                # Move current x,y over to prev
                self.player[i].prev_x = self.player[i].x
                self.player[i].prev_y = self.player[i].y
                # Move future x,y over to current
                self.player[i].x = self.player[i].next_x
                self.player[i].y = self.player[i].next_y

                if (abs(self.player[i].x) > stages.edgegroundposition(self.stage) or \
                        self.player[i].y < -6) and not self.player[i].on_ground:
                    self.player[i].off_stage = True
                else:
                    self.player[i].off_stage = False

                # Keep track of a player's invulnerability due to respawn or ledge grab
                self.player[i].invulnerability_left = max(
                    0, self.player[i].invulnerability_left - 1)
                if self.player[i].action == Action.ON_HALO_WAIT:
                    self.player[i].invulnerability_left = 120
                # Don't give invulnerability to the first descent
                if self.player[
                        i].action == Action.ON_HALO_DESCENT and self.frame > 150:
                    self.player[i].invulnerability_left = 120
                if self.player[
                        i].action == Action.EDGE_CATCHING and self.player[
                            i].action_frame == 1:
                    self.player[i].invulnerability_left = 36

                # Which character are we right now?
                if self.player[i].character in [
                        Character.SHEIK, Character.ZELDA
                ]:
                    if self.player[i].transformed == self.player[i].iszelda:
                        self.player[i].character = Character.SHEIK
                    else:
                        self.player[i].character = Character.ZELDA
                # If the player is transformed, then copy over the sub-character attributes
                if self.player[i].transformed:
                    self.player[i].action = self.player[i + 4].action
                    self.player[i].action_counter = self.player[
                        i + 4].action_counter
                    self.player[i].action_frame = self.player[i +
                                                              4].action_frame
                    self.player[i].invulnerable = self.player[i +
                                                              4].invulnerable
                    self.player[i].hitlag_frames_left = self.player[
                        i + 4].hitlag_frames_left
                    self.player[i].hitstun_frames_left = self.player[
                        i + 4].hitstun_frames_left
                    self.player[i].charging_smash = self.player[
                        i + 4].charging_smash
                    self.player[i].jumps_left = self.player[i + 4].jumps_left
                    self.player[i].on_ground = self.player[i + 4].on_ground
                    self.player[i].speed_air_x_self = self.player[
                        i + 4].speed_air_x_self
                    self.player[i].speed_y_self = self.player[i +
                                                              4].speed_y_self
                    self.player[i].speed_x_attack = self.player[
                        i + 4].speed_x_attack
                    self.player[i].speed_y_attack = self.player[
                        i + 4].speed_y_attack
                    self.player[i].speed_ground_x_self = self.player[
                        i + 4].speed_ground_x_self
                    self.player[i].x = self.player[i + 4].x
                    self.player[i].y = self.player[i + 4].y
                    self.player[i].percent = self.player[i + 4].percent
                    self.player[i].facing = self.player[i + 4].facing

                # The pre-warning occurs when we first start a dash dance.
                if self.player[i].action == Action.DASHING and self.player[
                        i].prev_action not in [Action.DASHING, Action.TURNING]:
                    self.player[i].moonwalkwarning = True

                # Take off the warning if the player does an action other than dashing
                if self.player[i].action != Action.DASHING:
                    self.player[i].moonwalkwarning = False

            #TODO: This needs updating in order to support >2 players
            xdist = self.ai_state.x - self.opponent_state.x
            ydist = self.ai_state.y - self.opponent_state.y
            self.distance = math.sqrt((xdist**2) + (ydist**2))
            self.fixiasa()
            self.fixframeindexing()
            return True
        if label == "stage":
            self.stage = unpack('<I', mem_update[1])[0]
            self.stage = self.stage >> 16
            self.stage &= 0x000000ff
            try:
                self.stage = enums.Stage(self.stage)
            except ValueError:
                self.stage = enums.Stage.NO_STAGE
            return False
        if label == "menu_state":
            self.menu_state = unpack('<I', mem_update[1])[0]
            self.menu_state &= 0x000000ff
            self.menu_state = enums.Menu(self.menu_state)
            return False
        #Player variables
        if label == "percent":
            if player_int > 4:
                try:
                    self.player[player_int].percent = int(
                        unpack('<f', mem_update[1])[0])
                except ValueError:
                    self.player[player_int].percent = 0
                return False
            self.player[player_int].percent = unpack('<I', mem_update[1])[0]
            self.player[
                player_int].percent = self.player[player_int].percent >> 16
            return False
        if label == "stock":
            self.player[player_int].stock = unpack('<I', mem_update[1])[0]
            self.player[player_int].stock = self.player[player_int].stock >> 24
            return False
        if label == "facing":
            self.player[player_int].facing = unpack('<I', mem_update[1])[0]
            self.player[player_int].facing = not bool(
                self.player[player_int].facing >> 31)
            return False
        if label == "x":
            self.player[player_int].next_x = unpack('<f', mem_update[1])[0]
            return False
        if label == "y":
            self.player[player_int].next_y = unpack('<f', mem_update[1])[0]
            return False
        if label == "character":
            temp = unpack('<I', mem_update[1])[0] >> 24
            try:
                self.player[player_int].character = enums.Character(temp)
            except ValueError:
                self.player[
                    player_int].character = enums.Character.UNKNOWN_CHARACTER
            return False
        if label == "cursor_x":
            self.player[player_int].cursor_x = unpack('<f', mem_update[1])[0]
            return False
        if label == "cursor_y":
            self.player[player_int].cursor_y = unpack('<f', mem_update[1])[0]
            return False
        if label == "action":
            temp = unpack('<I', mem_update[1])[0]
            try:
                # Keep track of old action
                self.player[player_int].prev_action = self.player[
                    player_int].action
                self.player[player_int].action = enums.Action(temp)
            except ValueError:
                self.player[player_int].action = enums.Action.UNKNOWN_ANIMATION
            return False
        if label == "action_counter":
            #TODO look if this is backwards
            temp = unpack('I', mem_update[1])[0]
            temp = temp >> 8
            self.player[player_int].action_counter = temp
            return False
        if label == "action_frame":
            temp = unpack('<f', mem_update[1])[0]
            try:
                self.player[player_int].action_frame = int(temp)
            except ValueError:
                pass
            return False
        if label == "invulnerable":
            self.player[player_int].invulnerable = unpack('<I',
                                                          mem_update[1])[0]
            self.player[player_int].invulnerable = self.player[
                player_int].invulnerable >> 31
            return False
        if label == "hitlag_frames_left":
            temp = unpack('<f', mem_update[1])[0]
            try:
                self.player[player_int].hitlag_frames_left = int(temp)
            except ValueError:
                pass
            return False
        if label == "hitstun_frames_left":
            temp = unpack('<f', mem_update[1])[0]
            try:
                self.player[player_int].hitstun_frames_left = int(temp)
            except ValueError:
                pass
            return False
        if label == "charging_smash":
            temp = unpack('<I', mem_update[1])[0]
            if temp == 2:
                self.player[player_int].charging_smash = True
            else:
                self.player[player_int].charging_smash = False
            return False
        if label == "jumps_left":
            temp = unpack('<I', mem_update[1])[0]
            temp = temp >> 24
            #This value is actually the number of jumps USED
            #   so we have to do some quick math to turn this into what we want
            try:
                totaljumps = int(self.characterdata[
                    self.player[player_int].character]["Jumps"])
                self.player[player_int].jumps_left = totaljumps - temp + 1
            # Key error will be expected when we first start
            except KeyError:
                self.player[player_int].jumps_left = 1
            return False
        if label == "on_ground":
            temp = unpack('<I', mem_update[1])[0]
            if temp == 0:
                self.player[player_int].on_ground = True
            else:
                self.player[player_int].on_ground = False
            return False
        if label == "speed_air_x_self":
            self.player[player_int].speed_air_x_self = unpack(
                '<f', mem_update[1])[0]
            return False
        if label == "speed_y_self":
            self.player[player_int].speed_y_self = unpack('<f',
                                                          mem_update[1])[0]
            return False
        if label == "speed_x_attack":
            self.player[player_int].speed_x_attack = unpack(
                '<f', mem_update[1])[0]
            return False
        if label == "speed_y_attack":
            self.player[player_int].speed_y_attack = unpack(
                '<f', mem_update[1])[0]
            return False
        if label == "speed_ground_x_self":
            self.player[player_int].speed_ground_x_self = unpack(
                '<f', mem_update[1])[0]
            return False
        if label == "coin_down":
            temp = unpack('<I', mem_update[1])[0]
            temp = temp & 0x000000ff
            self.player[player_int].coin_down = (temp == 2)
            return False
        if label == "stage_select_cursor_x":
            self.stage_select_cursor_x = unpack('<f', mem_update[1])[0]
            return False
        if label == "stage_select_cursor_y":
            self.stage_select_cursor_y = unpack('<f', mem_update[1])[0]
            return False
        if label == "ready_to_start":
            temp = unpack('>I', mem_update[1])[0]
            temp = temp & 0x000000ff
            self.ready_to_start = not bool(temp)
            return False
        if label == "controller_status":
            temp = unpack('>I', mem_update[1])[0]
            temp = temp & 0x000000ff
            self.player[player_int].controller_status = enums.ControllerStatus(
                temp)
            return False
        if label == "hitbox_1_size":
            self.player[player_int].hitbox_1_size = unpack(
                '<f', mem_update[1])[0]
            return False
        if label == "hitbox_2_size":
            self.player[player_int].hitbox_2_size = unpack(
                '<f', mem_update[1])[0]
            return False
        if label == "hitbox_3_size":
            self.player[player_int].hitbox_3_size = unpack(
                '<f', mem_update[1])[0]
            return False
        if label == "hitbox_4_size":
            self.player[player_int].hitbox_4_size = unpack(
                '<f', mem_update[1])[0]
            return False
        if label == "hitbox_1_status":
            temp = unpack('<I', mem_update[1])[0]
            status = True
            if temp == 0:
                status = False
            self.player[player_int].hitbox_1_status = status
            return False
        if label == "hitbox_2_status":
            temp = unpack('<I', mem_update[1])[0]
            status = True
            if temp == 0:
                status = False
            self.player[player_int].hitbox_2_status = status
            return False
        if label == "hitbox_3_status":
            temp = unpack('<I', mem_update[1])[0]
            status = True
            if temp == 0:
                status = False
            self.player[player_int].hitbox_3_status = status
            return False
        if label == "hitbox_4_status":
            temp = unpack('<I', mem_update[1])[0]
            status = True
            if temp == 0:
                status = False
            self.player[player_int].hitbox_4_status = status
            return False
        if label == "hitbox_1_x":
            self.player[player_int].hitbox_1_x = unpack('<f', mem_update[1])[0]
            return False
        if label == "hitbox_1_y":
            self.player[player_int].hitbox_1_y = unpack('<f', mem_update[1])[0]
            return False
        if label == "hitbox_2_x":
            self.player[player_int].hitbox_2_x = unpack('<f', mem_update[1])[0]
            return False
        if label == "hitbox_2_y":
            self.player[player_int].hitbox_2_y = unpack('<f', mem_update[1])[0]
            return False
        if label == "hitbox_3_x":
            self.player[player_int].hitbox_3_x = unpack('<f', mem_update[1])[0]
            return False
        if label == "hitbox_3_y":
            self.player[player_int].hitbox_3_y = unpack('<f', mem_update[1])[0]
            return False
        if label == "hitbox_4_x":
            self.player[player_int].hitbox_4_x = unpack('<f', mem_update[1])[0]
            return False
        if label == "hitbox_4_y":
            self.player[player_int].hitbox_4_y = unpack('<f', mem_update[1])[0]
            return False
        if label == "iasa":
            self.player[player_int].iasa = bool(
                unpack('<I', mem_update[1])[0] >> 31)
            return False
        if label == "transformed":
            temp = unpack('<I', mem_update[1])[0]
            status = False
            if temp == 16777216:
                status = True
            self.player[player_int].transformed = status
            return False
        if label == "iszelda":
            temp = unpack('<I', mem_update[1])[0]
            status = False
            if temp == 18:
                status = True
            self.player[player_int].iszelda = status
            return False
        if label == "projectiles":
            #Only once per new frame that we get a projectile, clear the list out
            if self.newframe:
                self.projectiles.clear()
                self.i = 0
            self.i += 1
            self.newframe = False
            if len(mem_update[1]) < 10:
                self.projectiles.clear()
                return False
            proj = Projectile()
            proj.x = unpack('>f', mem_update[1][0x4c:0x50])[0]
            proj.y = unpack('>f', mem_update[1][0x50:0x54])[0]
            proj.x_speed = unpack('>f', mem_update[1][0x40:0x44])[0]
            proj.y_speed = unpack('>f', mem_update[1][0x44:0x48])[0]
            try:
                proj.subtype = enums.ProjectileSubtype(
                    unpack('>I', mem_update[1][0x10:0x14])[0])
            except ValueError:
                return False
            self.projectiles.append(proj)
        return False
Ejemplo n.º 5
0
 def update(self, mem_update):
     label = self.locations[mem_update[0]][0]
     player_int = int(self.locations[mem_update[0]][1])
     if label == "frame":
         self.frame = unpack('<I', mem_update[1])[0]
         self.newframe = True
         #Now that the frame is ready, let's calculate some derived information
         #   These are not stored inside Melee anywhere, but are nonetheless
         #   important pieces of information that we don't want to make the
         #   user have to re-calculate on their own
         for i in self.player:
             if abs(self.player[i].x) > stages.edgegroundposition(
                     self.stage):
                 self.player[i].off_stage = True
             else:
                 self.player[i].off_stage = False
         #TODO: This needs updating in order to support >2 players
         xdist = self.ai_state.x - self.opponent_state.x
         ydist = self.ai_state.y - self.opponent_state.y
         self.distance = math.sqrt((xdist**2) + (ydist**2))
         self.fixframeindexing()
         return True
     if label == "stage":
         self.stage = unpack('<I', mem_update[1])[0]
         self.stage = self.stage >> 16
         self.stage &= 0x000000ff
         try:
             self.stage = enums.Stage(self.stage)
         except ValueError:
             self.stage = enums.Stage.NO_STAGE
         return False
     if label == "menu_state":
         self.menu_state = unpack('<I', mem_update[1])[0]
         self.menu_state &= 0x000000ff
         self.menu_state = enums.Menu(self.menu_state)
         return False
     #Player variables
     if label == "percent":
         self.player[player_int].percent = unpack('<I', mem_update[1])[0]
         self.player[
             player_int].percent = self.player[player_int].percent >> 16
         return False
     if label == "stock":
         self.player[player_int].stock = unpack('<I', mem_update[1])[0]
         self.player[player_int].stock = self.player[player_int].stock >> 24
         return False
     if label == "facing":
         self.player[player_int].facing = unpack('<I', mem_update[1])[0]
         self.player[player_int].facing = not bool(
             self.player[player_int].facing >> 31)
         return False
     if label == "x":
         self.player[player_int].x = unpack('<f', mem_update[1])[0]
         return False
     if label == "y":
         self.player[player_int].y = unpack('<f', mem_update[1])[0]
         return False
     if label == "character":
         temp = unpack('<I', mem_update[1])[0] >> 24
         try:
             self.player[player_int].character = enums.Character(temp)
         except ValueError:
             self.player[
                 player_int].character = enums.Character.UNKNOWN_CHARACTER
         return False
     if label == "cursor_x":
         self.player[player_int].cursor_x = unpack('<f', mem_update[1])[0]
         return False
     if label == "cursor_y":
         self.player[player_int].cursor_y = unpack('<f', mem_update[1])[0]
         return False
     if label == "action":
         temp = unpack('<I', mem_update[1])[0]
         try:
             self.player[player_int].action = enums.Action(temp)
         except ValueError:
             self.player[player_int].action = enums.Action.UNKNOWN_ANIMATION
         return False
     if label == "action_counter":
         #TODO look if this is backwards
         temp = unpack('I', mem_update[1])[0]
         temp = temp >> 8
         self.player[player_int].action_counter = temp
         return False
     if label == "action_frame":
         temp = unpack('<f', mem_update[1])[0]
         try:
             self.player[player_int].action_frame = int(temp)
         except ValueError:
             pass
         return False
     if label == "invulnerable":
         self.player[player_int].invulnerable = unpack('<I',
                                                       mem_update[1])[0]
         self.player[player_int].invulnerable = self.player[
             player_int].invulnerable >> 31
         return False
     if label == "hitlag_frames_left":
         temp = unpack('<f', mem_update[1])[0]
         try:
             self.player[player_int].hitlag_frames_left = int(temp)
         except ValueError:
             pass
         return False
     if label == "hitstun_frames_left":
         temp = unpack('<f', mem_update[1])[0]
         try:
             self.player[player_int].hitstun_frames_left = int(temp)
         except ValueError:
             pass
         return False
     if label == "charging_smash":
         temp = unpack('<I', mem_update[1])[0]
         if temp == 2:
             self.player[player_int].charging_smash = True
         else:
             self.player[player_int].charging_smash = False
         return False
     if label == "jumps_left":
         temp = unpack('<I', mem_update[1])[0]
         temp = temp >> 24
         #This value is actually the number of jumps USED
         #   so we have to do some quick math to turn this into what we want
         #TODO = characterstats.maxjumps(self.player[player_int].character) - temp + 1
         self.player[player_int].jumps_left = temp
         return False
     if label == "on_ground":
         temp = unpack('<I', mem_update[1])[0]
         if temp == 0:
             self.player[player_int].on_ground = True
         else:
             self.player[player_int].on_ground = False
         return False
     if label == "speed_air_x_self":
         self.player[player_int].speed_air_x_self = unpack(
             '<f', mem_update[1])[0]
         return False
     if label == "speed_y_self":
         self.player[player_int].speed_y_self = unpack('<f',
                                                       mem_update[1])[0]
         return False
     if label == "speed_x_attack":
         self.player[player_int].speed_x_attack = unpack(
             '<f', mem_update[1])[0]
         return False
     if label == "speed_y_attack":
         self.player[player_int].speed_y_attack = unpack(
             '<f', mem_update[1])[0]
         return False
     if label == "speed_ground_x_self":
         self.player[player_int].speed_ground_x_self = unpack(
             '<f', mem_update[1])[0]
         return False
     if label == "coin_down":
         temp = unpack('<I', mem_update[1])[0]
         temp = temp & 0x000000ff
         self.player[player_int].coin_down = (temp == 2)
         return False
     if label == "stage_select_cursor_x":
         self.stage_select_cursor_x = unpack('<f', mem_update[1])[0]
         return False
     if label == "stage_select_cursor_y":
         self.stage_select_cursor_y = unpack('<f', mem_update[1])[0]
         return False
     if label == "ready_to_start":
         temp = unpack('>I', mem_update[1])[0]
         temp = temp & 0x000000ff
         self.ready_to_start = not bool(temp)
         return False
     if label == "controller_status":
         temp = unpack('>I', mem_update[1])[0]
         temp = temp & 0x000000ff
         self.player[player_int].controller_status = enums.ControllerStatus(
             temp)
         return False
     if label == "hitbox_1_size":
         self.player[player_int].hitbox_1_size = unpack(
             '<f', mem_update[1])[0]
         return False
     if label == "hitbox_2_size":
         self.player[player_int].hitbox_2_size = unpack(
             '<f', mem_update[1])[0]
         return False
     if label == "hitbox_3_size":
         self.player[player_int].hitbox_3_size = unpack(
             '<f', mem_update[1])[0]
         return False
     if label == "hitbox_4_size":
         self.player[player_int].hitbox_4_size = unpack(
             '<f', mem_update[1])[0]
         return False
     if label == "hitbox_1_status":
         temp = unpack('<I', mem_update[1])[0]
         status = True
         if temp == 0:
             status = False
         self.player[player_int].hitbox_1_status = status
         return False
     if label == "hitbox_2_status":
         temp = unpack('<I', mem_update[1])[0]
         status = True
         if temp == 0:
             status = False
         self.player[player_int].hitbox_2_status = status
         return False
     if label == "hitbox_3_status":
         temp = unpack('<I', mem_update[1])[0]
         status = True
         if temp == 0:
             status = False
         self.player[player_int].hitbox_3_status = status
         return False
     if label == "hitbox_4_status":
         temp = unpack('<I', mem_update[1])[0]
         status = True
         if temp == 0:
             status = False
         self.player[player_int].hitbox_4_status = status
         return False
     if label == "hitbox_1_x":
         self.player[player_int].hitbox_1_x = unpack('<f', mem_update[1])[0]
         return False
     if label == "hitbox_1_y":
         self.player[player_int].hitbox_1_y = unpack('<f', mem_update[1])[0]
         return False
     if label == "hitbox_2_x":
         self.player[player_int].hitbox_2_x = unpack('<f', mem_update[1])[0]
         return False
     if label == "hitbox_2_y":
         self.player[player_int].hitbox_2_y = unpack('<f', mem_update[1])[0]
         return False
     if label == "hitbox_3_x":
         self.player[player_int].hitbox_3_x = unpack('<f', mem_update[1])[0]
         return False
     if label == "hitbox_3_y":
         self.player[player_int].hitbox_3_y = unpack('<f', mem_update[1])[0]
         return False
     if label == "hitbox_4_x":
         self.player[player_int].hitbox_4_x = unpack('<f', mem_update[1])[0]
         return False
     if label == "hitbox_4_y":
         self.player[player_int].hitbox_4_y = unpack('<f', mem_update[1])[0]
         return False
     if label == "projectiles":
         #Only once per new frame that we get a projectile, clear the list out
         if self.newframe:
             self.projectiles.clear()
             self.i = 0
         self.i += 1
         self.newframe = False
         if len(mem_update[1]) < 10:
             self.projectiles.clear()
             return False
         proj = Projectile()
         proj.x = unpack('>f', mem_update[1][0x4c:0x50])[0]
         proj.y = unpack('>f', mem_update[1][0x50:0x54])[0]
         proj.x_speed = unpack('>f', mem_update[1][0x40:0x44])[0]
         proj.y_speed = unpack('>f', mem_update[1][0x44:0x48])[0]
         try:
             proj.subtype = enums.ProjectileSubtype(
                 unpack('>I', mem_update[1][0x10:0x14])[0])
         except ValueError:
             proj.subtype = enums.ProjectileSubtype.UNKNOWN_PROJECTILE
         self.projectiles.append(proj)
     return False
Ejemplo n.º 6
0
    def __init__(self, write):
        if write:
            self.csvfile = open('framedata.csv', 'a')
            fieldnames = [
                'character', 'action', 'frame', 'hitbox_1_status',
                'hitbox_1_size', 'hitbox_1_x', 'hitbox_1_y', 'hitbox_2_status',
                'hitbox_2_size', 'hitbox_2_x', 'hitbox_2_y', 'hitbox_3_status',
                'hitbox_3_size', 'hitbox_3_x', 'hitbox_3_y', 'hitbox_4_status',
                'hitbox_4_size', 'hitbox_4_x', 'hitbox_4_y'
            ]
            self.writer = csv.DictWriter(self.csvfile, fieldnames=fieldnames)
            self.writer.writeheader()
            self.rows = []
        #Read the existing framedata
        path = os.path.dirname(os.path.realpath(__file__))
        self.framedata = defaultdict(
            lambda: defaultdict(lambda: defaultdict(dict)))
        with open(path + "/framedata.csv") as csvfile:
            # A list of dicts containing the frame data
            csvreader = list(csv.DictReader(csvfile))
            # Build a series of nested dicts for faster read access
            for frame in csvreader:
                # Pull out the character, action, and frame
                character = enums.Character(int(frame["character"]))
                action = enums.Action(int(frame["action"]))
                action_frame = int(frame["frame"])
                self.framedata[character][action][action_frame] = \
                    {"hitbox_1_status": frame["hitbox_1_status"] == "True", \
                    "hitbox_1_size": float(frame["hitbox_1_size"]), \
                    "hitbox_1_x": float(frame["hitbox_1_x"]), \
                    "hitbox_1_y": float(frame["hitbox_1_y"]), \
                    "hitbox_2_status": frame["hitbox_2_status"] == "True", \
                    "hitbox_2_size": float(frame["hitbox_2_size"]), \
                    "hitbox_2_x": float(frame["hitbox_2_x"]), \
                    "hitbox_2_y": float(frame["hitbox_2_y"]), \
                    "hitbox_3_status": frame["hitbox_3_status"] == "True", \
                    "hitbox_3_size": float(frame["hitbox_3_size"]), \
                    "hitbox_3_x": float(frame["hitbox_3_x"]), \
                    "hitbox_3_y": float(frame["hitbox_3_y"]), \
                    "hitbox_4_status": frame["hitbox_4_status"] == "True", \
                    "hitbox_4_size": float(frame["hitbox_4_size"]), \
                    "hitbox_4_x": float(frame["hitbox_4_x"]), \
                    "hitbox_4_y": float(frame["hitbox_4_y"])}

        #Read the action state data csv
        path = os.path.dirname(os.path.realpath(__file__))
        with open(path + "/actiondata.csv") as csvfile:
            # A list of dicts containing the frame data
            self.actiondata = list(csv.DictReader(csvfile))

        #read the character data csv
        self.characterdata = dict()
        path = os.path.dirname(os.path.realpath(__file__))
        with open(path + "/characterdata.csv") as csvfile:
            reader = csv.DictReader(csvfile)
            for line in reader:
                del line["Character"]
                #Convert all fields to numbers
                for key, value in line.items():
                    line[key] = float(value)
                self.characterdata[enums.Character(
                    line["CharacterIndex"])] = line
Ejemplo n.º 7
0
    def __post_frame(self, gamestate, event_bytes):
        gamestate.stage = self._current_stage
        gamestate.frame = np.ndarray((1,), ">i", event_bytes, 0x1)[0]
        controller_port = np.ndarray((1,), ">B", event_bytes, 0x5)[0] + 1

        if controller_port not in gamestate.player:
            gamestate.player[controller_port] = PlayerState()

        playerstate = gamestate.player[controller_port]
        playerstate.x = np.ndarray((1,), ">f", event_bytes, 0xa)[0]
        playerstate.y = np.ndarray((1,), ">f", event_bytes, 0xe)[0]

        playerstate.character = enums.Character(np.ndarray((1,), ">B", event_bytes, 0x7)[0])
        try:
            playerstate.action = enums.Action(np.ndarray((1,), ">H", event_bytes, 0x8)[0])
        except ValueError:
            playerstate.action = enums.Action.UNKNOWN_ANIMATION

        # Melee stores this in a float for no good reason. So we have to convert
        playerstate.facing = np.ndarray((1,), ">f", event_bytes, 0x12)[0] > 0

        playerstate.percent = int(np.ndarray((1,), ">f", event_bytes, 0x16)[0])
        playerstate.shield_strength = np.ndarray((1,), ">f", event_bytes, 0x1A)[0]
        playerstate.stock = np.ndarray((1,), ">B", event_bytes, 0x21)[0]
        playerstate.action_frame = int(np.ndarray((1,), ">f", event_bytes, 0x22)[0])

        # Extract the bit at mask 0x20
        try:
            bitflags2 = np.ndarray((1,), ">B", event_bytes, 0x27)[0]
            playerstate.hitlag = bool(bitflags2 & 0x20)
        except TypeError:
            playerstate.hitlag = False

        try:
            playerstate.hitstun_frames_left = int(np.ndarray((1,), ">f", event_bytes, 0x2B)[0])
        except TypeError:
            playerstate.hitstun_frames_left = 0
        except ValueError:
            playerstate.hitstun_frames_left = 0
        try:
            playerstate.on_ground = not bool(np.ndarray((1,), ">B", event_bytes, 0x2F)[0])
        except TypeError:
            playerstate.on_ground = True
        try:
            playerstate.jumps_left = np.ndarray((1,), ">B", event_bytes, 0x32)[0]
        except TypeError:
            playerstate.jumps_left = 1

        try:
            playerstate.invulnerable = int(np.ndarray((1,), ">B", event_bytes, 0x34)[0]) != 0
        except TypeError:
            playerstate.invulnerable = False

        try:
            playerstate.speed_air_x_self = np.ndarray((1,), ">f", event_bytes, 0x35)[0]
        except TypeError:
            playerstate.speed_air_x_self = 0

        try:
            playerstate.speed_y_self = np.ndarray((1,), ">f", event_bytes, 0x39)[0]
        except TypeError:
            playerstate.speed_y_self = 0

        try:
            playerstate.speed_x_attack = np.ndarray((1,), ">f", event_bytes, 0x3D)[0]
        except TypeError:
            playerstate.speed_x_attack = 0

        try:
            playerstate.speed_y_attack = np.ndarray((1,), ">f", event_bytes, 0x41)[0]
        except TypeError:
            playerstate.speed_y_attack = 0

        try:
            playerstate.speed_ground_x_self = np.ndarray((1,), ">f", event_bytes, 0x45)[0]
        except TypeError:
            playerstate.speed_ground_x_self = 0

        # Keep track of a player's invulnerability due to respawn or ledge grab
        if controller_port in self._prev_gamestate.player:
            playerstate.invulnerability_left = max(0, self._prev_gamestate.player[controller_port].invulnerability_left - 1)
        if playerstate.action == Action.ON_HALO_WAIT:
            playerstate.invulnerability_left = 120
        # Don't give invulnerability to the first descent
        if playerstate.action == Action.ON_HALO_DESCENT and gamestate.frame > 150:
            playerstate.invulnerability_left = 120
        if playerstate.action == Action.EDGE_CATCHING and playerstate.action_frame == 1:
            playerstate.invulnerability_left = 36

        # The pre-warning occurs when we first start a dash dance.
        if controller_port in self._prev_gamestate.player:
            if playerstate.action == Action.DASHING and \
                    self._prev_gamestate.player[controller_port].action not in [Action.DASHING, Action.TURNING]:
                playerstate.moonwalkwarning = True

        # Take off the warning if the player does an action other than dashing
        if playerstate.action != Action.DASHING:
            playerstate.moonwalkwarning = False

        # "off_stage" helper
        if (abs(playerstate.x) > stages.EDGE_GROUND_POSITION[gamestate.stage] or \
                playerstate.y < -6) and not playerstate.on_ground:
            playerstate.off_stage = True
        else:
            playerstate.off_stage = False

        # ECB top edge, x
        ecb_top_x = 0
        ecb_top_y = 0
        try:
            ecb_top_x = np.ndarray((1,), ">f", event_bytes, 0x49)[0]
        except TypeError:
            ecb_top_x = 0
        # ECB Top edge, y
        try:
            ecb_top_y = np.ndarray((1,), ">f", event_bytes, 0x4D)[0]
        except TypeError:
            ecb_top_y = 0
        playerstate.ecb_top = (ecb_top_x, ecb_top_y)

        # ECB bottom edge, x coord
        ecb_bot_x = 0
        ecb_bot_y = 0
        try:
            ecb_bot_x = np.ndarray((1,), ">f", event_bytes, 0x51)[0]
        except TypeError:
            ecb_bot_x = 0
        # ECB Bottom edge, y coord
        try:
            ecb_bot_y = np.ndarray((1,), ">f", event_bytes, 0x55)[0]
        except TypeError:
            ecb_bot_y = 0
        playerstate.ecb_bottom = (ecb_bot_x, ecb_bot_y)

        # ECB left edge, x coord
        ecb_left_x = 0
        ecb_left_y = 0
        try:
            ecb_left_x = np.ndarray((1,), ">f", event_bytes, 0x59)[0]
        except TypeError:
            ecb_left_x = 0
        # ECB left edge, y coord
        try:
            ecb_left_y = np.ndarray((1,), ">f", event_bytes, 0x5D)[0]
        except TypeError:
            ecb_left_y = 0
        playerstate.ecb_left = (ecb_left_x, ecb_left_y)

        # ECB right edge, x coord
        ecb_right_x = 0
        ecb_right_y = 0
        try:
            ecb_right_x = np.ndarray((1,), ">f", event_bytes, 0x61)[0]
        except TypeError:
            ecb_right_x = 0
        # ECB right edge, y coord
        try:
            ecb_right_y = np.ndarray((1,), ">f", event_bytes, 0x65)[0]
        except TypeError:
            ecb_right_y = 0
        playerstate.ecb_right = (ecb_right_x, ecb_right_y)
        if self._allow_old_version:
            self._frame = gamestate.frame