Исходник функции TRACE_HULL? / Момент вычисления glb_trace_plane_normal?

Сообщения
78
Реакции
65
Здравствуйте, пытаюсь сделать плагин исправляющий surf bug (это баг когда наклонная поверхность тормозит игрока до 0, чем больше его FPS, тем чаще баг)
Для этого нужно определить находится ли игрок сейчас на наклонной поверхности. Делаю я это через функцию trace_hull и переменную TR_vecPlaneNormal.

Код:
static Float:playerOrigin[3], Float:planeNormal[3], Float:traceHullEnd[3]
traceHullEnd[0] = playerOrigin[0]
traceHullEnd[1] = playerOrigin[1]
traceHullEnd[2] = playerOrigin[2] - 0.01 // "трейсим" под игроком

engfunc(EngFunc_TraceHull, playerOrigin, traceHullEnd, IGNORE_MONSTERS | IGNORE_MISSILE, hull, id, 0)
get_tr2(0, TR_vecPlaneNormal, planeNormal) // нормаль поверхности под игроком?

rampAngle = planeNormal[2] // Искомый угол поверхности под игроком получен

1. Хороший ли это способ получение наклона поверхности под игроком или есть получше, какой?
2. Можно ли где-то увидеть исходный код функции TRACE_HULL?
3. С какими параметрами для trace_hull вычисляется glb_trace_plane_normal? И как часто, каждый кадр? (Это вопрос от любопытства, для моего плагина эта глобалка не годится, вызывает баг с наклонным телепортом)
 
Последнее редактирование:
Сообщения
169
Реакции
462
Помог
2 раз(а)
Можно ли где-то увидеть исходный код функции TRACE_HULL?
Можно
С какими параметрами для trace_hull вычисляется glb_trace_plane_normal? И как часто, каждый кадр?
Это не совсем так работает. Каждый раз когда какая-либо функция делает трейс, результат она может сохранить в эти самые глобальные (glb_*) переменные (например, в rehlds, функция которая делает трейс, может вызывать эту функцию для сохранения результата трейса). По идеи, результат должен сохраняться и при вызове функции trace_hull, но в рехлдс этого не сделано (не знаю почему, может есть причины, а может и недоработка, не разбирался).
 

ssx

Сообщения
295
Реакции
86
У меня на 490+ ФПС (клиент) проявляются два бага:
1. Тормозит когда об бок стенки или ящика
2. Не сразу срабатывают A D если присел.
 
Сообщения
78
Реакции
65
the_hunter, спасибо!
ssx, Когда тебя тормозит стена, это вроде бы wall bug, хотя его причина наверняка та же что у surf bug. Кстати wall bug полезен на HNS серверах и возможно KZ. А насчёт движения в присяде, это уже другое что то, если я правильно понял о чём ты.
А surf bug очень вреден для психики игроков на серверах с auto-bhop и сёрфингом. Хотя возможно и wall bug может мешать в очень редких ситуациях, но пока что я нацелен только на surf bug.
14 Сен 2020
Ресурсы я создавать не могу, но если кому то нужен будет такой плагин выложу сюда хотя бы, боли этот баг доставляет много.
Исходник в прикрепе, или:
Код:
/*
    (DONE) TODO: fix teleport bug.
    When player land on ramp with trigger_teleport and get teleported,
    plugin thinks that's surf bug and revert player's speed after he teleported.

    Solution: Instead of using global 'glb_trace_plane_normal' we need to calculate our own.
    Because it seems to set trace_hull's end point too low (72 units or more below the player).

    TODO: Think more about 'prevSpeed != 0.0' and make sure it don't allow even one frame for surf bug.
    
*/

#include <amxmodx>
#include <fakemeta>

#define AUTHOR "Lopol2010"
#define PLUGIN "surffix"
#define VERSION "0.1"

#define prefix "[surffix]" // Chat prefix
#define UNSTUCK_HEIGHT 0.01 // How high to teleport player after surf bug.
#define TRACE_HULL_HEIGHT 0.01 // How high to teleport player after surf bug.

