Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Гайд Far Cry Series — Реверс Havok Engine: Энтити, ESP и сигнатуры

Обратите внимание, что на пользователя недавно была жалоба: Жалоба от lovehvhneverlose на hex_cat. Будьте осторожны!
Sloppy
Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
458
Реакции
10
Народ, кто плотно ковыряет серию Far Cry (начиная с тройки и выше), в курсе, что там под капотом вовсю юзается Havok Engine. Если вам нужно вытащить энтити для ESP или реализовать телепорт, проще всего это сделать через RTTI самого Havok и его структурированный лайаут.

Основная фишка в том, что энтити в Havok имеют четкую иерархию. Нам интересен hkpWorld, который хранит массив активных hkpSimulationIsland. В этих «островах» и лежат реальные объекты: игроки, NPC, животные.

Техническое мясо по структурам:

  1. Все полезные для нас объекты (игроки, боты) имеют hkpCapsuleShape по офсету 0x10. Это идеальный фильтр, чтобы отсеять всякий статический мусор типа деревьев.
  2. У энтити есть поинтер на объект перемещения по офсету 0x18. Сами координаты (Vector3) лежат внутри этого объекта по офсету 0x30.
  3. По офсету 0xE0 часто висит вектор позиции, доступный для записи (удобно для телепорта).

Код:
Expand Collapse Copy
namespace HAVOK
{
    class hkpEntity
    {
    public:
        Vector3 GetPosition()
        {
            auto pos_class = *(uintptr_t*)((uintptr_t)this + 0x18);
            if (!pos_class) return { 0, 0, 0 };
            return *(Vector3*)(pos_class + 0x30);
        }

        bool HasCapsuleShape()
        {
            static void* hkpCapsuleShapeVFT = reinterpret_cast<void*>(OFFSETS::GameBase + OFFSETS::hkpCapsuleVFT);
            auto shape = *(uintptr_t**)((uintptr_t)this + 0x10);
            return (shape && *shape == hkpCapsuleShapeVFT);
        }
    };

    class hkpWorld
    {
    public:
        char pad_10[0x10];
        Vector3 gravity;
        char pad_1c[0x4];
        uintptr_t* fixedSimulationIsland;
        uintptr_t* fixedRigidBody;
        Array<class hkpSimulationIsland*> activeSimulationIslands;

        static hkpWorld* GetWorld()
        {
            static uintptr_t StartingAddr = (uintptr_t)(OFFSETS::GameBase + 0x01EE9114); 
            return (hkpWorld*)(ResolvePTR(StartingAddr, { 0x3C, 0x11C, 0x48, 0x18, 0xC8, 0x4, 0x0 }));
        }
    };
}

Логика обновления энтити-листа:
Проходимся по всем островам симуляции, чекаем наличие капсулы и закидываем в свой массив. Это гораздо стабильнее, чем пытаться парсить игровые массивы через Pawn, если вы только начали реверсить бинарник.

Код:
Expand Collapse Copy
void UpdateHavokEntities()
{
    HavokEntities.clear();
    auto world = HAVOK::hkpWorld::GetWorld();
    if (!world) return;

    for (int i = 0; i < world->activeSimulationIslands.Num(); i++)
    {
        auto island = world->activeSimulationIslands[i];
        if (!island) continue;

        for (int j = 0; j < island->Entities.Num(); j++)
        {
            auto entity = island->Entities[j];
            if (!entity || !entity->HasCapsuleShape()) continue;
            HavokEntities.push_back(entity);
        }
    }
}

Полезные сигнатуры (актуально для FC3, на других частях нужно подправлять):

  • Локальный игрок в Havok (ESI после брейкпоинта на позиции):
    Код:
    Expand Collapse Copy
    0F 29 86 ? ? ? ? 8B 40 ? D9 40 ? 8B 11 DC 0D
  • GetAllPawns (для получения игровых объектов):
    Код:
    Expand Collapse Copy
    B8 ? ? ? ? C3 55 8B EC 8B 41 ? 8B 88 ? ? ? ? 8B 45

Если хотите копнуть глубже в сторону оригинальных игровых классов, ищите функции LUA в IDA. Там полно инфы по Pawn-ам. И не забывайте про старые PDB от Xbox версии — структуры там практически идентичные PC билдам.

Кто уже пробовал этот метод в FC6, насколько сильно там перепахали hkpWorld?
 
Назад
Сверху Снизу