* Register   * Advanced search 
Search for:


Post new topic Reply to topic Board index » Offtopic
Author Message
PostPosted: Sun May 26, 2013 10:53 am
 
Master
Master
User avatar

Joined: Sat Jun 21, 2003 2:21 pm
Posts: 904
Online: 1652:13:32
Status: banned
Reg. players: 0
Překlad Racalacova tutoriálu v0.6d: 19/02/2009. Upozornění na chyby v překladu a případné připomínky vítány.

Tutorial byl rozdělen na dvě části z důvodu maximálního povoleného počtu znaků na post (60000). Tato první část obsahuje kapitoly 1-10. Druhou naleznete v následujícím postu, nicméně lze se na ní odkazovat i z obsahu uvedeného zde.

Předmluva

Tento tutorial je cílený na scriptery, kteří mají alespoň nějakou předchozí zkušenost s jiným procedurálním programovacím jazykem. Pokud jste nikdy dříve neprogramovali ani nescriptovali, doporučuji se na vaší škole podívat po předmětu, kde je vyučován Basic nebo Pascal. Pokud nestudujete příslušnou vysokou školu, popřemýšlejte o zakoupení knihy zabývající se programováním pro začátečníky. Jakákoliv ze zmíněných metod vám umožní se naučit se eScript snadněji a rychleji. Na druhou stranu se předem omlouvám, pokud některé věci vysvětluji otravně, v jednoduchých termínech.

Obsah

Kapitola 1
Kapitola 2: Stručný přehled datových struktur
Kapitola 3: Podmínky a iterace
Kapitola 4
Kapitola 5
Kapitola 6: Vestavěné atributy a POL objektová reference
Kapitola 7
Kapitola 8: Použití konfiguračních souborů a přístupnost
Kapitola 9: Balíčky
Kapitola 10: Debugování
Kapitola 11: Pokročilé datové struktury a funkce
Dodatek A: Popis příznaků gumpů

Kapitola 1

Deklarace proměnné a přiřazení

Skriptovací jazyk eScript je slabě typovaný. To znamená, že v eScriptu nejsou žádné typy proměnných. Nicméně proměnné lze přetypovat (překonvertovat) do několika datových typů: integer (celé číslo), real (reálné číslo; číslo s plovoucí desetinnou čárkou) a string (řetězec). Je jednoduché deklarovat novou proměnnou:
Code:
var moje_promenna;

Podle toho, kde ve vašem programu takto deklarujete proměnnou, k ní můžete přistupovat. To se nazývá rozsah proměnné. Pokud řádek uvedený výše umístíte mimo funkční blok, je viditelný všem funkcím v programu (známé jako globální proměnná). Pokud zmíněný řádek umístíte dovnitř funkčního bloku, proměnná je dosažitelná všude v tomto bloku. Pokud deklarujete proměnnou uvnitř bloku kódu (tedy mezi if-endif, for-endfor atd.), je použitelná pouze v rámci tohoto bloku.

Poznámka: Ve starších scriptech můžete vidět proměnné deklarované s klíčovými slovy 'local' a 'global'. První zmiňované znamená to samé, jako 'var' uvnitř funkce a druhé zmiňované je to samé, jako 'var' mimo funkci. Měli byste k deklaraci vašich proměnných vždy používat 'var' namísto těchto starších klíčových slov.

Fajn, nyní jsme si opatřili proměnné. Teď si vysvětlíme, jak do nich vložit nějaká data, abychom je mohli použít ve skriptu. Toto můžete uskutečnit v čase deklarace nebo kdykoliv později ve skriptu. Syntaxe tohoto úkonu je následující:
Code:
moje_promenna := 10;

Operátor ":=" (dvojtečka + rovnítko) přiřazuje výraz vpravo do proměnné vlevo. Výraz může mít mnoho podob. Může obsahovat čísla (jak je uvedeno v kódu výše), jiné proměnné, matematické výrazy, volání funkce aj. Přiřazení můžete provést v času deklarace: var pocet_kolacu := 15;

Deklarovat konstantu, neboli proměnnou ze které lze pouze číst, musíte na začátku souboru, před všemi funkcemi, podobně jako když deklaruejte globální proměnnou. Konstanty jsou totiž také globální. Kdykoliv překladač vidí konstantu ve výrazu, je nahrazena její hodnotou. Následuje syntaxe tohoto úkonu:
Code:
CONST MOJE_KONSTANTA := 47;

Použití konstant je klíčem k dobře psanému, čitelnému kódu. Odstraňují nejasnost přítomnosti hrubých čísel (tzv. magických konstant) ve scriptu tím, že jim dávají význam. Je dobrý nápad se držet zvyklosti deklarovat konstanty VELKÝM PÍSMEM. Většina programátorů je takto navyklá.

Příklad kusu kódu (moc toho nedělá, ale ukazuje různé možnosti, jak deklarovat proměnné):
Code:
CONST VELIKOST_TACU := 15;
var kolacu_na_tacu := VELIKOST_TACU;

Aritmetika

Toto je jednoduché, výraz vpravo od přiřazovacího operátoru je vyhodnocen a vložen do proměnné vlevo. Matematické operátory v eScriptu jsou následující:
  • '+' - Sčítání
  • '-' - Odečítání
  • '*' - Násobení
  • '/' - Dělení
  • '%' - Modulo neboli zbytek po dělení
  • '>>' - Bitový posun vpravo
  • '<<' - Bitový posun vlevo
Výrazy v závrkách jsou vyhodnoceny nejdříve. Následuje vyhodnocení zleva doprava. Takto:
Code:
var pouzite_kolace := pouzite_kolace + 1; // Inkrementuje 'pouzite_kolace' o 1
var zbyvajici_kolace :=  pocet_tacu * (kolacu_v_tacu – pouzite_kolace);

Měl bych zmínit něco o typech proměnných v aritmetice, speciálně u dělení. Pokud dělíte dva integery tak, že výsledek by měl desetinnou část, POL bude brát v potaz pouze celou část. Pokud si chcete být jistí, že výsledek bude reálné číslo (integer + desetinná část), ujistěte se, že alespoň jeden z operandů je reálné číslo. To můžete udělat uvedením celého čísla s desetinnou částí (např. 100.0) nebo přetypováním (konverzí) na reálné číslo. V eScriptu je několik funkcí určených k přetypování, CInt(), CStr(), CDbl().
Code:
CInt(100.3) // Výsledek je 100
CStr(100);  // Výsledek je řetězec "100" Ten nyní nemůže být použit v matematických výrazech
CDbl(100);  // Výsledek je 100.0

Další funkce určené ke konverzi, obsažené v basic.em:
Code:
Hex(100);  // Výsledek je řetězec "0x64"
Bin(100);  // Výsledek je řetězec "1100100" - CInt() toto nepřekonvertuje správně do desítkové soustavy
CAsc("A"); // Výsledek je integer 65
CChr(65);  // Výsledek je řetězec "A"


Komentáře

Komentování vašeho kódu je velmi důležité. Komentáře vám umožňují přidat jakýkoliv text k vysvětlení čehokoliv, co potřebujete, aniž byste narušili funkcionalitu skriptu. Komentáře jsou také často používány k zneplatnění kusu kódu, aniž byste ho museli skutečně odstranit (známé jako "zakomentování kódu"). V eScriptu jsou dvě možnosti jak vkládat komentáře do vašeho kódu:
  • Jakýkoliv text po "//" do konce řádku je považován za komentář. Další řádky už za komentáře považované nejsou. Abyste z nich komentář udělali, musíte vždy na začátku řádku opět přidat "//". Toto je dobré řešení pro krátké komentáře. K Zakomentování většího bloku kódu využijte "/* */" (viz níže).
  • Veškerý text po "/*" a před "*/" je považován za komentář. Použitím těchto dvou značek můžete zakomentovat velké bloky kódu jednoduše umístěním "/*" na začátek a "*/" na konec kódu. Tento typ komentáře nelze zanořovat, protože "*/" signalizuje konec komentáře, přestože za ním později může následovat další "*/". Pokud se tomuto problému chcete vyhnout, doporučuji komentovat většinu kódu pomocí "//".
Kapitola 2

Dobrá, takže umíme vytvořit proměnné typu integer, real a string. K jakémukoliv netriviálnímu scriptování ale budeme potřebovat také datové struktury. V této kapitole si popíšeme pole, struktury a slovníky.

Pole

Pole jsou kolekce objektů s přímým přístupem. Objekty jsou v poli seřazené na pozicích od 1 (první element) až do X (poslední element). Ke kterémukoliv objektu v poli lze přistupovat pomocí tzv. indexu. Deklarovat pole můžeme několika způsoby:
Code:
var a := array;                           // Prázdné pole (array)
var b := array{5, 32, "ahoj", "svete"};   // Inicializované pole
var c := array{array{1,2}, array{3,4,5}}; // Pole obsahující další pole

Pole může být přiřazeno jakékoliv jiné proměnné, a to i pokud tato proměnná nebyla deklarovaná jako pole:
Code:
var a := array{2, 4, 6, 8};
var b;
b := a;

Podobně, pokud funkce vrací pole (tímto se budeme zabývat později), není potřeba žádná speciální deklarace:
Code:
var a;
a := FunctionThatReturnsAnArray();

V některých jiných programovacích jazycích nelze přistupovat (číst nebo zapisovat) za konec pole deklarované velikosti. V eScriptu pole automaticky rostou bez jakýchkoliv chybových hlášení:
Code:
var a := array;
a[1] := 4;
a[4] := 7;

Elementy pole mohou být jakéhokoliv typu objektu, včetně dalšího pole:
Code:
var a := array{};
var b := array{};
a[1] := 5;
b[1] := a;
b[2] := 6;

Následující kód popisuje dvě ekvivalentní metody průchodu polem. Použití 'foreach' je mnohem vhodnější a efektivnější. Smyčkami obecně se budeme zabývat v další kapitole.
Code:
var a := array{2,4,6,8};

var i;
for(i:=1; i<=a.Size(); i:=i+1)
  Print(a[i]);
endfor

foreach i in ( a )
  Print(i);
endforeach

Pole můžete použít k různým účelům. Předávání více než jedné proměnné funkci (funkce jsou vysvětlené později) apod. Existuje také několik speciálních funkcí vztahující se k poli (array.Insert() a další). O těch si také povíme později.

Struktury

Struktury jsou objektově orientované datové typy s různými prvky nebo atributy, které jsou jejich součástí a které obsahují vlastní data. K přístupu k prvkům struktury použijte '.' operátor.
Code:
Print(a.vyska);
Print(a.sirka);

