←  Pytania

AMXX.pl: Support AMX Mod X i SourceMod

»

[ROZWIĄZANE] Jak stworzyc menu z listą gra...


Najlepsza odpowiedź Droso 24.11.2013 21:08

Myślę, że łatwiej będzie Ci to zrozumieć:

 

Najpierw tworzymy jakby uchwyt i nazwę naszego menu:

new menu = menu_create("Lista Graczy:", "menu_handler");

Następnie przystępujemy to pętli, ty użyłeś do tego jeszcze funkcji get_players, ale ja osobiście jej nie lubię :D, bo zawiera błędy itd.

Dlatego użyjemy samej pętli :)

Najpierw zmienne

new maxplayers = get_maxplayers(); // ile osob moze byc maksymalnie na serwerze
new name[32] // zmienna przechowujaca nick gracza
new data[6] // to bedzie ID gracza, ktore wysylamy w info :)

Teraz pętla:

for(new i=1; i<=maxplayers; i++)  // pętla od 1 DO MAKSYMALNEJ LICZBY GRACZY
{
     if(!is_user_connected(i))
          continue;      // jezeli gracz o danym ID (i) nie jest polaczony to go pomijamy uzwajać "continue"
 
     if(is_user_hltv(i) || is_user_bot(i))
          continue;    // jezeli dane ID to HLTV/BOT - pomijamy!

     num_to_str(i, data, 5);
     get_user_name(id, name, 31);  // pobieramy nick
     menu_additem(menu, name, data);  // dodajemy do menu gracza.
}


Zakończenie menu, czyli wyświetlelnie:

menu_display(id, menu, item);

Teraz funkcja menu_handler :)


public menu_handler(id, menu, item)
{
	if(item == MENU_EXIT)  // jezeli gracz wyszedl z MENU - nic nie robimy :)
	return;
	
	if(!is_user_connected(id))  // jezeli gracz, ktory wybieral cos z menu nie jest polaczony to konczymy interakcje :D
	return; 
	
	// zmienne sa wymagane ;(
	new name[32]; // ta zmienna bedzie przechowywala nick gracza, a inaczej tekst wybranej czesci menu.
	new callback; // to jest callback na razie Ci nie potrzebny nie zwracaj uwagi
	new data[6]; // to będzie ID gracza ;)
	new dostep; // to Ci nie potrzebne;
	
	menu_item_getinfo(menu, item, dostep, data, 5, name, 31, callback); // pobieramy dane wybranego/ej itemu/opcji z menu!
	
	new id2 = str_to_num(data);
	
	if(!is_user_connected(id2))
	return;
	
	
	// id2 - to id gracza wybranego z menu :)
	// name - to jego nick.
	
	client_print(id, print_chat, "Wybrales gracza: %s o ID: %d", name, id2); :)
}

Proszę.

Nie rozumiesz, pisz - wytłumaczymy w tym temacie.

 

Przejdź do postu
Zablokowany

  • +
  • -
Mister Silenzo - zdjęcie Mister Silenzo 24.11.2013

Witam, piszę ten temat gdyż utknąłem w martwym punkcie. Bardzo chciałem stworzyć w/w menu, tylko nie do końca wiem jak, a nie chcę wzorować się na gotowcach, bo tak się nic nie nauczę i nie chcę też dostawać tutaj gotowych odpowiedzi, a raczej proszę o naprowadzenie mnie na właściwe rozwiązanie.

public plugin_init() {
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	register_clcmd("say /menu", "menu_handle")
}

public menu_handle(id)
{
	new menu = menu_create("Lista graczy:", "menu_handler")
	new players[32], num, name[32]
	get_players(players, num)
	for(new i = 1; i<num; i++){
	get_user_name(i, name, 31)
	menu_additem(menu, name)
	}
	
	menu_display(id, menu)
}

public menu_handler(id, menu, item)
{
	switch(item)
	{
		case 0:
		{
			client_print(id, print_chat, "Wybrales gracza %s" /*i nie wiem jak pobrac teraz poprawnie nazwe gracza bez tworzenia nowych zmiennych etc.*/)
		}
	}
}
Tutaj fragment kodu. Za pomoc będę wdzięczny ;> Daję +
Odpowiedz

  • +
  • -
Najlepsza odpowiedź Droso - zdjęcie Droso 24.11.2013

