←  Problemy

AMXX.pl: Support AMX Mod X i SourceMod

»

[ROZWIĄZANE] Jedna z pozycji w menu zachow...


Najlepsza odpowiedź GwynBleidD 09.06.2013 21:32

Dobrze, przyjrzyjmy się Callbackowi...:

public mcbMyMenuCT(id, menu, item)
{
    if(id != g_Simon || cs_get_user_team(id) == CS_TEAM_T && item > 0)
    {
        return ITEM_DISABLED;
    }
    else
    {
        return ITEM_ENABLED;
    }
    if(id == g_Simon || cs_get_user_team(id) == CS_TEAM_T || get_user_flags( id ) & MENUSIMONA_DOSTEP && item == 0)
    {
        return ITEM_DISABLED;
    }
    else
    {
        return ITEM_ENABLED;
    }
    return ITEM_DISABLED;
}

Linia 50: sprawdzasz czy gracz jest simonem lub czy posiada flagę i item jest większy od 0. Z kolejności wykonywania operatorów wynika, że item > 0 przyczepi się do sprawdzenia teamu, więc równoznaczny zapis (dodałem nawias, który NIC nie zmienia, ale pokazuje jak warunek się zachowa):

if(id != g_Simon || ( cs_get_user_team(id) == CS_TEAM_T && item > 0 ) )

Więc gdy ktoś NIE jest simonem zablokuje mu wszystkie opcje, gdy jest simonem, ale jest w CT, zablokuje mu wszystkie zaczynając od 2giej. Prawidłowy warunek (i think):

if( (id != g_Simon || ( cs_get_user_team(id) == CS_TEAM_T) && item > 0 ) )

Ten warunek zadziała już tak, że zablokuje wszystkie opcje prócz 1szej. Ale to nie jedyny błąd...

 

Popatrzmy na linię 54. Co to oznacza? Ano to, że kod od linii 58 do 66 mógłby nie istnieć, bo albo wykona się return z linii 52. albo z 56. Widzisz już ten błąd? Teraz zaczyna się prawdziwa jazda... bo będziemy mieli mnóstwo warunków... więc polecam przepisać kod na nowo, dzięki czemu będzie czytelny dużo bardziej. Oto przepisany kod:

public mcbMyMenuCT(id, menu, item)
{
    if (cs_get_user_team != CS_TEAM_CT && !(get_user_flags( id ) & MENUSIMONA_DOSTEP))
        return ITEM_DISABLED;
 
    if (item == 0) {
        if (id == g_Simon)
            return ITEM_DISABLED;
    } else {
        if(id != g_Simon)
            return ITEM_DISABLED;
    }
 
    return ITEM_ENABLED;
}
       
 

Krótki opis:

Linia 50. Gdy ktoś nie jest w CT i nie ma flagi dostępu do menu simona (sprawdzając warunek, czy ktoś jest w TT dawałeś dostęp dla spectów, uważaj na to!), nie powinien mieć dostępu do ŻADNEJ opcji. Zwracamy więc Disabled

Linia 53. Gdy item == 0, zwracamy więc DISABLED gdy gracz jest simonem

Linia 56. Item nie jest 0, więc zwracamy DISABLED gdy gracz nie jest simonem

Linia 61. Gdy żadne z powyższych nie zaistniało, zwracamy ENABLED.

 

W ten sposób kod jest bardzo zgrabny i przejrzysty. Warunki nie są namieszane (tak, wiem że można to zrobić jednym IFem, ale nie tędy droga... nawet byś się zdziwił jak tego IFa można pokręcić by go skrócić i żeby poprawnie działało, ale pogubiłbyś się w tym, tak jak w swoim pierwotnym kodzie) i łatwo idzie dojść do tego, kiedy co następuje :)

 

I jedna uwaga: Callback jest wykonywany przy WYŚWIETLANIU menu, nie przy wybraniu pozycji. Więc może zaistnieć sytuacja, gdy ktoś otworzy menu i np zmieni team, a następnie wybierze opcję która dla niego nie jest przeznaczona. Tak samo może nagle stać się simonem, dlatego w handlerze menu musisz jeszcze raz warunki sprawdzić, co by zamieszania nie było :D

