C++ Исходник Walkbot Class

кошмарим форум
Забаненный
Статус
Оффлайн
Регистрация
22 Май 2021
Сообщения
84
Реакции[?]
11
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
C++:
#pragma once
// used: winapi includes, singleton
#include "../common.h"
// used: usercmd
#include "../sdk/datatypes/usercmd.h"
// used: baseentity, baseweapon
#include "../sdk/entity.h"
// used: timer
#include "../utilities.h"
#include "../sdk/nav/nav_area.h"
#include "../utilities/micropather.h"
#include "../sdk/nav/nav_file.h"
#include "../utilities/micropather.h" // edit: im a retard
 
struct tEnemyBlacklist {
    tEnemyBlacklist(CBaseEntity* pEnt) {
        m_pEntity = pEnt;
        m_tTimeSinceLast.Reset();
    };
 
    bool ShouldRemove() {
        return m_tTimeSinceLast.Elapsed() > 5000;
    }
 
    CBaseEntity* m_pEntity;
    CTimer m_tTimeSinceLast{};
};
 
class CWalkBot : public CSingleton<CWalkBot>
{
public:
    void Run(CUserCmd* pCmd, CBaseEntity* pLocal);
    void Reset(bool bReloadNav = false);
    inline float GetAvgViewDelta() {
        return m_flDeltaAvg;
    };
 
private:
    float m_flDeltaAvg;
    CTimer m_tDoorOpenTimer{};
    CTimer m_tSinceLastArea{};
    CTimer m_tCrouchTimer{};
    CTimer m_tBackUpTimer{};
    CTimer m_tJumpTimer{};
    std::string m_szCurrentMapName{};
    nav_mesh::nav_file* m_pNavFile = nullptr;
    nav_mesh::nav_area* m_pCurrentTarget{};
    std::vector<nav_mesh::nav_area*> m_vAreasPath{};
    std::deque<float> m_vDeltaAnglesHist{ 30, 999.0f };
    std::deque<tEnemyBlacklist> m_vEnemyBlacklists{};
 
    void UpdateEnemyBlacklist();
    bool IsEnemyBlacklisted(CBaseEntity* pEnt);
    void CalculateDeltaAvg();
    void DrawAreas(CBaseEntity* pLocal);
    bool LevelCheck();
    void DoObstacleAction(CBaseEntity* pLocal, CUserCmd* pCmd);
    void OptimizePath(Vector vPlayerPos);
    void CalculateFootMovement(Vector vPlayerPos, Vector vPointPos, CUserCmd* pCmd);
    bool DoesNeedNewPath(CBaseEntity* pLocal);
    nav_mesh::nav_area* GetAreaNearEnemies(CBaseEntity* pLocal);
    nav_mesh::nav_area* GetAreaNearPlayer(CBaseEntity* pLocal);
};



C++:
#include "walkbot.h"
 
#include "../core/variables.h"
#include "../sdk/definitions.h"
#include "../utilities/math.h"
#include "../utilities/logging.h"
#include "../core/interfaces.h"
#include "../global.h"
 
#include <regex>
#include <thread>
 
