Dobrze zaczynajmy
Pierwszą taką funkcją będzie nikomu nie znane SearchKey. Tak to wygląda:
SearchKey(value,keys) { return floatround(floatlog(float(value & keys),2.0)) }Taka mała niepozorna funkcja zastępuje całkiem dużo kodu.
value - wartość w której szukamy
keys - suma bitowa
Co ona robi takiego? Hmm najprościej ujmując szuka w zmiennej value bitów ze zmiennej keys i zwraca nr znalezionego bitu (Standardowy logarytm).
Jest pewna uwaga co do zastosowania, gdyż tylko jeden bit może byc taki sam w obu zmiennych (inaczej zwróci nie pożądane wyniki)
Teraz pewnie wiele waszych mózgów przetworzyło taką oto informację: na co mi to?
Zarzucę pięknym przykładem:
Chcemy sprawdzić jaki gracz ma pistolet (broń drugorzędna),ten w plecaku lub aktualnie wyciągnięty.(zakładamy że gracz ma tylko jeden pistolet)
Normalnie większość z was zrobiła by tak:
new SB = 1<<CSW_ELITE | 1<<CSW_FIVESEVEN | 1<<CSW_USP | 1<<CSW_GLOCK18 | 1<<CSW_DEAGLE | 1<<CSW_P228 new weapons[32], numweapons,weapon; get_user_weapons(id, weapons, numweapons); for(new i=0; i<numweapons; i++) if((1<<weapons[i]) & SB) weapon = weapons[i]; //Jupii znaleźliśmy nasz pistolet :DOczywiście nie biorę pod uwagę gorszych przypadków szukania broni
Ja za to zrobił bym to tak:
new SB = 1<<CSW_ELITE | 1<<CSW_FIVESEVEN | 1<<CSW_USP | 1<<CSW_GLOCK18 | 1<<CSW_DEAGLE | 1<<CSW_P228 new weapons,weaponlist[32],num,weapon weapons = get_user_weapons(id,weaponlist,num) weapon = SearchKey(weapons,SB) //I tak oto znaleźliśmy pistoletZastrzegam prawa do gnębienia tego przykładu gdyż jest dosyć głupi (nie widać dużej różnicy kodu ani 100% poprawności) bo na połowie aktualnych serwerów można mieć wiele broni na raz (także tego samego typu(typ tzn. pierwszorzędne/drugorzędne/itd))
Ale np. gdy mamy info o graczu:
enum {Latam=1,Plywam,Biegam,Chodze,Stoje,NicSieZeMnaNieDzieje,PosiadamC4,Pisze,WidzeHud,WidzeMotd,WidzeSay} new Player[33]To gdy chcemy sprawdzić co się z ziomkiem (ale tylko rzeczy między Latam a NicSieZeMnaNieDzieje) dzieje to musimy zrobić tak:
new CoRobiGracz if(Player[id] & 1<<Latam) CoRobiGracz = Latam //Ja latam jeee else if(Player[id] & 1<<Plywam) CoRobiGracz = Plywam // Plywam :D else if(Player[id] & 1<<Biegam) CoRobiGracz = Biegam // A jednak biegam else if(Player[id] & 1<<Chodze) CoRobiGracz = Chodze // Spacerek else if(Player[id] & 1<<Stoje) CoRobiGracz = Stoje // Zmeczylem sie else if(Player[id] & 1<<NicSieZeMnaNieDzieje) CoRobiGracz = NicSieZeMnaNieDzieje // Totalny odpoczynekPamiętajmy iż może być więcej niż jeden bit aktywny!!!
Podalem 6 możliwości a czasem jest ich 31 no nie fajnie tak wypisywać 31 instrukcji dlatego z pomocą przychodzi nam ta funkcja:
new CoRobiGracz = SearchKey(Player[id],Player[id] & (1<<Latam|1<<Plywam|1<<Biegam|1<<Chodze|1<<Stoje|1<<NicSieZeMnaNieDzieje)) // I tak w oto sposob sie dowiedzielismy co sie dzieje z graczem (pewnie to ostatnie)Ten przykład tez nie pokazuje prawdziwego potencjału tej funkcji ale co zrobić jak brakuje nam weny.
Różnicę tu akurat widać dużą. Z 6 instrukcji na 0 to jest dużo.
Teraz pytania: dlaczego użyłem:
• float
• floatlog
• floatround
A bo nie ma logarytmu pracującego nie na floacie (w amxx'ie)
Jeśli się mylę to proszę o wskazanie mi poprawnego toku myślenia.
Jedziemy dalej. Kolejnym całkiem sprytnym trikiem użycia funkcji dostępnych w amxx'ie jest coś takiego:
Wycinek z pluginu nr. 1:
public Wywolaj() { new R,X,text[6] formatex(text,5,"Zjem") X = CreateMultiForward("Tutorial",ET_IGNORE,FP_CELL,FP_STRING); ExecuteForward(X, R, X, text); } public Tutorial(id,text[]) { DestroyForward(id) server_print("%s noge tu byl",text) }A teraz drugi plugin:
public Tutorial(id,text[]) { new PolowaTekstu[10] formatex(PolowaTekstu,9,"%s ci",text) ExecuteForward(id, R, id, PolowaTekstu); }To wcale nie jakies wiekopomne odkrycie ale ciekawe. Wywołanie funkcji Wywolaj sprawi że plugin nr. 1 napisze w konsoli serwera Zjem ci noge tu byl. Prawda że ciekawe rzeczy robi ta funkcja, a najciekawsze jest to że przerzucam sobie po pluginach uchwyt do multi forwardu
I to działa o dziwo. Nie wiem czy ze wszystkimi uchwytami z modułu amxmodx tak sie da bo nigdy nie miałem powodów by to sprawdzać
Kolejna rzecz to pokazanie wam wszystkim czego nie powinno się robić.
public Menu(id) { new menu = menu_create( "Menu" , "Menu_Zwrot"); if(is_user_alive(id)) menu_additem(menu,"+ 50Hp") else menu_additem(menu,"Ozyw") menu_additem(menu,"Pusta opcja") menu_setprop(menu, MPROP_PERPAGE, 1) menu_display(id, menu); }Załóżmy że to menu samo się otwiera co 1 min. W pewnym przypadku graczu zostało otworzone te menu kiedy żył ale przez jego głupotę zginą i po śmierci widzi opcje +50Hp i nie kliknie jej (bo według niego ona nic mu nie da)
Niestety jako ludzie rozumni nie możemy go za nic winić i co tu zrobić nie każdy zna amxx'a i wie że w hook'u menu jest jeszcze raz sprawdzane czy zyje.
Dlatego trzeba by menu odświeżać ale nam się niee chce. Tyle kodu by gracz widział inną opcję. Za nic!!! Niech się potrudzi i zmieni stronę menu
Moje rozwiązanie (Całkiem głupie, ale przydaje sie gdy nie chcemy marnowac wysyłanych pakietow na durne menu, a czasem menu trzeba by odswiezyc ze 100 razy na 5 sek)
new const NameMenuItem[][] = {"+ 50Hp ","Ozyw"} public Menu2(id) { new menu = menu_create( "Menu" , "Menu_Zwrot"); new cb = menu_makecallback("Menu_Callback"); menu_additem(menu,"Taki tam tekst",_,_,cb) menu_additem(menu,"Pusta opcja",_,_,cb) menu_setprop(menu, MPROP_PERPAGE, 1) menu_display(id, menu); } public Menu_Callback(id,menu,item) { static acces,callback,name[100],tryb,data[2] menu_item_getinfo(menu,item,acces,data,1,name,99,callback) switch(item) { case 0: { if(is_user_alive(id)) tryb = 0 else tryb = 1 } case 1: return ITEM_DISABLED } if(contain(name, NameMenuItem[tryb]) == -1) { formatex(name,99,"%s^n^n Aby odswiezyc menu zmien strone",NameMenuItem[tryb]) menu_item_setname(menu,item,name) } return ITEM_ENABLED }Funkcja contain jest tu bardzo ale to bardzo ważna. Dlaczego? A bo zmieniając cały czas w menu nazwy przyciskow nasze cudne menu sie buguje i powoli zjada nam text (nie zawsze do gracza dochodzi opcja multipart ale czemu?? nie mam pojęcia) na szczęście ten bug występuje kiedy menu ma więcej znaków niż 1000 czy 1024 nie mam pojęcia bo nie sprawdzałem dokładnie. Ale grunt że po zmianie strony odświeża + nie trzeba używać jakichś rozległych funkcji
Więcej wam nie powiem bo wyjdzie na to że dzisiaj opiszę wam wszystkie znane mi ciekawostki / funkcje (taak mam coś jeszcze w zanadrzu) a ja chcę jeszcze was czymś w przyszłości zaskoczyć
Użytkownik BlackPerfum edytował ten post 17.07.2014 14:53