Grenade Prediction (subliminal)

DREDD

Administrator
Administrator
Administrator
Administrator
Status
Offline
Joined
Apr 18, 2019
Messages
147
Reaction score
249
.cpp:
C++:
void GrenadePrediction::Tick(int buttons)
{
    bool in_attack = buttons & IN_ATTACK, in_attack2 = buttons & IN_ATTACK2;

    if (g_ctx.m_local && g_ctx.m_local->m_iHealth() > 0)
    {
        act = (in_attack && in_attack2) ? ACT_LOB :
            (in_attack2) ? ACT_DROP :
            (in_attack) ? ACT_THROW :
            ACT_NONE;
    }
}

bool IsGrenade(weapon_t* weapon)
{
    auto WeaponIDz = weapon->m_iItemDefinitionIndex();
    if (WeaponIDz == WEAPON_HEGRENADE || WeaponIDz == WEAPON_INCGRENADE ||
        WeaponIDz == WEAPON_MOLOTOV || WeaponIDz == WEAPON_FLASHBANG ||
        WeaponIDz == WEAPON_DECOY || WeaponIDz == WEAPON_SMOKEGRENADE)
        return true;
    return false;
}

void GrenadePrediction::View(CViewSetup* setup)
{

    if (g_ctx.m_local && g_ctx.m_local->m_iHealth() > 0)
    {
        auto weapon = reinterpret_cast<weapon_t*>(g_csgo.m_entitylist()->GetClientEntity(g_ctx.m_local->GetActiveWeaponIndex()));
        if (!weapon) return;
        if (IsGrenade(weapon))
        {
            type = weapon->m_iItemDefinitionIndex();
            Simulate(setup);
        }
        else
            type = 0;
    }
}
inline float CSGO_Armor(float flDamage, int ArmorValue) {
    float flArmorRatio = 0.5f;
    float flArmorBonus = 0.5f;
    if (ArmorValue > 0) {
        float flNew = flDamage * flArmorRatio;
        float flArmor = (flDamage - flNew) * flArmorBonus;

        if (flArmor > static_cast<float>(ArmorValue)) {
            flArmor = static_cast<float>(ArmorValue) * (1.f / flArmorBonus);
            flNew = flDamage - flArmor;
        }

        flDamage = flNew;
    }
    return flDamage;
}
void DrawLine(int x1, int y1, int x2, int y2, Color color)
{
    g_csgo.m_surface()->DrawSetColor(color);
    g_csgo.m_surface()->DrawLine(x1, y1, x2, y2);
}
void DrawFilled3DBox(Vector origin, int width, int height, Color outline, Color filling)
{
    float difw = float(width / 2);
    float difh = float(height / 2);
    Vector boxVectors[8] =
    {
        Vector(origin.x - difw, origin.y - difh, origin.z - difw),
        Vector(origin.x - difw, origin.y - difh, origin.z + difw),
        Vector(origin.x + difw, origin.y - difh, origin.z + difw),
        Vector(origin.x + difw, origin.y - difh, origin.z - difw),
        Vector(origin.x - difw, origin.y + difh, origin.z - difw),
        Vector(origin.x - difw, origin.y + difh, origin.z + difw),
        Vector(origin.x + difw, origin.y + difh, origin.z + difw),
        Vector(origin.x + difw, origin.y + difh, origin.z - difw),
    };

    static Vector vec0, vec1, vec2, vec3,
        vec4, vec5, vec6, vec7;

    if (math::world_to_screen(boxVectors[0], vec0) &&
        math::world_to_screen(boxVectors[1], vec1) &&
        math::world_to_screen(boxVectors[2], vec2) &&
        math::world_to_screen(boxVectors[3], vec3) &&
        math::world_to_screen(boxVectors[4], vec4) &&
        math::world_to_screen(boxVectors[5], vec5) &&
        math::world_to_screen(boxVectors[6], vec6) &&
        math::world_to_screen(boxVectors[7], vec7))
    {
        Vector lines[12][2];
        lines[0][0] = vec0;
        lines[0][1] = vec1;
        lines[1][0] = vec1;
        lines[1][1] = vec2;
        lines[2][0] = vec2;
        lines[2][1] = vec3;
        lines[3][0] = vec3;
        lines[3][1] = vec0;

        // top of box
        lines[4][0] = vec4;
        lines[4][1] = vec5;
        lines[5][0] = vec5;
        lines[5][1] = vec6;
        lines[6][0] = vec6;
        lines[6][1] = vec7;
        lines[7][0] = vec7;
        lines[7][1] = vec4;

        lines[8][0] = vec0;
        lines[8][1] = vec4;

        lines[9][0] = vec1;
        lines[9][1] = vec5;

        lines[10][0] = vec2;
        lines[10][1] = vec6;

        lines[11][0] = vec3;
        lines[11][1] = vec7;

        for (int i = 0; i < 12; i++)
            DrawLine(lines[i][0].x, lines[i][0].y, lines[i][1].x, lines[i][1].y, outline);
    }
}
void DrawF(int X, int Y, unsigned int Font, bool center_width, bool center_height, Color Color, std::string Input)
{
    /* char -> wchar */
    size_t size = Input.size() + 1;
    auto wide_buffer = std::make_unique<wchar_t[]>(size);
    mbstowcs_s(0, wide_buffer.get(), size, Input.c_str(), size - 1);

    /* check center */
    int width = 0, height = 0;
    g_csgo.m_surface()->GetTextSize(Font, wide_buffer.get(), width, height);
    if (!center_width)
        width = 0;
    if (!center_height)
        height = 0;

    /* call and draw*/
    g_csgo.m_surface()->DrawSetTextColor(Color);
    g_csgo.m_surface()->DrawSetTextFont(Font);
    g_csgo.m_surface()->DrawSetTextPos(X - (width * .5), Y - (height * .5));
    g_csgo.m_surface()->DrawPrintText(wide_buffer.get(), wcslen(wide_buffer.get()));
}
Vector2D GetTextSize(unsigned int Font, std::string Input)
{
    /* char -> wchar */
    size_t size = Input.size() + 1;
    auto wide_buffer = std::make_unique<wchar_t[]>(size);
    mbstowcs_s(0, wide_buffer.get(), size, Input.c_str(), size - 1);

    int width, height;
    g_csgo.m_surface()->GetTextSize(Font, wide_buffer.get(), width, height);

    return Vector2D(width, height);
}
void GrenadePrediction::Paint()
{
    if (!g_ctx.m_local) return;
    if (g_ctx.m_local->m_iHealth() > 0)
    {
        if ((type) && path.size() > 1)
        {
            Vector nadeStart, nadeEnd;
            Vector prev = path[0];

            auto weapon = reinterpret_cast<weapon_t*>(g_csgo.m_entitylist()->GetClientEntity(g_ctx.m_local->GetActiveWeaponIndex()));
            if (!weapon) return;
            auto WeaponIDz = weapon->m_iItemDefinitionIndex();

            for (auto it = path.begin(), end = path.end(); it != end; ++it)
            {
                if (math::world_to_screen(prev, nadeStart) && math::world_to_screen(*it, nadeEnd))
                    DrawLine((int)nadeStart.x, (int)nadeStart.y, (int)nadeEnd.x, (int)nadeEnd.y, Color(255, 0, 0));
                prev = *it;
            }
            for (auto it = others.begin(), end = others.end(); it != end; ++it)
                DrawFilled3DBox(it->first, 5, 5, Color(0, 135, 255, 200), Color(0, 135, 255, 200));

            //RENDER::DrawFilled3DBox(others.rbegin()->first, 4, 4, CColor(255, 0, 0, 200), CColor(0, 135, 255, 200));
            if (math::world_to_screen(prev, nadeEnd))
            {
                if (WeaponIDz == WEAPON_FLASHBANG)
                    DrawF((int)nadeEnd.x - 5, (int)nadeEnd.y, fonts[iconslol], true, true, Color(255, 255, 255, 255), "i");
                else if (WeaponIDz == WEAPON_HEGRENADE)
                    DrawF((int)nadeEnd.x - 5, (int)nadeEnd.y, fonts[iconslol], true, true, Color(255, 255, 255, 255), "j");
                else if (WeaponIDz == WEAPON_INCGRENADE)
                    DrawF((int)nadeEnd.x - 5, (int)nadeEnd.y, fonts[iconslol], true, true, Color(255, 255, 255, 255), "n");
                else if (WeaponIDz == WEAPON_MOLOTOV)
                    DrawF((int)nadeEnd.x - 5, (int)nadeEnd.y, fonts[iconslol], true, true, Color(255, 255, 255, 255), "l");
                else if (WeaponIDz == WEAPON_DECOY)
                    DrawF((int)nadeEnd.x - 5, (int)nadeEnd.y, fonts[iconslol], true, true, Color(255, 255, 255, 255), "m");
                else if (WeaponIDz == WEAPON_SMOKEGRENADE)
                    DrawF((int)nadeEnd.x - 5, (int)nadeEnd.y, fonts[iconslol], true, true, Color(255, 255, 255, 255), "k");
            }
        }
    }
}


