def find_landing_plane(l: Vector, v: Vector, g: float): if abs(l.y) >= 5120 or (v.x == 0 and v.y == 0 and g == 0): return 5 times = [ -1, -1, -1, -1, -1, -1 ] # side_wall_pos, side_wall_neg, back_wall_pos, back_wall_neg, ceiling, floor if v.x != 0: times[0] = (4080 - l.x) / v.x times[1] = (-4080 - l.x) / v.x if v.y != 0: times[2] = (5110 - l.y) / v.y times[3] = (-5110 - l.y) / v.y if g != 0: # this is the vertex of the equation, which also happens to be the apex of the trajectory h = v.z / -g # time to apex k = v.z * v.z / -g # vertical height at apex # a is the current gravity... because reasons # a = g climb_dist = -l.z # if the gravity is inverted, the the ceiling becomes the floor and the floor becomes the ceiling... if g < 0: climb_dist += 2030 if k >= climb_dist: times[4] = vertex_quadratic_solve_for_x_min_non_neg( g, h, k, climb_dist) elif g > 0: climb_dist += 20 if k <= climb_dist: times[5] = vertex_quadratic_solve_for_x_min_non_neg( g, h, k, climb_dist) # this is necessary because after we reach our terminal velocity, the equation becomes linear (distance_remaining / terminal_velocity) terminal_velocity = (2300 - v.flatten().magnitude()) * sign(g) falling_time_until_terminal_velocity = (terminal_velocity - v.z) / g falling_distance_until_terminal_velocity = v.z * falling_time_until_terminal_velocity + -g * ( falling_time_until_terminal_velocity * falling_time_until_terminal_velocity) / 2. fall_distance = -l.z if g < 0: times[5] = get_landing_time( fall_distance + 20, falling_time_until_terminal_velocity, falling_distance_until_terminal_velocity, terminal_velocity, k, h, g) else: times[4] = get_landing_time( fall_distance + 2030, falling_time_until_terminal_velocity, falling_distance_until_terminal_velocity, terminal_velocity, k, h, g) return times.index(min(item for item in times if item >= 0))
def valid_ceiling_shot(agent: VirxERLU, cap_=5): struct = agent.ball_prediction_struct if struct is None: return end_slice = math.ceil(cap_ * 60) slices = struct.slices[30:end_slice:2] if agent.me.location.x * side(agent.team) > 0: quadrilateral = (round(agent.foe_goal.right_post.flatten()), round(agent.foe_goal.left_post.flatten())) else: quadrilateral = (round(agent.foe_goal.left_post.flatten()), round(agent.foe_goal.right_post.flatten())) quadrilateral += ( Vector(0, 640), Vector(round(agent.me.location.x - (200 * sign(agent.me.location.x))), round(agent.me.location.y - (200 * side(agent.team)))), ) agent.polyline(quadrilateral + (quadrilateral[0], ), agent.renderer.team_color(alt_color=True)) for ball_slice in slices: intercept_time = ball_slice.game_seconds time_remaining = intercept_time - agent.time if time_remaining <= 0: return ball_location = Vector(ball_slice.physics.location.x, ball_slice.physics.location.y, ball_slice.physics.location.z) if ball_location.z < 642: continue if not point_inside_quadrilateral_2d(round(ball_location.flatten()), quadrilateral): continue return ball_location