Jump to content

Scydo

Obsahový guru
  • Příspěvků

    872
  • Registrován

  • Aktivní

  • Vítězných dnů

    83

Everything posted by Scydo

  1. Tento topic je inspirován z videa https://www.youtube.com/watch?v=RV2ftqfYk_s . Princip je prostý: Napsat jakoukoliv informaci, která bude naprosto zbytečná k životu, je 99.9 % šance, že jí nikdy nevyužijeme/nebudeme potřebovat nebo o ní už v životě neuslyšíme. (pro některé: jakákoliv kromě vzorců z matematiky/fyziky... Takže žádné psaní vzorečků). (zdroj: https://dianetika.cz/o-nas/co-je-scientologie/)
  2. Modrý Kyslík. A s rychlostí 2 MB/s při stahování z nexus stránek. Ono, některé mají i 1 GB, a při více stahovaných souborech se to totálně zpomalí, takže jsem musel postupně
  3. Nastahoval a rozjel Skyrim se 156 módama a hrál déle než 5 vteřin . Akorát problém nastal v momentě kdy jsem měl neustálé pády a do debugu se nenapsalo nic z jakého to je důvodu. Takže když to i po reinstalaci stále padalo, tak jsem to musel odinstalovat a vykašlal jsem se na to už. Když k tomu počítám i celou přeinstalaci, celé mi to trvalo skoro týden(+ spánek a jídlo). Takže jsem se nenudil . Celá složka s módama+retextur byla 89 GB velká a stahovalo se to cca 3 dny celkově dohromady.
  4. Však autor chtěl, abych sdílel informace ohledně zajimavých technologií, tak je sdílím. Nevím, co bych na tom mohl popsat. Stránky u obou odkazu mluví za vše, o co jde, k čemu to bude a hlavně na co to je dobré. Maximálně bych mohl prodiskutovávat nějaká negativa, ale žádná mě momentálně nenapadají.
  5. https://videray.com https://www.kickstarter.com/projects/openbci/openbci-biosensing-for-everybody
  6. :seenobodycares: :airquotes: :catmeh: :itsthelaw: Zdroje:
  7. @Lukasz Ještě jsi nám nenapsal, jaké máš vlastně ty předsevzetí?
  8. Moje předsevzetí je se připojit k nějakým protivládním aktivistům/extrémistům. // Ne, opravdu to není vtip.
  9. Taky že ano. YSI neupravuje kód PAWN, jen nabízí novou možnost, jak s ním pracovat a ve velké většině se zkrátka opakuje(což je i dobře, nikdo by přece nechtěl aby na každý include byl jiný způsob používání, to by se pak nikdo nenaučil).
  10. YSI_Storage\y_ini ***** Prolog: Anketa: Nejdříve si ukážeme jaké funkce mají naše vybrané includy (dini, DOF2, eINI a y_ini), abych ukázal, že není mezi nimi moc velký rozdíl(dokonce, některé nabízejí více možností): /* DINI DOF2 EINI Y_INI */ /* --- */ >>> DOF2_ParseFile(); >>> INI::ParseINI(); >>> INI_ParseFile(); dini_Create(); >>> DOF2_CreateFile(); >>> INI::CreateINI(); >>> INI_Open(); dini_Exists(); >>> DOF2_FileExists(); >>> INI::IsValidHandle(); >>> fexist(); // ! dini_Set(); >>> DOF2_SetString(); >>> INI::WriteString(); >>> INI_WriteString(); dini_IntSet(); >>> DOF2_SetInt(); >>> INI::WriteInteger(); >>> INI_WriteInt(); dini_FloatSet(); >>> DOF2_SetFloat(); >>> INI::WriteFloat(); >>> INI_WriteFloat(); dini_BoolSet(); >>> DOF2_SetBool(); >>> INI::WriteBool(); >>> INI_WriteBool(); dini_Get(); >>> DOF2_GetString(); >>> INI::ReadString(); >>> INI_String(); dini_Int(); >>> DOF2_GetInt(); >>> INI::ReadInteger(); >>> INI_Int(); dini_Float(); >>> DOF2_GetFloat(); >>> INI::ReadFloat(); >>> INI_Float(); dini_Bool(); >>> DOF2_GetBool(); >>> INI::WriteBool(); >>> INI_Bool(); /* --- */ >>> DOF2_SetHex(); >>> INI::WriteHex(); >>> INI_WriteHex(); /* --- */ >>> DOF2_SetBin(); >>> INI::WriteBinary(); >>> INI_WriteBin(); /* --- */ >>> DOF2_SaveFile(); >>> INI::CloseINI(); >>> INI_Close(); /* --- */ >>> DOF2_RemoveFile(); >>> fremove(); /* Asi?*/ >>> fremove(); // ! /* DINI DOF2 EINI Y_INI */ Více o eINI - zde Jediná potíž je, že y_ini má všechny fce pouze načítací ve fci ze ParseFile. Důvodem je hlavně rychlost, protože tímhle způsobem je načítání rychlejší když načítá rovnou celý soubor, či více údajů naráz. (Lze i určité, ale obtížnost spadá do ***). Tak jo začnem. První co asi některé mohlo zarazit je, že y_ini nemá funkce na smazání či zjištění existence souboru. Nicméně, jestliže chceme to zakomponovat, není problém si na to udělat makra: #define INI_Exists fexist #define INI_Remove fremove Když teď na to máme fce tak ukázka jak se zjišťuje existence souboru, otevírají a zavírají: if (INI_Exists("cesta/soubor.txt")) { new INI:soubor = INI_Open("cesta/soubor.txt"); INI_Close(soubor); // ! } Nesmíme zapomenout, že y_ini má vlastní tag na soubory. Ne File: jako mají soubory ale INI: tag. To není tak těžké. Teď si zkusíme do toho souboru vepsat pár údajů, všech možných datových typů: if (INI_Exists("cesta/soubor.txt")) { new INI:soubor = INI_Open("cesta/soubor.txt"); INI_WriteInt(soubor, "myInt", 94515); INI_WriteFloat(soubor, "myFloat", 0.594); INI_WriteHex(soubor, "myHex", 0xFF000000); INI_WriteBool(soubor, "myBool", true); INI_WriteString(soubor, "myString", "Ahoj, tohle je pro string"); INI_Close(soubor); } Pokud jde o načítání, tak jak jsem již psal, y_ini nemá fce na načítání určitých údajů(jako má, ale je to složitější) ale pouze ve volané funkci, kterou můžeme zavolat pomocí INI_ParseFile(). Je ještě jedna funkce na načítání a to INI_Load(). Funkce jsou prakticky stejné, akorát u Load není vícero argumentů ohledně načítání, takže doporučuji raději používat INI_ParseFile(): (A taky hlavně protože jsem zjistil, že Load nemá ani jméno funkce, do které vkládat načítání ale má nějakou vlastní, kterou jsem za boha nezjistil jaká to je ) INI_ParseFile(fname[], remoteFormat[], bool:bFileFirst = false, bool:bExtra = false, extra = 0, bool:bLocal = true, bool:bPassTag = false, bool:bFilter = true, filter[] = "") Tak jo. Má spousty argumentů ale pojďme si je vysvětlit: fname[] = Jaký soubor se má načíst. remoteFormat[] = Z jaké funkce se budou údaje načítat. bFileFirst = Jestliže nejdříve začít načítání souboru a až pak od určitého tagu a nebo při false, proces bude opačný. bExtra = Načíst nějaká speciální data. extra = Jaká speciální data načítat (ve 99 % případů to je playerid) bLocal = Načítat z lokální funkce či globální? bPassTag = Přidát tag k přidání speciálního parametru? NE K JMÉNU FUNKCE. bFilter = Přidat filter na všechny tagy a nebo jen na určitý? filter[] = Přidaný text pro nalézání určitého tagu na načtení. Jestliže jste zmatený, co jaká přesně delá, tak není třeba si dělat obavu. Za sebe můžu říct, že určitě použijete pouze 2 argumenty a to zrovna bExtra a extra pro playerid. Lze použít inline? Ano! A tady přichází ta ukázka, kde šlo poznat, že někdo kód okopíroval z tutoriálu, protože používal následujicí načítání: INI_ParseFile(UserPath(playerid), "LoadUser_%s", .bExtra = true, .extra = playerid); forward LoadUser_data(playerid, name[], value[]); public LoadUser_data(playerid, name[], value[]) { Což by sice fungovalo ale jen pouze, jestliže před vpisování údajů přidal i tag: INI_SetTag(soubor, "data"); Bez tagu, se to nenačte! Takže, přicházím s následujicím: Tagy jsou fajn a užitečné, ale pouze pro rozdělení sekcí údajů a není třeba je používat na načítání určitých údajů. Tím myslím rozdělení, kdy někteří nejdříve načítají registrační údaje jako je jméno, heslo, popřípadě IP a až poté načítají zbytek údajů. Za mě se to zdá zbytečné, a klidně naráz načíst vše, protože se na server stejně nedostane, dokud nezadá správné heslo. Načítat jenom určité bych uznal jen, pokud se načítá skutečně enormně velké množství údajů jako například 100 i víc. No, nevím, hlasujte v anketě, co si o tom myslíte. Tak a jak je to s načítáním samotným. Nic těžkého, stačí si na to zavolat funkci(nesmíse také zapomenout návratovou hodnotu!). Následujicí načítání má pouze 2 argumenty a to jméno klíče co se načítají a do čeho se má načítat: public OnPlayerConnect(playerid) { INI_ParseFile(SouborHrace(playerid), "NacistData", .bExtra = true, .extra = playerid); return 1; } forward NacistData(playerid, name[], value[]); public NacistData(playerid, name[], value[]) { INI_Int("myInt", myInt[playerid]); INI_Float("myFloat", myFloat[playerid]); INI_Hex("myHex", myHex[playerid]); INI_Bool("myBool", myBool[playerid]); INI_String("myString", myString[playerid]); return 1; } Ale jestliže chceme načíst takové hodnoty, do kterých se musí hodnota nastavit/navrátit, můžeme si ve funkci deklarovat proměnnou a pomocí ní načítat vše: #include <YSI_Data\y_playerarray> new PlayerArray:IsVip<MAX_PLAYERS>; forward NacistData(playerid, name[], value[]); public NacistData(playerid, name[], value[]) { new bool:hodnota; INI_Bool("myBool", hodnota); Bit_Set(IsVip, playerid, hodnota); return 1; } Nejlepší ukázka, kde lze dobře využít y_ini je registrace a přihlášení. YSI_Server/y_colours Nebo také YSI_Server\y_colors není nic více než hromada(přesnějí skoro 4000) předdefinovaných barev. Ne jen pro šestnáctková(barva nicku hráče) tak i desitkové nebo i barvy pro gametext. Pro šestnáctkovou před jménem barvy se přidává X11, u desitkové se nemusí nic přidávat stačí jméno a stejně jako u obyčejných gametext se přidává znak ~. Příklady použití: #include <YSI_Server\y_colours> SendClientMessage(playerid, X11_RED, "Tohle celé bude červená zpráva"); SendClientMessage(playerid, X11_RED, "Tohle bude červené "SNOW"tohle bílé"); GameTextForPlayer(playerid, "~X~~H~~H~zluta", 3000, 1); Hlavní topic - odkaz Všechny barvy u y_colors/y_colours:
  11. Jestliže se mi to povede, tenhle topic by měl vyjít přesně na nový rok... (Skoro, o jednu minutu, sakra...) Happy New Year.
  12. 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
  13. Přes YSI se opravdu dá dělat prakticky cokoliv a obsahuje includy prakticky na všechno. I scripty jako například anticheat, závody nebo i registrace/přihlášení. Všechno to má už udělané, a uživatel s tím může pracovat.
  14. 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
  15. 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
  16. No... "iba". A to se bavíme jen čistě o proměnných? Žádné podmínky, cykly nebo fce?
  17. YSI_Data\y_bit ***** Prolog: Dá se říct, že celá YSI ohledně této tématiky má tři hlavní kategorie a to y_bit, y_playerarray, y_jaggedarray. y_bit je include z knihovny pro komprimaci paměti boolean proměnných. Pak jeho odvozenina je y_playerarray, což je prakticky to samé, nicméně s jediným rozdílem a to, že má jiný tag při deklaraci, ale použití je identické(spíše pro rozeznání). A třetí je y_jaggedarray, pomocí něhož lze přeskupit velikosti ve 2D poli a jejich buněk(nicméně jeho použití spadá už do obtížnosti ****). y_bit je výborně hodí, jestliže používáte spousty boolean polí. Problém u proměnných typu int a boolean je, že oba využivají stejný počet paměti, i když u boolean lze mít pouze dvě možné výsledné hodnoty a to 1(true) nebo 0(false). Někteří si můžou říct, že při těch pár proměnných není třeba nic šetřit. Jenže, v momentě, kdy je makro #MAX_PLAYERS 500 a uživatel proměnnou s ním deklaruje hned několikrát, tak už to může být problém. Při tvorbě příkladů jsem využil novou YSI5. Y_Less v návodě na instalaci uvadí, aby uživatelé použili sampctl. Nicméně, je i varianta pro uživatele bez toho a to zde: [klik] Pro použivání y_bit je nejdříve zapotřebí si ho nahrát: #include <YSI_Data\y_bit> Pozor. Jestliže, chcete používat i y_playerarray, musí se načíst i y_bit, protože obsahuje většinu fcí pro něj. #include <YSI_Data\y_bit> #include <YSI_Data\y_playerarray> A následná deklarace(ano, deklaruje se v ostrých závorkách): new BitArray:varX<ind>; // varX = jméno pole // ind = velikost pole, dále jinak jako "slot" new PlayerArray:AdminLevel<MAX_PLAYERS>; // AdminLevel = jméno pole // MAX_PLAYERS = velikost pole, dále jinak jako "slot" y_bit(a y_playerarray) mají následujicí základní funkce, které si každou individuálně vysvětlíme: Bit_Get(BitArray:array<>, slot); Bit_Set(BitArray:array<>, slot, bool:set); Bit_Let(BitArray:array<>, slot); Bit_Vet(BitArray:array<>, slot); Bit_SetAll(BitArray:array<>, bool:set); Bit_Get(); Vrátí boolean hodnotu dle toho, jaký má daný slot. Příklad: new BitArray:varA<256>; if (Bit_Get(varA, 100) == true) { print("Tanto bunka je true !"); } Bit_Set(); Nastaví danému slotu danou boolean hodnotu. Příklad: new BitArray:varA<256>; if (Bit_Get(varA, 32) == true) { print("Chyba, správně by měla být false!"); Bit_Set(varA, 32, false); } if (Bit_Get(varA, 128) == false) { print("Chyba, správně by měla být true!"); Bit_Set(varA, 128, true); } Bit_Let(); a Bit_Vet(); Jde vlastně o podobné funkce s tím rozdílem, že u Bit_Let() se nastaví hodnota na true, mezitím co u Bit_Vet() hodnotu na false. Obě fce jsou o trochu rychlejší než Bit_Set(). Příklad: new BitArray:varA<256>; if (Bit_Get(varA, 32) == true) { print("Chyba, správně by měla být false!"); Bit_Vet(varA, 32); } if (Bit_Get(varA, 128) == false) { print("Chyba, správně by měla být true!"); Bit_Let(varA, 128); } Bit_SetAll(); Jde o funkci, která nastaví u všech buňěk danou boolean hodnotu. Hodí se například u nastavení různých nutných null u hráče či serveru. Příklad: new BitArray:varA<256>; new i = 0; while (i < sizeof(varA)) { Bit_Vet(varA, i); i++; } // Tak tohle celé je zbytečné, protože stačí: Bit_SetAll(varA, false); Využití Tak to je celkém široké, protože jde víceméně o náhražku proměnné boolean, nicméně pár využití by tu bylo: Prostý AFK script: #include <YSI_Data\y_bit> #include <YSI_Data\y_playerarray> new PlayerArray:IsAfk<MAX_PLAYERS>; #include <YSI_Visual\y_commands> YCMD:afk(playerid, params[], help) { // Jestliže ještě není afk: if (Bit_Get(IsAfk, playerid) == false) { Bit_Let(IsAfk, playerid); SendClientMessage(..., "Nyní jsi AFK, pro navrácení napiš /afk"); TogglePlayerControllable(playerid, false); // Jestliže ale už afk je: }else{ Bit_Vet(IsAfk, playerid); SendClientMessage(..., "Vrátil ses zpět do hry."); TogglePlayerControllable(playerid, true); } return 1; } Prostý Event script s typem Admin Portu: #include <a_samp> #include <YSI_Data\y_bit> #include <YSI_Data\y_playerarray> new BitArray:EventPort<MAX_PORT_TYPES>; new PlayerArray:OnEvent<MAX_PLAYERS>; #include <YSI_Visual\y_commands> YCMD:event(playerid, params[], help) { if (getPlayerAdminLevel(playerid) > LEVEL_PLAYER) { Bit_Let(EventPort, strval(params)); // Nastaví se typ eventu } if (Bit_Get(OnEvent, playerid) == true) { return SendClientMessage(..., "Už jsi na eventu !"); } if (Bit_Get(EventPort, 0) == true) { // Na event se lze portnout pouze s vozidlem } if (Bit_Get(EventPort, 1) == true) { // Na event se lze portnout pouze bez vozidla } if (Bit_Get(EventPort, 2) == true) { // Na event se lze portnout pouze s určitým modelem vozidla } if (Bit_Get(EventPort, 3) == true) { // Tento event je TDM/DM } if (Bit_Get(EventPort, 4) == true) { // Tento event je závod } Bit_Let(OnEvent, playerid); // A pošleme ho na event, jestliže vše projde v pořádku return 1; } YCMD:koneceventu(playerid, params[], help) { Bit_SetAll(EventPort, false); Bit_SetAll(OnEvent, false); // Sample code return 1; } Scydovy YSI návody - Hlavní topic: odkaz
  18. Asi myslíš strval() ? Kdyžtak použití určitě jasné: příklad strval("1000"); vrátí 1000, lze i záporná čísla ale pokud to nenajde číslo(nebo to např. nebude správný string) tak ti to vrátí 0.
  19. Jsem velmi rád, že fórum se i po tak masivním omylném výmazu opět snaží o vývoj. Upřímně, už jsem pomalu začal spadat do druhé skupiny propragátorů negativního postoje :D Takže přeji, že všechny naplánované akce výjdou bez problémů a taky samozřejmě všechno nejlepší jak k Vánocům tak i na Nový rok.
  20. Scydo

    nabízím Nabizim

    Taky nic jiného si nezasloužíš. Protože víme, co bys s ním udělal... Pokud jde o to obvinění z "krádeže", tak určitě. Ukradil jsem toho víc jak ty... Dokonce jsem byl v tom tak dobrej, že místo toho, abych okopírovaný kód rovnou prodával, a jen trapně přepsal autora, tak jsem ho celý vymazal, a napsal dle sebe řádek po řádku. Odhalen.
  21. Scydo

    nabízím Nabizim

    Takže počkej... Vysvětli mi jak dokážeš nabízet něco, co sám nemáš? To zní jako efekt, co se děje během dělení nulou... Nebo to je jen další finta, jak z lidí vytáhnout prachy nebo cizí práce? Ale hlavně se mi líbí, jak se snaží nastavit skóre na hodnotu nastavení skóre... To mi něco připomíná:
  22. Scydo

    pomoc helpme

    https://ctrlv.link/shots/2020/12/16/k1Ck.png Opět přidáváš fci, která už existuje, takže jakmile správně vložíš include do Pawno složek, tak až pak nahraj i-zcmd a je to: #include <i-zcmd> // Nebo #include <zcmd> // Podle toho, jak si to pojmenuješ
  23. Scydo

    pomoc pomoc

    Jestliže máš už existující funkci v kódu a kompilátor si myslí, že jí vytváříš další, tak sázím na to, že jsi velmi pravděpodobně zapomněl tu podmínku vkládat i do správné fce: https://sampwiki.blast.hk/wiki/OnPlayerCommandText public OnPlayerCommandText(playerid, cmdtext[]) { if (!strcmp("/prikaz1", cmdtext, true)) { /* Nějaký kód Nějáký kód #2 Nějaký kód #3 */ return 1; } if (!strcmp("/prikaz2", cmdtext, true)) { /* Nějaký kód Nějáký kód #2 Nějaký kód #3 */ return 1; } return 0; }
  24. Skvěle tu radíš. Moc dobrá ráda, celkem dospělácká. Mám jenom jednu otázku... Když nám to tady radíš, něco tak očividně pozitivního, proč to sám ne(u)děláš? Taky se mi líbí, jak nemáš absolutní problém napsat sr***, alepak neochotně chceš psát "deb****". Horší slova se ti píší snáz? Protože, tohle může být potenciální multiúčet, tak se k tomu nějak moc vyjadřovat nebudu...
  25. Jestliže někdo neví o co jde a chtěl by tak zde: Ani netušíš, kolikrát jsem se snažil tohle vysvětlit Ale fórum je dělané právě na tyto možné "agrese" například právě omezením reakci za den. Takže musím dát hold alespoň za to. Nicméně souhlasím, s tím, že tohle už z obyčejného psaní, přeslo místy do mírného útoku(ale pouze místy, a ještě záleží z jaké strany myslíš), ale za mě já už se distancuji, protože nemá cenu vysvětlovat 10x to stálé dokola. Jestliže by měl někdo zájem to vysvětlit, ať to prosím zkusí za mě, děkuji. Ale stále. Je to diskuzní fórum. Takže, tímto způsobem by se to mělo i vést. Diskutovat(v chatu např.) a vysvětlit problém. A pravě v tomto byl problém, kdy to už Num tahal i do jiných příspěvků, viz (https://ctrlv.link/shots/2020/12/14/Jx42.png) Takže na konec, abych jenom neukazoval prstem tak to tady utnu a na další příspěvky od tohoto "uživatele" nebudu reagovat dalším příspěvkem (ani v Chatu). Co se týče reakcí, to je stále stejné. Když to bude oprávněné, dostane ho. Tak tomuhle se nemá ani cenu vyjadřovat... Přecijen ale: Je rozdíl mezi hádáním a pokusem se vysvětlit problém. Jestiže si myslíš, že dva diskutujicí lidé ihned brečí, tak to jsem zvědav, jak vidíš normální diskuzi teda...
×
×
  • Create New...