void CWalkBot::Run(CUserCmd* pCmd, CBaseEntity* pLocal)
{
    if (!LevelCheck())
        return;
 
    if (DoesNeedNewPath(pLocal)) {
        Reset();
 
        if (!pLocal->IsAlive())
            return;
 
        m_pCurrentTarget = GetAreaNearEnemies(pLocal);
        nav_mesh::nav_area* pAreaClosestToPlayer = GetAreaNearPlayer(pLocal);
 
        L::Print(fmt::format("Trying to find path to #{} at {}.", m_pCurrentTarget->get_id(), std::string(m_pNavFile->GetNameOfPlace(m_pCurrentTarget->get_place()))));
        bool bWasPathSuccessful = true;
 
        try
        {
            m_vAreasPath = m_pNavFile->find_path(pAreaClosestToPlayer->get_id(), m_pCurrentTarget->get_id());
        }
        catch (const std::exception&)
        {
            bWasPathSuccessful = false;
        }
 
        if(bWasPathSuccessful)
            L::Print(fmt::format("Path to #{} at {} found.", m_pCurrentTarget->get_id(), std::string(m_pNavFile->GetNameOfPlace(m_pCurrentTarget->get_place()))));
 
        return;
    }
    else {
        UpdateEnemyBlacklist();
        CalculateDeltaAvg();
 
        if (C::Get<bool>(Vars.bWalkbotVisualize))
            DrawAreas(pLocal);
 
        if (m_tCrouchTimer.Elapsed() < 250)
            pCmd->iButtons |= IN_DUCK;
 
        if (m_tJumpTimer.Elapsed() < 250)
            pCmd->iButtons |= IN_JUMP;
 
        const Vector vOurPos = pLocal->GetOrigin();
        const Vector vOurPosNoHeight = { pLocal->GetOrigin().x, pLocal->GetOrigin().y, 0.0f };
 
        if (C::Get<bool>(Vars.bWalkbotAutoOptimize))
            OptimizePath(vOurPos);
 
        const Vector vNextPos = m_vAreasPath.back()->get_center();
        const Vector vNextPosNoHeight = { m_vAreasPath.back()->get_center().x, m_vAreasPath.back()->get_center().y, 0.0f };
 
        static const Vector vEyesHeight = pLocal->GetEyePosition() - vOurPos;
 
        QAngle vCalculatedAngles = M::CalcAngle(pLocal->GetEyePosition(), vNextPos + vEyesHeight);
        QAngle vDeltaAngles = vCalculatedAngles - pCmd->angViewPoint;
 
        vDeltaAngles.Normalize();
 
        m_vDeltaAnglesHist.pop_back();
        m_vDeltaAnglesHist.push_front(fabsf(vDeltaAngles.x + vDeltaAngles.y));
 
        if (C::Get<bool>(Vars.bWalkbotLookAtPoint)) {
            if (C::Get<bool>(Vars.bWalkbotHumanize))
                vDeltaAngles /= 25.0f;
 
            pCmd->angViewPoint += vDeltaAngles;
            I::Engine->SetViewAngles(pCmd->angViewPoint);
        }
 
        CalculateFootMovement(vOurPos, vNextPos, pCmd);
        DoObstacleAction(pLocal, pCmd);
 
        if (m_tBackUpTimer.Elapsed() < 250)
            pCmd->flForwardMove = -420.0f;
 
        const float flDistToNext = (vOurPos.z - 64.0f < vNextPos.z) ? vOurPosNoHeight.DistTo(vNextPosNoHeight) : vOurPos.DistTo(vNextPos);
        if (flDistToNext < 32.0f) {
            m_tSinceLastArea.Reset();
            m_vAreasPath.pop_back();
        }
    }
}
 
void CWalkBot::Reset(bool bReloadNav) {
    m_pCurrentTarget = nullptr;
    m_vEnemyBlacklists.clear();
    m_tDoorOpenTimer.Reset();
    m_tSinceLastArea.Reset();
    m_vAreasPath.clear();
    if(bReloadNav)
        m_szCurrentMapName.clear();
}
 
bool CWalkBot::IsEnemyBlacklisted(CBaseEntity* pEnt) {
    for (const auto& blEnemy : m_vEnemyBlacklists) {
        if (pEnt == blEnemy.m_pEntity)
            return true;
    }
    return false;
}
 
void CWalkBot::UpdateEnemyBlacklist() {
    m_vEnemyBlacklists.erase(
        std::remove_if(m_vEnemyBlacklists.begin(), m_vEnemyBlacklists.end(),
            [](const tEnemyBlacklist& blEnemy) {
                return !blEnemy.m_pEntity->IsAlive() || blEnemy.m_tTimeSinceLast.Elapsed() > 500;
            }),
        m_vEnemyBlacklists.end()
    );
}
 
void CWalkBot::CalculateDeltaAvg() {
    float flTotalVal = 0.0f;
    for (float flVal : m_vDeltaAnglesHist) {
        flTotalVal += flVal;
    }
 
    m_flDeltaAvg = flTotalVal / 30.0f;
}
 
