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

d3m37r4

111111
Сообщения
1,420
Реакции
1,162
Помог
10 раз(а)
Спавн армори энтити
Без названия.gif
Код:
// ArmouryItemPack, see cssdk_const.inc
spawnArmouryEntity(const ArmouryItemPack:armouryItem, const armouryCount, const Float:origin[3], bool:blockPickup = false) {
    new ent = rg_create_entity("armoury_entity");
   
    if(is_nullent(ent)) {
        return NULLENT;
    }
   
    set_member(ent, m_Armoury_iItem, ArmouryItemPack:armouryItem);
    set_member(ent, m_Armoury_iCount, armouryCount);
    set_entvar(ent, var_solid, blockPickup ? SOLID_NOT : SOLID_TRIGGER);

    engfunc(EngFunc_SetOrigin, ent, origin);
    dllfunc(DLLFunc_Spawn ,ent );

    return ent;
}
Код:
#include <amxmodx>
#include <fakemeta>
#include <reapi>

const Float:SpawnDist = 200.0     // in units

public plugin_init() {
    register_concmd("say wpn", "cmdSpawnArmoury");
}

public cmdSpawnArmoury(id) {
    new Float:originStart[3];
    get_entvar(id, var_origin, originStart);

    new Float:originEnd[3]
    getCoordPointInDirView(id, SpawnDist, originEnd);

    // ArmouryItemPack, see cssdk_const.inc
    if(spawnArmouryEntity(ARMOURY_AK47, 1, originEnd) == NULLENT) {
        log_amx("Invalid entity index");
    }
}

spawnArmouryEntity(const ArmouryItemPack:armouryItem, const armouryCount, const Float:origin[3], bool:blockPickup = false) {
    new ent = rg_create_entity("armoury_entity");
   
    if(is_nullent(ent)) {
        return NULLENT;
    }
   
    set_member(ent, m_Armoury_iItem, ArmouryItemPack:armouryItem);
    set_member(ent, m_Armoury_iCount, armouryCount);
    set_entvar(ent, var_solid, blockPickup ? SOLID_NOT : SOLID_TRIGGER);

    engfunc(EngFunc_SetOrigin, ent, origin);
    dllfunc(DLLFunc_Spawn ,ent );

    return ent;
}

stock getCoordPointInDirView(const index, const Float:dist, Float:output[3]) {
    new Float:start_origins[3];
    pev(index, pev_origin, start_origins);

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

    new Float:end_origins[3];
    end_origins[0] = start_origins[0] + dist * floatcos(angles[1], degrees) * floatabs(floatcos(angles[0], degrees));
    end_origins[1] = start_origins[1] + dist * floatsin(angles[1], degrees) * floatabs(floatcos(angles[0], degrees));
    end_origins[2] = start_origins[2];

    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];
}
 

Albertio

скриптизёр
Сообщения
336
Реакции
392
Предупреждения
5
Помог
7 раз(а)
Дистанция между игроком/объектом и "потолком" карты либо помещения.

Код:
stock Float:fm_distance_to_ceiling(index, ignoremonsters = 1) {
    new Float:start[3], Float:dest[3], Float:end[3];
    pev(index, pev_origin, start);
    dest[0] = start[0];
    dest[1] = start[1];
    dest[2] = 8191.0;

    engfunc(EngFunc_TraceLine, start, dest, ignoremonsters, index, 0);
    get_tr2(0, TR_vecEndPos, end);

    pev(index, pev_absmin, start);
    new Float:ret = start[2] - end[2];

    return ret < 0 ? floatabs(ret) : 0.0;
}
 
Последнее редактирование:
Сообщения
1,481
Реакции
1,476
Помог
2 раз(а)
Код:
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
  
new g_fwd_FM_Spawn
  
public plugin_precache()
   g_fwd_FM_Spawn = register_forward( FM_Spawn, "fwd_spawn" )
  
public plugin_init()
{     
   unregister_forward( FM_Spawn, g_fwd_FM_Spawn )
}
  
