Skip to content

Prediction

Using Prediction SDK

WARNING

Before using the SDK you need to instantiate it using sdk_init::prediction() - example provided on this page

Prediction Enums

cpp
enum hitchance: int {
    automatic = -1,
    any = 0,
    low = 30,
    medium = 50,
    high = 70,
    very_high = 85,
    guaranteed_hit = 100,
};

enum class hit_type: uint8_t {
    normal = 0,
    undodgeable,
    cast,
    zhonyas,
    cc,
    cc_hard,
    dash,
};

enum class spell_type: uint8_t {
    linear = 0,
    targetted,
    circular,
    vector,
};

/*
    basic attack range from edge to edge
    targeted skill range from center to center (mainly not always)
    skillshot range from center to edge (mainly not always)
    and the range of self-centered area of effects are from the center of the source (blitz R, diana R..)
*/
enum class targetting_type: uint8_t {
    center = 0,
    center_to_edge,
    edge_to_edge,
};

enum class collision_type: uint8_t {
    unit = 0,
    hero,
    turret,
    terrain,
    yasuo_wall,
    braum_wall,
};
enum hitchance: int {
    automatic = -1,
    any = 0,
    low = 30,
    medium = 50,
    high = 70,
    very_high = 85,
    guaranteed_hit = 100,
};

enum class hit_type: uint8_t {
    normal = 0,
    undodgeable,
    cast,
    zhonyas,
    cc,
    cc_hard,
    dash,
};

enum class spell_type: uint8_t {
    linear = 0,
    targetted,
    circular,
    vector,
};

/*
    basic attack range from edge to edge
    targeted skill range from center to center (mainly not always)
    skillshot range from center to edge (mainly not always)
    and the range of self-centered area of effects are from the center of the source (blitz R, diana R..)
*/
enum class targetting_type: uint8_t {
    center = 0,
    center_to_edge,
    edge_to_edge,
};

enum class collision_type: uint8_t {
    unit = 0,
    hero,
    turret,
    terrain,
    yasuo_wall,
    braum_wall,
};

Spell Data

INFO

This is the data that needs to be fed to most prediction functions

cpp
class spell_data {
public:
    spell_type spell_type{};
    targetting_type targetting_type{};
    int expected_hitchance = hitchance::automatic; // the expected hitchance

    game_object* source{}; // source object, if none player will be taken
    math::vector3 source_position{}; // position where the skillshot originates from, if none player position will be taken

    bool bypass_anti_buffering{}; // allows casting spells while other spells are being casted (allow spell buffering)
    int spell_slot = -1; // will be used to check for CD if expected_hitchance is automatic, if the CD of the spell is low we can spam it more
    float range{}; // max range of the spell
    float radius{}; // circle is the same as linear, use * 0.5f of the TOTAL radius (so only distance from player to one side)
    float cast_range{}; // the cast range of the spell for vector types: viktor E, ruble R..
    float delay{}; // cast delay
    float proc_delay{}; // delay until the spell hits, for example syndra Q is static 0.6
    float projectile_speed = FLT_MAX; // projectile speed if any, FLT_MAX if the spell has no projectiles
    float extension_override{}; // if we want to override the prediction extension

    std::vector< collision_type > forbidden_collisions{}; // things we dont want to skillshot to collide with
    std::vector< hit_type > expected_hit_types{}; // if we want special hit types only, fill them in here
    std::function< bool( game_object* ) > additional_target_selection_checks{}; // custom function for target selection checks, example: target with specific buff(s) only
};
class spell_data {
public:
    spell_type spell_type{};
    targetting_type targetting_type{};
    int expected_hitchance = hitchance::automatic; // the expected hitchance

    game_object* source{}; // source object, if none player will be taken
    math::vector3 source_position{}; // position where the skillshot originates from, if none player position will be taken

    bool bypass_anti_buffering{}; // allows casting spells while other spells are being casted (allow spell buffering)
    int spell_slot = -1; // will be used to check for CD if expected_hitchance is automatic, if the CD of the spell is low we can spam it more
    float range{}; // max range of the spell
    float radius{}; // circle is the same as linear, use * 0.5f of the TOTAL radius (so only distance from player to one side)
    float cast_range{}; // the cast range of the spell for vector types: viktor E, ruble R..
    float delay{}; // cast delay
    float proc_delay{}; // delay until the spell hits, for example syndra Q is static 0.6
    float projectile_speed = FLT_MAX; // projectile speed if any, FLT_MAX if the spell has no projectiles
    float extension_override{}; // if we want to override the prediction extension