new count[33]

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR)
    register_forward(FM_CmdStart, "OnCmdStart")

    register_clcmd("say /surffix", "print_count", -1, "Print in chat count of fixed surf bugs.")
}

public client_putinserver(id)
{
    set_task(1.0, "welcome_message", id)
}

public client_disconnected(id)
{
    count[id] = 0
}

public welcome_message(id)
{
    client_print_color(id, print_team_red, "^4%s^1 You are protected from surf bugs! See your surf bugs count via /surffix", prefix)
}

public print_count(id)
{
    client_print_color(id, print_team_red, "^4%s^1 You saved from ^3%d ^1surf bugs.", prefix, count[id])
}

public OnCmdStart(id, handle, seed)
{
    static Float:lastGoodVelocity[3], Float:playerOrigin[3], Float:planeNormal[3], Float:traceHullEnd[3]
    static Float:speed, Float:prevSpeed, Float:rampAngle, hull

    speed = GetVelocity(id)

    pev(id, pev_origin, playerOrigin)

    traceHullEnd[0] = playerOrigin[0]
    traceHullEnd[1] = playerOrigin[1]
    traceHullEnd[2] = playerOrigin[2] - TRACE_HULL_HEIGHT

    hull = pev(id, pev_flags) & FL_DUCKING ? HULL_HEAD : HULL_HUMAN
    engfunc(EngFunc_TraceHull, playerOrigin, traceHullEnd, IGNORE_MONSTERS | IGNORE_MISSILE, hull, id, 0)
    get_tr2(0, TR_vecPlaneNormal, planeNormal)

    // Angle of slope below player
    rampAngle = planeNormal[2]

    // Plain surface is 0.0 and 1.0, so we want everything between
    if(rampAngle < 0.99999 && rampAngle > 0.00001)
    {
        prevSpeed = vector_length(lastGoodVelocity)
        // Player got surf bug
        if(speed == 0.0 && prevSpeed != 0.0)
        {
            set_pev(id, pev_velocity, lastGoodVelocity)
            playerOrigin[2] = playerOrigin[2] + UNSTUCK_HEIGHT
            set_pev(id, pev_origin, playerOrigin)

            ++ count[id]
        }
        else
        {
            pev(id, pev_velocity, lastGoodVelocity)
        }
    }
    
}

// Don't use this method.
// When you stuck on surf ramp, you might not move at all,
// but your vertical velocity will be -1.2 which will make player speed > 0 and break bug detection algorythm.
stock Float:GetMoveSpeed(id)
{
    static Float:v[3]
    pev(id, pev_velocity, v)
    return vector_length(v)
}

stock Float:GetVelocity(id)
{
    static Float:v[3]
    pev(id, pev_velocity, v)
    return floatsqroot(floatpower(v[0], 2.0) + floatpower(v[1], 2.0))
}
 

Download all Attachments

Последнее редактирование:
Сообщения
134
Реакции
463
Помог
2 раз(а)
Нашел такой сток, мб пригодится
Код:
stock is_player_sliding(id)
{
    if(!is_user_alive(id))
        return 0;

    new flags = entity_get_int(id, EV_INT_flags);
    if(flags & FL_ONGROUND)
        return 0;

    new Float:origin[3], Float:dest[3];
    pev(id, pev_origin, origin);

    dest[0] = origin[0];
    dest[1] = origin[1];
    dest[2] = origin[2] - 1.0;

    new ptr = create_tr2();
    engfunc(EngFunc_TraceHull, origin, dest, 0, flags & FL_DUCKING ? HULL_HEAD : HULL_HUMAN, id, ptr);
    new Float:flFraction;
    get_tr2(ptr, TR_flFraction, flFraction);
    if( flFraction >= 1.0 )
    {
        free_tr2(ptr);
        return 0;
    }

    get_tr2(ptr, TR_vecPlaneNormal, dest);
    free_tr2(ptr);

    return dest[2] <= 0.7;
}
 
Сообщения
78
Реакции
65
medusa, Спасибо, а я и забыл про базовые проверки типа is_alive :) Завтра по человечески доделаю.
Но по логике то же что я написал, кроме проверки угла поверхности, я беру не 0.7 а малейший наклон 0 < n < 1