public fwd_spawn( iEnt )
{
   if( !pev_valid( iEnt ) )
      return FMRES_IGNORED
      
   new i, szClassName[ 32 ]
   new szRemovingEntities[][] =
   {
      "hostage_entity",       
      "func_hostage_rescue",
      "info_hostage_rescue"
   }
      
   pev( iEnt, pev_classname, szClassName, charsmax( szClassName ) )
  
   for( i = 0; i < sizeof szRemovingEntities; ++i )
   {
      if( equal( szClassName, szRemovingEntities[ i ] ) )
      {
         engfunc( EngFunc_RemoveEntity, iEnt )
            
         return FMRES_SUPERCEDE
      }
   }
   return FMRES_IGNORED
}
Код:
#include <amxmodx>
#include <engine>
#include <hamsandwich>
 
new mapname[31]
 
#define MAP     "cs_discounter"   // Название карты,где будут убраны Заложники
    
public plugin_precache()
{   
          get_mapname(mapname,31)
          if(!equali(mapname, MAP)) return 
  
          RegisterHam(Ham_Spawn, "hostage_entity", "Remove_Hostage", true);
}
  
public Remove_Hostage(Ent)
          remove_entity(Ent);
P.S. Если было и повтор - просьба удалить
 
Сообщения
1,481
Реакции
1,476
Помог
2 раз(а)
stalin_alex попросил меня предоставить код на удаление дропнутых Щипцов
Скину сюда для всех,может кому-то и пригодится

#define THIGHTPACK_TIME 10.0 // Через сколько секунд удалять Щипцы

Код:
#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <hamsandwich>

#define PLUGIN_NAME                      "THIGHTPACK DELETE"
#define PLUGIN_VERSION                           "1.0"
#define PLUGIN_AUTHOR                          "MayroN"

#define THIGHTPACK_TIME    10.0     //    Через сколько секунд удалять Щипцы

public plugin_init()
{
    register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR);

    register_forward(FM_SetModel, "Thighpack_ItemModel")
    RegisterHam(Ham_Think, "item_thighpack", "Remove_Thighpack")
}

public Thighpack_ItemModel(const iEntity)
{
    if(!pev_valid(iEntity))
        return FMRES_IGNORED;

    #define m_rgpPlayerItems2 34
    #define m_iId 43

    static szClassName[32]
    pev(iEntity, pev_classname, szClassName, charsmax(szClassName))

    if(equal(szClassName, "item_thighpack"))  
    {
        set_pev(iEntity, pev_nextthink, get_gametime() + THIGHTPACK_TIME);  
    }
   
    return FMRES_IGNORED;
}

public Remove_Thighpack(iEntity)
{
    if (!pev_valid(iEntity))
        return HAM_IGNORED;

    set_pev(iEntity, pev_flags, FL_KILLME);

    return HAM_SUPERCEDE;
}
 
Последнее редактирование:

d3m37r4

111111
Сообщения
1,420
Реакции
1,162
Помог
10 раз(а)
Albertio, чо мне мешает хеш подсмотреть этот?
 
Сообщения
2,713
Реакции
2,993
Помог
59 раз(а)
Код:
stock CreateTranslation(const lang[3], const key[], const value[]) {
  AddTranslation(lang, CreateLangKey(key), value)
}
Usage:
Код:
  enum Lang_s {
    key[128],
    lang[3],
    value[1024]
  }

  new const langs[][Lang_s] = {
    //
    { "Player_Cash_Award_ExplainSuicide_YouGotCash", "en", "(You were awarded ^4+$%i^1 compensation for the suicide of %n)" },
    { "Player_Cash_Award_ExplainSuicide_YouGotCash", "ru", "(вы получаете компенсацию ^4+$%i^1 за самоубийство %n)" },
  }

  for(new i; i < sizeof langs; i++) {
    CreateTranslation(langs[i][lang], langs[i][key], langs[i][value])
  }

 
 client_print(0, print_chat, "%l", "Player_Cash_Award_ExplainSuicide_YouGotCash", 123, 0)
 
Сообщения
1,661
Реакции
1,486
Помог
24 раз(а)
Чересчур простая функция-велосипед, но зачем-то каждый раз заново пишется.

Что делает? Возвращает противоположную игровую команду.
Использование: Для TR вернет CT и наоборот, TEAM_UNASSIGNED в случае неудачи.
Пример:
new TeamName:team = getReversePlayableTeam(get_member(id, m_iTeam))

Код:
TeamName:getReversePlayableTeam(TeamName:team) {
    switch (team) {
        case TEAM_TERRORIST: {
            return TEAM_CT
        }
        case TEAM_CT: {
            return TEAM_TERRORIST
        }
    }
    return TEAM_UNASSIGNED
}
 