Przejdź do postu
Zablokowany

  • +
  • -
szelbi - zdjęcie szelbi 10.03.2013

Witam. Posiadam w swoim pluginie menu wraz z callbackiem (SMA poniżej). Pozycja "Prowadz" powinna być nieaktywna dla prowadzącego, natomiast aktywna dla innych osób, które nim nie są. Niestety, coś nie działa i pozycja ta zachowuje się tak jak pozostałe, tj. kolejne po niej. Nie wiem, czy źle napisałem if'a, czy coś innego, więc proszę o pomoc.

if (cs_get_user_team(id) == CS_TEAM_CT || get_user_flags( id ) & MENUSIMONA_DOSTEP)
{
new menu = menu_create("Wybierz czynnosc:", "simon_choice");
formatex(option, charsmax(option), "Prowadz")
menu_additem(menu, option, "1", 0, Szare)

formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_OPEN")
menu_additem(menu, option, "2", 0, Szare)

formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_FD")
menu_additem(menu, option, "3", 0, Szare)

formatex(option, charsmax(option), "Menu Duszka")
menu_additem(menu, option, "4", 0, Szare)

if (g_GameMode == 1)
{
  formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_CLR")
  menu_additem(menu, option, "5", 0)
}

else
{
  formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_CLR")
  menu_additem(menu, option, "5", 0)
}

formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_GONG")
menu_additem(menu, option, "6", 0, Szare)

formatex(option, charsmax(option), "Losuj wieznia")
menu_additem(menu, option, "7", 0, Szare)

formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_PUNISH")
menu_additem(menu, option, "8", 0, Szare)

formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_SIMON_GAMES")
menu_additem(menu, option, "9", 0, Szare)

formatex(option, charsmax(option), "%L",LANG_SERVER, "UJBM_MENU_BIND")
menu_additem(menu, option, "10", 0)

menu_display(id, menu)

}
return PLUGIN_HANDLED
}
public mcbMyMenuCT(id, menu, item)
{
if(id != g_Simon || cs_get_user_team(id) == CS_TEAM_T && item > 0)
{  
return ITEM_DISABLED;
}
else
{
return ITEM_ENABLED;
}
if(id == g_Simon || cs_get_user_team(id) == CS_TEAM_T || get_user_flags( id ) & MENUSIMONA_DOSTEP && item == 0)
{
return ITEM_DISABLED;
}
else
{
return ITEM_ENABLED;
}
return ITEM_DISABLED;
}

Z góry dziękuję.
Odpowiedz

  • +
  • -
szelbi - zdjęcie szelbi 11.03.2013

Odświeżam.
Odpowiedz

  • +
  • -
Andrzejek - zdjęcie Andrzejek 18.03.2013

Może tak?

if (zmienna sprawdzajaca czy gracze maja simona)
{
formatex(option, charsmax(option), "Prowadz")
menu_additem(menu, option, "1", 0, Szare)

}
else
{
formatex(option, charsmax(option), "Prowadz")
menu_additem(menu, option, "1", 0)
}
Odpowiedz

  • +
  • -
K!113r - zdjęcie K!113r 18.03.2013

Albo jestem ślepy, albo niewidomy, callback'a nie masz.
amxx.pl/dokumentacja/f1094/menu-makecallback
Spójrz na przykład, zajrzyj do poradnika o tworzeniu menu, bowiem w callback'u ustalasz czy opcja jest włączona czy nie.
Odpowiedz

  • +
  • -
Andrzejek - zdjęcie Andrzejek 18.03.2013

Na przykładzie K!113r, pierwszy raz mam z tym stycznosc wiec moze nie dzialac :P

Przed

new menu = menu_create("Wybierz czynnosc:", "simon_choice");

dodaj

new callback=menu_makecallback("cos")

A to zmień

formatex(option, charsmax(option), "Prowadz")
menu_additem(menu, option, "1", 0, Szare)

na to:

formatex(option, charsmax(option), "Prowadz")
menu_additem(menu, option, "1", 0, callback)

Gdzieś poniżej kodu dodaj

public cos(id, menu, item)
{
if(item==0)
return ITEM_DISABLED
return ITEM_ENABLED
}
Odpowiedz

  • +
  • -
szelbi - zdjęcie szelbi 08.06.2013


Albo jestem ślepy, albo niewidomy, callback'a nie masz.

 

Wkleiłem niepełny kod ;)

public cmd_simonmenu(id)
{

new option[257]
new Szare=menu_makecallback("mcbMyMenuCT");


if (cs_get_user_team(id) == CS_TEAM_CT || get_user_flags( id ) & MENUSIMONA_DOSTEP)
{
	new menu = menu_create("Wybierz czynnosc:", "simon_choice");
	formatex(option, charsmax(option), "Prowadz")
	menu_additem(menu, option, "1", 0, Szare)
	
	formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_OPEN")
	menu_additem(menu, option, "2", 0, Szare)
	
	formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_FD")
	menu_additem(menu, option, "3", 0, Szare)
	
	formatex(option, charsmax(option), "Menu Duszka")
	menu_additem(menu, option, "4", 0, Szare)
	
	if (g_GameMode == 1)
	{
		formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_CLR")
		menu_additem(menu, option, "5", 0)
	}
	
	else
	{
		formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_CLR")
		menu_additem(menu, option, "5", 0)	
	}
	
	formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_SIMONMENU_GONG")
	menu_additem(menu, option, "6", 0, Szare)
	
	formatex(option, charsmax(option), "Losuj wieznia")
	menu_additem(menu, option, "7", 0, Szare)
	
	formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_MENU_PUNISH")
	menu_additem(menu, option, "8", 0, Szare)
	
	formatex(option, charsmax(option), "%L", LANG_SERVER, "UJBM_SIMON_GAMES")
	menu_additem(menu, option, "9", 0, Szare)
	
	formatex(option, charsmax(option), "%L",LANG_SERVER, "UJBM_MENU_BIND")
	menu_additem(menu, option, "10", 0)
	
	menu_display(id, menu)
	
}
return PLUGIN_HANDLED
}

public mcbMyMenuCT(id, menu, item)
{
if(id != g_Simon || cs_get_user_team(id) == CS_TEAM_T && item > 0)
{    
	return ITEM_DISABLED;
}
else
{
	return ITEM_ENABLED;
}

if(id == g_Simon || cs_get_user_team(id) == CS_TEAM_T || get_user_flags( id ) & MENUSIMONA_DOSTEP && item == 0)
{
	return ITEM_DISABLED;
}
else
{
	return ITEM_ENABLED;
}

return ITEM_DISABLED;
}
Odpowiedz

  • +
  • -
DEADP00L - zdjęcie DEADP00L 08.06.2013

A nie powinno być tak z tym ifem:

if (cs_get_user_team(id) == CS_TEAM_CT && get_user_flags( id ) & MENUSIMONA_DOSTEP)


Bo prędzej wychodziło, że wszyscy z CT mieli dostęp do tych opcji w menu lub jeżeli ktoś nie był w TT to sprawdzało dopiero flagę.

Odpowiedz

  • +
  • -
szelbi - zdjęcie szelbi 08.06.2013

A nie powinno być tak z tym ifem:

if (cs_get_user_team(id) == CS_TEAM_CT && get_user_flags( id ) & MENUSIMONA_DOSTEP)

Bo prędzej wychodziło, że wszyscy z CT mieli dostęp do tych opcji w menu lub jeżeli ktoś nie był w TT to sprawdzało dopiero flagę.

 

Bo właśnie tak ma być jak jest napisane, a nie działa i jest na odwrót. Oczywiście tylko w pierwszej pozycji, reszta jest OK.

Odpowiedz

  • +
  • -
szelbi - zdjęcie szelbi 09.06.2013

Odświeżam.

Odpowiedz

  • +
  • -
Najlepsza odpowiedź GwynBleidD - zdjęcie GwynBleidD 09.06.2013