Myślę, że łatwiej będzie Ci to zrozumieć:

 

Najpierw tworzymy jakby uchwyt i nazwę naszego menu:

new menu = menu_create("Lista Graczy:", "menu_handler");

Następnie przystępujemy to pętli, ty użyłeś do tego jeszcze funkcji get_players, ale ja osobiście jej nie lubię :D, bo zawiera błędy itd.

Dlatego użyjemy samej pętli :)

Najpierw zmienne

new maxplayers = get_maxplayers(); // ile osob moze byc maksymalnie na serwerze
new name[32] // zmienna przechowujaca nick gracza
new data[6] // to bedzie ID gracza, ktore wysylamy w info :)

Teraz pętla:

for(new i=1; i<=maxplayers; i++)  // pętla od 1 DO MAKSYMALNEJ LICZBY GRACZY
{
     if(!is_user_connected(i))
          continue;      // jezeli gracz o danym ID (i) nie jest polaczony to go pomijamy uzwajać "continue"
 
     if(is_user_hltv(i) || is_user_bot(i))
          continue;    // jezeli dane ID to HLTV/BOT - pomijamy!

     num_to_str(i, data, 5);
     get_user_name(id, name, 31);  // pobieramy nick
     menu_additem(menu, name, data);  // dodajemy do menu gracza.
}


Zakończenie menu, czyli wyświetlelnie:

menu_display(id, menu, item);

Teraz funkcja menu_handler :)


public menu_handler(id, menu, item)
{
	if(item == MENU_EXIT)  // jezeli gracz wyszedl z MENU - nic nie robimy :)
	return;
	
	if(!is_user_connected(id))  // jezeli gracz, ktory wybieral cos z menu nie jest polaczony to konczymy interakcje :D
	return; 
	
	// zmienne sa wymagane ;(
	new name[32]; // ta zmienna bedzie przechowywala nick gracza, a inaczej tekst wybranej czesci menu.
	new callback; // to jest callback na razie Ci nie potrzebny nie zwracaj uwagi
	new data[6]; // to będzie ID gracza ;)
	new dostep; // to Ci nie potrzebne;
	
	menu_item_getinfo(menu, item, dostep, data, 5, name, 31, callback); // pobieramy dane wybranego/ej itemu/opcji z menu!
	
	new id2 = str_to_num(data);
	
	if(!is_user_connected(id2))
	return;
	
	
	// id2 - to id gracza wybranego z menu :)
	// name - to jego nick.
	
	client_print(id, print_chat, "Wybrales gracza: %s o ID: %d", name, id2); :)
}

Proszę.

Nie rozumiesz, pisz - wytłumaczymy w tym temacie.

 


Droso (24.11.2013 21:09):
Wszystko pisane z pamięci - mogą być literówki.
Odpowiedz

  • +
  • -
Mister Silenzo - zdjęcie Mister Silenzo 24.11.2013

O co chodzi z przypisaniem zmiennej data jako info itemu w pętli (To jest potrzebne do menu_item_getinfo, tak?)? Dlaczego w menu_handler nie ma switch(item) i temu podobnych rzeczy? Czy funkcja menu_handler stała się jedną dla wszystkich itemów? Mam rozumieć, że wartość "data" w "new id2 = num_to_str(data)" jest pobierana z powyższego "item_menu_getinfo"?


To chyba tyle jeżeli chodzi o pytania :D

PS.

[..]a nie chcę wzorować się na gotowcach, bo tak się nic nie nauczę i nie chcę też dostawać tutaj gotowych odpowiedzi, a raczej proszę o naprowadzenie mnie na właściwe rozwiązanie.

Ale i tak dzięki za szybką reakcję :P
Odpowiedz

  • +
  • -
Droso - zdjęcie Droso 24.11.2013

O co chodzi z przypisaniem zmiennej data jako info itemu w pętli (To jest potrzebne do menu_item_getinfo, tak?)?

Tak, parametr info w menu_additem - jest bardzo przydatny - możesz umieścić tam ID gracza (tylko najpierw trzeba zamienić liczbę na string num_to_str) i wiele innych rzeczy.

Właściwie ty chciałeś tylko nick gracza, ale ja jeszcze w handlerze pobrałem Ci ID gracza właśnie dzięki temu służy info.

