• Регистрация на форуме отключена.
    Она будет открываться первого числа каждого месяца на 24 часа.

    Другие способы описаны>> тут <<

Склад полезного кода [GoldSrc]

Сообщения
429
Реакции
276
Предупреждения
5
Помог
13 раз(а)
И не нужно использовать глобальные. Вы можете содержимое гарантировать? Нет. А содержимое трейса при врезке? Нет.
 
Последнее редактирование модератором:
Сообщения
1,187
Реакции
960
Предупреждения
1
Помог
15 раз(а)
fantom, я не понимаю откуда вы эти косинусы взяли и каким образом и зачем сами считаете, если в сурсах мейка и происходит это.
Тем более везде в кс делается так.

Сурс MakeVectors, сразу forward, rigth, up записывается в глобалки при вызове:
Код:
void EXT_FUNC PF_makevectors_I(const float *rgflVector)
{
    AngleVectors(rgflVector, gGlobalVariables.v_forward, gGlobalVariables.v_right, gGlobalVariables.v_up);
}
Сурс AngleVectors в ReGameDLL, преобразование в углы Эйлера вроде:
https://github.com/s1lentq/ReGameDL...071ac0dd1/regamedll/pm_shared/pm_math.cpp#L12

Код:
stock get_CoordPointInDirView(const index, const Float:dist, Float:output[3]) {
    new Float:start_origins[3];
    pev(index, pev_origin, start_origins);

    new Float:angles[3];
    new Float:forward[3];
    pev(index, pev_v_angle, angles);

    engfunc(EngFunc_MakeVectors, angles); // делаем глобальный вектор по углу
    global_get(glb_v_forward, forward); // берем перед, так же можно v_right, v_up, либо всё сразу через AngleVectors

    new Float:end_origins[3];
    end_origins[0] = start_origins[0] + forward * dist; // задаем смещения
    end_origins[1] = start_origins[1] + forward * dist;
    end_origins[2] = start_origins[2] + forward * dist; // тут тоже можно

    engfunc(EngFunc_TraceLine, start_origins, end_origins, DONT_IGNORE_MONSTERS, index, 0);
    get_tr2(0, TR_vecEndPos, end_origins);

    output[0] = end_origins[0];
    output[1] = end_origins[1];
    output[2] = end_origins[2];
}
Пример статусбара (когда наводишь на игроков):
Код:
    TraceResult tr;
    UTIL_MakeVectors(pev->v_angle + pev->punchangle);

    Vector vecSrc = EyePosition();
    Vector vecEnd = vecSrc + (gpGlobals->v_forward * ((pev->flags & FL_SPECTATOR) != 0 ? MAX_SPEC_ID_RANGE : MAX_ID_RANGE));

    UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, edict(), &tr);
 
Последнее редактирование модератором:
Сообщения
2,389
Реакции
2,459
Помог
56 раз(а)
не доверяю get_players() из за его основания на user messages, пишу свой на ReAPI
Код:
#include <amxmodx>
#include <amxmisc>
#include <reapi>

public plugin_init() {
    new aPlayers[MAX_PLAYERS], count;

    _get_players(aPlayers, count);
    register_srvcmd("a", "asd");
}

public asd() {
    server_print("^n^n^n^n======================");
    server_print("_get_playersnum_ex(): %i | %i", _get_playersnum_ex(), get_playersnum_ex());

    new GetPlayersFlags:flags = GetPlayers_MatchTeam;
    server_print("_get_playersnum_ex(T): %i | %i", _get_playersnum_ex(flags, "TERRORIST"), get_playersnum_ex(flags, "TERRORIST"));
    server_print("_get_playersnum_ex(CT): %i | %i", _get_playersnum_ex(flags, "CT"), get_playersnum_ex(flags, "CT"));

    flags += GetPlayers_ExcludeDead | GetPlayers_CaseInsensitive;
    server_print("_get_playersnum_ex(GetPlayers_ExcludeDead, T): %i | %i", _get_playersnum_ex(flags, "TERrORIST"), get_playersnum_ex(flags, "TERrORIST"));
    server_print("_get_playersnum_ex(GetPlayers_ExcludeDead, CT): %i | %i", _get_playersnum_ex(flags, "Ct"), get_playersnum_ex(flags, "Ct"));

    flags = GetPlayers_MatchTeam | GetPlayers_ExcludeAlive;
    server_print("_get_playersnum_ex(GetPlayers_ExcludeAlive, T): %i | %i", _get_playersnum_ex(flags, "TERRORIST"), get_playersnum_ex(flags, "TERRORIST"));
    server_print("_get_playersnum_ex(GetPlayers_ExcludeAlive, CT): %i | %i", _get_playersnum_ex(flags, "CT"), get_playersnum_ex(flags, "CT"));

    flags = GetPlayers_ExcludeHuman;
    server_print("_get_playersnum_ex(GetPlayers_ExcludeHuman): %i | %i", _get_playersnum_ex(flags), get_playersnum_ex(flags));

    flags = GetPlayers_MatchNameSubstring;
    server_print("_get_playersnum_ex(GetPlayers_MatchNameSubstring): %i | %i", _get_playersnum_ex(flags, "FAKE"), get_playersnum_ex(flags, "FAKE"));

    flags = GetPlayers_ExcludeHLTV;
    server_print("_get_playersnum_ex(GetPlayers_ExcludeHLTV): %i | %i", _get_playersnum_ex(flags), get_playersnum_ex(flags));

    flags = GetPlayers_IncludeConnecting;
    server_print("_get_playersnum_ex(GetPlayers_IncludeConnecting): %i | %i", _get_playersnum_ex(flags), get_playersnum_ex(flags));
}



