Jump to content

Search the Community

Showing results for tags 'návod'.



More search options

  • Search By Tags

    Oddělujte čárkami
  • Search By Author

Content Type


Fórum

  • Fórum
    • Pravidla fóra
    • Co by se tu mělo změnit
    • Nahlášení chyb/Návrhy změn
    • Všechno možné
  • Pawn
    • Pomoc
    • Návody
    • Mapy a editor map
    • Scripty
    • Prezentace módů
    • Hledám pawnera/mappera
  • Programování a grafika
    • Vývoj webových stránek a aplikací
    • Vývoj desktopových a jiných aplikací
    • Grafika a webdesign
    • Dlouhodobé projekty
    • Hledám programátora/skriptera
  • Hry a herní tématika
    • MTA
    • Counter Strike 1.6 , Source, Global Offensive
    • Ostatní hry
    • Obrázky a videa z her
    • Herní hostingy
    • Prezentace herních klanů
    • Prezentace herních serverů
  • Ostatní
    • Hardware a software
    • Hledám/nabízím
    • Koš

Categories

  • Pawn – filterscripty a gamemody
  • Pawn – skripty od nováčků povinně sem
  • Aplikace a hry

Blogs

  • rEwolutionary
  • Polisův Blogík
  • DoubleX's Blog
  • [Info] Dark Island
  • Albus Brambůrek's Blog
  • Trampoty pána buggeda
  • vEndovo všechno možné
  • Cybrionkov Game Development v Unity
  • [Printova hlava]

Calendars

  • Kalendář Pawno.cz

Categories

  • Verze

