Гайд API SF | Урок 6 - ESP(рисуем на игроках)

Тема в разделе "C/C++", создана пользователем CleanLegend, 16 окт 2018.

  1. CleanLegend

    Всефорумный модератор

    Регистрация:
    28 мар 2013
    Сообщения:
    251
    Симпатии:
    287
    Введение
    В этом уроке покажу как можно рисовать на игроках

    Начало работы
    Для начала нужно зарегистрировать callback present, в нем мы будем рисовать.

    bool CALLBACK Present ( CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride,
                                     CONST RGNDATA *pDirtyRegion )
    {
       if( SUCCEEDED( SF->getRender()->BeginRender() ) ) // если рендер готов к рисованию
       {
           // рисуем
           SF->getRender()->EndRender(); // завершаем рисование
       };
    
       return true; // возвращаем положительный результат
    };
    в mainloop:
    SF->getRender()->registerD3DCallback(eDirect3DDeviceMethods::D3DMETHOD_PRESENT, Present);
    Создаем функцию для удобства и в ней начинаем с цикла:
    void ESP()
    {
    for (int i = 0; i < SAMP_MAX_PLAYERS; i++) // перебираем всех игроков и проверяем их на вилидность
    {
    if (SF->getSAMP()->getPlayers()->iIsListed[i] != 1) continue;
    if (SF->getSAMP()->getPlayers()->pRemotePlayer[i] == NULL) continue;
    if (SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData == NULL) continue;
    if (SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->pSAMP_Actor == NULL) continue;
    if (SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->pSAMP_Actor->pGTA_Ped == NULL) continue;
            // Если игрок не существует или не в зоне стрима, то пропускаем
    }
    }
    Можно сделать проверку на зону стрима вызовом одной функции:
    if (SF->getSAMP()->getPlayers()->IsPlayerDefined(i, true))
    {
    // Игрок в стриме
    }
    Теперь нужно получить координаты игрока, перевести их в экранные и проверить есть ли игрок на экране:

    // Получаем координаты игрока
    enpos[0] = SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->fOnFootPos[0]; // X
    enpos[1] = SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->fOnFootPos[1]; // Y
    enpos[2] = SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->fOnFootPos[2]; // Z
    // Переводим игровые координаты в экранные
    SF->getGame()->convert3DCoordsToScreen(enpos[0], enpos[1], enpos[2], &screen[0], &screen[1]);
    // Получаем CPed
    CPed* Ped = GAME->GetPools()->GetPed((DWORD*)SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->pSAMP_Actor->pGTA_Ped);
     // Проверяем есть ли игрок на экране
    if (Ped->IsOnScreen())
    {
                // игрок на экране
    }
    Перейдем к рисованию, сначала с квадрата.
    Для этого нужно вызвать функцию для рисования квадрата и указать экранные координаты:
    SF->getRender()->DrawBox(screen[0], screen[1], 35, 35, 0xFF00FF00);
    получаем:
    [​IMG]
    Рисуем линии:
    SF->getRender()->DrawLine(640, 900, screen[0], screen[1], 5,0xFF00FF00);
    получаем:
    [​IMG]
    Рисуем текст:
    char buf[255];
    // Заполняем буфер ником и id
    sprintf_s(buf, "%s[%d]", SF->getSAMP()->getPlayers()->GetPlayerName(i),i);
     // Рисуем текст
     pFont->Print(buf, 0xFF00FF00, screen[0], screen[1], false);
    для использования pFont нужно объявить и инициализировать его:
    stFontInfo *pFont;
    //Затем один раз инициализируем шрифт:
    pFont = SF->getRender()->CreateNewFont("Tahoma", 12, FCR_BORDER );
    получаем:
    [​IMG]
    По такому принципу можно рисовать всё что угодно.
    весь код функции:
    void ESP()
    {
        float enpos[3]; // для координат игрока
        float screen[2]; // для экранных координат
        char buf[255]; // для текста
        for (int i = 0; i < SAMP_MAX_PLAYERS; i++) // перебор всех игроков
        {
            // проверяем каждого игрока на валидность, зону стрима
            if (SF->getSAMP()->getPlayers()->iIsListed[i] != 1) continue;
            if (SF->getSAMP()->getPlayers()->pRemotePlayer[i] == NULL) continue;
            if (SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData == NULL) continue;
            if (SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->pSAMP_Actor == NULL) continue;
            if (SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->pSAMP_Actor->pGTA_Ped == NULL) continue;
            // Если игрок не существует или не в зоне стрима, то пропускаем
    
            // Можно сделать это одной функцией
            /*if (SF->getSAMP()->getPlayers()->IsPlayerDefined(i, true))
            {
             // рисуем
            }*/
            // Тут подойдут два варианта, это уже как вам будет удобнее
           
            // Получаем координаты игрока
            enpos[0] = SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->fOnFootPos[0]; // X
            enpos[1] = SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->fOnFootPos[1]; // Y
            enpos[2] = SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->fOnFootPos[2]; // Z
            // Переводим игровые координаты в экранные
            SF->getGame()->convert3DCoordsToScreen(enpos[0], enpos[1], enpos[2], &screen[0], &screen[1]);
            // Получаем CPed
            CPed* Ped = GAME->GetPools()->GetPed((DWORD*)SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->pSAMP_Actor->pGTA_Ped);
            // Проверяем есть ли игрок на экране
            if (Ped->IsOnScreen())
            {
                // начинаем рисовать
    
                // Рисуем квадрат на игроках
                //    SF->getRender()->DrawBox(screen[0], screen[1], 35, 35, 0xFF00FF00);
                // Рисуем линии
                //SF->getRender()->DrawLine(640, 900, screen[0], screen[1], 5,0xFF00FF00);
               
                // Заполняем буфер ником и id
                sprintf_s(buf, "%s[%d]", SF->getSAMP()->getPlayers()->GetPlayerName(i),i);
                // Рисуем текст
                pFont->Print(buf, 0xFF00FF00, screen[0], screen[1], false);
    
            }
    
        }
    }
     
    Rjx13, #kerosin, butchers и 3 другим нравится это.
  2. butchers

    butchers Активный участник

    Регистрация:
    27 авг 2017
    Сообщения:
    26
    Симпатии:
    12
    Дополни как рендер ника сделать чтобы он был равен цвету самого ника. Думаю у людей будет такой вопрос
     
  3. Carloson

    Carloson Местный житель

    Регистрация:
    27 июн 2017
    Сообщения:
    758
    Симпатии:
    112
    А нельзя это сделать с "if and" как в клео ?
    void ESP()
    {
    for (int i = 0; i < SAMP_MAX_PLAYERS; i++) // перебираем всех игроков и проверяем их на вилидность
    {
    if and
    (SF->getSAMP()->getPlayers()->iIsListed[i] != 1) continue;
     (SF->getSAMP()->getPlayers()->pRemotePlayer[i] == NULL) continue;
     (SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData == NULL) continue;
     (SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->pSAMP_Actor == NULL) continue;
     (SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData->pSAMP_Actor->pGTA_Ped == NULL) continue;
            // Если игрок не существует или не в зоне стрима, то пропускаем
    }
    }
     
  4. CleanLegend

    Всефорумный модератор

    Регистрация:
    28 мар 2013
    Сообщения:
    251
    Симпатии:
    287
    pFont->Print(buf, SF->getSAMP()->getPlayers()->GetPlayerColor(i), screen[0], screen[1], false);
    Всё можно упростить, но для понимания посчитал нужным сделать так.
    Будет выглядеть примерно так:
    if (SF->getSAMP()->getPlayers()->iIsListed[i] != 1 || SF->getSAMP()->getPlayers()->pRemotePlayer[i] == NULL || SF->getSAMP()->getPlayers()->pRemotePlayer[i]->pPlayerData == NULL)
                continue;
     
    Carloson нравится это.