/**
 * Stores a filtered list of client indexes to an array.
 *
 * @note Example retrieving all alive CTs:
 *       get_players_ex(players, num, GetPlayers_ExcludeDead | GetPlayers_MatchTeam, "CT")
 *
 * @param players   Array to store indexes to
 * @param num       Variable to store number of indexes to
 * @param flags     Optional filtering flags (enum GetPlayersFlags); valid flags are:
 *                    GetPlayers_None - No filter (Default)
 *                    GetPlayers_ExcludeDead - do not include dead clients
 *                    GetPlayers_ExcludeAlive - do not include alive clients
 *                    GetPlayers_ExcludeBots - do not include bots
 *                    GetPlayers_ExcludeHuman - do not include human clients
 *                    GetPlayers_MatchTeam - match with team
 *                    GetPlayers_MatchNameSubstring - match with part of name
 *                    GetPlayers_CaseInsensitive - match case insensitive
 *                    GetPlayers_ExcludeHLTV - do not include SourceTV proxies
 *                    GetPlayers_IncludeConnecting - include connecting clients
 * @param team      String to match against if the "MatchTeam" or "GetPlayers_MatchNameSubstring" flag is specified
 *
 * @noreturn
 */
stock _get_players_ex(players[MAX_PLAYERS] = {}, &num, GetPlayersFlags:flags = GetPlayers_None, const buffer[] = "") {
    #define _get_user_team(%1) (get_member(%1, m_iTeam))
    #define _str_contains(%1,%2,%3) bool:((%3 ? contain(%1,%2) : containi(%1,%2)) != -1)
    new TeamName:team = TEAM_UNASSIGNED;
    new name[MAX_NAME_LENGTH];
    if (flags & GetPlayers_MatchTeam) {
        team = TeamFromName(buffer, !(flags & GetPlayers_CaseInsensitive));
    }
    for (new i = 1; i <= MaxClients; i++) {
        if (is_user_connected(i) || ((flags & GetPlayers_IncludeConnecting) && is_user_connecting(i))) {
            if (is_user_alive(i) ? (flags & GetPlayers_ExcludeAlive) : (flags & GetPlayers_ExcludeDead))
                continue;
            if (is_user_bot(i) ? (flags & GetPlayers_ExcludeBots) : (flags & GetPlayers_ExcludeHuman))
                continue;
            if ((flags & GetPlayers_MatchTeam) && _get_user_team(i) != team)
                continue;
            if ((flags & GetPlayers_ExcludeHLTV) && is_user_hltv(i))
                continue;
            if (flags & GetPlayers_MatchNameSubstring) {
                get_entvar(i, var_netname, name, charsmax(name));
                if (!_str_contains(buffer, name, !(flags & GetPlayers_CaseInsensitive)))
                    continue;
            }
            players[num++] = i;
        }
    }
}
/**
 * Returns the number of clients on the server that match the specified flags.
 *
 * @note Example retrieving all alive CTs:
 *       new AliveCt = get_playersnum_ex(GetPlayers_ExcludeDead | GetPlayers_MatchTeam, "CT")
 *
 * @param flags     Optional filtering flags (enum GetPlayersFlags); valid flags are:
 *                    GetPlayers_None - No filter (Default)
 *                    GetPlayers_ExcludeDead - do not include dead clients
 *                    GetPlayers_ExcludeAlive - do not include alive clients
 *                    GetPlayers_ExcludeBots - do not include bots
 *                    GetPlayers_ExcludeHuman - do not include human clients
 *                    GetPlayers_MatchTeam - match with team
 *                    GetPlayers_MatchNameSubstring - match with part of name
 *                    GetPlayers_CaseInsensitive - match case insensitive
 *                    GetPlayers_ExcludeHLTV - do not include SourceTV proxies
 *                    GetPlayers_IncludeConnecting - include connecting clients
 * @param team      String to match against if the GetPlayers_MatchTeam or GetPlayers_MatchNameSubstring flag is specified
 *
 * @return          Number of clients on the server that match the specified flags
 */