Found 401 results

  1. Multi jazyk pre GM Obtížnost: 2/5 Osnova/obsah: 1. Úvod 2. Čo je multi jazyk (multilanguage) a načo sa dá použiť? 3. Vytváranie vlastných funkcií a ich použitie 4. Záver 1. Úvod Tento návod som sa rozhodol vytvoriť, pretože v dnešnej dobe už GM s jedným jazykom nemá veľkú popularitu, a mladší hráči ktorý neovládajú veľmi angličtinu nehrávajú na serveroch písaných po anglicky. Upozorňujem, že tento návod nie je copy + paste. Pre tvorbu svojích funkcií je nutné kódu rozumieť. 2. Čo je multi jazyk a načo sa dá použiť? Multi jazyk je implementácia dvoch a viacerých jazykov do GM. V tomto návode sa Vám posnažím čo najjednoduchšie vysvetliť, ako si vytvoriť svoje funkcie na multijazyčnosť a ako ich použiť. Multijazyčnosť je vhodná pre servery, ktoré plánujú expandovať na zahraničný "trh" a tým rozšíriť svoju klientelu (hráčov). 3. Vytvárania vlastných funkcií a ich použitie Celý systém funguje na princípe #define. Pre pochopenie kódu je nutné poznať: #include, #define, cyklus for, SendClientMessage/ToAll, format(...) V prvom rade, budeme potrebovať definície naších textov (textových reťazcov/stringov). Pre lepší prehľad som ich vložil do zložky INCLUDE s názvom lang_SK.inc a lang_CZ.inc. !!! POZOR !!! Je nutné nastaviť formátovanie textu na ANSI. lang_CZ.inc lang_SK.inc new.pwn
  2. Obtížnost: 1/5 Zdarec, akorát jsem řešil problém s chybou symbol "@yH_OnUnoccupiedVehicleUpdate@0" is truncated to 31 characters kterou hází y_hook v případě že délka jména callbacku přesáhne určitý počet znaků. V praxi se s tím setkáte jen u hookování callbacků jako je například OnUnoccupiedVehicleUpdate a OnPlayerEnterRaceCheckpoint. Existuje jednoduché řešení které YLess implementoval do YSI. Jmenují se HOOK_REPLACEMENTS. V podstatě jde o to že nějakou část jména callbacku zaměníte za náhradu která je kratší. V YSI jsou připravené replacementy například pro Checkpointy kde místo hook OnPlayerEnterRaceCheckpoint hooknete hook OnPlayerEnterRaceCP V případě mé chyby jsem si nad callback OnUnoccupiedVehicleUpdate přidal řádek DEFINE_HOOK_REPLACEMENT( Unoccupied , Uncp ); a pak změnil hook na hook OnUncpVehicleUpdate a tím je problém vyřešen. Doufám , že to někomu pomůže, samozřejmě určitě to nekdo znal ale já se k tomu dostal dnes.
  3. V tomto návode resp. v tejto sérií sa naučíme pawno :). Nebudeme sa učiť hneď tie najťažšie príkazy, funkcie atď... začneme pekne od najľahšieho. Pustime sa do toho :). Predpokladám že publicy už poznáte, ak viete po EN aspoň trochu, určite budete vedieť čo ktorý public znamená. ==[Ľahký príkaz]== Na začiatok si ukážeme fakt tú najprimitívnejšiu vec. A to je "SetPlayerHealth". Keby sme to mali preložiť, tak => "NastavHráčoviZdravie". Ukážme si to: ==[Legenda]== SetPlayerHealth => Nastaví hráčovy život. playerid => Zistí VAŠE ID. 100 => Počet životov, ktoré sa majú doplniť. Životy tak isto môžete odoberať nastavením nižšej hodnoty. 0 = Smrť. [Formát]: SetPlayerHealth(playerid,zivot); ----------------------------------- ==[Ďalší príkaz]== Zatiaľ to je ľahké že? :-) Teraz si predstavíme príkaz "SendClientMessage". V preklade => "PošliKlientovySprávu". Ukážka: ==[Legenda]== SendClientMessage => Pošle hráčovi správu playerid => Už vieme -1 => Farba správy (uvádzajte v "0xXXX" príklad si ukážeme a konci návodu) "text" => Správa, ktorá sa zobrazí hráčovi. [Formát]: SendClientMessage(playerid,COLOR,"TEXT"); ----------------------------------- ==[Definície]== Nechce sa vám stále písať "SetPlayerHealth", "SendClientMessage" atď?? Uľahčime si to definíciou! Definíciu píšeme vždy pod #include (vysvetlíme si v budúcom návode). Ukážka: ==[Legenda]== [Formát]: #define NÁZOV FUNKCIA ----------------------------------- ==[Zistenie farieb]== Otvoríme si napr. skicár a kalkulačku. V skicári si zvolíme Úprava farieb Zvoľme si nejakú farbu, ktorá sa nám bude páčiť. Teraz je dôležité si všimnúť 3 veci, a tie sú: "červená", "zelená", "modrá"} ktoré sa nachádzaju vpravo dole. Kalkulačku si prepnime na programátorskú, a po jednom tam po porade píšte tie farby. Po napísaní farby si všimnime okienko "HEX", zobrazí sa tam kód, ktorý si napíšeme do Pawna za 0x. Takže napr: 0x1234 atď.. Toto urobme na ostatných farbách. Nakoniec nám z toho vznikne v pawne kód na tú farbu. A to by bolo na dnes všetko :). Aby ste si to precvičili, dám vám domácu úlohu. Úlohu urobte, a script ktorý ste urobili napíšte sem dole do odpovedi :). Som zvedaví ako sa vám darí :). ==[D.Ú]== Vytvor script, ktorý doplný hráčovy HP na 50, a napíše správu o doplnení. Farbu správy daj oranžovú.
  4. Custom Skins [***] Obtiažnosť: 3/5 Osnova: 1.)Úvod 2.)Vysvetlenie funkcie AddCharModel 3.)Pridanie custom skinu 4.)Vysvetlenie pre nefungujúce AddPlayerClass 5.)Screenshoty 6.)Záver 1.)Úvod Zdravím Vás,v novej verzii sa-mp 0.3.8 vznikla možnosť pridať si vlastný custom skin. Nie je to nič obtiažné ale zo začiatku som s tým dosť bojoval kým som prišiel na to,čo ktorá funkcia spraví a ako to že to nefunguje pri AddPlayerClass. Limit pre custom skiny je od 20000 do 30000 čiže 10000 id. Chcem ešte upozorniť že napr. na skin ID 0 (CJ) môžte mať viac custom skinov...(Napr. Homera,DeadPoola apod), Preto je to tak lebo aj Homer aj DeadPool bude mať vlastné unikátne ID (napr. 25555 a 25559) a k tomu ak si dáte že SetPlayerSkin s id 0 bude Vám fungovať aj CJ Podobný návod som tu ešte nenašiel tak ho pridám...Ak sa niečo nepáči,kľudne ma opravte. 2.)Vysvetlenie funkcie AddCharModel Funkcia AddCharModel slúži na pridanie Custom Skinu do hry. Prvý parameter v tejto funkcii je ID základného skinu v hre napr. ID 0 (CJ) Druý parameter slúži na poskytnutie ID vášmu skinu napr. (25666) Tretí parameter je názov súboru vášho skinu s koncovkou dff Štvrtý parameter je názov súboru vášho skinu s koncovkou txd Takže ak chcete zapísať Váš skin s názvom NEWCJ na ID nového skinu 25000 na normálneho CJ ktorý má ID 0 tak zapíšete ho takto: AddCharModel(0, 25000, "NEWCJ.dff", "NEWCJ.txd"); 3.)Pridanie custom skinu V prvom rade si musíte nejaký custom skin stiahnuť.Napríklad tu http://www.gtainside.com/en/sanandreas/skins-123/. Po stiahnutí súbor .dff a súbor .txd si uložíte do: Otvoríte si priečinok s sa-mp serverom,otvoríte si priečinok s názvom models a uložíte ich sám. Ďalej tie nové skiny musíte zapísať. Otvoríte si v priečinku models txt súbor s názvom artconfig. A tam vložíte AddCharModel podľa ukážky v predchádzajúcom bode. 4.)Nefungujúce ADDPLAYERCLASS pri vyberaní postavy Na samp fóre som sa dočítal že pre AddPlayerClass nefungujú CUSTOM SKINY ale CustomSkiny fungujú len na SetPlayerSkin. Čiže ak si chcete vybrať hneď pri spustení hry Custom Skin trebalo vymyslieť nejaký iný spôsob. Ja som to poriešil tak že som si upravil filterscript SKINCHANGER.Zmenil som tam iba rozmedzie čísiel SKINU a ID SKINU k príslušnému obrázku. 5.)Screenshoty https://imgur.com/a/aqsnJ 6.)Záver Nie je to nič zložité.Pri nejakých otázkach kľudne sa pýtajte a ak budem vedieť pomôžem.Toť vsio
  5. Aby som si ulahčil prácu pri štylizovaní labelov (na ktorom si potrpím), som si už dávnejšie spravil ľahší script pomcou ktorého som si prácu proste ulahčil. Trocha som ho prerobil aby to nevyzeralo nejako zle a hodim to aj sem, pretože to môže niekomu pomocť. Je to s live preview ukážkou - aspoň približnou. Je viac ako pravdepodobné, že v scripte sú chyby a veľké, napríklad znaky { a } pri prefarobvaní nefungujú párovo, teda ak použijete napr {{{, pekne script zblbnete a zrejme nebude fungovať, ako by mal. Keď má niekto nejaké návrhy, tak nech ich sem napíše napríklad. Anyway, neviem či je to v dobrej sekcii. http://bigweb.6f.sk/tools/3dlabel/
  6. script Timestamp to date

    Zdravím, přináším Vám nový způsob převádění timestamp (časového razítka = počet sekund od 1.1.970) na lidčtější způsob. Sice je tento způsob paměťově (RAM) náročnější. Zato CPU nejrychlejší. Ovšem RAM paměti je pro sa-mp server všude dost. Zato CPU ne. Existuje mnoho způsobů např. vložit timestamp do databáze a nechat si vrátit string výsledek. Ovšem můj způsob vykazuje rychlejší výsledky. Další a asi nejhloupější zpusobje samotné počítání data. Protože tu není povoleno vlozit tak dlouhý kód, dávám sem odkaz: https://pastebin.com/6BN6kc1L Použíti: new time = gettime();//random(cellmax); printf("dnes je %s",GetDate(time)); Pokud chcete k tomu přidat i čas tak to lze lehce pomocí: new time = gettime();//random(cellmax); time = time%(24*60*60); printf("hodin=%d minut=%d vterin=%d",time/(60*60)/*pozor na časové pásmo !!!*/,(time/60)%60,time%60); Enjoy
  7. Obtížnost: Osnova: 1. Úvod; 2. Charakteristika a vlastnosti jazyka; 3. Odlišnosti oproti jiným jazykům; 4. Užitečné odkazy; 5. Závěr. 1. Úvod Zdravím, po delší pauze jsem se rozhodl, že rozjedu nový seriál, tentokrát zaměřený na jazyk Python. Tento jazyk mě hodně baví a rád bych vás do něj trochu zasvětil. Třeba vás zaujme stejně jako mě. Předem bych chtěl varovat, že se nebude jednat o návody psané pro začátečníky s programováním, očekávám již nějakou programátorskou zkušenost. Nebudu dělat podrobné výklady té či oné části jazyka, budu uvádět jen důležité a věcné informace. Postupně projdu různá témata – základní konstrukce jazyka, práci s regulárními výrazy, objektově orientované programování, podpora funkcionálního programování v Pythonu a různé zajímavé možnosti jazyka. Většina návodů bude psána pro verzi 3 a vyšší. V případě, že se daná vlastnost/funkce jazyka vyskytuje od určité verze, budu se snažit tuto informaci uvést. K úvodním informacím by to bylo vše, v tomto návodu se podíváme na charakteristiku jazyka a poté si uvedeme rozdíly oproti jiným jazykům. 2. Charakteristika a vlastnosti jazyka Nerad bych nudil táhlou historií vývoje, takže zmíním jen dva zajímavé fakty – Python se vyvíjí již od konce 80. let minulého století a jeho autorem je nizozemský programátor Guido van Rossum. Tímto máme historii pokrytou. Nebolelo to, že? Každý programovací jazyk má svou charakteristiku. Je-li řeč o Pythonu, jako první zmíním, že se jedná o víceúčelový vysokoúrovňový skriptovací jazyk. Co je vysokoúrovňový jazyk vysvětlovat nebudu (hodně zjednodušeně – není to C ani assembler), stejně tak to bude s pojmem skriptovací (to si můžete vygooglit ). Co bych ale rád rozebral je všestrannost Pythonu. Python totiž nemá jedno konkrétní zaměření. Lze si v něm vytvořit okenní aplikaci (PyQT, tkinter), stejně tak i testovací skripty ke studentským projektům (vysokoškoláci pochopí). Uplatnění má i při vývoji webových stránek a her. Pokročilí programátoři jej využívají i pro strojové učení. Python můžete zkrátka využít (či zneužít) ke všem možným, nemožným, legálním i nelegálním programátorským nápadům. Nyní se zaměřme na jeho konkrétní vlastnosti, které bychom měli znát. Dobré je vědět, že je multiplatformní. Pro ty, kdo se s tím slovem nikdy nesetkali – Python skripty vám budou fungovat i jinde než na Windows (na Linuxu, Mac OS X i dalších). Abychom tyto ale skripty mohli vůbec spustit, budeme potřebovat interpret (ke stažení zde). V tuto chvíli bych měl asi říct, že je to tedy interpretovaný jazyk; to je taky z části pravda. Bez interpretu se neobejdeme, nicméně Python při spuštění skriptu generuje soubory, tzv. bytecode, jež jsou poté interpretovány. Proto bude lepší říct, že Python využívá to nejlepší z obou světů, tedy kompilace i interpretace. Z programovacího hlediska by nás mohlo zajímat, že Python nevyžaduje deklaraci proměnných a využívá tzv. dynamického typování, což znamená, že nejenže nemusíme deklarovat, ale také nebudeme pevně určovat datový typ. Zkrátka si do proměnných uložíme, co se nám zrovna bude hodit. S datovými typy také souvisí silná typová kontrola. Tím vám chci naznačit, abyste hned zapomněli na veškerou černou magii z Javascriptu ("1" + 2 - "3" + "4" == "94") a podobných jazyků. V Pythonu nelze sčítat či odčítat řetězce s čísly a podobně. Často vyzdvihovanou vlastností Pythonu je také to, že podporuje více paradigmat. Pokud jste se teď zhrozili při slově paradigma, nebojte se, nejde o nic strašného. Programovací paradigma si představte jako způsob řešení a zápisu dané úlohy. Existuje hodně paradigmat – procedurální (Pawn), objektově orientované (Java), logické (Prolog), funkcionální (Haskell)... Některé spolu souvisejí, některé jsou nadřazené jiným, další jsou přesným opakem jiných. Nebudu vám v tom dělat guláš, pro zájemce je tu třeba tento článek. A co tedy Python z toho všeho umožňuje? Úlohy v Pythonu lze řešit procedurálně, ale máme možnost využít i objektově orientované programování; do jisté míry umožňuje Python i funkcionální programování (o tom třeba později). 3. Odlišnosti oproti jiným jazykům Teď už víme o základních vlastnostech Pythonu. V této druhé části návodu se podíváme na rozdíly oproti jiným známým jazykům. Žádné středníky Na konci příkazů a výrazů se, na rozdíl od jazyků jako C, Java či PHP, nepíše středník: // kód v C int n = 5; printf("Proměnná 'n' má hodnotu %i", n); # kód v Pythonu n = 5 print("Proměnná 'n' má hodnotu", n) Odsazení namísto složených závorek Většina jazyků se syntaxí jazyka C (C/C++, C#, Java, PHP, Pawn atd.) využívá ke tvorbě bloků složené závorky. V Pythonu se bloky tvoří dvojtečkou za příkazem (if, else, for, while...) a odsazením (běžně 4 mezery): // kód v C if(promenna < 1) { printf("Hodnota proměnné je menší než 1."); return 1; } # kód v Pythonu if promenna < 1: print("Hodnota proměnné je menší než 1.") return 1 and, or, not Logické operátory se nejčastěji zapisují jako && (and), || (or) a ! (not). V Pythonu se tyto operátory zapisují and, or a not: // kód v C if(promenna1 && promenna2 || !promenna1 && !promenna2) # kód v Pythonu if promenna1 and promenna2 or not promenna1 and not promenna2: Pozměněné názvy příkazů Tohle nebude žádná raketová věda, jen se tu a tam změnilo písmenko či slovíčko. Příklad 1: Namísto else if se píše elif. Příklad 2: Namísto catch u zachytávání výjimek máme except. Příklad 3: Poznámky se píší za mřížku #, ne za dvě lomítka //. Příklad 4: Zkuste najít. Chybějící struktury a operátory Ačkoliv vás to asi překvapí, v Pythonu neexistují jisté struktury a operátory, které jsou v ostatních jazycích běžné. Jedná se o struktury switch, do-while a operátory ++ a --. Není to ale nic, co by nešlo nahradit jiným kódem: # kód v Pythonu # náhrada switche if promenna == 1: print("Je to jedna") elif promenna == 2: print("Je to dva") else: print("Je to Bůh ví co") promenna += 1 # náhrada ++ Ternární operátor ?: Mnozí z vás používají ternární operátor ?: pro tvorbu "inline podmínek". Ani tento operátor v Pythonu není, místo něj je tu konstrukce if-else: // kód v C promenna = 1 < 2 ? 1 : 0; // podmínka ? pravda : nepravda # kód v Pythonu promenna = 1 if 1 < 2 else 0 # pravda if podmínka else nepravda Funguje úplně stejně (podmínky lze řetězit), jen se změnilo pořadí operandů. 4. Užitečné odkazy Zde máte několik užitečných odkazů, mimo jiné odkaz na stažení interpretu Pythonu, bez kterého jeho skripty nespustíte: • stažení interpretu Pythonu; • oficiální dokumentace Pythonu; • oficiální dokumentace Pythonu (pro starší verzi 2.7); • kurz Pythonu na Codeacademy; • vývojové prostředí PyCharm (od JetBrains). 5. Závěr A tím pro dnešek končím. Tento text byl jen lehkým úvodem do Pythonu, měli jsme možnost oťukat si trochu jeho syntaxi a uvést jeho vlastnosti. V příštím návodu se budeme věnovat konstrukcím v Pythonu. Pokud jste narazili na nějakou chybu, nějaký překlep nebo se chcete na něco zeptat, případně mi napsat jen tak, jen do toho.
  8. Předmluva Předem bych chtěl podotknout, že návod je vážně určen absolutním nováčkům, a už mírně pokročilí si budou říkat, že to umí každý. Proč dělám tento návod? Když jsem s pawnem začínal úplně, nenašel jsem žádný návod, jež by byl pro největší „lamy“ Pak jsem ale narazil na nejmenovaného člověka, a ten mě naučil začátky. Momentálně bych řekl, že jsem mírně pokročilý. A nyní k samotnému návodu Obtížnost: Úvod - základy Komentář v codu - Chcete-li si udělat nějakou poznámku v kodu, použijte „//“ (bez uvozovek), pokud to je na více řádků, tak „/*“ a na konci „*/“ (opět bez uvozovek) Include - Abyste vůbec mohli jakýkoliv FS / GM vytvořit, musíte mít na začátku codu „#include <a_samp>“ - Dále Vám doporučuji „#include <izcmd>“, jež slouží k snažšímu psaní příkazů. Stáhnete jej tady: https://www.mediafire.com/file/76kh8qfmckpwzcx/izcmd.inc nebo http://forum.sa-mp.com/showthread.php?t=576114 - A existují různé další includy, jež Vám ulehčí práci. Upozornění: - Za každou funkcí se musí psát „;“, za podmínkou ne První příkazy - Na začátek modu si dáme „#include <a_samp“, na další řádek „#include <izcmd>“. - Tento příkaz bude sloužit k doplnění HP a vesty. Níže si jej i rozebereme. Code: #include <a_samp> #include <izcmd> CMD:heal(playerid, params[]) { SetPlayerHealth(playerid, 100); SetPlayerArmour(playerid, 100); SendClientMessage(playerid, 0xFF0000AA, "Doplnil sis HP a vestu"); return 1; } Vysvětlení CMD:heal(playerid, params[]) - Vytvoří nám příkaz /heal - „playerid“ nám zjišťuje ID hráče, jež příkaz zadal - „params[]“ Parametry, jež hráč zadal za samotným příkazem. { } - Do těchto závorek se dávají kody. Kod se těmito závorkami "otevírá" a "uzavírá" Příklad: { //Náš kod return 1; } SetPlayerHealth(playerid, 100); - „SetPlayerHealth“ je funkce na nastavování HP - „playerid“ nám zjišťuje ID hráče, jež příkaz zadal - „100“ je počet HP, kolik daná funkce nastaví SetPlayerArmour(playerid, 100); - „SetPlayerArmour“ je funkce na nastavování vesty - „playerid“ nám zjišťuje ID hráče, jež příkaz zadal - „100“ je počet vesty, kolik daná funkce nastaví SendClientMessage(playerid, 0xFF0000AA, "Doplnil sis HP a vestu"); - „SendClientMessage“ je funkce na odeslání zprávy konkrétnímu hráči (v našem případě hráči, jež zadal příkaz /heal) - „playerid“ nám zjišťuje ID hráče, jež příkaz zadal - „0xFF0000AA“ je hexadecimální kod barvy, touto barvou bude daná zpráva odeslána - "Doplnil sis HP a vestu" je zpráva, jež to danému hráči odešle return 1; - Vrátí hodnotu, resp. ukončí danou funkci Jak odeslat zprávu všem? stock Nick(playerid) { new name[25]; GetPlayerName(playerid, name, 25); return name; } CMD:zprava(playerid, params[]) { new string[128]; format(string, sizeof(string), "Hráč %s zadal příkaz /zprava", Nick(playerid)); SendClientMessageToAll(0xFF0000AA, string); return 1; } Vysvětlení: „stock Nick(playerid) { new name[25]; GetPlayerName(playerid, name, 25); return name; }“ - „stock Nick(playerid)“ je funkce na zjištění nicku hráče, aby jsme mohli odeslat formátovanou zprávu (v tomto případě s jeho nickem) - „new name[25];“ Tady se nám uloží nick hráče - „GetPlayerName“ Zjistí nám nick hráče - „(playerid, name, 25);“ playerid nám opět zjistí ID hráče, name je název newu a 24 je maximální délka nicku + místo pro nulový znak = 25 (Nulový znak se musí přidávat do každého newu, jelikož by se nám jinak zpráva nevypsala celá.) - „return name;“ nám vráti hodnotu, resp. ukončí danou funkci CMD:zprava(playerid, params[]) { new string[128]; format(string, sizeof(string), "Hráč %s zadal příkaz /zprava", Nick(playerid)); SendClientMessageToAll(0xFF0000AA ,string); return 1; } CMD:zprava(playerid, params[]) - vysvětlili jsme si výše - new string[128]; nám uloží zprávu, 128 je maximální délka zprávy - format(string, sizeof(string), "Hráč %s zadal příkaz /zprava", Nick(playerid)); - format znamená formátování, resp. použití údajů zapsaných za (v našem případě) zprávou, ale může to být použito i v dialogu, nebo printf, ale to si vysvětlíme později - string je naše zpráva - sizeof(string) znamená, že velikost naší zprávy bude stejná jako velikost stringu - "Hráč %s zadal příkaz /zprava" zpráva vypsaná do chatu - Nick(playerid) je náš stock, jež nám zjistí údaj, v tomto případě nick, a vypíše ho - return 1; vrátí hodnotu Závěrem Doufám, že se menší návod líbil, jak bylo vzpomenuto výše, je určen absolutním nováčkům, tak to vezměte na vědomí při hodnocení. Nejspíše bude tento návod na více dílů, tady jsme si vysvětlili základy. Doufám, že návod bude označen jako platný, nováčkům by mohl pomoci.
  9. Ahoj v první řadě se omlouvám jestli jsem to dal do špatný sekce ale nevím kam jinam to dát Teď k věci... taky vás štve už nejméně 3 roky když si chcete zahrát sampko... v clientu na INTERNET a ukáže vám to jen servery které jsou hosted ? Našel sem jednu věc která tento problém řeší, sám jsem to zkoušel a funguje perfektně tak se s vámi chci podělit https://github.com/spmn/sa-mp_masterlist_fix/releases a stáhněte version.dll Po stažení jen soubor vložte do složky, kde máte nainstalovaný samp Možná o tom pár z vás vědělo ale myslím si že ne všichni. Každopádně to funguje perfektně
  10. https://www.youtube.com/watch?v=wWCJQ2_Pyww
  11. Obsah Úvod #define enum Ďalšie použitie 1. Úvod Napadlo mi, že rýchlejšie než vysvetliť niekomu čo je to enum, by bolo dať mu odkaz na nejaký návod. Žiadny som však nenašiel. Boli útržky toho čo je to enum tu a tam, ale nič čo by sa dalo ľahko nájsť. Enum slúži na náhradu direktív preprocesora (#define NIECO). Je prehľadnejší a umožňuje lepšiu kontrolu errorov pri kompilácii. Enum je skratka od enumeration, tj. výčet, vyčíslenie. V tomto návode teda ukážem riešenie konkrétnej úlohy dvomi spôsobmi. Pomocou #define a enum. Majme systém, ktorý kontroluje kde sa nachádzajú isté autá a či sú obsadené. Použijeme teda jednu globálnu premennú. 2. #define #define POSX 0 #define POSY POSX + 1 #define POSZ POSX + 2 #define OCCUPIED POSX + 3 #define VELKOST_POLA (OCCUPIED - POSX + 1) // 3-0+1=4 #define POCET_AUT 20 new Vozidla[POCET_AUT][VELKOST_POLA]; ... stock PouzitiePola() { printf("Velkost posledneho pola = %d", VELKOST_POLA); for (new i; i < sizeof (Vozidla); i++) if (Vozidla[i][OCCUPIED] == true) { printf("%f", Vozidla[i][POSX]); // len nejaky priklad } } 3. Enum Rovnakú funkcionalitu s použitím enumu by sme dosiahli nasledovným kódom. Nie je nutné písať názvy jednotlivých prvkov v enume veľkým písmom. Záleží na vašich preferenciách, mne celkom dáva zmysel, že keďže to nahrádza konštanty, tiež by to malo byť veľkým písmom. #define POCET_AUT 20 enum CarEnum { Float:POSX, // enum umoznuje jednoduchu a prehladnu kontrolu typov Float:POSY, Float:POSZ, bool:OCCUPIED }; new Vozidla[POCET_AUT][CarEnum]; ... stock PouzitiePola() { printf("Velkost posledneho pola = %d", _:CarEnum); for (new i; i < sizeof (Vozidla); i++) if (Vozidla[i][OCCUPIED]) { printf("%f", Vozidla[i][POSX]); // len nejaky priklad } } Možno ste si všimli v PouzitiePola() s enumom: printf("Velkost posledneho pola = %d", _:CarEnum); Tá časť _:CarEnum musí mať predponu _: inak by kompiler hodil warning. Fungovalo by to ajtak. Je to len bug kompilera. V praxi som vypísanie veľkosti enumu ešte nevidel, nebojte sa že by to hnusilo kód. Pre pokročilých: 4. Ďalšie použitie Enum nemusí číslovať od nuly, dá sa spraviť aj toto: #include <a_samp> enum TestEnum { PREMENNA = 5, PREMENNA2, PREMENNA3, // pauza PREMENNA4 = 25, PREMENNA5 }; main() { printf("%d, %d", _:PREMENNA3, _:PREMENNA5); } Server log: SA-MP Dedicated Server ---------------------- v0.3.7-R2, (C)2005-2015 SA-MP Team ... [01:05:25] 7, 26 Som presvedčený, že s enumami sa dajú robiť rôzne pekelné kúsky z ktorých ja žiadne nepoznám, určite ak nejaké máte, pridajte.
  12. Hookovanie funkcií a callbackov Obsah Čo je to hookovanie Princíp hookovania a preprocesor _ALS_ - Advanced Library System Hookovanie funkcií Hookovanie callbackov Zhrnutie 1. Čo je to hookovanie Predstavte si gamemod v Pawn ako reťaz, kde každý krúžok predstavuje jednu funkciu (stock). Tieto krúžky sú pospájané, pretože jedna funkcia (stock) volá druhú a tá ďalšiu, atď. Dobrý, čitateľný kód je rozdelený do mnoho súborov, includov. Nanešťastie, každý callback môže byť definovaný iba raz, čo bráni efektívnemu rozdeleniu kódu. Tento problém rieši hookovanie, ktoré si možno predstaviť tak, že reťaz (gamemode) sa v niektorom krúžku rozdelí, pridá sa tam kód, ktorý chceme hooknuť a naspäť sa spojí, bez toho aby to akokoľvek ovplyvnilo zvyšok reťaze. To umožňuje použiť jeden callback aj viackrát v jednom súbore (prípadne v includoch). 2. Princíp hookovania a preprocesor Je treba povedať, že Pawn kompiler nefunguje (ani nemá prečo fungovať) tak ako Cčkový, alebo iný. Povedzme, že chceme upraviť (hooknuť) funkciu GivePlayerMoney() tak, že vždy keď je zavolaná, dá hráčovi dvojnásobok peňazí. Samozrejme bez toho, aby sme ovplyvnili nejaký už-existujúci kód. stock GivePlayerMoneyEx(playerid, money) { // definujeme vlastnu funkciu return GivePlayerMoney(playerid, money * 2); // v nej zavolame tu povodnu } #define GivePlayerMoney GivePlayerMoneyEx // predefinujeme tu povodnu Ďalšie použitie funkcie GivePlayerMoney() by už hráčovi dalo dvojnásobok peňazí. Štvrtý riadok spôsobí, že každé nasledujúce volanie GivePlayerMoney() preprocesor nahradí za GivePlayerMoneyEx(), teda za náš hook. Kompiler nehodí error/warning v prípade, že predefinujete už-existujúcu funkciu/callback. Na pochopenie princípu hookovania je treba vedieť ako funguje preprocesor Pawn. Stačí vedieť, že prebieha vo viacerých krokoch. V prvom kroku prebehne daný súbor, ktorý má spracovať. Skontroluje v ňom makrá a podmienky preprocesora a vyhodnotí ich. Súčasne si zapamätá ktoré funkcie (stocky, publicy) existujú, pridá si ich do medzipamäte a súbor prebehne znovu (opäť vyhodnotí makrá a podmienky preprocesora). Toto správanie podporí aj nasledujúci kód. Pre vaše dobro si každý z tých kódov skompilujte. #if defined A #error Funkcia je definovana #endif stock A() { } Kompiler hodí error kvôli tomu, že funkcia "A" je definovaná, hoc až za makrom. Zaujímavý je však tento kód: #if !defined A // vsimnite si zmenu, negaciu podmienky #error Funkcia nie je definovana #endif stock A() { } Hodí error rovnako, ako kód predtým. Ako je to možné? Predsa ide o znegovanú podmienku. Nečítajte ďalej, ak na to chcete prísť sami. Druhý kód prebieha tak, že preprocesor prejde ku "#if !defined". Tam samozrejme zastaví, pretože doteraz symbol "A" nikde nenašiel. Prečo teda prvý kód tiež narazil na error? V prvom kóde, preprocesor prebehne ku #if defined. "A" definované nie je a teda ide ďalej, ku koncu súboru, medzitým "A" nájde a uloží si ho do zoznamu známych symbolov. V ďalšej iterácii však preprocesor znova dôjde k #if defined, "A"čko už pozná a preto hodí error. Musím ešte povedať, že toto som zistil experimentami, popravde neviem ako funguje ten preprocesor. Ak máte nejaké objasnenie, môžete napísať. 3. _ALS_ - Advanced Library System Ak ste niekedy videli hookovací kód, všimli ste si, že oproti môjmu príkladu s GivePlayerMoney(), tam bolo niečo navyše. Správny kód by mal vyzerať takto: stock GivePlayerMoneyEx(playerid, money) { GivePlayerMoney(playerid, money * 2); } #if defined _ALS_GivePlayerMoney #undef GivePlayerMoney #else #define _ALS_GivePlayerMoney #endif #define GivePlayerMoney GivePlayerMoneyEx Toto slúži na detekciu, či už bola daná funkcia hooknutá. Ak áno, kód by nefungoval a tiež vyhodil warning 201: redefinition of constant/macro (symbol "GivePlayerMoney") Predefinovanie stocku/callbacku warning nehodí, predefinovanie makra/define áno. Kúzlo s "_ALS_" ošetruje práve to, aby bolo možné skombinovať viac hookov. Syntax "_ALS_" je akýsi neoficiálny štandard. Používajú to všetci a tým sa zaručí kompatibilita hookov od rôznych autorov. 4. Hookovanie funkcií Hookovanie funkcií už bolo ukázané, ale dám ešte jeden príklad. // ak je hrac vo vozidle, portne aj vozidlo stock SetPlayerPosEx(playerid, Float:x, Float:y, Float:z, bool:vehicleToo=false) { if (vehicleToo) { if (IsPlayerInAnyVehicle(playerid)) return PortWithVehicle(playerid, x, y, z); else return SetPlayerPos(playerid, x, y, z); } else return SetPlayerPos(playerid, x, y, z); } #if defined _ALS_SetPlayerPos #undef SetPlayerPos #else #define _ALS_SetPlayerPos #endif #define SetPlayerPos SetPlayerPosEx ... public OnPlayerCommandText(playerid, cmdtext[]) { if (!strcmp("/portme", cmdtext)) SetPlayerPos(playerid, 1, 2, 3, true); else if (!strcmp("/oldport", cmdtext)) SetPlayerPos(playerid, 234, 46, 324); } 5. Hookovanie callbackov Hookovanie callbackov prebieha trochu ináč než funkcií. Aj keď kód je skoro rovnaký, na pozadí ide v podstate o opačný proces než u funkcií. public OnPlayerGiveDamage(playerid, damagedid, Float:amount, weaponid, bodypart) { // pouzijeme povodny callback if (IsPlayerAdmin(damagedid)) { // pridame vlastnu funkcionalitu Kick(playerid); } // zavolame nasledujuci hook #if defined MyOnPlayerGiveDamage // moze sa stat, ze neexistuje viac hookov, preto podmienka return CallLocalFunction("MyOnPlayerGiveDamage", "iifii", playerid, damagedid, amount, weaponid, bodypart); #else return 0; // v callbackoch su dolezite spravne return hodnoty #endif } #if defined _ALS_OnPlayerGiveDamage #undef OnPlayerGiveDamage #else #define _ALS_OnPlayerGiveDamage #endif #define OnPlayerGiveDamage MyOnPlayerGiveDamage // premenovanie nasledujuceho callbacku #if defined MyOnPlayerGiveDamage // samozrejme forward forward MyOnPlayerGiveDamage(playerid, damagedid, Float:amount, weaponid, bodypart); #endif V skripte použijeme ten pôvodný callback a "predefinujeme" tie nasledujúce. Syntax "MyOnPlayerGiveDamage" už nie je "štandardizovaná", môžete použiť aj iný názov. 6. Zhrnutie Pri hookovaní v podstate nejde o ten kód, ako o to pochopiť čo robí preprocesor na pozadí. Ak ste si všetky kódy pozreli a porozmýšlali nad nimi, mali by ste tomu rozumieť. Či do toho "vidíte skrz na skrz" si môžete skúsiť odpovedaním na tieto dve bonusové otázky: 1.) V prípade, že je 10 skriptov čo hookujú nejakú funkciu a môj skript ju hookol prvý, koľká v poradí sa vykoná funkcia z môjho skriptu? 2.) V prípade, že je 10 skriptov čo hookujú nejaký callback a môj skript ho hookol prvý, koľký v poradí sa vykoná callback z môjho skriptu? Ak máte otázky/vylepšenia, pokojne sem s nimi.
  13. https://t.co/G4gWmPeC3y https://t.co/vp5FzG5baf

  14. Zdravím, rád bych vám dnes ukázal jak si jednoduše vytvořit vlastní panel do Tracy. Ti z Vás kdož používají Nette se s Tracy znáte, pro vás ostatní je to skvělá utilita o které si popovídáme jindy Základem je mít nainstalovanou Tracy , pokud pracujete v Nette tak tracy máte nainstalovanou automaticky. Já osobně své vlastní panely mám uchované přímo vedle Tracy tzn , že ve složce knihovny jsem si vytvořil složku tracy_modules do které dávám jednotlivé soubory k jednotlivým panelů. Začneme tím , že si tedy vytvoříme soubor pro náš panel s nádledujícím obsahem <?php use Tracy\IBarPanel; class <jmeno_naseho_panelu> implements IBarPanel { function getTab() { } function getPanel() { } } Nyní si rozebereme ty dvě funkce.. Funkce getTab vrací vlastně obsah který se bude zobrazovat na Tracy. A funkce getPanel vrací obsah pro popup který se otevře při najetí na getTab. Pro účely tutoriálu náš panel bude mít ikonku php a v popupu bude titulek PHP a pod ním vypsána verze PHP. Najdeme si ikonku nejlépe 24x24 pixelů a vytvoříme si tedy tab function getTab() { return "<span title='<tooltip_titulek>'><img src='<url_ikonky>'><volitelny_titulek_vedle_ikonky></span>"; } Případně nemusíme používat ikonku tudíž vynecháme celý tag . No a nyní tedy chceme na hover vidět verzi php kterou disponujeme function getPanel() { $title = "<h1>PHP</h1>"; $header = "<div class='tracy-inner'><table><tbody>"; $content = "<tr><td>Verze PHP</td><td>".phpversion()."</td></tr>"; $footer = "</tbody></table>"; return $title.$header.$content.$footer; } Requirneme soubor s naším panelem. A panel přidáme do tracy v mém případě se panel jmenuje PHPPanel Tracy\Debugger::getBar()->addPanel( new PHPPanel() ); A můj panel nyní vypadá takto A to je vše. Nyní je kompletně na Vás co bude Váš panel umět a co bude zobrazovat
  15. Obtížnost: Osnova: 1. Úvod, co je to funkce; 2. Definice funkce a její části; 3. Parametry; 4. Návratová hodnota; 5. Závěr. 1. Úvod, co je to funkce Zdravím, tímto návodem konečně dokončím šňůru návodů pro začátečníky. Posledním tématem, které jsme ještě nestihli probrat, jsou funkce. O čem je řeč? Funkce jsou takové části kódu, které lze volat v různých částech skriptu. Někdy se lze také setkat s pojmem podprogram (ačkoliv to není to samé – podprogramem mohou být i metody, ale to se nás ani Pawn netýká). Účel je jasný – abychom nemuseli psát tentýž kód na více místech, napíšeme jej jen jednou a voláme jej tam, kde potřebujeme. Přináší nám to hned několik benefitů – kratší a přehlednější kód, při úpravě kódu jej stačí upravit na jednom místě, totéž platí pro opravy chyb. Počas skriptování SA:MP skriptů se setkáváme s funkcemi nepřetržitě, jmenovitě například funkce GetPlayerName, SendClientMessage, strval, ale i OnPlayerConnect či OnFilterScriptInit. 2. Definice funkce a její části Když už máme představu, co to funkce je, měli bychom si ukázat, jak ji vytvořit. Každá funkce má svůj název (identifikátor), dále pak parametry, o kterých si řekneme za chvíli, tělo, do kterého vkládáme kód, a jako poslední návratovou hodnotu (i když tu nemusí mít nezbytně, o tom za chvíli). Ukažme si to na kódu: Secist(cislo1, cislo2) { new suma; suma = cislo1 + cislo2; return suma; } Teď si určíme jednotlivé části funkce: – identifikátor: Secist – parametry: cislo1 a cislo2 – tělo funkce: všechno mezi složenými závorkami {} – návratová hodnota: return suma; Jak je vidět, jako první se uvádí identifikátor, poté následují parametry ohraničené kulatými závorkami, následně se píše tělo kódu do složených závorek a do těla se uvádí návratová hodnota příkazem return. Výše uvedená funkce slouží k součtu dvou celých čísel. 3. Parametry Díky parametrům můžeme funkci předávat vstupní hodnoty a/nebo ovlivňovat to, jak se bude chovat. U naší sčítací funkce parametry slouží k předání sčítanců. Ale například funkce strcmp má parametr ignorecase, který nám určuje, zda má funkce ignorovat rozdíl mezi velkými a malými písmeny. Tento parametr ovlivňuje chování funkce. Parametry funkcí v Pawn mohou být různého datového typu (tedy celá čísla, desetinná čísla, logické hodnoty, řetězce atd.) a může jich být libovolný počet. Jsou funkce, které nemají žádné parametry (kulaté závorky ale musíme uvést vždy – ()), jsou takové, které jich mají i 10. Zde je pár funkcí na ukázku, každá s jiným počtem parametrů (všechny lze dohledat na SA:MP wiki): GetTickCount(); //funkce bez parametrů SendClientMessage(playerid, color, const message[]); //funkce se 3 parametry AddPlayerClass(modelid, Float:spawn_x, Float:spawn_y, Float:spawn_z, Float:z_angle, weapon1, weapon1_ammo, weapon2, weapon2_ammo, weapon3, weapon3_ammo); //funkce s 11 parametry Lze si všimnout, že u některých se objevují věci jako Float:, [] apod. Právě tyto, prozatím tomu říkejme "věci", nám určují, jaký datový typ bude daný parametr mít. Seznam nejčastěji používaných datových typů: playerid // když neuvedeme nic, bere to jako celé číslo Float:x // Float: nám značí desetinné číslo bool:ignorecase // bool: nám značí logickou hodnotu (true/false) message[] // hranaté závorky znamenají řetězec (nebo pole, viz předchozí návody) Zbývá nám uvést si, jak takové parametry dosazovat při volání funkce. Jednoduše za ně dosadíme skutečné hodnoty (přesněji argumenty) v tom pořadí, v jakém jsme je definovali: GetTickCount(); //nic se nemění SendClientMessage(0, 1, "Ahoj, světe!"); //dosazení argumentů (skutečných hodnot) Nad rámec návodu (pro zvídavé): 4. Návratová hodnota Na začátku jsme řekli, že funkce má také návratovou hodnotu. Přesněji řečeno, může mít, ale nemusí. Přesně tak, funkce žádnou návratovou hodnotu mít nemusí. V některých jazycích se pak funkce bez návratové hodnoty nazývá procedurou. V kódu naší sčítací funkce je vidět, že hodnotu vrátíme příkazem return. Ve funkci můžeme tento příkaz použít vícekrát (často to souvisí s podmínkami a větvením), ale pravidlem je, že musí vždy vrátit hodnotu stejného datového typu. Kompilátor nám neumožní vrátit jednou celé číslo a jednou řetězec, to prostě nejde. Když už jsme zmínili datové typy, je třeba si dávat pozor na jednu věc. Pokud vracíme hodnotu jinou než celé číslo či řetězec, musíme před identifikátor uvést příslušný tag (teď už nepíši "věc", ale tag). Upravme si tedy naši funkci pro sčítání dvou desetinných čísel: Float:Secist(Float:cislo1, Float:cislo2) // před názvem nám přibyl tag Float { new Float:suma; suma = cislo1 + cislo2; return suma; } Zde je vidět, že před názvem nám přibylo Float:. Je to nutné pro správný chod funkce. Kdybychom vraceli např. logické hodnoty, byl by tam tag bool:. A jak je to tedy s funkcemi (procedurami, jestli chcete), které nic nevracejí? Jsou dvě možnosti, buď uvedeme prázdný return – return; – nebo neuvedeme nic. Je to jen na vás, běžná je druhá varianta (neuvádět nic). Ukázka: Vypis(const message[]) { print(message); return; } Vypis2(const message[]) { print(message); } 5. Závěr A tím jsme se dostali jak k závěru tutoriálu, tak k závěru celé série. Děkuji všem, kteří si návod přečetli, a obdivuji všechny, kteří prošli celou sérií. Doufám, že jste se dozvěděli něco nového, pokud ne, alespoň jste si to zopakovali. Prozatím neplánuji začínat další sérii návodů, ale je možné, že se sem tam něco objeví. Ještě jednou děkuji a platí to, co vždycky – pokud jste našli nějakou chybu či nesrovnalost nebo se jen chcete na něco zeptat, zanechte mi vzkaz pod tímto příspěvkem.
  16. Obsah Úvod Čo sú to runtime erorry Príklad použitia Záver Úvod Pri vývoji softvéru je veľmi ľahké urobiť nejakú chybu. Na testovanie (debugovanie) sa používajú rôzne metódy, jednou z tých agresívnejších môžu byť runtime errory. Je len na Vás, či si vyberiete túto metódu s využitím runtime errorov / výnimiek / exceptions. V návode sa v podstate nenaučíte nič nové, patrí medzi "zložitejšie" len preto, že na správne využitie týchto informácií musíte mať isté programátorské myslenie a poznať peklo debugovania komplexných programov. Čo sú to runtime errory Určite ste sa stretli s tým, že Vám padol za behu server s textom Run time error 4: "Array index out of bounds" Stalo sa to, že server na pozadí pri každom priradení hodnoty kontroluje, či ste neprekročili veľkosť premennej. Server zistil, že áno a zhodil server. V momente ste vedeli, že v kóde je chyba. Keby server nepadol, čo by sa stalo? V prípade, že by nedochádzalo ku kontrole, že či nebola prekročená veľkosť pola, zapisovanie údajov by pokračovalo ďalej v pamäti (aj za danou premennou) a mohlo by sa stať, že by sa prepísali hodnoty nasledujúcich premenných / polí. Takáto chyba je prakticky nemožná na detekciu. Napíšem príklad z mojej praxe. Čo to obnáša? V prípade, že dôjde k nejakej chybe, padne server. V prípade, že tam nejaká chyba je, nájdete ju ľahšie. Prakticky platí, čim väčší mód, tým ťažšie sa hľadajú chyby a presne to uľahčujú runtime errory. V skratke teda ide len o to, že namiesto bežnej kontroly extrémnych hodnôt premenných, nevrátite "0", "-1", alebo nejakú podobnú hodnotu, ale rovno zhodíte server a poviete programátorovi, kde hľadať chybu. Samozrejme pri nasadení servera online môžete tieto runtime errory vypnúť a používať ich len pri debuggingu. Príklad použitia Pre zjednodušenie práce som dal dokopy definície runtime errorov (žiadny zložitý kód). Includ sa dá stiahnuť tu. Nezabudnite ho uložiť do pawno/include. #define DEBUGGING // povoli run time errory | pre ich vypnutie staci zakomentovat / zmazat tento riadok #include <runtime_errors> // includnut AZ ZA DEFINE DEBUGGING main() { new a = 4; TestZero(a, AMX_ERR_PARAMS, "Tento string sa nevypise kedze a nie je 0."); a = 0; TestZero(a, AMX_ERR_PARAMS, "Hodnota \"a\" nemoze mat nulu."); print("Tento string sa uz nevypise, kedze server padol v predoslom kroku."); } Výstup: ... Loaded 0 filterscripts. Hodnota "a" nemoze mat nulu. Script[gamemodes/test.amx]: Run time error 25: "Parameter error" Number of vehicle models: 0 Odkiaľ je funkcia TestZero()? To je len príklad, nemusíte ju použiť. Nachádza sa už defaultne v include. Vyzerá takto: stock TestZero(var, err, str[]) { // nazov funkcie si zmente ako chcete #pragma unused var, err, str #if defined DEBUGGING if (var == 0) { // tuto podmienku mozete zmenit, vsetko ostatne nechajte tak print(str); switchError(err); } #endif } Svoje vlastné funkcie si môžete vytvoriť na základe predlohy TestZero(), alebo akokoľvek sa rozhodnete. Odkiaľ mám hodnotu AMX_ERR_PARAMS? To sú oficiálne hodnoty vstavané do Pawn AMX, ich zoznam sa nachádza v include runtime_errors, ale na ukážku sem nejaké dám. Ich hodnoty nie sú nijak podstatné, upravujú len správu čo sa vypíše pri páde servera. Môžete tiež všade použiť AMX_ERR_NONE, čo nevypíše žiadnu ďalšiu správu o páde a vypísať svoje vlastné informácie pre uľahčené nájdenie chyby. #define AMX_ERR_NONE 0 #define AMX_ERR_EXIT 1 // forced exit #define AMX_ERR_ASSERT 2 // assertion failed #define AMX_ERR_STACKERR 3 // stack/heap collision #define AMX_ERR_BOUNDS 4 // index out of bounds Úplný zoznam errorov sa nachádza v include. Záver To, či je toto využitie dobré, alebo nie, nikto nemôže povedať. Je to jednoducho štýl programovania a "exceptions", alebo "runtime errory" sú bežnou súčasťou vyšších programovacích jazykov. Ich implementácia v Pawn je vcelku chabá, ale dá sa použiť. Ak sa však raz pre neho rozhodnete, buďte zodpovední a používajte ho všade.
  17. EASY BANKSYSTEM Předtím, než tohle někdo z uživatelů napíše, rád bych řekl, že takové návody jsou roky staré, nefunkční a nebo naprosto prasácky zpracované. Než přistoupíme k návodu, tak bych chtěl zmínit pár bodů, které v tomto návodě nebudu vysvětlovat do podrobností(až ke konci k tomu budu mít pár poznámek): Vizuální zpracování dialogů - To si může každý uživatel udělat idividuálně(v tom případě si proto si hlídejte délky v řetězcích !), Větší počet bankomatů - Chci se spíše zaměřit na ukázku, jak jednodušše na takový systém. Samozřejmě, lze i snadno aplikovat na více bankomatů, Ukládání a načítání množství peněz v bance - Kromě toho, že každý používá jiný include na ukládání a načítání, tak opravdu nemám v úmyslu ukazovat, jak ukládat jednu proměnnou. ZAČÍNÁME Samozřejmě, nahrajeme si základní include a_samp. #include <a_samp>Budeme potřebovat nějakou proměnnou, kam se bude vpisovat počet peněz v bance: new Banka[MAX_PLAYERS];Jelikož víme, že určitě nebudeme zadávat záporná čísla, a přes fci strval může projít záporné znaménko, tak pro jistotu si přidáme fci, aby zjišťovat čistě jen a pouze čísla: stock OnlyNumbers(input[]) { new i; while (i != strlen(input)) if (input[i] <= '9' && input[i] >= '0') i++; else return false; return true; }Nakonec, by bylo dobré si pojmenovat nějak id dialogů, aby si to pak každý mohl individiálně upravit. Můžeme zvolit buď preprocesorovou cestu a nebo přes výčet hodnot. My použijeme výčet hodnot a začneme například hodnotou 6666: enum { DIALOG_BANKA = 6666, DIALOG_BANKA_VLOZIT, DIALOG_BANKA_VYBRAT } Pro lajky OTEVŘENÍ DIALOGU BANKY Tady jsem raději zvolil způsob přes příkaz. Proč? Jelikož, sice je jednoduché přes pickup, ale takhle má alespoň člověk jistotu, že se otevře pouze jednou a u bankomatu. Začneme podmínkou, zda je u daných pozic(jednoho z) bankomatu: public OnPlayerCommandText(...) { if (!strcmp("/banka", cmdtext, true)) { if (IsPlayerInRangeOfPoint(playerid, 1.0, Banka_x, Banka_y, Banka_z)) {Pozice daného bankomatu si pak může každý uživatel přidat jaké chce. Pokračujeme přidáním akce, zda je na daných souřadnicích a to, že se mu ukáže dialog, v opačném případě vrátí zprávu s informací, že neni u bankomatu(na dané pozici): ShowPlayerDialog(playerid, DIALOG_BANKA, DIALOG_STYLE_LIST, "Banka", "Vložit peníze\nVybrat peníze\nStav konta", "Vybrat", "Zavrit"); }else return SendClientMessage(playerid, -1, "Nejsi u bankomatu");Samozřejmě, nesmíme zapomenout správně uzavřít všechny bloky a správné návratové hodnoty. BANKA A LISTY V DIALOGU Začneme zavoláním samotného callbacku pro dialogy a jako první si přepneme dialogid, kvůli rychlosti(i když skoro nepatrné): public OnDialogResponse(...) { switch(dialogid) {A abychom pak neměli problém s bloky, přidáme si všechny 3 podmínky na všechny dialogy rovnou a všem přidáme podmínku, pokud hráč stiskl druhé tlačítko(Zavřít), tak se "nic" nestane a dialog "se zavře". Dále přiřadíme správném návratové hodnoty, a i samotnému callbacku: case DIALOG_BANKA: { if (!response) return true; /* code */ return true; } case DIALOG_BANKA_VLOZIT: { if (!response) return true; /* code */ return true; } case DIALOG_BANKA_VYBRAT: { if (!response) return true; /* code */ return true; }Začneme hlavním dialogem a to DIALOG_BANKA. Ten bude nejsnadnější. Začneme opět přepnutím, a tentokrát listitemu, a oběma dialogům(vložit a vybrat), protože oba budou typu "input", tak je ukážeme hráči a přiřadíme jim jejich dialogid: case DIALOG_BANKA: { if (!response) return true; switch(listitem) { case 0: ShowPlayerDialog(playerid, DIALOG_BANKA_VLOZIT, DIALOG_STYLE_INPUT, "Banka", "Napište částku, kterou chcete vložit", "Potvrdit", "Zavrit"); case 1: ShowPlayerDialog(playerid, DIALOG_BANKA_VYBRAT, DIALOG_STYLE_INPUT, "Banka", "Napište částku, kterou chcete vybrat", "Potvrdit", "Zavrit");A poslední listitem bude spíše informační, tak si tam rovnou formátujeme množství peněz v bance a ukážeme to v dialogu hráči: case 2: { new s_vBance[43]; format(s_vBance, sizeof s_vBance, "Na kontě máš momentálně %i$", Banka[playerid]); ShowPlayerDialog(playerid, DIALOG_BANKA, DIALOG_STYLE_MSGBOX, "Banka", s_vBance, "Zavrit", ""); } } return true; }Další dialog bude případ, kdy vkládá peníze(DIALOG_BANKA_VLOZIT). Začneme základní podmínkou a na to použijeme naší fci, zda hráč píše pouze čísla. Pokud ne, vrátí mu to zprávu: if (!OnlyNumbers(inputtext)) return SendClientMessage(playerid, -1, "Můžete vepsat pouze čísla !");Pak samozřejmě, aby nemohl neustále vkládat 0$: if (strval(inputtext) == 0) return SendClientMessage(playerid, -1, "Nelze vložit 0$ !");A nakonec, zda počet peněz které vkládá není větší, než u sebe skutečně má: if (GetPlayerMoney(playerid) < strval(inputtext)) return SendClientMessage(playerid, -1, "Nemáte takový obnos peněz !");Pak už jen 2 operace. První, přiřadíme k naší proměnné Banka hodnotu, kterou již má a k ní přičteme počet peněz, které hráč vkládá, a druhá, odečteme hráči daný počet peněz: Banka[playerid] = Banka[playerid] + strval(inputtext); GivePlayerMoney(playerid, -strval(inputtext)); return true; }A posledním dialogem bude případ, kdy peníze vybírá(DIALOG_BANKA_VYBRAT). Opět, začneme základní podmínkou a na to použijeme naší fci, zda hráč píše pouze čísla. Pokud ne, vrátí mu zprávu: if (!OnlyNumbers(inputtext)) return SendClientMessage(playerid, -1, "Můžete vepsat pouze čísla !");Opět, aby nemohl neustále vybírat 0$: if (strval(inputtext) == 0) return SendClientMessage(playerid, -1, "Nelze vybrat 0$ !");Nakonec podmínku, zda peníze, které vybírá nejsou větší, než které v bance ve skutečni jsou: if (Banka[playerid] < strval(inputtext)) return SendClientMessage(playerid, -1, "Nemáte v bankce tolik peněz !");A na úplny konec už jen prohodíme obě operace, a to způsobem, že první, přiřadíme k naší proměnné Banka hodnotu, kterou již má a odečteme počet peněz, které hráč vybírá, a druhá, přičteme hráči daný počet peněz: Banka[playerid] = Banka[playerid] - strval(inputtext); GivePlayerMoney(playerid, strval(inputtext)); return true; } JAK NA VÍCE BANKOMATŮ? To je prosté. Buď si(například) zjistit všechny pozice a pak je v příkaze všechny kontrolovat: if (!strcmp("/banka", cmdtext, true)) { if ( IsPlayerInRangeOfPoint(playerid, 1.0, xxx, yyy, zzz) || IsPlayerInRangeOfPoint(playerid, 1.0, xxx, yyy, zzz) || IsPlayerInRangeOfPoint(playerid, 1.0, xxx, yyy, zzz) || IsPlayerInRangeOfPoint(playerid, 1.0, xxx, yyy, zzz) || IsPlayerInRangeOfPoint(playerid, 1.0, xxx, yyy, zzz) || IsPlayerInRangeOfPoint(playerid, 1.0, xxx, yyy, zzz) ) { ShowPlayerDialog(playerid, ...Nebo, skoro stejným způsobem: Deklarovat si pole s výčtem hodnot x-ové pozice, y-ové pozice a z-ové pozice a pak v cyklu je všechny zjistit najednou(něco na způsob): Je tu několik návodů, kde by se hodilo už udělat novější a vylepšenější variantu. Pokud budou dobré ohlasy, udělám další návody. PS: snad jsou všechny kódy správně. Testoval jsem a bylo funkční(až na úplně poslední, to jsem netestoval), pokud přecijen bude někde nějaká chyba, napište mi SZ, ať tu není zbytečně spam. PSS: Ano, jde to udělat ještě lépe, ale já jsem to chtěl zpracovat jednoduchou a snadně-pochopitelnou cestou. Děkuji.
  18. Předem bych rád upozornil, že v repo může být i napřed před návody. Už jen z toho důvodu , že si hodlám kód připravovat a nepsat ho přímo při návodu. Pojďme si založit nový mód. Ve složce php si vytvoříme složku s libovolným názvem. V mém případě se složka jmenuje samp-php-gamemode. Do ní vytvoříme soubor gamemode.php Do souboru gamemode.php si připravíme dva eventy prvním bude nastartování módu a druhým připojení hráče. <?php include "core/bootstrap.php"; Event::on('GameModeInit', function() { }); Event::on('PlayerConnect', function($player){ }); A začneme tím , že přivítáme hráče na našem serveru... Použijeme k tomu známou funkci SendClientMessage byť krapet pozměněnou po stránce argumentů. SendClientMessage( 0xFF00FF00 , "Hráč ".$player->getName()." se připojil na náš PHP server :)"); Asi se možná ptáte ale kde je id kterému se má message poslat ? Event si ho sám určí Respektive si ho najde z instance $player. Dále si můžeme nastavit nějaké ty informace o serveru.. Například GameModeText a PED animace Event::on('GameModeInit', function() { Server::setGameModeText( "Ewolutions PHP Gamemode" ); Server::usePlayerPedAnims(); }); Jména funkcí jsou nebo mohou být krapet odlišná. Ale veškeré funkce najdete ve složce php/core. Tímto dílem bych ve Vás chtěl probudit trošku zvědavosti a navnadit Vás co všechno by mohlo být možné V příštím už se vrhneme na něco komplexnějšího... Třeba registraci
  19. Zdravím, Chtěl bych rozjet takový menší seriálek o tom jak vytvářet scripty, a módy do SA-MP v PHP. Proč ? Je to jednoduché. Díky PHP si do sampu přineseme možnost OOP. Ale k tomu se dostaneme v průběhu. Celý projekt bude dostupný na Githubu. V tomto prvním díle Vám ukážu jak to cele sprovoznit. A od dalšího dílu už začneme programovat Stáhneme: SA-MP Server => zde PHP Plugin => zde Tutoriálové repo => zde Rozbalíme server a sloučíme ho s obsahem archivu s pluginem. Složka serveru by měla vypadat tedy zhruba takto: Vytvoříme si ve složce gamemodes libovolný pwn soubor. Já jsem použil gamemod bare ve kterém jsem obsah nahradil za #include <a_samp> main(){} Zkompilujeme a tím jsme hotoví s jazykem pawn Server.cfg by měl vypadat přibližně následovně. echo Executing Server Config... lanmode 0 rcon_password changedfdfme maxplayers 50 port 7777 hostname SA-MP 0.3 Server gamemode0 bare filterscripts plugins samphp announce 0 chatlogging 0 weburl www.sa-mp.com onfoot_rate 40 incar_rate 40 weapon_rate 40 stream_distance 300.0 stream_rate 1000 maxnpc 0 logtimeformat [%H:%M:%S] language English Po nastartování serveru by jste měli v konzoli vidět pár printů ohledně toho jak programovat.
  20. Nazdars. Určite poznáte tú paranoju, keď ste na laptope, pozeráte napr. Shreka, či iné a máte strach, že niekto vás sleduje cez Vašu webkameru. Môžete sa síce vyhovárať na to, že máte pri kamere indikátor zapnutia (čiže by ste vedeli, že Vás sledujú), ja ho tam napr. nemám, ale keď už majú Vašu citlivú fotku, už je neskoro. Okrem teda prelepenia kamery existuje teda aj elegantnejšie riešenie a to Vám predvediem. Blokovanie driverov Spustite Device manager (Správca zariadení) cez Štart, prípadne cez Run zadajte "devmgmt.msc" Nájdite tam svoju kameru (Zariadenia na spracovanie obrázkov -> Webcam) Kliknite "Zakázať" Resetnite PC Otestovať či to funguje je jednoduché. Stačí otvoriť Skype > Nástroje > Možnosti > Nastavenie videa a uvidíte, že nič neuvidíte. Opätovne spustiť kameru sa dá kliknutím na Povoliť namiesto Zakázať. Je to bezpečné? Áno. Písal som to na viaceré stránky a hovoril som o tom viacerým ľuďom, nikto o niečom takom nepočul a teda keďže nikto to takto neblokuje, vírusy to nemajú prečo riešiť. Pre absolútnu paranoju je tiež možné odstrániť ovládače úplne. Tie sa bez admin-práv nedajú opätovne nainštalovať, vírusy tiež nemajú prístup k Windowsovej databáze driverov (tá ajtak nikdy nefunguje), tj. nevedia aký driver nainštalovať.
  21. Ahoj, koukám, že tu vznikla nová sekce, tak přidám moji serií tutoriálů na C#. Série obsahuje 45 dílů. Současně již nepokračuje, protože není nálada ani čas. Takže doufám, že to někomu pomůže aspoň do začátků a nedělal jsem to zbytečně. Takže ať se líbí Kompletní série je zde: (jednotlivé díly potom na pravé straně) https://www.youtube.com/watch?v=k2KqJEP05Z4&list=PL8428DD4872FA7FB3&index=1 Případné dotazy, cokoliv, kolem videí, C# můžete psát sem. Určitě se najdou tací, kteří dokáží zodpovědět dotazy ohledně tohodle téma
  22. pls dejte mi donate pro více takových funkčních návodu: StudioEtenity@gmail.com (to je email na paypal pošlete něco pls pls pls)
  23. návod PHP Mini - Star Operator

    Dneska jsem se dočetl o novém operátoru , který nejspíše přidají v PHP 7.2 nebo v PHP 8. Je to operátor hvězdička hlavní využití podle vývojářů je to , že umožní aby časté operace pro escapování byli jednodužší. Syntaxe nového operátoru <?* $str ?> <?* $str, 'html' ?> <?* $str, $context ?> A jedná se o zkrácení následujícího kódu $thing['name'] = "dsfwčgevěv"; // Aktuálně <?= htmlspecialchars(urlencode($thing['name'])) ?> // Nový operátor <?* $thing['name']?> Není uplně potvrzené , že opravdu tento operátor přidají ale momentálně to tak vypadá. Uvidíme co bude dál
  24. Úvod Tak, hra GTA Vice City je už poměrně stará hra, přes to je ale zatím pořád dobrá. Jak hru dohrát na 100%, tak to najdete všude možně po internetu. Ovšem tady na pawno.cz to není, tak to sem dávám. Zároveň je toto moje první téma, takže ta prezentace nemusí vypadat nějak skvostně. No dost keců a jdeme na to.. 1) Splnit příběhové mise (jak už je nejspíše jasné): 1. In the Beginning 2. The Party 3. Back Alley Brawl 4. Jury Fury 5. Riot 6. Four Iron 7. Demolition Man 8. Treacherous swine 9. Mall Shootout 10. Guardian Angels 11. The Chase 12. Phantom Penh '86 13. The Fastest Boat 14. Supply § Demmand 15. Sir, Yes Sir ! 16. Death Row 17. Rub Out 18. Two Bit Hit 19. All Hands on Deck! 20. Shake Down 21. Bar Browl 22. Cop Land 23. Cap the Collector 24. Keep Your Friends Close - Odměna: Titulky (jde splnit až po dokončení misí u nemovitostí, nemusí být Malibu Club) 2) Splnit Vedlejší mise 1) Love First 1. Love juice 2. Psycho Killer 3. Publicity Tour 2) Big Mitch Baker 1. Alloy Wheels of Steel 2. Messing with the Man 3. Hog Tield 3) Umberto Robina 1. Stunt Boat Challenge 2. Cannon Fodder 3. Naval Engagement 4. Trojan Voodoo 4) Auntie Poulet 1. Juju Scrable 2. Bombs Away 3. Dirty Lickin's 5) Phil Cassidy 1. Gun Runner 2. Boomshine Saigon 3) Nemovitosti 1. 3312 Vice Point 2. 1102 Washington Street 3. Links View 4. Ocean Hights 5. El Swanko Casa 6. Hyman Condo 7. Skumhole Shack 8. Boatyard (Přístav) 9. Cherry Popper Icecram 10. Pole Position Strip Club 11. Print Works 12. Kaufman Cabs 13. Sunshine Auto Showroom 14. Malibu Club 4) Splnit 5 telefonních misí 1. Road Kill 2. Waste the Wife 3. Autocide 4. Check Out at the Check In 5. Loose End 5) Vyhrát všechny Ilegální závody 1. Terminal Velocity 2. Ocean Drive 3. Border run 4. Capital Cruise 5. Tour ! 6. V.C. endurance 6) RC Mise 1. RC vrtulník 2. RC autíčko 3. RC letadlo 7) Mise na šikovnost 1. Cone Crazy 2. PCJ Playgroud 3. Trial By Dirt 4. Test Track 8) Mise na stadionech 1. Dirt Ring 2. Hot Ring 3. Blood Ring 9) Výcvik ve vrtulníku 1. Ocean Beach 2. Vice Point 3. Downtown 4. Little Haiti 10) Policie, Sanitka, Pizza, Hasiři, Taxi a Rifle Range 1. Nasbírat alespoň 45 bodů v Rifle Range 2. Dokončit 12 požárnických misí 3. Dokončit 12 misí se sanitkou 4. Dokončit 12 misí za policisty 5. Dokončit 10 misí rozvážky pizzy 11) Ostatní 1. Najít 100 balíčků 2. Vykonat 35 výtržností/rampages 3. Skočit 36 unikátních skoků 4. Vyloupit 15 obchodů
  25. návod Úvod do OOP #1

    Úvod do OOP #1 Obsah: Úvod Pojmy Závěr 1. Úvod Jenom bych chtěl předem říci, že téma popisuji s nadsázkou, proto pokud objevíte nějakou blbost/nedostatek, tak mi to okomentujte a opravím/přidám. Co vlastně OOP je? Jedná se o Objektově-orientované programování a je jedním z nejvyužívanějších programovacích paradigmat1. Těch paradigmat je spoustu, určitě jste zaslechli o procedurální2, logické3 nebo funkcionální4 a další a další. Než si uvedeme nějaké základní pojmy, bylo by fajn si říct jaké jsou vlastně výhody OOP. Hlavní výhodou OOP je snažší údržba, rychlejší vývoj aplikace (z hlediska týmového), méně chybovost a rychlá orientace. Nevýhody – koncept třídy (vysvětlíme si později pojem) jedné osoby nemusí být sympatické té druhé. Většinou se proto dává důraz na to, že třídy se snaží být co nejvíce nezávislé nezasahujíc do něčeho co nemá zasahovat/co nemá v popisu práce. Dále chybou je zneužívání OOP, vytváření různých tříd na vše možné, co člověka napadne a špatně využití zapouzdření. Prakticky třídy vyžadují ohromnou dokumentaci a přípravu. 1 jednají se o styl, koncept a principy programování 2 nebo také imperativní – hlavní charakteristikou je výpočet pomocí posloupností příkazů a určuje přesný postup, např. C, PHP atd. Dělí se ještě do dalších podskupin, ale ty řešit nebudeme. 3 vyhodnocování matematickou logikou, např. prolog 4 matematické funkce a jejich výpočetní vyhodnocování – lambda kalkul, lisp, Zpravidla se jednají o rekurentní výpočty. 1. Pojmy Třída (class) je abstrakce entity, popisuje datový typ. Udává nám jaké vlastnosti (členy) bude mít objekt (také jako instance třídy případně proměnné). Mezi vlastnostmi se zařazují členské proměnné (atributy, položky, attributes) a interface také jako členské funkce (metody, methods). Třídy se mohou i libovolně skládat resp. objekt třídy x je členskou proměnnou třídy y. Na následujícím příkladu si všechny tyto pojmy ukážeme a vysvětlíme. Příklady se pokusím vždy co nejvíce předvádět objektivně (jelikož deklarace tříd apod se liší v závislosti v jakém jazyku programujete), pro upřesnění se budu spíše držet syntaxe C++ (nejsou avšak korektní). Uvedený příklad budu postupem času rozšiřovat dle nových pojmů co si zavedeme. Na OOP samozřejmě také existují spoustu prog. konvencí, ačkoliv v téhle kapitole se jich držet nebudeme kvůli znázornění základních pojmů Př. Zvolme třídu Web. Jeho atributy bude návštěvnost, url a majitel webu, který je objektem třídy Osoba. Obsahuje jen jednu členskou metodu IncreaseTraffic a to na inkrementaci návštěvnosti. Třída Osoba obsahuje jméno, věk a víceméně pohlaví. class Osoba { /* Member variables */ string name; int age; bool gender; } class Web { /* Member methods */ IncreaseTraffic(); /* Member variables */ int traffic; string url; Osoba owner; } /* V závislosti na jazyk, ve kterém programujeme může definice členských metod být jinačí. Pro přehlednost vždy definici funkce budu dávat vně tříd */ IncreaseTraffic() { ++traffic; } /* Deklarace objektu pak vypadá:*/ Web pawnocz = new Web(); /* alokace objektu Webu s názvem pawnocz */ pawnocz.url = "pawno.cz"; /* k jednotlivým atributům/metodám se přistupuje pomocí tečkové notace případně šipkové (např. v PHP). Zde nastavujeme atribut */ pawnocz.owner.name = "chytrak" /* nastavování členských proměnných objektu owner (patriot Print) */ pawnocz.IncreaseTraffic(); /* voláme funkci IT(); k pawnocz Konstruktory a destruktory. Co to je? Konstruktor se deklaruje jako metoda a volá se vždy při vytvoření objektu1. Tzn když jsme deklarovali objekt pawnocz, zavolal se konstruktor. Ten ale nemáme deklarovaný ani definovaný, proto si zpravidla kompilátor vygeneruje sám2. Obecně o konstruktorech je toho hrozně moc informací, ale v základní verzi si uvedeme jen inicializační bez parametrů a s parametrama. Destruktor se naopak volá při zaniknutí objektu. Dobré zmínit je, že konstruktor nelze explicitně volat na existující objekt. 1 poctivému čtenáři může v tuhle chvíli dojít, že při vytvoření objektu pawnocz se také a dokonce jako první zavolal konstruktor Osoba 2 pro zajímavost, C++ dokáže vytvořit inicializační konstruktor na vynulování proměnné. v Javě naopak vytvoří prázdný konstruktor. Více informací o C++ konstruktoru – http://en.cppreference.com/w/cpp/language/initialization Pojďme rozšířit náš příklad. Destruktor a konstruktor se deklaruje v závislosti na jazyku (např v PHP __construct, __destruct). Pro zpřehlednění si smažeme třídu Osobu a změníme majiteli datový typ. class Web { /* Constructor & destructor */ Web(); /* konstruktor MUSÍ mít stejný název jako třída a NEMÁ návratovou hodnotu */ ~Web(); /* pro destruktor platí to co u konstruktoru, akorát před názvem je '~' */ IncreaseTraffic(); int traffic; string url; string owner; } Web() { traffic = 50; } /* inicializační konstruktor bez parametru */ IncreaseTraffic() { ++traffic; } Web pawnocz = new Web(); /* při alokaci webu je nyní traffic rovna 50 */ pawnocz.url = "pawno.cz"; pawnocz.owner = "chytrak" pawnocz.IncreaseTraffic(); První větším pojmem, které se setkáme při OOP je zapouzdření (anglicky encapsulation). Jak jsem již trochu nastínil nějaké settery a gettery. Jedná se vlastně o viditelnost neboli přístup k členům třídy. Dělíme do tří skupin – public, private, protected. Public znamená, že je přístupná komukoli v programu. Private je přístupná POUZE a JEN POUZE v dané třídě (neplést si to s objekty). K protected dojdeme později, jelikož ještě neznáme pojem dědění. Pojďme si zase rozšířit náš příklad. V našem příkladu použiji C++ encapsulation, jelikož mi přijde takové hezčí na uvedení. Pro poznámku, třída v C++ je implicitně privátní, zpřístupníme informace tím, že viditelnost označíme jinak. Víc na příkladech class Web { public: /* veřejná viditelnost – implicitně (tedy defaultně) je private a nepíše se tam. */ Web(); /* konstruktor a destruktor musí být vždy PUBLIC */ ~Web(); IncreaseTraffic(); /* v Javě se nedělí na viditelnost jako v C++, ale označuje klíčovým slovem public/private/protected před metodou případně u proměnných. Viz public IncreaseTraffict(); */ string owner; private: /* privátní */ int traffic; /* v Javě private int traffic */ string url; } Web() { traffic = 50; } /* inicializační konstruktor bez parametru */ IncreaseTraffic() { ++traffic; } Web pawnocz = new Web(); pawnocz.url = "pawno.cz"; /* CHYBA, proměnná url se nachází v private sekci */ pawnocz.IncreaseTraffic(); /* VALIDNÍ KROK, metoda se nachází v public sekci */ pawnocz.owner = "chytrak"; /* VALIDNÍ KROK, proměnná owner je v public sekci */ Jak zpřístupnit privátním informacím ostatním? Tím že pro členskou proměnnou si vytvoříme getter a setter. Setter a getter zní možná sofistikovaně, ale není to nic jiného než obyčejná metoda na čtení případně zapisování. Teď ale přichází kámen úrazu – a to zbytečně vytváření setterů a getterů. Vytvoříme-li setter a getter pro privátní proměnnou, rovnou ji můžeme nechat zviditelnit celou. Proto je tady potřeba pořádně promyslet zda-li vůbec potřebujeme settery a gettery. Samozřejmě pokud máme proměnnou, kterou nechceme aby nám někdo cizí měnil obsah, postačí nám pouze getter pro čtení informací. Občas nechceme vůbec aby nám někdo četl informace, v tu chvíli nepotřebujeme ani jednu z metod. int getTraffic() { return traffic; } string getUrl(string u) { return url; } void setOwner(string o) { owner = o; } Pojďme si ještě zmínit klíčové kouzelné slovo this. Jedná se o proměnnou (většinou reference) na danou instanci nad kterou pracujeme. Používá se pro upřesnění s jakým objektem pracujeme, např pro rozlišování proměnné instance od parametru. Občas se hodí i předávat danou instanci dál v metod. Zároveň si rozšíříme příklad o konstruktoru s parametrem. class Web { public: Web(int traffic, string url, string owner); /* rozšířili jsme konstruktor o tři parametry */ ~Web(); IncreaseTraffic(); int getTraffic(); string getUrl(); setOwner(string owner); private: string url; int traffic; string owner; /* jenom drobná změna, owner jsme přesunuli mezi private */ } Web(int traffic, string url, string owner) { /*Vtip je v tom, že náš parametr se jmenuje stejně jako naše členská proměnná, tak jak to vyřešit? Můžeme přistoupit k proměnné slůvkem this->traffic = traffic; Pro zamezení tohoto konfliktu osobně třeba používám prefix "m_" --> tedy přejmenovat to na m_Traffic = traffic; */ this->traffic = traffic; /* v c++ se jedná o pointer, v javě reference. v PHP $this->traffic; */ this->owner = owner; this->url = url; } IncreaseTraffic() { ++traffic; } int getTraffic() { return traffic; } string getUrl() { return url; } void setOwner(string owner) { this->owner = owner; } Web pawnocz = new Web(50,"pawno.cz","chytrak"); /* voila, závorka není nic jiného než konstruktor. Lze vytvořit i lokální objekty Web pawnocz(50,"pawno.cz");, const Web pawno(50,"pawno.cz");...*/ print pawnocz.getUrl() + " má " + pawnocz.getTraffic() + " návštěvnost."; /* pawno.cz má 50 návštěvnost */ pawnocz.IncreaseTraffic(); pawnocz.setOwner("Lukáš Valenta"); /* už se nám nelíbilo, že je chytrak majitelem webu. */ Metody i proměnné můžou být static. Co to pro nás znamená? Co se týče metod, tak jsou podobné běžným funkcím, nemají implicitní instanci ani implicitní členské proměnné, ani this nejsou k dispozici. Jediné plus je mají přístup k třídním proměnným a volat třídní metody. Statické třídní proměnné jsou sdíleny instancemi třídy, a jsou dodržována standartními pravidly zapouzdření. Statické metody ani proměnné nás ale teď nezajímá. Zbývá nám ještě projasnit si tři základní pojmy – protected, polymorfismus a dědičnost Dědičnost slouží k vytvoření nových datových typ na základě něčeho čeho už máme. Proč jsem si nechal encapsulation protected až teď? Protected je víceméně private plus navíc to, že se věci pod touto viditelností dědí do ostatních podtříd. Pro znázornění využijeme třídu Osoba, kterou jsem si hezky nadeklaroval na začátku a rozšíříme ji o metodu pozdrav. Na tento příklad později navážeme polymorfismus. Vysvětlíme si příklad, chceme třídu Cech a Nemec a ty budou dědit Osoba, která se bude chovat jako abstraktní třída1. Každý vždy bude mít navíc členskou proměnnou a každý umí jen svůj jazyk. 1 abstraktní třída je třída, která nemá svoji implementaci a chová se jen čistě jako rozhraní pro třídy, které ho budou dědit. Na abstraktní třídy nelze vytvořit instance. Abstraktní třídy jsou užitečné, pokud víme, že všechny zděděné třídy jsou schopny provést implementaci abstraktních metod class Osoba { public: Osoba(); ~Osoba(); void pozdrav() = 0; /* = 0; znamená, že označujeme pozdrav() za abstraktní metodu v c++. V Javě a PHP je označení klíčovým slůvkem "abstract" před "class" */ protected: string name; int age; bool gender; } /* v Javě class Cech extends Osoba, v PHP tuším taky */ /* v C++ lze využít klíčové slovo public/private nebo vůbec nic. V případě public znamená, že ponechává vidtelnost zděděných věcí. Private je, že zděděné věci nemají viditelnost mimo této třídy a zakazuje polymorfismus */ class Cech : public Osoba { public: Cech(); ~Cech(); string getFavouriteBeer(); private: string favouriteBeer; } class Nemec: public Osoba { public: Nemec(); ~Nemec(); bool hasMustache(); private: bool mustache; } Polymorfismus umožňuje pracovat a používat jednotné rozhraní pro více (podobných) typů objektů. Podstatou polymorfismu je, zajistit přehlednost, jednoduchost jednotně pracovat se třídy velmi podobné, avšak trochu se lišící. Dokonce jsme si připravili rozhraní (viz výše Osoba) a poděděné třídy. Naším cílem je zajistit volání z databáze Osob1 takovým způsobem, aby každá osoba své národnosti volal svůj pozdrav2. 1 přeskočíme-li řeči o dynamických a statických vazeb, tabulce virtuálních metod neboli VMT (c++), zjišťování instance (java) 2 abychom nemuseli složitě zjišťovat jakou instancí jaké třídy, ale stačí volat a nechat na běhu programu ať si zvolí metodu sám. // Kód v C++ Osoba ** arr = new Osoba*[20]; for ( int i = 0; i < 20; i ++){ if(rand % 2 == 0) arr[i] = new Cech; else arr[i] = new Nemec; } for( int i = 0; i < 20; i ++) arr[i]->pozdrav(); // Guten tag / Ahoj v závislosti na random for( int i = 0; i < 20; i ++) delete arr[i]; // nesmíme zapomenout na uvolňování :-) 2. Závěr Tak došli jsme úspěšně ke konci. V dnešní kapitolě jste si doufám odnesli nějaké základy o OOP a jeho základní pojmy (zapouzdření, polymorfismus, dědění,...). Pokud máte v něčem nejasno, neváhejte a zeptejte se. Polymorfismus jsem trochu odbil, takže se za to omlouvám, ale snad jsem Vám nastínil trochu tý černé magie okolo ní. Pokud byste si přáli o ní něco více vědět, tak editnu trochu příklad a rozšířím ji. Pokud jsem něco uvedl špatně, prosím napište mi to. Pokud jsem na něco zapomněl, také mi to napište. Každopádně se s Vámi loučím a snad jsem někoho zaujal vyzkoušet si OOP.
×