Dobrze, przyjrzyjmy się Callbackowi...:

public mcbMyMenuCT(id, menu, item)
{
    if(id != g_Simon || cs_get_user_team(id) == CS_TEAM_T && item > 0)
    {
        return ITEM_DISABLED;
    }
    else
    {
        return ITEM_ENABLED;
    }
    if(id == g_Simon || cs_get_user_team(id) == CS_TEAM_T || get_user_flags( id ) & MENUSIMONA_DOSTEP && item == 0)
    {
        return ITEM_DISABLED;
    }
    else
    {
        return ITEM_ENABLED;
    }
    return ITEM_DISABLED;
}

Linia 50: sprawdzasz czy gracz jest simonem lub czy posiada flagę i item jest większy od 0. Z kolejności wykonywania operatorów wynika, że item > 0 przyczepi się do sprawdzenia teamu, więc równoznaczny zapis (dodałem nawias, który NIC nie zmienia, ale pokazuje jak warunek się zachowa):

if(id != g_Simon || ( cs_get_user_team(id) == CS_TEAM_T && item > 0 ) )

Więc gdy ktoś NIE jest simonem zablokuje mu wszystkie opcje, gdy jest simonem, ale jest w CT, zablokuje mu wszystkie zaczynając od 2giej. Prawidłowy warunek (i think):

if( (id != g_Simon || ( cs_get_user_team(id) == CS_TEAM_T) && item > 0 ) )

Ten warunek zadziała już tak, że zablokuje wszystkie opcje prócz 1szej. Ale to nie jedyny błąd...

 

Popatrzmy na linię 54. Co to oznacza? Ano to, że kod od linii 58 do 66 mógłby nie istnieć, bo albo wykona się return z linii 52. albo z 56. Widzisz już ten błąd? Teraz zaczyna się prawdziwa jazda... bo będziemy mieli mnóstwo warunków... więc polecam przepisać kod na nowo, dzięki czemu będzie czytelny dużo bardziej. Oto przepisany kod:

public mcbMyMenuCT(id, menu, item)
{
    if (cs_get_user_team != CS_TEAM_CT && !(get_user_flags( id ) & MENUSIMONA_DOSTEP))
        return ITEM_DISABLED;
 
    if (item == 0) {
        if (id == g_Simon)
            return ITEM_DISABLED;
    } else {
        if(id != g_Simon)
            return ITEM_DISABLED;
    }
 
    return ITEM_ENABLED;
}
       
 

Krótki opis:

Linia 50. Gdy ktoś nie jest w CT i nie ma flagi dostępu do menu simona (sprawdzając warunek, czy ktoś jest w TT dawałeś dostęp dla spectów, uważaj na to!), nie powinien mieć dostępu do ŻADNEJ opcji. Zwracamy więc Disabled

Linia 53. Gdy item == 0, zwracamy więc DISABLED gdy gracz jest simonem

Linia 56. Item nie jest 0, więc zwracamy DISABLED gdy gracz nie jest simonem

Linia 61. Gdy żadne z powyższych nie zaistniało, zwracamy ENABLED.

 

W ten sposób kod jest bardzo zgrabny i przejrzysty. Warunki nie są namieszane (tak, wiem że można to zrobić jednym IFem, ale nie tędy droga... nawet byś się zdziwił jak tego IFa można pokręcić by go skrócić i żeby poprawnie działało, ale pogubiłbyś się w tym, tak jak w swoim pierwotnym kodzie) i łatwo idzie dojść do tego, kiedy co następuje :)

 

I jedna uwaga: Callback jest wykonywany przy WYŚWIETLANIU menu, nie przy wybraniu pozycji. Więc może zaistnieć sytuacja, gdy ktoś otworzy menu i np zmieni team, a następnie wybierze opcję która dla niego nie jest przeznaczona. Tak samo może nagle stać się simonem, dlatego w handlerze menu musisz jeszcze raz warunki sprawdzić, co by zamieszania nie było :D


Użytkownik GwynBleidD edytował ten post 09.06.2013 21:34
Odpowiedz

  • +
  • -
