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

Сообщения
192
Реакции
148
Помог
1 раз(а)
DamageDecal из ReGameDLL
Код:
stock DamageDecal( const index )
{
    new rendermode = get_entvar( index, var_rendermode );

    if ( rendermode == kRenderTransAlpha )
        return -1;

    static glassdecal; if ( !glassdecal ) glassdecal = engfunc( EngFunc_DecalIndex, "{bproof1" );

    if ( rendermode != kRenderNormal )
        return glassdecal;

    static decal; if ( !decal ) decal = engfunc( EngFunc_DecalIndex, "{shot1" );

    return ( decal - random_num( 0, 4 ) );
}
Чем не устраивает Ham_DamageDecal?
Этим:
Безымянный.jpg
 
Сообщения
1,487
Реакции
1,480
Помог
2 раз(а)
Я давно хотел найти, как правильно задать остаток в минутах и секундах,ибо видя множество плагинов где пишеться либо так - 15:43 или просто одно слово минут после цыфр )))
Код, о правильном остатке времени в чат... ( минута, минуты, минут | секунда, секунды, секунд )
Тестировал на стандартном плагине timeleft
Также если остаток времени меньше 1 минуты - пишет в чат только остаток в секундах

Сам Код
Код:
new words[][] = {"секунда", "секунды", "секунд"};

client_print(0,print_chat,"Итого %s",words[declOfNum(get_systime())]);

}

/ -------------------- /

declOfNum(number)
{
new cases[] = {2, 0, 1, 1, 1, 2};
return (number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5];
}
Пример на плагине
Код:
public sayTimeLeft(id)
{
    if (get_cvar_float("mp_timelimit"))
    {
        new a = get_timeleft()
        new words_minutes[][] = {"минута", "минуты", "минут"}, words_seconds[][] = {"секунда", "секунды", "секунд"}
        if (get_cvar_num("amx_time_voice"))
        {
            new svoice[128]
            setTimeVoice(svoice, 127, 0, a)
            client_cmd(id, "%s", svoice)
        }
                if((a / 60) > 0)
                    ColorChat(0, RED, "^4%L^1  •  ^3%d %s %d %s", LANG_PLAYER, "TIME_LEFT", (a / 60), words_minutes[declOfNum((a / 60))], (a % 60), words_seconds[declOfNum((a % 60))]);
                else
                    ColorChat(0, RED, "^4%L^1  •  ^3%d %s", LANG_PLAYER, "TIME_LEFT", (a % 60), words_seconds[declOfNum((a % 60))]);
    }
    else
              ColorChat(0, RED, "^4%L", LANG_PLAYER, "NO_T_LIMIT")
   
    return PLUGIN_CONTINUE
}

declOfNum(number)
{
new cases[] = {2, 0, 1, 1, 1, 2};
return (number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5];
}
Результат в игре
1.jpg

Выражаю огромную благодарность своему напарнику

Администрация рекомендует использовать лучший вариант: Склад полезного кода [GoldSrc]
 
Последнее редактирование модератором:
Сообщения
657
Реакции
229
Помог
11 раз(а)
MayroN, 2ой вариант, все проверки внутри стока
Код:
public count_down_timer()
{
    if(--g_iCountDown)
    {
        //g_iCountDown = секунды
        CenterMsgFix_PrintMsg(0, print_center, "Обратный отсчёт: %s",  CalculateElapsed(g_iCountDown));
    }
    else
    {
        CenterMsgFix_PrintMsg(0, print_center, "Обратный отсчёт закончен");
    }
   
}

CalculateElapsed(seconds) {
   new iMinutes, iSeconds, iChoice;
   new gszElapsed[64],iLen;
   static szMinutes[][] = {
      "минуту",
      "минуты",
      "минут"
   };
   static szSeconds[][] = {
      "секунду",
      "секунды",
      "секунд"
   };

   iMinutes = seconds / 60;
   iSeconds = seconds - iMinutes * 60;

   if (iMinutes) {
      switch (iMinutes) {    // correct case up to 20
         case 1    : iChoice = 0;
         case 2..4 : iChoice = 1;
         default   : iChoice = 2;
      }
      iLen += formatex(gszElapsed[iLen], charsmax(gszElapsed) - iLen, iSeconds ? "%d %s " : "%d %s", iMinutes, szMinutes[iChoice]);
   }
   if (iSeconds) {
      switch (iSeconds) {
         case 1, 21, 31, 41, 51 : iChoice = 0;
         case 2..4, 22..24, 32..34, 42..44, 52..54 : iChoice = 1;
         default : iChoice = 2;
      }
      iLen += formatex(gszElapsed[iLen], charsmax(gszElapsed) - iLen,  " %d %s", iSeconds, szSeconds[iChoice]);
   }
   return gszElapsed;
}