void GrenadePrediction::Setup(Vector& vecSrc, Vector& vecThrow, Vector viewangles)
{

    if (!g_ctx.m_local) return;
    Vector angThrow = viewangles;
    float pitch = angThrow.x;

    if (pitch <= 90.0f)
    {
        if (pitch < -90.0f)
            pitch += 360.0f;
    }
    else
        pitch -= 360.0f;

    float a = pitch - (90.0f - fabs(pitch)) * 10.0f / 90.0f;
    angThrow.x = a;

    float flVel = 750.0f * 0.9f;
    static const float power[] = { 1.0f, 1.0f, 0.5f, 0.0f };
    float b = power[act];
    b = b * 0.7f; b = b + 0.3f;
    flVel *= b;

    Vector vForward, vRight, vUp;
    math::angle_vectors(angThrow, &vForward, &vRight, &vUp);

    vecSrc = g_ctx.m_local->get_eye_pos();
    float off = (power[act] * 12.0f) - 12.0f;
    vecSrc.z += off;

    trace_t tr;
    Vector vecDest = vecSrc;
    vecDest += vForward * 22.0f;

    TraceHull(vecSrc, vecDest, tr);

    Vector vecBack = vForward; vecBack *= 6.0f;
    vecSrc = tr.endpos;
    vecSrc -= vecBack;

    vecThrow = g_ctx.m_local->m_vecVelocity(); vecThrow *= 1.25f;
    vecThrow += vForward * flVel;
}

