Beispiel #1
0
    def __item_update(self, gamestate, event_bytes):
        projectile = Projectile()
        projectile.position.x = np.ndarray((1, ), ">f", event_bytes, 0x14)[0]
        projectile.position.y = np.ndarray((1, ), ">f", event_bytes, 0x18)[0]
        projectile.x = projectile.position.x
        projectile.y = projectile.position.y
        projectile.speed.x = np.ndarray((1, ), ">f", event_bytes, 0xc)[0]
        projectile.speed.y = np.ndarray((1, ), ">f", event_bytes, 0x10)[0]
        projectile.x_speed = projectile.speed.x
        projectile.y_speed = projectile.speed.y
        try:
            projectile.owner = np.ndarray(
                (1, ), ">B", event_bytes, 0x2A)[0] + 1
            if projectile.owner > 4:
                projectile.owner = -1
        except TypeError:
            projectile.owner = -1
        try:
            projectile.type = enums.ProjectileType(
                np.ndarray((1, ), ">H", event_bytes, 0x5)[0])
        except ValueError:
            projectile.type = enums.ProjectileType.UNKNOWN_PROJECTILE

        try:
            projectile.frame = int(
                np.ndarray((1, ), ">f", event_bytes, 0x1E)[0])
        except ValueError:
            projectile.frame = -1

        projectile.subtype = np.ndarray((1, ), ">B", event_bytes, 0x7)[0]

        # Ignore exploded Samus bombs. They are subtype 3
        if projectile.type == enums.ProjectileType.SAMUS_BOMB and projectile.subtype == 3:
            return
        # Ignore exploded Samus missles
        if projectile.type == enums.ProjectileType.SAMUS_MISSLE and projectile.subtype in [
                2, 3
        ]:
            return
        # Ignore Samus charge beam while charging (not firing)
        if projectile.type == enums.ProjectileType.SAMUS_CHARGE_BEAM and projectile.subtype == 0:
            return

        # Add the projectile to the gamestate list
        gamestate.projectiles.append(projectile)
Beispiel #2
0
 def __item_update(self, gamestate, event_bytes):
     projectile = Projectile()
     projectile.x = np.ndarray((1,), ">f", event_bytes, 0x14)[0]
     projectile.y = np.ndarray((1,), ">f", event_bytes, 0x18)[0]
     projectile.x_speed = np.ndarray((1,), ">f", event_bytes, 0xc)[0]
     projectile.y_speed = np.ndarray((1,), ">f", event_bytes, 0x10)[0]
     try:
         projectile.owner = np.ndarray((1,), ">B", event_bytes, 0x2A)[0] + 1
         if projectile.owner > 4:
             projectile.owner = -1
     except TypeError:
         projectile.owner = -1
     try:
         projectile.subtype = enums.ProjectileSubtype(np.ndarray((1,), ">H", event_bytes, 0x5)[0])
     except ValueError:
         projectile.subtype = enums.ProjectileSubtype.UNKNOWN_PROJECTILE
     # Add the projectile to the gamestate list
     gamestate.projectiles.append(projectile)
Beispiel #3
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
Beispiel #4
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