void CWalkBot::DrawAreas(CBaseEntity* pLocal) {
    I::DebugOverlay->ClearAllOverlays();
 
    Vector vLastPoint = pLocal->GetOrigin();
    for (int i = m_vAreasPath.size() - 1; i >= 0; i--) {
        if (i == m_vAreasPath.size() - 1) {
            I::DebugOverlay->AddBoxOverlay(m_vAreasPath[i]->get_center(), Vector(-4.0f, -4.0f, 0.0f), Vector(4.0f, 4.0f, 48.0f), QAngle(), 0, 255, 0, 32, 0.16f);
            I::DebugOverlay->AddLineOverlay(vLastPoint + Vector(0.f, 0.f, 12.f), m_vAreasPath[i]->get_center() + Vector(0.f, 0.f, 12.f), 0, 255, 0, 255, 0.25f, 0.16f);
        }
        else {
            I::DebugOverlay->AddBoxOverlay(m_vAreasPath[i]->get_center(), Vector(-4.0f, -4.0f, 0.0f), Vector(4.0f, 4.0f, 48.0f), QAngle(), 255, 0, 0, 32, 0.16f);
            I::DebugOverlay->AddLineOverlay(vLastPoint + Vector(0.f, 0.f, 12.f), m_vAreasPath[i]->get_center() + Vector(0.f, 0.f, 12.f), 255, 0, 0, 255, 0.25f, 0.16f);
        }
 
        vLastPoint = m_vAreasPath[i]->get_center();
    }
}
 
#define PLAYER_BODY_RADIUS 8.0f // normally 16.0f
 
bool CWalkBot::LevelCheck() {
    std::string szMapName{ I::Engine->GetLevelName() };
    if (szMapName != m_szCurrentMapName) {
        m_szCurrentMapName = szMapName;
 
        std::string szFileName = m_szCurrentMapName.substr(0, m_szCurrentMapName.length() - 3).append("nav");
 
        static char szPathTemp[MAX_PATH];
        static int iUnused = GetModuleFileNameA(GetModuleHandle("client.dll"), szPathTemp, MAX_PATH);
 
        std::string szNavPath{ std::string(szPathTemp).substr(0, std::string(szPathTemp).length() - 14).append(szFileName).c_str() };
 
        if (std::filesystem::exists(szNavPath)) {
            if (m_pNavFile)
                delete m_pNavFile;
 
            L::Print(fmt::format(XorStr("Loaded .nav file for map \"{}\" from \"{}\"."), std::string(I::Engine->GetLevelNameShort()), szNavPath));
 
            m_pNavFile = new nav_mesh::nav_file{ szNavPath };
            return true;
        }
        else {
            L::Print(fmt::format(XorStr("Could not find .nav file for map \"{}\". Trying to save from .bsp file."), std::string(I::Engine->GetLevelNameShort())));
            I::Engine->ExecuteClientCmd("nav_save");
 
            // This is bad :p
            int iRetryAttempts = 0;
            while (!std::filesystem::exists(szNavPath) && iRetryAttempts < 5) {
                iRetryAttempts++;
                std::this_thread::sleep_for(std::chrono::milliseconds(200));
            }
 
            if (std::filesystem::exists(szNavPath)) {
                if (m_pNavFile)
                    delete m_pNavFile;
 
                m_pNavFile = new nav_mesh::nav_file();
                m_pNavFile->load(szNavPath);
                return true;
            }
            else {
                L::Print(fmt::format(XorStr("Unable to save .nav file for map \"{}\". These files cannot be generated while on official Valve servers."), std::string(I::Engine->GetLevelNameShort())));
                C::Get<bool>(Vars.bWalkbot) = false;
                Reset(true);
                return false;
            }
        }
    }
    return true;
}
 
#define MAKE_TRACE(varname, vecStart, anglesin, mask) Trace_t varname{}; \
{\
    Vector vecEnd, vecForward;\
    M::AngleVectors(anglesin, &vecForward);\
    vecEnd = vecStart + vecForward * PLAYER_BODY_RADIUS + vecForward * 32.f;\
    Ray_t ray(vecStart, vecEnd);\
    CTraceFilter filter(pLocal);\
    I::EngineTrace->TraceRay(ray, mask, &filter, &varname);\
    I::DebugOverlay->AddLineOverlayAlpha(vecStart, vecEnd, 255, 255, 255, 255, true, 1.0f);\
}
 