stock _get_playersnum_ex(GetPlayersFlags:flags = GetPlayers_None, const buffer[] = "") {
    new num;
    _get_players_ex(_, num, flags, buffer);
    return num;
}
stock TeamName:TeamFromName(const team[], bool:caseSensitive = true) {
    if(strcmp(team, "TERRORIST", caseSensitive) == 0)
        return TEAM_TERRORIST;
    if(strcmp(team, "CT", caseSensitive) == 0)
        return TEAM_CT;
    if(strcmp(team, "SPECTATOR", caseSensitive) == 0)
        return TEAM_SPECTATOR;
    
    return TEAM_UNASSIGNED;
}
 
Последнее редактирование:
Сообщения
1,315
Реакции
366
Предупреждения
1
Помог
20 раз(а)
wopox1337, это точно хорошая идея? Вроде все всегда топили за дефолтный гетплеерс, якобы потому что он лучше тем, что цикл выполняется на cpp, и лишение игроки там же отсекается, а тут ты кучу нативов передергал. Не понимаю тогда
 
Последнее редактирование модератором:
Сообщения
639
Реакции
554
Помог
7 раз(а)
Nordic Warrior, на сколько я помню, он не сторонник экономии на спичках, лишь только там где это действительно необходимо, и с этим вопросом я с ним солидарен
 
Последнее редактирование модератором:
Сообщения
904
Реакции
729
Предупреждения
1
Помог
9 раз(а)
Nordic Warrior, get_players то же самое делает.
https://github.com/alliedmodders/am...35426053db8dd7f8902/amxmodx/amxmodx.cpp#L2346
P.S. в сколько долей там разница между циклом в амхх и цпп?
24 Апр 2020
wopox1337, внеси ясность:
из за его основания на user messages
24 Апр 2020
В is_user_alive и подобных нативах используется:
https://github.com/s1lentq/ReGameDL...010984b788a/regamedll/dlls/player.h#L360-L361
Что, собственно, используется и в amxx get_players, тогда в чем профит?
 
Последнее редактирование модератором:
  • Нравится
Реакции: voed
Сообщения
2,389
Реакции
2,459
Помог
56 раз(а)
Сообщения
2,275
Реакции
2,523
Помог
58 раз(а)
d3m37r4, на самом деле это та же проблема, что и с get_user_team. Оно то и понятно. В разных модах команды по разному называются. Но из-за этого оно часто бажит и отдает неактуальные данные. Особенно если есть плагины изменяющые команду игрока отправляя свое сообщение, которое не перехватывет амхх.
 
Последнее редактирование модератором:
Сообщения
2,389
Реакции
2,459
Помог
56 раз(а)
... если иметь бОльшую выборку серверов. И воткнуть логирование.
24 Апр 2020
В is_user_alive и подобных нативах используется:
не было задачи полностью заменить. Места, которые приемлимы - я не трогал.
 
Последнее редактирование модератором:

Garey

ninjaCow
Сообщения
267
Реакции
676
Помог
4 раз(а)
Код для конвертации ближайшего тона HUE <-> RGB, может использоватся для topcolor, bottomcolor.
Код:
stock HUEtoRGB(hue, Float:rgb[3])
{
    rgb[0] = (hue / 255.0) + 1.0 / 3.0;
    rgb[1] = (hue / 255.0);
    rgb[2] = (hue / 255.0) - 1.0 / 3.0;

    for (new i = 0; i < 3; i++)
    {
        if (rgb[i] < 0.0)
        {
            rgb[i] += 1.0;
        }
        if (rgb[i] > 1.0)
        {
            rgb[i] -= 1.0;
        }
        if (6.0 * rgb[i] < 1)
        {
            rgb[i] = rgb[i] * 6.0
            continue;
        }

        if (2.0 * rgb[i] < 1)
        {
            rgb[i] = 1.0;
            continue;
        }

        if (3.0 * rgb[i] < 2.0)
        {
            rgb[i] = ((2.0 / 3.0) - rgb[i]) * 6.0
            continue;
        }

        rgb[i] = 0.0;
    }
    rgb[0] *= 255.0;
    rgb[1] *= 255.0;
    rgb[2] *= 255.0;
}