Администрация рекомендует использовать лучший вариант: Склад полезного кода [GoldSrc]
 
Последнее редактирование модератором:
Сообщения
2,713
Реакции
2,995
Помог
59 раз(а)
Print long string (>255 chars) in console:
Код:
#include <fakemeta>
stock SERVER_PRINT(const buffer[]) {
  for(new i, len = strlen(buffer); i < len; i+=255) {
    engfunc(EngFunc_ServerPrint, fmt("%-255s", buffer[i]));
  }
  engfunc(EngFunc_ServerPrint, "\n");
}
 
Последнее редактирование:
Сообщения
579
Реакции
338
Предупреждения
1
Помог
9 раз(а)
Замена взрыва звука у HE гранаты (replace he grenade explosion sound)
WARNING: Данный плагин удаляет звуки у эффекта TE_EXPLOSION. Не ставьте в своих плагинах framerate 30 (arg 7), которые используют эффект TE_EXPLOSION
p.s: хз, вроде всё ок работает. Можете поиграться с ATTN_EXPLODE_SOUND (слышимость звука на расстоянии).
Код:
#include <amxmodx>
#include <reapi>

const Float: ATTN_EXPLODE_SOUND = 0.5;
new const EXPLODE_SOUND[] = "grenades/hegrenade_explode.wav";

public plugin_init()
{
    register_message(SVC_TEMPENTITY, "msg_TempEntity");
    RegisterHookChain(RG_CGrenade_ExplodeHeGrenade, "CGrenade_ExplodeHeGrenade_Post", .post = true);
}

public plugin_precache()
{
    precache_sound(EXPLODE_SOUND);
}

public msg_TempEntity(iMsgId, iMsgDest, iMsgEntity)
{
    if(get_msg_arg_int(1) == TE_EXPLOSION)
    {
        if(get_msg_arg_int(7) == 30)
        {
            set_msg_arg_int(8, ARG_BYTE, get_msg_arg_int(8) | TE_EXPLFLAG_NOSOUND);
        }
    }
}

public CGrenade_ExplodeHeGrenade_Post(iEntity, iTrace, iBitsDamageType)
{
    if(is_nullent(iEntity))
    {
        return;
    }

    rh_emit_sound2(iEntity, 0, CHAN_VOICE, EXPLODE_SOUND, VOL_NORM, ATTN_EXPLODE_SOUND); // chain_weapon
}
 
Последнее редактирование:
Сообщения
225
Реакции
90
Помог
1 раз(а)
Только сегодня и только сейчас! "Цирковые волки на костыльных велосипедах"!
Мб это где-то есть, но я не найти.
Вектор скорости из точки fStart в направление точки fEnd длиной length.
C++:
create_velocity_vector(const Float:fStart[3], const Float:fEnd[3], const Float:length, Float:fOut[3])
{
    new Float:fDistance = get_distance_f(fStart, fEnd);
    fOut[0] = (fEnd[0] - fStart[0]) * (length / fDistance);
    fOut[1] = (fEnd[1] - fStart[1]) * (length / fDistance);
    fOut[2] = (fEnd[2] - fStart[2]) * (length / fDistance);
}
Координаты конца вектора fVector проложенного из точки fStart
C++:
get_end_vector(const Float:fVector[3], const Float:fStart[3], Float:fOut[3])
{
    fOut[0] = fVector[0] + fStart[0];
    fOut[1] = fVector[1] + fStart[1];
    fOut[2] = fVector[2] + fStart[2];
}
Точка на удалении fDifference от точки fEnd на прямой, которую образуют fStart и fEnd.
C++:
point_behind_point(const Float:fStart[3], const Float:fEnd[3], const Float:fDifference, Float:fOut[3])
{
     new Float:fDistance = get_distance_f(fStart, fEnd);
     create_velocity_vector(fStart, fEnd, fDistance + fDifference, fOut);
     get_end_vector(fOut, fStart, fOut);
}
 
Последнее редактирование:
Сообщения
392
Реакции
283
Помог
3 раз(а)
Получение цветов из JSON
C++:
const COLOR_SIZE = 3;
new const COLOR_LETTERS[COLOR_SIZE][] = {"R", "G", "B"};

// Является ли обьект/массив цветом
#define json_array_is_color(%1) json_is_array_of(%1,JSONNumber,COLOR_SIZE)
bool:json_object_is_color(const JSON:Obj){
    if(!json_is_object(Obj))
        return false;

    for(new i = 0; i < COLOR_SIZE; i++)
        if(!json_object_has_value(Obj, COLOR_LETTERS[i], JSONNumber))
            return false;
    return true;
}