Funkcją menu_item_getinfo pobierasz informacje o wybranej opcji (itemie) z menu - ja pobrałem zawartość tekstową opcji czyli nick oraz info - czyli ID w stringu (jeszcze pobrałem callbacka i dostęp - ale o tym poczytaj w poradniku w dziale Turtoriale)

Następnie zamieniłem string na liczbę (str_to_num) - następnie sprawdziłem, czy ten gracz jest jeszcze na serwerze :).

Tak podałem Ci jeszcze ID gracza mimo iż prosiłeś tylko o nick - ale jak wiemy mając ID możemy też pobrać nick :), więc ID daje nam więcej możliwości.

 

 

 

Czy funkcja menu_handler stała się jedną dla wszystkich itemów?

Zawsze tak jest - tylko zmienia się parametr item w funkcji (trzeci parametr).

ITEM nie jest równe ID gracza wybranego - dlatego to info między innymi :).

 

 

 

Mam rozumieć, że wartość "data" w "new id2 = num_to_str(data)" jest pobierana z powyższego "item_menu_getinfo"?

Tak - wyżej zgrubsza to wyjaśniłem w dokumentacji powinno być to bardziej opisane. -> menu_item_getinfo

 

 

PS.

[..]a nie chcę wzorować się na gotowcach, bo tak się nic nie nauczę i nie chcę też dostawać tutaj gotowych odpowiedzi, a raczej proszę o naprowadzenie mnie na właściwe rozwiązanie.

Ale i tak dzięki za szybką reakcję :P

 

 

Sorki, ale cięzko to przedstawić bez dokładnych przykładów itd., lepiej podać tak niż bez żadnych moich komentarzy ^^


Użytkownik HubertTM edytował ten post 24.11.2013 22:11
Odpowiedz

  • +
  • -
Mister Silenzo - zdjęcie Mister Silenzo 24.11.2013

Wielkie dzięki, jak będę miał wątpliwości to zgłoszę się na PW :P


@@edit

PS. Popraw literówki, bo ktoś może nie zauważyć, że w
client_print(id, print_chat, "Wybrales gracza: %s o ID: %d", name, id2); :)
uśmieszek jest niezakomentowany i potem dziwić się, że się nie skompiluje :P

@@edit2

public plugin_init() {
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	register_clcmd("say /menu", "menu_handle")
}

public menu_handle(id)
{
	new menu = menu_create("Lista graczy:", "menu_handler")
	new maxplayers = get_maxplayers()
	new name[32], data[6]
	
	for(new i=1;i<=maxplayers;i++) {
	if(!is_user_connected(i))
		continue;
		
	if(!is_user_hltv(i) || !is_user_bot(i))
		continue;
	
	num_to_str(i, data, 5);
	get_user_name(i, name, 31);
	menu_additem(menu, name, data);
	}
	menu_display(id, menu)
}

public menu_handler(id, menu, item)
{
	if(item == MENU_EXIT)
	return;
	
	if(!is_user_connected(id))
	return;
	
	new name[32]
	new callback
	new data[6]
	new dostep
	
	menu_item_getinfo(menu, item, dostep, data, 5, name, 31, callback);
	
	new id2 = str_to_num(data);
	
	if(!is_user_connected(id2))
	return;
	
	client_print(id, print_chat, "Wybrales gracza %s o id: %d", name, id2);
}

Wygląda to tak, ale po wpisaniu na say /menu nic się nie dzieje Dx.
Użytkownik Mister Silenzo edytował ten post 24.11.2013 22:40
Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 25.11.2013

[code=pawn:27]    if(!is_user_hltv(i) || !is_user_bot(i))
        continue;[/pawn]

Warunek ten oznacza:

Jeśli gracz NIE jest HLTV lub NIE jest botem, pomiń jego dodawanie do menu (instrukcja continue pomija bieżące wykonanie pętli i przeskakuje do następnego). Co oznacza, że w menu dostaniesz tylko graczy, którzy są jednocześnie HLTV i botami, a tacy nie istnieją. Dlatego nic się nie dzieje :)

 

Prawidłowo powinno być bez wykrzykników, wtedy nie negujesz warunków.

 

Co do menu, podpowiem tylko, że jeśli korzystasz z ID gracza to możesz wywołać przypadkiem opcję z menu dla gracza, który już opuścił serwer, a na jego miejsce wszedł inny. Dlatego dobrze jest w takich miejscach użyć zamiast ID, userid, które jest zawsze unikalne, więc jak gracz opuści serwer, to na 100% będziesz o tym wiedział :)