void GrenadePrediction::Simulate(CViewSetup* setup)
{
    Vector vecSrc, vecThrow;
    Vector angles; g_csgo.m_engine()->GetViewAngles(angles);
    Setup(vecSrc, vecThrow, angles);

    float interval = g_csgo.m_globals()->m_interval_per_tick;
    int logstep = (int)(0.05f / interval);
    int logtimer = 0;

    path.clear(); others.clear();
    for (unsigned int i = 0; i < path.max_size() - 1; ++i)
    {
        if (!logtimer) path.push_back(vecSrc);

        int s = Step(vecSrc, vecThrow, i, interval);
        if ((s & 1)) break;
        if ((s & 2) || logtimer >= logstep) logtimer = 0;
        else ++logtimer;
    }
    path.push_back(vecSrc);
}

#define PI 3.14159265358979323846f

int GrenadePrediction::Step(Vector& vecSrc, Vector& vecThrow, int tick, float interval)
{
    Vector move; AddGravityMove(move, vecThrow, interval, false);
    trace_t tr; PushEntity(vecSrc, move, tr);

    int result = 0;

    auto weapon = reinterpret_cast<weapon_t*>(g_csgo.m_entitylist()->GetClientEntity(g_ctx.m_local->GetActiveWeaponIndex()));
    if (!weapon) return 0;
    if (!IsGrenade(weapon)) return 0;


    if (CheckDetonate(vecThrow, tr, tick, interval))
        result |= 1;

    if (tr.fraction != 1.0f)
    {
        result |= 2;
        ResolveFlyCollisionCustom(tr, vecThrow, interval);

        QAngle angles;
        math::vector_angles((tr.endpos - tr.startpos).Normalized(), angles);
        others.push_back(std::make_pair(tr.endpos, angles));
    }

    vecSrc = tr.endpos;

    return result;
}
bool GrenadePrediction::CheckDetonate(const Vector& vecThrow, const trace_t& tr, int tick, float interval)
{
    switch (type)
    {
    case WEAPON_SMOKEGRENADE:
    case WEAPON_DECOY:
        if (vecThrow.Length2D() < 0.1f)
        {
            int det_tick_mod = (int)(0.2f / interval);
            return !(tick % det_tick_mod);
        }
        return false;

    case WEAPON_MOLOTOV:
    case WEAPON_INCGRENADE:
        if (tr.fraction != 1.0f && tr.plane.normal.z > 0.7f)
            return true;

    case WEAPON_FLASHBANG:
    case WEAPON_HEGRENADE:
        return (float)tick * interval > 1.5f && !(tick % (int)(0.2f / interval));
    default:
        assert(false);
        return false;
    }
}

