←  Problemy

AMXX.pl: Support AMX Mod X i SourceMod

»

Problem z timerem


Najlepsza odpowiedź Gargamel 14.06.2014 17:01

Bardzo dziękuję, teraz wszystko działa :)

Przejdź do postu
Zablokowany

  • +
  • -
Gargamel - zdjęcie Gargamel 13.06.2014

Witam.
Dzisiaj zacząłem pisać swój pierwszy plugin do CS'a.
Wraz z poradnikami, i z dawniejszymi doświadczeniami z Pawn (pisałem skrypty do gry SAMP), napisałem coś takiego:
#include <amxmodx>
#include <amxmisc>

#define PLUGIN "KickBots"
#define VERSION "0.1"
#define AUTHOR "Pan_Gargamel"

new g_kickmenu; // tworzymy zmienną globalną, uchwyt dla menu
new g_kickmenu_tak;
new g_kickmenu_nie;

public plugin_init() {
    register_plugin(PLUGIN, VERSION, AUTHOR);

    register_clcmd("say /kickbots", "kickmenu");
}

public plugin_cfg() { // tworzymy menu, np. w tej funkcji, bo wykonuje się ona tylko raz na mapę
    g_kickmenu = menu_create("Jestes za wyrzuceniem botow?", "kickmenuhandle");
    menu_additem(g_kickmenu, "Tak"); // item = 0
    menu_additem(g_kickmenu, "Nie"); // item = 1

    menu_setprop(g_kickmenu, MPROP_EXITNAME, "Wyjscie");
    
}

public kickmenu(id) {
    for(new i=0; i<32; i++)
    {
        if(!is_user_alive(i)) continue;
    
        menu_display(i, g_kickmenu)
        client_print(i, print_chat, "Gracz %id% rozpoczal glosowanie o wyrzucenie botow z serwera.");
        CreateTimer(30.0, kickmenu_wyniki);
    }
    
    return PLUGIN_HANDLED;
}

public kickmenuhandle(id, menu, item) { // funkcja posiada trzy parametry, id gracza, uchwyt menu oraz klawisz/item/opcję, która została wybrana
    if(item == MENU_EXIT) {
        return PLUGIN_HANDLED; // zamykamy menu, generalnie nie trzeba dodawać tutaj tego warunku, ale z przyzwyczajenia ja go tutaj dodaję, zresztą czasami nawet lepiej to robić na samej górze funkcji
    }

    switch(item) { // używamy switcha, pamiętamy, że wartość klawisza/itemu/opcji zaczyna się od 0
        case 0: {
            client_print(id, print_chat, "Zaglosowales za wyrzuceniem botow.");
            g_kickmenu_tak = g_kickmenu_tak + 1
        }
        case 1: {
            client_print(id, print_chat, "Zaglosowales przeciwko wyrzuceniu botow.");
            g_kickmenu_nie = g_kickmenu_nie + 1
        }
    }
public Action:kickmenu_wyniki(Handle:timer)
    {
        if(g_kickmenu_tak > g_kickmenu_nie || g_kickmenu_nie == g_kickmenu_tak)
        {
            amx_exec @SERVER "epb_removebots"
            for(new i=0; i<32; i++)
            {
                if(!is_user_alive(i)) continue;
                client_print(i, print_chat, "[Glosowanie] Boty zostaly wyrzucone z serwera!");
            }
        }
    }
    return PLUGIN_HANDLED;
}
Skrypt ma na celu robienie głosowania dla wszystkich graczy po wpisaniu /kickbots. Każdemu graczowi powinno się wyświetlić pytanie czy boty mają być wyrzucone, a jeśli po trzydziestu sekundach od startu głosowania suma głosów na tak będzie większa niż suma głosów na nie, boty zostaną wyrzucone.
 
Niektóre błędy udało mi się naprawić, ale kilku nie udało mi się rozwiązać:
bco7o8.jpg
GwynBleidD (14.06.2014 08:22):
Staraj się na przyszłość wklejać kod pluginu z numeracją linii i jako "czysty tekst" (przełączając się na edytor nie-graficzny lub używając przycisku wstawiania kodu), gdyż niektóre edytory (szczególnie amx_studio) wstawiają dodatkowo śmieci, jak dodatkowe puste linie, gdy wklejasz w edytorze graficznym. Więcej o tym tutaj: http://amxx.pl/topic...-kodu-na-forum/
Odpowiedz

  • +
  • -
VertekS - zdjęcie VertekS 14.06.2014

1. Nie ma takiej funkcji jak CreateTimer. Użyj set_task.

2. 

Action:kickmenu_wyniki(Handle:timer)

Zamień na:

public kickmenu_wyniki()

3. Funkcja kickmenuhandle nie jest zamknięta (brakuje nawiasu klamrowego na końcu funkcji).

4. W ten sposób nie wyrzuca się botów na serwerach CS'a. Najpierw musisz sprawdzić, czy gracz jest botem i wtedy wykonać na nim komendę AMXX - kick:

server_cmd("kick #%d ^"Gracz jest botem!^"", get_user_userid(id));

5. Po funkcji kickmenu_wyniki jest o jedna klamra za dużo.

6. Funkcja kickmenuhandle powinna zwracać wartość na końcu. Najlepiej zwrócić PLUGIN_HANDLED (i tak już nic nie robisz z tym menu po wybraniu opcji). Dodatkowo jeżeli wartość wybrana w menu to MENU_EXIT, zniszcz menu za pomocą:

menu_destroy(menu)

Kod jest brzydko napisany, ale to będziesz potrafił zoptymalizować sam p przeczytaniu artykułów w dziale tutoriale na tym forum (nie zawsze się operuje na 32 graczach / używa do tego pętli for). 

Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 14.06.2014

4. W ten sposób nie wyrzuca się botów na serwerach CS'a. Najpierw musisz sprawdzić, czy gracz jest botem i wtedy wykonać na nim komendę AMXX - kick:

A to zależy od botów :) Niektóre po kicknięciu ich z serwera po prostu wrócą i należy wykonać komendę, która wyłącza całkowicie boty, a nie je kickować. Ale to:
            amx_exec @SERVER "epb_removebots"
nie jest poprawnym wykonaniem jakiejkolwiek komendy. Do tego używamy server_exec.
server_cmd("kick #%d ^"Gracz jest botem!^"", get_user_userid(id));

Dodatkowo jeżeli wartość wybrana w menu to MENU_EXIT, zniszcz menu za pomocą:

menu_destroy(menu)

NIE NIE I JESZCZE RAZ NIE!! W tym przypadku menu_destroy NIE UŻYWAMY !!

menu_destroy używamy, gdy generujemy menu tuż przed jego wyświetleniem dla pojedynczego gracza i nie mamy zamiaru wyświetlać tego samego menu drugi raz. W tym przypadku menu jest generowane na początku działania pluginu i jest wyświetlane jedno dla wszystkich graczy, więc po użyciu menu_destroy będzie mógł zagłosować TYLKO JEDEN GRACZ, bo po zagłosowaniu menu już nie będzie istnieć!
Odpowiedz

  • +
  • -
Gargamel - zdjęcie Gargamel 14.06.2014

Teraz plugin kompiluje się bez żadnych błędów, lecz timer się nie uruchamia, a przynajmniej nie wykonuje się to co powinno po upłynięciu czasu.
 
Tutaj dałem set_task:
 

public kickmenu(id) {
    for(new i=0; i<32; i++)
    {
        if(!is_user_alive(i)) continue;
    
        menu_display(i, g_kickmenu)
        client_print(i, print_chat, "Gracz %id% rozpoczal glosowanie o wyrzucenie botow z serwera.");
        set_task(30.0, "kickmenu_wyniki", 666);
    }
    
    return PLUGIN_HANDLED;
}

 
A tutaj jest to co powinno się wykonać po 30 sekundach:
 

public kickmenu_wyniki()
{
    if(g_kickmenu_tak > g_kickmenu_nie || g_kickmenu_nie == g_kickmenu_tak)
    {
        server_cmd("pb removebots");
        for(new i=0; i<32; i++)
        {
            if(!is_user_alive(i)) continue;
            client_print(i, print_chat, "[Glosowanie] Boty zostaly wyrzucone z serwera!");
        }
    }
    else
    {
        for(new i=0; i<32; i++)
        {
            if(!is_user_alive(i)) continue;
            client_print(i, print_chat, "[Glosowanie] Boty nie zostaly wyrzucone z serwera!");
        }
    }
    return PLUGIN_HANDLED;
}

Użytkownik Gargamel edytował ten post 14.06.2014 13:47
Odpowiedz

  • +
  • -
VertekS - zdjęcie VertekS 14.06.2014

Więc tak...

To co napisze poniżej piszesz w public kickmenu(id).

Tworzysz 31 elementową tablicę na nick gracza (31 elementów = 31 znaków):

new voteplayer[31];

Następnie pobierasz nick gracza, który wpisał komendę:

get_user_name(id, voteplayer, sizeof(voteplayer));

Natyw register_clcmd przekazuje ID gracza jako parametr, więc warto to wykorzystać. Parametry funkcji zobacz w dokumentacji. Operator sizeof sprawdza wielkość łańcucha znaków (i nie tylko jego), co można w tym wypadku użyć do poinformowania get_user_name, ile liter nicku gracza ma pobrać. Warto pamiętać, że nick gracza w CS może mieć maksymalnie 31 liter. 

Następnie przejdź do linii:

client_print(i, print_chat, "Gracz %id% rozpoczal glosowanie o wyrzucenie botow z serwera.");

...która była powodem błędów. ID gracza w CS jest traktowane jak zwykła liczba całkowita. Trzeba tylko pamiętać, że to musi być liczba z zakresu 1 - 32.

W celu wyświetlenia, kto zaczął głosowanie wykorzystaj wcześniej przygotowaną zmienną na nick. Poprawny zapis wygląda tak:

client_print(i, print_chat, "Gracz %s rozpoczal glosowanie o wyrzucenie botow z serwera.", voteplayer);

Plugin będzie działać w 99% poprawnie. Podczas testów zauważyłem, że musisz się zabezpieczyć przed sytuacją, kiedy żaden gracz nie głosuje (obecnie w takiej sytuacji boty są wyrzucane z serwera).


Użytkownik VertekS edytował ten post 14.06.2014 16:41
Odpowiedz

  • +
  • -
Najlepsza odpowiedź Gargamel - zdjęcie Gargamel 14.06.2014

Bardzo dziękuję, teraz wszystko działa :)

Odpowiedz
Zablokowany