Последнее редактирование:
Сообщения
73
Реакции
60
Помог
1 раз(а)
При работе с получаемыми пакетами по HTTP нужен был JSON парсер, написал самую простую функцию

Описание
Сколько бы не пробовал, без strtok не обойтись. Amxmodx просто ломается и EOS не реагирует.
Поэтому тут танец с бубном.

Функция ищет в строке вхождение и выход нужной строки (сектор/секцию) и копирует его в массив.
Пример для JSON:
У нас есть строка: Locatin: url.ru {"key":"result"} 0 0
Как же нам извлечь JSON? Использовать такую конфигурацию:
C++:
ExtractDataFromString(szString, szOutPut, charsmax(szOutPut), '{', '}');
И тогда наш массив szOutPut будет содержать чистый JSON.
Тут нужно быть осторожным, ибо если в строке будет '{' или '}' что не входят в JSON-сектор, он извлечёт не те данные.

szString[] : Массив со строкой в котором будет извлечение желаемого сектора.
szOutPut[] : Массив строчного типа в который мы извлечём сектор, который мы ищем.
iLen : Длина массива szOutPut.
iStartChar : Символ для начала вхождения в сектор.
iCloseChar : Символ который говорит что вхождение окончено (выход из сектора), дальше в строке идет текст который нам не нужен.
bClearEntry : Если указать 'true', то сектор будет получен без символов вхождения и выхода сектора,
'false' получает сектор вместе с iStartChar и iCloseChar.
iJumpPos : С какого символа из массива szString начинать поиск.

@ return : возвращает номер символа на котором закончился сектор или 0, если сектор не найден

C++:
stock ExtractDataFromString(szString[], szOutPut[], iLen, iStartChar = '{', iCloseChar = '}', bool:bClearEntry = false, iJumpPos = 0) {
    new iStartPos = -1, iLenStr = strlen(szString);
    for(new iChar = iJumpPos; iChar <= iLenStr; iChar++) {
        if(iStartPos == -1 && szString[iChar] == iStartChar) iStartPos = iChar;
        if(iStartPos != -1 && szString[iChar] == iCloseChar) {
            if(bClearEntry) iStartPos++;
            static szBuffer[2048], szNull[2];
            formatex(szBuffer, charsmax(szBuffer), szString[iStartPos]);
            strtok(szBuffer, szBuffer, charsmax(szBuffer), szNull, charsmax(szNull), iCloseChar);
            if(!bClearEntry) add(szBuffer, charsmax(szBuffer), fmt("%c", iCloseChar));
            copy(szOutPut, iLen, szBuffer);
            return iChar;
        }
    }
    return 0;
}
19 Сен 2021
Создание бекапа конфигов

Бекап менеджер для .cfg и .txt
Его основная задача - сделать бекап ваших кваров и ключей LANG.
Пример: вы часто добавляете новые квары, а заливать с заменой cfg не желаете, так как старые настройки кваров собьются. Данный inc решает все эти проблемы, он возвращает из бекапа квары/lang только те, что были в момент бекапа. Новые квары/ключи не трогает.

Делал для себя, сразу говорю, мне оно нужно редко и никакой нагрузки не имеет, так как используется только тогда, когда это нужно. Таким образом можно бекапить ваши настройки и не боятся их "просрать". С [en] и [ru] если они в одном файле есть косяки, но думаю никто 2+ языка не использует. (Да и вроде секцию языка что выше не портит)

прописать в plugin_init:
public plugin_init()
{
bcfg_init();
}

Данный inc нужно подрубить к одному любому плагину.

Команды сервера:

bcfg help - справка

bcfg add <названиебекапфайла.txt> <тип:cfg или data> <путь к файлу, который мы бекапим>
Важно! bcfg add: если мы пишем cfg, то путь к файлу начинается с configs/, а если data, то с data/.
Пример с JBE cfg: bcfg add "all_cvars_bckp.txt" cfg "jb_engine/all_cvars.cfg"
Пример с JBE data: bcfg add "jbe_core_bckp.txt" data "lang/jbe_core.txt"
Важно! bcfg add: команда лишь подготавливает файлы до бекапа!

bcfg create - создаёт бекап файлов, которые мы подготовили через bcfg add