// Получение цвета из элемента
bool:json_get_color(const JSON:Item, Color[COLOR_SIZE]){
    if(json_object_is_color(Item)){
        for(new i = 0; i < COLOR_SIZE; i++)
            Color[i] = json_object_get_number(Item, COLOR_LETTERS[i]);
    }
    else if(json_array_is_color(Item)){
        for(new i = 0; i < COLOR_SIZE; i++)
            Color[i] = json_array_get_number(Item, i);
    }
    else return false;

    for(new i = 0; i < COLOR_SIZE; i++)
        Color[i] = clamp(Color[i], 0, 255);
       
    return true;
}

// Проверка типов элементов массива
bool:json_is_array_of(const JSON:Arr, const JSONType:Type, const Size = -1){
    if(!json_is_array(Arr))
        return false;

    if(Size > json_array_get_count(Arr))
        return false;

    new JSON:v;
    new to = (Size == -1) ? json_array_get_count(Arr) : Size;
    for(new i = 0; i < to; i++){
        v = json_array_get_value(Arr, i);
        if(!(
            v != Invalid_JSON
            && json_get_type(v) == Type
        )){
            json_free(v);
            return false;
        }
        json_free(v);
    }
    return true;
}

// Получение цвета из элемента массива
bool:json_array_get_color(const JSON:Arr, const Index, Color[COLOR_SIZE]){
    new JSON:Item = json_array_get_value(Arr, Index);
    new bool:Res = json_get_color(Item, Color);
    json_free(Item);
    return Res;
}
+получение массива цветов
C++:
// Получение массива цветов
Array:json_get_color_list(const JSON:Item){
    new Color[COLOR_SIZE];
    new Array:List;

    if(json_get_color(Item, Color)){
        List = ArrayCreate(COLOR_SIZE, 1);
        ArrayPushArray(List, Color);
        return List;
    }

    if(!json_is_array(Item))
        return Invalid_Array;
   
    List = ArrayCreate(COLOR_SIZE, json_array_get_count(Item));

    for(new i = 0; i < json_array_get_count(Item); i++){
        if(json_array_get_color(Item, i, Color))
            ArrayPushArray(List, Color);
    }
    return List;
}

// Получение массива цветов из элемента обьекта
Array:json_object_get_color_list(const JSON:Obj, const Name[], const bool:DotNot = false){
    new JSON:Item = json_object_get_value(Obj, Name, DotNot);
    new Array:List = json_get_color_list(Item);
    json_free(Item);
    return List;
}
C++:
#include <amxmodx>
#include <json>

const COLOR_SIZE = 3;
new const COLOR_LETTERS[COLOR_SIZE][] = {"R", "G", "B"};

#define json_array_is_color(%1) json_is_array_of(%1,JSONNumber,COLOR_SIZE)
bool:json_object_is_color(const JSON:Obj){
    if(!json_is_object(Obj))
        return false;

    for(new i = 0; i < COLOR_SIZE; i++)
        if(!json_object_has_value(Obj, COLOR_LETTERS[i], JSONNumber))
            return false;
    return true;
}

bool:json_get_color(const JSON:Item, Color[COLOR_SIZE]){
    if(json_object_is_color(Item)){
        for(new i = 0; i < COLOR_SIZE; i++)
            Color[i] = json_object_get_number(Item, COLOR_LETTERS[i]);
    }
    else if(json_array_is_color(Item)){
        for(new i = 0; i < COLOR_SIZE; i++)
            Color[i] = json_array_get_number(Item, i);
    }
    else return false;

    for(new i = 0; i < COLOR_SIZE; i++)
        Color[i] = clamp(Color[i], 0, 255);
       
    return true;
}

bool:json_array_get_color(const JSON:Arr, const Index, Color[COLOR_SIZE]){
    new JSON:Item = json_array_get_value(Arr, Index);
    new bool:Res = json_get_color(Item, Color);
    json_free(Item);
    return Res;
}

Array:json_get_color_list(const JSON:Item){
    new Color[COLOR_SIZE];
    new Array:List;

    if(json_get_color(Item, Color)){
        List = ArrayCreate(COLOR_SIZE, 1);
        ArrayPushArray(List, Color);
        return List;
    }

    if(!json_is_array(Item))
        return Invalid_Array;
   
    List = ArrayCreate(COLOR_SIZE, json_array_get_count(Item));

    for(new i = 0; i < json_array_get_count(Item); i++){
        if(json_array_get_color(Item, i, Color))
            ArrayPushArray(List, Color);
    }
    return List;
}

Array:json_object_get_color_list(const JSON:Obj, const Name[], const bool:DotNot = false){
    new JSON:Item = json_object_get_value(Obj, Name, DotNot);
    new Array:List = json_get_color_list(Item);
    json_free(Item);
    return List;
}