void GrenadePrediction::TraceHull(Vector& src, Vector& end, trace_t& tr)
{
    Ray_t ray; CTraceFilterWorldOnly filter;
    ray.Init(src, end, Vector(-2.0f, -2.0f, -2.0f), Vector(2.0f, 2.0f, 2.0f));
    g_csgo.m_trace()->TraceRay(ray, 0x200400B, &filter, &tr);
}

void GrenadePrediction::AddGravityMove(Vector& move, Vector& vel, float frametime, bool onground)
{
    Vector basevel(0.0f, 0.0f, 0.0f);
    move.x = (vel.x + basevel.x) * frametime;
    move.y = (vel.y + basevel.y) * frametime;

    if (onground)
        move.z = (vel.z + basevel.z) * frametime;
    else
    {
        float gravity = 800.0f * 0.4f;
        float newZ = vel.z - (gravity * frametime);
        move.z = ((vel.z + newZ) / 2.0f + basevel.z) * frametime;
        vel.z = newZ;
    }
}

void GrenadePrediction::PushEntity(Vector& src, const Vector& move, trace_t& tr)
{
    Vector vecAbsEnd = src;
    vecAbsEnd += move;
    TraceHull(src, vecAbsEnd, tr);
}

void GrenadePrediction::ResolveFlyCollisionCustom(trace_t& tr, Vector& vecVelocity, float interval)
{
    float flSurfaceElasticity = 1.0, flGrenadeElasticity = 0.45f;
    float flTotalElasticity = flGrenadeElasticity * flSurfaceElasticity;
    if (flTotalElasticity > 0.9f) flTotalElasticity = 0.9f;
    if (flTotalElasticity < 0.0f) flTotalElasticity = 0.0f;

    Vector vecAbsVelocity;
    PhysicsClipVelocity(vecVelocity, tr.plane.normal, vecAbsVelocity, 2.0f);
    vecAbsVelocity *= flTotalElasticity;

    float flSpeedSqr = vecAbsVelocity.LengthSqr();
    static const float flMinSpeedSqr = 20.0f * 20.0f;

    if (flSpeedSqr < flMinSpeedSqr)
    {
        vecAbsVelocity.x = 0.0f;
        vecAbsVelocity.y = 0.0f;
        vecAbsVelocity.z = 0.0f;
    }

    if (tr.plane.normal.z > 0.7f)
    {
        vecVelocity = vecAbsVelocity;
        vecAbsVelocity *= ((1.0f - tr.fraction) * interval);
        PushEntity(tr.endpos, vecAbsVelocity, tr);
    }
    else
        vecVelocity = vecAbsVelocity;
}

int GrenadePrediction::PhysicsClipVelocity(const Vector& in, const Vector& normal, Vector& out, float overbounce)
{
    static const float STOP_EPSILON = 0.1f;

    float backoff, change, angle;
    int   i, blocked;

    blocked = 0;
    angle = normal[2];

    if (angle > 0) blocked |= 1;
    if (!angle) blocked |= 2;

    backoff = in.Dot(normal) * overbounce;
    for (i = 0; i < 3; i++)
    {
        change = normal[i] * backoff;
        out[i] = in[i] - change;
        if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
            out[i] = 0;
    }
    return blocked;
}
.h:
C++:
#pragma once


#include <deque>




enum ACT
{
    ACT_NONE,
    ACT_THROW,
    ACT_LOB,
    ACT_DROP,
};


class GrenadePrediction : public singleton<GrenadePrediction>
{
private:
    std::vector<Vector> path;
    std::vector<std::pair<Vector, QAngle>> others;
    //std::vector<Vector> others;
    int type = 0;
    int act = 0;

    void Setup(Vector& vecSrc, Vector& vecThrow, Vector viewangles);
    void Simulate(CViewSetup* setup);

    int Step(Vector& vecSrc, Vector& vecThrow, int tick, float interval);
    bool CheckDetonate(const Vector& vecThrow, const trace_t& tr, int tick, float interval);

    void TraceHull(Vector& src, Vector& end, trace_t& tr);
    void AddGravityMove(Vector& move, Vector& vel, float frametime, bool onground);
    void PushEntity(Vector& src, const Vector& move, trace_t& tr);
    void ResolveFlyCollisionCustom(trace_t& tr, Vector& vecVelocity, float interval);
    int PhysicsClipVelocity(const Vector& in, const Vector& normal, Vector& out, float overbounce);
public:
    void Tick(int buttons);
    void View(CViewSetup* setup);
    void Paint();
};
 
Top