bcfg return - начинает восстановление из резервного копирования файлов (если они есть)

команды bcfg ujbl start и bcfg ujbl return убираем сами. Они для примера, как нужно бекапить соазу большое количество файлов.

При всём желании можно сделать автоматическое резервное копирование раз в неделю или месяц. Как в общем пожелаете. Дальше от вашей фантазии зависит.
19 Сен 2021
Ещё шняга есть, которая для меня полезна: автодобавления ланг ключа, по его названию. Не очень полезно, но допустим для систем как Shop с автодобавлением предметов (тот же Zombie) выручает

Код добавляет ключ в .txt (lang) файл, исходя от самого названия ключа

пример:
test("ITEM_MP5", 1)

функция/код возьмёт ключ "ITEM_MP5", уберёт мусор (идентификацию мусора вы сами добавляете) и запишет LANG ключ в файл, если данного ключа нет

ITEM_MP5 ->

ITEM_MP5 = item mp5

C++:
/*
    szLang -> строка, по типу "ITEM_MP5"
*/

#define GameLangDir "addons/amxmodx/data/lang/jb_engine/jbe_games.txt"
    if( file_exists( GameLangDir ) ) {
        new szBuffer[ 128 ], iLine, iMaxLen, bool: bGameAdd;
        while( read_file( GameLangDir, iLine++, szBuffer, charsmax( szBuffer ), iMaxLen ) )
        {
            if( equal( szBuffer, "[ru]" ) || equal( szBuffer, "[en]" ) )
                continue;
            
            if( containi( szBuffer, szLang ) != -1 ) {
                bGameAdd = true; break;
            }
        }
        
        if( !bGameAdd ) {
            format( szBuffer, charsmax( szBuffer ), szLang );
    
            while( replace( szBuffer, charsmax( szBuffer ), "ITEM_", "" ) ) {}
            while( replace( szBuffer, charsmax( szBuffer ), "_", " " ) ) {}
            
            strtolower( szBuffer ); ucfirst( szBuffer );
            format( szBuffer, charsmax( szBuffer ), "%s = %s", szLang, szBuffer );
            write_file( GameLangDir, szBuffer, -1 );
        }
    }
19 Сен 2021
----
Отступление: делал для себя, если есть нарекания в работе кода, по тому же примеру "Это можно лучше сделать" -- меня абсолютно не волнует. Если можно лучше -- делайте, меня же всё устраивает
 

Вложения

Сообщения
645
Реакции
222
Помог
11 раз(а)
AnonymousAmx, а вот ты под каким ником ты сидишь))
 
Сообщения
73
Реакции
60
Помог
1 раз(а)
@d3m37r4,я не нашёл, мож невнимательный. Типо у меня мусорная строка была, не только с JSON. Ну, даже если и есть, сток пригодится не только для поиска JSON
 
Сообщения
775
Реакции
291
Помог
11 раз(а)
d3m37r4, единственный минус спавна, в конце раунда надо удалять иначе будет на том же месте в новом раунде
 
Сообщения
2,491
Реакции
2,790
Помог
61 раз(а)
При работе с получаемыми пакетами по HTTP нужен был JSON парсер, написал самую простую функцию
Заголовки от тела отделены двойным \n\n. Это по стандарту. А по факту используйте grip или curl модули. Для curl-а также нужен модуль json, который включен по умолчанию в 1.9.0 версию
 
Сообщения
2,713
Реакции
2,993
Помог
59 раз(а)
UTIL_ShowScores() - форсивное отображение таблицы счёта игрокам.

Код:
#if defined _showscores_util_included
    #endinput
#endif

#define _showscores_util_included

// UTIL_ScoreBoard
static stock const TASKID_ShowScores_Show = (MAX_PLAYERS * 4)
static stock const TASKID_ShowScores_Hide = (MAX_PLAYERS * 5)

@ShowScores_Show(const taskID) {
    new client = (taskID - TASKID_ShowScores_Show)
    client_cmd(client, "+showscores")
}

@ShowScores_Hide(const taskID) {
    new client = (taskID - TASKID_ShowScores_Hide)

    remove_task(client + TASKID_ShowScores_Show)
    client_cmd(client, "-showscores")
}

/**
 * Shows the client a score board.
 *
 * @param index         Client index
 * @param duration      Show duration
 * @param freq          Update frequency. Protection from being hidden by the client.
 *
 * @noreturn
 */