bool:json_is_array_of(const JSON:Arr, const JSONType:Type, const Size = -1){
    if(!json_is_array(Arr))
        return false;

    if(Size > json_array_get_count(Arr))
        return false;

    new JSON:v;
    new to = (Size == -1) ? json_array_get_count(Arr) : Size;
    for(new i = 0; i < to; i++){
        v = json_array_get_value(Arr, i);
        if(!(
            v != Invalid_JSON
            && json_get_type(v) == Type
        )){
            json_free(v);
            return false;
        }
        json_free(v);
    }
    return true;
}

public plugin_cfg(){
    Example();
}

Example(){
    new JSON:SomeObj = json_parse("Example.json", true);
    new Array:List;

    List = json_object_get_color_list(SomeObj, "OneColor");
    PrintColorArray(List, "OneColor");
    ArrayDestroy(List);

    List = json_object_get_color_list(SomeObj, "TwoColors");
    PrintColorArray(List, "TwoColors");
    ArrayDestroy(List);
}

PrintColorArray(const Array:Arr, const Title[]){
    if(Arr == Invalid_Array)
        return;
    server_print("%s:", Title);
    for(new i = 0 ; i < ArraySize(Arr); i++){
        new Color[3];
        ArrayGetArray(Arr, i, Color);
        server_print("  #%d: %d %d %d", i, Color[0], Color[1], Color[2]);
    }
}
Example.json:
JSON:
{
    "OneColor": [255, 0, 0],
    "TwoColors": [
        [0, 255, 0],
        {"R": 0, "G": 0, "B": 255}
    ]
}
Output:
Код:
OneColor:
  #0: 255 0 0
TwoColors:
  #0: 0 255 0
  #1: 0 0 255

P.S. Примерно таким же макаром можно читать те же координаты и всё такое...
 

Вложения

Сообщения
392
Реакции
283
Помог
3 раз(а)
Получение из строки отдельных символов с поддержкой мнобайтовых символов.

C++:
/**
* Возвращает одну букву из строки
*
* @param Str       Строка
* @param Letter    Сюда будет записана буква
* @param Next      Номер ячейки с которой начать читать букву. Будет увеличено на кол-во байт, занимаемых полученной буквой.
*
* @return          true если будет получена, иначе false
*/
bool:GetLetterFromStr(const Str[], Letter[8], &Next = 0){
    if(!Str[Next])
        return false;
    new bytes = get_char_bytes(Str[Next]);
    copy(Letter, bytes, Str[Next]);
    Next += bytes;
    return true;
}
Plugin:
C++:
#include <amxmodx>

#define LETTER_SIZE 8

new const TEST_STRING[] = "Test Тест 123!";

public plugin_init(){
    PrintStrLetters(TEST_STRING);
}

PrintStrLetters(const Str[]){
    new Letter[LETTER_SIZE], Next = 0;
    server_print("Letters of string '%s':", Str);
    while(GetLetterFromStr(Str, Letter, Next))
        server_print("  %s", Letter);
}

/**
 * Возвращает одну букву из строки
 *
 * @param Str       Строка
 * @param Letter    Сюда будет записана буква
 * @param Next      Номер ячейки с которой начать читать букву. Будет увеличено на кол-во байт, занимаемых полученной буквой.
 *
 * @return          true если будет получена, иначе false
*/
bool:GetLetterFromStr(const Str[], Letter[LETTER_SIZE], &Next = 0){
    if(!Str[Next])
        return false;
    new bytes = get_char_bytes(Str[Next]);
    copy(Letter, bytes, Str[Next]);
    Next += bytes;
    return true;
}
Output:
Код:
Letters of string 'Test Тест 123!':
  T
  e
  s
  t

  Т
  е
  с
  т

  1
  2
  3
  !
 

Вложения

Последнее редактирование:
Сообщения
1,408
Реакции
182
Помог
2 раз(а)
Способ предложил: malniata
Доработка: wellasgood

Описание:

В функцию поступает строка, первый символ строки сравнивается с каждым элементом массива символов.
Если нужный найдется, то вернет его числовую позицию из массива, дальше можно использовать по коду.

Аргумент value, по какому условию вычислять: 1-с регистром; 2-без регистра

В случае неудачи, если не найдет нужный символ, вернет -1

C++:
+ #define ARRAY_BUFFER 64

