Jump to content

Search the Community

Showing results for tags 'navod'.

  • 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

  1. Jak vytvořit NPC - překlad ze SA-MP fóra Obtížnost: Překlad a úprava: StarsCream Původní autor: kc Link na původni topic: http://forum.sa-mp.com/index.php?topic=119947.0 Na tuto věc se bude ptát hodně lidí, takže kc udělal TUT, jak pracovat s NPC, tedy neehratelnými postavami, nebo-li také "boti". Obsah 1) Nahrávka pohybu NPC 2) Trovba scriptu 3) Import do módu 1) Nahrávka pohybu NPC Nejdříve potřebujeme zapsat pohyb a všechno okolo toho pro NPC. K tomu slouží nahrávka, která se pak přehrává v postavě NPC. Spusťte SA-MP 0.3 server s jakýmkoli módem. Přihlašte se pod rcon. (Napište "/rcon login " ) a nahrajte filterscript npc_record (Napište "/rcon loadfs npc_record" ) Po úspěšném nahrání npc_record nás zajímají 3 základní příkazy. /vrecord - Začíná nahrávat vaše pohyby a akce vozidla, ve kterém sedíte do souboru jmeno_souboru. /ofrecord - Začíná nahrávat vaše pohyby postavy pěšky do souboru jmeno_souboru. /stoprecord - Ukončuje jakékoli nahrávání V tomto tutorialu programujeme bota, který řídí auto, takže jděte do vozidla a napište /vrecord mujbot (Pzn: musíte být pod RCONem) pro začátek nahrávání. Ujedte trasu, kterou má bot vykonávat a pak napiště /stoprecord. Ukončete hru a jděte do složky ScriptFiles ve vašem SA-MP 0.3 serveru, tam by měl být soubor mujbot.rec. Přesuňte jej do /npcmodes/recordings/še> Hotovo? Super, máte nahrané pohyby NPC a umístěné je v požadované složce. 2) Tvorba scriptu Pokračujeme ve scriptu: Ve složce npcmodes máte spoustu příkladů jak na boty, tyto "mini" scripty určují chování NPC. takže pojďme si vytvořit další. Zapněte pawno, dejte nový soubor a přepiště všechen obsah tímto #define RECORDING "mujbot" //Název souboru, který jsme nahrávali bez přípony .rec #define RECORDING_TYPE 1 //1 pokud je v autě, pěšky je to 2 #include main(){} public OnRecordingPlaybackEnd() StartRecordingPlayback(RECORDING_TYPE, RECORDING); #if RECORDING_TYPE == 1 public OnNPCEnterVehicle(vehicleid, seatid) StartRecordingPlayback(RECORDING_TYPE, RECORDING); public OnNPCExitVehicle() StopRecordingPlayback(); #else public OnNPCSpawn() StartRecordingPlayback(RECORDING_TYPE, RECORDING); #endif Toto může vaypadat nesrozumitelně, proto to vezmu po řádcích: #define RECORDING "mujbot" //Název souboru, který jsme nahrávali bez přípony .rec Komentář již napovídá, že se jedná o jméno souboru, který má přehrávat, akorát bez přípony .rec. takže pokud se váš soubor mujbot jmenuje alfonz, musíte mít v /npcmodes/recordings/ soubor alfonz.rec Pak by to vypadalo takto: #define RECORDING "alfonz" //Název souboru, který jsme nahrávali bez přípony .rec #define RECORDING_TYPE 1 //1 pokud je v autě, pěšky je to 2 Jak opět naznačuje komentář, jde o typ přehrávání. Pokud je tvůj NPC ve vozidle, je tam 1, pokud je pěšky 2. #include Základní include pro boty. public OnRecordingPlaybackEnd() StartRecordingPlayback(RECORDING_TYPE, RECORDING); OnRecordingPlaybackEnd je callback forwardovaný v NPC includu. Tento řádek říká, že jakmile nahrávka končí, začíná opět odznova, takže jee to nekonečná smyčka. public OnNPCEnterVehicle(vehicleid, seatid) StartRecordingPlayback(RECORDING_TYPE, RECORDING); Toto je zase callback, také z includu NPC. Způsobuje, že se začne přehrávat, když bot sedne do auta. public OnNPCExitVehicle() StopRecordingPlayback(); A zase další callback opět z includu NPC. Tento zastavuje přehrávání, kdyykoli je jakkoli bot vyndán z auta. public OnNPCSpawn() StartRecordingPlayback(RECORDING_TYPE, RECORDING); A zase další callback opět z includu NPC. Tento spustí nahrávku NPC pokud se spawne a NPC má byt pěšího typu a ne v autě. Jak vidíte, jee to velmi jednoduché. Nyní uložte vás NPC "mini" script jako "mujbot.pwn" do /npcmodes/še> a zkompilujte jej. Pokud máte hotovo, přesuneme se k dalšímu, poslednímu kroku tohoto tutorialu, pokud vám to vyhodilo errror, ujistěte se, že máte aktualizované includy u pawna na ty u SA-MP 0.3 3) Import do módu Poslední krok... Takže, vytvořili jsme "mini" script pro kontrolu NPC postavy, ale teď potřebujeme bota nahrát na server. Použijeme k mód/filterscipt. zavřete "mini" script, a a otevřete váš mód, nebo filterscript v pawnu. Je čas, zasvětit vás do funkce ConnectNPC. Jak už název napovídá, jde o připojení NPC na server. Podívejme se na parametry funkce a co znamenají... ConnectNPC("Michal","mujbot"); "Michal" - První parametr je jméno bota. Takto rozeznáte různé boty navzájem od sebe. "mujbot" - Toto je jméno souboru (bez přípony) našeho dříve vytvořeného "mini" scriptu. Nyní známe parametry funkce ConnectNPC. Připojme vašeho prvního bota! S vaší novou znalostí funkce ConnectNPC, zkusíme vytvořit NPC připojení při loadu módu/filterscriptu. Vyzkoušeli? OK, dal jsem to do OnGameModeInit... public OnGameModeInit() { print("my gamemode"); ConnectNPC("Michal","mujbot"); return 1; } Nyní, pokud sme vytvářeli bota, co řídí vozidlo, tak mu ho taky musíme dát. Takže script upravíme takto: new AutoBota; //Global variable! public OnGameModeInit() { print("my gamemode"); ConnectNPC("Michal","mujbot"); AutoBota = CreateVehicle(400, 0.0, 0.0, 5.0, 0.0, 3, 3, 5000); return 1; } Pzn: je jedno, kde auto vytvoříte, při začátku přehrávání bota se auto přesune na požadovanou pozici. ještě poslední věc, než začnete testovat svého bota. Musíme ho nějak dát do auta. Já používám OnPlayerSpawn... public OnPlayerSpawn(playerid) { if(IsPlayerNPC(playerid)) //Kontrola, pokud je spawnutý NPC. { new npcname[MAX_PLAYER_NAME]; GetPlayerName(playerid, npcname, sizeof(npcname)); //Zjišťuje jméno NPC. if(!strcmp(npcname, "Michal", true)) //Zjišťuje, jestli je jméno bota Michal { PutPlayerInVehicle(playerid, AutoBota, 0); //Strčí NPC do auta, které sme vytvořili } } return 1; } Nyní zkompilujte mód/filterscript a hurá na server. S trochou štěstí uvidíte bota jezdit v autě přesně tak, jak jste nastavili. Gratuluju! Vytvořili jste svého 1. robota Nefunguje něco? Napište sem, a společně to opravíme Návod upraven tak, aby odpovídal šabloně pro "Nové návody" Návod označen jako platný Ten to návod byl označen jako platný.Návod může být kdykoli označen jako nevhodný či neplatný
  2. Úvod: • Je veľmi ťažké urobiť návod na povolania kvôli ich všestrannosti a rozmanitosti, ale posnažím sa spraviť to. Postup pri vytváraní zamestnania: • Je takmer nemožné použiť na každé zamestnanie rovnaký návod, ale približne sa môžete riadiť týmto mojim: Postup napísaný v kóde: Príklady zamestnania a konkrétny postup: 1. Kompletné zamestnanie sa ako policajt: Informační návod - Návod označen jako platný Ten to návod byl označen jako platný.Návod může být kdykoli označen jako nevhodný či neplatný
  3. Takze jelikoz ma samp 0.3 public OnPlayerClickPlayer tak proc toho nevyuzit treba na pekny PM system. V nejake starsi RC verzi to bylo tak ze kdyz ste klikli na hrace v tabulce (klavesa TAB) tak vam to otevrelo textove okno jakoby jste chteli napsat do chatu a samo se tam napsalo "/pm ID " a uz ste jenom psali a pak enter...jenomze tahle psaci funkce uz je co ja vim zrusena....tak sem na samp foru hledal neco podobnyho a nasel sem celkem hezkej PM system...jenze mel problem, kdyz ste poslali zpravu nekomu jinymu nez sobe tak vam spadnul server....tak sem se rozkodl to opravit a dat vam to sem....ale ted uz dost kecu a pustime se do prace: Zacneme rovnou od zacatku: nahoru dejte toto: #define DIALOGID_PM 123tohle urcuje ID dialogu...jelikoz predpokladam ze to nebude jedine dialogove okno co pouzijete tak sem nechal ID 123 aby jste na to uz v podstate nemuseli myslet. a toto: new PlayerPMTarget[MAX_PLAYERS];je to promena ktera vam urcuje na koho jste kliknuli v tabulce hracu potom: public OnPlayerClickPlayer(playerid, clickedplayerid, source) { if (source == CLICK_SOURCE_SCOREBOARD) { PlayerPMTarget[playerid] = clickedplayerid; ShowPlayerDialog(playerid, DIALOGID_PM, DIALOG_STYLE_INPUT,"Poslat PM","Zde napis zpravu:\n","Odeslat","Storno"); } return 1; }tadyto nastavi tu promenou na hrace na ktereho jste kliknuli a otevce dialogove okno s inputem na text(polem kam napisete text) a dale do modu dejte toto: public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) { if (response && dialogid == DIALOGID_PM) { if (!IsPlayerConnected(PlayerPMTarget[playerid])) return SendClientMessage(playerid, 0xE10000AA, "Hrac neni pripojen."); new msg[128]; new msg2[128]; format(msg, 128, "[PM] Od %s : %s", Jmeno(playerid), inputtext); SendClientMessage(PlayerPMTarget[playerid], 0xFFFF00AA, msg); format(msg2, 128, "[PM] Odeslana hraci %s : %s", Jmeno(PlayerPMTarget[playerid]), inputtext); SendClientMessage(playerid, 0xFFFF00AA, msg2); for(new a=0;a toto odesle vasi zpravu kterou ste napsali do toho okenka hraci na ktereho jste kliknuli. a jeste pokud vam to hodi error ohledne "Jmeno" tak dejte dolu do modu tohle: stock Jmeno(playerid) { new j[255]; GetPlayerName(playerid,j,255); return j; } Aby jste si to mohli vyzkouset sami na sobe tak to neni omezene ze nemuzete poslat PM sami sobe...takze kdyz kliknete na sebe tak si muzete poslat PM aby jste vedeli jak to vypada. Pokud s tim nekdo bude mit problemy tak piste. EDIT: na prani uzivatele "tippl" byl pridan do TuTu i PM Reader pro RCON adminy...;a++) Návod označen jako platný Ten to návod byl označen jako platný.Návod může být kdykoli označen jako nevhodný či neplatný
  4. #emit ***** Rád bych vás chtěl informovat, že tento topic bude čistě jen o základních informacích. Vyhnu se stránkám textů jak funguje compiler, další formy preprocesorů... jelikož to není tak extrémně podstatné. Zdravím vás u návodu na nejtěžší látce v pawn. CO JE TO EMIT? Existují 2(možná víc) výborných anglických návodů na emit, ale v obou jsou asi 2 strany čisté teorie a informací, ohledně jak funguje compiler, jak vzniklo PAWN, jak funguje amxing, co je to opkód... takže najít tam prostě smysluplnou větu a odpověď na tuhle otázku tam není jednoduché, ale rád vám na ní odpovím já: emit nejsou nic více než jen pointery(jestliže nevíte, co je to pointer, budete se muset naučit teorii C++ především v oblasti pointerů, jelikož bez toho emit nepochopíte). Každá proměnná, kterou deklarujete má relevantní informace a to jméno, údaj a především adresu: new Promenna = 3; Vy vidíte pouze 2 informace a to jméno proměnné(Promenna) a údaj(3). Ale adresu ne. A s ní můžeme pracovat pomocí emitu. EMIT A PAWN Mezitím, co v C++ můžete pracovat s kolika pointery se vám zlíbí, v pawn na to máte pouze 2 pointery a to PRI(primární aka první) a ALT(alterantivní aka druhé). Obou můžete přiřadit hodnoty jak z lokálních tak i globálních proměnných(ano, skutečně emit potřebuje vědět, jestliže vkládáte údaje z globální či lokální), a jenom těmto 2 se mohou dít dané "operace"(sečtení, negace, odečtení aj). Určitě se někteří tedy ptáte k čemu je mi emit, když můžu jednoduše přiřaďovat a měnit hodnoty pomocí rovnítka? Ano, můžete ale pointery zjistí adresu proměnné. Najde její adresu, kde je přesně a přepíše údaj. Rovnítko "hledá", jak se jmenuje proměnná a přepíše údaj. Proto je taky emit rychlejší než operace. Nechápeme? Vysvětlím: V případě, že hledáte text(nebo-li jméno proměnné) tak je to pomalejší, jelikož se musí zjistit přesné jméno do poslední znaku, aby jsme neměli například proměnnou ahoj a Ahoj a nebral to jako 1 a tu samou. Ale, pod adresou si můžeme představit jako "id" té proměnné, a číslo se hledá podstatně jednodušeji, protože jediný způsob jak najít číslo je řádově počítat(0, 1, 2, 3, 4, 5...), a protože emit zná adresu proměnné(což neni nic více než číslo), proto je také rychlejší. UKÁZKA EMITU Emit se značí preprocesorovým znamínkem # a slovem emit: #emit Pro představuj tu je jednoduchá operace a to sečtení 2 proměnných a výsledek vložený do 3 proměnné: new Cislo1 = 11, Cislo2 = 22, Vysledek; #emit LOAD.S.PRI Cislo1 #emit LOAD.S.ALT Cislo2 #emit ADD #emit STOR.S.PRI Vysledek printf("%i", Vysledek); // 33 Teď si to postupně rozebereme: #emit LOAD.S.PRI Cislo1 Do primárního(prvního) pointeru načte a připíše hodnotu proměnné Cislo1 #emit LOAD.S.ALT Cislo2 Do alternativního(druhého) pointeru načte a připíše hodnotu proměnné Cislo2 #emit ADD Vezme hodnoty z primárního a alternativního a sečte je. #emit STOR.S.PRI Vysledek Výsledný údaj ze primární(jelikož add sečte a vepíše do primárního) a připíše jí do proměnné Vysledek. Pro uživatele, co ovládají C++, tak je to stejné(spíše podobné) jako: int Cislo1 = 11; int Cislo2 = 22; int Vysledek; int * p1 = &Cislo1; /* 0000 */ int * p2 = &Cislo2; /* 0004 */ Vysledek = *p1 + *p2; Tady bych to rád zakončil, jelikož jsem vám chtěl ukázat jen základy k emitu. Samozřejmě, emit jak píše Misiur v návodě http://forum.sa-mp.com/showthread.php?p=3430898 v případě tvorby filterscriptu či gamemodu ho vůbec nepotřebujete. Spíše se hodí pro tvorbu includů a knihoven kvůli rychlost. TEST RYCHLOSTI #emit vs konstantní #emit vs obyč. operace #emit: 13 Konstantní emit: 13 Operace: 26
  5. Trošku té základní gramotnosti okolo pawn. Pawn x Pawno Velmi často dochází k záměně těchto slov a tím k celkové mystifikaci. Pawn je jazyk ve kterém scriptujete. Pawno je editor do kterého scriptujete. Ŕádky Je absolutně jedno kolik má který mód řádků. Kvalita módu se vůbec neodvíjí od počtu řádků. Počet řádků je čistě jen o optimalizaci a zkušenostech pawnera. Můžete mít mód který má 200k řádků a mód který má 50k řádků. Rozdíly mezi nimi ve funkčnosti být nemusí. Například kdyby dělal mód třeba Lukáš V. tak vzhledem že mám pocit nikdy v pawn nedělal tak jeho mód by měl třeba 500k. A kdybych ten stejný mód dělal třeba já tak můžu nahnat třeba 70% úsporu co se týče řádků. Funkce na funkci Krásným příkladem je třeba stock IsPlayerInSphere. Proč ? Je to uplně to stejné jako IsPlayerInRangeOfPoint jen s jiným pořadím argumentů. Fuguje to uplně stejně. Jen IsPlayerInRangeOfpoint je nativní tudíž rychlejší. Programuju ? Laicky řečeno ano. Pawn je ale scriptovací jazyk tudíž spíš scriptujete. Na první pohled není poznat rozdíl mezi jazykem programovacím a scriptovacím. Ale taková poučka třeba může být , že výplod programování nepotřebuje pro svůj běh server. Samozřejmě nelze to taky použít uplně kdykoliv. Budu postupně editovat stím co mě napadne dále.
  6. PŘECHOD Z DINI/DCMD/JINÉ NA YSI4 ***** Je to až k neuvěření... dini oslavuje 10 let od doby jeho první publikace(8 let od jeho poslední aktualizace) a stejně se najde spousty uživatelů, kteří si ho bez nějakých námitek vesele používání, a prohlašují ho za nejlepšího, i když ani nemají ponětí jak přesně funguje. To samé dcmd. A navíc, o nějaké lepší, rychlejší a efektivnější variantě nechtějí ani slyšet, protože buď zatvrdnou na nich a ostatní je pro ně pitomost nebo moc složité i přesto, že je to neuvěřitelných 80% to samé. Myslím, že je asi zbytečné vám vysvětlovat funkčnost dini/dcmd a jejich pomalost. Zkušenější to už dávno ví a snaží se to vtlouc začátečníkům, kteří buď o tom nic neví, nebo to nechápou či to ignorují. Chci se zaměřit na ukázky hlavně v kódě. Ale nenechte se zmást. I když mají uživatelé YSI za neskutečně rychlou, už se najdou i rychlejší includy. Akorát, k čemu si stahovat celou knihovnu a z ní využít jen pár includů a pak si postahovat ty rychlejší? Nikdo vám za to nemůže utrhnout hlavu, když budete pracovat jen s knihovnou, protože už jenom, že se odvážíte pracovat s YSI je pro ně něco. V tomto topicu vám nechci jen popsat, jak jednoduše přejít z dcmd a dini na YSI4, ale také další změny v kódě, například práce s timery, cyklusem a tak dále. A do budoucna doufám, že v případě, kdyby si někdo neuměl představit jak přejít na YSI, nebo by ho měl za složité, tak, že bych mu mohl já nebo někdo z uživatelů mu odeslat odkaz na tento topic, aby se přesvědčil o opaku. Chtěl bych upozornit, že tento topic je doporučen především pro uživatele, co už mají přehled, jak funguje jaká funkce či callbacky. Proto se nechci zdržovat s vysvětlováním některých fcí, které se objeví v tomto topicu. Obsah Ukládání a načítání - Ukázka, jak můžeme jednoduše přejít z dini na y_ini. Příkazy - Ukázka, jak je jednoduché přejít z dcmd na y_commands. Proměnné - Ukázka, jaký je rozdíl práce klasicky s proměnnými a s y_playerarray + y_bit. Formátování - Ukázka, jak nám y_va velice usnadní práci s formátováním například zpráv. Dialogy - Ukázka, jak nám y_dialog pomůže s dialogID a všeobecně s prací s dialogy. Cyklus - Ukázka, jak y_iterate může zjednodušit práci s cyklusem. Callback - Ukázka, jak můžeme jednodušeji hookovat callbacky pomocí y_hooks jinak, než pomocí preprocesoru "ALS". Timer - Ukázka, jak je jednoduché přejít z klasického timeru na y_timers. Použito z knihovny Závěr Ukládání a načítání Ukládání a načítání je docela základní záležitost. Hlavně pro registraci a přihlášení. Ale pracovat na tom s dini je zbytečně zdlouhavé a ještě velice pomalé. Je desítek návodů na dini, samozřejmě i na jeho mnohonásobně lepší variantu dof2, najdou se dokonce návody i na y_ini, ale nikdo je moc nechápe, proto zůstávájí u toho dini s tím, že si myslí, že je to jednodušší. Ale dělat na registraci s y_ini není o nic moc složitější. Tady je taková rychlá jednoduchá registrace přes dini: (INFO Ano, prozatím se nebudeme zdržovat s hashováním hesla. A také nepřidám i ukládání při odchodu, protože je to prakticky to samé, jako je v callbacku s dialogem přihlašování). Teď si ten samý script uděláme pomocí YSI knihovny. V případě, že ostatním funkcím nerozumíte, tak nevadí. Dozvíte se o nich později v topicu. Začneme v OnPlayerConnect(). Především budeme pracovat s podmínkou existence souboru. Můžeme jí nahradit, že v případě, že neexistuje jeho soubor, zobrazí se dialog s registrací, a pokud ano, tak načteme údaje ze souboru(kvůli heslu hlavně), a zobrazíme dialog s přihlašováním. Ano, já vím. Načítám už všechny ostatní údaje (život, adminlevel...), když se ještě ani nepřihlásil. Ale to nevadí, jelikož, pokud nezadá správné heslo, tak se stejně na server nedostane. A když ho zadá správně, tak se nemusíme zdržovat s načítáním už: A nyní vše načteme. Funkce pro načítání si jsou dosti podobné s dini(jak později uvidíte v tabulce). Nebude tak obtížné se je naučit. Všimně te si, že nemusíme už zadávat adresu souboru, odkud to má načítat. Callback už to zná, stejně jako funkce: A nakonec už jen samotné callbacky s dialogy. Oba budou samozřejmě kontrolovat, zda hráč nezadal žádné heslo. U registrace nemusíme zjišťovat, jestli hráčův soubor neexistuje pro vytvoření, jelikož INI_Open ho vytvoří automaticky v případě, že neexistuje, a nesmíme zapomenout soubor zavřít. U přihlášení samozřejmě zkontrolujeme, zda nezadal špatné heslo. Jelikož jsme už údaje načetli, nemusíme naše heslo znova zjišťovat ze souboru, už s naší proměnnou můžeme pracovat rovnou. Stejně jako načítání, i zde jsou callbacky. Musíme přidat i forward: U přihlášení můžeme i přidat zprávu, že se přihlásil. Jinak nemusíme nic více, jelikož vše se jíž načetlo. No, nevím co vy, ale podle mě je to mnohem přehlejší, kratší, jednoduší... a dokonce i mnohem rychlejší jak po stránce tvorby, tak po stránce funkčnosti. To byla jen ukázka, kde jsme použili ukládání 4 základních datových typů (integer, string, float a boolen). Aby jste viděli, že v práci mezi dini a y_ini není tak velký rozdíl, připravil jsem si pro vás 2 tabulky. Obě obsahují dini a y_ini, a obě obsahují fce a informace k nim: Funkce pro ukládání a vepisování údajů [/td] td --> dini YSI Účel Funkce Informace Funkce Informace Vytvořit soubor dini_Create(); - INI_Open INI_Open otevře a zároveň vytvoří sbr v případě, že neexistuje. Používá ještě tag INI: jako mají files File: Zavřít soubor - Zavírá soubor zbytečně při každém vepsání! INI_Close(); - Existence sbr dini_Exists Je to prakticky jen preprocesor fce fexist - - Vepsat tag - - INI_SetTag(); Jde jen o poznámku, ale lze i šikovně využít. Vepsat integer dini_IntSet - INI_WriteInt(); - Vepsat string dini_Set - INI_WriteString(); - Vepsat float dini_FloatSet - INI_WriteFloat(); - Vepsat boolen dini_BoolSet - INI_WriteBool(); - Vepsat hex - - INI_WriteHex(); - Vepsat bin - - INI_WriteBin(); - Funkce pro načítání údajů dini YSI Účel Funkce Informace Funkce Informace Načíst všechny údaje--INI_ParseFile();Všechny fce na načítaní pak stačí přidávat do callbacku.Načíst integerdini_Int-INI_Int();-Načíst stringdini_Get-INI_String();Musíte do fce přidat i délku.Načíst floatdini_Float-INI_Float();-Načíst boolendini_Bool-INI_Bool();-Načíst hex--INI_Hex();-Načíst bin--INI_Bin();- Příkazy Pawn obsahuje sice callback, který zjišťuje, zda hráč zadal příkaz, ale zjistit, co zadal po příkazu (tzv. parametry) není už tak jednoduché. Takže, začátečníkům dělá problémy vytvořit příkazy s id, například /heal [iD_hráče]. Ale na internetu je jednoduché řešení, a to za pomoci includu. Akorát, velká většina skončí u dcmd. Jakmile přidáte do kódu patřičný preprocesor (pro jeho "nahrání"), tak využití je celkem jednoduché a prosté: dcmd_prikaz(playerid, params[]) { Avšak to není všechno. S každým příkazem musíme ještě přidat takovou "funkci" ještě do callbacku OnPlayerCommandText. Nechci se zdržovat s vysvětlováním o co přesně je a co to dělá, ale jde o: public OnPlayerCommandText(playerid, cmdtext[]) { dcmd(prikaz, 6, cmdtext); Není to tak hrozné, ale představte si, že to budete muset psát pro každičký příkaz, a jakmile zapomenete jen jediný, tak nám to nepůjde a budeme se divit proč. Všimněte si, jak je každé přidávání příkazu zpracováno: nejdříve samotné slovíčko dcmd, což je i jméno preprocesoru, díky kterému můžeme naše příkazy přidávat, pak spodní podtržítko a jméno příkazu a nakonec parametry playerid a params. Okej... nyní to porovnáme se zápisem y_commands: YCMD:prikaz(playerid, params[], help) { Jako u dcmd, je také nějaké označení, že přidáváme příkazy s parametrem a to YCMD, pak to pokračuje podobně akorát místo spodního podtržítka je tam dvojtečka a za ní jméno příkazu, a nakonec také parametry playerid a params, včetně help. Parametr help nám vrací true v případě, že hráč napíše příkaz a za ním otazník (například /admins ?), nebo nemusí to být otazník ale cokoliv jiného. Ale, když ho nebudete využívat, nic ne nestane. Nyní, kde je takový rozdíl? Není nějak extrémně velký, pro ukázku obě přidávání příkazu: dcmd_prikaz(playerid, params[]) { YCMD:prikaz(playerid, params[], help) { Rozdíl v zápisu tak velký není ale po stránce funkčnosti je celkem dost značný. Hlavně po stránce rychlosti, jelikož y_commands pracuje na principu, že každý příkaz bere jako nějaké id, jelikož hledání/porovnávání stringu(textu) je mnohem pomalejší. Ale také y_commands obsahuje další vychytávky, například přidávání alternativných příkazů: public OnScriptInit() { Command_AddAltNamed("help", "pomoc"); Nyní, když přidáme příkaz help, tak automaticky už je /help to samé jako /pomoc a nemusíme nikde nic vracet či přidávat znovu obsah příkazu. Nebo také lze jednoduše povolit, zda se hráčovi povede příkaz napsat. V případě, že je mu nastaveno false, bude to pro něj, jako by ten příkaz neexistoval: if (!IsPlayerAdmin(playerid)) { Command_SetPlayerNamed("kick", playerid, false); } Nyní si ukážeme nějakou rozsáhlejší ukázku, například zrovna příkaz /heal [iD_hráče], nejdříve využijeme dcmd: Teď to zkusíme s y_command. První co změníme je naše první slovíčko a to ze dcmd_ na YCMD:. Dále přidáme parametr help. Využijeme již formátované zprávy ze y_va, a nakonec vymažeme naší "funkci" z callbacku: Žádný extra rozdíl, co? Každopádně je to kratší samozřejmě a nemusíme přidávat naší "funkci" do callbacku. Ale jak jsem říkal, po stránce funkčnosti je tam značný rozdíl. Proměnné Další ukázky se už netýkají dini a dcmd, ale spíše, kdyby jste dělali na gamemodu či scriptu, tak jak přejít na YSI a pracovat s knihovnou. V téhle části jde o práci s proměnnými, přesněji s datovým typem boolen a polem. Zkušenější, možná i někteří začátečnicí ví, že ke každé proměnné můžeme přidat pole, a čím větší to pole je, tím více zabírá paměti. Například proměnná: new bool:Promenna[MAX_PLAYERS]; Jak jistě někteří ví, tak MAX_PLAYERS není nic více než jen preprocesor pro číslo 500. Když si nyní trošku započítáme, tak zjistíme z příkladu 500*4 že touto jedinou proměnnou využijeme až 2 000 bajtů. Teď si jich představte například deset. Nemluvě o tom, že některé publikované gamemody se zdrojovým kódem obsahují až stovky takových proměnných. Můžeme využít i char, které nám pole vydělí 4, a využití paměti spadne už na 500 bajtů, ale furt je to dost. Ale, když přidáme proměnnou pomocí y_bite: new BitArray:Promenna<MAX_PLAYERS>; Tak využití paměti spadne už jen na pár desítek bitů(nejsem si jistý přesným číslem). Nojo, ale, když chceme zjistit, jestli má hráč premium, tak jak to uděláme? Jednoduše, přidáme si naší proměnnou(když je to pro hráče hodí se využít y_playerarray): new PlayerArray:bIsPremium<MAX_PLAYERS>; Teď ale příjde ta těžší část. y_playerarray a y_bit používá na zjištění hodnoty a přiřazování hodnot fce. Ale, pokud vám nesedí s nimi pracovat, můžete na to použít preprocesor(ukážeme si později). Použítí pro podmínky(takže zjištění hodnoty): if (Bit_Get(sIsPremium, playerid)) /* v případě, že vlastní premium */ if (!Bit_Get(sIsPremium, playerid)) /* v případě, že nevlastní premium */ Nebo si na to přidáme preprocesor: #define IsPlayerPremium(%0) Bit_Get(bIsPremium, %0) if (IsPlayerPremium(playerid)) /* V případě že vlastní premium */ if (!IsPlayerPremium(playerid)) /* V případě že nevlastní premium */ Pro přiřazení hodnot máme 2 možnosti, a to buď klasické Bit_Set, kterým můžeme přiřadit hodnotu jak true tak i false a nebo využít 2 rychlejší fce: Bit_Set(sIsPremium, playerid, true); /* Nyní vlastní premium */ Bit_Set(sIsPremium, playerid, false); /* Nyní přišel o premium */ Bit_Let(sIsPremium, playerid); /* Nyní vlastní premium */ Bit_Vet(sIsPremium, playerid); /* Nyní přišel o premium */ A toť vše. Že to není tak složité, že ne? A co, když chceme VIP s 3 levely? Řešení je prosté. Prostě využijeme dvojdimenzní proměnnou: new PlayerArray:bIsPremium[3]<MAX_PLAYERS>; Můžeme si říct, že 0 bude Bronze, 1 bude Silver a 2 bude Gold. A pro kontrolu, pokud například není Silver použijeme: if (!Bit_Get(sIsPremium[1], playerid)) return NejsiSilver(); A pro nastavení Silver VIP zase použijeme: Bit_Let(sIsPremium[1], playerid); /* Nyní má VIP level Silver Formátování I když Pawn obsahuje dvě funkce na odeslání zpráv (jednotlivci a nebo všem hráčům na serveru), tak jediné, co může odeslat je text, ale ne nějaké zjištěné hodnoty, například adminlevel toho hráče, jméno toho hráče a podobně. To všechno musíme formátovat. Nojo, ale každé formátování vyžaduje nějakou proměnnou, kterou bude formátovat, pak samotnou fci formátování a pak, co s tím formátováným obsahem (například odeslání zprávy). To už jsou ale 3/4 řádky a jen například na jedinou zprávu. Pro více zpráv je potřeba více řádků a to hrozně zdržuje. Ukážeme si nějaký příklad. Chceme, aby nám do chatu zjistilo několik důležitých informací(pro lepší ukázku příkladu v tomto případě nebudeme využívat nový řádek, aka \n): A to ještě formátujeme jedinou proměnnou neustále. Jsou i uživatelé co neustále formátují další a další proměnné. Ale jak vidíte, je to zdlouhavé, trochu i matoucí a ne zrovna jednoduché, hlavně, kdyby tam bylo více údajů. Ale pomocí y_va to jde velice zjednodušit. Ten už má všechny "prvky"(proměnnou, formátování a akci) už v jednom, takže nemusíme nic formátovat, stačí jenom přidat: Mnohem kratší, jednoduší a přehledější, že ano? A to není vše, také je to rychlejší než obyčejné formátování, jak přes funkci, tak přes preprocesor, dokonce i rychlejši než fce za použitím emitu: Věřím, že jak se to používá, tak je zcela zřejmé. Navíc si můžeme přidat i vlastní va_ fci(je to už složitější), ale y_va už má některé fce již předpřipravené, takže nemusíme je vytvářet. Zde je seznam těch nejdůležitějších, jejich parametry a jejich příklad použití: Dialogy Tohle je velice častý problém mnoha začátečníků ale i několika autorů scriptů. Jelikož fce ShowPlayerDialog(), vyžaduje vepsat ID dialogu, tak si musí každý pawner hlídat, aby nezadával stejná id, jinak by se dialogy křižily a nefungovaly by, jak mají. Na to je hned několik řešení: 1) Tohle je známe především u gamemodů a nebo u větších scriptů, a to místo toho čísla(dialogid) přidat preprocesor s tím číslem, a tak si uživatel pak může následující čísla měnit, aby mu dialogy už fungovaly. 2) Ani tohle není vzácné, a to za dialogid dosadit nějaké obrovské číslo. Například 3000, jelikož nejvyšší možné dialogid je 32767, tak ve většine případech je celkem malá šance, že se zrovna dialogy budou křížit. Ale je tu ještě jedna možnost, a to nezadávat žádné dialogid a to pomocí y_dialog. Ten funguje na principu, že najde nejnižší nepoužívané dialogid (například, pokud zrovna někdo nebo něco nepoužívá dialogid 1, tak ho vezme) a ním pak pracuje. Uživatel má možnost také si nějaké id "zabrat", takže nebude hledat ale bude pracovat jen s tím daným id. Ukážeme si příklad, máme 3 dialogy v nějakém už propracovanějším módě: Je v tom už menší zmatek, a to jsou pouze tři dialogy s listy. Nic méně. Pomocí y_dialog to celé můžeme zkrátit a úplně se vyhnout callbacku OnDialogResponse. Jak je to možné? Můžeme pomocí fce Dialog_ShowCallback, což už sama o sobě něco říká, a to, že veškéré akce daného dialogu budou v patřičném callbacku, který si přidáme. Jak se s tím pracuje, tak vám samozřejmě ukážu. Nejdříve nahradíme fci ShowPlayerDialog, funkcí Dialog_ShowCallback. Ale místo parametr dialogid nedáme nějaké id ale 3 slova a to "using callback dDialogNeco" bez uvozovek. Kdo nerozumí, co to je, tak to znamená, že dění toho dialogu(hráč stiskne tlačítko, hráč klikne na list) se bude odehrát v tom daném callbacku dDialogNeco(z příkladu to jistě pochopíte). Jinak pokračujeme stejně. Jen doporučuji tuhle fci Dialog_ShowCallback u typů dialogů listy, input a password. Na obytečjný text můžete využití obyčejnou fci Dialog_Show(později si ukážeme použití). Tak začneme tím přepsáním: Pak přidáme postupně každý forward a každý callback, jako u normální přidávání callbacku. Nemůžeme to dát do jednoho, musíme to dát samostatně, jinak by to nefungovalo. Nemusíme kontrolovat o jaké jde id dialogu, každý ten callback to ví: Přehledjší, rychlejší, kratší a navíc bez potřeby id dialogu. Ale co, když chceme odeslat obyčejný box, se zprávou, který bude mít jenom tlačítko zavřít? Není problém, můžeme využít obyčejné Dialog_Show. Dialog se po stisknutí na tlačítko Zavřit jednoduše prostě zavře a nic více se nebude dít: Dialog_Show(playerid, DIALOG_STYLE_MSGBOX, "Uvítání", "Vítej na našem serveru", "Zavrit", ""); Cyklus Hodně tvůrců scriptů jistě zná asi nejstarší cyklus na všechny hráče na serveru a to: for(new i; i<MAX_PLAYERS; i++) { if(IsPlayerConnected(i)) { Akorát u několika lidí se moc neosvědčilo kvůli preprocesoru, který není nic více než jen číslo 500. A tak někteří přidávají preprocesor MAX_PLAYER_EX s menším číslem, (nebo jen undefnou MAX_PLAYERS a nahradí novým číslem) například: #define MAX_PLAYER_EX (100) for(new i; i<MAX_PLAYERS_EX; i++) { if(IsPlayerConnected(i)) { Ale to je furt pro několik lidí docela složitě na naučení. A ještě k tomu nedávno se v updatu objevila nová fce, která nám zjistí nejvyšší playerid na serveru a to: for(new i = 0, j = GetPlayerPoolSize(); i <= j; i++) { if(IsPlayerConnected(i)) { Ale zase je i tento způsob pro někoho složitý na naučení. A tak je tu ještě jedna možnost, dost jednoduchá, mnohem rychlejší, a to za pomocí y_iterate/y_foreach. Tam stačí pouze jmého samotného cyklusu z tohoto includu, pak deklarovaná proměnné a, co má ocyklovat: foreach(new i: Player) { } Nyní máme cyklus, který projede všechny přítomné hráče na serveru. Nic více nepotřebujeme a pracujeme stejně jako s cyklusem v první ukázce, akorát je rychlejší, efektivnější a bez nutnosti fce IsPlayerConnected. A přitom to nemusí být zrovna Player, může to být i pro všechny vozidla(Vehicle), všechny BOTy(Bot), všechny charaktery(Character) a nebo všechny actory(Actor). Nebo, si můžeme přidat i vlastní tzv. Iterator, který pak do cyklu dosadíme, který má project. Můžeme například nemovitosti. Chceme, aby nám vypsal všechny volné nemovitosti. Začneme tím, že si určíme maximum nemovitostí a to třeba 10, pak deklarujeme samotný Iterator za pomoci zrovna tagu Iterator a na konec proměnné, které budeme potřebovat. V případě, že chceme, aby tam ty nemovitosti vypsal, tak jednoduše použijeme funkci Iter_Add, ale nejdříve musíme pro něj najít volné místo v cyklusu pomocí Iter_Free. Pak následuje samotný foreach a na konec, pokud chceme, aby nám to nevypsalo jakoukoliv nemovitost, tak jednoduše ten iterator "vyčistíme", pomocí Iter_Clear: Jakto, že nevypíše tu Autodílnu s cenou 1000? Odpověď je prostá. Sice jsme všechny 3 přidali do iterátoru pomocí fce PridatNemovitost, ale v cyklusu foreach podmínkujeme, zda je volná a to naše Autodíla není. Iterator má podle mě velikou škálů využití. Například s ním lze jednoduše vytvořit fci, která vám už rovnou bude přidávat administrátory do /admins: Callback Tato část se týká především tvůrců includů. Asi znáte, že velká škládá fci nebo možností potřebuje patřičný callback, jinak nebudou fungovat, jak mají. A tak vytváří další callback a pak uživatel ho bude muset přidat do hlavního callbacku, který a_samp již obsahuje, například: Což ještě sice není tak hrozné, ale jde furt o jediný callback. Nojo, ale jak jsem říkal, je více udělaných takových to includů, hlavně ty staré, takže to může dopadat i nějak takto: To už je trošku bordel, co? Samozřejmě je úspornější a lepší možnost a to přes preprocesor "ALS". Ale ten není o nic moc jednoduší. Ale je tu ještě 3. možnost. Představte si, že můžete volat 2x stejný callback a nemusíte přidávat nový (přes forward). S y_hooks je to jednoduché. Stačí akorát zaměnit slovíčko public za hook a můžete přidat stejný callback a compiler nebude protestovat: Takhle můžete do include si vesele si přidávat hooky a uživatel nebude muset nikam přidávat volání. Užitečné, že ano? Ukážu nějaké jednoduché využití. Budu mít include, například nějaké úplně jednoduché VIP.inc a v něm: Tak. Nyní jsem si vytvořil include, který obsahuje nastavení proměnné (Bit_Let) aka jeho VIP, a hook, že jakmile se spawne tak mu to nastaví plnou vestu a život, a napíše, že se spawnul VIP hráč. Teď, když si náš include nahrajeme a přejdeme do editoru, kde máme nový list: A to je vše. Jakmile se hráč připojí tak se nastaví VIP. A jakmile se spawne, stane se přesně to, co jsem popisoval před chvilkou. Všimněte si, že nikde nemusím volat OnPlayerSpawn a přidávat do něj nějaký nový callback VIP_OnPlayerSpawn. Snad tohle posune některé include už ku předu trošku. Timer A nakonec timer. Tohle se už týká i té pokročilejší skupiny. Viděl jsem hodně includů či scriptů, kde jak zachází s timery. Od jejich spuštění, po jejich obsah až k zastavení. Timer je snad jedna z nejpoužívanějších funkcí v PAWN. Má hodně velkou škálů využití. Tipy, ochrana, anticheat, eventsystém, porty (ty s 5 sekundovým čekáním), nemovitnosti, dražba a mnoho dalšího. Ale my se zaměříme na nějaké, které lze pomocí YSI4 velice zjednodušit a vylepšit. Například, asi snad každý zná jeden z nejjednoduších scriptů a to tipy. Několik desítek zpráv, které se po nějakém čase odešlou hráčům. Jako ukázku jsem si připravil tipy a k nim 5 zpráv, včetně spuštění a vypnutí: Jak vidíte, i když to jsou obyčejné tipy je to celkem rozsáhlé. Teď zkusíme udělat ty samé tipy zapomocí y_timers. První co, tak můžeme vymazat proměnnou TipyTimer, jelikož y_timers pracuje "s jménem" toho timeru(uvidíme v příkladě), ale může se mu samozřejmě nastavit ID. Dál změníme fci na spouštění na repeat (defer by nám spustil jednom jednou, repeat nám to bude opakovat). Čas nemusíme zadávat, to budeme zadávat až ve fci timer. A nakonec vypnutí opět zaměníme fci KillTimer na obyčejné stop: A to je vše. Není to přecijen jednoduší a kratší? Nemluvě o tom, že je to rychlejší. Ale y_timers také se může široce využít, například když máte příkazy ve VIP a chcete, aby je hráč mohl využít třeba jen 1x za 2 minuty. Ve starších verzích(v některých nových vlastně také) to vypadá nějak následovně: Je to dost vyčerpávající, a to jsou zatím jenom 3 příkazy. Teď na to zkusíme využít y_timers. Můžeme použít, že spolu se spuštěním timeru, nám pošle i pár potřebným argumentů a to id toho hráče a jaký příkaz použil. Takže nebudeme muset přidávat timer na každý příkaz zvlášť ale stačí jediný: Opět mnohem kratší a jednoduší, že ano? Použito z knihovny Include Cesta Alternativní cesta Popis y_ini <YSI_Storage\y_ini> <YSI\y_ini> Ukládání a načítá údaje ze souboru. y_commands <YSI_Visual\y_commands> <YSI\y_commands> Umožňuje pracovat s příkazy a s jejich parametry, plus help. y_bit <YSI_Data\y_bit> <YSI\y_bit> Šetří paměť proměnné boolen(s polem). y_playerarray <YSI_Data\y_playerarray> <YSI\y_playerarray> Šetří paměť proměnné boolen(s polem). Doporučeno na proměnné určené pro hráče. y_va <YSI_Coding\y_va> <YSI\y_va> Umožní pracovat s již formátovanými funkcemi. y_dialog <YSI_Visual\y_dialog> <YSI\y_dialog> Umožní pracovat s dialogy bez nutnosti jim přidělovat id. y_iterate <YSI_Data\y_dialog> <YSI\y_iterate> Umožní pracovat s cyklusem foreach. y_foreach <YSI_Data\y_foreach> <YSI\y_foreach> Alternativní cesta na include y_iterate y_hooks <YSI_Data\y_hooks> <YSI\y_hooks> Umožní jednoduše hookovat callbacky. y_timers <YSI_Data\y_timers> <YSI\y_timers> Práce s timery ze YSI. y_scriptinit <YSI_Coding\y_scriptinit> <YSI\y_scriptinit> Přidává callback, který je možné použít jak ve FS tak v GM. Závěr To je prozadím vše. V případě, že naleznu nějakou další užitečnou zajímavou informaci, přidám jí sem. ! Kódy, kde jsem nevyužíval YSI slouží jako ukázka! Nebyly kontrolovány compilerem a tak se tam můžou vyskytnout chyby. Proto je v žádném případě nepoužívejte! PS: Topic obsahuje skutečně mnoho textu a kódu a tudíž, než ho celý pročtu a zkontroluji, chvilku to potrvá, tak se prosím prozatím zdržte komentářů poukázující na nějakou chybu. Děkuji.
  7. sscanf2 ***** Zdravím vás u dalšího návodu, konkrétně o velice populárním a dost často používaném pluginu a to sscanf. Jde o plugin, který mnoha uživatelům vypomáhá při tvorbě více parametrových příkazů či u více informačních údajů(například inputtext) v samp. Obsah Ukázka použití Specifikátory Integer String Pole Enum Velké specifikátory Integer String Pole Enum Použití Změnit hráčovi počet životů Zabanovat hráče s důvodem Nahrát více údajů v jednom souboru Download Závěr Ukázka použití Hodně uživatelů využívá tuhle funkci hlavně v podmínkách v příkazech, například: if (sscanf(params, "ui", ID, Penize)) return SendClientMessage(playerid, -1, "Použití: /prachy [ID/Jméno hráče] [Počet]"); Jak to funguje? Vezme údaje ze params, a z celého řetězce zjistí, kde tam jsou dané datové typy, a to u nebo-li string(číslo nebo nick hráče, či jeho součást) a i nebo-li integer, a dosadí do daných proměnných(ID a Peníze), a podmínka nám vrací true/false dle toho, zda při rozdělovaní (ne)vzniknou nějaké komplikace, například jeden z údajů chybí, nebo nenašel v řetězci daný datový typ(například místo čísla aka peněz napíšete nějaký string. Funkce to vyhodnotí jako text, nikoliv číslo a chyba). V případě, že jste to nepochopili, můžeme si to ukázat na jiném příkladě. Jelikož sscanf2 je funkce, lze jí jednoduše používat i bez podmínek: new String[15] = "abcd", Cislo = 0; sscanf("Potrebuji 1000", "si", String, Cislo); printf(" %s %i", String, Cislo); Právě jsme si deklarovali 2 proměnné a to String a k němu jsme si přiřadili hodnotu "abcd" a proměnnou Cislo s přiřazenou hodnotou 0. Nyní využijeme fci sscanf, aby vzal daný řetězec a to Potrebuji 1000 a rozdělil je do těchto 2 proměnných. Jak si můžete všimnout, obsahuje 2 datové typy a to string a integer. Takže jelikož první údaj je string tak logicky první specifikátor(o nich později) bude s, a druhé je číslo, takže specifikátor bude i. Nyní se nám za proměnné dosadí oba údaje a do konzole se nám vypíše Potrebuji 1000, a ne abcd 0. Specifikátory Nebudu tu vypisovat všechny specifikátory, které sscanf obsahuje, ale jen prozatím ty, které uživatelé používají asi nejčastěji: Specifikátor Jméno Příklad i, d Integer 4, 72, -1024 [/td] --> s String Ahoj, Admin, sb75c4 l Boolean true, false f Float 0.5, 33.1, -99.9 h, x Hex FF, 0xAD35 u Jméno/ID hráče a botů SkiBig18, 2 r Jméno/ID hráče SkiBig18, 2 Integer Specifikátor se značí písmenkem i nebo d. Nejjednoduší specifikátor. Jde rozdělit 2 nebo i více řad čísel do daných proměnných, například: new Cislo1 = 0, Cislo2 = 0; sscanf("100 200", "ii", Cislo1, Cislo2); printf("%i %i", Cislo1, Cislo2); /* Vypíše 100 200 */ Není problém ani s řadou čísel, jen si musíte hlídat počet íček: new Cislo[6]; sscanf("1 4 9 2 -1 5", "iiiiii", Cislo[0], Cislo[1], Cislo[2], Cislo[3], Cislo[4], Cislo[5]); printf("%i %i %i %i %i %i", Cislo[0], Cislo[1], Cislo[2], Cislo[3], Cislo[4], Cislo[5]); V případě, že vynecháte jedno z íček, sscanf poslední hodnotu specifikuje jako 0 a také jí dosadí. To stejné platí i u stringu: sscanf("1 4 9 2 -1 5", "iiiii", Cislo[0], Cislo[1], Cislo[2], Cislo[3], Cislo[4], Cislo[5]); printf("%i %i %i %i %i %i", Cislo[0], Cislo[1], Cislo[2], Cislo[3], Cislo[4], Cislo[5]); /* Vypíše 1 4 9 2 -1 0 */ Lze nahradit písmeno i také písmenem d, výsledek i efekt bude naprosto stejný: sscanf("1 4 9 2 -1 5", "dddddd", Cislo[0], Cislo[1], Cislo[2], Cislo[3], Cislo[4], Cislo[5]); printf("%i %i %i %i %i %i", Cislo[0], Cislo[1], Cislo[2], Cislo[3], Cislo[4], Cislo[5]); /* Vypíše 1 4 9 2 -1 5 */ String Specifikátor se značí písmenkem s. Další nejčastěji používaný specifikátor. Používá se hlavně v příkazech pro důvody. Ale sscanf2 nabízí více možností práce se stringem. Jak jsem již na začátku ukazoval, kód: sscanf("Potrebuji 1000", "si", String, Cislo); Vypíše Potrebuji 1000. Ale co, když chceme do první proměnné přidat ještě slovo? sscanf("Potrebuji ihned 1000", "s[10]i", String, Cislo); Tak selže dosazování, jelikož slovo ihned není číslo, a po slově Potrebuji doplní nulu a tím končí. Řešení je prosté. Stačí buď přidat další specifikátor: new String[2][10], Cislo; sscanf("Potrebuji ihned 1000", "s[16]s[6]i", String[0], String[1], Cislo); printf("%s %s %i", String[0], String[1], Cislo); /* Vypíše Potrebuji ihned 1000 */ A nebo vynechat číslo a nechat jen jeden specifikátor pro celý text: new String[16]; sscanf("Potrebuji ihned", "s[16]", String); print(String); /* Vypíše Potrebuji ihned */ Ale problém je teď, že specifikátor vezme celý text, nebo-li všechno po slovech Potrebuji ihned(pokud samozřejmě bude mít větší délku). V případě, že potřebujeme jen samostatně jediné slovo, stačí přidat po specifikátoru mezeru: new String[16]; sscanf("Potrebuji ihned", "s[16] ", String); print(String); /* Vypíše Potrebuji */ Pole Specifikátor se značí písmenkem a<>. Práce s polem u sscanf je podobné jako stringu, s tím rozdílem, že velikost pole nepoužíváme jako délku, ale k dosazení počtu prvků, a za každý prvek se dosadí daná hodnota v poli určité proměnné, například: new Pole[5]; sscanf("1 3 8 6 2", "a<i>[5]", Pole); printf("%i %i %i %i %i", Pole[0], Pole[1], Pole[2], Pole[3], Pole[4]); /* Vypíše 1 3 8 6 2 */ Jak si můžete všimnout, specifikátory pro jediné pole jsou 2 a to a(array v překladu pole), a i jako integer. Aby si sscanf nepletlo pole a velikost retězce, využíváme na začátek specifkátoru pro pole, jiné závorky, a to <>. Specifikátor i pak obsahuje datové typy pole nebo-li čísla. A nakonec [5] je maximální počet buněk v poli. Samozřejmě lze kombinovat i jiné datové typy v poli, například string: new String[3][3 + 1]; sscanf("Abc Ab A", "a<s[4]>[3]", String); printf("%s %s %s", String[0], String[1], String[2]); /* Vypíše Abc Ab A */ Jak to funguje tady? Deklarovali jsme si 3 řetězce s počtem 4 znaků (3 + nul. znak). Za každý řetězec dosadí specifická písmena. Je to úplně stejné jako bychom retězci0( String[0] ) přiřadili hodnotu "Abc", řetězci1( String[1] ) hodnotu "Ab" a řetězci2( String[2] ) hodnotu "A". Enum Specifikátor se značí písmenkem e<>. Tento dodatek se považuje za nejlepší dodatek v sscanf. A ani se nedivím, jelikož vám umožní měnit výčet hodnot dokonce v samotném enumu. A jako u pole i zde platí, že lze přepsat všechny datové typy. Ale je to pár rozdílů, jeden z nejrelevantnějších je, že musíte vypsat všechny specifikátory všech datových typů, co enum obsahuje(logicky, jinak by sscanf nevěděl, jakou proměnnou má přesně v enumu přepsat). Ukážeme si to na příkladu: enum enum_PlayerInfo { e_AdminLevel, e_VipLevel, e_VipBodu, } new e_Enum[enum_PlayerInfo]; sscanf("5 1 1000", "e<iii>", e_Enum); printf("%i %i %i", e_Enum[e_AdminLevel], e_Enum[e_VipLevel], e_Enum[e_VipBodu]); /* Vypíše 5 1 1000 */ Zde jsem si deklarovali proměnnou s výčtem hodnot, který obsahuje AdminLevel, VipLevel a počet bodů. Sscanf nám zjistí ze všech specifikátorů ve specifikaci struktury v enumu(nebo-li v <>), že jde o čísla a tak přepíše hodnoty. Ano, práce s polem je mu velice podobná a teď zkusíme zapojit více datových typů a všem nastavíme nějakou hodnotu: enum enum_Info { e_Integer, e_String[24], Float: e_Float, e_Char } new e_Enum[enum_Info]; sscanf("10 Ahoj 12.33 c", "e<is[24]fc>", e_Enum); printf("%i %.2f %s %c", e_Enum[e_Integer], e_Enum[e_Float], e_Enum[e_String], e_Enum[e_Char]); /* Vypíše 10 12.33 Ahoj c */ Velké specifikátory V případě, že vložíme prázdný řetězec(či neúplný), můžeme mu při rozdělení přidat i tzv. "defaultní hodnoty", které pak dosadí, nejjednodušší příklad: Integer new Cislo; sscanf("", "I(10)", Cislo); printf("%i", Cislo); /* Vypíše 10 */ Specifikátor se značí písmenkem I nebo D. Jak si můžeme všimnout, sscanf dostal prázdný řetězec na rozdělení. Tak jak je možné, že se nám do konzole odešle 10? Je to prosté: U specifikátorů datových typů, jsme zaměnili malé i za velké I, což je znamení pro sscanf, že v případě, že tam hodnotou nenajde v řetězci, ať tam doplní jinou, a ta hodnota se přidává do kulatých závorek (). Samozřejmě, lze nastavit defaultní hodnoty i více prom. například: new Cislo1, Cislo2; sscanf("", "I(10)I(20)", Cislo1, Cislo2); printf("%i %i", Cislo1, Cislo2); /* Vypíše 10 20 */ String Specifikátor se značí písmenkem S. Tady je to zajímavější, jelikož defaultní hodnotu u stringu nemusíme psát do uvozovek: new String[4 + 1]; sscanf("", "S(Ahoj)", String); print(String); /* Vypíše */ Samozřejmě nesmíme zapomenout na délku stringu, jelikož nám to hodí varování. Doplňujeme zásadně až za defaultní hodnotou: new String[4 + 1]; sscanf("", "S(Ahoj)[5]", String); print(String); /* Vypíše Ahoj */ Pole Specifikátor se značí písmenkem A<>. Ani tady není extra rozdíl. Může se hodit při doplňování hodnot, například: new Pole[3]; sscanf("1 2", "A<i>(3)[3]", Pole); printf("%i %i %i", Pole[0], Pole[1], Pole[2]); /* Vypíše 1 2 3 */ Všimněte si ale, že nesmíme přepsat specifikátor integeru, v poli na velké písmenko ale musíme celé pole. I tady je funkčnost jednoduchá. Pole, které jsme si deklarovali má 3 prvky. My mu ale doplníme jenom 2. Díky velkému písmenku A informujeme sscanf, že tam nebudou všechny údaje, a tak poslednímu ať defaultně přiřadí hodnotu 3. A co, když tam nebudou například 2? Postup je stále stejný: sscanf("1", "A<i>(1, 2)[3]", Pole); A jak postup, tak výsledek bude stejný. Sscanf dostane na rozdělení pouze jeden údaj ze 3, které mají být správně v poli, a tak vezme defaulní hodnoty a doplní je. Ale co, když nastavíme defaulní hodnotu pouze 1 na 2 chybějící prvky?: sscanf("1", "A<i>(2)[3]", Pole); Tady sscanf nemá moc na vybranou. I když jeho primárním cílem bude doplnit všechny hodnoty do pole, dostane jen jednu defaultní, a zapracuje velice zajímavě: vezme tu jedinou defaultní a doplní je do všech prvků v poli, takže ve výsledku se nám do konzole vypíše 1 2 2 Enum Specifikátor se značí písmenkem E<>. Tady je problém, že uživatel ne jen, že musí přidávat všechny specifikátory ve výčtu, ale také ještě v případě práce s defaultními hodnotami v enumu musí vypsat k každému údaji defaultní hodnotu, i když už nějakou má, například: sscanf("11", "E<iii>(11, 22, 33)", epromenna); printf("%i %i %i", epromenna[e_cislo], epromenna[e_cislo2], epromenna[e_cislo3]); /* Vypíše 11 22 33 */ Jak si můžete všimnout, v řetězci je 11, ale stejně jí musíme přidat do defaultních hodnot. Na závěr kapitoli něco trošku těžšího: sscanf("", "E<s[5]fs[6]ii>(Ahoj, 11.2, Scydo, 11, 22)", epromenna); print(epromenna[e_String]); printf("%.1f", epromenna[e_Float]); print(epromenna[e_String2]); printf("%i", epromenna[e_Integer]); printf("%i", epromenna[e_Integer2]); /* Vypíše: Ahoj 11.2 Scydo 11 22 */ Použití Změnit hráčovi počet životů Zabanovat hráče s důvodem Nahrát více údajů v jednom souboru Download To už je složitější, jelikož i když se vydala nová verze, spousty uživatelů hlásí, že buď je tam něco nefunkční a nebo samotná verze nefunguje. Proto jsem vám pro jistotu nahrál verzi sscanfu, kterou používám já a použil jsem ho i na kódy v tomto návodě, a je plně funkční: https://uloz.to/!vV4WzRFEG/sscanf2-zip Ihned na začátek zdrojového kódu samozřejmě nesmíte zapomenou sscanf vůbec nahrávat: #include <sscanf2> A do konfigurace serveru do řádku pro nahrávání pluginů na Windows vepíšete: plugins sscanf V případě Linuxu: plugins sscanf.so Závěr Naschvál jsem vynechal spousty ještě dodatků v sscanf2, například "quite" stringy, jelikož nevidím moc lidí, co by to tady využívalo. A na závěr bych chtěl dodat, že některá teoretická vysvětlení se mohou zdát neúplná, pozměněná a nebo trošku špatná. Důvodem je, že zcela správnÁ vysvětlení by prostý začátečník nebo i čtenář nepochopil. Samozřejmě, pokud mám některé hrubější chybu v kódě nebo v teorii, jak mi napište. Ověřený návod Tento návod prošel validací, a lze ho proto považovat za ověřený.
  8. Zdravím, včera a dnes došlo k reorganizaci návodů. Došlo ke smazání některých sekcí a k přidání nových. Stále platí, že návody musí projít revizí, aby mohly být označeny jako ověřené, a stále platí, že musí být zpracovány dle předlohy. a) Návody V hlavní sekci jsou všechny návody, které se týkají SA:MP funkcí a callbacků. Také jsou zde návody, které vysvětlují, jak něco vytvořit. Příklady: dialogy, textdrawy, cmd systémy, file systémy atd. Základy pawn a Rozšířené znalosti pawn Tyto podsekce sdružují návody, které se týkají přímo jazyka Pawn. V Základech jsou návody pro nováčky, v Rozšířených znalostech návody pro pokročilejší. Příklady pro Základy: proměnná, podmínky, cykly, funkce atd. Příklady pro Rozšířené znalosti: bitová manipulace, pokročilá inicializace polí, ternární operátor, pokročilá práce s řetězcem atd. c) Práce s YSI Podsekce pro návody o knihovně YSI. Příklady: y_ini, y_commands, y_groups, y_va atd. d) Nové návody Podsekce, která slouží k přidávání nových návodů. Pokud chcete založit nový návod, udělejte to zde. Jakmile dojde k ověření moderátorem, bude návod přesunut do příslušné (pod)sekce. e) Neověřené návody V této podsekci je většina dosavadních návodů. Žádný z nich neprošel kontrolou, proto je nemůžeme považovat za ověřené. Nezodpovídáme za pravdivost ani úplnost informací z těchto návodů.
  9. Obtížnost: Osnova: 1. Úvod, co je to podmínka 2. Vytvoření podmínky 3. Další možnosti větvení 4. Vnořené podmínky 5. Závěr 1. Úvod Dostáváme se k šestému návodu o základech jazyka Pawn. V něm si vysvětlíme, co to jsou podmínky a jak probíhá větvení. Než budeme pokračovat, měli byste mít znalosti alespoň z předchozích dvou návodů (z tohoto a tohoto). Abychom se posunuli dál, musíme si nejdříve říct, co to podmínka a větvení je. Podmínku si můžeme představit jako výraz (tvořený relačními a logickými operátory – viz návod na operátory), který je buď pravdivý, nebo nepravdivý. Je-li pravdivý, vykoná se kód, který jsme podmínili. Můžeme také určit, co se stane, když je výraz nepravdivý. Tomuto rozdělování kódu dle výsledku podmínek se říká větvení. Bloky ani klíčová slova if, else a switch neukončujeme středníkem! 2. Vytvoření podmínky Teď si zkusme vytvořit takovou podmínku a větev. Syntaxe je následující: . if(logický výraz) { //kód } . Klíčové slovo if nám značí, že se bude jednat o podmínku (z angličtiny if – jestliže). Do kulatých závorek píšeme logický výraz, který se má vyhodnotit. Mezi složené závorky (které nám tvoří větev – blok) píšeme kód, který se má vykonat, když je podmínka pravdivá. Zkusme si to na příkladu: . new cislo = 10; if(cislo == 10) { print("Hodnota proměnné cislo je rovna deseti."); } . Podmínka je pravdivá, kód se vykoná. Co by se stalo, kdyby podmínka pravdivá nebyla? Nestalo by se nic. Kód uvnitř bloku if by se nevykonal. 3. Další možnosti větvení Na začátku jsem psal, že může nastat i situace, kdy chceme, aby se něco stalo v případě, že podmínka neplatí. I to nám jazyk umožňuje provést, a to hned několika způsoby. a) else If nám tvořilo "pravdivou větev", else nám pak bude tvořit "nepravdivou větev", tedy blok, který se vykoná, když bude podmínka nepravdivá. Nutno dodat, že k else se podmínka nedává a že ho nemůžeme použít samostatně (je vázán na if). . new cislo = 5; if(cislo == 10) { print("Hodnota proměnné cislo je rovna deseti."); } else { print("Hodnota proměnné cislo není rovna deseti."); } . Podmínka se vyhodnotí jako nepravdivá, takže blok if se přeskočí a místo toho se vykoná blok else. b ) else if Složitější větvení nám pak umožňuje else if. Zjednodušeně řečeno je to else s dodatečnou podmínkou. Else if bloků může být více, ale stejně jako else nemohou stát samostatně. . new cislo = 5; if(cislo == 10) { print("Hodnota proměnné cislo je rovna deseti."); } else if(cislo == 5) { print("Hodnota proměnné cislo je rovna pěti."); } else if(cislo == 0) //tato podmínka se už vyhodnocovat nebude { print("Hodnota proměnné cislo je rovna nule."); } . A v čem je vlastně kouzlo else if? Script vyhodnotí podmínku v if, zjistí, že je nepravdivá, tak přeskočí k následujícímu else if. Opět vyhodnotí podmínku, zjistí, že je pravdivá, tak vykoná tento blok. K dalšímu else if už ale nepokračuje, protože jedna z podmínek nad ním byla pravdivá. A tím se liší od soustavy if – if – if; u takové soustavy by totiž script vyhodnocoval všechny podmínky nehledě na to, že některá z nich byla pravdivá. c) if – else if – else Samozřejmě to jde také vše zkombinovat, záleží jen na tom, co potřebujeme. . new cislo = 5; if(cislo == 10) { print("Hodnota proměnné cislo je rovna deseti."); } else if(cislo == 5) { print("Hodnota proměnné cislo je rovna pěti."); } else { print("Hodnota proměnné cislo není ani 10, ani 5."); } . d) switch Pro určité případy zde máme ještě jednu strukturu, a tou je switch. O switchi si něco povíme až v příštím návodu. 4. Vnořené podmínky Do teď jsme si ukazovali jednoduché podmínky a jednoduché větvení. Ale abyste si nemysleli, že je možné jen tohle, máme možnost podmínky vnořovat, tedy vkládat podmínku do podmínky. Viz tento příklad: . new cislo = 5; if(cislo > 0) { if(cislo == 5) { print("Hodnota proměnné cislo je rovna pěti."); } else { print("Hodnota proměnné cislo není rovna pěti."); } } . Zde je vidět, že uvnitř bloků lze tvořit další bloky. Platí to u podmínek, platí to u cyklů, platí to u všech struktur, které tvoří bloky. 5. Závěr A to je z podmínek všechno. Dozvěděli jste se, jak podmínky a větvení fungují, jak můžete uplatnit svou znalost relačních a logických operátorů v praxi, jak tvořit větev pro pravdu i nepravdu, jak vytvářet složitější podmínky a jak podmínky vnořovat. V dalším návodu si probereme onen zmíněný switch. Tento návod, stejně jako ten předchozí, je určen pro nováčky, pokročilejší věci byly buďto úplně vynechány, nebo jsou uvedeny ve spoilerech. Přesto, zdá-li se Vám, že jsem něco opomněl, někde jsem se spletl nebo se jen chcete vyjádřit, pište do tohoto tématu. Ověřený návod Tento návod prošel validací, a lze ho proto považovat za ověřený.
  10. DOF2 UKLÁDÁNÍ A NAČÍTÁNÍ, UŽ NIKDY VÍC DINI ***** Nemůžu uvěřit, že i po tak dlouhé době si hodně začátečníků myslí, že se s dini furt nejjednodušeji pracuje, a nechtějí ani dof2, protože buď to podle nich nefunguje a nebo je to moc těžké... Ale to jsou jenom kecy. Ve skutečně rozdíl práce mezi dof2 a dini je asi tak 5%. Ukážu vám, jak na to. Instalace je jednoduchá. Stačí z odkazu http://pastebin.com/TQJGwYyZ zkopírovat obsah do textového souboru a uložit ho nejlépe jako dof2.inc(ta koncovka .inc je tam důležitá). #include <dof2> VYTVOŘIT SOUBOR DOF2_CreateFile(JménoSouboru[], Heslo[] = ""); Parametry: JménoSouboru[] - Jméno souboru, který má vytvořit ve scriptfiles. V případě, že jde o větší cestu, stačí přidávat lomítka. Heslo[] - Vepíše hash string(aka heslo) rovnou do souboru a nemusíme používat fci SetString. V případě, že to nechceme, můžeme ten argument jednoduše vynechat. Ukázka použití: EXISTENCE SOUBORU DOF2_FileExists(JménoSouboru[]); Ukázka použití: public OnGameModeInit() { if (DOF2_FileExists("soubor.txt")) { DOF2_CreateFile("soubor.txt"); } return true; } PŘEJMENOVAT SOUBOR DOF2_RenameFile(JménoSouboru[], NovéJmeno[]); Ukázka použití: DOF2_RenameFile("soubor.txt", "Soubornik.txt"); /* Nyní se soubor ve scriptfiles přejmenuje na Soubornik */ SMAZAT SOUBOR DOF2_RemoveFile(JménoSouboru[]); Ukázka použití: DOF2_RemoveFile("soubor.txt"); /* Zcela smaže soubor.txt ve scriptfiles */ ULOŽENÍ SOUBORU DOF2_SaveFile(); Ukázka použití: public OnGameModeInit() { if (!DOF2_FileExists("soubor.txt")) { DOF2_CreateFile("soubor.txt"); DOF2_SetInt("soubor.txt", "jenomcislo", 666); DOF2_SaveFile(); } return 1; } VEPSAT STRING/TEXT DO SOUBORU DOF2_SetString(JménoSouboru[], Klíč[], String[]); Parametry: Klíč[] - Jde o informaci, pod jakým klíčovým slovem, by se měla ta daná hodnota ukládat. Nejčastěji jde o jedno vystihující slovo. String[] - Údaje, které se vepíšou do souboru(v tomhle případě je hodnota řetězec). Ukázka použití: public OnPlayerConnect(playerid) { new Soubor[40 + 1], Jmeno[MAX_PLAYER_NAME + 1]; GetPlayerName(playerid, Jmeno, sizeof(Jmeno)); GetPlayerName(playerid, Soubor, sizeof(Soubor)); strcat(Soubor, ".txt"); if (!DOF2_FileExists(Soubor)) { DOF2_CreateFile(Soubor); DOF2_SetString(Soubor, "JmenoHrace", Jmeno); /* Nyní se ve souboru uloží údaj: JmenoHrace = SkiBig18 */ DOF2_SaveFile(); } return 1; } ZJISTIT STRING/TEXT ZE SOUBORU DOF2_GetString(JménoSouboru[], Klíč[]); Ukázka použití: new Text[MAX_PLAYER_NAME + 1]; strcat(Text, DOF2_GetString(Nick, "JmenoHrace")); print(Text); /* Vypiše: SkiBig18 */ return 1; } VEPSAT INTEGER/ČÍSLO DO SOUBORU DOF2_SetInt(JménoSouboru[], Klíč[], Číslo); Parametry: Číslo - Údaje, které se vepíšou do souboru(v tomhle případě je hodnota číslo). Ukázka použití: DOF2_SetInt(Nick, "Penize", GetPlayerMoney(playerid)); ZJISTIT INTEGER/ČÍSLO ZE SOUBORU DOF2_GetInt(JménoSouboru[], Klíč[]); Ukázka použití: GivePlayerMoney(playerid, DOF2_GetInt(Nick, "Penize")); VEPSAT BOOLEAN DO SOUBORU DOF2_SetBool(JménoSouboru[], Klíč[], bool:Boolean); Parametry: Boolen - Údaje, které se vepíšou do souboru(v tomhle případě je hodnota boolen). Ukázka použití: DOF2_SetBool(Nick, "IsVip", bIsVip[playerid]); ZJISTIT BOOLEAN ZE SOUBORU DOF2_GetBool(JménoSouboru[], Klíč[]); Ukázka použití: bIsVip[playerid] = DOF2_GetBool(Nick, "IsVip"); VEPSAT FLOAT DO SOUBORU DOF2_SetFloat(JménoSouboru[], Klíč[], Float:FloatHodnota); Parametry: FloatHodnota - Údaje, které se vepíšou do souboru(v tomhle případě jsou hodnoty desetinná čísla). Ukázka použití: new Float: Health; GetPlayerHealth(playerid, Health); DOF2_SetFloat(Nick, "Health", Health); ZJISTIT FLOAT ZE SOUBORU DOF2_GetFloat(JménoSouboru[], Klíč[]); Ukázka použití: SetPlayerHealth(playerid, DOF2_GetFloat(Nick, "Health")); UŽITEČNÉ FUNKCE DOF2 Nyní přichází fce, které dini neobsahuji, a které můžou být někomu užitečné. Jedna z nich je možnost si vytvořit jakousi zálohu i s časem: DOF2_MakeBackup(JménoSouboru[]); Ukázka použití: DOF2_MakeBackup("soubor.txt"); Za další obsahuje hashování textu, ale je to součásti fce, která spolupracuje s DOF2_CreateFile a to přesněji s parametrem Heslo[], které můžete spolu s vytvořením souboru také uložit: DOF2_CheckLogin(JménoSouboru[], Heslo[]); Ukázka použití: if (dialogid == dialog_Login) { if (!response) return 1; if (DOF2_CheckLogin(Nick, inputtext)) { /* Nahrát data */ }else { /* Zadal nesprávné heslo. */ } } Další tu je možnost přejmenovat samotný klíč v souboru, kam se ukládají údaje, kdyby se vám na něm něco nelíbilo: DOF2_RenameKey(JménoSouboru[], JménoKlíče[], NovéJméno[]); Ukázka použití: DOF2_SetInt(Nick, "Penize", GetPlayerMoney(playerid)); DOF2_RenameKey(Nick, "Penize", "Prachy"); DOF2_SaveFile(); UKÁZKA POUŽITÍ DOF2 /* Deklarujeme si 4 nejznámější datové typy: */ new Cislo = 101, Float: DesCislo = 103.3, String[10] = "Ahoj", bool: Boolean = true; public OnFilterScriptInit() { /* Zjistíme, jestli, že neexistuje, jestliže ne, vytvoří nový */ if (!DOF2_FileExists("soubor.txt")) DOF2_CreateFile("soubor.txt"); /* Vepíše integer do souboru: */ DOF2_SetInt("soubor.txt", "Cislo", Cislo); /* Vepíše float do souboru: */ DOF2_SetFloat("soubor.txt", "DesCislo", DesCislo); /* Vepíše string do souboru: */ DOF2_SetString("soubor.txt", "String", String); /* Vepíše boolean do souboru: */ DOF2_SetBool("soubor.txt", "Boolean", Boolean); /* Uloží (uzavře) soubor: */ DOF2_SaveFile(); /* A nyní si můžeme všechny údaje načíst: */ /* Přiřadí k proměnné Cislo zjištěnou hodnotu ze souboru: */ Cislo = DOF2_GetInt("soubor.txt", "Cislo"); /* Přiřadí k proměnné DesCislo zjištěnou hodnotu ze souboru: */ DesCislo = DOF2_GetFloat("soubor.txt", "DesCislo"); /* Přiřadí k proměnné String zjištěnou hodnotu ze souboru: */ strcat(String, DOF2_GetString("soubor.txt", "String")); /* Přiřadí k proměnné Boolean zjištěnou hodnotu ze souboru: */ Boolean = DOF2_GetBool("soubor.txt", "Boolean"); return 1; } A zde je screen, jak se nám uložily údaje do souboru: ROZDÍL PRÁCE MEZI DINI A DOF2 Jak jsem již psal, rozdíl v práci s ním je asi tak 5%. Jestliže mi nevěříte ani po tomto návodu, zde je odkaz na pastebin, kde jsem shrnul ukázky fcí asi 3 nejznáměnších používaných includů na ukládání a načítání: pastebin.com/8MW3kzbF A pokud to stále je málo, tak dokonce i samotný dof2 obsahuje preprocesor, který stačí jen přidat, a můžete pracovat úplně stejně jako s dini: #if defined DINI_CONVERT #define dini_Exists DOF2_FileExists #define dini_Remove DOF2_RemoveFile #define dini_Create DOF2_CreateFile #define dini_Set DOF2_SetString #define dini_Get DOF2_GetString #define dini_IntSet DOF2_SetInt #define dini_Int DOF2_GetInt #define dini_BoolSet DOF2_SetBool #define dini_Bool DOF2_GetBool #define dini_FloatSet DOF2_SetFloat #define dini_Float DOF2_GetFloat #define dini_Unset DOF2_Unset #define dini_Isset DOF2_IsSet #if !defined _dini_included #define _dini_included #endif #endif Ověřený návod Tento návod prešiel validáciou a preto je možné ho považovať za overený.
  11. Zdravím všechny nováčky, co vidějí poprvé Pawno, tento tutoriál už se bude týkat samotného pawna Začneme teda s tím že si vysvětlíme něco o pawnu a pawn: Pawn: -je programovací jazyk určený hlavně k tvorbě SA-MP modů a Filterscriptů. Pawno: -je editor scriptovacího jazyka Pawn pro hru SA-MP. Tento editor je považován za oficiální editor. -jestliže vytvoříte nějaký filterscript nebo mode tak mají koncovku .pawn, .amx . Dále bych řekl, co jsou to filterscripty: -Filterscript je vlastě script, který si vytvoříte, a poté si ho přidáte do složky filterscripts, je to například: Carmenu, WeaponMenu, Warpy, Tuning, zaměstnání, banka, firmy, gangy, domy, atd... Gamemode: -Gamemod je vlastě herní mod serveru, například: Realná Země, Craftyho Pařba, SFDFD, Dream Gaming, atd ... Teď už teda k nějakým základům: Takže dneska bych vám ukázal první příkaz a vlastně to aby jste se mohli ocitnout na té vaší mapě, takže tedy: otevřeme složku pawno, poté soubor pawno s koncovkou .exe, doporučuji spouštět jako správce, jelikož po spuštění máte v pravo takovou tabulku funkcí, a pokud nespustíte jako správce, tak ji tam mít nebudete. Takže tedy spustíme jako správce, v levo nahoře dáme file, poté New, open jen pokud, jestliže máte třeba něco rozdělanýho a uložily jste si to, tak spustíte pawno a místo file - new, dáte file - open. Nuže tedy jsme si spustily pawno. Vidíme několik řádků s různýma věcma. Nějak je rozebírat nebudu, vrhneme se rovnou na pojmenování modu a na ten první příkaz - warp. 1. Zajedem na řádek 91. Máme tam asi toto: if (strcmp ("/mycommand", cmdtext, true, 10) == 0) 2.Místo /mycommand si dáme příkaz v mém případě to bude warp, a to warp do Los Santos, takže dáme /LS, jinak vše necháme, tento řádek, byl vlastně to, co musíme zadat pro provedení akce. 3. přejedeme tam, kde máme zelený text // DO SOMETHING HERE, text označíme a smažeme a ničím poté nehýbem, a začneme psát napíšeme: SetPlayerPos(playerid, x, y, z) X, Y, Z tam mám pro to, nebo ještě jsme nezjistily pozici na kterou se chceme portnout, ale zatím dopíšeme příkaz, a pak doladíme to, co chybí. Takže máme: SetPlayerPos(playerid, x, y, z) - Tento příkaz obsahuje souřadnice, na které to warpne, jak dopíšeme, tak dejte enter a píšem SendClientMessage(playerid, color, Cont Message) Takže tedy tohle je tedy druhý řádek, jak máme color, tak vložíme např toto: 0xFF0011FF, toto je červená barva, o zjištění barev si povíme až příště, ale zatím necháme tu červenou a místo "color" dáme tedy ten červený text, dále v tom dolním máme "Cont Message" což je zpráva, která se vám zobrazí po napsání /LS , dáme tedy třeba "Byl jsi teleportovan!" důležité mít tam ty uvozovky a souřadnice zjistite tak, že půjdete do hry, je jedno na jaký server, ale v singleplayeru to nejde, příjdete na místo, na které se chcete warpnout a dáte /save (pokud chcete napsat k tomu nějaký text třeba warpLS tak to uděláte takhle: /save warpLS). Půjdete poté do dokumenty/Gta Andreas User Files/ Samp a otevřeme program v textovém dokumentu savedposition najdeme tam souřadnice a zatím by měl být ten váš text, První jednociferné číslo necháme a následujících 6 čísel zkopírujeme a vložíme místo X, Y, Z. Celé ty 3 řádky teda vypadají takto: if (strcmp ("/LS", cmdtext, true, 10) == 0) SetPlayerPos(playerid, 1788.8439,-1696.0013,13.4861); SendClientMessage(playerid, 0xFF0011FF, "Byl jsi teleportovan!"); Ale nikdy nezapomeňte příkazy ukončovat ; Nuže tedy dáme file - Save as, zvolíme třeba plochu, pojmenujeme jak chceme a OK, dáme ještě F5, tím se zkontroluje jestli není někde chyba, jinak by se taky mohlo stát že kdyby jste si ten server načetli tak mi to hned crashlo. Soubor tedy i po kontrole by měl být dvakrát: jednou s koncovkou .pwn a druhou s .amx, oboje zkopírujeme do složky se serverem a do složky gamemodes, a otevřeme server.cfg a místo gamemode0 grandlarc ten grandlarc smažeme a napíšeme jméno toto souboru co jste si vložily do složky, vše stejně, MALÁ I VELKÁ PÍSMENA !!! Nyní když půjdete do hry, tak by vám server měl naběhnout, sice bez výběrech skinu, bez možností spawnování, absolutně bez ničeho, jen s tím warpem co jste si vytvořily stačí tedy otevřít Chat "T" a napsat ten příkaz (u mě /LS). Měli by jste se teleportovat a i text by to mělo napsat. Toť vše k druhému dílu, příště bych rozebral nejspíše Barvy. Brzo výjde další tutoriál. PS: Ještě jsem úplně zapomněl na pojmenování modu takže: Přejdeme na řádek 27 a pojmenujeme v závorce To samé i na řádku 36.
  12. Zdravím všechny začátečníky, co něvědí vůbec, jak začít s vytvořením serveru, pokud jste to vy, tak jste na správném místě, chtěl bych vás nějaké základy naučit, tento příspěvek nebude přímo na pawno, bude na stáhnutí serveru. Takže tedy: Stáhneme si server na sa-mp.com, a to tak, že klikneme na "Download Page" Oranžově zvýrazněno. Vždy stahujte jen tu nejnovější verzi, sa-mp verzí je totiž několik, ale aktuálně je nejnovější 0.3.7, takže tedy po kliknutí na "Download Page" se nám ukáže možnost stáhnou "SA-MP 0.3.7 Client Mirror by SA-MP team, ale předpokládám, že klienta máte, tak tedy níže máte možnosti stáhnout buď: "SA-MP 0.3.7-R2 Windows server", nebo "SA-MP 0.3.7-R2 Linux Server x86". Zvolíme tedy Windows server, pokud tedy máte Systém windows, co se týče instalace klienta tak ta je, jak klasická instalačka, nic těžkého, proto nemá cenu se rozepisovat o instalaci, a přejdeme radši k serveru, po stáhnutí složky se serverem, extrahujeme WinRar archiv, předpokládám, že to všichni máte v tomto programu, popřípadě i jiném, ale prostě tedy extrahujem, extrahovanou složku si můžeme pojmenovat, jak chceme v našem tedy mém případě se složka bude jmenovat "Server" , ale vaše složka se může jmenovat jakkoliv. Po otevření uvidíme ve složce pár dalších složek a souborů, otevřeme soubor server s koncovkou .cfg, pokud nemáte možnost spustit v poznámkovém dokumentu, nebo Wordpadu, tak si to udělejte.Já osobně doporučuji Poznámkový blok. Nuže tedy po otevření souboru server.cfg vydíme nějaké věty, takže bych je všechny nějak rozebral, takže: echo Executing Server Config... - necháme, tak jak je. lanmode 0 - taky necháme. rcon_password changeme - Rcon heslo, které si můžete změnit na jakékoliv, a to tak, že smažete slovo "changeme" a nahradíme svím heslem, v mém případě to bude třeba "1234". maxplayers 50 - Počet slotů serveru, můžeme změnit na téměř jakýkoliv počet, v mém případě to bude třeba "50" port 7777 - port serveru, který se zadává za IP je ip čili třeba 198.168.0.1:7777, port necháme těch "7777" hostname - jméno serveru, za to hostname napíšeme jméno jaké chceme, ale nezapomeňte oddělit mezerníkem, nesmí to být takhle "hostnamejménoserveru". Já zvolím třeba jméno "Test" gamemode0 grandlarc - Gamemode serveru, například "Realná Země", zatím žádný mod nemame, takže necháme tak jak je. Ostatní necháme tak, až na language a na weburl. weburl www.sa-mp.com - Zde si můžete místo toho "www.sa-mp.com" napsat svůj web serveru, pokud máme, ale dejme tomu, že nemáme, tak necháme. language - Jazyk serveru, zobrazuje se vedle Mode, když spustíte klient. Config máme nastavenej, uložíme dokument a zavřeme. Nyní spuštění serveru: Otevřeme soubor "samp-server s koncovkou .exe . Server se bude chvíli načítat a měl by se načíst. Poté stačí jen spustit klienta, kliknout na fajfku v oranžovém čtverečku a zadáme vaší IP s portem :7777. Ptáte se, jak mám zjistit svojí IP ? Já neznám svou IP. Odpověď jednoduchá: jděte do startu (říkám, jak je to na Windows 7). Jdeme tedy do startu a napíšeme cmd, naskočí program cmd s koncovkou .exe, spustíme jej, naskočí nějáké věci, a tam, kde můžete psát napíšete ipconfig. Poté naskočí nějaké IP, ale nás zajímá Adresa IPv 4, tu si přepíšeme do té možnosti přidání serveru, a za tu ip :7777, server se nám nyní přidal, a můžeme se volně připojit, zaregistrujeme se, vyberete si skin, spawn lokaci, no a jsme na základním primitivním serveru, ale na menší pojížděnou to jde, ovšem tam skoro nic není, takže je to vcelku na nic. Příště si už ukážeme základy s pawnem. Doufám že se vám můj první Tutoriál líbil, video bylo sice jen pro začátečníky, pro ty co vydí poprvé možnost vytvoření serveru atp ... Ale myslím že to bylo srozumitelně vysvětlené. Již brzy bude další tutoriál.
  13. YSI4 VELIKOST AMX PO KOMPILACI #6 ***** Zdravím vás u dalšího návodu práce s YSI. Dnešní díl bude spíše jen takové kecání o teorii, s kterou má snad každý troufalí začátečník problém. A jeden z takových je i tady(že ano Carloosi), a jelikož jde o dalšího uživatele, co nedá pokoj, dokud nedostane co chce, i když mu každý jasně naznačuje, že to prostě není ještě pro něj, tak jsem byl jaksi nucen udělat tento návod. Jak mnoho z vás ví, tak YSI(od verze 3.0) je obrovská skoro(ano skoro) zcela includově mezi sebou propojená knihovna. Protože po kompilaci si bere některé potřebné údaje i z jiných includů, které uživatel ani nechtěl nahrát, proto je výsledný kompilovaný soubor tak velký. Ale, co z pár řádků a jednoho nahraného includu způsobí, že kompilovaný soubor je až v několika MB? Všude je odpověď zcela prostá. Ve starších verzích(od 3.1 a méně) za to mohli samotní uživatelé, jelikož hned ze začátku nahrávali soubor, který obsahoval nahrání skoro všech uživatelných includů(y_ini, y_commands, y_colors, y_foreach...) a to sice pomocí: #include <YSI> Pak není divu, že ano, když nahráváte přes 40 includů a z něj využijete možnosti jen z jediné, že má až přes 4MB, že ano? Nojo, ale jak to je s novější verzi a to 4.0+? To zase záleží na několika faktorech: 1) Na verzi používané knihovny - to jsem zmiňoval právě před chvilkou, že verze 3.1 měla dokonce i soubor, kde se načítali zcela skoro všechny includy z knihovny najednou. Verze 4.0 už ale má tzv. "alternativní načítání" což načte jen daný potřebný include(y_commands, y_timers, y_hooks...), a nemusí někde se tamhle propojovat například s y_races. /* Staromódní načítání(+ještě z verze 3.1): lze takto načítát i s verzí 4+ ale doporučuji jen na rychlé ověřující práce */ #include <YSI\y_ini> #include <YSI\y_commands> #include <YSI\y_colors> /* Alternativní a doporučené načítání(od verze 4) */ #include <YSI_Storage\y_ini> #include <YSI_Visual\y_commands> #include <YSI_Server\y_colors> /* a tak dále */ 2) Použité includy z knihovny - některé includy mají více možností, které Y_Less nebo autoři neuveřejňují, jelikož jde spíše o systémové fce, callbacky, proměnné a tak dále, které slouží spíše pro knihovnu, než pro uživatele. A právě velká většina includů obsahuje tyhle věci "navíc", které se prostě do kompilace přidají. Samozřejmě, také záleží, jak uživatel pracuje s tou knihovnou(viz. bod 4). 3) Zpracování kódu - Optimalizace, optimalizace a zase jen optimalizace. Způsobem, jaký uživatel pracuje s knihovnou tak ovlivňuje obsah po kompilaci, jelikož YSI se v několika případech snaží "zachránit" obsah tím, že buď tam něco přidá, a nebo prostě spadne kompiler. K tomu může dojít hodně způsoby například nedostatečnou znalostí teorie samotného pawn, zbytečné bloky navíc, šílené pole, nadměrný počet použitých fcí, špatné hookování... Kód, který uživatel zpracovává musí být maximálně "čistý" jak jen to je možné(přehlednost, bez zbytečných proměnných, vkládat návratové hodnoty jen tam kde jsou nutné, hlídat si podmínky, operátory)... A hlavně v žádném případě nemíchejte knihovnu s nějakým jiným podřadným includem. UŽ VŮBEC NE DINI NEBO DCMD. Ne jen, že je to naprostí kktina, ale taky tím zcela zmarníte tu krásnou rychlost a optimalizaci knihovny(kromě sscanf2, který snad spolupracuje všude se vším). Ani i-zcmd a podobné rychlejší includy na příkazy apod. jelikož pak ztratíte další možnosti toho daného includu(y_commands) například přidávat alternativní příkazy, přidávat je jen pro danou skupinu a tak dále. Zde je menší ukázka dobře optimalizovaného a skoro(dokonalost samozřejmě nejde, najde se pokaždé lepší) "čistý" zpracovaný kód s využitím YSI4: #include <YSI_Core\y_utils> #include <YSI_Data\y_iterate> #include <YSI_Coding\y_timers> #include <YSI_Coding\y_hooks> #define MAX_TIPS (10) new Iterator: Tips<MAX_TIPS>, Tip_Text[MAX_TIPS][145], Tip_Color[MAX_TIPS]; void:Tip_Add(color, const text[]) { new Tip_ID = Iter_Free(Tips); strcpy(text, Tip_Text[Tip_ID]); Tip_Color[Tip_ID] = color; Iter_Add(Tips, Tip_ID); } hook OnScriptInit() { defer Tip_Timer();return (true);} hook OnScriptExit() { stop Tip_Timer(); Iter_Clear(Tips);return (true);} timer Tip_Timer[1000*60*3]() { new Tip_ID = Iter_Random(Tips); SendClientMessageToAll(Tip_Color[Tip_ID], Tip_Text[Tip_ID]); } 4) Práce s knihovnu - Tohle se spíše týká uživatelů. Jak jsem již zmínil uživatel má neskutečný vliv na výsledné AMX. Každá vychytávka YSI má nějaké pro i proti. Proto, když nejsou zcela nutné dané includy používat, tak je nepoužívejte, ani možnosti v nich. Například tagy v y_ini: new INI: Sbr = INI_Open("sbr.txt"); INI_SetTag(Sbr, "Hrac"); INI_WriteInt(Sbr, "AdminLevel", ...); INI_WriteInt(Sbr, "Level", ...); INI_WriteInt(Sbr, "Deaths", ...); INI_WriteBool(Sbr, "IsVip", ...); INI_Close(Sbr); K čemu přidávat tagy, když tam vkládáte jenom odstavec údajů a konec. Vůbec to nějak netřídíte. Sice je to jen poznámka, která nám zrovna nepřidá MB, ale to je jen pro příklad. Nebo v y_timers. Hodně lidí má nutnost používat defer, nebo ptask. Ale o žádné extra rozdíly nejde. Bez problémů lze používat i obyčejné timer. Na závěr bych rád dodal: jestliže pracujete s YSI a mezi problémy patří error cannot read from file: "internal\y_version" , neustále padá kompiler či kompilovaný soubor je stejně v MB, tak YSI není pro vás a přejděte raději na dof2, i-zcmd apod. Jinak velice doporučuji YSI4(/4.1). Jinak, děkuji za přečtení, a že už to daný uživatelé konečně pochopí. V případě, že jsem se někde sekl, něco mám špatně, nebo blbě vysvětlené... je to zcela možné, tak napište. Stejné v případě, že máte nějaké dotazy.
  14. Obtížnost: Osnova: 1. Úvod, co je operátor a operand 2. Dělení operátorů 3. Aritmetické operátory 4. Závěr 1. Úvod Vítám Vás u čtvrtého návodu pro začínající pawnery. Tématem tohoto návodu budou základní informace o operátorech, jejich dělení a aritmetické operátory. O dalších druzích operátorů napíši, vzhledem k množství informací, návod zvlášť. Ačkoliv to teď nevíte, operátory jsme využívali už v předchozích návodech, ale také v matematice (třeba +). Úkolem operátorů je vykonávat nějakou operaci (třeba sčítání). Aby tuto operaci mohli vykonávat, musí pracovat s tzv. operandy. Operand je nějaká hodnota, která stojí před, nebo za operátorem (čísla, která sčítáme). . 1 + 3 //plus je operátor, 1 a 3 jsou operandy . Operandy mohou být konstantní (neměnné), to jsou třeba čísla nebo jmenné konstanty jako MAX_PLAYERS, ale také variabilní (proměnné), to jsou proměnné, pole, návratové hodnoty funkcí apod. Kombinací operátorů a operandů vzniká výraz. 2. Dělení operátorů a) Počet operandů Dělit operátory můžeme podle různých kritérií. Prvním je počet operandů. Operátory s jedním operandem nazýváme unární, se dvěma operandy binární a se třemi operandy ternární. . !promenna //vykřičník je unární operátor 1 + 3 //plus je binární operátor výraz ? true : false //otazník s dvojtečkou jsou jediným ternárním operátorem v Pawn . b ) Účel Dále můžeme operátory dělit podle jejich účelu. Pak mluvíme o operátorech artimetických, relačních, logických, přiřazovacích a binárních. Tohoto dělení se budeme držet a ty hlavní skupiny si blíže rozepíšeme. 3. Aritmetické operátory Se základními aritmetickými operacemi jsme se setkali právě v matematice. Jsou to sčítání, odčítání, násobení a dělení. . new cislo = 5, cislo2 = 10; cislo + cislo2 //plus sečte dva výrazy (výsledek je 15) cislo - cislo2 //mínus odečte dva výrazy (výsledek je -5) cislo * cislo2 //hvězdička vynásobí dva výrazy (výsledek je 50) cislo / cislo2 //jedno lomítko vydělí dva výrazy (výsledek je 0.5) . Pak je tu ještě jeden speciální operátor pro dělení, který ovšem vrací zbytek po dělení. Nazývá se modulo. . cislo % cislo2 //procento vydělí dva výrazy a vrátí nám zbytek (zbytek je 5) . Všechny výše uvedené operátory jsou binární. Nezapomeňme, že pro ně platí stejná matematická pravidla jako v reálném životě (nulou nelze dělit, násobení má přednost před sčítáním, sčítání a násobení jsou komutativní operace atd.). Pokud chceme, aby nějaká operace měla přednost před jinou (sčítání před násobením), můžeme, stejně jako v matematice, použít kulaté závorky. . 4 * (1 + 1) //díky závorkám dojde nejprve k sečtení jedniček a až poté k vynásobení čtyřkou . Dalšími aritmetickými operacemi jsou inkrementace a dekrementace. S těmi se setkáme později u cyklů. Oba operátory pro tyto operace jsou unární a uvádí se buď před, nebo za proměnnou. Ano, v tomto případě musí být operandem proměnná / buňka pole. . new cislo = 5; cislo++ //inkrementace, hodnota proměnné cislo se zvětší o 1, tedy na 6 cislo-- //dekrementace, hodnota proměnné cislo se zmenší o 1, tedy na 4 . Jak už je uvedeno v poznámce, inkrementace zvýší hodnotu o 1, dekrementace sníží hodnotu o 1. Pro zajímavost (rozklikněte spoiler): . Poslední aritmetický operátor, který si zmíníme, je unární mínus. Uvádí se před operandem a jeho úkolem je převést kladné číslo v záporné a naopak. Na nulu nebude mít vliv. . -cislo . 4. Závěr První část návodu o operátorech je za námi. Vysvětlili jsme si pojmy jako operátor, operace, operand a výraz. Také jsme si uvedli, jak se operátory rozlišují a co to jsou aritmetické operátory. V příštím návodu si objasníme zbývající kategorie – relační, logické, přiřazovací a bitové operátory. Tento návod, stejně jako ten předchozí, je určen pro nováčky, pokročilejší věci byly buďto úplně vynechány, nebo jsou uvedeny ve spoilerech. Přesto, zdá-li se Vám, že jsem něco opomněl, někde jsem se spletl nebo se jen chcete vyjádřit, pište do tohoto tématu. Ověřený návod Tento návod prošel validací, a lze ho proto považovat za ověřený.
  15. Návod Vlastní zpráva při zadání příkazu který neexistuje. POTŘEBA je mít knihovnu zcmd. Ahoj, v pawnu dělám teprve 2 dny, chci se toho naučit co nejvíce, a v tom prvním dnu jsem se naučil například toto: Vlastní zpráva při zadání příkazu který neexistuje, tím myslím, že když zadáte ve hře nějaký příkaz, který neexistuje, zezačátku když nemáte vlastní zprávů tak píše: SERVER: Unkown Command. Ale my si to chceme změnit, tak tu je návod. stačí kamkoliv vložit toto: public OnPlayerCommandPerformed(playerid, cmdtext[], success)// public { //otevření příkazu if(!success) SendClientMessage(playerid,-1, "Vaše zpráva");//zpráva, ( jen při příkazu který na serveru není! ) return 1; }// zavření příkazu Mělo by to fungovat, testováno na windows serveru.
  16. Obtížnost: Osnova: 1. Úvod, co je řetězec 2. Nulový znak 3. Ukládání hodnot do řetězce 4. Závěr 1. Úvod Zdravím Vás, dostali jsme se už ke třetímu návodu pro začínající pawnery. Ještě než se do toho pustíme, doporučuji, abyste si přečetli předchozí dva návody (návod na pole – návod na proměnnou), zejména návod na pole, bez něj budete mít problémy pochopit problematiku řetězců. O řetězci (angl. string) byla řeč již dříve. Zopakujeme si to hlavní – je to pole znaků, do kterého ukládáme texty, zprávy, hesla atd. Každá buňka obsahuje jeden znak. Do poslední buňky nic neukládáme. Proč vlastně do poslední buňky nic neukládáme? Kvůli nulovému znaku. 2. Nulový znak Je načase, abychom si konečně vysvětlili, proč u řetězců potřebujeme buňku navíc, proč tuhle poslední buňku nikdy nezaplňujeme. Je to kvůli tzv. nulovému znaku (také EOS – End of String). Tenhle konkrétní znak (mimochodem vypadá takhle – '\0') v Pawn totiž určuje konec řetězce. Jazyk po nás požaduje, abychom mu sdělili, když řetězec skončí. Proto je nezbytné k délce řetězce vždy přičíst jeden znak navíc, ten je vyhrazen pro tento nulový znak. . new pozdrav[4+1]; //deklarace řetězce, která je nám důvěrně známa z předchozího návodu na pole pozdrav = "ahoj"; //uložení pozdravu do řetězce . Slovo "ahoj" má 4 znaky, celkem tedy potřebujeme řetězec o délce pěti znaků (4 + nulový znak). Abychom měli představu, jak to v tom řetězci vypadá, rozpitváme si ho: . pozdrav[0] = 'a' pozdrav[1] = 'h' pozdrav[2] = 'o' pozdrav[3] = 'j' pozdrav[4] = '\0' //onen nulový znak v páté buňce s indexem 4 . Ať už potřebujeme řetězec k čemukoli, vždy musíme myslet na tento nulový znak. Pro příklad, pokud funkce SendClientMessage může odeslat zprávu o maximální délce 144 znaků, řetězec s touto zprávou musí mít délku 145. 3. Ukládání hodnot do řetězce Existuje více způsobů, jak můžeme do řetězce něco uložit. Vlastně jich je spousta, my si ukážeme ty základní. a) Přímé ukládání pomocí operátoru přiřazení Tím mám na mysli rovnítko (=). Takhle jsme to dělali doposud, uvedeme identifikátor řetězce (bez hranatých závorek), rovnítko a poté text ohraničený uvozovkami ("). . pozdrav = "ahoj"; . Tento způsob ukládání lze použít, když přesně víme, co tam chceme uložit. Také je nutno podotknout, že ukládaný text nesmí být delší, než je délka řetězce. Upřímně si myslím, že s tímto se v praxi moc nepotkáte (akorát při inicializaci). Často je potřeba text upravit, dosadit do něj hodnoty proměnné apod. K těmto účelům nám slouží formátování. b ) Formátování Když formátujeme text, označujeme tím proces, při kterém do něj vkládáme hodnoty jiných proměnných a řetězců. Slouží nám k tomu funkce format. . format(output[], len, const format[], {Float,_}:...) . Za "output[]" dosadíme řetězec, kam chceme výsledný text uložit. Parametr "len" po nás chce délku výsledného textu. "const format[]" je onen text, který chceme formátovat. To poslední – "{Float,_}:..." – jsou proměnné/řetězce, které chceme dosadit. Ukažme si to na příkladu: . new hrac[4+1] = "Pepa"; //takto vypadá inicializace řetězce new penize = 500, score = 1000; //proměnné, které budeme dosazovat new vysledek[100]; //výsledný řetězec, kde bude nás formátovaný text format(vysledek, sizeof vysledek, "Hráč %s má %d dolarů a %d skóre.", hrac, penize, score); . V řetězci vysledek teď budeme mít: Hráč Pepa má 500 dolarů a 1000 skóre. . Ve fomátované zprávě jsme použili jisté znaky – %s a %d. Těmto znakům se říká specifikátory. Aby ta funkce format věděla, kam má to hrac, penize a score dosadit, musíme mu to dát nějak vědět. To je účel specifikátorů. Uvádíme je vždy v tom pořadí, v jakém po sobě jdou proměnné/řetězce, které dosazujeme. Máme následující specifikátory: %d nebo %i – celá čísla %s – řetězec %f – čísla s desetinnou čárkou %c – znak Nejsou všechny, ale jako základ nám tohle postačí. 4. Závěr A to by k řetězcům bylo všechno. Konečně již víme, co je nulový znak a k čemu slouží. Už víme, jak do řetězců ukládat běžný, ale také formátovaný text. Jediné, na co jsem ještě zapomněl – pomocí sizeof jsme zjistili velikost řetězce vysledek (počet buněk toho řetězce). Tento návod, stejně jako ten předchozí, je určen pro nováčky, pokročilejší věci byly buďto úplně vynechány, nebo jsou uvedeny ve spoilerech. Přesto, zdá-li se Vám, že jsem něco opomněl, někde jsem se spletl nebo se jen chcete vyjádřit, pište do tohoto tématu. Ověřený návod Tento návod prošel validací, a lze ho proto považovat za ověřený.
  17. Zdravím, asi jste si všimli, že přibyla nová sekce "Základy pawn". Po domluvě s Ewwem jsem se rozhodl, že většinu svých návodů z ewa (jiného fóra) přesunu i sem. Vyžádal jsem si na to svou sekci, za chvíli vysvětlím proč. Vlastně vysvětlím všechno. Proč to vzniklo? Jednoduše řečeno, je zde horda lidí, co žádají o pomoc se svým kódem nebo problémem, ale když jim někdo poskytne návod, jak toho dosáhnout, skončí to na tom, že dotyčný nezná základy. Odkázat jej na google či na samp wiki bez toho, aniž by to helper nějak přiblížil, má asi stejnou vypovídací hodnotu jako ten příspěvek od toho, co žádá pomoc. Řešením je odkázat jej na místní sekci "Návody", ale... ...ale to by v té sekci nesměl být takový bordel. Za ty roky se tam nahromadily stovky návodů, sice byl pokus o to je roztřídit (nice try, Petře, Hipe), ale že by to zrovna dvakrát pomohlo, to ne. Proto vznikla tato sekce, která bude sdružovat návody pro úplné začátečníky. Jakých návodů se to týká a co musí splňovat? Jsou to návody, které se věnují jednotlivým strukturám jazyka Pawn, jeho syntaxi apod. Já prozatím plánuji návody na proměnnou, pole, funkce, podmínky, cykly a řetězce. Co bude dál, to se uvidí. Přispět svým návodem může každý, ale návod v této sekci by měl splňovat tato pravidla, jinak by sekce postrádala smysl: 1. Návod musí být sepsán "jako pro blbce"; to znamená, že musí být vše pododrobna a srozumitelně vysvětleno, žádné odborné výrazy a úseky, popř. tyto úseky musí být od návodu nějak odděleny s upozorněním, že jde o něco navíc (já využívám spoilerů); 2. Tématem by neměla být žádná konkrétní funkce SA:MP (timery, 3dlabely apod.) ani žádný větší celek (jak udělat TDM, jak na anketu apod.), sekce je pouze pro věci týkající se Pawn; 3. Návod musí být v souladu s šablonou pro psaní návodů. Každý návod v této sekci musí projít schválením, když nebude splňovat bod 1 nebo 2, bude přesunut do sekce "Ostatní návody". V případě, že by nesplňoval bod 3, by jej uživatel musel nejprve upravit tak, aby byl v souladu s šablonou (není nutné to moderátorům znesnadňovat tím, že se to nebude dodržovat). Jak přesně to má pomoct? Zkušení pawneři mohou žadatelům o pomoc poslat odkaz na tuto sekci, pokud daný člověk nebude mít elementární znalosti Pawn. Závěrem Doufám, že se to osvědčí, udělat pořádek v celé sekci "Návody" si myslím je utopická myšlenka, takže tohle je (by mohla být?) ta zlatá střední cesta.
  18. Jak jistě víte existuje několik systému nebo spíše způsobů jak pracovat s příkazy. Klasický strcmp Dcmd Zcmd Ycmd Pawn.CMD Jaký je mezi nimi rozdíl ? Tak především v rychlosti zpracování. Vývojář Pawn.CMD uvádí několik udajů k rychlosti především jde o prodlevu mezi tím než server příkaz obdrží a vykoná. strcmp a DCMD t 183 mikrosekund YCMD : 177 mikrosekund zcmd : 104 mikrosekund Pawn.cmd 27 mikrosekund Samozřejmě že Pawn.cmd bych měl nejspíše vyškrtnou protože to není pure pawn řešení ale pro zajímavost ho tu ponechám. Ale rozdíly nejsou jen v rychlosti. V současné době bych řekl že jsou nejoblíbenější dva systémy a to YCMD a ZCMD. YCMD z důvodu propojitelnosti s YSI knihovnou. A ZCMD když nic propojovat nechcete. Pros x Cons strcmp - no upřímně nevím co říct pozitivního x pomalé ... dcmd - to je v podstatě jinak zabalený strcmp. zcmd - jsou rychlé obsahují mnoho funkcí navíc Ycmd - jak jsem již zmínil tak propojení s ostatními knihovanmi YSI , aliasy a podobně.. ZCMD | YCMDv3 | YCMDv4 | Pawn.CMD
  19. MULTISAVE V JEDNOM SOUBORU ***** Na tenhle návod mě přivedl Ewwe s jeho problémem ohledně ukládání domů a vozidel... Kdo neví o co jde, tak Ewwe se snažil ukládat ve 2 souborech domy a vozidla. Akorát problém nastal v tom, že se načítaly domy ale nikoliv vozidla. Existuje takový trik jak se vyhnout tomuhle celému složitému ukládání... stačí pak načítat jediný soubor bez nutnosti formátovat cestu, a to za pomocí iterate a tagů v y_ini. Jelikož tag je v souborech nic více než jen poznámka, jde toho šikovně využití a nemusíme se bát, že se nám budou blbě načítat údaje, když jich tam budeme mít moc(jak mi někdo tvrdil, že se mu to děje). A naštěstí i poznámka lze zjistit, takže jak jsem říkal, jde to velice široce využít. Ukážeme si, jak vytvořit ukládání do takové formy: A furt je to v jednom souboru. Nemusíme načítat extra hodnoty, nemusíme nějak složitě zjišťovat cestu, stačí jenom povolit načítání tagů a to je vše. Začneme deklarováním proměnných. Budeme je potřebovat, abychom věděli, do čeho načtené údaje dát: #include <YSI_Data\y_iterate> #include <YSI_Storage\y_ini> enum eHouseInfo { HouseName[MAX_HOUSE_NAME + 1], HouseName[MAX_PLAYER_NAME + 1], bool: HouseLock, HouseVeh0, HouseVeh1, HouseVeh2, Float: HouseXPos, Float: HouseYPos, Float: HouseZPos } new HouseInfo[MAX_HOUSES][eHouseInfo]; A následně i iterátor, do kterého budeme přidávat id domů, které se budou načítat: new Iterator: House<MAX_HOUSES>; Teď, nejlepší na přidávání domů je si udělat fci. Vyhnu se detailům jako textlabel, některé podmínky... To si tam může pak přidat každý individuálně: stock AddHouse(const sHouseName[MAX_HOUSE_NAME+1], const sHouseOwner[], Float:fhX, Float:fhY, Float:fhZ, bool:bLock, ...) { Jelikož používáme iterate, nemusíme zjišťovat počet vytvořených domů... můžeme to jednoduše rovnou přes to zjistit, a to počtem přiřazených hodnot: if (Iter_Count(House) == MAX_HOUSES) A tady přichází ta novinka. Nemusíme přidávat nějaké housecount, nemusíme zjišťovat jestli je volno... můžeme na to využít fci, která nám zjistí nejbližší volné "id domu". new House_ID = Iter_Free(House); A nyni stačí jen přiřadit hodnoty(nesmíme samozřejmě zapomenout přiřadit do iterátoru i samotné id) HouseInfo[House_ID][HouseName] = sHouseName; HouseInfo[House_ID][HouseName] = sHouseOwner; HouseInfo[House_ID][HouseLock] = bLock; HouseInfo[House_ID][HouseXPos] = fhX; HouseInfo[House_ID][HouseYPos] = fhY; HouseInfo[House_ID][HouseZPos] = fhZ; new INI: Soubor = INI_Open("Houses.txt"); INI_SetTag(Soubor, sprintf("House%i", House_ID)); INI_WriteString(Soubor, "HouseName", HouseInfo[House_ID][HouseName]); INI_WriteString(Soubor, "HouseOwner", HouseInfo[House_ID][HouseName]); INI_WriteBool(Soubor, "HouseX", HouseInfo[House_ID][HouseLock]); INI_WriteFloat(Soubor, "HouseX", HouseInfo[House_ID][HouseXPos]); INI_WriteFloat(Soubor, "HouseY", HouseInfo[House_ID][HouseYPos]); INI_WriteFloat(Soubor, "HouseZ", HouseInfo[House_ID][HouseZPos]); INI_Close(Soubor); Iter_Add(House, House_ID); return (true); } Takže ano, prakticky normální ukládání. A teď k načítání... to bude to zajímavější. Protože pracujeme s tagem a v tagu je jen slovo House a číslo, tak právě z toho musíme vytáhnout čistě jenom to číslo. Což pro zběhlejší to není takový problém, ale i pro ty další vám ukážu jak na to. Nejdříve si extrahujeme do stringu sString jen to dané číslo: forward NahratData(tag[], name[], value[]); /* Všimněte si argumentu tag[] */ public NahratData(tag[], name[], value[]) { new sString[14]; strmid(sString, tag, 5, strlen(tag)); Nadále to číslo konvertujeme jako číslo: new House_ID = strval(sString); To je všechno... a už jenom načteme: INI_String("HouseName", HouseInfo[House_ID][HouseName]); INI_String("HouseOwner", HouseInfo[House_ID][HouseName]); INI_Bool("HouseX", HouseInfo[House_ID][HouseLock]); INI_Float("HouseX", HouseInfo[House_ID][HouseXPos]); INI_Float("HouseY", HouseInfo[House_ID][HouseYPos]); Iter_Add(House, House_ID); /* UPOZORNĚNÍ! Fce nesmí být na konci. jelikož jeho spec. návratová hodnota může ukončit celé načítání! */ INI_Float("HouseZ", HouseInfo[House_ID][HouseZPos]); return (false); } A nakonec ten samotný soubor načteme. Jak jsem již říkal: cestu nějak nemusíme formátovat, a nepotřebujeme extra hodnoty, stačí jenom načíst, a povolit načítání tagů: public OnGameModeInit() { INI_ParseFile("Houses.txt", "NahratData", .bPassTag = true); return (true); } Doporučuji pak vyčistit po ukončení scriptu(gamemodu) iterátor: Iter_Clear(House); A aby to nebylo málo, tak za pomocí iterátorů můžeme i zjistit, zda to dané id u kterého stojí hráč patří k domům: if (Iter_Contain(House, House_ID)) return (true); ODKAZY Doporučuji používat sprintf. Velice užitečná věcička: http://forum.sa-mp.com/showpost 612 Kdyby někdo nepochopil, jak se s tím pracuje... tak jsem tuhle vychytávku používal hodně často, například u přidávání adminů do /admins pastebin.com/qZV5evSz PODĚKOVÁNÍ xhunterx za radu s tímto trikem.
  20. Koukal jsem se na fórum, a nikde jsem tu nenašel Race Checkpoint. Pokusím se vám ho popsat, kdyby jste něčemu nerozuměli řekněte. Snad to bude dobře Hlavní: Typy Závodního Checkpointu 0 - Klasický (Takové to jak je v něm šipka), 1 - Klasický Finální (Také znáte je v něm finále takovej ten praporek když je konec), 2 - Žádkný (Jen prázdno), 3 - Letecký (Takoví ten kruh jak je pří závodech v letadlech), 4 - Letecký finální (Ani nwm jak vipadá). Nastavení: SetPlayerRaceCheckpoint(playerid, type, Float:x, Float:y, Float:z, Float:nextx, Float:nexty, Float:nextz, Float:size) playerid = ID Pro které se zobrazí. type = Typ CP, nahoru jsem to dával. Float:x, Float:y, Float:z = Kde bude. Float:nextx, Float:nexty, Float:nextz = Kam bude ukazovat. Float:size = Velikost. Použití: Nahoru pro přepínání: new Zkouska[MAX_PLAYERS]; Někam do příkazu nebo kde chcete aby se nějáký zobrazil: Zkouska[playerid] = 1; //Nastaví CP na 1. DisablePlayerRaceCheckpoint(playerid); //Zničí všechny závodní CP. SetPlayerRaceCheckpoint(playerid, 0, 2641.9673,921.9190,6.4502, 2355.1331,833.7064,6.4543, 20); //Dá hráči závodní CP (Změnte si). Do OnPlayerEnterRaceCheckpoint(playerid): switch(Zkouska[playerid]) //Dáme switch na přepínání CP. { case 1: //První CP. { Zkouska[playerid] = 2; //Nastaví na 2. DisablePlayerRaceCheckpoint(playerid); //Odstraní ostatní. SetPlayerRaceCheckpoint(playerid, 0, 2641.9673,921.9190,6.4502, 2355.1331,833.7064,6.4543, 20); // Dá hráčovi závodní CP. } case 2: { Zkouska[playerid] = 3; //Nastaví na 3. DisablePlayerRaceCheckpoint(playerid); //Odstraní ostatní. SetPlayerRaceCheckpoint(playerid, 0, 2355.1331,833.7064,6.4543, 1984.5858,833.6744,6.4541, 20); // Dá hráčovi závodní CP. } } P.S.: V OnPlayerEnterRaceCheckpoint není return ! (alespon já ho tam nedávam). A doufam že to tu neni
  21. Obtížnost: Obsah: - Věci ke stažení - Vysvětlení - Příklady - Návod - Závěr Věci ke stažení: ZCMD plugin: http://samp-scripts.com/post/INC_zcmd_031__Fast_amp_Simple_Command_Processor_updated_30102009-MatrixBoY-other_include-15/ Vysvětlení: Pocity jsou jednoduché měl by to zvládnout i pouhý začátečník. Jde o to že hráč napíše nějaký pocit např. /lol a napíše to do chatu všem "Hráč Ponozka se směje!". Ponozka to je jen nick, který jsem si vymyslel. Příklady: Zde je příklad kdybych chtěl příkaz /lol : NÁVOD: Takže jako neprve si vytvoříme tento stock: (Dejte ho třeba úplně dolů) Potom pod include <a_samp> si zapíšeme: A nyní k samotnému příkazu Takže vytvoříme si příkaz lol: Pod to dáme { na další řádek dáme TAB a return 1; potom zas další řádek a }. Nyní jsme si vytvořili samotný příkaz, ale bez žádné funkce tudíž to nic neudělá. ZATÍM! Tákže nad return 1; si uděláme takovou funkci na maximální počet písmen Dále si uděláme formát, aby to vypisovalo hráčův nick: A nakonec samoszřejmě funkce SendClientMessageToAll, aby to napsalo všem hráčům na serveru: To je vše k příkazu lol a nyní si uděláme ještě dialog ve kterém budou všechny pocity. Takže začneme zase tím, že si uděláme příkaz třeba /pocity: Vložíme funkci aby to zobrazilo dialog: 1457 - ID dialogu DIALOG_STYLE_MSGBOX - Styl dialogu "SEZNAM POCITŮ" - Nadpis, který je nahoře v dialogu ZÁVĚR: Ták a tohle je už úplně vše k těm pocitům můžete si samozřejmě těch pocitů udělat víc princip je stejný akorát upravíte text Já se loučím ČAU!
  22. Navod 3DTextLabel zdravim, vitejte u meho 2 navodu, ( 3DTextLabel ) 3DText je, ze treba u wang cars bude lezet text na zemi... takze budeme pouzivat public ongamemodeinit... kod by mel vypadat takto: public OnGameModeInit() { Create3DTextLabel("Radek1\nRadek 2", BARVA, POZICE ( KDE BUDE TEXT LEZET); return 1; } muzete pridat dalsi radek pomoci \n parametry vypadaji takto: (text[], color, Float:X, Float:Y, Float:Z, Float:DrawDistance, virtualworld, testLOS) textové [] Počáteční textový řetězec. obarvit barvu textu x X souřadnicový y Y souřadnicový z Z souřadnicový DrawDistance Vzdálenost od místa, kde jste schopni vidět textu popisku 3D Virtuální svět virtuální svět, ve kterém jste schopni vidět 3D Text testLOS 0/1 Test line-of-sight takže tento text nelze vidět skrze předměty Doufam, ze to nekterym pomuze, toto hlavne je pro novacky, nebo pro ty, co o teto funkcni nevedeli, a co dela... Toto by bylo vse, zatim cau.
  23. Navod JAK NA CMD A proc nepouzivat dcmd... DCMD: Co je otravne, kdyz pouzivate dcmd? dcmd(prikaz,5,cmdtext); Toto je nejvic otravne, kdyz pouzivate dcmd.. DCMD zabira radky... dcmd hleda text a hledat text je delsi nez cislo... + DCMD je 8 let stare.. ZCMD: ZCMD je o hodne lepsi nez dcmd!! k ZCMD potrebujete pouze include zcmd DOWNLAND zcmd include: http://uloz.to/xPfVRwNf/zcmd-inc Takze nahoru staci napsat: #include <zcmd> Pouzivani zcmd: CMD:prikaz(playerid, params[]) { SendClientMessage(playerid, 0xC138FB88, "Napsal jsi /prikaz"); return 1; } Tak toto by bylo pro zatim vse, doufam ze to nejakym novackum pomohlo, a nebo ti kteri pouzivaji dcmd, a precetli si tento navod, tak si doufam uvedomi, ze dcmd je na nic! A lepsi je ZCMD, samozrejme je super i YSI a spoustu dalsich typu, ale tento je rozhodne lepsi nez DCMD!
  24. [**] Rychlost vozidla Zdravím, v tomto návodu se zaměříme na vytváření jednoduchého tachometru a věcí kolem. Vše bude spíše z teoretické stránky věci. Odkaz na původní topic (zdroj): http://ewolutions.cz/index.php?/topic/1843-rychlost-vozidla/ Obtížnost: Úvod Na fóru se nachází jistě dost návodů a scriptů, které obsahují téma „Tachometr“. Vše ale vzniklo před, troufám si říct, několika lety, a tak nevyužívají nových možností, které SA:MP (0.3z+) nabízí. Nebudeme se zde zabývat vzhledem samotného tachometru (to už je individuální). Vektory Pro výpočet rychlosti budeme používat funkci VectorSize. Ke zjištění rychlosti použijeme funkci GetVehicleVelocity, která vrátí rychlost vozidla na jednotlivých osách. Z těchto hodnot poté musíme zjistit jednu hodnotu. Budeme tedy vypočítávat velikost vektoru se souřadnicemi X, Y, Z. Výpočet velikosti: Nyní se budeme pohybovat kvůli vizualici v rovině. Tento vektor, se souřadnicemi X, Y má nějakou velikost označenou červenou čárou. Z obrázku asi každý pochopí, že na výpočet můžeme použít Pythagorovu větu. Výpočet tedy bude: √(x^2 + y^2) Výpočet velikosti v prostoru je potom obdobný, pouze přidáme další souřadnici. Dostáváme následující: √(x^2 + y^2 + z^2) Starý výpočet: Jak jsem již předesílal, dnešní SA:MP umožňuje lepší způsoby, ale ještě si ukážeme, jak se pořád vypočítává velikost vektoru. new Float:vx, Float:vy, Float:vz; GetVehicleVelocity(vehicleid, vx, vy, vz); vz = floatsqroot(vx * vx + vy * vy + vz * vz); // ve vz nyní máme velikost /* viděl jsem také floatsqroot(floatpower(vx, 2) + floatpower(vy, 2) + floatpower(vz, 2)); a další verze s floatabs a dalšími zbytečnostmi. */ Způsob je to správný, jen je zastaralý a lze využít rychlejší řešení. Výpočet, který není za opicema Na funkci VectorSize asi není nic moc co vysvětlovat, protože název hovoří za vše. Výpočet velikosti vektoru tedy bude následující. new Float:vx, Float:vy, Float:vz GetVehicleVelocity(vehicleid, vx, vy, vz); vz = VectorSize(vx, vy, vz); // ve vz nyní máme velikost Jdeme scriptovat? Nyní se můžeme zaměrit na samotný script. Budeme vycházet z toho, že máme deklarované pole PlayerTextů o velikosti MAX_PLAYERS. Nějak takto: new PlayerText:pSpeed[MAX_PLAYERS]; Samotná pozice, vzhled a barva již bude na vás. Dále budeme potřebovat veřejnou funkci, která bude mít jako parametr playerid (budeme updatovat rychlost každého hráče zvlášť). forward updateSpeed(playerid); public updateSpeed(playerid) { if(IsPlayerInAnyVehicle(playerid)) // pokud je hráč v nějakém vozidle... { // zde proběhne update new str[9]; // 9 znaků stačí (km/h → 4, 123 → 3, mezera → 1) format(str, sizeof(str), "%d km/h", getSpeed(GetPlayerVehicleID(playerid))); PlayerTextDrawSetString(playerid, pSpeed[playerid], str); } } Také nastavíme timer (například v OnPlayerConnect heh) SetTimerEx("updateSpeed", interval, true, "d", playerid); Nezapomeneme podle potřeby ukončovat timer, abychom nepřehltili server. Jako poslední krok tu máme samotnou funkci getSpeed. Jako parametry nám poslouží id vozidla, ale můžete si to zas dle potřeby předělat (zde pracujeme jen s vozidly). stock getSpeed(vehicleid) { new Float:vx, Float:vy, Float:vz; GetVehicleVelocity(vehicleid, vx, vy, vz); return floatround(VectorSize(vx, vy, vz) * 180); } Funkcí floatround zaokrouhlíme velikost vektoru na celá čísla. Celé to násobíme 180 abychom dostali „reálné“ rychlosti. Vozidla se v GTA pohybují nereálnou rychlostí a vynásobením tímto číslem se můžeme alespoň přiblížit k reálným. Pro každé vozidlo je toto číslo jiné, tudíž se používá hodnota okolo 180 jako takové univerzální. Návod označen jako platný Ten to návod byl označen jako platný.Návod může být kdykoli označen jako nevhodný či neplatný
  25. INFO: Zdravím lidi toto je můj první návod tak vás prosím o schovívavost a nejsem nějaký profík v pawnu ale přesto se s vámi chci podělit o svoje znalosti. NÁVOD: Nejdřív si někam nahoru do módu napíšeme: #define dcmd(%1,%2,%3) if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(playerid, ""))) || (((%3)[(%2) + 1] == ' ') && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) return 1 Potom si najdeme public OnPlayerCommandText a napíšeme tam: dcmd(sf,2,cmdtext); "sf" to bude protože v našem případě to bude warp /sf Takže zatím to bude vypadat takhle: public OnPlayerCommandText(playerid, cmdtext[]) { dcmd(sf,2,cmdtext); return 1; } To číslo 2 = počet písmen toho příkazu Pod to si napíšeme: dcmd_sf(playerid,params[]) { #pragma unused params new string[128]; if(IsPlayerInAnyVehicle(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER) //Zjistí jestli hráč nesedí v nějakym autě { SetVehiclePos(GetPlayerVehicleID(playerid), -1947.1663,576.3934,35.1719); //Pokud ano přemístí auto na danou pozici }else{ SetPlayerPos(playerid, -1947.1663,576.3934,35.1719); //Pokud ne tak přemístí na danou pozici pouze hráče } format(string, sizeof(string), "{00CC00}Hráč {FF0000}%s {00CC00}se teleportoval do {FF0000}San Fierra", PlayerName(playerid)); //Zpráva která se zobrazí všem hráčům když hráč napíše /sf SendClientMessageToAll(0x00FF51, string); //Barva té zprávy return 1; } A máme hotovo! Nyní vše je funkční a když hráč na server napíše /sf tak ho to teleportuje do SF a navíc napíše informační zprávu všem. Doufám že se vám můj menší návod líbil pokud ano dejte +rep a ohodnoťte do 10 bodů
×
×
  • Create New...