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

Сообщения
443
Реакции
319
Помог
13 раз(а)
И не нужно использовать глобальные. Вы можете содержимое гарантировать? Нет. А содержимое трейса при врезке? Нет.
 
Последнее редактирование модератором:
Сообщения
1,698
Реакции
1,510
Помог
26 раз(а)
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,751
Реакции
3,016
Помог
61 раз(а)
не доверяю 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;
}
 
Последнее редактирование:
Сообщения
3,579
Реакции
1,569
Помог
137 раз(а)
wopox1337, это точно хорошая идея? Вроде все всегда топили за дефолтный гетплеерс, якобы потому что он лучше тем, что цикл выполняется на cpp, и лишение игроки там же отсекается, а тут ты кучу нативов передергал. Не понимаю тогда
 
Последнее редактирование модератором:
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
Nordic Warrior, на сколько я помню, он не сторонник экономии на спичках, лишь только там где это действительно необходимо, и с этим вопросом я с ним солидарен
 
Последнее редактирование модератором:

d3m37r4

111111
Сообщения
1,449
Реакции
1,175
Помог
10 раз(а)
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,751
Реакции
3,016
Помог
61 раз(а)
Сообщения
2,491
Реакции
2,794
Помог
61 раз(а)
d3m37r4, на самом деле это та же проблема, что и с get_user_team. Оно то и понятно. В разных модах команды по разному называются. Но из-за этого оно часто бажит и отдает неактуальные данные. Особенно если есть плагины изменяющые команду игрока отправляя свое сообщение, которое не перехватывет амхх.
 
Последнее редактирование модератором:
Сообщения
2,751
Реакции
3,016
Помог
61 раз(а)
... если иметь бОльшую выборку серверов. И воткнуть логирование.
24 Апр 2020
В is_user_alive и подобных нативах используется:
не было задачи полностью заменить. Места, которые приемлимы - я не трогал.
 
Последнее редактирование модератором:

Garey

ninjaCow
Сообщения
422
Реакции
1,056
Помог
10 раз(а)
Код для конвертации ближайшего тона 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);
}
 
Сообщения
91
Реакции
141
Помог
1 раз(а)
Drag and Drop support
Palette window
Palette export: JASC, raw formats
Right bmp exporting
Right .qc file exporting
And other useful stuff
c/c++ + winapi32
Supports only valid 8 bit bmps
Supports given palette
Auto padding recognising (3 types)
Parsing dir with bmps
Parsing qc files
Allow different types of path's in .qc file, absolute, relative
Output path
Colored help info (-h param)
Too much fixes
It's really fast
You can get more useful info with -h param.

ARJegyUUehU.jpg
Sprite_Viewer_BRgYHSZL4l.png
Sprite_Viewer_8gDVpp5ges.png
Sprite_Viewer_qTMXxpmDSg.png
 

Download all Attachments

Сообщения
443
Реакции
319
Помог
13 раз(а)
https://dev-cs.ru/threads/222/post-79158

v0.0.3
Fix undefined behaviour on array overflow. (32 players)

v0.0.2
Fixed loading thru modules.ini without reqlib. (никогда никому не понадобится, но для тех кто упорно пытался)

Сoвeтую oбнoвится тeм y кoгo сeрвeрa с 32 игрoкaми. Слyчaйнo зaбыл кoe гдe измeнить 32 нa 33 пepeд peлизoм в пepвый paз.
 

Download all Attachments

Сообщения
2,491
Реакции
2,794
Помог
61 раз(а)
Способ сменить класснейм у ентити загруженой с карты. Пример перевод с 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,491
Реакции
2,794
Помог
61 раз(а)
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;
}
 
Сообщения
192
Реакции
148
Помог
1 раз(а)
Удаление оружие по его названию из инвентаря игрока

Код:
#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;
}
 
Последнее редактирование модератором:
Сообщения
225
Реакции
90
Помог
1 раз(а)
Может быть пригодится кому. Макрос итеративного перебора хэш-таблицы.
C++:
#define FOR_ITERATE_TRIE(%0) for(new TrieIter:iter = TrieIterCreate(%0); !TrieIterEnded(iter); TrieIterNext(iter))
 
Сообщения
1,698
Реакции
1,510
Помог
26 раз(а)
Ruby, можно просто rg_drop_item или rg_remove_item.
 
Последнее редактирование модератором:
  • Нравится
Реакции: Ayk
Сообщения
225
Реакции
90
Помог
1 раз(а)
fantom, это обязательно? Тогда косяк.
Можно за циклом создавать итератор и внести его как аргумент в макрос. Так ещё и поддержка вложенности циклов появится.
 
Последнее редактирование модератором:
Сообщения
1,291
Реакции
2,288
Помог
57 раз(а)
Код:
#define FOR_ITERATE_TRIE(%0) for(new TrieIter:iter = TrieIterCreate(%0); !TrieIterEnded(iter) || !TrieIterDestroy(iter); TrieIterNext(iter))
Получается, Что пока конец таблицы не достигнут, оно будет останавливаться на
Код:
!TrieIterEnded(iter)
А когда достигнет конца, отработает
Код:
!TrieIterDestroy(iter)
Вернув true (успешный дестрой) что не будет удовлетворять условию, и получим и дестрой и конец цикла

Но тут в любом случае надо помнить о выходе из цикла раньше естественного конца. Т.е. помнить об iter и о необходимости его задестроить. Макрос своим использованием его не упоминает (упоминает тока объявлением). Т.е. не интуитивно и сомнительно, на мой взгляд.
 
Последнее редактирование модератором:

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

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