SymbolsHandler(data[], value)
{
    new i, Buffer[ARRAY_BUFFER];

    while(i < ArraySize(SaveArray)
    {
        Buffer[0] = EOS;
        ArrayGetString(SaveArray, i, Buffer, charsmax(Buffer));

        if(value == 1 ? contain(data[0], Buffer) == 0 : containi(data[0], Buffer) == 0) return i;

        i++;
    }

    return -1;
}

иначе (с switch):

C++:
+ #define ARRAY_BUFFER 64

SymbolsHandler(data[], value)
{
    new i, Buffer[ARRAY_BUFFER];

    while(i < ArraySize(SaveArray)
    {
        Buffer[0] = EOS;
        ArrayGetString(SaveArray, i, Buffer, charsmax(Buffer));

        switch(value)
        {
            case 1: if(contain(data[0], Buffer) == 0) return i;
            case 2: if(containi(data[0], Buffer) == 0) return i;
        }

        i++;
    }

    return -1;
}

В функцию нужно посылать строку, увеличивая на 1 элемент, пока не будет достигнут конец строки.

Пример использования:

C++:
    new Data[MESSAGEMODE_ARRAY_BUFFER];
    read_args(Data, charsmax(Data));

    new i;
    while(Data[i] != EOS)
    {
        //получаем числовую позицию символа в массиве
        new num = SymbolsHandler(Data[i++], 1);

        //Если вернуло -1 (т.е символ не нашелся)
        if(num < 0) continue;

       //далее используем как хотим.
    }
 
Последнее редактирование модератором:
Сообщения
453
Реакции
255
Помог
9 раз(а)
wellasgood, один из возможных вариантов, тут хотя бы функция своим именем и используется заточенный под поиск строк функционал. Вообще не понятно для чего это нужно, но вот:

Код:
get_num_by_name(name[MAX_SIZE], bool: caseSensivity = false)    {
    new temp[MAX_SIZE]/*hackerman*/, i;
    copy(temp, charsmax(temp), name);

    while ((i = (ArrayFindString(g_aArray, temp) != -1)))    {
        if (caseSensivity)    {          
            return (containi(name, temp) != -1) ? i-1 : 0;
        }
        return i-1;
    }
    return 0;
}
 
Сообщения
1,408
Реакции
182
Помог
2 раз(а)
malniata, не знаю, вариант отсюда Склад полезного кода [GoldSrc] хорошо работает. Сами проверьте.

Пример использования:


Все зависит от конкретной задачи.

В данном плагине, в игре, если написать текст >>> 'dev-cs.ru', то появятся эти спрайты в той последовательности которой написан текст. Значит код работает? Не так ли?

1616527357506.png
 
Последнее редактирование модератором:
Сообщения
392
Реакции
283
Помог
3 раз(а)
В данном плагине, в игре, если написать текст >>> 'dev-cs.ru', то появятся эти спрайты в той последовательности которой написан текст. Значит код работает? Не так ли?
А с кириллицей работает?)
 
Последнее редактирование модератором:
Сообщения
1,408
Реакции
182
Помог
2 раз(а)
у contain и containi есть поддержка русских символов и тп.

Работает.
23 Мар 2021
C:
/**
* Tests whether a string is found inside another string.
*
* @param source        String to search in.
* @param string        Substring to find inside the original string.
*
* @return                -1 on failure (no match found). Any other value
*                        indicates a position in the string where the match starts.
*/
native contain(const source[], const string[]);

/**
* Tests whether a string is found inside another string with case ignoring.
*
* @note This supports multi-byte characters (UTF-8) on comparison.
*
* @param source        String to search in.
* @param string        Substring to find inside the original string.
*
* @return                -1 on failure (no match found). Any other value
*                        indicates a position in the string where the match starts.
*/
native containi(const source[], const string[]);

почему-то тут не указано про UTF-8 в случае с contain, но работает в плагине. Вычисляет русские буквы. и большие и маленькие.
23 Мар 2021
возможно работает, потому что в массиве символы.

C:
static cell AMX_NATIVE_CALL contain(AMX *amx, cell *params) /* 2 param */
{
    register cell *a = get_amxaddr(amx, params[2]);
    register cell *b = get_amxaddr(amx, params[1]);
    register cell *c = b;
    cell* str = b;
    cell* substr = a;
 
    while (*c)
    {
        if (*c == *a)
        {
            c++;
            if (!*++a)
                return b - str;
        } else {
            c = ++b;
            a = substr;
        }
    }
 
    return -1;
}

// native containi(const source[], const string[]);
static cell AMX_NATIVE_CALL containi(AMX *amx, cell *params)
{
    enum args { arg_count, arg_source, arg_search };

    auto sourceLength = 0;
    auto searchLength = 0;

    auto source = get_amxstring(amx, params[arg_source], 0, sourceLength);
    auto search = get_amxstring(amx, params[arg_search], 1, searchLength);

    if (sourceLength && searchLength)
    {
        auto sourceFolded = get_amxbuffer(2);
        auto searchFolded = get_amxbuffer(3);

        sourceLength = utf8casefold(source, sourceLength, sourceFolded, MAX_BUFFER_LENGTH - 1, UTF8_LOCALE_DEFAULT, nullptr, TRUE);
        searchLength = utf8casefold(search, searchLength, searchFolded, MAX_BUFFER_LENGTH - 1, UTF8_LOCALE_DEFAULT, nullptr, TRUE);

        sourceFolded[sourceLength] = '\0';
        searchFolded[searchLength] = '\0';

        auto result = strstr(sourceFolded, searchFolded);

        if (result)
        {
            return result - sourceFolded;
        }
    }

    return -1;
}
 
Последнее редактирование модератором:
Сообщения
2,713
Реакции
2,995
Помог
59 раз(а)
Код:
/**
 * Executes action for each player appropriate for condition
 *
 * @param playerVar  Variable name which stores player index
 * @param condition  Condition for player choosing
 * @param action
 */
#define ForEachPlayer(%1,%2,%3) do {\
    for (new %1 = 1; %1 <= MAX_PLAYERS; %1++) {\
        if (%2) {\
            %3;\
        }\
    }\
} while (is_linux_server() == 0xDEADBEEF)
Example:
Код:
new name[MAX_NAME_LENGTH];
get_user_name(player, name, charsmax(name));
ForEachPlayer(x, x != player, client_print(x, print_chat, "You are not %s", name));