Возникли вопросы по этому стоку, если кто знает помогите:
1. Почему создаётся свой tr2 (create_tr2) вместо использования глобального? То есть посылать 0 в функции, у меня это работает вроде бы исправно.
2. Что за TR_flFraction? В стоке проверка >= 1.0 а я нашел описание: " Возвращает число от 0.0 до 1.0 " и как он может быть больше 1.0? Для trace_hull эта штука имеет другой смысл?
 
Последнее редактирование:
Сообщения
212
Реакции
334
Помог
3 раз(а)
Lopol2010,
А стоит ли брать малейший наклон? Если у грани, на которой стоит игрок, есть наклон, то это не значит, что это сюрф поверхность.
1. Потому что если этот сток будет использоваться, к примеру, во время обработки глобального дескриптора каким-то другим плагином/движком, то это может привести к неопределенному поведению, т.к ты начнешь переопределять уже записанную в нулевой дескриптор трейсу, которая используется.
2. TR_flFraction описывает сколько процентов пути прошла трейса от заданного начала и конца. 1.0, соответственно, 100%, т.е весь путь без препятствий. Препятствия задаются специальными флагами, но препятствием всегда является worldspawn (т.е карта целиком, исключая брашевые объекты). Больше сотни процентов число не вернется, так что тут небольшая неточность.
 
Сообщения
78
Реакции
65
Xelson, в моём случае это необходимо. Когда играешь на auto-bhop сервере с большим fps, любая наклонная поверхность может тебя тормозить. А для обычного сёрф сервера с fps_max 131 и впрямь хватит того что в стоке.

Спасибо за ответы я так и предполагал, только насчёт первого я все ещё не уверен, но глобальный трейс перестану использовать.
 
Сообщения
78
Реакции
65
Думаю последняя версия 1.0
Протестировал на surf и bhop с 1000 фпс, ни разу не тормознуло.

Код:
/*

    cvars:
        # Inform joined player that this plugin is enabled on the server.
        surffix_welcome 1

    description:
        This plugin prevents surf bug. Surf bug is when player sliding or surfing and instantly got 0 speed. Kind of stuck in the wall.
        Very useful for jump or surf servers where players can have high FPS.

    How it works:
        1. Detect if player stands or slides on a slope of any angle, kinda is_player_on_slope function.
        2. Detect speed is 0 and set previous speed that is not zero

*/

#include <amxmodx>
#include <fakemeta>
#include <engine>

#define AUTHOR "Lopol2010"
#define PLUGIN "surffix"
#define VERSION "1.0"

#define prefix "[surffix]" // Chat prefix
#define UNSTUCK_HEIGHT 0.01 // How high to teleport player after surf bug.
#define TRACE_HULL_HEIGHT 0.01 // How high to teleport player after surf bug.

new pWelcome

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR)
    register_forward(FM_CmdStart, "OnCmdStart")
    pWelcome = register_cvar("surffix_welcome", "1")
}

public client_putinserver(id)
{
    if(get_pcvar_num(pWelcome) == 1)
    {
        set_task(1.0, "welcome_message", id)
    }
}

public welcome_message(id)
{
    client_print_color(id, print_team_red, "^4%s^1 You are protected from surf bugs!", prefix)
}

