Правильная стрельба и работа хитбоксов. Возможно ?

Сообщения
144
Реакции
276
Помог
1 раз(а)
Приветствую.

На днях разбирался в работе хитбоксов игрока и возможных багах связанных с ними.

На первом этапе постарался определить основные проблемы:

1. Отсутствие синхронизации углов вращения модели игрока на сервере и клиенте.

2. Возможные проблемы с блендингом (этот вопрос ещё не разбирал). Блендинг в модели игрока отвечает за перекос верхней части туловища по двум осям. Благодаря ему модель игрока может смотреть "вверх/вниз", ну или помотать головой например. За информацию по блендингу отвечают два pev:
pev_blending_0,
pev_blending_1,

Как я понял, они являются чисто информационными и изменить их значение со стороны Амх нельзя, хотя блендинг ещё есть в фуллпаке "ES_Blending", но так далеко я пока не залезал.

3. Отставание модели игрока от реальных хитбоксов во время перемещения (чем выше скорость, тем больше отставание). Решается значением ex_interp 0.01 на клиенте.

На сколько я понял, решить эти проблемы (особенно последнюю), без изменения движка/протокола не получится, т.к. все эти "Баги" (на сколько я понимаю) призваны компенсировать возможные задержки между сервером и клиентом.

Немного поковыряв сурсы, нашел код, который отвечает за возникновение первой проблемы:

Код:
void CBasePlayer::StudioEstimateGait(void)
{
    float dt;
    vec3_t est_velocity;

    dt = gpGlobals->frametime;

    if (dt < 0)
        dt = 0;
    else if (dt > 1)
        dt = 1;

    if (dt == 0)
    {
        m_flGaitMovement = 0;
        return;
    }

    est_velocity[0] = pev->origin[0] - m_prevgaitorigin[0];
    est_velocity[1] = pev->origin[1] - m_prevgaitorigin[1];
    est_velocity[2] = pev->origin[2] - m_prevgaitorigin[2];
    m_prevgaitorigin[0] = pev->origin[0];
    m_prevgaitorigin[1] = pev->origin[1];
    m_prevgaitorigin[2] = pev->origin[2];
    m_flGaitMovement = sqrt(est_velocity[0] * est_velocity[0] + est_velocity[1] * est_velocity[1] + est_velocity[2] * est_velocity[2]);

    if (dt <= 0 || m_flGaitMovement / dt < 5)
    {
        m_flGaitMovement = 0;
        est_velocity[0] = est_velocity[1] = 0;
    }

    if (est_velocity[0] == 0 && est_velocity[1] == 0)
    {
        float flYawDiff = pev->angles[1] - m_flGaityaw;
        float flYaw = flYawDiff;
        flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360;

        if (flYawDiff > 180)
            flYawDiff -= 360;

        if (flYawDiff < -180)
            flYawDiff += 360;

        if (flYaw < -180)
            flYaw += 360;
        else if (flYaw > 180)
            flYaw -= 360;

        if (flYaw > -5 && flYaw < 5)
            m_flYawModifier = 0.05;

        if (flYaw < -90 || flYaw > 90)
            m_flYawModifier = 3.5;

        if (dt < 0.25)
            flYawDiff *= dt * m_flYawModifier;
        else
            flYawDiff *= dt;

        if (abs(flYawDiff) < 0.1)
            flYawDiff = 0;

        m_flGaityaw += flYawDiff;
        m_flGaityaw -= (int)(m_flGaityaw / 360) * 360;
        m_flGaitMovement = 0;
    }
    else
    {
        m_flGaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI);

        if (m_flGaityaw > 180)
            m_flGaityaw = 180;

        if (m_flGaityaw < -180)
            m_flGaityaw = -180;
    }
}

void CBasePlayer::CalculateYawBlend(void)
{
    float dt;
    float flYaw;
    float maxyaw;
    float blend_yaw;

    dt = gpGlobals->frametime;

    if (dt < 0)
        dt = 0;
    else if (dt > 1)
        dt = 1;

    StudioEstimateGait();

    maxyaw = 255.0;
    flYaw = pev->angles[1] - m_flGaityaw;

    if (flYaw < -180)
        flYaw += 360;
    else if (flYaw > 180)
        flYaw -= 360;

    if (m_flGaitMovement != 0)
    {
        if (flYaw > 120)
        {
            m_flGaityaw -= 180;
            m_flGaitMovement = -m_flGaitMovement;
            flYaw -= 180;
        }
        else if (flYaw < -120)
        {
            m_flGaityaw += 180;
            m_flGaitMovement = -m_flGaitMovement;
            flYaw += 180;
        }
    }

    flYaw = (flYaw / 90) * 128.0 + 127.0;

    if (flYaw > 255)
        flYaw = 255;
    else if (flYaw < 0)
        flYaw = 0;

    blend_yaw = maxyaw - flYaw;
    pev->blending[0] = (int)(blend_yaw);
    m_flYaw = blend_yaw;
}

И очень занятный оффсет m_flGaitYaw. Как раз он выдает правильный угол модели и на его основе рассчитывается угол на стороне сервера. Очевидно, что на стороне клиента этот код другой.

После, я собрал код в виде отдельной энтити, которая в пресинке перенимает от игрока: Оригины, Велосити, Кадр анимации и Animtime, а угол был скопирован с m_flGaitYaw, что в итоге дало "видимую" модель игрока с правильными хитбоксами. Фактически, такая реализация решает 1 и 3 проблемы (хотя в идеале нужен фуллпак).