Код:
/**
 * Stores a filtered list of client indexes to an array.
 *
 * @param players    Array to store indexes to
 * @param num        Variable to store number of indexes to
 * @param playerVar  Variable name which stores player index (for condition)
 * @param condition  Condition which filters players
 */
#define GetPlayers(%0,%1,%2,%3) do {\
    %1 = 0;\
    for (new %2 = 1; %2 <= MAX_PLAYERS; %2++) {\
        if (%3) {\
            %0[%1++] = %2;\
        }\
    }\
} while (is_linux_server() == 0xDEADBEEF)
Example:
Код:
new zombies[MAX_PLAYERS], zombieCount;
GetPlayers(zombies, zombieCount, x, is_user_alive(x) && zp_get_user_zombie(x));
client_print(0, print_chat, "Zombie count is %d", zombieCount);

Код:
/**
 * Stores a filtered list of random client indexes to an array.
 * Executes GetPlayers then limits and randomize that list
 *
 * @param players    Array to store indexes to
 * @param num        Variable to store number of indexes to (and this variable sets limit of player count)
 * @param playerVar  Variable name which stores player index (for condition)
 * @param condition  Condition which filters players
 */
#define GetRandomPlayers(%0,%1,%2,%3) do {\
    static _plrs[MAX_PLAYERS];\
    new _plrCount;\
    GetPlayers(_plrs, _plrCount, %2, %3);\
    \
    %1 = min(%1, _plrCount);\
    for (new _i = 0; _i < %1; _i++) {\
        new _rnd = random_num(0, _plrCount - 1);\
        \
        %0[_i] = _plrs[_rnd];\
        _plrs[_rnd] = _plrs[_plrCount - 1];\
        \
        _plrCount--;\
    }\
} while (is_linux_server() == 0xDEADBEEF)
Example:
Код:
new humans[3], humanCount = sizeof(humans);
GetRandomPlayers(humans, humanCount, x, is_user_alive(x) && !zp_get_user_zombie(x));
for (new i = 0; i < humanCount; i++) {
    client_print(humans[i], print_chat, "You're a randomly chosen player");
}

Код:
/**
 * Gets a random player appropriate for this condition
 *
 * @param player     Variable to store chosen player index (will be 0 if can't found appropriate player)
 * @param playerVar  Variable name which stores player index (for condition)
 * @param condition  Condition for player choosing
 */
#define GetRandomPlayer(%0,%1,%2) do {\
    static _players[MAX_PLAYERS];\
    new _playerCount;\
    GetPlayers(_players, _playerCount, %1, %2);\
    %0 = _playerCount ? _players[random_num(0, _playerCount - 1)] : 0;\
} while (is_linux_server() == 0xDEADBEEF)
Example:
Код:
new player;
GetRandomPlayer(player, x, is_user_alive(x) && cs_get_user_team(x) == CS_TEAM_CT);
client_print(player, print_chat, "You have received a bonus");
source
 
Сообщения
1,408
Реакции
182
Помог
2 раз(а)
Активация плагина только на нужных картах (в Names добавляются те наименования карт, только где должен работать плагин)

Данный код можно разместить в plugin_precache() или plugin_init() (смотря где регистрируется плагин), после регистрации плагина register_plugin()