Struktura se deklaruje takto:
Code:
var a := struct;                            // Prázdná struktura
var b := struct{"vyska", "sirka"};          // Struktura s prvky, které ale nemají žádné hodnoty
var c := struct{"vyska":=5, "sirka":=100};  // Struktura s inicializovanými prvky

K přidání nových prvků použijte '.+' operátor:
Code:
var a:= struct;
a.+vyska := 7;
a.+sirka;

// Přiřazení hodnoty existujícímu prvku struktury
a.sirka := 5;


Slovníky

Slovníky jsou pole, jejichž elementy jsou pojmenovány. Často jsou označovány jako 'asociativní pole'.
Code:
Print(a["vyska"]);
Print(a["sirka"]);

Slovníky deklarujeme takto:
Code:
var a := dictionary;                            // Prázdný slovník
var b := dictionary{"vyska", "sirka"};          // Slovník s indexy, které nemají hodnoty
var c := dictionary{"vyska"->5, "sirka"->100};  // Slovník s indexy a hodnotami

Slovníky automaticky vytváří nové indexy, pokud jsou použity.
var a:= dictionary;
Code:
a["vyska"] := 7;
a["sirka"] := 100;

Kapitola 3

V této kapitole pokryjeme dvě témata. Podmíněný příkaz a smyčky

Podmíněný příkaz

Podméněné příkazy (If-příkazy) jsou potřeba v každém skriptu, takže je nutné, abyste jim rozuměli. Podmíněný příkaz vašemu skriptu jednoduše umožňuje dělat rozhodnutí na základě kriterií, která jste jim dali. Obecná syntaxe je následující:
Code:
if(vyraz)
  // kód
elseif(vyraz)
  // kód
elseif(vyraz)
  // kód
else
  // kód
endif

Všimněte si, že můžete mít jakýkoliv počet (volitelných) "elseif" větví mezi "if" a (volitelným) "else". Klíčovou částí v syntaxi výše je "vyraz". Když skript běží a dostane se k podmíněnému příkazu, zkontroluje, zda-li je první "vyraz" pravdivý. Pokud ne, pokračuje k dalšímu "vyrazu", dokud nenalezne některý, který je pravdivý nebo nenarazí na "else" větev (pokud taková existuje). Syntaxe "výrazu" je:
Code:
variable1 {operator variable2} ...

Některé příklady, které jsou vyhodnoceny jako pravdivé výrazy:
Code:
var var1 := 10;
var var2 := 5;

if (var1 > var2)  //TRUE (PRAVDA)

if ((var1 – 5) == var2) //TRUE (PRAVDA)

if (var2 < var1) //TRUE (PRAVDA)

if ((var2+5) >= var2) //TRUE (PRAVDA)

if (var1 != var2) //TRUE (PRAVDA)