    std::vector< collision_type > forbidden_collisions{}; // things we dont want to skillshot to collide with
    std::vector< hit_type > expected_hit_types{}; // if we want special hit types only, fill them in here
    std::function< bool( game_object* ) > additional_target_selection_checks{}; // custom function for target selection checks, example: target with specific buff(s) only
};

Prediction Data

INFO

This is the data returned by most prediction functions

cpp
struct collision_data
{
    game_object* object{};
    math::vector3 collided_position{};
};

struct collision_ret
{
    bool collided{};
    std::vector< collision_data > collided_units{};
};

class pred_data {
public:
    bool is_valid{}; // if this is true, prediction was successful we are assured that we can use all the members
    game_object* target{}; // the target prediction is aiming at
    int hitchance{}; // use expected_hitchance field inside spell_data if you only want to check > hitchance

    math::vector3 predicted_position{}; // predicted position of the target **use cast_position** if you want to cast a spell
    math::vector3 predicted_dodge_position{}; // predicted dodge position (usually on the side of the target)
    math::vector3 cast_position{}; // position to use when casting the spell (second cast if vector type)
    math::vector3 first_cast_position{}; // for vector types: viktor E, ruble R..
    float intersection_time{}; // time until the skillshot will hit the player

    math::vector3 collision_pos{}; // the point where the spell collided
    std::vector< collision_data > collided_units{}; // the forbidden_collisions that the spell collided with

    pred_data() {};
    pred_data( game_object* target )
    {
        this->target = target;
    }
};
struct collision_data
{
    game_object* object{};
    math::vector3 collided_position{};
};

struct collision_ret
{
    bool collided{};
    std::vector< collision_data > collided_units{};
};

class pred_data {
public:
    bool is_valid{}; // if this is true, prediction was successful we are assured that we can use all the members
    game_object* target{}; // the target prediction is aiming at
    int hitchance{}; // use expected_hitchance field inside spell_data if you only want to check > hitchance

    math::vector3 predicted_position{}; // predicted position of the target **use cast_position** if you want to cast a spell
    math::vector3 predicted_dodge_position{}; // predicted dodge position (usually on the side of the target)
    math::vector3 cast_position{}; // position to use when casting the spell (second cast if vector type)
    math::vector3 first_cast_position{}; // for vector types: viktor E, ruble R..
    float intersection_time{}; // time until the skillshot will hit the player

    math::vector3 collision_pos{}; // the point where the spell collided
    std::vector< collision_data > collided_units{}; // the forbidden_collisions that the spell collided with

    pred_data() {};
    pred_data( game_object* target )
    {
        this->target = target;
    }
};

Predicting

There are multiple functions you can use depending on your need:

Find a target and predict it

pred_sdk::pred_data sdk::prediction->predict( pred_sdk::spell_data spell_data )

Predicts a specific target

pred_sdk::pred_data sdk::prediction->predict( game_object* obj, pred_sdk::spell_data spell_data )

Finds a target and predicts it (for targetted spells only, used to account for wall collisions)

pred_sdk::pred_data sdk::prediction->targetted( pred_sdk::spell_data spell_data )

Getting the collision position

If you want to check if the spell collided during prediction you can do so using this example:

cpp
pred_sdk::spell_data q_data{};

q_data.spell_type = pred_sdk::spell_type::linear;
q_data.targetting_type = pred_sdk::targetting_type::center;
q_data.expected_hitchance = 45; // pred_sdk::hitchance::automatic is possible
q_data.spell_slot = 0;
q_data.range = 1150.f;
q_data.radius = 60.f;
q_data.delay = 0.25f;
q_data.projectile_speed = 2000.f;
q_data.forbidden_collisions =
{
	pred_sdk::collision_type::unit,
	pred_sdk::collision_type::hero,
	pred_sdk::collision_type::yasuo_wall,
	pred_sdk::collision_type::braum_wall,
};

const auto pred = sdk::prediction->predict( q_data );
if( !pred.is_valid && pred.collision_pos != math::vector3{} )
{
    g_sdk->log_console( "Spell collided at %s", pred.collision_pos.to_string().c_str() );
}
pred_sdk::spell_data q_data{};

q_data.spell_type = pred_sdk::spell_type::linear;
q_data.targetting_type = pred_sdk::targetting_type::center;
q_data.expected_hitchance = 45; // pred_sdk::hitchance::automatic is possible
q_data.spell_slot = 0;
q_data.range = 1150.f;
q_data.radius = 60.f;
q_data.delay = 0.25f;
q_data.projectile_speed = 2000.f;
q_data.forbidden_collisions =
{
	pred_sdk::collision_type::unit,
	pred_sdk::collision_type::hero,
	pred_sdk::collision_type::yasuo_wall,
	pred_sdk::collision_type::braum_wall,
};

const auto pred = sdk::prediction->predict( q_data );
if( !pred.is_valid && pred.collision_pos != math::vector3{} )
{
    g_sdk->log_console( "Spell collided at %s", pred.collision_pos.to_string().c_str() );
}

Example using Ezreal Q

cpp
pred_sdk::spell_data q_data{};

q_data.spell_type = pred_sdk::spell_type::linear;
q_data.targetting_type = pred_sdk::targetting_type::center;
q_data.expected_hitchance = 45; // pred_sdk::hitchance::automatic is possible
q_data.spell_slot = 0;
q_data.range = 1150.f;
q_data.radius = 60.f;
q_data.delay = 0.25f;
q_data.projectile_speed = 2000.f;
q_data.forbidden_collisions =
{
	pred_sdk::collision_type::unit,
	pred_sdk::collision_type::hero,
	pred_sdk::collision_type::yasuo_wall,
	pred_sdk::collision_type::braum_wall,
};

const auto pred = sdk::prediction->predict( q_data );
if ( pred.is_valid )
{
    g_sdk->log_console( "Casting spell at %s | hitchance %d", pred.target->get_char_name().c_str(), pred.hitchance );

    util::cast_spell( q_data.spell_slot, pred.cast_position );
}
pred_sdk::spell_data q_data{};

q_data.spell_type = pred_sdk::spell_type::linear;
q_data.targetting_type = pred_sdk::targetting_type::center;
q_data.expected_hitchance = 45; // pred_sdk::hitchance::automatic is possible
q_data.spell_slot = 0;
q_data.range = 1150.f;
q_data.radius = 60.f;
q_data.delay = 0.25f;
q_data.projectile_speed = 2000.f;
q_data.forbidden_collisions =
{
	pred_sdk::collision_type::unit,
	pred_sdk::collision_type::hero,
	pred_sdk::collision_type::yasuo_wall,
	pred_sdk::collision_type::braum_wall,
};

const auto pred = sdk::prediction->predict( q_data );
if ( pred.is_valid )
{
    g_sdk->log_console( "Casting spell at %s | hitchance %d", pred.target->get_char_name().c_str(), pred.hitchance );

    util::cast_spell( q_data.spell_slot, pred.cast_position );
}

Predicting on Path

WARNING

Only use this function if you cannot achieve what you want with the functions above

math::vector3 sdk::prediction->predict_on_path( game_object* obj, float time, bool use_server_pos = true )

INFO

The time argument takes seconds
The use_server_pos argument lets you choose between client predicted position or server position

Collision

To check whether a spell collides with any forbidden_collisions you may use the function

cpp
struct collision_data
{
    game_object* object{};
    math::vector3 collided_position{};
};

struct collision_ret
{
    bool collided{};
    std::vector< collision_data > collided_units{};
};
struct collision_data
{
    game_object* object{};
    math::vector3 collided_position{};
};

struct collision_ret
{
    bool collided{};
    std::vector< collision_data > collided_units{};
};

collision_ret sdk::prediction->collides( const math::vector3& end_point, pred_sdk::spell_data spell_data, const game_object* target )

INFO

This is used internally inside the predicting functions

Prediction Utilities

cpp
float sdk::prediction->util()->get_spell_range( pred_sdk::spell_data& data, game_object* target, game_object* source )
bool sdk::prediction->util()->is_in_range( pred_sdk::spell_data& data, math::vector3 cast_position, game_object* target )
float sdk::prediction->util()->get_spell_hit_time( pred_sdk::spell_data& data, math::vector3 pos, game_object* target = nullptr )
float sdk::prediction->util()->get_spell_escape_time( pred_sdk::spell_data& data, game_object* target )
float sdk::prediction->util()->get_spell_range( pred_sdk::spell_data& data, game_object* target, game_object* source )
bool sdk::prediction->util()->is_in_range( pred_sdk::spell_data& data, math::vector3 cast_position, game_object* target )
float sdk::prediction->util()->get_spell_hit_time( pred_sdk::spell_data& data, math::vector3 pos, game_object* target = nullptr )
float sdk::prediction->util()->get_spell_escape_time( pred_sdk::spell_data& data, game_object* target )
Example
cpp
const auto cursor_pos = g_sdk->hud_manager->get_cursor_position();

g_sdk->log_console( "Time until spells hit cursor position %.2f", sdk::prediction->util()->get_spell_hit_time( q_data, cursor_pos ) );
const auto cursor_pos = g_sdk->hud_manager->get_cursor_position();

g_sdk->log_console( "Time until spells hit cursor position %.2f", sdk::prediction->util()->get_spell_hit_time( q_data, cursor_pos ) );