void CWalkBot::DoObstacleAction(CBaseEntity* pLocal, CUserCmd* pCmd) {
    // All the rays for testing here
    MAKE_TRACE(step_front, pLocal->GetOrigin() + Vector(0.0f, 0.0f, 15.0f), QAngle(0.0f, pCmd->angViewPoint.y, 0.0f), MASK_PLAYERSOLID);
    MAKE_TRACE(crouchjump_front, pLocal->GetOrigin() + Vector(0.0f, 0.0f, 54.0f), QAngle(0.0f, pCmd->angViewPoint.y, 0.0f), MASK_PLAYERSOLID);
    MAKE_TRACE(object_left, pLocal->GetOrigin() + Vector(0.0f, 0.0f, 32.0f), QAngle(0.0f, pCmd->angViewPoint.y - 45.0f, 0.0f).Normalize(), MASK_PLAYERSOLID);
    MAKE_TRACE(object_right, pLocal->GetOrigin() + Vector(0.0f, 0.0f, 32.0f), QAngle(0.0f, pCmd->angViewPoint.y + 45.0f, 0.0f).Normalize(), MASK_PLAYERSOLID);
    MAKE_TRACE(windowtest_front, pLocal->GetOrigin() + Vector(0.0f, 0.0f, pLocal->GetEyePosition().z - pLocal->GetOrigin().z), QAngle(0.0f, pCmd->angViewPoint.y, 0.0f), CONTENTS_WINDOW);
    MAKE_TRACE(standing_front, pLocal->GetOrigin() + Vector(0.0f, 0.0f, 72.0f), QAngle(0.0f, pCmd->angViewPoint.y, 0.0f), MASK_PLAYERSOLID);
 
    // Auto Jump detection
    {
        if (!(standing_front.DidHit() || standing_front.pHitEntity != nullptr)) {
            if (step_front.DidHit() || step_front.pHitEntity != nullptr) {
                if (m_tJumpTimer.Elapsed() > 250) {
                    if (crouchjump_front.DidHit() || crouchjump_front.pHitEntity != nullptr) {
                        if (m_tCrouchTimer.Elapsed() > 250) {
                            m_tCrouchTimer.Reset();
                        }
                    }
                    m_tJumpTimer.Reset();
                }
            }
        }
    }
 
    // back the fuck up detection
    {
        if (standing_front.DidHit() || standing_front.pHitEntity != nullptr) {
            if (step_front.DidHit() || step_front.pHitEntity != nullptr) {
                if (m_tBackUpTimer.Elapsed() > 250) {
                    m_tBackUpTimer.Reset();
                }
            }
        }
    }
 
    // Glass break detection
    {
        if (windowtest_front.DidHit()) {
            pCmd->iButtons |= IN_ATTACK;
        }
    }
 
    // Hip Airbags :D
    {
        bool bDidHitLeft = object_left.DidHit() || object_left.pHitEntity != nullptr;
        bool bDidHitRight = object_right.DidHit() || object_right.pHitEntity != nullptr;
        if (bDidHitLeft && !bDidHitRight) {
            pCmd->flSideMove = -420.0f;
        }
        else if(bDidHitRight && !bDidHitLeft) {
            pCmd->flSideMove = 420.0f;
        }
    }
 
    // Door open detection
    {
        if (standing_front.pHitEntity != nullptr) {
            const std::string szEntName{ standing_front.pHitEntity->GetClientClass()->szNetworkName };
            if (szEntName == "CPropDoorRotating" &&    m_tDoorOpenTimer.Elapsed() > 500) {
                m_tDoorOpenTimer.Reset();
                pCmd->iButtons |= IN_USE;
            }
        }
    }
 
    // crouch detection
    {
        if (standing_front.pHitEntity != nullptr || standing_front.DidHit()) {
            if (!(step_front.pHitEntity != nullptr || standing_front.DidHit())) {
                const std::string szEntName{ standing_front.pHitEntity->GetClientClass()->szNetworkName };
                if (szEntName != "CPropDoorRotating") {
                    pCmd->iButtons |= IN_DUCK;
                }
            }
        }
    }
}
 
void CWalkBot::OptimizePath(Vector vPlayerPos) {
    if (m_vAreasPath.size() > 1) {
        const float flDistToFirst = vPlayerPos.DistTo(m_vAreasPath.back()->get_center());
        const float flDistToSecond = vPlayerPos.DistTo(m_vAreasPath[m_vAreasPath.size() - 2]->get_center());
 
        if (flDistToFirst > flDistToSecond) {
            m_vAreasPath.pop_back();
            m_tSinceLastArea.Reset();
        }
    }
}
 