Logické operátory v eScriptu (vyhodnocováno zleva doprava):
  • '==' - Shodnost
  • '!=' - Neshodnost
  • '>' - Větší
  • '<' - Menší
  • '<=' - Menší nebo rovno
  • '>=' - Větší nebo rovno
  • '&& nebo 'and'' - Logické AND (Výraz je pravdivý, pokud jsou oba podvýrazy pravdivé
  • '|| nebo 'or'' - Logické OR (Výraz je pravdivý, pokd je alespoň jeden z podvýrazů pravdivý
Příklady:
Code:
if ( (var1 > var2) || (var1 == 5) )
  // TRUE (PRAVDA) protože alespoň jeden z individuálních podvýrazů je pravdivý.
  // Toto je exklusivní OR, takže všechny podvýrazy mohou být pravdivé a výsledný výraz je také pravdivý.
 
if ( (var1 > var2) or (var1 ==5) )
  // Toto je stejný výraz, jako ten výše. Pouze je použito "or" namísto "||" pro potenciálně lepší čitelnost.
 
if ( (var1 > var2) && (var1 == 5) )
  // FALSE (NEPRAVDA), protože ne všechny podvýrazy jsou pravdivé
 
if ( (var1 > var2) and (var1 == 10) )
  // TRUE (PRAVDA), protože oba podvýrazy jsou pravdivý. Používá "and" namísto "&&".

Podmíněné příkazy budete používat ve všech, kromě těch nejjednodušších scriptů. Měli byste si ujasnit, co chcete udělat, než použijete podmíněný příkaz. Je jednoduché udělat chybu:
Code:
if ( score < 60 )
  Print("Mas mene nez 60");
elseif ( score == 50 )
  Print("Mas 50!");
endif

Toto je špatný příklad skriptování, protože pokud byste skutečně měli 50, první výraz by byl pravdivý (Vytiskl by "Máš méně než 60") a do větve elseif(score == 50) by se pak běžící skript nikdy nedostal, přestože to je více specifická kontrola než ta předchozí.

V eScriptu je jakýkoliv výraz, který je vyhodnocený jako nula považován za nepravdu (false) a jakýkoliv, který je vyhodnocen jako nenulový, je považován za pravdu (true). Můžete tak mít podmíněný výraz bez jakýchkoliv logických operátorů:
Code:
var platnost := 1;
if ( platnost )
  // Delej neco
else
  // Delej neco jineho
endif

nebo:
Code:
if ( !platnost ) // To samé jako "pokud je platnost nenulová, výsledek je nepravda"
  // Delej neco
endif

Case (switch) příkaz

Při skriptování se běžně objevuje situace, kdy potřebujete vytvořit podmíněný příkaz na základě velkého množství možností (a tyto možnosti jsou známé v čase kompilace). Vytvořit něco takového pomocí kaskády if-elseif příkazů by bylo ošklivé a k tomu ještě pomalé. Naštěstí eScript poskytuje čistější cestu:
Code:
// Deklarace konstant
const MODRA := 1;
const ZLUTA := 2;
const CERVENA := 3;
const FIALOVA := 4;

// Ošklivá if-elseif metoda:

function FunkceJedna()
  var odpoved := JakaJeTvaOblibenaBarva();
  if ( odpoved == MODRA )
    // neco delej
  elseif ( odpoved == ZLUTA )
    // neco delej
  elseif ( odpoved == CERVENA )
    // neco delej
  elseif ( odpoved == FIALOVA )
    // neco delej
  else
    // delej neco jineho
endfunction

// Cistejsi metoda vyuzivajici "case"

function FunkceDve()
  var odpoved := JakaJeTvaOblibenaBarva();
  case ( odpoved )
    MODRA:
      // delej neco
    ZLUTA:
      // delej neco
    CERVENA:
      // delej neco
    FIALOVA:
      // delej neco
    default:
      // delej neco jineho
  endcase
endfunction

Obecná struktura case příkazu je:
Code:
case ( vyraz )
  hodnota_k_porovnani:
    // kod
    break;
  hodnota_k_porovnani:
    // kod
    break;
  ...
  default:
    // Kod, pokud zadna z vyse uvedenych hodnot k porovnani neodpovida porovnavane hodnote (volitelna vetev)
    break;
endcase

"vyraz" může být vyhodnocen za běhu skriptu, ale "hodnota_k_porovnani" musí být známá v čase kompilace. To znamená, že case příkaz je dobrý pouze k učinění rozhodnutí na základě jakéhokolilv počtu předem známých konstant. "hodnota_k_porovnani" nemůže být žádný typ výrazu, který je vyhodnocován za běhu skriptu (což jsou např. matematické výrazy). Case příkaz může být použit pouze k porovnáním, které jsou založené na ekvivalenci (Nelze použít porovnání na základě '>=', '<=', '<', '>', ...). 'break' příkazy jsou volitelné. Pokud není "hodnota_k_porovnani" následována žádným kódem (jinými slovy je za ní hned další "hodnota_k_porovnani") a ta další "hodnota_k_porovnani", kódem následována je, obě možnosti spustí tento kód.

Příklad:
Code:
function FunkceTri()
  var odpoved := JakaJeTvaOblibenaBarva();
  case ( odpoved )
    MODRA:
    ZLUTA:
      // neco delej
    CERVENA:
      // delej neco jineho
    default:
      // delej neco jeste jineho
  endcase
endfunction

V této situaci obě MODRA i ZLUTA spustí kód "neco delej". CERVENA spustí kód "delej neco jineho" a kterákoliv jiná odpověď spustí kód "delej neco jeste jineho". Pokud jste chtěli, aby MODRA nedělala vůbec nic, musíte použít "break" příkazy v sekcích, u kterých chcete, aby nic neprováděly. Příkaz 'break' řekne programu, aby skočil na konec case bloku. Chování v případě prázdného bloku (jak je vidět u části MODRA výše) je známé jako propadávání.

Iterace

V minulé kapitole jsem zmínil "průchod polem". To je ve většině skriptů velmi častá operace. Jsou dvě oblíbené možnosti, jak průchod polem implementovat. Následující kusy kódu známe již z dřívějška:
Code:
var a := array{2,4,6,8};

var i;
for ( i:=1; i<=a.Size(); i:=i+1)
  Print(a[i]);
endfor

Výstup tohoto kódu:
Code:
2
4
6
8

Smyška for by měla být známá každému, kdo má již nějaké zkušenosti s programováním. Její syntaxe je následující:
Code:
for (inicializace ; podmínka cyklu; inkrementace)
  // kod
endfor


V iniciliaziační i inkrementační části můžete použít jakýkoliv kód. Toto pojmenování pouze ukazuje nejčastější použití. Obvykle je for-smyčka cyklus s konečným počtem opakování. Na konci každého kola cyklu se automaticky provede inkrementace. Následně se zkontroluje podmínka cyklu a pokud je pravdivá, pokračuje se dalším kolem cyklu. Pokud pravdivá není, cyklus skončil. V uvedeném příkladu je dekolarována proměnná "i". Před prvním kolem for-smyčky je "i" inicializována na hodnotu 1. Pokud je hodnota "i" menší nebo rovna délce pole "a", je proveden kód uvnitř for-bloku. Na konci for-bloku je provedena inkrementace přidáním 1 k hodnotě proměnné "i". Následně je hodnota "i" opět porovnána s délkou pole "a" (v příkladě výše je jeho délka 4). Hodnota "i" je tedy stále nižší než délka pole "a" a kód uvnitř for-bloku je tak znovu proveden. Takto to pokračuje, dokud hodnota "i" není vyšší než délka pole. Klíčové slovo endfor signalizuje konec for-bloku.

Jiná, více praktická metoda je ukázána v dalším příkladu:
Code:
foreach i in ( a )
  Print(i);
endforeach

Zde nemusíme inicializovat 'i'. foreach-smyčka to udělá za nás. Tato smyčka provádí stejnou operaci jako for-smyčka výše, ale mnohem stručnějším (a efektivnějším) způsobem. Obecná syntaxe je:
Code:
foreach promenna in ( jmeno_pole )
  // kod
endforeach

Při použití foreach-smyčky vzniká skrytá proměnná _promenna_iter, která uchovává informaci, v které iteraci (kole cyklu) se nacházíte.
Code:
var a := array{"A", 1000};
foreach value in ( a )
  Print(_value_iter);
  Print(value);
endforeach

Výstup tohoto kódu:
Code:
1
A
2
1000

Posledním typem for-smyčky je styl známy z programovacího jazyka basic.
Code:
for i:=0 to 3
  Print(i);
endfor

Výstup kódu:
Code:
0
1
2
3

Dalším typem smyček, které eScript podporuje je while-smyčka, která provádí kroky cyklu, dokud je podmínka cyklu splněná.
Code:
while ( podminka )
  // kod
endwhile

Je třeba si uvědomit, že pokud v kódu cyklu nějak nezměníte pravdivost podmínky (např. změnou hodnoty proměnných v ní obsažených) nebo nepoužíjete speciální klíčová slova (viz níže) cyklus nikdy neskončí.

Dalším typem smyčky je repeat–until-smyčka. Je velmi podobná while-smyčce až na fakt, že garantuje, provedení kódu cyklu alespoň jednou, protože kontrola podmínky je provedena vždy na konci bloku cyklu. Kód repeat–until-smyčky je prováděn dokud podmínka není splněná.
Code:
repeat
  // kod
until ( podminka );

Podobně lze upravit while-smyčku tak, aby prováděla kontrolu také až na konci bloku cyklu. Kód do-while-smyčky je prováděn dokud podmínka je splněná.
Code:
do
  // kod
dowhile ( podminka );

Pravděpodobně přijdou situace, kdy budete chtít smyčku ukončit dříve, než je podmínka k jejímu ukončení naplněna. K tomu slouží klíčové slovo break umístěné uvnitř bloku cyklu (platí pro for, while, repeat-until). Pokud chcete pouze skočit na konec bloku cyklu a pokračovat dalším kolem cyklu, použijte klíčové slovo continue.
Code:
while ( podminka != 0 )
  if ( podminka == 42 )
    // Sakra ctyricetdvojka, rychle pryc z cyklu!
    break;
  elseif ( condition == 13 )
    // Neprovadej kod pod timto if-blokem a rovnou skoc na dalsi kolo cyklu
    continue;
  endif
  podminka := podminka * neco;
endwhile

Kapitola 4

Funkce a parametry

Dosud jsme si ukazovali pouze segmenty kódu, které nemohou být použity samy o sobě. Všechen kód musí být umístěn uvnitř funkcí. Ty jsou fundamentálními stavebními prvky programování - potenciálně znovupoužitelné sekce kódu. V eScriptu jsou dva typy funkcí: function a program. Pokud jste programovali již dříve, můžeme funkci program přirovnat k funkci main. To znamená, že pokud je skript spuštěn, vstupním bodem (první funkcí, která je spuštěna) je vždy začátek funkce označené klíčovým slovem program. Zde je obecná syntaxe obou typů funkcí:
Code:
program JmenoProgramu(parametr, ...)
  // kod
endprogram

function JmenoFunkce(parametr, ...)
  // kod
endfunction

Klíčová slova endprogram and endfunction označují konec funkce. Jsou naprosto nezbytná a překladač vám bude zobrazovat chybová hlášení (errors), pokud je nepoužijete (více o kompilaci později). JmenoFunkce může být jakékoliv, pokud je to jedno slovo a začíná písmenem.

Seznam parametrů je malinko složitější an vysvětlení. Jsou to jména proměnných, která jsou předána do této funkce odkudkoliv, kde proběhlo její volání. Jako parametr může být zvolen jakýkoliv typ proměnné, dokonce i pole a struktury. Některé příklady budou uvedeny níže. Zapamatujte si, že to, co dělá program (hlavní funkci) speciální je, že vy si nevolíte, jaké parametry jsou do něho předány. Je to totiž systém (v tomto případě jádro POLu), kdo volá funkci program a ten určí, jaké parametry jsou do něj předány. List parametrů funkce program závisí na typu skriptu (o typech skriptů více později). V následujících příkladech předpokládejme, že do hlavní funkce nebyly předány žádné parametry. List parametrů může obsahovat nula nebo více parametrů.

Tady je jednoduchý přáklad, jak můžete vytvářet své vlastní funkce:
Code:
program Main()
  var var1 := "lidi";
  var var2 := "oingo";
  var var3 := "boingo";
  var var4 := "pojdme";
  var var5 := 42;
 
  MojeFunkce(var1, var4); // 1
  MojeFunkce(var2, var3); // 2
  MojeFunkce(var5, var1); // 3
  MojeFunkce(var3);       // 4
  MojeFunkce();           // 5
endprogram

function MojeFunkce(a:= "Yo yo", b := "hey hey")
  Print(a + " " + b);
endfunction

Zde je výstup z pěti zavolání funkce MojeFunkce:
Code:
lidi pojdme
oingo boingo
42 lidi
boingo hey hey
Yo yo hey hey

Všimněte si, že v deklaraci funkce MojeFunkce máme několik parametrů a rovnou i přiřazení hodnot do každého z nich. Pokud pro tyto parametry nejsou předány žádné hodnoty, tak je namísto nich použita hodnota na pravé straně přiřazení, jak je vidět na čtvrtém a pátém řádku výstupu.

Toto je velmi jednoduchý příklad a neukazuje moc, proč byste měli používat více oddělených funkcí namísto nacpání veškerého kódu do jedné velké funkce. Nicméně je to dobrý programátorský návyk rozdělit úlohy do oddělených funkcí z důvodu lepší čitelnosti, znovupoužitelnosti a abstrakce.

Funkce mohou vrátit jednu hodnotu předtím než jsou ukončeny. To je uskutečněno použitím klíčového slova return. Po zavolání funkce získáte tuto hodnotu tím, že na levou stranu operátoru přiřazení umístíte proměnnou a na pravou stranu volání funkce.
Code:
program Main()
  var pozdrav;
  pozdrav := DnesniPozdrav();
  Print(pozdrav);
endprogram

function DnesniPozdrav()
  var dnesek_vysledek := "Zdarec";
  return dnesek_vysledek;
endfunction

Tiskne:
Code:
Zdarec

Aby mohla funkce vrátit více než jednu hodnotu, použijte pokročilé datové typy (pole, struktura, slovnik).
Code:
program Main()
  var pozdrav;
  pozdrav := DnesniPozdrav();
  Print(pozdrav[1]);
  Print(pozdrav[2]);
endprogram

function DnesniPozdrav()
  var dnesek_vysledek := array{"Nazdar", "Lampione"};
  return dnesek_vysledek;
endfunction

Tiskne:
Code:
Nazdar
Lampione

Vkládání kódu z jiných souborů

Doteď byl veškerý kód, s kterým jsme si hráli, v jednom souboru. K použití kódu z jiných souborů (Speciální soubory nazývané "include", jejichž přípona je ".inc". Ty nemohou obsahovat hlavní funkci program, pouze obyčejné funkce function) uveďte na začátku vašeho skriptu, před jakékoliv deklarace proměnných a funkcí, řádek:
Code:
include "jmenosouboru_bez_.inc";

Pak můžete z vašeho skriptu (přípona .src) volat jakoukoliv funkci, která je definována v daném include souboru. Všimněte si, že veškeré proměnné které jsou v daném include souboru deklarované jako globální, jsou globální i ve vašem skriptu. Musite tedy být opatrní, abyste nedeklarovali proměnné se stejnými jmény. V opačném případě překladač zobrazí chybové hlášení, které vás ale často nemusí na tuto chybu navést.

Řádek výše bude fungovat, pokud je daný include soubor ve stejné složce, jako váš skript. Pokud chcete použít některé ze standardních include souborů (Nalezitelné v /scripts/include), použijte syntaxi:
Code:
include "include/jmenosouboru";

Pokud chcete použít include soubor který je v balíčku (package), použijte:
Code:
include ":jmenoBalicku:jmenoSouboru";

Kapitola 5

Radujte se! Teď už se budeme bavit pouze o věcech okolo UO, POLu, *.em souborů a funkcí. Jsem rád že jse vydrželi všechnu tu syntaxi a nezačali hned touto kapitolou. Pokud jste to udělali, hodně štěstí, tady už žádné opakování syntaxe nenajdete.

Skripty

Nyní se začneme učit, jak psát reálné skripty v UO-POL prostředí. Nyní už umíte psát skripty, které něco dělají, ale pravděpodobně ne nic opravdu užitečného. Abyste mohli psát užitečné skripty, musíte být schopni přistupovat k datům herního světa. POL nabízí rozhraní složené z určitého množství "funkcí jádra", které jsou definovány v ".em" souborech. Naleznete je v /pol/scripts/modules složce. ".em" soubory nazýváme moduly (angl. modules).

Nejdříve si ale něco řekneme o typech skriptů v POL prostředí, kdy jsou spouštěny a s jakými parametry. Zde je stručný seznam:

pozn: Jména parametrů jsou pouze příklady, které jsem si vymyslel. Mohou být jakékoliv. Nicméně snažte se, aby byly popisné a výstižné. Neměnné je pouze pořadí parametrů

  • Use Script - Parametery: 1: CharRef uzvivatel, 2: ObjRef predmet_pouzity
    Spuštěn při dvojkliku na daný předmět v UO okně.
  • Walk-on Script - Parametery: 1: CharRef chodec, 2: ObjRef predmet_zaslapnuty
    Spuštěn při stoupnutí postavy na daný předmět.
  • Text Command Script - Parametery: 1: CharRef recnik, 2: Text za prikazem (např. ".command blah" by dal Text "blah")
    Spuštěn, pokud hráč použije příkaz ".jmenoskriptu" a má příslušná privilegia.
  • Spell Script - Parametery: 1: CharRef sesilatel
    Spuštěn, když hráč sešle kouzlo z kouzelné knihy (angl. spellbook).
  • Control Script - Parametery: 1: ObjRef predmet_pod_kontrolou
    Spuštěn při (re)startu serveru, při vytvoření daného předmětu.
  • AI Script - Parametery: 1: MobRef NPC
    Spuštěn při (re)startu serveru, při vytvoření daného NPC. Definuje jeho chování, neměl by nikdy skončit.
  • Skill Script - Parametery: 1: CharRef hrac_pouzivajici_skill
    Spuštěn, pokud hráč použije skill.

CharRef = Reference na postavu, která spustila skript
MobRef = Reference na pohyblivý objekt (NPC, Postava)
ObjRef = Reference na předmět (angl. item)

Začneme s textovými příkazy (angl. Text Command Script), protože jsou nejjednodušší na rozběhnutí. Textové příkazy jsou spuštěny pouze, pokud má hráč používající daný příkaz, příslušná privilegia. Ujistěte se, že postava, s kterou příkaz testujete, je na úrovni GM (většinou úroveň 4) anebo vyšší. Všechny naše skripty budeme umisťovat do složky /scripts/textcmd/gm.

Fajn, začněme s jednoduchým skriptem. Řekněme, že chcete napsat skript, který všem postavám na serveru napíše zprávu. Zde je script "rozhlas.src". Vysvětlím každý řádek:
Code:
/*1*/ use uo;
/*2*/
/*3*/ program MujRozhlas(recnik, text)
/*4*/
/*4*/   foreach postava in ( EnumerateOnlineCharacters() )
/*5*/     SendSysmessage(postava,text);
/*6*/   endforeach
/*7*/
/*8*/ endprogram

Řádek 1: Klíčové slovo use řekne překladači, aby vyhledal následující .em soubor, obsahující definice funkcí, které v našem skriptu použijeme (Podívejte se do daného modulu, najdete v něm funkce EnumerateOnlineCharacters a SendSysmessage).
Řádek 3: Protože toto je Text Command Script, POL automaticky předá referenci na postavu, která příkaz použila a text následující po názvu příkazu. Zde parametry "recnik" a "text".
Řádek 4: Funkce EnumerateOnlineCharacters vrací pole referencí na postavy, které jsou přihlášené do hry na serveru. foreach-smyčka vždy vezme prvek tohoto pole a uloží ho do proměnné "postava".
Řádek 5: Funkce SendSysmessage zobrazí řetězec "text" v levém dolním rohu UO okna hráče, přihlášeného za postavu "postava".
Řádek 6: Klíčové slovo endforeach signalizuje konec foreach-bloku.
Řádek 8: Klíčové slovo endprogram signalizuje konec hlavní funkce skriptu.

Použití skriptu má následující průběh:

1. GM napíše .rozhlas Nazdar vsichni!
2. POL vyhledá script "rozhlas.src" a v něm hlavní funkci program. Do ní předá referenci na GM postavu a text "Nazdar vsichni!"
3. Funkce EnumerateOnlineCharacters vrátí pole o x referencích na postavy.
4. Funkce SendSysmessage zobrazí text "Nazdar vsichni!" v levém dolním rohu UO okna x hráčů.

Ale GM nechce, aby se mu zobrazovaly jeho vlastní zprávy. Můžete upravit váš skript tak, aby se toto nestávalo. Toho dosáhnete kontrolou, zda-li reference na postavu uložená v proměnné "postava" není náhodou stejná, jako reference "recnik", předaná hlavní funkci POLem:
Code:
/*1*/ use uo;
/*2*/
/*3*/ program MujRozhlas(recnik, text)
/*4*/
/*5*/   foreach postava in ( EnumerateOnlineCharacters() )
/*6*/     if ( postava != recnik )
/*7*/       SendSysmessage(postava,text);
/*8*/     endif
/*9*/   endforeach
/*10*/
/*11*/ endprogram

Nyní zpráva nebude zobrazena tomu, kdo jí poslal.

Kompilace

Dobrá, je načase si rozjet svůj první skript. POL nedokáže přímo číst váš zdrojový kód. Než může být spuštěn, musí být nejprve zkompilován (přeložen) do pro něj čitelného formátu. Toto také znamená, že pokud změníte .inc soubor, musíte znovu překompilovat všechny *.src soubory, které ho používají. Ke kompilaci je určen program "ecompile". Budu předpokládat, že máte zkušenosti s příkazovým řádkem vašeho operačního systému. Zde budu používat příkazový řádek MS Windows.

Nejdříve vemte kód uvedený výše a vložte ho do souboru jménem "rozhlas.src". Tento soubor umístěte do složky pol/scripts/textcmd/gm. Nyní se přepněte do příkazové řádky a dostaňte se do složky /pol/scripts. Napište "ecompile /?" a odentrujte. Měli byste dostat seznam možností použití. My nepotřebujeme žádné přepychové příznaky nebo možnosti, postačí nám základní použití programu. Potřebujeme překladači říct, kde se nachází soubor, který chceme zkompilovat. Napište tedy do vašeho příkazového řádku následující:
Code:
ecompile.exe txtcmd/gm/rozhlas.src

Protože to je místo, kam jsme umístili náš skript. Do konzole by se mělo vypsat něco takovéhleho:
Code:
EScript Compiler v1.05
Copyright (C) 1994-2006 Eric N.Swanson
Compiling: D:\pol\scripts\textcmd\gm\rozhlas.src
Writing: D:\pol\scripts\textcmd\gm\rozhlas.ecl

Pokud vám ecompile říká, že zapisuje do .ecl souboru, znamená to, že kompilace byla úspěšná a skript může být spuštěn. Ujistěte se, že POL úspěšně běží a jste přihlášeni za GM postavu (nebo vyšší úroveň, např. admin). Nyní napište .rozhlas Ahoj. Pokud jste vše udělali správně, neměli byste vidět nic. To protože jsme to naskriptovali tak, abychom nepřijímali svůj vlastní rozhlas. Abyste svůj skript otestovali, buď použijte dřívější verzi skriptu, která posílá zprávu i jejímu odesilateli anebo sežeňte pár kamarádů a požádejte je, aby se připojili na váš server. Poté rozhlas použijte znovu. Pokud se jim zpráva zobrazila, gratuluji, vytvořili jste svůj první skript.

Kapitola 6: Vestavěné atributy a POL objektová reference

V POLu je vše objekt: postavy, účty, předměty, mrtvoly, NPC atd.

POL využívá třídní hierarchie, která umožňuje dědit atributy (angl. properties) mezi objekty. Např ve světě UO, vše má x, y a z souřadnice. To zahrnuje předměty i pohybující se objekty (NPC nebo postavy). Z POL třídní hierarchie lze zjistit, že Mobile object i Item object jsou potomci třídy UObject. Všimněte si, že třída UObject obsahuje několik atributů, včetně x, y, z, serial, objtype, color atd. Tyto atributy jsou zděděné všemi ostatními třídami objektů, které jsou ve stromě hierarchie pod třídou UObject, což znamená, že tyto základní atributy jsou součástí všech objektů UO světa.

Součástí některých tříd objektů jsou dokonce i funkce (metody), což je znakem objektově orientovaného přístupu programování. Např. součástí třídy Door jsou metody Door.Open() a Door.Close(), které umožňují otevření resp. zavření dveří. K metodám třídy přistupujete pomocí operátoru tečky ".". Podle toho, s jakým typem objektu pracujete, tedy můžete mít k dispozici určité atributy a metody. Například součástí objektu třídy Door není atribut quality, který by byl přítomen v objektu třídy Equipment, nicméně u obou těchto tříd můžete přistupovat k jejich x, y, z souřadnicím. Některé atributy lze pouze číst, do některých lze i zapisovat. Tak je to nastaveno v zájmu vaší vlastní bezpečnosti. Mohli byste nadělat pěkný svinčík, kdybyste se snažili zapisovat např. do character.dead nebo do character.acct.

Kapitola 7

Vlastní atributy

Vlastní atributy (angl. Custom Properties nebo CProps) jsou tím, co dělá eScript flexibilním. Kromě vestavěných atributů, o kterých jsme mluvili v předchozí kapitole, můžete použít i vlastní atributy. Ty vám umožňují skladovat volitelné množství jakýchkoliv dat tak, že je jednoduše přiřadíte k vámi vybranému objektu. Tato data mohou být uskladněna jakýmkoliv skriptem a později opět použita jakýmkoliv dalším (nebo i stejným) skriptem, který má k dispozici referenci na daný objekt. Můžete takto skladovat jakýkoliv typ dat: řetězec, integer, reálné číslo, pole, ... Brzy si ověříte, že tato možnost ukládat a později znovu získávat data skrývá velkou moc. Projdu zde několik příkladů skriptů, které používají vlastní atributy a dotknu se tak některých dalších aspektů skriptování.

Řekněme, že chcete vytvořit předmět na jedno použití, který umožní hráči, poté co byl oživen, se teleportovat zpět ke svému tělu. Je zde několik věcí, které musíme udělat, abychom tohoto dosáhli:

1. Vytvořit popis nového vlastního předmětu, který hráči dá tuto schopnost.
2. Vytvořit skript, který kontroluje chování našeho nového předmětu.
3. Napsat kód, který bude uchovávat souřadnice hráčova těla.

Nejdříve ale rychlý návod, jak vytvořit nový vlastní předmět:

Otevřete jakýkoliv itemdesc.cfg, který najdete. Tento soubor obsahuje definice všech předmětů v UO světě, které mají nějakou funkčnost. Potřebujeme přidat náš nový předmět do jednoho z těchto souborů. Prozatím budeme používat /config/itemdesc.cfg. Zde je definice našeho nového předmětu spolu s popisem jednotlivých parametrů:
Code:
Item 0xABCD
{
  Name    prsten_navraceni
  Desc    Prsten Navraceni
  Graphic 0x108A
  Script  prsten_navrat
}

  • Item 0xABCD - Začátek definice předmětu. Objtype je volitelný, ale musí být unikátní. Rozsah čísel je 0x5000 až 0xFFFF.
  • Name prsten_navraceni - Vnitřní název předmětu, abyste při jeho vytváření mohli použít příkaz ".create prsten_navraceni" namísto ".create 0xABCD".
  • Desc Prsten Navraceni - Název předmětu, který hráč uvidí, pokud na něj klikne.
  • Graphic 0x108A - Objtype grafiky předmětu, která je určena k jeho reprezentaci. Toto číslo jsem získal pomocí InsideUO, když jsem hledal vhodnou grafiku pro prsten.
  • Script prsten_navrat - Název skriptu, který se spustí, když někdo dvojklikne na náš předmět.
Krátký popis funkcí, které budeme používat a které pracují s vlastními atributami (nalezitelné v uo.em):
Code:
SetObjProperty(objekt, jmeno_atributu_retezec, hodnota_atributu);

Uskladní atribut jmeno_atributu_retezec o hodnote hodnota_atributu v objektu daného referencí objekt.
Code:
GetObjProperty(objekt, jmeno_atributu_retezec);

Získá hodnotu atributu jmeno_atributu_retezec z objektu daného referencí objekt. Pokud tento atribut neexistuje, vrátí chybové hlášení (error).
Code:
EraseObjProperty(objekt, jmeno_atributu_retezec);

Vymaže atribut jmeno_atributu_retezec z objektu daného referencí objekt. Pokud tento atribut neexistuje, vrátí chybové hlášení (error).

Zkusme nyní napsat kus kódu, který uloží hráčovu polohu po jeho smrti. Skript, který je spuštěn poté, co postava zemře je /scripts/misc/chrdeath.src. Pojďme se na něj podívat blíže. Je v něm pravděpodobně již spousta kódu určeného pro různé účely, ale ten můžeme prozatím ignorovat. Parametry hlavní funkce budou vypadat nějak takto:
Code:
program ChrDeath(telo, duch) // Pripadne anglicke ekvivalenty corpse a ghost

Parametr telo je reference na předmět reprezentující tělo mrtvého hráče. Vzpomeňte si, že objekt Item dědí všechny atributy třídy UObject, což jsou mimo jiné i x, y, z souřadnice. K těm můžeme přistupovat pomocí operátoru tečky. Potřebujeme tyto souřadnice těla uschovat na postavě, aby si je tam skript prstenu mohl později přečíst. Parametr duch je reference na pohybující se objekt reprezentující samotného mrtvého hráče. Nevadí, že je nyní duch, stále k jeho datům můžeme přistupovat jako obvykle. Do chrdeath.src byste tedy měli přidat:
Code:
SetObjProperty(duch, "x_telo", telo.x);
SetObjProperty(duch, "y_telo", telo.y);
SetObjProperty(duch, "z_telo", telo.z);

Fajn, nyní máme všechno připraveno a můžeme se vrhnout do psaní skriptu prstenu. Vytvoříme soubor jménem "prsten_navrat.src" ve složce /scripts/items. Tady je základní tok programu:

1. Zkontroluj, jestli tyto tři atributy existují na postavě, která používá prsten
1a. Pokud atributy existují, ulož je do tří proměnných.
1b. Pokud atributy neexistují, skonči s chybovým hlášením.
2. Přesuň hráče na příslušné souřadnice
3. Odstraň atributy z postavy
4. Znič prsten

A tady je kód:
Code:
use uo;
program PrstenNavrat(hrac, prsten)
// Nezapomente ze toto je usescript, promenne hrac a prsten
// jsou parametry predane skriptu jadrem POLu
  var x,y,z;
 
  x := GetObjProperty(hrac,"x_telo");
  y := GetObjProperty(hrac, "y_telo");
  z := GetObjProperty(hrac, "z_telo");
 
  if ( (x== error) or (y == error) or (z == error) )
    SendSysMessage(hrac,"Nenasel jsem tve telo");
    return 0; // Ukonci skript
  endif
  // Pozn: Jelikoz pol97 funkce MoveCharacterToLocation je zastarala, pouzijeme namisto ni MoveObjectToLocation   
  MoveCharacterToLocation(hrac,x, y, z);
  EraseObjProperty(hrac, "x_telo");
  EraseObjProperty(hrac, "y_telo");
  EraseObjProperty(hrac, "z_telo");
  DestroyItem(prsten);
endprogram

Jednoduché, že? Nyní stačí jen zkompilovat chrdeath.src a return_ring.src, restartovat script chrdeath, pokud server zrovna běží (.unload chrdeath), vytvořit nový předmět a otestovat to. Teď si možná říkáte: "Když hráč s tímto prstenem umře, ten přece zůstane v jeho těle a nijak mu nepomůže k teleportu, až bude hráč oživen!" Máte pravdu, je několik možností, jak toto řešit:

1. Říci hráči, jak je hloupý, že si ten prsten nenechal v bance. Nicméně pokud by našel healera uprostřed divočiny, ani prsten v bance by mu k ničemu nebyl.
2. Udělat prsten newbie předmět, který zůstává u ducha a je použitelný po oživení postavy.
3. Změnit předmět na něco, co nelze nosit, což by mohlo hráče navést k tomu, že tento předmět nemá nosit sebou.

Je dobré vědět, jak POL ukládá vlastní atributy v předmětech. Pokud použijete příkaz .props na jakýkoliv objekt, jako je např. náš nešťastný hráč, uvidíte něco jako: cprop x_telo i300, kde důležitou informací je "i" před hodnotou atributu. To signalizuje typ dat. K tomu se vrátíme v příští kapitole.

Vlastní atributy na účtech

Můžete také použít atributy na samotné účty (tedy nejenom na specifické postavy v nich obsažené). Musíte ale použít odlišnou syntaxi. namísto SetObjProperty(ucet, "atribut", hodnota) použijete tyto speciální metody:
Code:
account.SetProp("JmenoAtributu", hodnota);
account.GetProp("JmenoAtributu");

Kapitola 8: Použití konfiguračních souborů a přístupnost

V POLu jsou v konfiguračních souborech (.cfg) uskladněna statická data určená ke čtení za běhu. Mohou být editována bez nutnosti restartu či rekompilace. Z tohoto důvodu je to vhodné místo, kam umístit data, která jsou často měněna. Jsou dva typy cfg souborů v POLu: jedny jsou přímo používány jádrem a druhé jsou čteny skripty. S prvně zmiňovanými pracovat nebudeme, nicméně jde např. o konfiguraci systému, pol.cfg; konfiguraci kouzel, spells.cfg; konfiguraci skillů, attributes.cfg atd. Existují některé konfigurační soubory, které jsou využívány jak jádrem, tak ostatními skripty, např. itemdesc.cfg a npcdesc.cfg (oba jsou čteny příslušnými funkcemi jádra, ale skripty z nich mohou také získávat informace, jak brzy uvidíme). Konfigurační soubory mají některé vlastnosti o kterých byste měli vědět. Každý konfigurační soubor se skládá z nula či více elementů, každý element má typ a nula či více atributů. Následuje příklad s popisem:
Code:
BowcraftData 0x13B2
{
  Name Bow
  Material 16
  Difficulty 30
  PointValue 20
}

  • BowcraftData - Typ elementu. Není používán žádným systémem a slouží pouze k tomu, aby měl skripter nějaké ponětí, k čemu se tento element vztahuje.
  • 0x13B2 - Klíč elementu nebo jednoduše klíč. Musí to být řetězec nebo číslo a je používán k vyhledávání požadovaného elementu v souboru.
  • Name Bow,Material 16,Difficulty 30,PointValue 20 - Atributy elementu a jejich hodnoty. Tedy samotná data
Zde je postup, jak nalézt specifická data (nutné použít modul cfgfile.em):
1. Načíst konfigurační soubor, ve kterém je uložen požadovaný element pomocí ReadConfigFile(jmenoSouboru)
2. Za pomocí klíče nalézt specifický element, ve kterém jsou obsažena požadovaná data - FindConfigElem(cfgsoubor, klic).
3. Načíst libovolné množství dat podobně jako v případě vlastních atributů, pomocí GetConfigXXXX(elem, jmenoAtributu), kde XXXX závisí na typu dat (integer, reálné číslo, řetězec).

Pro rychlý příklad předpokládejme, že element výše je v souboru jménem "bowery.cfg" (ve složce /config) a chceme hodnotu atributu "Material" obyčejného luku.
Code:
use cfgfile;

function GetMaterial(predmet)
  // Predpokladejme, ze 'predmet' je reference na obycejny luk
  var cfgfile, element, hodnotaAtributu;
  cfgfile := ReadConfigFile("bowery");
  element := FindConfigElem(cfgfile, predmet.objtype);
  hodnotaAtributu := GetConfigInt(element,"material");
endfunction

Co dáte do konfiguračních souborů je na vás, ale nejvíce jsou vhodné pro velké množství dat, která se liší klíčem elementu. Klíč je často objtype nebo jednoduše zvyšující se sekvence. Můžete si to strukturovat, jak je libo.

V konfiguračních souborech, které jsou používány jak jádrem, tak ostatními skripty, jsou obsažené atributy očekávané z obou těchto pohledů. Vezměme si jako příklad popis NPC. Jádro očekává standardní atributy NPC, jako jsou staty, barva, grafika atd. Můžete ale přidat další atributy, které jádro nepotřebuje, ale mohou se hodit např. v AI skriptu pro upřesnění chování (např. útěk od hráče nebo naopak útok). Třetí možnost je přidání vlastních atributů. Rozebereme si následující NPC šablonu (angl. template):
Code:
NpcTemplate shade
{
  Name a shade
  script killpcs
  ObjType 0x1a
  Color 0
.
.
.
  lootgroup 29
  Magicitemchance 1
  provoke 67
  CProp Undead i1
}

Všiměte si:
1. 'shade' je klíčem tohoto elementu. Pokud máte referenci na pohybující se objekt 'shade', můžete k tomuto elementu v npcdesc.cfg souboru přistupovat pomocí atributu shade.npctemplate, která odpovídá klíči.
2. První čtyři atributy jsou využívány jádrem při vytvoření NPC.
3. Následující tři atributy nejsou využívány jadrem, ale jinými skripty. První dva jsou zřejmě využívány nějakým skriptem určeném ke generování lootu, poslední pak nejspíše v nějakém 'provocation' skriptu
4. Poslední atribut je vlastní, který je předán každé instanci této NPC šablony.

Číslo 4 je velmi důležité: pokud definujete vlastní atribut v konfiguračním souboru jako je npcdesc.cfg nebo itemdesc.cfg, tento atribut je automaticky nastaven na každé instanci tohoto předmětu (resp. NPC), která je vytvořena. To přináší staré známé dilema "prostor vs. čas". Vlastní atributy v konfiguračních souborech jsou nastaveny na každý jeden z těchto předmětů, což sice zabírá extra paměť, ale dá se k nim rychleji přistupovat. Čtení těch samých dat z konfiguračních souborů trvá sice déle, ale jsou uložena pouze na jednom místě. Použití vlastních atributů nemá smysl v elementech z kterých nejsou nikdy vytvořeny žádné předměty.

Kapitola 9: Balíčky

Asi jste si všimli, že doteď jsme vkládali soubory na 'standardní' místa, /scripts/items pro useskripty předmětů, /config pro konfigurační soubory atd. To je považováno za špatný návyk, protože je vše bez jakékoliv organizace umístěné na jednom místě. Abychom se tomu vyhnuli, POL nabízí systém balíčků, kde všechny soubory sloužící specifickému účelu mohou být umístěné ve složce pojmenované v souladu s tímto účelem. Například, pokud napíšete systém pro nový skill, mohli byste všechy soubory související s tímto novým skillem dát do jednoho balíčku: všechny zdrojové soubory skriptů, zkompilované zdrojové soubory, podpůrné konfigurační soubory, readme soubory atd. V POLu jsou dva druhy balíčků: Standardní balíčky, které jsou defaultně povolené (v /pkg/std/), klasické skill systemy, kouzla, spawner atd. Dále pak volitelné balíčky, které jsou defaultně zakázané, nicméně mohou být používané, jak je potřeba (v /pkg/opt/). Povolení volitelného balíčku se provede pomocí speciálních instrukcí ve speciálním konfiguračním souboru, který je součástí balíčku.

Každý balíček musí obsahovat konfigurační soubor pkg.cfg, který daný balíček popisuje a má následující formát (Znak '#' značí komentář):
Code:
# Priklad popisovacího konfiguracniho souboru balicku

Enabled 1
  # Enabled 0/1 - Ma byt balicek povolen?
 
Name template
  # Jmeno balicku. Melo by byt stejne jako dana slozka
 
Version 1.3
  # Version v0.v1..vn  Cislo verze balicku
   
Requires spawner 1.2
  # Vyzaduje jmenoBalicku {verze}
  # Dalsi vyzadovane balicky (Muze tedy byt vice techto radku)
   
Conflicts some-package
  # Konflikt s jmenoBalicku
  # Tento balicek nemuze koexistovat s jinym specifickym balickem
  # Nelze specifikovat verzi
   
### Cokoliv pod timto radkem je prozatim systemem ignorovano, ale presto je dobre
### tyto informace zahrnout ve vasem pkg.cfg, k lepsi informovanosti ostatnich skripteru
   
CoreRequired 96
  # Verze jadra, ktera je vyzadovana bez znaku '0', ktery by mohl indikovat oktalove cislo
 
Maintainer John Q. Public
  # Vase jmeno
Email johnq@public.com
  # Vas email

V předchozích příkladech, které používají ReadConfigFile by mohla přítomnost balíčků komplikovat funkčnost. Jak např. zajistit v kterém itemdesc.cfg číst? Lze totiž vybírat z těch, umístěných v jednotlivých balíčcích, ze standardního umístěného v /config či dokonce můžeme číst ve všech najednou. Toto je řešeno pomocí formátu jména souboru, který předáte do ReadConfigFile funkce. Možné formáty jsou:
Code:
ReadConfigFile("jmenoCFG")
  - u skriptu, které nejsou v balicku, hledej v /config/[jmenoCFG].cfg
  - u skriptu, ktere jsou v balicku, hledej v [jmenoCFG].cfg ve stejnem balicku

ReadConfigFile(":*:jmenoCFG")
  - Cte v kazdem konfiguracnim souboru daneho jmena

ReadConfigFile(":jmenoPKG:jmenoCFG")
  - hledej v [slozkaPKG]/[jmenoCFG].cfg

ReadConfigFile("::jmenoCFG")
  - hledej v pol/config/[jmenoCFG].cfg

U speciálních konfiguračních souborů itemdesc.cfg, npcdesc.cfg, attributes.cfg a spells.cfg první tři použité formáty vyústí ve vrácení "složeného" konfiguračního souboru zahrnujícího obsah všech těchto cfg souborů ve všech povolených balíčcích společně s obsahem příslušného standardního cfg souboru.

Existuje několik dalších případu, kdy je tento přístup použit, jako je start_script() nebo UnloadConfigFile funkce. Z tohoto důvodu je syntaxe pro .unloadcfg příkaz ".unloadcfg :jmenoPKG:jmenoCFG". K tomu se vztahuje další důležity aspekt systému. Konfigurační soubory jsou cachovány systémem a musí být "unloadnuty", abychom dosáhli vyditelné online změny.

Kapitola 10: Debugování

Mnoho knih bylo napsáno na téma nalezení a opravení softwarových chyb a bylo by zbytečné opakovat jejich obsah. Tato kapitola vám ukáže některé cesty k nalezení bugu ve vašich skriptech specifické pro POL/eScript. Nejdříve se koukneme na chyby v času kompilace. Ecompile, překladač eScriptu si vede relativně dobře pokud jde o odhad, kde vaše syntaktické chyby skriptu jsou. Mluvím o odhadu protože základním pravidlem programování je nikdy 100% nevěřit chybovým hlášením překladače (či interpretu). Často jsou velmi užitečné, ale někdy vás mohou svést z cesty, pokud je berete jako dogma. Chybové hlášení obsahuje číslo řádku, okolo kterého se chyba nalézá. Ta může být o několik řádků výše nebo o několik řádků níže. Zbytek chybového hlášení je obvykle správný i když někdy trochu vágní. Zde jsou některé příklady:
Code:
Don't know what to do with Unknown Token: (280,8,'elseif') in SmartParser::parseToken
Error compiling statement at D:\pd\pol\scripts\items\torch.src, Line 4

- Chybové hlášení vzniklé chybějícím středníkem v if-bloku na řádku 5
Code:
Warning: Equals test result ignored. Did you mean := for assign?
near: item.graphic = 0xa12;
File: D:\pd\pol\scripts\items\torch.src, Line 5

- Zde ecompile uhádlo správně: Použili jsme pouze rovnítko, když jsme chtěli přiřazovat
Code:
Warning! possible incorrect assignment.
Near: if(item.graphic := 0x0f64)

- Toto ecompile zachytí také, většinou nechcete přiřazovat v if-podmínce. Není to ilegální, takže překladač dokončí kompilaci v pořádku, nicméně dá vám varování.
Code:
Unhandled reserved word: 'endprogram'
Error compiling statement at D:\pd\pol\scripts\items\torch.src, Line 7
Error in IF statement starting at File: D:\pd\pol\scripts\items\torch.src, Line 4

- Toto chybové hlášení jsme dostali, když jsme zapomněli vložit klíčové slovo endif. Překladač narazil na endprogram dříve než na endif, což je syntaktická chyba.
Code:
Token 'item' cannot follow token ')'
Error compiling statement at D:\pd\pol\scripts\items\torch.src, Line 2

- Chybové hlášení vzniklé chybějící pravou závorkou v if-podmínce na řádku 4
Code:
Error compiling statement at D:\pd\pol\scripts\items\torch.src, Line 2
Error detected in program body.

- Tahle chyba je ošklivá, protože vám nedá žádnou nápovědu v tom, co je špatně. Já jsem na toto chybové hlášení narazil pouze, když jsem se pokusil deklarovat proměnnou se stejným jménem, jako nějaké klíčové slovo (v tomto případě for)

Chyby v čase běhu programu jsou mnohem hůře nalezitelné. To jsou chyby, které jsou syntakticky správné, nicméně produkují chybné výsledky. Překladač je nezachytí ani vám je nepomůže nalézt. Vaše nejlepší možnost, jak tyto chyby chytnout, je sledovat, kde a kdy se skript chová nesprávně a následně se ponořit do daného segmentu kódu a porozhlédnout se okolo. K zachycení specifického problému máte několik možností:

1. Průběžně si nechat vypisovat hodnoty podezřelých proměnných. Zúžit množství kódu v kterém se může bug nalézat.
2. Mnoho funkcí jádra vrací 'error', pokud se stalo něco nesprávného (např. se skript snažil vytvořit NPC na nelegální pozici). Pokud porovnáte návratovou hodnotu funkce s 'error', můžete to zachytit - viz. např. if(CreateNPCAtLocation == error) .
3. Některé funkce dokonce vrací '.errortext' vestavěný atribut, který vám dá informace navíc - viz např:
Code:
var house := CreateMultiAtLocation(...);
if(house == error)
  Print(house.errortext);
endif

4. Pokud ani jeden z výše uvedených bodů nefungoval, můžete se pokusit využít funkce debugování. POL pak tiskne jednotlivé řádky kódu do konzole tak, jak jsou jednotlivé příkazy prováděny. Toto často není příliš nápomocné, protože pokud běží několik instancí skriptů, všechny jsou vypisovány do konzole. Nejlépe je tak debugovat na lokálním serveru s minimem spuštěných skriptů. K zapnutí funkce debugování musíte použít (includovat) modul os.em a pak vložit řádek:
Code:
set_debug(1);

Poté musíte říci překladači, že chcete debugovat. Toho dosáhnete pomocí příznaku '-i', např.: ecompile –i test.src.

_________________
Gereth, Montarick, Tanova - V nesprávný čas, v nesprávné guildě.<Banned>
Finwe, Gereth, Simone - On a quest to die better.
Nobody's tomorrow is guaranteed.
CSFD // CBDB


Top
 Profile ICQ  
 
Ads
PostPosted: Mon Jul 01, 2013 11:20 am
 
Master
Master
User avatar

Joined: Sat Jun 21, 2003 2:21 pm
Posts: 904
Online: 1652:13:32
Status: banned
Reg. players: 0
Druhá část překladu Racalacova tutoriálu. Obsahuje kapitolu 11 a Dodatek A.

Obsah

Kapitola 11: Pokročilé datové struktury a funkce
Dodatek A: Popis příznaků gumpů

Kapitola 11: Pokročilé datové struktury a funkce

V této kapitole si více do hloubky projdeme pole, struktury a slovníky, vysvětlíme si typy chyb (angl. error types), koncept perzistence a definujeme globální atributy. U funkcí si ukážeme některé techniky umožňující překonat limity toho, co z nich může být navráceno. Ukážeme si volání funkcí odkazem a použití pole parametrů.

Globální atributy

V tuto chvíli už byste měli vědět, jak zacházet s vlastními atributy (angl. cprops). Už je běžně přiřazujete k předmětům, postavám a dokonce i k účtům. Co když je ale nechcete k ničemu přiřazovat? Je zde možnost skladovat informace a nechat je viset jen tak v prostoru, dosažitelné odkudkoliv?

Asi jste správně uhodli, že taková možnost tu je a její název jsou globální atributy (angl. global properties nebo gprops). Pracuje se s nimi víceméně stejně jako s vlastními atributy až na to, že nemusíte specifikovat, k čemu mají být přiřazeny. Zde jsou tři základní funkce, které potřebujete k práci s globálními atributy:
Code:
GetGlobalProperty("JmenoAtributu");
SetGlobalProperty("JmenoAtributu","HodnotaAtributu");
EraseGlobalProperty("JmenoAtributu");

Jak jste už zvyklí, můžete použít proměnné k reprezentaci jména nebo hodnoty atributu.
Code:
var globjmeno := "Attr1";
SetGlobalProperty(globjmeno ,"Ne");

Kód uvedený výše by nastavil globální atribut "Attr1" na hodnotu "Ne". Samozřejmě můžete jako hodnotu vlastního i globálního atributu využít složitější datové struktury. Zde je příklad:
Code:
var jmenoAtributu := "Attr1";
var hodnotaAtributu := array{0 , 1 , "dva"};
SetGlobalProperty(jmenoAtributu, hodnotaAtributu);

Voila! "JmenoAtributu" má nyní hodnotu pole obsahujícího 0,1 a "dva". Pokud byste později udělali následující:
Code:
var vystupAtribut := GetGlobalProperty("jmenoAtributu");
Print(vystupAtribut[1]);

Výstup by byl 0. Takto to funguje i s vlastními atributy.

Nyní si můžeme položit zajímavou otázku. Pokud jednoduché proměnné a pole mohou být uloženy v atributech, co dalšího tam můžeme uschovat? Abychom si mohli odpovědět, vysvětlíme si koncept perzistence.

Pokud může být typ proměnné uložen v atributu, řekneme že je perzistentní. Od verze Pol090 neexistují datové typy, které nejsou perzistentní, takže tento odstavec je tu hlavně proto, abyste věděli, co tím bylo myšleno, když čtete staré changes.txt a vidíte poznámky o tom, že některé věci mohou nyní být perzistentní. Ve verzi Pol089 byl jen jeden datový typ, ktery nemohl být perzistentní, tajemný typ ERROR. Tento typ dat dostanete, pokud jste použili funkci, která měla vrátit nějakou hodnotu, ale selhala. Pokud jste se pak navíc tento ERROR pokusili použít ve vlastním atributu, nastal problém. Nedrželo to, protože nebyl perzistentní. Teď už perzistentní je a funguje stejným způsobem jako struktura.

Nyní si projdeme trochu více do detailu datové typy, s kterými jste se setkali už dříve.

Pole

Preferovaný způsob inicializace prázdného pole je:
Code:
var a := array;

To funguje stejně jako dříve:
Code:
var a := {};

Pole má v sobě několik vestavěných metod - funkcí určených k přímé manipulaci s nimi:

  • array.Size() - Vrací počet elementu v poli obsažených.
  • array.Insert(index , hodnota) - Vloží nový element o hodnotě hodnota na místo specifikované parametrem index.
  • array.Erase(index) - Smaže element na místě specifikovaném parametrem index.
  • array.Shrink(nelems) - Smaže všechny elementy pole kromě prvních x elementů, kde x je hodnota určená parametrem nelems.
  • array.Append(hodnota) - Přidá element o hodnotě hodnota na konec pole.
  • array.Reverse() - Převrátí pořadí elementů v poli.
  • array.Sort() - Seřadí pole.
Zde je příklad:
Code:
/*1*/  var barvy := array;
/*2*/  barvy[1] := "zelena";
/*3*/  barvy[2] := "modra";
/*4*/  var vel_barvy := barvy.Size();
/*5*/  barvy[5] := "leskla";
/*6*/  vel_barvy := barvy.Size();

Vezměme to krok za krokem. Řádek 1 definuje pole. Řádky 2 a 3 do něj vloží první elementy. Na řádku 4 je to s proměnnými následovně:
Code:
barvy[1] = "zelena"
barvy[2] = "modra"
vel_barvy = 2

Řádek 5 vloží nový element na pozici 5, s čímž si eScript v pořádku poradí. Takže na řádku 6 je to s proměnnými takto:
Code:
barvy[1] = "zelena"
barvy[2] = "modra"
barvy[3] =     <--- tady bude ten ERROR typ o kterém jsme se bavili dříve
barvy[4] =
barvy[5] = "leskla"
vel_barvy = 5

Všimněte si, že když se počíta, kolik je elementů v poli, jsou do tohoto součtu zahrnuty i "prázdná" místa. Jinými slovy, bylo by přesnější říct, že array.Size() vrací poslední platný index pole. Pokud se pokusíte číst na pozici pole, která se nachází za jeho koncem (zde např. barvy[10]), bude vám navrácen <uninitialized object> (neinicializovaný objekt).

Dobrá, pojďme pokračovat s předchozím příkladem:
Code:
/*7*/ barvy.Insert(3, "bronzova");
/*8*/ vel_barvy := barvy.Size();

O co se tu pokoušíme nyní? Vkládáme element o hodnotě "bronzova" na pozici 3 v poli. Po této operaci bude pole vypadat následovně:
Code:
barvy[1] = "zelena"
barvy[2] = "modra"
barvy[3] = "bronzova"
barvy[4] =
barvy[5] =
barvy[6] = "leskla"
vel_barvy = 6

Všimněte si, že insert posune zbývající elementy o jedno místo doprava a to i když vkládáme element na prázdné místo. Pokud takto posouvat nechcete, nepoužívejte insert, použijte namísto toho operátor přiřazení: barvy[3] := "bronzova".
Code:
/*9*/ barvy.Erase(3);

Tento příkaz uvede pole do stavu před insertem.
Code:
/*10*/ barvy.Erase(3);

Pokud příkaz zopakujeme, vymaže jedno z prázdných míst v poli. Použití erase metody posune zbývající elementy o jedno místo doleva (opak insertu). Po řádku 10 tedy vypadá pole takto:
Code:
barvy[1] = "zelena"
barvy[2] = "modra"
barvy[3] =
barvy[4] = "leskla"
vel_barvy = 6 // po erase operacich jsme jiz size metodu nevolali, takze je v teto promenne hodnota odminula

Code:
/*11*/ barvy.shrink(3);

Toto zredukuje pole na první tři elementy - v tomto případě:
Code:
barvy[1] = "zelena"
barvy[2] = "modra"
barvy[3] =

Code:
/*12*/ barvy.Append("hneda");
/*13*/ barvy.Reverse();

Tyto příkazy zanechají pole v následujícím stavu:
Code:
barvy[1] = "hneda"
barvy[2] =
barvy3] = "modra"
barvy[4] = "zelena"

Code:
/*14*/ barvy.shrink(2);
/*15*/ barvy.reverse();

Code:
barvy[1] =
barvy[2] = "hneda"

Popravdě, nejsem si uplně jistý, jak funguje sort. Poskytnu dva příklady mého testování a nechám vás provést svoje vlastní experimenty.
Code:
a := array;
a[1] := 4;
a[2] := 7;
a[3] := "ukaz";
a[4] := "melodie";
a.Sort();

Tisk elementů pole proběhl následovně:
Code:
ukaz melodie 4 7

Nicméně při...
Code:
a := array;
a[1] := 4;
a[2] := 7;
a[3] := "ukaz";
a[5] := "melodie";
a.Sort();

následný tisk seřazených hodnot ukázal:
Code:
tunes  show 4 7

Všimněte si také, že element pole může být jakéhokoliv typu. Může obsahovat číslo, strukturu, ERROR nebo další pole. Pokoušet se řadit pole polí doporučuji pouze na vlastní riziko.

Struktury (v rychlosti)

Struktura je podobná poli ve směru, že obsahuje kolekci více hodnot. Nicméně oproti seřazenému seznamu u pole, struktury jsou skladovány ...no ... ve struktuře. Nejprve ji musíte inicializovat:
Code:
var a := struct;

Tímto dáte překladači vědět, že hodláte použít datový typ struct a on se k němu podle toho bude chovat. Hezká vlastnost struktur je, že ve velké míře s nimi můžete zacházet jako s objekty. Například postava má určité vestavěné atributy, např. polohu. K té může být přistupováno pomocí operátoru '.' - player.x, player.y, player.z. Podobně můžeme přiřadit struktuře elementy, ke kterým přistupujeme naprosto stejným způsobem. Tady je příklad:
Code:
var vytah := struct;
vytah.+poschodi;
vytah.+uzivatele;
vytah.+sachta;

vytah.poschodi := 1;       // Prvni poschodi.
vytah.uzivatele := array;  // Budeme si uchovavat pole lidi, ktery vytah pouzivaji
                           // Budeme pouzivat append a erase tak, abychom vzdy znali aktualni stav
vytah.sachta := 3;         // Treti sachta zleva

Takže, řekněme že někdo vejde do výtahu a zmáčkne trojku.
Code:
vytah.uzivatele.Append("Honza");

vytah.poschodi := 3;     
vytah.uzivatele.Erase(1);   // Nejdrive to najde vytah.uzivatele, uvidi, ze to je
                            // pole, a tak prida na konec Honzu.
                            // Pak jedeme do tretiho patra.
                            // Honza ve tretim patre vystupuje.

Slovníky

Slovníky nesou rysy jak polí tak struktur, je to takový most mezi nimi. Slovník vytvoříte nepřekvapivě takto:
Code:
var vec := dictionary;

Pak už se k nim chováte jako k polím až na to, že namísto seřazené sekvence čísel může mít slovník jako klíč (index) slova nebo čísla.
Code:
vec["zelena"] := "modra";
vec["cislo"] := 4;
vec[3] := array{1 , 3};

Vnitřně jsou struktury ve výsledku slovníky, takže následující dva příklady jsou v základu stejné:
Code:
var vec1 := struct;
vec.+prvni;
vec.prvni := "jedna";

var vec2 := dictionary;
vec2["prvni"] := "jedna";

Navíc to znamená, že metody pro slovníky fungují správně i na strukturách. Metody to jsou následující:

  • dictionary.Size() - Vrací počet elementů.
  • dictionary.Erase(klic) - Smaže element na místě specifikovaném parametrem klic.
  • dictionary.Insert(klic , hodnota) - Vloží element o hodnotě hodnota na místo specifikované parametrem klic. Stejné jako dictionary["klic"] := hodnota;
  • dictionary.Exists(klic) - Vrátí PRAVDA (true), pokud klíč existuje.
  • dictionary.Keys() - Vrátí seznam klíčů.
Funkce vrací žádnou nebo jednu hodnotu. Často chceme z funkce ale vrátit více než jeden kus dat. Můžeme vrátit pole, strukturu nebo slovník.

Takto to funguje i obráceně. Funkce start_script bere pouze dva parametry - jméno skriptu a jeden parametr k předání. Když chcete předat více dat, vložíte do tohoto parametru samozřejmě pole. Je zvykem toto pole pojmenovávat "parms".

Zde je příklad. řekněme že máte skript jménem testskript. Jako parametry požaduje referenci na toho, kdo skript zavolal a reference na dva předměty, na které uživatel poklikal. Pokud tento skript chcete zavolat z jiného skriptu, mohli byste to udělat následovně:
Code:
start_script("testskript" , array{kdo, cil1, cil2});

nebo:
Code:
var parms := array;
parms[1] := kdo;
parms[2] := cil1;
parms[3] := cil2;
start_script("testscript" , parms);

Nyní obsah testskript.src:
Code:
program testskript(parms)
  if ( parms[2] ) // Otestuje, zdali bylo predano pole
    char := parms[1];
    prvnicil := parms[2];
    druhycil := parms[3];
  else
    char := parms;
  endif
  // neco delej
endprogram

Program umí reagovat, jak na jednu proměnnou, tak na celé pole parametrů.

Volání funkcí odkazem

Poslední sekce této kapitoly pokrývá předávání proměnných do funkcí odkazem (by reference). Doteď jsme předávali hodnotou (by value). Jaký je rozdíl?

Když předáváme hodnotou, posíláme obsah originální proměnné do nové (její kopie). Nová proměnná je pak absolutně nezávislá na té staré. Takže, když máme:
Code:
var prvni := "jedna";
var druhy := 2;
TestFunkce(prvni, druhy);

a
Code:
function TestFunkce (tohle, tamto)
  print(tohle);  // vytiskne "jedna"
  print(tamto);  // vytiskne "2"
  tohle := "zelena";
endfunction

Jakmile je kód proveden, hodnoty proměnných prvni a druhy se nemění.

Nicméně, pokud předáváme odkazem, do funkce ve skutečnosti posíláme polohu samotné proměnné v paměti, ne tedy její hodnotu. Toho dosáhneme použitím prefixu byref v deklaraci funkce. Například:
Code:
var a := 4;
var b := 6;
var c := 9;
Foo(a, b, c);

function Foo(pa, byref pb, pc)
  pa := 3;
  pb := 5;
  pc := 8;
endfunction

Po provedení veškerého kódu a a c zůstanou nezměněny, ale hodnota b bude změněna na 5, protože pb je reference na proměnnou b, ne její kopie.

S tímto musíte být opatrní. Je snadné zaměnit referenci za kopii. Nicméně je to velmi silný nástroj. Je to také více efektivní než předávání hodnotou, protože nemusíte vytvářet kopii hodnoty proměnné a pak ji na konci volání funkce zase rušit. Nezapomeňte, že proměnná může reprezentovat obrovská pole, struktury nebo slovníky.

Dodatek A: Popis příznaků gumpů

Příznak - Syntaxe/Popis

noclose - [NONE]
gump nemůže být zavřen kliknutím pravého tlačítka myši. Musí být vytvořeno tlačítko pro exit.

nomove - [NONE]
s gumpem nemůže být hýbáno po obrazovce.

nodispose - [NONE]
gump nemůže být zavřen tlačítkem ESC. Pokud toto nastavení není specifikováno a uživatel zmáčkne ESC, dialog je zrušen, ale žádná zpráva není odeslána na server. Server neví, že hráč s gumpem skončil. Všechny dialogové gumpy by měly mít specifikovaný příznak 'nodispose'.

tilepic - [X] [Y] [T]
Zobrazí dlaždici (angl. tile) v gumpu.
[X] - Souřadnice X dlazdice.
[Y] - Souřadnice Y dlazdice.
[T] - Dlaždice (viz InsideUO).

resizepic - [X1] [Y1] [G] [X2] [Y2]
Definuje layout pozadí gumpu
[X1] - Startovní souřadnice X gumpu.
[Y1] - Startovní souřadnice Y gumpu.
[G] - Použitá grafika pozadí gumpu.
[X2] - Koncová souřadnice X gumpu.
[Y2] - Koncová souřadnice Y gumpu.
Pozn: Buďte opatrní, ne všechny gumpy jsou "roztahovací". U některých musí být správne specifikovaná velikost.
5100 = roztahovací sede pozadí gumpu.

page - [N]
[N] - Číslo strany.
Pozn: Definuje layout strany. Strana 0 ovlivňuje všechny následující strany (položky gumpu nebudou odstraněny posunutím se na další stranu). To zahrnuje např pozadí. Strana 1 je vždy zobrazena, když se gump poprvé otevře (Je tedy zobrazena na tom, co je definováno na straně 0).

button - [X] [Y] [G1] [G2] [E] [P] [R]
Tlačítko.
X - Souřadnice X tlačítka.
Y - Souřadnice Y tlačítka.
G1 - Výchozí grafika.
G2 - Grafika, když je tlačítko zmáčknuté.
E - Exit. Tlačítko uzavře gump a vrátí návratovou hodnotu.
P - Číslo strany (Skoč na stranu)
R - Návratová hodnota

radio - [X] [Y] [G1] [G2] [P] [R]
Přepínač. Syntaxe jako u tlačítka.

text - [X] [Y] [COLORCODE] [STRINGNUMBER]
Zobrazí text. Číslování řetězců je trochu ošemetné. UO považuje první předaný string jako 0, ale POL považuje jako první element pole 1. Uděláte to tedy následovně:
text 0 0 32 0 <---> array[1] := "Toto chci zobrazit".

gumppic - [X], [Y], [G].
Zobrazí zvolený gump.

textentry [X] [Y] [WIDTH] [HEIGHT] [COLOR] [RETURNVALUE] [INITSTRINGNUMBER]
Zobrazí editovatelný řádek textu.
[RETURNVALUE] - Klíč k extrakci řetězce.
[INITSTRINGNUMBER] - Inicializační řetězec.
Pozn: Opět pozor na číslování

checkbox - [X] [Y] [GUMPGFX] [CLICKGUMPGFX] [PREVALUE] [RETURNVALUE]
RETURNVALUE všech zašrktnutých boxů je nalezitelná v result.keys[].

_________________
Gereth, Montarick, Tanova - V nesprávný čas, v nesprávné guildě.<Banned>
Finwe, Gereth, Simone - On a quest to die better.
Nobody's tomorrow is guaranteed.
CSFD // CBDB


Top
 Profile ICQ  
 
PostPosted: Mon Jul 01, 2013 11:23 am
 
Master
Master
User avatar

Joined: Sat Jun 21, 2003 2:21 pm
Posts: 904
Online: 1652:13:32
Status: banned
Reg. players: 0
Překlad ukončen. Dotazy, přípomínky, poukázání na chyby vítáno. Stejně pak případná souhrná korekce. Bohužel na tomto foru nefungují správně tagy anchor a goto, takže nelze správně odkazovat v rámci postu. :?

Pokud by někdo tutoriál použil, nechte mi pm, ať vím, že to případně nebyl úplně vyhozený čas.

Hodně štěstí při skriptování.

_________________
Gereth, Montarick, Tanova - V nesprávný čas, v nesprávné guildě.<Banned>
Finwe, Gereth, Simone - On a quest to die better.
Nobody's tomorrow is guaranteed.
CSFD // CBDB


Top
 Profile ICQ  
 
PostPosted: Mon Jul 01, 2013 11:43 am
 
Adept
Adept
User avatar

Joined: Mon Oct 25, 2004 3:55 pm
Posts: 395
Location: Bílá Opava
Online: 00:00:00
Status: active
Reg. players: 0
nemuzu si pomoct, ale neverim, ze pokud clovek nezvladne takovy tutorial v anglictine, ma vubec sanci se ve skriptovani ujmout.. ale samozrejme me jen potesi, kdyz me nekdo presvedci o opaku :)

