Jump to content

Search the Community

Showing results for tags 'ysi5'.

  • Search By Tags

    Oddělujte čárkami
  • Search By Author

Content Type


Fórum

  • Obecné
    • Všeobecné
    • Všechno možné
  • Programování
    • Poradna
    • Návody
    • Tvorba
    • Hledám programátora
  • Herní oblast
    • Poradna
    • Jak na to?
    • Herní kontext
    • Herní zážitky
    • Komunita
  • Grafika
    • Poradna
    • Návody
    • Tvorba
  • Ostatní
    • Hardware a software
    • Hledám/nabízím
    • Archiv
    • 3D Tisk

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Web


Facebook


Jabber


Skype


Steam


Twitter


Github


Pastebin

Found 5 results

  1. YSI_Players\y_text 📄 + YSI_Players\y_languages 📚 ***** Upozornění: YSI_Players\y_text 📄 #include <YSI_Players\y_text> Takže, nejdříve y_text. Je založena podobně jako, když si uděláme makra zpráv, které se například opakuji a nechceme je neustále psat: #define ERROR_MSG_ALEVEL "[ ! ] {FFFFFF}Nemáš dostatečné oprávnění !" // Simple code if (var[playerid] == false) return SendClientMessage(playerid, 0xFF000000, ERROR_MSG_ALEVEL); // Simple code Což je dobré. Můžeme kdykoliv zprávu změnit a nemusíme přepisovat stovky zpráv kdybychom chtěli cokoliv měnit. Nicméně problém je, že taková akce vyžaduje, aby se celý kód znovu kompiloval. A do toho přichází y_text. Díky kterému nejen, že můžeme měnit zprávu, ale můžeme jí změnit aniž by jsme museli znovu kompilovat kód. Teď někdo zkušenější by si asi řekl: ,,Nojo, ale pokud chceš mít upravitelné zprávy a nemuset stále kompilovat, tak si je jednoduše uložíš a pak načteš. Tak co bylo na tom tak speciální?". A odpověď zní ano. Je to prakticky načítání řetězců. Zkusíme si takový menší hloupější příklad: Může to být o trochu lepší ale prozatím pracujme s tímhle. Zatím to není tak hrozné, ale při více zprávách už začne být trochu problém(a navíc si na každou zprávu deklarovat proměnnou? Bruh). Teď zkusíme to samé se y_text: loadtext soubor[sekce]; public OnPlayerConnect(playerid) { Text_Send(playerid, $MSG_WELCOME); return 1; } public OnPlayerDisconnect(playerid, reason) { Text_Send(playerid, $MSG_BYE); return 1; } YCMD:hp(playerid, o[], help) { // Simple code if (AdminLevel[playerid] < LEVEL_MODERATOR) return Text_Send(playerid, $ERROR_MSG_ALEVEL); // Simple code } A to je všechno . Takže, jak si někteří všimli máme tu dvě zajímavosti a to funkce loadtext a Text_Send(). Funkce loadtext slouží právě na načtení údajů z našeho soubor.txt a přesněji všechen text pod tagem [sekce]. Jméno souboru i sekce jsou jedno jaké, klidně i server_text_benzinka.txt, ale jsou důležité tři body: Koncovka souboru se musí shodovat se zkratkou ve Langs_Add(o tom později), protože z toho pak načítá i text, dle toho v jakém jazyce se má zobrazit a jaký hráč má nastavený, Musíme přidat tag sekce textů, které má následně načíst, Adresa daného souboru aby byla ve scriptfiles/YSI/tu Takže příklad, vytvoříme si soubor Czech.CZ ve scriptfiles/YSI/ a v něm budou tři zprávy: [cze] MSG_HELLO = Ahoj, vítej na serveru. MSG_BYE = Sbohem. Zase se někdy zastav. MSG_ERROR = Někde nastala chyba! Nyní v kódě si tenhle text načteme pomocí: loadtext Czech[cze]; A můžeme začít používat kdekoliv pomocí funkce Text_Send(). Nesmíme ale zapomenout na znaménko $, které odkazuje právě na danou zprávu v souboru: Text_Send(playerid, $MSG_HELLO); Text_Send(playerid, $MSG_BYE); Text_Send(playerid, $MSG_ERROR); Ale tady zábava nekončí, protože Text_Send() je velmi chytrá funkce a nejen, že to může poslat hráčovi, ale také i všem hráčům v dané skupině: new Group:gVips; Text_Send(gVips, $MSG_VIP_EVENT); Nebo i všem co mají nějakou naší proměnnou. Nicméně pokud to je naše proměnná a nic ze YSI, tak musíme před proměnnou přidat znak @ a všem, kdo mají tuto proměnnou true se odešle zpráva(nelze udělat pro všechny co mají false ): new bool:bIsVip[MAX_PLAYER]; Text_Send(@ bIsVip, $MSG_VIP_EVENT); Můžeme i odeslat formátovanou zprávu se specifikátory! Stačí si jen ten specifikátor přidat do našeho souboru: [cze] MSG_HELLO = Ahoj %q, tvoje ID je %i. MSG_BYE = Sbohem %s(ID:%i). public OnPlayerConnect(playerid) { // Specifikátor %q je nick hráče a potřebuje jedno playerid // aby to jméno zjistil, pak druhé je jeho id samozřejmě. Text_Send(playerid, $MSG_HELLO, playerid, playerid); return 1; } Specifkátory do souboru jsou: %c - Character %b - Boolean %f - Float %s - String %q - Nick hráče, které zjistí z jeho ID %g - Zobrazení nekonečna %d + %i - Čísla %l - Slovně boolean, cokoliv větší než 0 se zobrazí jako true, a 0 se zobrazí jako false. %n - Příkaz, aka jak se zobrazí příkaz ve hře (kdyby uživatel chtěl změnit jejich jméno). [cze] MSG_HELP = Tento příkaz neexistuje, zkus se podívat do %n. Text_Send(playerid, $MSG_HELP, YCMD:help); Můžeme měnit i barvu naší zprávy. Ideální je na to použít naše y_colors, protože obsahují 4000 barev, tak na co si hledat vlastní? Jsou dvě možnost jak přidávat barvy do zpráv, lepší a horší. Horší je pomocí #jméno ale ten není zavřený, takže může sežrat i kus ze slova, například #GOLDenter by zobrazilo pouze ter, protože # sežral -en pro barvu GOLDEN, takže lepší je používat ve {jméno}: [cze] MSG_CMD_HELP = {RED}[ ! ] {SNOW}Tento příkaz neexistuje, zkus {RED}/help Lze použít i "X11" barvy, a postup je úplně stejný: RED -> X11_RED. Nicméně, je tu přecijen pár limitů. Jeden z nich je, že zpráva nemůže být delší než 128(je možné, že se to už zvětšilo, nikde o tom nic není). Takže, jestliže chceme delší text, tak můžeme použít další "specifikátor"(ono je to spíše identifikátor) a to _číslo, příklad _3, _2, _1...: [cze] MSG_DLOUHY_1 = Tohle bude moc dlouhý text, takže si radši na to něco dáme. "_2" "_3" MSG_DLOUHY_2 = Například budu tady psát náhodná slova takže něco jako slovosled MSG_DLOUHY_3 = to vůbec nebude existovat, protože heh to tak určitě. MSG_DLOUHE4 = Tohle už tam patřit nebude, protože nějáký vůl zapomněl přidat podtržítko před slovo DLOUHE. Text_Send(playerid, $MSG_DLOUHY); Teď, když víme jak na dlouhé texty, můžeme odeslat i dialog takhle? Ale samozřejmě, i na to má y_text funkce a hned na všechny styly dialogů: Text_MessageBox(...); Text_InputBox(...); Text_ListBox(...); Text_PasswordBox(...); // Jestliže ale i tak chceme vlastní tak: Text_DialogBox(playerid, DIALOG_STYLE_TABLIST_HEADERS, ...); Příklad použití: [czech] DIALOG_NABOJE_TITLE = Dům a náboje DIALOG_NABOJE = Napiš, kolik chceš schovat %s nábojů do domu číslo %i: DIALOG_CANCEL = Zrušit DIALOG_ACCEPT = Potvrdit inline OnHouseWeaponAdd(...) { // Simple code } Text_InputBox(playerid, using inline OnHouseWeaponAdd, $DIALOG_NABOJE_TITLE, $DIALOG_NABOJE, $DIALOG_ACCEPT, $DIALOG_CANCEL, GetPlayerWeaponName(playerid), GetHouseIDbyPlayer(playerid)); YSI_Players\y_languages 📚 A teď přichází ten důvod, proč je důležitá i koncovka souboru. Jestliže budeme používát y_text(nebo cokoliv, co ho obsahuje), tak nejen, že to vyhodí varování o nevyužití funkce Langs_Add a nejen, že stejné varování vyhodí i do konzole serveru ale také se nenahrají pořádně naše texty, protože ať chceme nebo ne, y_text se nahrajou spolu s y_languages a jakmile y_languages zaznamená, že není žádný jazyk, hodí se jako #NO_LANGUAGE (-1) a nic nenačte ani nenajde. Jestliže chceme ale jen používat vymoženost y_text a ukládat si naše zprávy do souboru, tak není problém. Stačí ten jazyk deklarovat, nastavit hráči a to je všechno. Nicméně, knihovna přináší pár zajímavých pomůcek pro servery co mají více jazyků. První co, tak si deklarujeme náš nový jazyk a jako vždy(a stejně jako y_groups) i on má vlastní tag: // Soubor czech.CZ: [all] HELLO = Dobrý den. //Soubor french.FR: [all] HELLO = Bonjour //Soubor germany.DE: [all] HELLO = Guten Tag. // Můžeme i více nahrání: loadtext czech[all], french[all], germany[all]; Všimněte si, že všechny 3 soubory mají stejný keyword HELLO. A jak teda pak zobrazit hráči tu správou zprávu? To přece podle toho jaký má nastavený jazyk! Tak pojďme si je vytvořit: Stejně jako y_groups i jazyky si musíme definovat: Mají dva argumenty a to 2 písmena(zkratka+koncovka souboru odkud se ten text jazyka nahrává) a jak se ten jazyk bude zobrazovat. Oboje samozřejmě lze zobrazit pak následně ve hře: public OnGameModeInit() { lCzech = Langs_AddLanguage("CZ", "Čeština"); lFrench = Langs_AddLanguage("DE", "Deutsche"); lGermany = Langs_AddLanguage("FR", "Français"); return 1; } Nyní ten jazyk samozřejmě musíme hráči nastavit. Můžeme buď jakmile se nastaví a nebo například v dialogu: new string[27]; format(string, sizeof string, "%s\n%s\n%s", Langs_GetName(lCzech), Langs_GetName(lFrench), Langs_GetName(lGermany)); inline OnChangeLanguage(pid, ...) { // Sample code switch (listitem) { case 0: Langs_SetPlayerLanguage(pid, lCzech); case 1: Langs_SetPlayerLanguage(pid, lFrench); case 2: Langs_SetPlayerLanguage(pid, lGermany); } // Sample code return 1; } Dialog_Show(playerid, using inline OnChangeLanguage, DIALOG_STYLE_LIST, "Nastavení", string, "Potvrdit", "Zavřít"); A teď, protože máme už jazyky načtené, máme je vytvořené i nastavené, tak můžeme hráčům posílat zprávy podle toho, jaký mají nastavený jazyk, například: YCMD:hello(playerid, o[], help) { return Text_Send(playerid, $HELLO), 1; } A to je všechno. Jak jsem již psal, y_languages si zjistí jazyk hráče podle toho jaký má nastavený. Pak dle toho vleze do správného souboru, vemze zprávu a zobrazí. Další věc, co se může hodit, tak zobrazení i zkratky jazyka: public OnPlayerText(playerid, text[]) { // Simple code if (...) { va_SendClientMessageToAll(X11_SNOW, "[%s] %s(%i): %s", Langs_GetCode(Langs_GetPlayerLanguage(playerid)), ReturnPlayerName(playerid), playerid, text); return 0; } // Simple code return 1; } Výsledek: [CZ] Scydo(ID:0): Ahoj, jak se vede? __________________________________________________________ Gratuluji, dostali jste se až na konec 🥳🥳🥳 Hlavní topic - odkaz
  2. YSI_Coding\y_stringhash + YSI_Coding\y_unique + YSI_Coding\y_remote + YSI_Game\y_vehicledata ***** Ahoj. Jsem tu opět a mám pár dalších docela zajímavých objevů ze YSI, o které se s váma musím podělit. YSI_Coding\y_stringhash #include <YSI_Coding\y_stringhash> hašování, přesněji hašovací funkce jsou funkce, které převedou pomocí matematické operace data do jednoduššího číselného údaje - více. y_stringhash pracuje velmi podobně. Vezme řetězec údajů a hodí do do číselné podobny, která se pak snadněji podmínkuje. K čemu to je dobré? Určitě známe všichni switch. Jestliže ne, více v návodě od @vEnd: A jak všichni víme, jediné údaje, které se dají přepnout jsou obyčejné hodnoty, které se lze porovnávat jako jsou int, float či boolean. A porovnávat řetězec? Například, když si chceme udělat příkaz /drazba, kde bude mít v příkaze možnost napsat jestliže bude dražit auto, dům nebo zbraň? Ani náhodou. Jediná možnost je pomocí funkce strcmp(), ale to není zrovna ideální. Tak přichází y_stringhash s možností i přepnout řetězec a to pomocí funkce YHash(): switch (YHash(mujStr, .podminka = boolean)) { case _H<dum>: { // Sample code } case _H<auto>: { // Sample code } case _H<zbran>: { // Sample code } YHash = Jméno funkce. mujStr = řetězec, který se hašuje, .podmínka = přesnějí argumenty funkce (jsou hned 4, později vysvětlím), _H = iterátor pro každý hašnutý údaj, ze slova Hash, <dum>, <auto>, <zbran> = hašnuté údaje, nepřidávat uvozovky! Ale pozor. YHash má zapnuté(true) case-sensitive, takže ahoj a Ahoj, aHoj apod nebude to samé. Jestliže chceme zahrnout i to, musíme ho vypnout(false) a používat jiný iterátor a to _I (od slova Insensitive): #include <YSI_Visual\y_commands> YCMD:event(playerid, o[], help) { switch (YHash(o, .sensitive = false)) { case _I<tunning>: { // Sample code } case _I<derby>: { // Sample code } case _I<dm>: { // Sample code } /* Zajímavost, vyhodí error, že už je definovaný: */ case _I<DM>: { // Sample code } Co se týče podmínek, přesněji argumentů u YHash, tak jsou následujicí: Jestliže chceme hašovat packnutý řetězec: switch (YHash(mujStr, .sensitive = false, .pack = true)) A nebo jestliže chceme hašovat jen určitou délku(max length) řetězce: switch (YHash(mujStr, .sensitive = false, .len = 5)) A teď pozor dvě a to dávejte si pozor jestliže se vám některý hašnutý údaj neopakuje(i když stejně, jestliže máte vypnuté case-sensitive tak vám to vyhodí chybu). Y_Less také říká, že se může, i když velmi nepravděpodobně, stát, že i když jste si jistý na 100 % že nemáte žádný stejný údaj dvakrát a stejně vám to vyhodí chybu o shodnosti, tak stačí změnit 3. argument funkce type. Více o tom, jak to funguje a jak se obě používají - zde. YSI_Coding\y_unique #include <YSI_Coding\y_unique> Často se nemusí ani nahrávat. Ve velké většině se nahraje automaticky spolu se y_hooks. y_unique není nic více než jen hromada maker, které přidávají ke funkcím číslo jako jejich "id" a tak umožní používat stejnou funkci vícekrát. Nejčastějí se takové věci hodí do include. Největší a nejužitečnější ukázka použití je právě y_hooks, protože nejen, že můžeme hookovat stejné funkce ale také můžeme je hookovat vícekrát: #include <YSI_Coding\y_hooks> hook OnPlayerConnect(playerid) { // Sample Code #1 } hook OnPlayerConnect@2(playerid) { // Sample Code #2 } hook OnPlayerConnect@3(playerid) { // Sample Code #3 } Největší "id", které se dá použít je 999. Takže jich je určitě dost. YSI_Coding\y_remote #include <YSI_Coding\y_remote> y_remote je prakticky jen vylepšené CallLocalFunction() a CallRemoteFunction(), nicméně, umožní dostávat chyby ještě před kompilací(například jestliže volaná fce nemá návratovou hodnotu a využívá se tak). Má hned několik keywords. Jedno z nich je vytvoření samotné funkce pomocí remotefunc: remotefunc LjmenoFunkce() { } // V jiném scriptu: remotefunc RjmenoFunkce() { } Dalším je voláním localfunc pro lokální a broadcastfunc pro mimo: public OnPlayerConnect(playerid) { // Zavolá pouze v aktuálním scriptu: localfunc LjmenoFunkce(); // Zavolá ve všech scriptech zároveň: broadcastfunc RjmenoFunkce(); return 1; } Pokud jde o argumenty, tak: localfunc LjmenoFunkce(cislo, Float:fcislo, string:rezezec[]) { pritnf("Cislo: %i, FCislo: %2.f Str %s", cislo, fcislo, retezec); } hook OnPlayerConnect@2(playerid) { localfunc LjmenoFunkce(11, 43.3, "ahojjoha"); return 1; } A jak jsem již psal, jedna z výhod y_remote je, že může vracet i určité chyby, například právě s chybou návratové hodnoty: #include <YSI_Core\y_utils> remotefunc void:prosteBla(cislo) { printf("Cislo = %i", cislo); } public OnPlayerConnect(playerid) { new mojecislo = localfunc prosteBla(10); return 1; } // Vyhodí chybu, prosteBla nemá návratovou hodnotu A ještě jedna věc. Jestliže máme deklarovanou funkci v jiném kódě v jiném scriptu, je potřeba u volání funkce s řetězcem přidat i délku(alespoň podle knihovny). YSI_Game\y_vehicledata #include <YSI_Game\y_vehicledata> Tak jo. Tohle bude zajímavější. Většina z nás si musela vždycky deklarovat jména modelů a nebo půl hodiny hledat id daného modelu pro náš FS. Teď ale díky y_vehicledata, které má prakticky všechny, není třeba. Funkce y_vehicledata mají tři hlavní kategorie: Vehicle_ = Funkce berou a používají vehicleid, které vrací například CreateVehicle(), Model_ = Funkce berou a používají modeild, které vrací právě GetVehicleModel(), VMI_ = aka "Vehicle Internal Model" a mají vlastní speciální hodnotu a je specifické pro tenhle include. A k tomu používají i vlastní tag VMI:. Rozdíl oproti modelům je, že je vždy validní, můžou se použít jako index pro foreach a také mají právě tag, díky kterému se můžou odlišit. Všechny tři kategorie si stojí i za jménem funkcí, takže například Vehicle_IsPolice(), Model_IsPolice() i VMI_IsPolice() je vše stejně definované. Nyní funkce: Vehicle_GetCategory(vehicleid); Navrátí ID kategorie vozidla, které můžete vidět na wiki - odkaz. Kdyžtak jména kategorií: CATEGORY_UNKNOWN CATEGORY_AIRPLANE CATEGORY_HELICOPTER CATEGORY_BIKE CATEGORY_CONVERTIBLE CATEGORY_INDUSTRIAL CATEGORY_LOWRIDER CATEGORY_OFFROAD // Verze 1 CATEGORY_OFF_ROAD // Verze 2 CATEGORY_PUBLIC CATEGORY_SALOON CATEGORY_SPORT CATEGORY_STATIONWAGON // Verze 1 CATEGORY_STATION_WAGON // Verze 2 CATEGORY_BOAT CATEGORY_TRAILER CATEGORY_UNIQUE CATEGORY_RC A teď pokud jde o funkce pro podmínky, tak těch je hned několik. A jsou právě kategorizované dle modelu daného vozidla: (Poznámka: za jménoFce dosadit jednu ze tří kategorií, co chcete použít a to Model, Vehicle nebo VMI). Vehicle_IsValid(vehicleid); // Jednoduše zjistí jestliže je vozidlo validní. jménoFce_IsCar(vehicleid); jménoFce_IsTruck(vehicleid); jménoFce_IsVan(vehicleid); jménoFce_IsFire(vehicleid); jménoFce_IsPolice(vehicleid); jménoFce_IsFBI(vehicleid); jménoFce_IsSWAT(vehicleid); jménoFce_IsMilitary(vehicleid); jménoFce_IsWeaponised(vehicleid); //Jakékoliv vozidlo, které může cokoliv "střílet" (započítává se i voda) jménoFce_IsHelicopter(vehicleid); jménoFce_IsBoat(vehicleid); jménoFce_IsPlane(vehicleid); jménoFce_IsBike(vehicleid); jménoFce_IsAmbulance(vehicleid); jménoFce_IsTaxi(vehicleid); jménoFce_IsOnWater(vehicleid) - //Vozidla, která nejsou ve CATEGORY_BOAT, ale mohou na vodu. jménoFce_IsCoastguard(vehicleid); jménoFce_IsTrain(vehicleid); // I včetně vagónů. jménoFce_IsLS(vehicleid); // Specificky pro policie ze LS. jménoFce_IsSF(vehicleid); // jménoFce_IsLV(vehicleid); // jménoFce_IsTank(vehicleid); jménoFce_IsFlowerpot(vehicleid); jménoFce_IsTransport(vehicleid); jménoFce_GetName(vehicleid); // Navrátí jméno modelu v packed řetězci. Použití, určité jasné: YCMD:stop(playerid, params[], help) { if (help) return SendClientMessage(playerid, X11_GREEN, "Zastavit hráče pro kontrolu"); if (!IsPlayerInAnyVehicle(playerid)) return SendClientMessage(playerid, X11_RED, "Nejsi ve vozidle"); if (!Vehicle_IsCar(GetPlayerVehicleID(playerid)) || !Vehicle_IsPolice(GetPlayerVehicleID(playerid))) return SendClientMessage(playerid, X11_RED, "Nejsi v policejním autě"); // Sample code } return 1; } A jaký je rozdíl mezi VMI a Model_/Vehicle_? Jak jsem již psal, je to jaká si vlastní forma y_vehicledata, a mají všechny 3 body: vlastí tag, vždy validní a použití jako index. new VIM:VIM_VehicleID = Vehicle_GetVIM(GetPlayerVehicleID(playerid)); new VIM:VIM_modelID = Model_ToVIM(GetPlayerVehicleID(playerid)); if (!VIM_IsPolice(VIM_modelID)) return ...; Hlavní topic - odkaz Gratuluju, dostali jste se na konec 🥳🥳🥳🥳.
  3. YSI_Core\y_utils YSI_Coding\y_va + YSI_Coding\y_inline YSI_Data\y_iterate / YSI_Data\y_foreach ***** Tak jo. Tyto 4 includy (plus jeden co je jen alternativa), sice obsahují mnoho dalších zajímavých vymožeností, nicméně, chci tu pouze ukázat to nejzajímavější a to, co s velkou pravděpodobností někdo použije při tvorbě FS/GM. YSI_Core\y_utils A začneme s y_utils. Jak už ang. slovo "utils" naznačuje, jde o nástroje, přesněji o hromadu užitečných funkcí. Většinou takové funkce jste mohli vidět na SA-MP fóře ve topicu "Useful functions": A to je jen ten seznam funkcí, co jsem našel . Kdoví, které tam ještě jsou. Tak zkusíme ty nejzajímavější/nejužitečnější: 1. isnull() pro parametry do příkazů: if (isnull(params)) return ...; 2. StrToUpper() pro změnu všech znaků písmen na velká a StrToLower() pro změnu všech znaků písmen na malá: format(str, sizeof str, "Máš zapnuté/vypnuté načítání? %s", Bit_Get(IsOnLoad, playerid) == true ? StrToUpper("true") : StrToUpper("false")); // Anti CapsLock va_SendClientMessageToAll(-1, "%s %s", ReturnPlayerName(playerid), StrToLower(text)); 3. Random() pro náhodné číslo a RandomFloat() pro náhodné desetinné číslo: Random(min, max); RandomFloat(Float:min, Float:max, dp = 2); Argument dp je ohledně zaokrouhlení výsledné hodnoty. Pro lepší představu kód: printf("%.3f %.3f %.3f %.3f", RandomFloat(1.0, 10.0, 0), RandomFloat(1.0, 10.0, 1), RandomFloat(1.0, 10.0, 2), RandomFloat(1.0, 10.0, 3)); printf("%.3f %.3f %.3f %.3f", RandomFloat(1.0, 10.0, 0), RandomFloat(1.0, 10.0, 1), RandomFloat(1.0, 10.0, 2), RandomFloat(1.0, 10.0, 3)); printf("%.3f %.3f %.3f %.3f", RandomFloat(1.0, 10.0, 0), RandomFloat(1.0, 10.0, 1), RandomFloat(1.0, 10.0, 2), RandomFloat(1.0, 10.0, 3)); printf("%.3f %.3f %.3f %.3f", RandomFloat(1.0, 10.0, 0), RandomFloat(1.0, 10.0, 1), RandomFloat(1.0, 10.0, 2), RandomFloat(1.0, 10.0, 3)); printf("%.3f %.3f %.3f %.3f", RandomFloat(1.0, 10.0, 0), RandomFloat(1.0, 10.0, 1), RandomFloat(1.0, 10.0, 2), RandomFloat(1.0, 10.0, 3)); printf("%.3f %.3f %.3f %.3f", RandomFloat(1.0, 10.0, 0), RandomFloat(1.0, 10.0, 1), RandomFloat(1.0, 10.0, 2), RandomFloat(1.0, 10.0, 3)); printf("%.3f %.3f %.3f %.3f", RandomFloat(1.0, 10.0, 0), RandomFloat(1.0, 10.0, 1), RandomFloat(1.0, 10.0, 2), RandomFloat(1.0, 10.0, 3)); A výsledek: 7.000 4.400 8.460 1.365 1.000 9.300 8.399 8.619 7.000 4.900 3.529 4.157 2.000 7.400 4.309 4.928 1.000 7.000 4.699 3.971 6.000 1.700 8.949 2.434 5.000 2.200 9.359 5.991 4. isnumeric() jestliže je řetězec znaků číslo: if (!isnumeric(inputtext)) return ...; 5. GetIP() vrátí IP hráče(ne pouze v číslech!): va_SendClientMessage(..., "%s", GetIP(playerid)); 6. IS_IN_RANGE jestliže hodnota je v rozmezí a NOT_IN_RAGE jestliže není: if (IS_IN_RANGE(10, 1, 100) == true) return print("Cislo 10 je v rozmezí!"); if (NOT_IN_RANGE(10, 1, 9) == true) return print("Cislo 10 není v rozmezí!"); 7. A nebo několik return ze řetězce hodnot do určitého datového typu: hexstr(string[]); boolstr(string[]); binstr(string[]); A mnohem více... YSI_Coding\y_va Include y_va pro změnu obsahuje možnost si udělat vlastní formátované zprávy, funkce apod. Příklad, běžného formátování zpráv: new string[144 + 1]; format (string, sizeof (string), "Bla bla bla %s %i %d", ReturnPlayerName(playerid), Random(10), Random(100)); SendClientMessage(playerid, -1, string); Další možnosti byly pomocí maker, nebo vzít proměnnou string jako globální proměnnou, nebo pomocí #emit. Nicméně pro obyčejné uživatelé to je velmi složitě. Include y_va nabízí jednodušší způsob, jak si takové funkce udělat. Ukázka použití funkce zpráv ze y_va: va_SendClientMessage(playerid, -1, "Bla bla bla %s %i %d", ReturnPlayerName(playerid), Random(10), Random(100)); A to není všechno. Nejen, že je to jednodušší, ale také rychlejší něž obyčejně či přes marka. Uživatel si může udělat vlastní pomocí va_format a va_start. Ukázka, jak je udělané va_SendClientMessage(): va_SendClientMessage(playerid, colour, const fmat[], {Float, _}:...) { new str[145]; va_format(str, sizeof (str), fmat, va_start<3>); return SendClientMessage(playerid, colour, str); } S tím, že formátování samotné fce je ve va_format a argument va_start<3> zastává pořadí, kdy se začnou přidávat hodnoty za specifikátory. Samozřejmě, nemusíte si takové funkce tvořit. Většina už je předdefinovaná. Seznam: va_print(const fmat[], va_args<>); va_SendPlayerMessageToPlayer(playerid, senderid, const fmat[], va_args<>); va_SendPlayerMessageToAll(senderid, const fmat[], va_args<>); va_SendClientMessage(playerid, colour, const fmat[], va_args<>); va_SendClientMessageToAll(colour, const fmat[], va_args<>); va_GameTextForPlayer(playerid, const fmat[], time, style, va_args<>); va_GameTextForAll(const fmat[], time, style, va_args<>); va_SetTimerEx(const function[], interval, bool:repeating, const fmat[], va_:STATIC_ARGS); va_CreatePlayerTextDraw(playerid, Float:x, Float:y, fmat[], va_args<>); va_TextDrawCreate(Float:x, Float:y, fmat[], va_args<>); va_CallLocalFunction(const function[], const fmat[], va_:STATIC_ARGS); va_CallRemoteFunction(const function[], const fmat[], va_:STATIC_ARGS); YSI_Data\y_foreach / YSI_Data\y_iterate Pokud jde rozdíl mezi foreach a iterate, tak žádný není. Jen foreach je více známé, protože je starší. y_iterare se dělí na dvě možnost použití. A. Lepší práce s cykly včetně s již předdefinovanýma podmínkama (například u cyklu pro hráče se cyklí pouze hráči). B. Udělat si vlastní hodnotu, co se bude cyklit. A. Nejdříve práce s cykly. Normální cyklus všichni asi známe, příklad: for(new i; i<MAX_PLAYERS; i++) { if(IsPlayerConnected(i)) { Pak je tu možnost s novou funkcí, která vrátí nejvyšší id hráče na serveru: for(new i = 0, j = GetPlayerPoolSize(); i <= j; i++) { if(IsPlayerConnected(i)) { A teď ukázka přes foreach: foreach (new i: Player) { Jednoduché že? A obsahuje to i samozřejmě podmínku zda je to hráče a jestliže je online. Jinak používání je úplně stejné jako u obyčejného cyklu: foreach (new i: Player) { if (AdminLevel[i] > 10) { // Sample code } } Slovo "Player" je takzvané iter tag aka typ. Zde ještě je seznam dalších iter tagů, které obsahuje: foreach (new v: Vehicle) foreach (new b: Bot) foreach (new a: Actor) foreach (new c: Character) // Další části knihovny: foreach (new p: Bit(bit_jméno)) foreach (new g: Group(gAdmins)) foreach (new i: Range(10,100)) // Potom několik speciálních například: // Cyklus vrátí každého index v poli které obsahuje 0. foreach (new i : Null(pole)) // Cyklus vrátí každého index v poli které NEobsahuje 0. foreach (new i : NonNull(pole)) // Cyklus půjde pozpátku foreach (new i : Reverse(10)) // Mocniny. 1, 2, 4, 8, 16... foreach (new i: Powers(2)) // 5x náhodná čísla foreach (new i: Random(5)) // Fibonacciho posloupnost foreach (new i: Fib()) // Cyklus skončí jakmile narazí index rovnají se číslu, takže 5 new pole[] = { 1, 2, 3, 4, 5, 6, 7} foreach (new i: Until(6, pole)) // Cyklus vypíše všechny indexy na kterých se nachází číslo 6 new pole[] = { 6, 1, 9, 3, 4, 6, 6} foreach (new i: Filter(6, pole)) B. Teď je další možnost, kdy si lze přidat vlastní iter tag. Zkusíme si například udělat příkaz /admins. Začneme deklarací našeho iteru: // Maximální počet hodnot v iteratoru: #define MAX_ADMINS (10) // Proměnná s tagem Iterator: a maximální počet hodnot v ostrých závorkách: new Iterator:Admins<MAX_ADMINS> Než ale budeme pokračovat, vysvětlení pár funkcí, které y_iterate obsahuje: // Zjistí volnou hodnotu v iteratoru: Iter_Free(Iterator:Name<>); // Jestliže iterator tuhle hodnotu už obsahuje: Iter_Contains(Iterator:Name<>, value); // Přidá do iteratoru danou hodnotu: Iter_Add(Iterator:Name<>, value); // Odebere z iteratoru danou hodnotu: Iter_Remove(Iterator:Name<>, value); // Zjistí počet vložených iteratoru: Iter_Count(Iterator:Name<>); // Pročistí celý iterator od všech hodnot: Iter_Clear(IteratorArray:Name[]<>); // Zjistí velikost iteratoru, // (Jestliže na všechno používáte MAX_něco makro tak není co řešit): Iter_Size(Iterator:Name<>); Teď, jestliže je hráč teda náš admin, musíme ho do našeho iteratoru přidat. Můžeme například poté, co se připojí na server: public OnPlayerConnect(playerid) { LoadPlayerData(playerid); // <-- Udělaná nějaká naše funkce na načítaní údajů hráče if (AdminLevel[playerid] > 0) { if (Iter_Count(Admins) < MAX_ADMINS) Iter_Add(Admins, playerid); else return printf("Něco je špatně. Asi máš moc Adminů v Admintýmu! %i", Iter_Count(Admins)); } return 1; } Samozřejmě, po odpojení ho musíme odebrat, jinak se nám budou stále přidávat další: public OnPlayerDisconnect(playerid, reason) { if (Iter_Contains(Admins, playerid)) Iter_Remove(Admins, playerid); return 1; } A nakonec, jestliže je se vypne FS či server, tak pro jistotu tenhle iterator pročistit. Lze to i po spuštění: public OnFilterScriptExit() { Iter_Clear(Admins); A teď, když náš iterator obsahuje POUZE hráče, co mají adminlevel, můžeme s ním snadno pracovat: YCMD:admins(playerid, o[], help) { if (Iter_Count(Admins) == 0) return SendClientMessage(playerid, X11_RED, "Momentálně není online žádný Admin!"); foreach (new i: Admins) { if (IsPlayerAdmin(i)) va_SendClientMessage(playerid, X11_YELLOW1, "%s [LEVEL %i + RCON]", ReturnPlayerName(i), AdminLevel[i]); else va_SendClientMessage(playerid, X11_YELLOW1, "%s [LEVEL %i]", ReturnPlayerName(i), AdminLevel[i]); } return 1; } YSI_Coding\y_inline Jednouše řečeno, jde o include, kde lze používat vnořené fce, aka funkce ve funkci a velmi často se přitom používá naše kouzelné slovíčko using, a buď inline pro uvnitř a nebo public pro mimo. Takto se VÝBORNĚ hodí na práci s dialogy, protože nikdo nechce ten mega obrovský OnDialogResponse kód. Je opět několik možností, jak tento inlcude používat. Jde i při tom tvořit vlastní funkce, které se budou volat, nicméně, to už spadá do obtížnosti ****, takže to vynechám. Ale kdo by se o to zajímal, tak více informací zde - odkaz My se zaměříme, jak to efektivně využít do našeho GM. Jak jsem již psal, výborně se hodí s y_dialogs, protože můžeme volat otevřený dialog a nemusíme ho cpát do fce OnDialogResponse(). Jednu variantu ukázky jsem tu již převedl a to voláním dialogu mimo fce a to ve Přechod z dini/dcmd/jiné na YSI4 (v části o dialogu) a nebo uvnitř fce a to ve Masivní použití knihovny. Hlavní topic (kdyžtak upraveny na 2020) - odkaz
  4. YSI_Visual\y_commands + YSI_Players\y_groups ***** V tomto návodě se hodí ukázat obojí, protože oba includy z knihovny můžou být výborně spojené, ale zároveň lze použít pouze ycmd. y_groups je právě takové rozšíření na skupiny a levely(příklad podobnosti: oprávnění z Minecraftu). Jestliže se někdo chce naučit YSI, tak doporučuji si k ruce vzít také tento topic, protože obsahuje většinu kódu, na který je zaměřen i tento návod. Začneme y_commands. Nejdříve si načteme include z knihovny samozřejmě: #include <YSI_Visual\y_commands> A následně, jeho volání příkazů je poměrně snadné, příklad: YCMD:prikaz(playerid, params[], help) { //Sample code return 1; } S tím, že argumenty jsou jasné a to playerid pro hráče co příkaz zavolal, params[] pro parametry a help, to si ukážeme za chvilku. Pozor! Každý příkaz se MUSÍ vracet přes hodnotu 0 či 1. Nikdy true či false. Je to z důvodu, že každý příkaz má několiko vlastních návratových hodnot(později si ukážeme ve funkci). Argument help je argument, ktery se vyvolá poté, co hráč za příkaz napíše znak '?', příklad "help ?" nebo "kick ?". Do podmínky se vkláda tak, že znak hráč napsal správně(ostatní je klasifikované jako parametry). Ukázka použití: #include <YSI_Server\y_colours> YCMD:tajnyprikaz(playerid, params[], help) { if (help) return SendClientMessage(playerid, X11_YELLOW1, "Tento příkaz ti dá všechna práva !"); return 1; } Pokud ale máte raději starý dobrý i-zcmd / zcmd styl, tak to y_commands ho také podporuje a to: CMD:name(playerid, params[]) { // Sample code return 1; } Návod a více informací: Akorát jediná nevýhoda je, že nepodporuje následný argument help. Takže, jestliže ho někdo chcete používát, musí i použít formu YCMD. A kdo je nadšenec do zcmd, tak ví, že při nepoužívání params, tento argument lze vynechat. To bohužel y_commands nepodporuje(to samé s argumentem help). Dále y_commands obsahuje i možnosti alternativních příkazů. Jsou dva způsoby, a to původní starý ve funkci OnGameModeInit() / OnFilterScriptInit() / OnScriptInit(): #include <YSI_Server\y_scriptinit> public OnScriptInit() { Command_AddAltNamed("primarni", "sekundarni"); return 1; } A nebo novější a zajímavější metoda a to rovnou nad příkaz do kódu: YCMD:statistiky(playerid, params[], help) = stats; YCMD:stats(playerid, params[], help) { //Sample code return 1; } Pokud jde o y_groups: Jak jistě víme, že jedna z možností, jak kontrolovat, jestliže má hráč oprávnění můžeme podmínkou v každém příkazu, příklad: #include <YSI_Server\y_colours> YCMD:me(playerid, params[], help) { if (!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, X11_RED, "Nemáš dostatečné Admin oprávnění!"); // Sample code return 1; } Teď to zkusíme s y_groups. Nejdříve si samozřejmě nahrajeme include z knihovny: #include <YSI_Players\y_groups> Dále si deklarujeme samotnou skupina. Každá skupina má vlastní tag, stejně jako u y_bit/y_playerarray: new Group:Admins; Ale pozor. Samotná proměnná, tedy skupina teď sama o sobě nic není, přesnějí je takzvaně UNDEF a nebude správně fungovat, dokud si jí nevytvoříme opět ve funkci OnGameModeInit() / OnFilterScriptInit() / OnScriptInit(): #include <YSI_Server\y_scriptinit> public OnScriptInit() { Admins = Group_Create(); return 1; } Funkce Group_Create() má ještě jeden argument a to jméno. Jde o jméno, které pak vrací jiná funkce(o ní později) a jde o jméno, které bude mít každý vlastnít dané skupiny (jestliže to uživatel nastaví). Můžeme jí tedy nastavit nejen jméno ale také i barvu. A jméno ani nemusíme nastavovat při vytváření. Můžeme si ho nastavit později dle sebe: public OnScriptInit() { Admins = Group_Create("Admin"); Group_SetColour(Admins, X11_RED); /*** A NEBO ***/ Admins = Group_Create(); Group_SetName(Admins, "Admin"); Group_SetColour(Admins, X11_RED); Teď, následně jméno skupiny můžeme dostat pomocí funkce Group_GetName(), příklad použití: #include <YSI_Coding\y_va> new Group:gPlayers; YCMD:skupina(playerid, params[], help) { if (Group_IsValid(gPlayers) == false) return SendClientMessage(playerid, -1, "Tato skupina není validní!"); if (Group_GetPlayer(gPlayers, playerid) == true) va_SendClientMessage(playerid, X11_YELLOW1, "Jsi ve skupině %s", Group_GetName(gPlayers)); else return SendClientMessage(playerid, -1, "Nejsi v této skupině!"); return 1; } A y_groups mají ještě jedno zajímavou funkci a to: public OnScriptInit() { gPlayers = Group_Create(); Group_SetGlobalGroup(gPlayers, true); Jde o funkci, která danou skupinu nastaví jako defaultní, teda všichni kdo se připojí, i ti co přijdou na serveru po prvé, tak se jím automaticky nastaví. Do takové skupiny se právě hodí hráči jako základ. A teď zpět ke y_commands. Jak jsem říkal, oba includy lze výborně propojit. Jedna taková funkce je způsob, který defaultně všem zakáže všechny příkazy: Group_SetGlobalCommandDefault(false); A teď jsou dva způsoby, jak povolovat/zakazovat příkazy. 1. Povolit/zakázat všechny příkazy určité skupině: // Povolí celé skupině Group_SetCommandDefault(jmenoSkupiny, ALLOW); // Zakáže celé skupině Group_SetCommandDefault(jmenoSkupiny, DENY); Poznámka: V původní verzi YSI, se namísto ALLOW/DENY používalo true/false. Y_Less říká, že vám to pravděpodobně bude také fungovat, nicméně, více doporučuje používat ALLOW/DENY, hlavně protože boolean styl vám vyhodí stejně varování o tagu, více zde. 2. Povolit/zakázat určitý příkaz celé určité skupině. Group_SetCommand(jmenoSkupiny, YCMD:prikaz, ALLOW); Group_SetCommand(jmenoSkupiny, YCMD:prikaz, DENY); Nezapomenout používat tag YCMD: u jmén příkazů. A teď nemusíme neustále používat podmínku u každého příkazu na oprávnění. A nebo pokud se nechceme upsat k smrti funkcema, lze použít i zajímavější metoda: GROUP_ADD<jmenoSkupiny> { @YCMD:help; @YCMD:stats; @YCMD:vip; @YCMD:credits; } Hráči se daná skupina nastaví pomocí funkci Group_SetPlayer(). Příklad použití: new Group:gPlayers, Group:gDeathMatch; public OnScriptInit() { gPlayers = Group_Create(); Group_SetGlobalGroup(gPlayers, true); gDeathMatch = Group_Create(); Group_SetCommandDefault(gPlayers, ALLOW); Group_SetCommandDefault(gDeathMatch, DENY); Group_SetCommand(jmenoSkupiny, YCMD:leave, ALLOW); return 1; } YCMD:tymcerveny(playerid, params[], help) { // Sample code SendClientMessage(playerid, X11_GREEN, "Připojil ses do Team DeathMatch!"); Group_SetPlayer(gDeathMatch, playerid, true); return 1; } Jestliže použijeme y_groups ke y_commands, tak se nám také otevírá další možnost návratové hodnoty u příkazu a to, jestliže právě nemá dostatečné oprávnění. Stejně jako i-zcmd, tak i y_commands mají na to vlastní funkci a to: public e_COMMAND_ERRORS:OnPlayerCommandReceived(playerid, cmdtext[], e_COMMAND_ERRORS:success) { if(success == COMMAND_DENIED) { SendClientMessage(playerid, X11_RED, "Nemáš dostatečné oprávnění!"); return COMMAND_OK; } if(success == COMMAND_UNDEFINED) { SendClientMessage(playerid, X11_WHITE, "Tento příkaz neexistuje! Zkus použít /help"); return COMMAND_OK; } return COMMAND_OK; } A návratové hodnoty u příkazů/ve funkci můžou být následujicí: // Příkaz vrátil 0. COMMAND_ZERO_RET = 0 , // Příkaz se správně zavolal. COMMAND_OK = 1 , // Příkaz neexistuje COMMAND_UNDEFINED = 2 , // Nemá oprávnění na příkaz. COMMAND_DENIED = 3 , // Také nemá oprávnění + nedá dát znát, že existuje. COMMAND_HIDDEN = 4 , // Příkaz použil hráč, který by neměl existovat. COMMAND_NO_PLAYER = 6 , // Všechny příkazy jsou deaktivované pro totoho hráče. COMMAND_DISABLED = 7 , // Použit například '/' namísto '#'. COMMAND_BAD_PREFIX = 8 , // Nenapsal správně příkaz jako '/neco' COMMAND_INVALID_INPUT = 10, Hlavní topic - odkaz
  5. MASIVNÍ POUŽITÍ KNIHOVNY ***** V tomto díle nepůjde ani tak moc o návod, jako spíše o ukázku, že velkou většinu částí/includů ze knihovny lze aplikovat a tvořit s její pomocí prakticky cokoliv a obsahuje skoro cokoliv. Nějakou dobu jsem přemýšlel, jak to nejlepé předvést a tak mě napadlo napsat takovou menší ukázku Admin scriptu s použitím co nejvíce možností z knihovny, jak to je jen možné. Situace je následujicí, použil jsem: y_hooks pro hookované funkce, y_va pro již vytvořené formátované funkce zpráv, y_timers pro lepší práci s timery, y_inline pro práci s funkcí volanou ve fci, y_commands pro příkazy a parametry, y_dialog pro práci s dialogy a abych nepotřeboval nastavovat ID, y_ini pro ukládání údajů o hráči, y_colours protože obsahuje skoro 4000 barev jak pro zprávy tak i pro obyčejné použití, y_scriptinit pro speciální fci která se vyvolá jak ve FS tak i ve GM, y_utils pro doplňkové fce jako například právě zjištění nicku ReturnPlayerName(), y_iterate pro lepší práci s cykly, y_playerarray pro komprimaci paměti boolean proměnných, y_groups pro práci s oprávněním a skupinama. A vytvořil následujicí kód: Kdyby si náhodou někdo myslel, že jsem si ten kód jen vycucal z prstů a nelze to kompilovat, tak zde : https://ctrlv.link/shots/2020/12/27/33IK.png Pouze varování a to nevyužití jednoho makra, ale to lze snadno vyřešit či ignorovat. Několik poznámek ohledně kódu Jelikož plánuji udělat na zbytek includů z knihovny individuální návod, nebudu zde popisovat o čem přesně jsou, nebo co přesně dělají, ale: Bohužel, funkce při čtení souboru nemají návratovou hodnotu vyčtené informace. To znamená, že pro nastavení boolean je zapotřebí si deklarovat proměnnou new bool:hodnota která načtenou informací vše nastaví. Při načítání jsme nemuseli zjišťovat jestliže je hráč, protože pak zjišťujeme jestliže není VIP či Admin, a obě možnosti můžou vyjít jako nepravé, takže lze nastavit rovnou Group_SetPlayer(gPlayer, playerid, true), že s určitostí patří mezi hráče. Příkaz setalevel má alternativní příkaz setlevel. YCMD mají hned několik možných návratových hodnot. To znamená, že není dobrý nápad používat boolean návratovou hodnotu true/false ale pouze čísla a to 1 nebo 0. Hookované fce jsou jen pouze, kdybych místo scriptu z toho udělal include. A také se zavolají dříve než public. Proměnná IsAdmin neni nic více než jen pro rozlišení jestliže je admin a aby mohl příkaz setalevel. Při hookování OnPlayerDisconnect, jsem musel použít jiné "id" hooku, protože původní už je někde použité v knihovně. y_bit/y_playerarray - Odkaz y_hooks - Odkaz y_timers - Odkaz Hlavní topic - Odkaz
×
×
  • Create New...