Given the available information, can you modify it so that it predicts the values 1 tick in the future (1/120 second). All the units are in unreal units per second. Action number 6 of prev_action (		self.controls.throttle = action[0]
		self.controls.steer = action[1]
		self.controls.pitch = action[2]
		self.controls.yaw = action[3]
		self.controls.roll = action[4]
		self.controls.jump = action[5] > 0
		self.controls.boost = action[6] > 0
		self.controls.handbrake = action[7] > 0) is if the player was boosting. We can predict if the other players were boosting by tracking the previous boost amount, if the boost amount went down, if it went up by less than 0.12 ( picking up small boost adds 0.12), or if it went up more than 0.12 but is less than 1.0 ( big boost fills the boost amount to 1.0). 
here is my current obs, modify it and provide the full code with the changes so I can copy and paste: import numpy as np
import random
from typing import List, Tuple

class CommonValues:
    SIDE_WALL_X = 4096
    BACK_WALL_Y = 5120
    CEILING_Z = 2044
    CAR_MAX_SPEED = 2300
    CAR_MAX_ANG_VEL = 5.5
    BALL_MAX_SPEED = 6000
    BOOST_LOCATIONS_AMOUNT = 34
    GRAVITY_Z = -650.0

class Team:
    BLUE = 0
    ORANGE = 1