_________________
Former [Soul] Aphex II...
...nowadays [Pytlik] Dilema, Tumor, Keen/Ooya
One moment of glory...
Soul Reavers shall never perish!


Top
 Profile ICQ  
 
PostPosted: Mon Jul 01, 2013 12:10 pm
 
Master
Master
User avatar

Joined: Thu Dec 18, 2008 2:10 pm
Posts: 815
Online: 00:07:53
Status: active
Reg. players: 0
Na tom něco bude.

_________________
Image
Pozn.: Serenu na Endoru jsem měl už asi od r. 2005, ale udělal jsem s ní maximálně tak 15 lvl, takže to nepočítám :)
Cube & Ravage: Heeding the Call (Guild Video)


Top
 Profile ICQ  
 
PostPosted: Mon Jul 01, 2013 12:45 pm
 
Master
Master
User avatar

Joined: Sat Jun 21, 2003 2:21 pm
Posts: 904
Online: 1652:13:32
Status: banned
Reg. players: 0
Při překladu jsem se nad tím také zamýšlel a říkal si, jestli zbytečně nepálím čas. Angličtina je potřebná minimálně ke čtení dokumentace. Nicméně vše to je o vůli a úrovni angličtiny. Pokud víte zhruba jak programovací jazyk funguje, není pro čtení dokumentace nutná extra vysoká úroveň znalosti angličtiny. Určitý okruh slov se neustále opakuje.