stock UTIL_ShowScores(const index = 0, const Float: duration = 10.0, const Float: freq = 0.3) {
    if (index < 0 || index > MaxClients)
        return

    for (new i = 1; i <= MaxClients; i++) {
        if (index != 0)
            i = index

        new showTaskID = (i + TASKID_ShowScores_Show)
        if (task_exists(showTaskID)) {
            @ShowScores_Hide(showTaskID)

            remove_task(i + TASKID_ShowScores_Hide)
        }

        client_cmd(i, "+showscores")

        set_task(freq, "@ShowScores_Show",
            (i + TASKID_ShowScores_Show),
            .flags = "a",
            .repeat = floatround(duration / freq, floatround_floor))

        set_task(duration, "@ShowScores_Hide",
            (i + TASKID_ShowScores_Hide))

        if (index != 0)
            return
    }
}
 

Вложения

Последнее редактирование:
Сообщения
2,713
Реакции
2,993
Помог
59 раз(а)
Пример реализации аргумента функции с динамическим типом тегом, а так же конвертируемым в нужный тег с помощью tagof
Код:
stock UTIL_RoundTimeALL(const {_, Float}: tmRemaining, const arg_type = tagof(tmRemaining)) {
    static msgId_RoundTime;
    if (!msgId_RoundTime) {
        msgId_RoundTime = get_user_msgid("RoundTime");
    }

    message_begin(MSG_ALL, msgId_RoundTime);
    write_short((arg_type == tagof(Float:)) ? floatround(tmRemaining) : tmRemaining);
    message_end();
}
P.S: варнинг убрать не получилось, возможно у вас получится ?
 
Последнее редактирование:
Сообщения
451
Реакции
254
Помог
9 раз(а)
Валялся в облаке, источник не помню

Код:
#define SECONDS_IN_HOUR 3600
#define SECONDS_IN_MINUTE 60

enum access_time_struct {
    TIME_HOUR,
    TIME_MINUTE,
    TIME_SECOND
};

stock set_task_runtime(time[11], const func[], id = 0, param[] = "", len = 0, flags[] = "")    {
    new eDataTime[access_time_struct];

    time(eDataTime[TIME_HOUR], eDataTime[TIME_MINUTE], eDataTime[TIME_SECOND]);

    new iCurrentSeconds = ((eDataTime[TIME_HOUR] * SECONDS_IN_HOUR) + (eDataTime[TIME_MINUTE] * SECONDS_IN_MINUTE) + eDataTime[TIME_SECOND]);

    replace_string(time, charsmax(time), ":", " ");

    new h[5], m[5], s[5];
    parse(time,
        h, charsmax(h),
        m, charsmax(m),
        s, charsmax(s)
    );

    eDataTime[TIME_HOUR] = (str_to_num(h) * SECONDS_IN_HOUR);
    eDataTime[TIME_MINUTE] = (str_to_num(m) * SECONDS_IN_MINUTE);
    eDataTime[TIME_SECOND] = str_to_num(s);

    new iRunSeconds = ((eDataTime[TIME_HOUR] * SECONDS_IN_HOUR) + (eDataTime[TIME_MINUTE] * SECONDS_IN_MINUTE) + eDataTime[TIME_SECOND]);

    new iTotalSeconds = iRunSeconds - iCurrentSeconds;

    if (iTotalSeconds <= 0) {
        iTotalSeconds = iCurrentSeconds - iRunSeconds;
    }

    return set_task(float(iTotalSeconds), func, id, param, len, flags);
}
set_task_runtime("23:00:00", "TaskFunc_Func")
 
Сообщения
1,481
Реакции
1,476
Помог
2 раз(а)
Получение количества прошедших дней с указанной даты по сегодняшний день.
Код:
stock UTIL_GetElapsedDays(const date[])
{
    return (get_systime() - parse_time(date, "%d.%m.%Y", -1)) / 86400/*SECONDS_IN_DAY*/;
}
Получение количества прошедших дней с даты по дату.
Код:
stock UTIL_GetElapsedDays(const date_ceil[], const date_floor[])
{
    return (parse_time(date_ceil, "%d.%m.%Y", -1) - parse_time(date_floor, "%d.%m.%Y", -1)) / 86400/*SECONDS_IN_DAY*/;
}
 

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

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