Написание плагинов

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
@Hollya, криво работать будет, ибо переменная статическая при смене карты или после выполнения команды не будет возвращаться в норм вид.
 

Hollya

❤ GIRL SCRIPTER ❤
Сообщения
128
Реакции
32
@Hollya, криво работать будет, ибо переменная статическая при смене карты или после выполнения команды не будет возвращаться в норм вид.
Это же лишь пример, не так сложно добавить убийство таймера.
Достаточно почитать [SourcePawn] Урок 6 - Таймеры и все будет у него. У него нету желание сделать что-то самому, а надо чтобы сделали за него.
 

Felton

Участник
Сообщения
799
Реакции
59
@Seton1447
Да забей ты на этот плрагин.Невижу целеособразности егго в исполвзованин
 
Последнее редактирование:

Mensi1337

Участник
Сообщения
242
Реакции
16
Покажи как ты реализовал отсчет.
Если что то не так поправь )
PHP:
#include <sourcemod>
#undef REQUIRE_PLUGIN
#include <adminmenu>

new Handle:hTopMenu;

public OnPluginStart()
{
    RegAdminCmd("sm_restart", Cmd_Restart, ADMFLAG_ROOT);

    new Handle:topmenu;
    if(LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) OnAdminMenuReady(topmenu);
}

public OnLibraryRemoved(const String:name[])
{
    if(StrEqual(name, "adminmenu")) hTopMenu = INVALID_HANDLE;
}

public OnAdminMenuReady(Handle:topmenu)
{
    if(topmenu == hTopMenu) return;

    hTopMenu = topmenu;

    new TopMenuObject:server_cmds = FindTopMenuCategory(hTopMenu, ADMINMENU_SERVERCOMMANDS);

    if(server_cmds != INVALID_TOPMENUOBJECT) AddToTopMenu(hTopMenu, "sm_restart", TopMenuObject_Item, AdminMenu_Restart, server_cmds, "sm_restart", ADMFLAG_ROOT);
}

public AdminMenu_Restart(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength)
{
    switch(action)
    {
        case TopMenuAction_DisplayOption:    Format(buffer, maxlength, "Перезагрузить сервер", param);
        case TopMenuAction_SelectOption:    Restart(param);
    }
}

public Action:Cmd_Restart(client, args)
{
    Restart(client);

    return Plugin_Handled;
}

stock Restart(client)
{
    CreateTimer(1.0, Timer_Restart, _, TIMER_REPEAT);
}

public Action:Timer_Restart(Handle:timer)
{
    static iTimer = 10;
    if(--iTimer == 0)
    {
        PrintCenterTextAll("Перезагрука сервера.");
        PrintToChatAll("\x04[SM] \x01Перезагрука сервера.");
        ServerCommand("_restart");
        return Plugin_Stop;
    }
    PrintCenterTextAll("Перезагрука сервера через %d секунд.", iTimer);
 
    return Plugin_Continue;
}
 

Hollya

❤ GIRL SCRIPTER ❤
Сообщения
128
Реакции
32
Если что то не так поправь )
PHP:
#include <sourcemod>
#undef REQUIRE_PLUGIN
#include <adminmenu>

new Handle:hTopMenu;

public OnPluginStart()
{
    RegAdminCmd("sm_restart", Cmd_Restart, ADMFLAG_ROOT);

    new Handle:topmenu;
    if(LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) OnAdminMenuReady(topmenu);
}

public OnLibraryRemoved(const String:name[])
{
    if(StrEqual(name, "adminmenu")) hTopMenu = INVALID_HANDLE;
}

public OnAdminMenuReady(Handle:topmenu)
{
    if(topmenu == hTopMenu) return;

    hTopMenu = topmenu;

    new TopMenuObject:server_cmds = FindTopMenuCategory(hTopMenu, ADMINMENU_SERVERCOMMANDS);

    if(server_cmds != INVALID_TOPMENUOBJECT) AddToTopMenu(hTopMenu, "sm_restart", TopMenuObject_Item, AdminMenu_Restart, server_cmds, "sm_restart", ADMFLAG_ROOT);
}

public AdminMenu_Restart(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength)
{
    switch(action)
    {
        case TopMenuAction_DisplayOption:    Format(buffer, maxlength, "Перезагрузить сервер", param);
        case TopMenuAction_SelectOption:    Restart(param);
    }
}

public Action:Cmd_Restart(client, args)
{
    Restart(client);

    return Plugin_Handled;
}

stock Restart(client)
{
    CreateTimer(1.0, Timer_Restart, _, TIMER_REPEAT);
}