Vysvětlím na příkladu z vlastní zkušenosti. Zhruba někdy ve 12ti jsem začal hrát Magic the Gathering. Sběratelská karetní hra v angličtině. V tu dobu byla moje angličtina v plenkách a já se na funkci každé karty musel ptát někoho staršího. Nicméně za nějaký čas, kdy jsem se té hře věnoval, jsem si vypěstoval takovou cílovou slovní zásobu, že jsem neměl problém si jakoukoliv novou kartičku přeložit...přestože jsem nebyl schopný si správně přeložit např. novinový článek v angličtině.

Druhá věc je, že člověk, který není opravdu zvyklý vstřebávat informace v oboru v angličtině nemusí mít tak úplně problém s překladem, ale může mít problém s pochopením. Překlad pak nemusí být primárně pouze přechod z angličtiny do češtiny, ale může přinést možnost vysvětlení určitých principů slovy, která jsou člověku bližší (mateřský jazyk). Pokud čtete větu v angličtině, můžete si jí přeložit, ale nemusíte správně pochopit její význam.

Abych shrnul mojí myšlenku ... ten překlad nemá nikoho spasit. Nicméně věřím, že někomu může ulehčit nebo urychlit přechod přes začátky. Důležité také je, že ten překlad se neztratí a může být použit každým novým potenciálním skripterem. Je to prostě další kus informace, která může pomoci.