C++:
+ #if !defined MAX_MAPNAME_LENGTH
+ #define MAX_MAPNAME_LENGTH 64
+ #endif
C++:
    new Map[MAX_MAPNAME_LENGTH];
    get_mapname(Map, charsmax(Map));

    new Names[][] = { "de_dust2" }; //если больше 1, то через запятую, пример: {"de_dust2", "de_dust2_other"}, вводить можно без чувст.к регистру.

    new bool:check, i;

    while(i < sizeof Names)
    {
        if(equali(Map, Names[i++]))
        {
            check = true;
            break;
        }
    }

    if(!check)
    {
        pause("ad");
        return;
    }

Пример можно глянуть здесь:

 
Последнее редактирование модератором:
Сообщения
1,176
Реакции
2,144
Помог
57 раз(а)
wellasgood, Дима, для кого ты постишь это? Здесь раздел нетривиальных решений для тех кто более-менее уже понимает что к чему (скриптит на достаточном уровне). А ты постишь какие-то банальные решения. Мало того что неправильные, так ещё и ненужные никому.
//если больше 1, то через запятую, пример: {"de_dust2", "de_dust2_other"}, вводить можно без чувст.к регистру.
Зачем это писать? Ты думаешь что, человек, не умеющий работать с массивами строк, полезет в данный раздел уму-разуму набираться в твоих стоках? Если так, почему ты в функцию не оформил пример? Человек не поймёт ничего. Ещё и while() + if(). Зачем, если можно прям в while всё сделать? Кошмар. Перестань пожалуйста это делать. Рано тебе учить других.
 
Сообщения
1,408
Реакции
182
Помог
2 раз(а)
BlackSignature, полезный код, кому-то да пригодится.
27 Мар 2021
BlackSignature, что то я не понял как ты собрался в while делать все. Поясни с примером, раз предлагаешь
 
Последнее редактирование модератором:
Сообщения
1,176
Реакции
2,144
Помог
57 раз(а)
wellasgood,
Код:
#include <amxmodx>

// Список префиксов/карт, на которых плагин не работает
new const DISABLED_MAPS[][] = {
    "$",
    "fy_",
    "aim_",
    "awp_",
    "35hp_"
}

stock bool:IsPluginDisabledByMap(const szMapList[][], iListSize = sizeof(szMapList)) {
    new szMapName[64]
    get_mapname(szMapName, charsmax(szMapName))

    for(new i; i < iListSize; i++) {
        if(equal(szMapName, szMapList[i], strlen(szMapList[i]))) {
            return true
        }
    }

    return false
}

public plugin_init() {
    register_plugin("Name", "Version", "Author")

    if(IsPluginDisabledByMap(DISABLED_MAPS)) {
        pause("ad")
        return
    }
}
 
Сообщения
443
Реакции
319
Помог
13 раз(а)
Код:
shiftArrayLeft(const Array: aArray, const iNum) {
    if(iNum<= 0) return;

    new tempArray[ArrayDataType], tempArray2[ArrayDataType];
    ArrayGetArray(aArray, 0, tempArray);

    for (new i = 0, l = iNum; i < l; i++) {
        ArrayGetArray(aArray, i + 1, tempArray2);
        ArraySetArray(aArray, i, tempArray2);
    }

    ArraySetArray(aArray, iNum, tempArray);
}
An example of usage:
Код:
Array: PrepareArray(const iCount, const Array: aCopyFrom, const iCopyFromSize) {
    new iNum = iCopyFromSize - 1;

    new Array: aTempArray = ArrayClone(aCopyFrom);

    if(iCount && iNum) {
        for (new i = 0, l = iCount; i < l; i++) {
            shiftArrayLeft(aTempArray, iNum);
        }
    }

    return aTempArray;
}
 
Последнее редактирование:
Сообщения
271
Реакции
347
Помог
15 раз(а)
Пример реализации VK Bot Long Poll API на павне. Может кто предложит лучше?

Как говорится:

полезный код, кому-то да пригодится.

Код:
#include <amxmodx>
#include <grip>

#pragma dynamic 32768

new const VK_API_VERSION[] = "5.130";
new const VK_ACCESS_TOKEN[] = "";
new const VK_GROUP_ID[] = "";

const VK_WAIT_TIME = 25;

enum VkTypes
{
    VK_MESSAGE_NONE = -1,
    VK_MESSAGE_NEW,
    VK_MESSAGE_REPLY,
    VK_MESSAGE_EDIT,
    VK_MESSAGE_EVENT
};

new const VK_TYPES[][] =
{
    "message_new",
    "message_reply",
    "message_edit",
    "message_event"
    // ...
};