public OnCmdStart(id, handle, seed)
{

    if(!is_user_alive(id))
    {
        return
    }

    static Float:planeNormal[3], Float:traceHullEnd[3], Float:playerOrigin[3], Float:lastGoodVelocity[3]
    static Float:rampAngle, Float:speed, Float:prevSpeed, hull

    entity_get_vector(id, EV_VEC_origin, playerOrigin)

    traceHullEnd[0] = playerOrigin[0]
    traceHullEnd[1] = playerOrigin[1]
    traceHullEnd[2] = playerOrigin[2] - TRACE_HULL_HEIGHT

    hull = entity_get_int(id, EV_INT_flags) & FL_DUCKING ? HULL_HEAD : HULL_HUMAN

    engfunc(EngFunc_TraceHull, playerOrigin, traceHullEnd, IGNORE_MONSTERS | IGNORE_MISSILE, hull, id, 0)
    get_tr2(0, TR_vecPlaneNormal, planeNormal)

    rampAngle = planeNormal[2]

    // Slope with any angle
    if(rampAngle != 0.0 && rampAngle != 1.0)
    {

        speed = get_player_velocity(id)

        // Player got surf bug
        if(speed == 0.0 && prevSpeed != 0.0)
        {
            entity_set_vector(id, EV_VEC_velocity, lastGoodVelocity)
            playerOrigin[2] = playerOrigin[2] + UNSTUCK_HEIGHT
            entity_set_vector(id, EV_VEC_origin, playerOrigin)
        }
        else
        {
            entity_get_vector(id, EV_VEC_velocity, lastGoodVelocity)
            prevSpeed = floatsqroot(floatpower(lastGoodVelocity[0], 2.0) + floatpower(lastGoodVelocity[1], 2.0)) // calculate velocity
        }
    }

}

stock Float:get_player_velocity(id)
{
    static Float:v[3]
    entity_get_vector(id, EV_VEC_velocity, v)
    return floatsqroot(floatpower(v[0], 2.0) + floatpower(v[1], 2.0))
}

Поставил плагин на свой сервер с bhop, если есть любители можете заценить. Один уже кайфанул, не считая меня.
193.19.118.100:27015
 

Вложения

Последнее редактирование:
Сообщения
134
Реакции
463
Помог
2 раз(а)
Поддержу, многим серверам спидрана и сюрфа не хватает такого.
Так же протестировал на ЛАН сервере плагин, с +- 600-900 фпс, засейвил примерно 600-700 клипингов на сюрфах.
 
Сообщения
13
Реакции
4
Lopol2010, тестил ваш плагин, заметил что иногда телепортит не в ту сторону... То есть при передвижении прямо меня оттолкнуло назад, так же отталкивало и вверх.
 
Сообщения
78
Реакции
65
Lopol2010, тестил ваш плагин, заметил что иногда телепортит не в ту сторону... То есть при передвижении прямо меня оттолкнуло назад, так же отталкивало и вверх.
Можно подробнее? У меня такого ни разу не случалось. То есть как назад, буквально вектор скорости повернулся на 180 и ты полетел спиной назад? В коде сохраняется твоё движение и в следующем кадре возвращается если тебя тормознуло, так не могло разверуть же.
Lopol2010, prevSpeed разве не должен быть массивом со своей последней скоростью для каждого игрока?
Спасибо. Ты гений, а я дэбил.
16 Сен 2020
p1oneer, Другими словами - как воспроизвести то что ты описал?
16 Сен 2020
fantom, p1oneer, ну конечно же. lastGoodVelocity тоже должен сохранятся каждому игроку, а пионера разворачивало как раз из за этого. Ему ставилась чужая скорость судя по всему :pardon:
 
Последнее редактирование:
Сообщения
78
Реакции
65
Публикация скомпилированных файлов
Версия 1.1
Исправил: prevSpeed и lastGoodVelocity теперь хранятся для каждого игрока.

Код:
/*

    cvars:
        # Inform joined player that this plugin is enabled on the server.
        surffix_welcome 1

    description:
        This plugin prevents surf bug. Surf bug is when player sliding or surfing and instantly got 0 speed. Kind of stuck in the wall.
        Very useful for jump or surf servers where players can have high FPS.

    How it works:
        1. Detect if player stands or slides on a slope of any angle, kinda is_player_on_slope function.
        2. Detect speed is 0 and set previous speed that is not zero

    version 1.1
        fix: 'prevSpeed' is now array and value saved for each player.
        fix: Some players was getting foreign speed on unstuck. Because 'lastGoodVelocity' is not saved per player!

*/

#include <amxmodx>
#include <fakemeta>
#include <engine>

#define AUTHOR "Lopol2010"
#define PLUGIN "surffix"
#define VERSION "1.1"

