[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

szelbi
10.03.2013
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ę.
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) }
K!113r
18.03.2013
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.
Andrzejek
18.03.2013
Na przykładzie K!113r, pierwszy raz mam z tym stycznosc wiec moze nie dzialac
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 }
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; }
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ę.
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.
Najlepsza odpowiedź
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
Użytkownik GwynBleidD edytował ten post 09.06.2013 21:34
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
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
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
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.
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