enum requestId
{
    REQUEST_GET_LONG_POLL_SERVER = 0,
    REQUEST_LISTEN_LONG_POLL_SERVER
};

enum longpoll_s
{
    m_server[512],
    m_key[512],
    m_ts[64]
};

new longpoll_s:g_longPollServer[longpoll_s];

public plugin_init()
{
    register_plugin("VK: Bot Long Poll API", __DATE__, "Denzer");

    getLongPollServer();
}

getLongPollServer()
{
    new formData[512]; formatex(formData, charsmax(formData), "access_token=%s&group_id=%s&v=%s", VK_ACCESS_TOKEN, VK_GROUP_ID, VK_API_VERSION);

    new GripBody:body = grip_body_from_string(formData);
    grip_request("https://api.vk.com/method/groups.getLongPollServer", body, GripRequestTypePost, "requestHandler", _, requestId:REQUEST_GET_LONG_POLL_SERVER);
    grip_destroy_body(body);
}

listenLongPollServer()
{
    //server_print("POPERLI");
    new formData[512]; formatex(formData, charsmax(formData), "act=a_check&key=%s&wait=%d&mode=2&ts=%s", g_longPollServer[m_key], VK_WAIT_TIME, g_longPollServer[m_ts]);

    new GripRequestOptions:options = grip_create_default_options();
    new GripBody:body = grip_body_from_string(formData);
    grip_request(g_longPollServer[m_server], body, GripRequestTypePost, "requestHandler", options, requestId:REQUEST_LISTEN_LONG_POLL_SERVER);
    grip_destroy_body(body);
    grip_destroy_options(options);
}

public requestHandler(requestId:reqId)
{
    if (grip_get_response_state() == GripResponseStateError)
    {
        return;
    }

    if (grip_get_response_status_code() != GripHTTPStatusOk)
    {
        return;
    }

    new errorBuffer[128];
    new GripJSONValue:json = grip_json_parse_response_body(errorBuffer, charsmax(errorBuffer));

    if (json == Invalid_GripJSONValue)
    {
        log_amx(errorBuffer);
        return;
    }

    switch (reqId)
    {
        case REQUEST_GET_LONG_POLL_SERVER:
        {
            new GripJSONValue:response = grip_json_object_get_value(json, "response");
            grip_destroy_json_value(json);

            grip_json_object_get_string(response, "key", g_longPollServer[m_key], charsmax(g_longPollServer[m_key]));
            grip_json_object_get_string(response, "server", g_longPollServer[m_server], charsmax(g_longPollServer[m_server]));
            grip_json_object_get_string(response, "ts", g_longPollServer[m_ts], charsmax(g_longPollServer[m_ts]));

            server_print("SERVER: %s^nKEY: %s^nTS: %s", g_longPollServer[m_server], g_longPollServer[m_key], g_longPollServer[m_ts]);

            grip_destroy_json_value(response);
        }
        case REQUEST_LISTEN_LONG_POLL_SERVER:
        {
            //server_print("OP");

            grip_json_object_get_string(json, "ts", g_longPollServer[m_ts], charsmax(g_longPollServer[m_ts]));
            // array
            new GripJSONValue:updates = grip_json_object_get_value(json, "updates");

            new updatesCount = grip_json_array_get_count(updates);
            
            for (new i = 0; i < updatesCount; i++)
            {
                new GripJSONValue:arrayElem = grip_json_array_get_value(updates, i);

                new GripJSONValue:type = grip_json_object_get_value(arrayElem, "type");
                new GripJSONValue:object = grip_json_object_get_value(arrayElem, "object");
                grip_destroy_json_value(arrayElem);

                new typeBuffer[128]; grip_json_get_string(type, typeBuffer, charsmax(typeBuffer));
                grip_destroy_json_value(type);
                new VkTypes:vkType = parseType(typeBuffer);

                if (vkType == VK_MESSAGE_NEW)
                {
                    new GripJSONValue:message = grip_json_object_get_value(object, "message");
                    new messageBuffer[512]; grip_json_object_get_string(message, "text", messageBuffer, charsmax(messageBuffer));
                    grip_destroy_json_value(message);
                    server_print(messageBuffer);
                }
                grip_destroy_json_value(object);
                //grip_json_serial_to_file(arrayElem, "test.json", true);
            }
 
            grip_destroy_json_value(updates);
            grip_destroy_json_value(json);
        }
    }

    listenLongPollServer();
}

VkTypes:parseType(type[])
{
    for (new i; i < sizeof(VK_TYPES); i++)
    {
        if (equal(VK_TYPES[i], type))
        {
            return VkTypes:i;
        }
    }

    return VK_MESSAGE_NONE;
}
 

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

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