#define prefix "[surffix]" // Chat prefix
#define UNSTUCK_HEIGHT 0.01 // How high to teleport player after surf bug.
#define TRACE_HULL_HEIGHT 0.01 // How high to teleport player after surf bug.

new pWelcome

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR)
    register_forward(FM_CmdStart, "OnCmdStart")
    pWelcome = register_cvar("surffix_welcome", "1")
}

public client_putinserver(id)
{
    if(get_pcvar_num(pWelcome) == 1)
    {
        set_task(1.0, "welcome_message", id)
    }
}

public welcome_message(id)
{
    client_print_color(id, print_team_red, "^4%s^1 You are protected from surf bugs!", prefix)
}

public OnCmdStart(id, handle, seed)
{

    if(!is_user_alive(id))
    {
        return
    }

    static Float:planeNormal[3], Float:traceHullEnd[3], Float:playerOrigin[3], Float:lastGoodVelocity[33][3], Float:prevSpeed[33]
    static Float:rampAngle, Float:speed, hull

    entity_get_vector(id, EV_VEC_origin, playerOrigin)

    traceHullEnd[0] = playerOrigin[0]
    traceHullEnd[1] = playerOrigin[1]
    traceHullEnd[2] = playerOrigin[2] - TRACE_HULL_HEIGHT

    hull = entity_get_int(id, EV_INT_flags) & FL_DUCKING ? HULL_HEAD : HULL_HUMAN

    engfunc(EngFunc_TraceHull, playerOrigin, traceHullEnd, IGNORE_MONSTERS | IGNORE_MISSILE, hull, id, 0)
    get_tr2(0, TR_vecPlaneNormal, planeNormal)

    rampAngle = planeNormal[2]

    // Slope with any angle
    if(rampAngle != 0.0 && rampAngle != 1.0)
    {

        speed = get_player_velocity(id)

        // Player got surf bug
        if(speed == 0.0 && prevSpeed[id] != 0.0)
        {
            entity_set_vector(id, EV_VEC_velocity, lastGoodVelocity[id])
            playerOrigin[2] = playerOrigin[2] + UNSTUCK_HEIGHT
            entity_set_vector(id, EV_VEC_origin, playerOrigin)
        }
        else
        {
            entity_get_vector(id, EV_VEC_velocity, lastGoodVelocity[id])
            prevSpeed[id] = get_player_velocity(id) // calculate velocity
        }
    }
   
}

stock Float:get_player_velocity(id)
{
    static Float:v[3]
    entity_get_vector(id, EV_VEC_velocity, v)
    return floatsqroot(floatpower(v[0], 2.0) + floatpower(v[1], 2.0))
}
 

Вложения

Последнее редактирование модератором:
Сообщения
2,491
Реакции
2,794
Помог
61 раз(а)
Lopol2010, у нас на форуме запрещена публикация скомпилированных файлов амхх. Ознакомьтесь с правилами. Также было бы хорошо если б вы оформили ваш плагин как ресурс, как это делают другие.
 
Сообщения
78
Реакции
65
Сообщения
2,491
Реакции
2,794
Помог
61 раз(а)
Lopol2010, для этого нужен статус участник. Он будет выдан автоматически после 15 сообщений и 5 лайкков. Лайков у вас уже достаточно. Остались 2 сообщения.
 
Сообщения
78
Реакции
65
steelzzz, Да скорей всего оповещение стоит убрать, уже на 1 сервере плагин стоит и админ выключил это оповещение. Моя мотивация такова: обычно я играю с переключателем fps между 131 и 500 чтобы избегать сёрф бага, что если игроки будут продолжать использовать эти бинды не зная о том что на сервере баг исправлен? Возможно это конечно чушь, ведь такими биндами заморочены единицы pro игроков, а нубам вообще плевать. Было сложно но я подумал благодаря твоему вопросу, спасибо.
 
Сообщения
13
Реакции
4
Ему ставилась чужая скорость судя по всему :pardon:
Вижу уже описывать в подробностях не обязательно)
А по поводу оповещения - кому надо тот сам сможет отключить... Чтож, буду тестить, если еще что нибудь замечу дам знать:smile3:
 

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

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