Odpowiedz

  • +
  • -
Mister Silenzo - zdjęcie Mister Silenzo 25.11.2013

No tak, nie zauważyłem błędu w tej negacji ;_; Mówiąc userid masz na myśli SID i "SID" z revEmu, tak?
Odpowiedz

  • +
  • -
sebul - zdjęcie sebul 25.11.2013

No tak, nie zauważyłem błędu w tej negacji ;_; Mówiąc userid masz na myśli SID i "SID" z revEmu, tak?

get_user_userid
Odpowiedz

  • +
  • -
Droso - zdjęcie Droso 25.11.2013

Dlatego dobrze jest w takich miejscach użyć zamiast ID, userid, które jest zawsze unikalne, więc jak gracz opuści serwer, to na 100% będziesz o tym wiedział :)

Gwynu masz rację - ale jaka jest szansa, że to nastąpi? Gracz musi wyjść i wejść ktoś na serwer i musi to ID być aktualnie najmniejsze :P + menu musi być prawdopodobnie bardzo wolno wciskane :P.

 

Owszem masz rację, ale po co chłopakowi utrudniać może zrobić tak w menu_handler:

 

Pobiera nick gracza i sprawdza czy taką samą opcję wybrał (pobieramy nazwę itemu menu_item_getinfo)

 

czyli:

new name2[32];
get_user_name(id2, name2, 31)

if(equal(name, name2))
// tego samego gracza wybral

Oczywiście narażamy się na zmianę nicku, ale przynajmniej kod się nie wykona :P, i wcale koledze nie utrudnimy sprawdzania tego gracza :P, bo jak byśmy użyli userid to musiałby pętli użyć :P

 

 

Średni z tego argument, ale jednak jak ja bym się uczył to nie wiedział bym jak użyć twej wskazówki.

Dlatego jeśli Mister Silenzo jest ciekaw o co chodzi Gwynowi :P

 

 

Wystarczy użyć tego:

for(new i=1; i<=maxplayers; i++)  // pętla od 1 DO MAKSYMALNEJ LICZBY GRACZY
{
     if(!is_user_connected(i))
          continue;      // jezeli gracz o danym ID (i) nie jest polaczony to go pomijamy uzwajać "continue"
 
     if(is_user_hltv(i) || is_user_bot(i))
          continue;    // jezeli dane ID to HLTV/BOT - pomijamy!

     num_to_str(get_user_userid(i), data, 5);
     get_user_name(id, name, 31);  // pobieramy nick
     menu_additem(menu, name, data);  // dodajemy do menu gracza.
}

oraz tego:

public menu_handler(id, menu, item)
{
	if(item == MENU_EXIT)
	return;
	
	if(!is_user_connected(id))
	return;
	
	new name[32]
	new callback
	new data[6]
	new dostep
	
	menu_item_getinfo(menu, item, dostep, data, 5, name, 31, callback);
	
	new userid = str_to_num(data);
	new id2 = get_id_by_userid(userid);
        
        if(!id2)
        return;
	
	client_print(id, print_chat, "Wybrales gracza %s o id: %d", name, id2);
}

stock get_id_by_userid(userid){
     for(new i=1; i<33; i++) // tutaj warto dodac zmienna z maxplayers graczy
          if(is_user_connected(i) && get_user_userid(i) == userid)
               return i;

     return 0;
}

Można też użyć cmd_target, ale i tak moja wersja jest raczej lepsza :P


Droso (25.11.2013 21:41):
Literówki ponownie możliwe - pisane z pamięci ;)
Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 25.11.2013

Jakie są szanse? Często podaję ten sam przykład z autopsji: na jednym z serwerów moich jest plugin na transfer kasy, wpisujesz w czacie /transfer, wybierasz komu i ile kasy chcesz przekazać i przekazuje tyle i tyle kasy. Często niestety się gracze skarżyli, że kasa idzie do nie tej osoby, którą wybrali w menu... właśnie przez brak takiego sprawdzenia... Przy pełnym 32 slotowym serwerze jest bardzo duża szansa, że ktoś akurat po kimś innym ID zajmie w mgnieniu oka...

Odpowiedz
Zablokowany