Гайд Хороший способ получения всех нужных костей(Internal)

Начинающий
Статус
Оффлайн
Регистрация
1 Янв 2020
Сообщения
69
Реакции[?]
4
Поинты[?]
3K
И так, так как у нас отличаются id костей у разных героев, и что бы не описывать для каждого героя нужный id костей, или не писать функцию которая будет для каждой кости проходиться всем ищя именно с нужным именем, воспользуемся игровыми функциями GetBonePos и LookUpBone:
(p.s.сигнатуры взяты с другого форума no ad)
bone func:
Vector3 GetBonePosition(void* entity, int bone) {
    using fnGetBonePosition = void(__thiscall*)(void*, int, Vector3&, Vector3&);
    static auto GetBonePositionFunc = reinterpret_cast<fnGetBonePosition>(PatternScan("client.dll", "48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC ?? 4D 8B F1 49 8B E8 8B F2"));

    Vector3 pos, rot;
    GetBonePositionFunc(entity, bone, pos, rot);
    return pos;
}

int LookupBone(void* entity, const char* bone) {
    using fnLookupBone = int(__thiscall*)(void*, const char*);
    static auto LookupBoneFunc = reinterpret_cast<fnLookupBone>(PatternScan("client.dll", "40 53 48 83 EC ?? 48 8B 89 ?? ?? ?? ?? 48 8B DA 48 8B 01 FF 50 ?? 48 8B C8"));

    return LookupBoneFunc(entity, bone);
}
GetBonePos - возвращает позицию по id.
LookUpBone - возвращает id по имени.

Стоит обратить внимание на то, что обе функции принимают указатель на пешку игрока, но при этом стоит учитывать что в случаях по мимо обычных ентити(самих игроков), мы должны передавать указатель на 'контроллер', тк у них контроллер и пешка условно 'равны' (речь про соул орбы, крипов, босов и т.д.).
Т.е. если для обычного игрока мы получаем контроллер, из него пешку, и дальше работаем с ним.
То для остальных ентити, то как мы получаем контроллер, можно сразу кастовать на пешку:

pseudo:
// для обычного игрока
CPlayerController* Controller = dwEntityList->Get<CPlayerController>(i);
CPlayerPawn* Pawn = dwEntityList->Get<CPlayerPawn>(Controller->GetHandlePawn());

//для остальных ентити
auto trooper = dwEntityList->Get<CPlayerPawn>(i);

Теперь нам достаточно просто пробежаться по всем нужным именам циклом:
Для примера буду просто отрисовывать круги на месте костей:

C++:
for (int i = 0; i < sizeof(bones) / sizeof(bones[0]); i++) {
    int boneIndex = LookupBone(trooper, bones[i]);

    Vector3 bonePos = GetBonePosition(trooper, boneIndex);
    Vector3 screenBone;

    if (world_to_screen(vm.vm, bonePos, bone2d)) {
        drawList->AddCircle(screenBone, 5, IM_COL32(255, 255, 255, 255));
    }
}
Список основных костей(их хватит для есп и аима(для мультипоинтов возможно вам понадобиться больше костей(и их имен) в зависимости от реализации мультипоинтов):
C++:
const char* bones[] = {
    "head",            // Голова
    "neck_0",          // Шея
    "spine_0",         // Верхняя часть спины
    "spine_1",         // Нижняя часть спины
    "clavicle_L",      // Левое плечо
    "arm_upper_L",     // Верхняя часть левой руки
    "hand_L",          // Левая рука
    "pelvis",          // Таз
    "clavicle_R",      // Правое плечо
    "arm_upper_R",     // Верхняя часть правой руки
    "hand_R",          // Правая рука
    "leg_upper_L",     // Левое бедро
    "leg_lower_L",     // Левая голень (колено)
    "ankle_L",         // Левая ступня
    "leg_upper_R",     // Правое бедро
    "leg_lower_R",     // Правая голень (колено)
    "ankle_R", // Правая ступня
    "arm_lower_L", //плечо
    "arm_lower_R" //плечо
};
Результат:
1729871875988.png
Пожалуйста, авторизуйтесь для просмотра ссылки.
 
Сверху Снизу