В моем случае я использовал полностью кастомные анимации модели игрока с измененным скелетом, по этому у меня не возникло проблем с анимациями ног "gaitsequence" и на сколько я понимаю, задействовать их на отдельной энтити не получится, т.к. gaitsequence работает только на реальном игроке.

Вот пример различия работы хитбоксов:
Взята большая модель. Есть пример не првильного рассчета углов и отставания реальных хитбоксов от клиентской модели при быстром передвижении.

У кого какие мысли ? Кто уже пробовал ковырять в этом направлении ?
 
Последнее редактирование:
Сообщения
1,104
Реакции
319
Ну так надо взять код клиентской стороны и вставить в rehlds или regamedll, пусть лучше будут кривые модели чем хитбоксы))
4 Авг 2019
Что отправляет клиентам сервер? Хитбоксы и модель, или только хитбоксы а клиентская часть рисует модель??
 
Сообщения
144
Реакции
276
Помог
1 раз(а)
Касательно третьей проблемы. Решается значением ex_interp 0.01 на клиенте.
 
Последнее редактирование:
Сообщения
144
Реакции
276
Помог
1 раз(а)
fantom, С серверой. С клиентской я хз где этот код взять. В ксаше возможно что-то есть.
 
Сообщения
2,491
Реакции
2,790
Помог
61 раз(а)
В ксаше возможно что-то есть
Код:
void CStudioModelRenderer::StudioEstimateGait(entity_state_t *pplayer)
{
    float dt;
    vec3_t est_velocity;

    dt = (m_clTime - m_clOldTime);

    if (dt < 0)
        dt = 0;
    else if (dt > 1.0)
        dt = 1;

    if (dt == 0 || m_pPlayerInfo->renderframe == m_nFrameCount)
    {
        m_flGaitMovement = 0;
        return;
    }

    if (m_fGaitEstimation)
    {
        VectorSubtract(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity);
        VectorCopy(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin);
        m_flGaitMovement = est_velocity.Length();

        if (dt <= 0 || m_flGaitMovement / dt < 5)
        {
            m_flGaitMovement = 0;
            est_velocity[0] = 0;
            est_velocity[1] = 0;
        }
    }
    else
    {
        VectorCopy(pplayer->velocity, est_velocity);
        m_flGaitMovement = est_velocity.Length() * dt;
    }

    if (est_velocity[1] == 0 && est_velocity[0] == 0)
    {
        float flYawDiff = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
        flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360;

        if (flYawDiff > 180)
            flYawDiff -= 360;
        if (flYawDiff < -180)
            flYawDiff += 360;

        if (dt < 0.25)
            flYawDiff *= dt * 4;
        else
            flYawDiff *= dt;

        m_pPlayerInfo->gaityaw += flYawDiff;
        m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360;
        m_flGaitMovement = 0;
    }
    else
    {
        m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI);

        if (m_pPlayerInfo->gaityaw > 180)
            m_pPlayerInfo->gaityaw = 180;

        if (m_pPlayerInfo->gaityaw < -180)
            m_pPlayerInfo->gaityaw = -180;
    }
}

void CGameStudioModelRenderer::CalculateYawBlend(entity_state_t *pplayer)
{
    float flYaw;
    StudioEstimateGait(pplayer);
    flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;
    flYaw = fmod(flYaw, 360.0f);
    if (flYaw < -180)
        flYaw = flYaw + 360;
    else if (flYaw > 180)
        flYaw = flYaw - 360;
    float maxyaw = 120.0;
    if (flYaw > maxyaw)
    {
        m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180;
        m_flGaitMovement = -m_flGaitMovement;
        flYaw = flYaw - 180;
    }
    else if (flYaw < -maxyaw)
    {
        m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180;
        m_flGaitMovement = -m_flGaitMovement;
        flYaw = flYaw + 180;
    }
    float blend_yaw = (flYaw / 90.0) * 128.0 + 127.0;
    blend_yaw = 255.0 - bound( 0.0, blend_yaw, 255.0 );
    m_pCurrentEntity->curstate.blending[0] = (int)(blend_yaw);
    m_pCurrentEntity->latched.prevblending[0] = m_pCurrentEntity->curstate.blending[0];
    m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0];
    m_pCurrentEntity->angles[YAW] = m_pPlayerInfo->gaityaw;
    if (m_pCurrentEntity->angles[YAW] < -0)
        m_pCurrentEntity->angles[YAW] += 360;
    m_pCurrentEntity->latched.prevangles[YAW] = m_pCurrentEntity->angles[YAW];
}
 
Сообщения
1,104
Реакции
319
Может проще спросить у разработчиком "ксаше" исправили они хитбоксы или нет))))
 
Сообщения
1,661
Реакции
1,486
Помог
24 раз(а)

d3m37r4

111111
Сообщения
1,420
Реакции
1,162
Помог
10 раз(а)
fl0wer, пиши фикс хитбоксов, разработчика дадут.
 
Сообщения
1,661
Реакции
1,486
Помог
24 раз(а)
d3m37r4, валв его встроят, а там приват, тут так нельзя, только опенсорс, ноунемейвский ник и связи
 
Сообщения
1,104
Реакции
319
Отставания это еще фигня, кто захочет напишет ex_interp 0...

А вот то что они вообще не совпадают с моделью, че нету толковых программистов которые смогут пофиксить эту хрень? (((
 
Сообщения
43
Реакции
6
В итоге есть решение ? для исправления hitbox ?
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу