Гайд Обьяснение работы функции CLagCompensationManager::StartLagCompensation с помощью ИИ

Разработчик
Статус
Оффлайн
Регистрация
1 Сен 2018
Сообщения
1,602
Реакции[?]
882
Поинты[?]
117K
Всем привет, я немного увлёкся играя с ИИ, и готов поделиться результатом с вами. В этом посте будет обьяснена работа такой сложной функции как StartLagCompensation ( нет, хотя для многих это становится сложностью ).
Советую к прочтению на оригинальном английском языке.

C++:
void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCmd *cmd )
{
    Assert( !m_isCurrentlyDoingCompensation );

    //DONT LAG COMP AGAIN THIS FRAME IF THERES ALREADY ONE IN PROGRESS
    //IF YOU'RE HITTING THIS THEN IT MEANS THERES A CODE BUG
    if ( m_pCurrentPlayer )
    {
        Assert( m_pCurrentPlayer == NULL );
        Warning( "Trying to start a new lag compensation session while one is already active!\n" );
        return;
    }

    // Assume no players need to be restored
    m_RestorePlayer.ClearAll();
    m_bNeedToRestore = false;

    m_pCurrentPlayer = player;

    if ( !player->m_bLagCompensation        // Player not wanting lag compensation
         || (gpGlobals->maxClients <= 1)    // no lag compensation in single player
         || !sv_unlag.GetBool()                // disabled by server admin
         || player->IsBot()                 // not for bots
         || player->IsObserver()            // not for spectators
        )
        return;

    // NOTE: Put this here so that it won't show up in single player mode.
    VPROF_BUDGET( "StartLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING );
    Q_memset( m_RestoreData, 0, sizeof( m_RestoreData ) );
    Q_memset( m_ChangeData, 0, sizeof( m_ChangeData ) );

    m_isCurrentlyDoingCompensation = true;

    // Get true latency

    // correct is the amout of time we have to correct game time
    float correct = 0.0f;

    INetChannelInfo *nci = engine->GetPlayerNetInfo( player->entindex() );

    if ( nci )
    {
        // add network latency
        correct+= nci->GetLatency( FLOW_OUTGOING );
    }

    // calc number of view interpolation ticks - 1
    int lerpTicks = TIME_TO_TICKS( player->m_fLerpTime );

    // add view interpolation latency see C_BaseEntity::GetInterpolationAmount()
    correct += TICKS_TO_TIME( lerpTicks );

    // check bouns [0,sv_maxunlag]
    correct = clamp( correct, 0.0f, sv_maxunlag.GetFloat() );

    // correct tick send by player
    int targettick = cmd->tick_count - lerpTicks;

    // calc difference between tick send by player and our latency based tick
    float deltaTime =  correct - TICKS_TO_TIME(gpGlobals->tickcount - targettick);

    if ( fabs( deltaTime ) > 0.2f )
    {
        // difference between cmd time and latency is too big > 200ms, use time correction based on latency
        // DevMsg("StartLagCompensation: delta too big (%.3f)\n", deltaTime );
        targettick = gpGlobals->tickcount - TIME_TO_TICKS( correct );
    }

    // Iterate all active players
    const CBitVec<MAX_EDICTS> *pEntityTransmitBits = engine->GetEntityTransmitBitsForClient( player->entindex() - 1 );
    for ( int i = 1; i <= gpGlobals->maxClients; i++ )
    {
        CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );

        if ( !pPlayer )
        {
            continue;
        }

        // Don't lag compensate yourself you loser...
        if ( player == pPlayer )
        {
            continue;
        }

        // Custom checks for if things should lag compensate (based on things like what team the player is on).
        if ( !player->WantsLagCompensationOnEntity( pPlayer, cmd, pEntityTransmitBits ) )
            continue;

        // Move other player back in time
        BacktrackPlayer( pPlayer, TICKS_TO_TIME( targettick ) );
    }
}

Обьяснение:
The first few lines of the code check whether lag compensation is enabled, and if not, then the function returns. The code then initializes the variables it needs to keep track of and sets a flag to indicate that it is currently performing lag compensation. Then, it calculates the actual latency in the connection by taking into account both the game server's latency and the player's view interpolation latency, and clamps the total latency between 0 and the value set by the server administrator in the sv_maxunlag variable. After that, it checks the difference between the command tick count sent by the player and the calculated tick count for latency, and if the difference is greater than 0.2f, the target tick count is corrected based on the latency AI: After that, the code iterates through all the active players, skips the player performing the lag compensation, and checks for any custom conditions (for example, what team the player is on) that might indicate whether lag compensation should be applied to them. If those conditions pass, the BacktrackPlayer() function is called to move the other player back in time according to the target tick count calculated before. AI: Finally, the isCurrentlyDoingCompensation flag is reset to indicate that lag compensation is no longer active.
Первые несколько строк кода проверяют, включена ли компенсация запаздывания, и если нет, то функция возвращается. Затем код инициализирует переменные, которые ему необходимо отслеживать, и устанавливает флаг, указывающий на то, что в данный момент выполняется компенсация задержки. Затем он вычисляет фактическую задержку в соединении, принимая во внимание как задержку игрового сервера, так и задержку интерполяции представления игрока, и зажимает общую задержку между 0 и значением, установленным администратором сервера в переменной sv_maxunlag. После этого проверяется разница между количеством тиков команды, отправленной игроком, и рассчитанным количеством тиков на предмет задержки, и если разница превышает 0,2f, то целевое количество тиков корректируется с учетом задержки.
После этого код перебирает всех активных игроков, пропускает игрока, выполняющего компенсацию задержки, и проверяет любые пользовательские условия (например, в какой команде находится игрок), которые могут указать, следует ли применять к нему компенсацию задержки. Если эти условия выполняются, вызывается функция BacktrackPlayer() для перемещения другого игрока назад во времени в соответствии с целевым количеством тиков, рассчитанным ранее. Наконец, флаг isCurrentlyDoingCompensation сбрасывается, чтобы указать, что компенсация запаздывания больше не активна.

Удачи в осведомлении дальнейшей работы игры!
 
Последнее редактирование:
like amiri in my mind
Пользователь
Статус
Оффлайн
Регистрация
4 Дек 2022
Сообщения
308
Реакции[?]
54
Поинты[?]
1K
Это конечно норм, но где, собственно, ИИ? Я вижу только что ты обьяснил малую часть работы анимаций(бектрек и еще по мелочи)
 
Начинающий
Статус
Оффлайн
Регистрация
22 Сен 2020
Сообщения
19
Реакции[?]
3
Поинты[?]
0
Полезно, но не трудно для самостоятельного изучения.
 
Разработчик
Статус
Оффлайн
Регистрация
1 Сен 2018
Сообщения
1,602
Реакции[?]
882
Поинты[?]
117K
Это конечно норм, но где, собственно, ИИ? Я вижу только что ты обьяснил малую часть работы анимаций(бектрек и еще по мелочи)
Не я этот текст писал, это делал собственно ИИ
 
t.me/maj0rblog
Дизайнер
Статус
Оффлайн
Регистрация
6 Окт 2018
Сообщения
975
Реакции[?]
619
Поинты[?]
7K
Классный гайд, спасибо!
Ой чувствую если мы поднажмём то будет обновление в хистерии на неверлуз)
 
Сверху Снизу