Mimochodem na scriptérském fóru právě existuje člověk, který je motivovaný, skriptuje, již zvládl stvořit některé snažší skripty, ale neoplývá silnou znalostí angličtiny. Vznik tohoto překladu je také tak trochu motivován snahou pomoci mu se přes tu jazykovou barieru dostat.

_________________
Gereth, Montarick, Tanova - V nesprávný čas, v nesprávné guildě.<Banned>
Finwe, Gereth, Simone - On a quest to die better.
Nobody's tomorrow is guaranteed.
CSFD // CBDB


Top
 Profile ICQ  
 
PostPosted: Sat Feb 08, 2014 9:31 pm
 
Master
Master
User avatar

Joined: Sat Jun 21, 2003 2:21 pm
Posts: 904
Online: 1652:13:32
Status: banned
Reg. players: 0
Na scriptérském fóru je k dispozici český překlad "POL Performance Guide by ToGu", článku o výkonnosti POLu a možnostech, jak tuto výkonnost může scripter ovlivnit. Dotazy, přípomínky, poukázání na chyby vítány. Stejně tak případná souhrná korekce. Hodně štěstí při efektivnějším skriptování.

_________________
Gereth, Montarick, Tanova - V nesprávný čas, v nesprávné guildě.<Banned>
Finwe, Gereth, Simone - On a quest to die better.
Nobody's tomorrow is guaranteed.
CSFD // CBDB


Top
 Profile ICQ  
 
Ads
Post new topic Reply to topic  Page 1 of 1
 [ 7 posts ] 

Board index » Offtopic
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

cron
SitemapIndex SitemapIndex
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group

phpBB SEO Valid XHTML 1.0 Transitional Valid CSS!
Highly modified by Pirozek