class EmbeddedOBS:
    def __init__(self,
                 teammate_dim: int = 68,
                 opponent_dim: int = 102,
                 ball_dim: int = 9,
                 player_dim: int = 25,
                 pos_coef: Tuple[float, float, float] = (1 / CommonValues.SIDE_WALL_X, 1 / CommonValues.BACK_WALL_Y, 1 / CommonValues.CEILING_Z),
                 vel_coef: float = 1 / CommonValues.CAR_MAX_SPEED,
                 ang_vel_coef: float = 1 / CommonValues.CAR_MAX_ANG_VEL,
                 rel_pos_coef: Tuple[float, float, float] = (1 / (2 * CommonValues.SIDE_WALL_X), 1 / (2 * CommonValues.BACK_WALL_Y), 1 / CommonValues.CEILING_Z),
                 rel_vel_coef: float = 1 / (2 * CommonValues.CAR_MAX_SPEED),
                 rel_ang_vel_coef: float = 1 / (2 * CommonValues.CAR_MAX_ANG_VEL),
                 ball_vel_coef: float = 1 / CommonValues.BALL_MAX_SPEED,
                 ball_ang_vel_coef: float = 1 / 6.0,
                 rel_ball_vel_coef: float = 1 / (CommonValues.BALL_MAX_SPEED + CommonValues.CAR_MAX_SPEED),
                 rel_ball_ang_vel_coef: float = 1 / (CommonValues.CAR_MAX_ANG_VEL + 6.0)):
        self.teammate_dim = teammate_dim
        self.opponent_dim = opponent_dim
        self.ball_dim = ball_dim
        self.player_dim = player_dim
        self.pos_coef = np.array(pos_coef)
        self.vel_coef = vel_coef
        self.ang_vel_coef = ang_vel_coef
        self.rel_pos_coef = np.array(rel_pos_coef)
        self.rel_vel_coef = rel_vel_coef
        self.rel_ang_vel_coef = rel_ang_vel_coef
        self.ball_vel_coef = ball_vel_coef
        self.ball_ang_vel_coef = ball_ang_vel_coef
        self.rel_ball_vel_coef = rel_ball_vel_coef
        self.rel_ball_ang_vel_coef = rel_ball_ang_vel_coef

    def build_obs(self, player: 'PlayerData', state: 'GameState', prev_action: List[float]) -> List[float]:
        result = []
        inv = player.team_num == Team.ORANGE

        # Process ball information
        result.extend(self.process_ball(state.inverted_ball if inv else state.ball))

        # Add boost pad information
        pads = state.inverted_boost_pads if inv else state.boost_pads
        result.extend(pads)

        # Add previous action
        result.extend(prev_action)

        # Process self information
        result.extend(self.process_local_player(player, state.inverted_ball if inv else state.ball, inv))

        # Process teammates
        result.extend(self.process_players(state.players, player.team_num, player.car_id, 
                                           state.inverted_ball if inv else state.ball, 
                                           player.inverted_car_data if inv else player.car_data, 
                                           inv, self.teammate_dim))

        # Process opponents
        result.extend(self.process_players(state.players, Team.ORANGE if player.team_num == Team.BLUE else Team.BLUE, 
                                           player.car_id, state.inverted_ball if inv else state.ball, 
                                           player.inverted_car_data if inv else player.car_data, 
                                           inv, self.opponent_dim))

        return result

    def process_ball(self, ball: 'PhysicsObject') -> List[float]:
        ball_obs = [
            *ball.position * self.pos_coef,
            *ball.linear_velocity * self.ball_vel_coef,
            *ball.angular_velocity * self.ball_ang_vel_coef
        ]
        return self.embed_info(ball_obs, self.ball_dim)

    def process_local_player(self, player: 'PlayerData', ball: 'PhysicsObject', inv: bool) -> List[float]:
        player_obs = self.add_local_player_to_obs(player, ball, inv)
        return self.embed_info(player_obs, self.player_dim)

    def process_players(self, players: List['PlayerData'], team: int, self_id: int, 
                        ball: 'PhysicsObject', local_player: 'PhysicsObject', inv: bool, embedding_size: int) -> List[float]:
        player_observations = []

        for other_player in players:
            if other_player.team_num == team and other_player.car_id != self_id:
                player_obs = self.add_player_to_obs(other_player, ball, local_player, inv)
                player_observations.append(player_obs)

        # Shuffle player observations
        random.shuffle(player_observations)

        return self.embed_info(player_observations, embedding_size)

    def add_local_player_to_obs(self, player: 'PlayerData', ball: 'PhysicsObject', inv: bool) -> List[float]:
        car_data = player.inverted_car_data if inv else player.car_data
        obs = []

        # Relative position to ball
        rel_pos_to_ball = (ball.position - car_data.position) * self.rel_pos_coef
        obs.extend(rel_pos_to_ball)

        # Relative velocity to ball
        rel_vel_to_ball = (ball.linear_velocity - car_data.linear_velocity) * self.rel_ball_vel_coef
        obs.extend(rel_vel_to_ball)

        # Player's position
        obs.extend(car_data.position * self.pos_coef)

        # Player's velocity and angular velocity
        obs.extend(car_data.linear_velocity * self.vel_coef)
        obs.extend(car_data.angular_velocity * self.ang_vel_coef)

        # Player's orientation
        obs.extend(car_data.forward())
        obs.extend(car_data.up())

        # Additional player state information
        obs.extend([
            player.boost_amount,
            float(player.on_ground),
            float(player.has_flip),
            float(player.is_demoed),
        ])

        return obs

    def add_player_to_obs(self, player: 'PlayerData', ball: 'PhysicsObject', local_player: 'PhysicsObject', inv: bool) -> List[float]:
        car_data = player.inverted_car_data if inv else player.car_data
        obs = []

        # Relative position to local player
        obs.extend((car_data.position - local_player.position) * self.rel_pos_coef)

        # Relative velocity to local player
        obs.extend((car_data.linear_velocity - local_player.linear_velocity) * self.rel_vel_coef)

        # Relative angular velocity to local player
        obs.extend((car_data.angular_velocity - local_player.angular_velocity) * self.rel_ang_vel_coef)

        # Relative position to ball
        rel_pos_to_ball = (ball.position - car_data.position) * self.rel_pos_coef
        obs.extend(rel_pos_to_ball)

        # Relative velocity to ball
        rel_vel_to_ball = (ball.linear_velocity - car_data.linear_velocity) * self.rel_ball_vel_coef
        obs.extend(rel_vel_to_ball)

        # Player's position
        obs.extend(car_data.position * self.pos_coef)

        # Player's velocity and angular velocity
        obs.extend(car_data.linear_velocity * self.vel_coef)
        obs.extend(car_data.angular_velocity * self.ang_vel_coef)

        # Player's orientation
        obs.extend(car_data.forward())
        obs.extend(car_data.up())

        # Additional player state information
        obs.extend([
            player.boost_amount,
            float(player.on_ground),
            float(player.has_flip),
            float(player.is_demoed),
        ])

        return obs

    def embed_info(self, info: List[float], embedding_size: int) -> List[float]:
        if not info:
            return [0.0] * embedding_size
        
        if isinstance(info[0], list):  # List of lists
            embedding = [0.0] * embedding_size
            for i in range(embedding_size):
                sum_values = sum(player_info[i % len(player_info)] for player_info in info)
                embedding[i] = sum_values / len(info)
        else:  # Single list
            embedding = [info[i % len(info)] for i in range(embedding_size)]
        
        return embedding