def __pre_frame(self, gamestate, event_bytes): # Grab the physical controller state and put that into the controller state 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.costume = self._costumes[controller_port - 1] playerstate.cpu_level = self._cpu_level[controller_port - 1] main_x = (np.ndarray((1, ), ">f", event_bytes, 0x19)[0] / 2) + 0.5 main_y = (np.ndarray((1, ), ">f", event_bytes, 0x1D)[0] / 2) + 0.5 playerstate.controller_state.main_stick = (main_x, main_y) c_x = (np.ndarray((1, ), ">f", event_bytes, 0x21)[0] / 2) + 0.5 c_y = (np.ndarray((1, ), ">f", event_bytes, 0x25)[0] / 2) + 0.5 playerstate.controller_state.c_stick = (c_x, c_y) # The game interprets both shoulders together, so the processed value will always be the same trigger = (np.ndarray((1, ), ">f", event_bytes, 0x29)[0]) playerstate.controller_state.l_shoulder = trigger playerstate.controller_state.r_shoulder = trigger buttonbits = np.ndarray((1, ), ">H", event_bytes, 0x31)[0] playerstate.controller_state.button[enums.Button.BUTTON_A] = bool( int(buttonbits) & 0x0100) playerstate.controller_state.button[enums.Button.BUTTON_B] = bool( int(buttonbits) & 0x0200) playerstate.controller_state.button[enums.Button.BUTTON_X] = bool( int(buttonbits) & 0x0400) playerstate.controller_state.button[enums.Button.BUTTON_Y] = bool( int(buttonbits) & 0x0800) playerstate.controller_state.button[enums.Button.BUTTON_START] = bool( int(buttonbits) & 0x1000) playerstate.controller_state.button[enums.Button.BUTTON_Z] = bool( int(buttonbits) & 0x0010) playerstate.controller_state.button[enums.Button.BUTTON_R] = bool( int(buttonbits) & 0x0020) playerstate.controller_state.button[enums.Button.BUTTON_L] = bool( int(buttonbits) & 0x0040) playerstate.controller_state.button[enums.Button.BUTTON_D_LEFT] = bool( int(buttonbits) & 0x0001) playerstate.controller_state.button[ enums.Button.BUTTON_D_RIGHT] = bool(int(buttonbits) & 0x0002) playerstate.controller_state.button[enums.Button.BUTTON_D_DOWN] = bool( int(buttonbits) & 0x0004) playerstate.controller_state.button[enums.Button.BUTTON_D_UP] = bool( int(buttonbits) & 0x0008) if self._use_manual_bookends: self._frame = gamestate.frame
def __pre_frame(self, gamestate, event_bytes): # Grab the physical controller state and put that into the controller state 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] main_x = (np.ndarray((1,), ">f", event_bytes, 0x19)[0] / 2) + 0.5 main_y = (np.ndarray((1,), ">f", event_bytes, 0x1D)[0] / 2) + 0.5 playerstate.controller_state.main_stick = (main_x, main_y) c_x = (np.ndarray((1,), ">f", event_bytes, 0x21)[0] / 2) + 0.5 c_y = (np.ndarray((1,), ">f", event_bytes, 0x25)[0] / 2) + 0.5 playerstate.controller_state.c_stick = (c_x, c_y) buttonbits = np.ndarray((1,), ">H", event_bytes, 0x31)[0] playerstate.controller_state.button[enums.Button.BUTTON_A] = bool(int(buttonbits) & 0x0100) playerstate.controller_state.button[enums.Button.BUTTON_B] = bool(int(buttonbits) & 0x0200) playerstate.controller_state.button[enums.Button.BUTTON_X] = bool(int(buttonbits) & 0x0400) playerstate.controller_state.button[enums.Button.BUTTON_Y] = bool(int(buttonbits) & 0x0800) playerstate.controller_state.button[enums.Button.BUTTON_START] = bool(int(buttonbits) & 0x1000) playerstate.controller_state.button[enums.Button.BUTTON_Z] = bool(int(buttonbits) & 0x0010) playerstate.controller_state.button[enums.Button.BUTTON_R] = bool(int(buttonbits) & 0x0020) playerstate.controller_state.button[enums.Button.BUTTON_L] = bool(int(buttonbits) & 0x0040) playerstate.controller_state.button[enums.Button.BUTTON_D_LEFT] = bool(int(buttonbits) & 0x0001) playerstate.controller_state.button[enums.Button.BUTTON_D_RIGHT] = bool(int(buttonbits) & 0x0002) playerstate.controller_state.button[enums.Button.BUTTON_D_DOWN] = bool(int(buttonbits) & 0x0004) playerstate.controller_state.button[enums.Button.BUTTON_D_UP] = bool(int(buttonbits) & 0x0008) if self._allow_old_version: self._frame = gamestate.frame
def __handle_slippstream_menu_event(self, event_bytes, gamestate): """ Internal handler for slippstream menu events Modifies specified gamestate based on the event bytes """ scene = np.ndarray((1,), ">H", event_bytes, 0x1)[0] if scene == 0x02: gamestate.menu_state = enums.Menu.CHARACTER_SELECT # All the controller ports are active on this screen gamestate.players[1] = PlayerState() gamestate.players[2] = PlayerState() gamestate.players[3] = PlayerState() gamestate.players[4] = PlayerState() elif scene in [0x0102, 0x0108]: gamestate.menu_state = enums.Menu.STAGE_SELECT gamestate.players[1] = PlayerState() gamestate.players[2] = PlayerState() gamestate.players[3] = PlayerState() gamestate.players[4] = PlayerState() elif scene == 0x0202: gamestate.menu_state = enums.Menu.IN_GAME elif scene == 0x0001: gamestate.menu_state = enums.Menu.MAIN_MENU elif scene == 0x0008: gamestate.menu_state = enums.Menu.SLIPPI_ONLINE_CSS gamestate.players[1] = PlayerState() gamestate.players[2] = PlayerState() gamestate.players[3] = PlayerState() gamestate.players[4] = PlayerState() elif scene == 0x0000: gamestate.menu_state = enums.Menu.PRESS_START else: gamestate.menu_state = enums.Menu.UNKNOWN_MENU # controller port statuses at CSS if gamestate.menu_state in [enums.Menu.CHARACTER_SELECT, enums.Menu.SLIPPI_ONLINE_CSS]: gamestate.players[1].controller_status = enums.ControllerStatus(np.ndarray((1,), ">B", event_bytes, 0x25)[0]) gamestate.players[2].controller_status = enums.ControllerStatus(np.ndarray((1,), ">B", event_bytes, 0x26)[0]) gamestate.players[3].controller_status = enums.ControllerStatus(np.ndarray((1,), ">B", event_bytes, 0x27)[0]) gamestate.players[4].controller_status = enums.ControllerStatus(np.ndarray((1,), ">B", event_bytes, 0x28)[0]) # CSS Cursors gamestate.players[1].cursor_x = np.ndarray((1,), ">f", event_bytes, 0x3)[0] gamestate.players[1].cursor_y = np.ndarray((1,), ">f", event_bytes, 0x7)[0] gamestate.players[2].cursor_x = np.ndarray((1,), ">f", event_bytes, 0xB)[0] gamestate.players[2].cursor_y = np.ndarray((1,), ">f", event_bytes, 0xF)[0] gamestate.players[3].cursor_x = np.ndarray((1,), ">f", event_bytes, 0x13)[0] gamestate.players[3].cursor_y = np.ndarray((1,), ">f", event_bytes, 0x17)[0] gamestate.players[4].cursor_x = np.ndarray((1,), ">f", event_bytes, 0x1B)[0] gamestate.players[4].cursor_y = np.ndarray((1,), ">f", event_bytes, 0x1F)[0] # Ready to fight banner gamestate.ready_to_start = np.ndarray((1,), ">B", event_bytes, 0x23)[0] # Character selected try: gamestate.players[1].character = enums.to_internal(np.ndarray((1,), ">B", event_bytes, 0x29)[0]) gamestate.players[1].character_selected = gamestate.players[1].character except TypeError: gamestate.players[1].character = enums.Character.UNKNOWN_CHARACTER gamestate.players[1].character_selected = enums.Character.UNKNOWN_CHARACTER try: gamestate.players[2].character = enums.to_internal(np.ndarray((1,), ">B", event_bytes, 0x2A)[0]) gamestate.players[2].character_selected = gamestate.players[2].character except TypeError: gamestate.players[2].character = enums.Character.UNKNOWN_CHARACTER gamestate.players[2].character_selected = enums.Character.UNKNOWN_CHARACTER try: gamestate.players[3].character = enums.to_internal(np.ndarray((1,), ">B", event_bytes, 0x2B)[0]) gamestate.players[3].character_selected = gamestate.players[3].character except TypeError: gamestate.players[3].character = enums.Character.UNKNOWN_CHARACTER gamestate.players[3].character_selected = enums.Character.UNKNOWN_CHARACTER try: gamestate.players[4].character = enums.to_internal(np.ndarray((1,), ">B", event_bytes, 0x2C)[0]) gamestate.players[4].character_selected = gamestate.players[4].character except TypeError: gamestate.players[4].character = enums.Character.UNKNOWN_CHARACTER gamestate.players[4].character_selected = enums.Character.UNKNOWN_CHARACTER # Coin down try: gamestate.players[1].coin_down = np.ndarray((1,), ">B", event_bytes, 0x2D)[0] == 2 except TypeError: gamestate.players[1].coin_down = False try: gamestate.players[2].coin_down = np.ndarray((1,), ">B", event_bytes, 0x2E)[0] == 2 except TypeError: gamestate.players[2].coin_down = False try: gamestate.players[3].coin_down = np.ndarray((1,), ">B", event_bytes, 0x2F)[0] == 2 except TypeError: gamestate.players[3].coin_down = False try: gamestate.players[4].coin_down = np.ndarray((1,), ">B", event_bytes, 0x30)[0] == 2 except TypeError: gamestate.players[4].coin_down = False if gamestate.menu_state == enums.Menu.STAGE_SELECT: # Stage try: gamestate.stage = enums.Stage(np.ndarray((1,), ">B", event_bytes, 0x24)[0]) except ValueError: gamestate.stage = enums.Stage.NO_STAGE # Stage Select Cursor X, Y for _, player in gamestate.players.items(): player.cursor.x = np.ndarray((1,), ">f", event_bytes, 0x31)[0] player.cursor.y = np.ndarray((1,), ">f", event_bytes, 0x35)[0] gamestate.stage_select_cursor_x = player.cursor.x gamestate.stage_select_cursor_y = player.cursor.y # Frame count gamestate.frame = np.ndarray((1,), ">i", event_bytes, 0x39)[0] # Sub-menu try: gamestate.submenu = enums.SubMenu(np.ndarray((1,), ">B", event_bytes, 0x3D)[0]) except TypeError: gamestate.submenu = enums.SubMenu.UNKNOWN_SUBMENU except ValueError: gamestate.submenu = enums.SubMenu.UNKNOWN_SUBMENU # Selected menu try: gamestate.menu_selection = np.ndarray((1,), ">B", event_bytes, 0x3E)[0] except TypeError: gamestate.menu_selection = 0 # Online costume chosen try: if gamestate.menu_state == enums.Menu.SLIPPI_ONLINE_CSS: for i in range(4): gamestate.players[i+1].costume = np.ndarray((1,), ">B", event_bytes, 0x3F)[0] except TypeError: pass # This value is 0x05 in the nametag entry try: if gamestate.menu_state == enums.Menu.SLIPPI_ONLINE_CSS: nametag = np.ndarray((1,), ">B", event_bytes, 0x40)[0] if nametag == 0x05: gamestate.submenu = enums.SubMenu.NAME_ENTRY_SUBMENU elif nametag == 0x00: gamestate.submenu = enums.SubMenu.ONLINE_CSS except TypeError: pass # CPU Level try: for i in range(4): gamestate.players[i+1].cpu_level = np.ndarray((1,), ">B", event_bytes, 0x41 + i)[0] except TypeError: pass except KeyError: pass # Is Holding CPU Slider try: for i in range(4): gamestate.players[i+1].is_holding_cpu_slider = np.ndarray((1,), ">B", event_bytes, 0x45 + i)[0] except TypeError: pass except KeyError: pass # Set CPU level to 0 if we're not a CPU for port in gamestate.players: if gamestate.players[port].controller_status != enums.ControllerStatus.CONTROLLER_CPU: gamestate.players[port].cpu_level = 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
def __handle_slippstream_menu_event(self, event_bytes, gamestate): """ Internal handler for slippstream menu events Modifies specified gamestate based on the event bytes """ scene = np.ndarray((1,), ">H", event_bytes, 0x1)[0] if scene == 0x02: gamestate.menu_state = enums.Menu.CHARACTER_SELECT # All the controller ports are active on this screen gamestate.player[1] = PlayerState() gamestate.player[2] = PlayerState() gamestate.player[3] = PlayerState() gamestate.player[4] = PlayerState() elif scene == 0x0102: gamestate.menu_state = enums.Menu.STAGE_SELECT elif scene == 0x0202: gamestate.menu_state = enums.Menu.IN_GAME elif scene == 0x0001: gamestate.menu_state = enums.Menu.MAIN_MENU elif scene == 0x0008: gamestate.menu_state = enums.Menu.SLIPPI_ONLINE_CSS gamestate.player[1] = PlayerState() gamestate.player[2] = PlayerState() gamestate.player[3] = PlayerState() gamestate.player[4] = PlayerState() elif scene == 0x0000: gamestate.menu_state = enums.Menu.PRESS_START else: gamestate.menu_state = enums.Menu.UNKNOWN_MENU # controller port statuses at CSS if gamestate.menu_state in [enums.Menu.CHARACTER_SELECT, enums.Menu.SLIPPI_ONLINE_CSS]: gamestate.player[1].controller_status = enums.ControllerStatus(np.ndarray((1,), ">B", event_bytes, 0x25)[0]) gamestate.player[2].controller_status = enums.ControllerStatus(np.ndarray((1,), ">B", event_bytes, 0x26)[0]) gamestate.player[3].controller_status = enums.ControllerStatus(np.ndarray((1,), ">B", event_bytes, 0x27)[0]) gamestate.player[4].controller_status = enums.ControllerStatus(np.ndarray((1,), ">B", event_bytes, 0x28)[0]) # CSS Cursors gamestate.player[1].cursor_x = np.ndarray((1,), ">f", event_bytes, 0x3)[0] gamestate.player[1].cursor_y = np.ndarray((1,), ">f", event_bytes, 0x7)[0] gamestate.player[2].cursor_x = np.ndarray((1,), ">f", event_bytes, 0xB)[0] gamestate.player[2].cursor_y = np.ndarray((1,), ">f", event_bytes, 0xF)[0] gamestate.player[3].cursor_x = np.ndarray((1,), ">f", event_bytes, 0x13)[0] gamestate.player[3].cursor_y = np.ndarray((1,), ">f", event_bytes, 0x17)[0] gamestate.player[4].cursor_x = np.ndarray((1,), ">f", event_bytes, 0x1B)[0] gamestate.player[4].cursor_y = np.ndarray((1,), ">f", event_bytes, 0x1F)[0] # Ready to fight banner gamestate.ready_to_start = np.ndarray((1,), ">B", event_bytes, 0x23)[0] # Character selected try: gamestate.player[1].character_selected = enums.to_internal(np.ndarray((1,), ">B", event_bytes, 0x29)[0]) except TypeError: gamestate.player[1].character_selected = enums.Character.UNKNOWN_CHARACTER try: gamestate.player[2].character_selected = enums.to_internal(np.ndarray((1,), ">B", event_bytes, 0x2A)[0]) except TypeError: gamestate.player[2].character_selected = enums.Character.UNKNOWN_CHARACTER try: gamestate.player[3].character_selected = enums.to_internal(np.ndarray((1,), ">B", event_bytes, 0x2B)[0]) except TypeError: gamestate.player[3].character_selected = enums.Character.UNKNOWN_CHARACTER try: gamestate.player[4].character_selected = enums.to_internal(np.ndarray((1,), ">B", event_bytes, 0x2C)[0]) except TypeError: gamestate.player[4].character_selected = enums.Character.UNKNOWN_CHARACTER # Coin down try: gamestate.player[1].coin_down = np.ndarray((1,), ">B", event_bytes, 0x2D)[0] == 2 except TypeError: gamestate.player[1].coin_down = False try: gamestate.player[2].coin_down = np.ndarray((1,), ">B", event_bytes, 0x2E)[0] == 2 except TypeError: gamestate.player[2].coin_down = False try: gamestate.player[3].coin_down = np.ndarray((1,), ">B", event_bytes, 0x2F)[0] == 2 except TypeError: gamestate.player[3].coin_down = False try: gamestate.player[4].coin_down = np.ndarray((1,), ">B", event_bytes, 0x30)[0] == 2 except TypeError: gamestate.player[4].coin_down = False if gamestate.menu_state == enums.Menu.STAGE_SELECT: # Stage try: gamestate.stage = enums.Stage(np.ndarray((1,), ">B", event_bytes, 0x24)[0]) except ValueError: gamestate.stage = enums.Stage.NO_STAGE # Stage Select Cursor X, Y gamestate.stage_select_cursor_x = np.ndarray((1,), ">f", event_bytes, 0x31)[0] gamestate.stage_select_cursor_y = np.ndarray((1,), ">f", event_bytes, 0x35)[0] # Frame count gamestate.frame = np.ndarray((1,), ">i", event_bytes, 0x39)[0] # Sub-menu try: gamestate.submenu = enums.SubMenu(np.ndarray((1,), ">B", event_bytes, 0x3D)[0]) except TypeError: gamestate.submenu = enums.SubMenu.UNKNOWN_SUBMENU except ValueError: gamestate.submenu = enums.SubMenu.UNKNOWN_SUBMENU # Selected menu try: gamestate.menu_selection = np.ndarray((1,), ">B", event_bytes, 0x3E)[0] except TypeError: gamestate.menu_selection = 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