public Action:Timer_Restart(Handle:timer)
{
    static iTimer = 10;
    if(--iTimer == 0)
    {
        PrintCenterTextAll("Перезагрука сервера.");
        PrintToChatAll("\x04[SM] \x01Перезагрука сервера.");
        ServerCommand("_restart");
        return Plugin_Stop;
    }
    PrintCenterTextAll("Перезагрука сервера через %d секунд.", iTimer);
 
    return Plugin_Continue;
}

Убийство таймера не сделал.
 

Hollya

❤ GIRL SCRIPTER ❤
Сообщения
128
Реакции
32

Hollya

❤ GIRL SCRIPTER ❤
Сообщения
128
Реакции
32
Внимательно, все равно не понимаю
--- Добавлено позже ---
Я на примерном плагине лучше понимаю
Плохо смотрел.

PHP:
/*
При написании игроком команды выводим ему сообщение в чат, и повторно команду он сможет написать только через 30 сек в этом же раунде.
Конечно это можно сделать куда оптимальнее и без таймеров но это просто как пример.
*/


#define DELAY    30.0    // Вынесем задержку в макрос для более удобно корректировки

Handle g_hTimer[MAXPLAYERS+1];

public void OnPluginStart()
{
    RegConsoleCmd("sm_timer", Timer_CMD);
    HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
}

public void Event_RoundStart(Event hEvent, const char[] sEvName, bool bDontBroadcast)    // Начался новый раунд
{
    for(int i = 1; i <= MaxClients; ++i)    // Цикл по всем игрокам
    {
        if(g_hTimer[i])    // Проверяем что таймер активен
        {
            KillTimer(g_hTimer[i]);    // Уничтожаем таймер
            g_hTimer[i] = null;        // Обнуляем значения дескриптора
        }
    }
}

public Action Timer_CMD(int iClient, int iArgs) // Игрок написал команду
{
    if(iClient)
    {
        if(g_hTimer[i])    // Если таймер активен
        {
            PrintToChat(iClient, "Команда еще недоступна!");
            return Plugin_Handled;
        }

        // Выводим игроку сообщение
        PrintToChat(iClient, "Вы ввели команду и сможете её повторно использовать через %i сек.", DELAY);
        g_hTimer[iClient] = CreateTimer(DELAY, Timer_Delay, iClient);    // Можем передать сразу индекс т.к. если игрок выйдет мы сразу уничтожим его таймер
    }

    return Plugin_Handled;
}

public void OnClientDisconnect(int iClient)    // Игрок отключился
{
    if(g_hTimer[iClient])    // Проверяем что таймер активен и уничтожаем
    {
        KillTimer(g_hTimer[iClient]);    // Уничтожаем таймер
        g_hTimer[iClient] = null;        // Обнуляем значения дескриптора
    }
}

public Action Timer_Delay(Handle hTimer, any iClient) // Каллбек нашего таймера
{
    g_hTimer[iClient] = null;        // Обнуляем значения дескриптора
    return Plugin_Stop;
}
 

Mensi1337

Участник
Сообщения
242
Реакции
16
Плохо смотрел.

PHP:
/*
При написании игроком команды выводим ему сообщение в чат, и повторно команду он сможет написать только через 30 сек в этом же раунде.
Конечно это можно сделать куда оптимальнее и без таймеров но это просто как пример.
*/


#define DELAY    30.0    // Вынесем задержку в макрос для более удобно корректировки

Handle g_hTimer[MAXPLAYERS+1];

public void OnPluginStart()
{
    RegConsoleCmd("sm_timer", Timer_CMD);
    HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
}

public void Event_RoundStart(Event hEvent, const char[] sEvName, bool bDontBroadcast)    // Начался новый раунд
{
    for(int i = 1; i <= MaxClients; ++i)    // Цикл по всем игрокам
    {
        if(g_hTimer[i])    // Проверяем что таймер активен
        {
            KillTimer(g_hTimer[i]);    // Уничтожаем таймер
            g_hTimer[i] = null;        // Обнуляем значения дескриптора
        }
    }
}

public Action Timer_CMD(int iClient, int iArgs) // Игрок написал команду
{
    if(iClient)
    {
        if(g_hTimer[i])    // Если таймер активен
        {
            PrintToChat(iClient, "Команда еще недоступна!");
            return Plugin_Handled;
        }

        // Выводим игроку сообщение
        PrintToChat(iClient, "Вы ввели команду и сможете её повторно использовать через %i сек.", DELAY);
        g_hTimer[iClient] = CreateTimer(DELAY, Timer_Delay, iClient);    // Можем передать сразу индекс т.к. если игрок выйдет мы сразу уничтожим его таймер
    }

    return Plugin_Handled;
}