szelbi - zdjęcie szelbi 10.06.2013

Linia 53. Gdy item == 0, zwracamy więc DISABLED gdy gracz jest simonem

 
Czyli jak dobrze rozumiem czytając kod, to do itemu == 0 również nie będzie miał dostępu. A ma mieć TYLKO do niego dostęp ;)
 
Czyli w tym miejscu trzeba zmienić na ENABLED.

if (item == 0) {
        if (id == g_Simon)
            return ITEM_DISABLED;
    } else {
        if(id != g_Simon)
            return ITEM_ENABLED;
    }

I teraz powinno działać odpowiednio, później skombinuję serwer testowy i powiem czy działa.
 
 
 

dlatego w handlerze menu musisz jeszcze raz warunki sprawdzić, co by zamieszania nie było

 
Czyli co? Przy wyborze każdej z opcji muszę sprawdzać czy ktoś jest simonem? Dobrze zrozumiałem? ;)


Użytkownik norbi1952 edytował ten post 10.06.2013 06:46
Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 10.06.2013

Tak, ale wystarczy na początku handlera sprawdzić team itp.

 

Co do warunków: nie, nie masz racji. Zobacz że w tych wewnętrznych IFach są odwrotne warunki :) I te warunki powinieneś zmieniać, gdyż teraz po Twojej zabawie z wstawieniem ITEM_ENABLED będziesz miał zawsze odblokowane te opcje z prostej przyczyny: IFy są tak ułożone, że jeśli żaden się nie wykona, zwracana jest wymieniona na końcu wartość ITEM_ENABLED. Teraz więc, czy ten ostatni IF się wykona, czy nie, będziesz miał ITEM_ENABLED w obu przypadkach. Zmień na ten kod, co podałem - gwarantuję Ci, że zadziała :)

Odpowiedz

  • +
  • -
szelbi - zdjęcie szelbi 10.06.2013

Tak, ale wystarczy na początku handlera sprawdzić team itp.

 

Co do warunków: nie, nie masz racji. Zobacz że w tych wewnętrznych IFach są odwrotne warunki :) I te warunki powinieneś zmieniać, gdyż teraz po Twojej zabawie z wstawieniem ITEM_ENABLED będziesz miał zawsze odblokowane te opcje z prostej przyczyny: IFy są tak ułożone, że jeśli żaden się nie wykona, zwracana jest wymieniona na końcu wartość ITEM_ENABLED. Teraz więc, czy ten ostatni IF się wykona, czy nie, będziesz miał ITEM_ENABLED w obu przypadkach. Zmień na ten kod, co podałem - gwarantuję Ci, że zadziała :)

 

Racja, przejrzałem kod i już rozumiem o co chodzi ;) Oczywiście plusiki poszły. Póki co nie zamykam, bo znając życie znów będę miał z czymś problem ;)

 

//

 

Co do zmiany drużyny to zrobiłem coś takiego, ale nie wiem za bardzo jak sprawdzać czy ktoś ma simona, a jeśli go nie ma to co ma się dziać.

if(cs_get_user_team != CS_TEAM_CT && !(get_user_flags( id ) & MENU_CT))
	{
		menu_destroy(menu)
		return PLUGIN_HANDLED
	}

Użytkownik norbi1952 edytował ten post 10.06.2013 16:25
Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 10.06.2013

Chyba dokładnie to samo, nie sądzisz? Masz inną flagę tutaj i inną w callbacku, celowo?

 

 

Co do nowych problemów: załóż wtedy nowy temat, skoro ten uważasz za zakończony. W temacie nie jest napisane "... i inne problemy", jest tylko o callbacku.

Odpowiedz

  • +
  • -
szelbi - zdjęcie szelbi 10.06.2013


Masz inną flagę tutaj i inną w callbacku, celowo?

 

Zmieniłem po prostu nazwę ;)

 


załóż wtedy nowy temat, skoro ten uważasz za zakończony.

 

W takim razie zamykam i bardzo dziękuję za pomoc :)

Odpowiedz
Zablokowany