stock RGBtoHUE(Float:rgb[3])
{
    new Float:r = rgb[0] / 255.0;
    new Float:g = rgb[1] / 255.0;
    new Float:b = rgb[2] / 255.0;
    new Float:cmax = floatmax(r, floatmax(g, b));
    new Float:cmin = floatmin(r, floatmin(g, b));
    new Float:delta = cmax - cmin;
    new Float:H = 1.0;
    if (!delta)
    {
        // undefined color seams like white or black which dont exists
        return 0;
    }
    if (r == cmax)
    {
        H = (g - b) / delta;
    }
    else if (g == cmax)
    {
        H = 2.0 + (b - r) / delta;
    }
    else
    {
        H = 4.0 + (r - g) / delta;
    }

    H /= 6.0;

    if (H < 0.0)
    {
        H += 1;
    }

    return floatround(H * 255);
}
 
Сообщения
2,275
Реакции
2,523
Помог
58 раз(а)
Способ сменить класснейм у ентити загруженой с карты. Пример перевод с armoury_entity в item_airbox
Код:
#include <amxmodx>
#include <fakemeta>

new FwdKeyValue;

public plugin_precache() {
    FwdKeyValue = register_forward(FM_KeyValue, "KeyValue_Pre", false);
}

public plugin_init() {
    unregister_forward(FM_KeyValue, FwdKeyValue, false);
}

public KeyValue_Pre(const ent, const kvd) {
    static value[32];
    get_kvd(kvd, KV_KeyName, value, charsmax(value));
    if (strcmp(value, "classname") != 0) {
        return FMRES_IGNORED;
    }
    get_kvd(kvd, KV_Value, value, charsmax(value));
    if (strcmp(value, "armoury_entity") != 0) {
        return FMRES_IGNORED;
    }
    set_kvd(kvd, KV_Value, "item_airbox");
    return FMRES_HANDLED;
}
 
Сообщения
2,275
Реакции
2,523
Помог
58 раз(а)
d3m37r4 задал вопрос можно ли выдать кастом оружие (ну например weapon_bazuka) с помощю rg_give_item. Привожу пример жуткого костыля
Код:
#include <amxmodx>
#include <fakemeta>
#include <reapi>

new const CLASS_NAME[] = "custom_deagle";

new StrIndex;

public plugin_init() {
    register_clcmd("radio3", "CmdRadio3");
    register_forward(FM_CreateNamedEntity, "CreateNamedEntity_Pre", 0);
    StrIndex = engfunc(EngFunc_AllocString, "weapon_deagle");
}

public CmdRadio3(const id) {
    rg_give_item(id, CLASS_NAME);
    return PLUGIN_HANDLED;
}

public CreateNamedEntity_Pre(const classIndex) {
    static className[32];
    global_get(glb_pStringBase, classIndex, className, charsmax(className));

    if (strcmp(className, CLASS_NAME) != 0) {
        return FMRES_IGNORED;
    }

    new ent = engfunc(EngFunc_CreateNamedEntity, StrIndex);
    set_entvar(ent, var_impulse, 1);
    forward_return(FMV_CELL, ent);
    return FMRES_SUPERCEDE;
}
 
Сообщения
25
Реакции
21
Код:
#define PDATA_SAFE                        2
#define MAX_ITEM_TYPES                    6

#define IsValidEntity(%0)                bool: ( pev_valid( %0 ) == PDATA_SAFE )

stock bool: UTIL_RemoveItemByName( const pPlayer, const szItemName[ ] )
{
    new pItem = UTIL_GetItemByName( pPlayer, szItemName );

    new pActiveItem = get_pdata_cbase( pPlayer, m_pActiveItem, linux_diff_player );
    if ( IsValidEntity( pActiveItem ) && pActiveItem == pItem )
        ExecuteHamB( Ham_Weapon_RetireWeapon, pItem );

    if ( !ExecuteHamB( Ham_RemovePlayerItem, pPlayer, pItem ) )
        return false;

    set_pev( pPlayer, pev_weapons, pev( pPlayer, pev_weapons ) & ~( 1 << get_pdata_int( pItem, m_iId, linux_diff_weapon ) ) );

    ExecuteHamB( Ham_Item_Kill, pItem );

    return true;
}

stock UTIL_GetItemByName( const pPlayer, const szItemName[ ] )
{
    for ( new i, szClassName[ 20 ], pItem; i < MAX_ITEM_TYPES; i++ )
    {
        pItem = get_pdata_cbase( pPlayer, m_rpgPlayerItems + i, linux_diff_player );

        while ( IsValidEntity( pItem ) )
        {
            pev( pItem, pev_classname, szClassName, charsmax( szClassName ) );

            if ( equal( szClassName, szItemName ) )
                return pItem;

            pItem = get_pdata_cbase( pItem, m_pNext, linux_diff_weapon );
        }
    }

    return -1;
}
 

Pokemoshka

pika pika
Сообщения
1,660
Реакции
1,356
Помог
27 раз(а)
Ruby, краткое описание бы для чего код
 
Сообщения
170
Реакции
154
Помог
3 раз(а)
Pokemoshka, удаление оружие по его названию из инвенторя игрока
 

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

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