public void OnClientDisconnect(int iClient)    // Игрок отключился
{
    if(g_hTimer[iClient])    // Проверяем что таймер активен и уничтожаем
    {
        KillTimer(g_hTimer[iClient]);    // Уничтожаем таймер
        g_hTimer[iClient] = null;        // Обнуляем значения дескриптора
    }
}

public Action Timer_Delay(Handle hTimer, any iClient) // Каллбек нашего таймера
{
    g_hTimer[iClient] = null;        // Обнуляем значения дескриптора
    return Plugin_Stop;
}
KillTimer(g_hTimer)?
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,521
Реакции
4,980
криво работать будет, ибо переменная статическая при смене карты или после выполнения команды не будет возвращаться в норм вид.
ну если использовать для рестарта, то не имеет никакой разницы, т.к. сервер будет перезапущен и все переменные исчезнут из ОЗУ.
 

AleksandrM3

Участник
Сообщения
137
Реакции
2
Кто может переделать чтобы команду могли запускать не только админы, но и игроки,
в идеале нужно чтобы на какую нибудь команду например !ex запускалось голосование за продление карты, в отсутствии админа, ну или чтобы любой мог запустить как тут

PHP:
PHP:
#include <sourcemod>

public OnPluginStart()
{
    RegAdminCmd("ex", ExtendedMap, ADMFLAG_RESERVATION);
}

public Action:ExtendedMap(client, args)
{
    if (client > 0)
    {
        if (args != 1)
        {
            ReplyToCommand(client, "[SM] Используйте !ex <time>");
        }
        else
        {
            decl String:time[100];
            GetCmdArg(1, time, sizeof(time));
            ServerCommand("mp_timelimit %d", (GetConVarInt(FindConVar("mp_timelimit")) + StringToInt(time)));
            ReplyToCommand(client, "[SM] Вы продлили время карты");
        }        
    }
    return Plugin_Handled;
}
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,521
Реакции
4,980
@Seton1447, пробуй
PHP:
#include <sourcemod>
#undef REQUIRE_PLUGIN
#include <adminmenu>

new Handle:hTopMenu,
    bool:bInCountdown;

public OnPluginStart()
{
    RegAdminCmd("sm_restart", Cmd_Restart, ADMFLAG_ROOT);

    new Handle:topmenu;
    if(LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) OnAdminMenuReady(topmenu);
}

public OnLibraryRemoved(const String:name[])
{
    if(StrEqual(name, "adminmenu")) hTopMenu = INVALID_HANDLE;
}

public OnAdminMenuReady(Handle:topmenu)
{
    if(topmenu == hTopMenu) return;

    hTopMenu = topmenu;

    new TopMenuObject:server_cmds = FindTopMenuCategory(hTopMenu, ADMINMENU_SERVERCOMMANDS);

    if(server_cmds != INVALID_TOPMENUOBJECT) AddToTopMenu(hTopMenu, "sm_restart", TopMenuObject_Item, AdminMenu_Restart, server_cmds, "sm_restart", ADMFLAG_ROOT);
}

public AdminMenu_Restart(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength)
{
    switch(action)
    {
        case TopMenuAction_DisplayOption:    Format(buffer, maxlength, "Перезагрузить сервер", param);
        case TopMenuAction_SelectOption:    Restart(param);
    }
}

public Action:Cmd_Restart(client, args)
{
    Restart(client);

    return Plugin_Handled;
}

stock Restart(client)
{
    if(bInCountdown) return;

    PrintCenterTextAll("Сервер будет перезагружен через 3 сек.");
    CreateTimer(1.0, Timer_Restart, TIMER_REPEAT);
}

public Action:Timer_Restart(Handle:timer)
{
    bInCountdown = true;
    static int time = 3;
    if(--time < 1)
    {
        PrintCenterTextAll("Сервер перезагружается.");
        if(time == -1) ServerCommand("_restart");
    }
    else PrintCenterTextAll("Сервер будет перезагружен через %d сек.", time);

    return Plugin_Continue;
}
 

Вложения

  • Restart.sp
    1.8 КБ · Просмотры: 14
  • Restart.smx
    5.4 КБ · Просмотры: 6

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
ну если использовать для рестарта, то не имеет никакой разницы, т.к. сервер будет перезапущен и все переменные исчезнут из ОЗУ.
Конкретно в этом кейсе применения - да.
Но я сейчас вообще говорю.
 
Сверху Снизу