Лотерея

Тема в разделе "Программирование / Скриптинг", создана пользователем diller110, 13 сен 2015.

  1. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Доброе время суток, хотел создать плагин лотереи, а точнее проапгрейдить существующий. А именно, вывод случайного числа через Hint сообщения на CS GO. upd: Плагин работает, я прошу помощи с возможными утечками и советов оптимизации.
    Вот исходник: Посмотреть вложение ac-luck.sp

    Сразу несколько вопросов:
    1. В начале раунда в хинт пишет типо Play!, и перебивает надпись лотереи. Многие другие плагины тоже перебивают, как их можно отключить на время рандоминга?
     
    Последнее редактирование: 13 сен 2015
  2. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.552
    Симпатии:
    1.987
    PHP:
    new String:Primary[36];
    Разве decl уже отменили? Используй его.
    PHP:
    g_Lottery[GetClientOfUserId(GetClientUserId(client))] = 0;
    Что за придумки, когда есть сам client?! Он же в обратном вызове консольной команды присутствует.
    PHP:
    GetCurrentMap(mapname30);
    Каждый раунд получать карту? Сохраняй разово в OnMapStart(), например.
    Код:
    for (new i = 0; i<(MAXPLAYERS[B]+1[/B]); i++)
    Уж лучше со знаком равно, чем каждый раз прибавлять единичку. А ещё лучше использовать MaxClients - это, в большинстве случаев-серверов, значительно уменьшит цикл. Вряд ли неполный цикл здесь будет создавать сбои в работе плагина (это, как минимум, нужен другой плагин, который меняет количество слотов сервера во время его работы).
    PHP:
    if (StrContains(mapname"de_"true) != -1mapDeType true;
    else 
    mapDeType false;
    Можно попробовать заменить на новом SM:
    PHP:
    mapDeType bool:(StrContains(mapname"de_"true) != -1);
    или хотя бы:
    PHP:
    mapDeType StrContains(mapname"de_"true) != -true:false;
    С таймером явно заморочено. Например, пытаешься получить Float значение, когда ничего не сохранял для первого вызова таймера. А amount мог прибавлять в массиве g_Lottery, ведь всё равно туда ничего не пишется, кроме 0 и 1, т.е. там вообще bool бы хватило.
    Я конечно подозреваю, что там может писаться цифра для Weapon_names, например, но пока всё смутно.
    Другие плагины тоже можно перебивать повторяющимся таймером, но не стоит.
     
  3. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Как думаете компилятор так и примет перечисления в штык? Case в любом случае оставлю, т.к. конструкция if else крайне неудобна в данной ситуации. Просто интересно как это повлияет на быстродействие.
    PHP:
        switch(Random){
            case 
    0,1,2,3,4,5,6:{
                if (
    Client_GetWeaponBySlot(client1) != -1SDKHooks_DropWeapon(clientClient_GetWeaponBySlot(client1));
                
    GivePlayerItem(clientWeapon_names[Random]);
                
    CGOPrintToChatAll("{LIME}[{LIGHTGREEN}AC{LIME}] {LIGHTOLIVE}%N {GRAY}выйграл {DEFAULT}%s{GRAY}! Попробуй и ты: /luck"clientWeapon_names_translated[Random]);
            }
            case 
    7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28:{            
                if (
    Client_GetWeaponBySlot(client0) != -1SDKHooks_DropWeapon(clientClient_GetWeaponBySlot(client0));
                
    CGOPrintToChatAll("{LIME}[{LIGHTGREEN}AC{LIME}] {LIGHTOLIVE}%N {GRAY}выйграл {DEFAULT}%s{GRAY}! Попробуй и ты: /luck"clientWeapon_names_translated[Random]);
                
    GivePlayerItem(clientWeapon_names[Random]);
            }
            case 
    29,30,31,32,33,34,35,36:{
                
    GivePlayerItem(clientWeapon_names[Random]);
                
    CGOPrintToChatAll("{LIME}[{LIGHTGREEN}AC{LIME}] {LIGHTOLIVE}%N {GRAY}выйграл {DEFAULT}%s{GRAY}! Попробуй и ты: /luck"clientWeapon_names_translated[Random]);
            }
            default:{
                
    CGOPrintToChat(client"{LIME}[{LIGHTGREEN}Rank{LIME}] {LIGHTOLIVE}Похоже вам попался приз-пустышка. Ничего, еще повезёт)");    
            }
        }
     
  4. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.552
    Симпатии:
    1.987
    Примет. Для него ты всё правильно делаешь, а оптимальность - забота самого скриптера. Оффтоп
     
  5. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    AlmazON, Спасибо, почти все замечания исправил. Решил добавить одну фичу, но столкнулся с непонятной мне логикой:
    PHP:
     if(args>0){
                    
    char c_arg[3]; int arg;
                    
    GetCmdArg(2c_arg3);
                    
    PrintToChat(client"%s"c_arg);
                    
    StringToInt(c_argarg);
                    if(
    arg==0) {
                        
    AutoLuck[client] = 0;
                        
    CGOPrintToChat(client"{LIME}[{LIGHTGREEN}AC{LIME}] {GRAY} Вы отключили автолотерею!");
                        return 
    Plugin_Handled;
                    } else if(
    arg>0){
                        if (
    arg 10arg 10;
                        
    AutoLuck[client] = arg;
                        
    CGOPrintToChat(client"{LIME}[{LIGHTGREEN}AC{LIME}] {GRAY}Вы включили автолотерею на %d раундов!",arg);
                        return 
    Plugin_Handled;
                    }
                    return 
    Plugin_Handled;
                }
    Стабильно выполняется кусок кода: if(arg==0) { },
    PrintToChat(client, "%s", c_arg); До него не выполняется, как и все остальное.

    _____
    Update: Ошибку понял, я дурак.
    Не StringToInt(c_arg, arg); А agr = StringToInt(c_arg);
     
  6. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.552
    Симпатии:
    1.987
    Нужно только в конце. Оффтоп
     
  7. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.995
    Симпатии:
    2.990
    diller110, или
    PHP:
    arg StringToInt(c_arg);
    Или
    PHP:
    StringToIntEx(c_argarg);
    Но не как у тебя
     
  8. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Между делом, не знаете в чем может быть проблема?
    В консоль выдает подобную ошибку:
    PHP:
     09/26/2015 18:39:32: [SMException reported: Array index is out of bounds
    L 09
    /26/2015 18:39:32: [SMBlaming pluginwebshortcuts_csgo.smx
    L 09
    /26/2015 18:39:32: [SMCall stack trace:
    L 09/26/2015 18:39:32: [SM]   [1Line 62webshortcuts_csgo.sp::OnSay()
    L 09/26/2015 18:39:32: [SM]   [3FakeClientCommand
    L 09
    /26/2015 18:39:32: [SM]   [4Line 90Resetscore+_v1.5.1.sp::LC()
    Вот коды на которые указывает:
    webshortcuts
    PHP:
        new start;
        new 
    len strlen(text);
        if ( 
    text[len-1] == '"' )  << 62 строка
        
    {
            
    text[len-1] = '\0';
            
    start 1;
        }
    ResetScore+
    PHP:
    if(t[1] !='\0'FakeClientCommand(C"%s %s"Nt);

    SourceMod девелоперский [01] SourceMod (1.8.0-dev+5666) by AlliedModders LLC. На 1.6 вроде было норм. Что-то связано с новым синтаксисом?
     
  9. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.552
    Симпатии:
    1.987
    Известная ошибка. Вызывается, когда идёт отсылка пустого сообщения. Судя по всему, такое удалось отправить через сброс счёта.
    Для решения:
    len не должно быть равно 0, как бывает. Сделать проверку этого.
     
  10. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    AlmazON, Спасибо, только не очень понял: "Судя по всему, такое удалось отправить через сброс счёта."

    И еще немного теории, всегда задавался вопросом насчет этого \0. Как понимаю он равнозначен пустоте. Как в text[len-1] = '\0'; он присваивается? (позиция text - единичная, а "\0" - 2 символа)
     
  11. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.995
    Симпатии:
    2.990
    diller110, 0 или '\0' это символ конца строки. Тоесть как только плагин в строке сталкивается с ним он понимает что это конец строки.
    это не 2 сивола, \ это экранирование, просто если написать '0' то это будет просто символ нуля
     
  12. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.552
    Симпатии:
    1.987
    Пример-эквивалент отправки пустого сообщения от игрока:
    PHP:
    FakeClientCommand(client"say ");
    Т.е. после пробела должен быть текст, а его нет. Это неправильно, но бывает, а система c len других плагинов этого не учитывает, "устарела".
    "Строка ограничивается нулевым символом, или 0. Без нулевого символа, Pawn не знает, где остановить чтение строки.", а также "...очень важно помнить о концепции нулевого символа, который свидетельствует о конце строки. Компилятор и большинство SourceMod функций будут автоматически остановлены нулевым символом..." - это давно описано в доках.
    Да, два видимых символа, это строка. Другое дело '\0', о котором и речь.
     
  13. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    AlmazON, R1KO, Спасибо! Поправил webshortcuts, ошибка вроде исчезла.

    Еще 1 нюанс, почему в ResetScore if(t[1] !='\0') FakeClientCommand(C, "%s %s", N, t); Проверка 2-ого символа? t[1] !='\0', а не t[0] !='\0'
     
  14. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.552
    Симпатии:
    1.987
    Это связано с возможностью писать любый символ впереди для команды без его конкретного упоминания, вроде !rs. Оффтоп
     
  15. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Еще один вопрос:
    Задача активация функции путем ввода /tutorial "первые 4 символа ника". Т.е. с моим ником diller110 - !tutorial dill.
    Вот что сделал я:
    PHP:
                char arges[4][16]; // Создаст 4 буфера, не помню зачем 4, наверно на всякий.
                
    ExplodeString(Text" "arges416);   // Делит введенную команду по 4 переменным.
                
                
    if(strlen(arges[2]) > || strlen(arges[3]) > 0)  // Если 2 или 3 аргументы не пусты, значит ошибка т.к. должно быть только 1.
                
    {
                    
    CGOPrintToChat(client"{GRAY}[{LIGHTBLUE}AC{GRAY}] Ошибка при подтверждении прохождения обучения. Введите правильный код из обучения.");
                    return 
    Plugin_Handled;
                }
                
    GetClientName(clientarges[2], 5);  //Получает имя игрока и записывает во 2 буффер (т.к. он свободен)
                
    if(strlen(arges[1])>&& StrEqual(arges[1], arges[2], false))   // Если код введен правильный
                
    {
    //выполняется функция
                            
    }
    А теперь что не так: Если у игрока суперпупер ник, например с такими ๑۩۩๑ символами. Активация не проходит. Логично после GetClientName отсекать все символы не буквы. Но как это делать я не знаю.
     
  16. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.995
    Симпатии:
    2.990
    Ну можешь прогнать по строке, посимвольно проверять.
    И буферов многовато.
     
  17. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.552
    Симпатии:
    1.987
    Вот потому обычно используют UserID или индекс клиента.
     
  18. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    AlmazON, Мне чтобы игрокам было понятней. Я с веб-частью не дружу, поэтому приходится выкручиваться вот так: *реклама* Оффтоп *реклама*.

    Сейчас попробую написать с проверками IsChar... если честно не догадывался об их существовании.

    Как понимаю нужно проверять символ на IsCharUpper и IsCharLower - т.к. символов больших и маленьких не бывает?
     
  19. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.552
    Симпатии:
    1.987
    Может быть и десяток одинаковых ников, различающихся лишь цифрой или тем же нечитаемым символом. Тут полностью надо.
     
  20. diller110

    diller110

    Сообщения:
    138
    Симпатии:
    48
    Решил немного полегче сделать, но и тут у меня много вопросов :blush2:
    Сначала получил вот это:
    0 -
    1 -
    2 -
    3 -
    4 -
    5 -
    6 -
    7 -
    8 -
    9 -
    10 -

    11 -
    12 -
    13 -
    14 -
    15 -
    16 -
    17 -
    18 -
    19 -
    20 -
    21 -
    22 -
    23 -
    24 -
    25 -
    26 -
    27 -
    28 -
    29 -
    30 -
    31 -
    32 -
    33 - !
    34 - "
    35 - #
    36 - $
    37 - %
    38 - &
    39 - '
    40 - (
    41 - )
    42 - *
    43 - +
    44 - ,
    45 - -
    46 - .
    47 - /
    48 - 0
    49 - 1
    50 - 2
    51 - 3
    52 - 4
    53 - 5
    54 - 6
    55 - 7
    56 - 8
    57 - 9
    58 - :
    59 - ;
    60 - <
    61 - =
    62 - >
    63 - ?
    64 - @
    65 - A
    66 - B
    67 - C
    68 - D
    69 - E
    70 - F
    71 - G
    72 - H
    73 - I
    74 - J
    75 - K
    76 - L
    77 - M
    78 - N
    79 - O
    80 - P
    81 - Q
    82 - R
    83 - S
    84 - T
    85 - U
    86 - V
    87 - W
    88 - X
    89 - Y
    90 - Z
    91 - [
    92 - \
    93 - ]
    94 - ^
    95 - _
    96 - `
    97 - a
    98 - b
    99 - c
    100 - d
    101 - e
    102 - f
    103 - g
    104 - h
    105 - i
    106 - j
    107 - k
    108 - l
    109 - m
    110 - n
    111 - o
    112 - p
    113 - q
    114 - r
    115 - s
    116 - t
    117 - u
    118 - v
    119 - w
    120 - x
    121 - y
    122 - z
    123 - {
    124 - |
    125 - }
    126 - ~
    127 - 
    128 - �
    На основании этого написал вот это:
    PHP:
    public Action Cmd_FourChars(int clientint args){
        
    char nickname[64], fourchars[4];
        
    GetClientName(clientnickname64);
        
    int length strlen(nickname), fourcharscount 0;
        for (
    int i 0lengthi++){
            if((
    nickname[i]>64 && nickname[i]<91 && fourcharscount<4) || (fourcharscount<&& nickname[i]>96 && nickname[i]<123)) {
                
    fourchars[fourcharscount++] = nickname[i];
            }
        }
        
    PrintToChatAll("%N = %s "clientfourchars);
        return 
    Plugin_Handled;
    }
    Почему выводит diller110 = dilldiller110 ?

    upd: У людей с символами например #$diller110 = dilldiller110 , т.е. сортирует удачно, но почему в конце второй раз ник?
    upd2: Когда пишет игрок ๑۩۩๑DiroLヅ команду !fourchars не происходит вообще ничего...... (не админ команда)
     
    Последнее редактирование: 27 сен 2015