[INC] HintTimer, прошу помощи в написании

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

  1. Dragon_Knight

    Dragon_Knight

    Сообщения:
    5
    Симпатии:
    0
    Всем привет
    С языком знаком хорошо, но вот решил заняться сервером CSS. Вики и доки по SM написаны ужасно, без примеров и без сопутствующего материала. Отсюда и много вопросов...

    Итак, понадобился какой-нить наглядный таймер, который было-бы крайне просто использовать. Ничего готово не нашёл, и решил написать свой. Собственно написал такой инклуд:
    PHP:
    new Handle:Timer_Countdown[MAXPLAYERS+1] = {INVALID_HANDLE, ...};
    new 
    CountdownCounts[MAXPLAYERS+1] = {0, ...};

    forward OnCountdownHintTimerEnd(clienttimeid);

    public 
    CountdownHintTimerCreate(clienttimeString:text[], id)
    {
        if(
    Timer_Countdown[client] == INVALID_HANDLE)
        {
            new 
    Handle:pack CreateDataPack();
            
    WritePackCell(packclient);
            
    WritePackCell(packtime);
            
    WritePackString(packtext);
            
    WritePackCell(packid);
            
            
    CountdownHintTimer(Handle:0pack); // Мегатопор
            
    Timer_Countdown[client] = CreateTimer(1.0CountdownHintTimerpackTIMER_REPEAT);
        }
        else
        {
            
    CPrintToChat(client"{gold}[CountdownHintTimer]: {red}Ошибка создания таймера для Вас, таймер уже создан!");
        }
    }

    public 
    Action:CountdownHintTimer(Handle:timerHandle:pack)
    {
        new 
    clienttimeString:text[64], id;
        
        
    ResetPack(pack);
        
    client ReadPackCell(pack);
        
    time ReadPackCell(pack);
        
    ReadPackString(Handle:packtextsizeof(text));
        
    id ReadPackCell(pack);
        
        if(
    CountdownCounts[client] < time)
        {
            
    PrintHintText(clienttext, (time CountdownCounts[client]));
            
    CountdownCounts[client]++;
        }
        else
        {
            
    ClearTimer(Timer_Countdown[client]);
            
    CountdownHintTimerReset(client);
            
    CloseHandle(pack);
            
    PrintHintText(client"");
            
            new 
    result;
            
    Call_StartFunction(INVALID_HANDLEOnCountdownHintTimerEnd);
            
    Call_PushCell(client);
            
    Call_PushCell(time);
            
    Call_PushCell(id);
            
    Call_Finish(result);
        }
    }

    public 
    CountdownHintTimerReset(client)
    {
        
    Timer_Countdown[client] = INVALID_HANDLE;
        
    CountdownCounts[client] = 0;
    }
    Работать с ним так: CountdownHintTimerCreate(pid, 25, "Таймер. осталось %d сек.", 0);

    Нареканий по работе нету, однако есть много мест, которые сделаны откровенно ... плохо, в частности:
    * CountdownHintTimerCreate > CountdownHintTimer(Handle:0, pack); - как более грамотно избавиться от этого топора, что-бы таймер начинал работать сразу.
    * Как сделать полноценный колбэк OnCountdownHintTimerEnd(client, time, id) ?
    * И что в целом можно сделать в коде, что-бы привести к более адекватному виду?
     
  2. R1KO

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

    Сообщения:
    5.993
    Симпатии:
    2.989
    PHP:
    new Handle:Timer_Countdown[MAXPLAYERS+1] = {INVALID_HANDLE, ...}; 
    new 
    CountdownCounts[MAXPLAYERS+1] = {0, ...}; 

    forward OnCountdownHintTimerEnd(clienttimeid); 

    public 
    CountdownHintTimerCreate(clienttimeString:text[], id

        if(
    Timer_Countdown[client] == INVALID_HANDLE
        { 
            new 
    Handle:pack CreateDataPack(); 
            
    WritePackCell(packclient); 
            
    WritePackCell(packtime); 
            
    WritePackString(packtext); 
            
    WritePackCell(packid); 
             
            
    CountdownHintPrint(clienttimetextid);
            
    Timer_Countdown[client] = CreateTimer(1.0CountdownHintTimerpackTIMER_REPEAT); 
        } 
        else 
        { 
            
    CPrintToChat(client"{gold}[CountdownHintTimer]: {red}Ошибка создания таймера для Вас, таймер уже создан!"); 
        } 


    public 
    Action:CountdownHintTimer(Handle:timerany:pack

        
    decl clienttimeString:text[64], id
        
    ResetPack(pack); 
        
    client ReadPackCell(pack); 
        
    time ReadPackCell(pack); 
        
    ReadPackString(packtextsizeof(text)); 
        
    id ReadPackCell(pack);
        
    CloseHandle(pack);
        
    CountdownHintPrint(clienttimetextid);
    }

    stock CountdownHintPrint(clienttimetextid)
    {
        if(
    CountdownCounts[client] < time
        { 
            
    PrintHintText(clienttext, (time CountdownCounts[client])); 
            
    CountdownCounts[client]++; 
        } 
        else 
        { 
            
    ClearTimer(Timer_Countdown[client]); 
            
    CountdownHintTimerReset(client); 
            
    PrintHintText(client""); 
             
            new 
    result
            
    Call_StartFunction(INVALID_HANDLEOnCountdownHintTimerEnd); 
            
    Call_PushCell(client); 
            
    Call_PushCell(time); 
            
    Call_PushCell(id); 
            
    Call_Finish(result); 
        } 


    public 
    CountdownHintTimerReset(client

        
    Timer_Countdown[client] = INVALID_HANDLE
        
    CountdownCounts[client] = 0
     
  3. Dragon_Knight

    Dragon_Knight

    Сообщения:
    5
    Симпатии:
    0
    Спасибо за ответ, но этот код гарантированно работать не будет.

    CreateTimer(1.0, CountdownHintTimer, pack, TIMER_REPEAT); - вызываем CountdownHintTimer и передаём ссылку на пак туда.
    CountdownHintTimer > CloseHandle(pack); - убиваем ссылку и уничтожаем сам пак. Следующий вызов таймера будет с pack = INVALID_HANDLE.

    Второй момент, public Action:CountdownHintTimer(Handle:timer, any:pack)
    почему "any:pack", когда туда конкретно передаётся только ссылка?
     
  4. R1KO

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

    Сообщения:
    5.993
    Симпатии:
    2.989
    Согласен. Затупил.

    Если бы было CreateDataTimer - то Handle:pack, а в твоем случае CreateTimer, поэтому any:pack
     
  5. Dragon_Knight

    Dragon_Knight

    Сообщения:
    5
    Симпатии:
    0
    R1KO, эм...
    PHP:
    stock Handle:CreateDataTimer(Float:intervalTimer:func, &Handle:datapackflags=0)
    {
        
    datapack CreateDataPack();
        
    flags |= TIMER_DATA_HNDL_CLOSE;
        return 
    CreateTimer(intervalfuncdatapackflags);
    }
    Разница тока в том, что CreateDataTimer это сток, который в себе создаёт пак и кладёт его в обычный таймер. Ну и ещё возвращает ссылку на пак, но только для удобства.
    Отсюда ровно нету разницы, что сначала создать пак и передать ссылку на него в CreateTimer, или использовать CreateDataTimer. Отсюда не понимаю, почемы Вы их так явно разделили...

    Ну а если число логически, то CreateDataTimer вообще какой-то не логичный сток. По логике сначала формируем данные а потом их передаём, а не надеемся что данные будут сформированы ДО того как вызовется таймер..
     
  6. R1KO

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

    Сообщения:
    5.993
    Симпатии:
    2.989
    Dragon_Knight, по сути без разницы что там будет, Hanle задает конкретный тип данных, а any сообщает что он может быть любым.
     
  7. Dragon_Knight

    Dragon_Knight

    Сообщения:
    5
    Симпатии:
    0
    R1KO, именно это я и хотел уточнить.
    Я люблю писать кокретно и не двусмысленно. Если передаём ссылку, то и тип входной переменной тлько ссылка... Я даже проверки типа if(ValidPlayer(pid)) не признаю, пишу исключительно так: if(ValidPlayer(pid) == true).
     
    Последнее редактирование: 18 апр 2014
  8. Dragon_Knight

    Dragon_Knight

    Сообщения:
    5
    Симпатии:
    0
    Как более грамотно написать коллбек, который будет вызываться при завершении таймера. И что-бы его наличие в коде было не обязательно.. Т.е. в данном случае если не писать в коде : public OnCountdownHintTimerEnd(client, time, id); будет ошибка о том, что функция не найдена.