void CWalkBot::CalculateFootMovement(Vector vPlayerPos, Vector vPointPos, CUserCmd* pCmd) {
    Vector vDelta = vPointPos - vPlayerPos;
 
    if (vDelta.Length() == 0.0f) {
        pCmd->flForwardMove = 0.0f;
        pCmd->flSideMove = 0.0f;
        return;
    }
 
    float speed = sqrt(vDelta.x * vDelta.x + vDelta.y * vDelta.y);
    QAngle vAngles;
    M::VectorAngles(vDelta, vAngles);
    float flYaw = M_DEG2RAD(vAngles.y - pCmd->angViewPoint.y);
    pCmd->flForwardMove = cos(flYaw) * 450.0f;
    pCmd->flSideMove = -sin(flYaw) * 450.0f;
    return;
}
 
bool CWalkBot::DoesNeedNewPath(CBaseEntity* pLocal) {
    if (m_vAreasPath.size() == 0) {
        return true;
    }
 
    Vector flNextAreaCenter = m_vAreasPath.back()->get_center();
    if (flNextAreaCenter.z > pLocal->GetEyePosition().z + 24.0f) {
        return true;
    }
 
    if (flNextAreaCenter.DistTo(pLocal->GetOrigin()) > 1024.0f) {
        return true;
    }
 
    if (!pLocal->IsAlive()) {
        return true;
    }
 
    if (m_tSinceLastArea.Elapsed() > 7000) {
        return true;
    }
 
    return false;
}
 
nav_mesh::nav_area* CWalkBot::GetAreaNearEnemies(CBaseEntity* pLocal) {
    nav_mesh::nav_area* pCurrentTarget = nullptr;
 
    CBaseEntity* pFurthestPlayer = nullptr;
    float flBestDistance = 0.0f;
    for (int i = 1; i < I::Globals->nMaxClients; i++)
    {
        CBaseEntity* entity = reinterpret_cast<CBaseEntity*>(I::ClientEntityList->GetClientEntity(i));
        if (!entity
            || entity == G::pLocal
            || entity->IsDormant()
            || entity->GetLifeState() != LIFE_ALIVE
            || entity->GetClientClass()->nClassID != EClassIndex::CCSPlayer
            || entity->GetTeam() == G::pLocal->GetTeam()
            || IsEnemyBlacklisted(entity))
            continue;
 
        if (entity->GetAbsOrigin().DistTo(G::pLocal->GetAbsOrigin()) > flBestDistance) {
            flBestDistance = entity->GetAbsOrigin().DistTo(G::pLocal->GetAbsOrigin());
            pFurthestPlayer = entity;
        }
    }
 
    if (pFurthestPlayer) {
        nav_mesh::nav_area* pNavArea = m_pNavFile->GetNearestArea(pFurthestPlayer->GetOrigin());
        if (pNavArea) {
            pCurrentTarget = pNavArea;
            m_vEnemyBlacklists.push_back(tEnemyBlacklist(pFurthestPlayer));
        }
    }
 
    if (!pCurrentTarget) {
        int iRandomIdx = M::RandomInt(0, m_pNavFile->m_areas.size() - 1);
        pCurrentTarget = &(m_pNavFile->m_areas[iRandomIdx]);
    }
 
 
    return pCurrentTarget;
}
 
nav_mesh::nav_area* CWalkBot::GetAreaNearPlayer(CBaseEntity* pLocal) {
    const Vector vPlayerOrigin = pLocal->GetOrigin();
    nav_mesh::nav_area* pNearestArea = nullptr;
    float flBestDistance = FLT_MAX;
 
    for (size_t i = 0; i < m_pNavFile->m_areas.size(); i++) {
        const Vector vCenter = m_pNavFile->m_areas[i].get_center();
        const float flDistance = vCenter.DistTo(vPlayerOrigin);
        if (flDistance < flBestDistance) {
            flBestDistance = flDistance;
            pNearestArea = &(m_pNavFile->m_areas[i]);
        }
    }
 
    return pNearestArea;
}
 
Похожие темы
Сверху Снизу