1. Co je to interakce ?

Pokud chcete oživit svět i jinak než umístěním spawnu potvory a čekat než jí někdo zabije, tak použijte právě interakční systém. Jinými slovy, interakce může libovolné NPC (Non-Player-Character) oživit do takové míry, aby bylo schopné vám třeba uvařit kafe když na něj písknete. Hlavní výhodou však je, že pro takový triviální úkol nepotřebujete podporu skripterů ani nikoho jiného z týmu. Vše bude ve vaší režii.

Interakční systém (dále jen IS) je tedy nástroj, který zpracovává a používá interakce pro vytvoření interaktivního herního prostředí. Pojem interakce si představte jako množinu prvků zvaných spouště (v angl. triggery). Pomocí těchto spouští následně můžete donutit NPC aby reagovalo na určité herní podněty. Co se stane při aktivaci dané spouště je čistě na vás

Interakce obsahující spouště se vytváří jako textový soubor v XML formátu. Na tvorbu interakcí tedy nepotřebujete žádné extra programy. Ve většině případů si vystačíte s obyčejným poznámkovým blokem. Pro vyšší komfort však doporučuji editor, který přímo podporuje XML formát. Jedním z mých oblíbených je editor PSPad, který je zadarmo. Zajisté však najdete celou řadu jiných a propracovanějších.

Pokud nic nevíte o formátu XML, vřele doporučuji přečíst návod od pana Koska. Pro psaní interakcí si bohatě vystačíte s prvními 5-ti kapitolami.

http://www.kosek.cz/clanky/swn-xml/syntaxe.html

Na závěr této kapitoly bych se zmínil o editoru MWQE (Manawydan Quest Editor), který je napsaný speciálně pro vytváření interakcí. Zastávám však názor, že pokud nepochopíte jak vypadá interakce zevnitř, nebudete nikdy schopní napsat pokročilejší typ interakce, protože některé techniky editor zkrátka neumí. Samozřejmě až pochopíte princip, tak je MWQE vítaným pomocníkem pro vytvoření základní kostry interakce. Tedy moje osobní doporučení je, zkuste to nejdřív podle mě a když to nepůjde, použijte MWQE.

2. Píšeme první interakci

Nyní když znáte teorii, je na čase zakousnout se do praktické ukázky. Otevřete si vybraný editor pro XML a vložte do něj následující text.

<?xml version="1.0" encoding="utf-8"?>
<Interaction ID="Brandon_Ishar">
</Interaction>

pozn. Některé editory jsou spíše grafického a klikacího rázu, ale troufnu si tipnout ze 99% z nich má nějakou možnost zadat XML přímo. Takže než začnete panikařit, zkuste tuto možnost najít. Pokud se nepodaří, spusťte si obyčejný poznámkový blok, soubor uložte s příponou xml a následně otevřete ve vašem editoru. Uvidíte jak je XML reprezentováno v tomto editoru.

pozn. Nebudu tady vysvětlovat formát zápisu tohoto textu. Pokud vám není něco jasné, znovu doporučuji se obrátit na popis XML formátu z první kapitoly.

Tento kousek textu představuje zcela základní interakci, kterou si lze představit jako prázdnou poštovní obálku. Takovou interakci nelze přiřadit na žádné NPC stejně jako nebudete odesílat prázdnou obálku. Nicméně tato interakce je nutnost, kterou musíte vždy vytvořit, stejně jako dopis bez obálky nelze poslat. Abyste tedy uspěli, je nutné do interakce přidat nějaké ty spouště - dopisy.

V této kapitole se však nejdřív zaměřím na atribut ID v elementu Interaction. Tento velmi důležitý prvek představuje jméno pro danou interakci, které hraje důležitou roli při pokročilejších úkolech. Přesto je nutné vždy tento atribut uvádět. Chápejte to jako číslo zásilky, které vám přidělí pošta, když posíláte dopis. Bez tohoto čísla je vaše zásilka takřka nedoručitelná. V tomto případě jste však poštou vy a vytvoření tohoto ID je na vás.

Pro valnou většinu interakcí platí základní pravidlo jejich pojmenování. Vždy si předem promyslete, jak se bude vaše NPC jmenovat. Toto jméno pak napište jako první část ID interakce následované znakem „_“ (podtržítko). Jméno může obsahovat mezery i diakritická znaménka.

Zde docházíme k důležitému poznatku. Jelikož se interakce jmenuje stejně jako NPC, tak je striktně zakázáno, aby interakce obsahovala informace týkající se jiného NPC. Vyjímkou jsou pak obecné interakce, které jsou využívány více různými NPC.

Druhá část názvu (za podtržítkem) je pak jméno města, ve kterém se NPC převážně vyskytuje. Pište plné názvy měst, žádné zkratky. Pokud se NPC potuluje např. v lese u Isharu, bude název vypadat jako „BrandonIsharLes“. Neboli za název města můžete zadat přesnější určení umístění tohoto NPC. Dodržujte však vždy pravidlo, že za prvním podtržítkem následuje název nejbližšího města.

Nakonec bych se zmínil o pojmenování souboru, který takto vytvoříte. Opět platí pravidlo, že soubor začíná jménem NPC. Místo názvu města pak následuje v kulatých závorkách uzavřená informace o funkci daného NPC vyjádřená 1-3 slovy. Tedy např. výše zmíněný Brandon z Isharu se žíví jako pekař. Jeho soubor se tedy bude jmenovat „Brandon (pekař).xml“.

3. Spouště jako základní kámen

Teď když máte pomyslnou obálku, je načase jí naplnit dopisy, aby adresát nebyl zmaten co že to po něm vlastně chcete. Adresátem je v tomto případě vaše NPC a dopisy představují spouště, neboli příkazy, na které postava reaguje.

<?xml version="1.0" encoding="utf-8"?>
<Interaction ID="Brandon_Ishar">
  <Procedure ID="doubleclick">
    <Trigger WaitOn="Doubleclick" Range="3" />
    <Say>Neklikej na mě !</Say>
  </Procedure>
</Interaction>

Toto je tedy ukázka jednoduché interakce, která už opravdu něco dokáže. Konkretně říká, aby při dvojkliku na NPC vyslovilo zadanou větu „Neklikej na mě !“. Ano opravdu takhle málo stačí, aby jste dosáhli takové akce. Rozebereme si to ovšem podrobněji.

Při porovnání se základní interakcí vidíte, že se zde objevil element Procedure. Ten si představte jako list papíru, na který budete psát pomyslný dopis. Atribut ID je opět povinné uvádět kvůli evidenci uvnitř systému. V analogii s dopisem si toto ID představte jako barvu papíru, takže adresát dokáže ihned poznat co po něm asi budete chtít. V tomhle nemá atribut žádná přísnější pravidla pro pojmenování. Napsat zde můžete téměř cokoliv, ale je dobrým zvykem vycházet z typu spouště.

Typ spouště je informace říkající, při jaké herní události má NPC reagovat. V tomto případě jde o „Doubleclick“ neboli „dvojklik“. Název typu spouště uvádíte v atributu WaitOn v elementu Trigger. Doslova se toto dá přeložit jako „čekej na aktivaci spouště dvojklikem“. Každá procedura (papír) může mít pouze jednu spoušť (nadpis) a musí být vždy na prvním místě.

Nakonec bych se zmínil o nepovinném atributu Range v elementu Trigger, který specifikuje maximální vzdálenost, na kterou lze spoušť aktivovat. Pokud tedy hráč dvojklikne na Brandona ze vzdálenosti 4 políček, tak se nic nestane. Až když přijde o krok blíže, aktivuje se spoušť. Ve většině případů však nemusíte tento atribut uvádět, pak se bere standardní hodnota 3 políček. Berte to jako určitou sadu pravidel, které napíšete v dopise pod hlavičku a pokud nejsou pravidla splněna, nebude adresát pokračovat ve čtení dopisu.

Nakonec tu máme nejjednodušší příkaz Say, kterým jednoduše NPC informujete co má vyslovit. Jelikož za tímto příkazem už není nic dalšího, interakce skončí a NPC se opět chová dle svého vlastního vědomí.

Jednotlivé typy spouští probereme v některé z následujících kapitol. Vězte však, že ve většině případů si vystačíte právě se spouští Doubleclick. Jen bych ještě zmínil, že v jedné interakci nemůže být více různých reakcí na stejnou událost. Jinými slovy, jedno NPC nedokáže zareagovat na dva různé dvojkliky, vždy jen jeden. Existují samozřejmě určité speciální případy, ale to je nad rámec této kapitoly.

4. Interaktivní text neboli co s pohlavím

Co s pohlavím ? Samozřejmě nemám namysli nic jiného než rozlišení, zda je postavička ve hře muž nebo žena. K tomuto účelu slouží právě zmíněný interaktivní text. Stejně jako pojem interakce označuje možnost vytvořit živé prostředí, tak interaktivní text umožňuje sestavit věty, které se samy mění dle situace.

<?xml version="1.0" encoding="utf-8"?>
<Interaction ID="Brandon_Ishar">
  <Procedure ID="doubleclick">
    <Trigger WaitOn="Doubleclick" Range="3" />
    <Say>Dobré ráno, #mladý pane#slečno#</Say>
  </Procedure>
</Interaction>

Z protivného Brandona jsme rázem udělali milou osobu, která hráče správně pozdraví podle pohlaví. Pokud ho tedy osloví žena, Brandon odpoví „Dobré ráno, slečno“. Jak jistě mnozí z vás pochopili, první část mezi znaky # se použije pro muže kdežto druhá část pro ženy. Rovněž je zde naznačeno, že mezi znaky # nemusí být pouze jedno slovo, ale klidně i celá věta.

<Say>Dobré ráno, #pane#paní#</Say>
<Say>Dobré ráno, pan#e#í#</Say>

Toto je naopak ukázka zkráceného zápisu, kdy společnou část slova umístíte mimo znaky #. Ušetříte si tak práci zdvojeným vypisováním téhož slova. Volbu způsobu zápisu však nechám čistě na vás. Někteří zlí jazykové označují zkrácený zápis za nepřehledný. Mě osobně se naopak zdá výhodnější.

<Say>##Dobré ráno, krásná slečno#</Say>
<Say>#Dobré ráno, mladý pane##</Say>

Tady máme menší hlavolam, ale pokud jste dávali dobrý pozor, jistě chápete, že v prvním případě jsme z Brandona udělali proutníka, co zdraví jen dámy a na pány z vysoka kašle. V druhém případě naopak pozdraví jen pány a dámská část populace zůstane bez pozdravu. Na první pohled mohou dva znaky ## vedle sebe působit zmateně, ale vězte, že to není nic jiného než vynechání textu pro jedno z pohlaví.

<Say>Rozhodl##a# jste se už pan#e#í# ?</Say>

Častější využití je vynechání části pro muže, pokud základní slovo je pro ně dostačující. Tedy místo toho abyste pracně vypisovali #Rozhodl#Rozhodla#, použijete tento krátký tvar. Nicméně opět je to otázka vlastní preference, někdo to nemá rád.

<Emote>#zamračil$zamračila#</Emote>

Na závěr bych ještě zmínil tuto alternativu, pokud chcete v textu rozlišovat pohlaví NPC. Zpravidla toto nepotřebujete jelikož znáte jméno vašeho NPC a tudíž i jeho pohlaví. Přesto se tento zápis hodí pro případy pokročilejších interakcí a questů. Tedy pouhou záměnou prostředního znaku # za znak $ se rozlišuje pohlaví NPC.

5. Výrazy nejen v interaktivním textu

Aby si text opravdu zasloužil přívlastek interaktivní, měl by umět daleko víc než jen doplnit správné pohlaví. V této kapitole objevujeme nový pojem výraz. Pokud navíc potřebujete získat hodnotu něčeho pro porovnání vůči jiné hodnotě, použijete také výraz. Tedy jinými slovy, výraz vždy vrací nějakou hodnotu.

Hodnoty vrácené výrazem mohou být jedním ze 3 typů: logický, textový, a číselný.

<Say>Vítejte, mé jméno je @this.Name@</Say>

Nejprve to máme použítí textového výrazu. Pokud chceme vložit jeho výsledek do textu, musíme ho obalit do znaků @. Výše tedy máme jednoduchý příklad kdy NPC pozdraví a představí se svým jménem. Stejně jako pohlaví z minulého dílu, tak toto zpravidla nepotřebujete, ale pro názornost je to dostačující.

Než budu pokračovat, zmíním se ještě o podivném slovíčku this, které zde vidíte použité. Tímto jednoduše určíte vlastníka daného výrazu. Neboli tím říkáte jestli se výraz týká NPC (právě použité this) nebo hráče (místo this bude target). Pokud toto určení vynecháte, bude ve většině případů použit právě hráč (target). Tedy v našem příkladu by se při vynechání this, NPC představilo jménem hráče, což není to pravé ořechové. Některé výrazy mají toto chování nastavené naopak a berou NPC jako výchozí. Tam kde logicky vyplývá, že vás tento výraz u NPC nejspíš nezajímá, tam zpravidla je výchozím vlastníkem hráč. Prakticky vzato však nic nezkazíte tím, když toto určíte vždy sami, nicméně často je zbytečné to uvádět.

Druhým a nejčastějším způsobem použití výrazů jsou podmínky. Často budete potřebovat nějakou část interakce provést jen za určitých podmínek. Opět menší příklad

<Interaction ID="Brandon_Ishar">
  <Procedure ID="doubleclick">
    <Trigger WaitOn="Doubleclick" Range="3" />
    <Req>target.Name = "Pepa"</Req>
    <Say>Nazdar Pepo</Say>
  </Procedure>
</Interaction>

V tomto případě tedy náš Brandon pozdraví jenom Pepu a na ostatní se vykašle. Používáme zde opět známý textový výraz Name.

<Trigger WaitOn="Doubleclick" Range="3" />
<Req>target.Name = "Pepa"</Req>
<Req>target.IsCraft</Req>
<Say>Nazdar řemeslníku Pepo</Say>

Máme zde novou podmínku, která využívá výrazu IsCraft vracející logickou hodnotou. Logický výraz nabývá pouze hodnot ano nebo ne. Tedy k pozdravu dojde jen v případě, že Pepa je řemeslník.

<Trigger WaitOn="Doubleclick" Range="3" />
<Req>target.Name = "Pepa"</Req>
<Req>target.IsCraft</Req>
<Req>target.Int > 50</Req>
<Say>Nazdar chytrý řemeslníku Pepo</Say>

A zde vidíte použitý poslední typ výrazu, tedy číselný. V tomto případě je ověřována inteligence Pepy řemeslníka a bude pozdraven, jen pokud má inteligenci vyšší než 50.

Na závěr této kapitoly ještě vysvětlím co to jsou parametrizované výrazy. Jednoduše řečeno jedná se o výrazy, jimž lze předat nějakou hodnotu (nebo více hodnot) a jejím základě se rozhodne, jakou hodnotu vrátit.

<Req>HasMoney(100)</Req>
<Say>Dej mi 100 stříbrných nebo vezmu tvůj život</Say>

Řekneme, že náš Brandon se stal loupežníkem. Pomocí výrazu HasMoney zjistíme, jestli hráč má u sebe 100 stříbrných. Parametr výrazu je tedy uzavřen do kulatých závorek.

<Req>Outlaw("Ishar") > 50</Req>
<Say>Přidej se ke mě a spolu ovládneme svět !</Say>

V tomto případě máme výraz Outlaw, který testuje jestli má hráč padoušství v Isharu větší než 50. Pokud je tedy parametr textový, nezapomeňte ho uzavřít do uvozovek.

<Req>HasItem("Bread",3)</Req>
<Say>Pan#e#í#, obdarujte prosím chudého může trochou jídla.</Say>

Poslední příklad ukazuje použití více parametrů ve výrazu. Jednoduše tedy použijete „,“ (čárku) mezi jednotlivými parametry. Pamatujte opět na typ parametru. Textové uzavírejte do dvojitých uvozovek, číselné naopak napište přímo. A co se týká výrazu HasItem, pouze testuje jestli má hráč u sebe kdekoliv v batohu požadovaný předmět v zadaném množství.

<Say>Ulovil jsi teprve @Text(Hunt("vlci"))@ vlků, to je málo !</Say>

Možná vám vrtá hlavou co je zase tohle, ale nejde o žádný zázrak. Vezmeme to postupně. Hunt je výraz, který vrací číselnou hodnotu ulovených zvířat, pokud jste hráče vyslali na lov. Do textu však nelze vkládat číselné hodnoty, proto je zde pomocný výraz Text, kterým obalíte vrácenou číselnou hodnotu. Pak bude vše bez problémů fungovat.

6. Teď si budu klást podmínky já

Už umíme reagovat na události pomocí spouští a pomocí několika málo příkazů rozpovídat NPC. To je všechno krásné, ale poněkud lineární a předvídatelné. Pokud chceme aby NPC jen předneslo proslov a nic jiného neumělo, tak to zajisté stačí, ale obvykle i v takové jednoduché interakci najdou uplatnění podmínky.

Použití podmínek bylo už lehce naznačeno v minulé kapitole. Teď se vysvětlíme podrobněji jak to celé funguje. Základem každé podmínky je vždy nějaký výraz, jehož vrácenou hodnotu testujeme proti hodnotě jiné. Každá podmínka se skládá ze tří částí a je uzavřena do příkazu <Req> (z angličtiny request - požadavek)

Levá část s hodnotou (obvykle výrazem) následovaná operátorem a pravou části s hodnotou, proti které se porovnává levá část. Okolo operátoru vždy nechte mezeru.

Nejprve je důležité si uvědomit, jak vypadá takový průchod podmínkou. Zkuste si to představit jako takové malé dobrodružství, kdy se hrdina snaží dostat do nějaké pevnosti. Podmínka pak může představovat bránu, kterou lze projít jen pokud je otevřená. Zavřenou bránu nelze překonat a je nutné hledat jinou cestu nebo výpravu vzdát.

<Interaction ID="Brandon_Ishar">
  <Procedure ID="doubleclick">
    <Trigger WaitOn="Doubleclick" Range="3" />
    <Req>Name = "Pepa"</Req>
    <Say>Nazdar Pepo</Say>
  </Procedure>
</Interaction>

Vypůjčil jsem si příklad z minulé kapitoly, kde funkčnost této „brány“ je naznačena. Tedy pokud na NPC dvojklikne hráč jménem Pepa, podmínka se vyhodnotí jako splněná a pustí nás dál k příkazu Say. V opačném případě interakce skončí, protože už neexistuje jiná cesta než skrz tuto bránu.

<Req>IsCraft</Req>
<Req>Name = "Pepa"</Req>
<Req>Int > 50</Req>
<Say>Nazdar chytrý řemeslníku Pepo</Say>

Podobný příklad jako z minulé kapitoly, kde vidíte několik podmínek neboli „bran“ za sebou. A funguji tak jak byste čekali. Tedy pokud otevřete první bránu, neznamená to, že jste v cíli, musíte otevřít i další dvě. Poskládáním podmínek takto za sebe tedy požadujete splnění více různých situací naráz a nesplnění jedné z nich má za následek neúspěch.

Výraz vracející logickou hodnotu již není potřeba testovat proti jiné hodnotě, protože výsledek Ano stačí k tomu, aby se brána otevřela. Naopak výsledek Ne ponechá bránu zavřenou. U logických výrazu tedy nepoužíváte operátory a není zde pravá strana podmínky.

<Req>!this.IsFemale</Req>
<Req>!IsCraft</Req>
<Say>Jsem muž a ty nejsi kraft</Say>

Hodnotu logického výrazu můžete také otočit pomocí magického znaku ! (vykričník), který umístíte před název výrazu (včetně případného určení vlastníka). Tato operace se nazývá negace. Tedy v příkladu výše první podmínka testuje výrazem IsFemale pohlaví NPC a jelikož je přidán vykričník, tak říkáme, že podmínka je splněna, pokud NPC není žena. Druhá podmínka pak je splněna pokud hráč není kraft.

<Req>Name = "Pepa"</Req>
<Req>Race != "Drow"</Req>
<Say>Nazdar Pepo</Say>

Dalším typem výrazů jsou tedy textové. Ty můžeme testovat pouze na rovnost a nerovnost. V příkladu ověřujeme, že hráč se jmenuje Pepa a zároveň zjišťujeme, že není rasy drow.

<Req>Int > 50</Req>
<Req>Str &lt; 40</Req>
<Say>Jsi sice chytrý, ale příliš slabý pro tento ůkol</Req>

Posledním typem jsou číselné výrazy, které kromě jednoduché rovnosti a nerovnosti (stejný zápis jako u textových výrazů), umožňuje i použití znamínek < (menší) a > (větší). Samozřejmostí také znamínka ⇐ (menší nebo rovno) a >= (větší nebo rovno).

Co vás v tomto příkladu výše určitě zarazilo, je zvláštní zápis &lt;. Ale neděste se, není to nic jiného než znamínko <. Při psaní interakce je nutné ho zapisovat tímto způsobem, kvůli využití v samotném XML formátu. Pokud chcete použít operátor „menší nebo rovnou, ⇐„, musíte zapsat “&lt;=„.

Na závěr této první části o podmínkách, bych jen zdůraznil nutnost textové hodnoty uzavírat do uvozovek a naopak číselné hodnoty v uvozovkách být nesmí.

7. Jiná cesta okolo brány vede přes rozcestí

V minulé kapitole jsem se zmínil o hledání jiné cesty, pokud je brána zavřená (podmínka není splněná). V příkladech však zatím byla vždy pouze jediná cesta a při neprůchodnosti interakce skončila. To určitě není také vždy žádoucí a chceme vytvořit i reakci pro ostatní hráče, aby jim nepřipadalo, že něco nefunguje. Je dobré se naučit tohle respektovat, protože NPC, které přestane reagovat, je pro hráče matoucí. Abychom mohli toto udělat, je nutné vytvořit určité rozcestí.

<Interaction ID="Brandon_Ishar">
  <Procedure ID="doubleclick">
    <Trigger WaitOn="Doubleclick" Range="3" />
    <If>
      <Req>Name="Pepa"</Req>
      <Say>Nazdar Pepo</Say>
      <End />
    </If>
    <Say>Dobrý den, #pane#paní#</Say>
  </Procedure>
</Interaction>

Trochu rozšířený příklad z minula. Podíváme se blíže co se to tu děje. Vidíte zde nový speciální příkaz <If>, který označuje začátek podmínkového bloku neboli větve chcete-li. Pokud použijeme analogii s bránáma, tak <If> je něco jako boční ulička a jako správný dobrodruhové jí musíme prozkoumat. Tam však hned narazíme na bránu a pokud se hráč nejmenuje Pepa, nemůže bránou projít a musí se vrátit. Pak nezbývá nic jiného než jít rovnou za nosem, kde už narazíme jen na pozdrav pro všechny ostatní.

Důležité pravidlo je, že při použití <If> musí být veškeré <Req> podmínky ihned za tímto <If>. Tedy analogicky, brána musí být ihned na začátku postranní cesty. Pokud bychom je umístili doprostřed, už se nelze vrátit a interakce skončí.

Ještě bych zmínil další speciální příkaz <End />. Ten si můžete představit jako neprůchodnou zeď nebo ještě lépe jako past, ve které náš pomyslný hrdina uvízne. Jakmile totiž dosáhne tohoto bodu, nemůže se vrátit ani pokračovat dál a interakce skončí. Pokud bychom toto v příkladu neuvedli, tak bude cesta pokračovat dál a Pepa bude pozdraven jeho jménem a poté znovu jako neznámý cizinec. To zajisté není žádoucí.

<Req>Race = "Human"</Req>
<If>
  <If>
    <Req>IsCraft</Req>
    <Req>Dex >= 50</Req>
    <Say>Buď pozdraven##a# obratn#ý#á# řemesln#íku#ice#.</Say>
    <End />
  </If>
  <If>
    <Req>IsPriest</Req>
    <Say>Buď pozdraven##a# služebn#íku#ice# boha.</Say>
    <End />
  </If>
</If>
<Say>Dobrý den, #pane#paní#</Say>

Než budete pokračovat ve čtení, tak se zkuste zamyslet, jak tento příklad bude asi fungovat. V prvním případě máme podmínku na rasu a odfiltrujeme tak všechy hráče, kteří nemají lidskou rasu. NPC na ně nebude reagovat, ale to není chyba pokud dodržíme, že na ně nebude reagovat nikde v interakci, takže pro tyto hráče se bude NPC tvářit jako když interakci nemá.

Dále pak narazíme na rozcestí, kde není žádná brána. To není v těchto případech případě nutné, protože toto rozcestí se dále dělí do dvou dalších cest. Jako správný dobrodruh vyzkoušíme postupně obě cesty, co kdyby jedna z nich byla správná ? V prvním směru ověřujeme, že je hráč kraft a má obratnost minimálně 50. Pokud některou z těchto podmínek nesplňuje, vrátíme se a jdeme další cestou hledající kněze (nezávisle na zvoleném bohu). A pokud ani přes tuto bránu neprojdeme, vrátí se na úplně první rozcestí a pokračuje přímo k pozdravu pro všechny ostatní. Pokud by však za druhým <If> blokem byl příkaz <End />, jsme chyceni do pasti a nelze se pokračovat ani se vrátit, ale znamenalo by to, že hráč nesplňující žádnou z podmínek by byl ignorován.

<If>
  <Req>Race != "Human"</Req>
  <Say>Bež pryč, nechci s tebou mluvit</Say>
  <End />
</If>

Tady máme ukázku lepšího řešení předchozí problému s rasou. Otočením podmínky zajistíme reakci pro hráče, který není člověk a nechceme s ním mluvit o ničem. Tedy pro všechny ostatní tady cesta končí. Zbytek interakce zůstává stejný.

<Req>Race = "Human" or Race = "Hobit"</Req>

Na závěr problematiky podmínek zmíním ještě tuto možnost, kdy můžete v jedné podmínce otestovat více výrazu najednou. Použitím spojovacího slovíčka or vytváříte situaci „buď a nebo“. Jinými slovy tento příklad ověřuje jestli je hráč rasy člověk nebo hobit. Toto se hodí pokud potřebujete vyvolat stejnou reakci na různé situace. V žádném případě nevytvářejte zbytečná rozcestí, kde budete reakci zdvojovat. Pomocí slovíčka or můžete spojít i více podmínek, nejenom dvě.

<If>
  <Req>Race != "Human"</Req>
  <Req>Race != "Hobit"</Req>
  <Say>Bež pryč, nechci s tebou mluvit</Say>
  <End />
</If>

Pro úplnost tady máme i opačné řešení této „buď a nebo“ situace. Tady ověřujete, že hráč není člověk a zároveň není hobit, tedy má jakoukoliv jinou rasu a tím pádem s ním nechceme mluvit.

8. Měníme a nastavujeme

Touto krátkou kapitolou bych zcela uzavřel problematiku výrazů. Výrazy totiž neslouží jen k zobrazování a testování hodnot. Pomocí výrazů můžeme provádět i zápis do některých hodnot. V současnosti jich není příliš mnoho, ale určitě se budou možnosti rozrůstat.

Stejně jako pro testování podmínek máme speciální příkaz Req, tak pro nastavování hodnot slouží příkaz Set. Příkaz je velmi podobný zmíněnému Req.

<Set>Hits = 20</Set>

Takže jak vidíte, opět se vše zapisuje mezi otevírací a ukončovací značku příkazu. Toto je nejjednoduší podoba příkazu, kdy do výrazu Hits (tedy počet hitpointů hráče) přiřadíme číslo 20. Je nutné dodržet způsob zápisu, kdy nalevo máme výraz, do kterého přiřazujeme. Ten musí být vždy následovaný operátorem = a poté následuje hodnota, na kterou nastavujeme. Toto nám obvykle ale nestačí, takže jdeme dále.

<Set>Mana = ManaMax</Set>

O trochu užitečnější varianta, která instantně doplní manu hráče na jeho povolené maximum. Dále si pak všimněte, že výrazy lze použít i na pravé straně. To lze snadno využít k dalším operacím.

<Set>Hits = Hits + 20</Set>

Systém tedy podporuje jednoduché matematické operace. K současnému počtu životů hráče můžeme přičíst 20 čímž ho trochu vyléčíme. Nebo naopak při použití znamínka - (mínus) hráče zraníme. Stejně tak lze použít operátory * pro násobení a / pro dělení. Více toho bohužel nelze, ale obvykle to je pro potřeby questů dostačující.

Při nastavování Hits, Mana, Stam není nutné kontrolovat, zda přesahuje maximum (nebo jde do mínusu), systém si to ohlídá sám a nedovolí překročit povolený rozsah.

9. Přikazuju ti, abys skočil

Ne, vy nemusíte nikam skákat ani vám nic nepřikazuji. V této kapitole se jen zaměříme na obecné použití základních příkazu a podíváme se na příkazové bloky, do kterých lze doslova skákat.

Doposud jsme poznali pouze jednoduché příkazy jako Req, Set, Say a Emote jejichž jediným parametrem byl text uzavřený mezi počáteční a ukončovací značkou. Narazili jsme také na speciální příkaz End, které nemá žádné parametry, ale přesto je poměrně důležitý. A v neposlední řadě už víme jak vytvořit spoušt pomocí speciálního příkazu Trigger. Speciální říkám proto, že má velmi specifický účel a pravidlo, kam ho můžete napsat, ale stále je to jen příkaz.

Pokud srovnáme příkazy s již probranými výrazy, tak asi největší rozdíl je v tom, že parametry příkazů mají každý své jméno oproti výrazům, kde parametry jsou určovány jen podle pořadi jak jdou za sebou. U příkazů na pořadí nezáleží. Druhý patrný rozdíl je v možnostech umístění. Výraz musíte umístit do Req nebo Set, ale příkaz téměř kamkoliv (kromě těch speciálních).

Dalším rozdílem oproti výrazům je, že u příkazů je nutné veškeré parametry uzavírat do dvojitých uvozovek bez ohledu na typ. Samozřejmě však musíte dodržet, že pokud je parametr číselný, tak abyste tam vkládali jen čísla. Pokud je parametr logického typu, tak použijte text „true“ pro ano a „false“ pro ne. A ted par prikladu:

<AddExperience Amount="30" />
<Say>Tady máš 30 expů</Say>
<GiveMoney Gold="1" Silver="500" />
<Emote>neochotně předává hrst peněz</Emote>
<Blacklist WholeCity="true" />
<Say>Haha a teď jsi hledaný mezi strážnými ty zloději!</Say>

Myslím, že to pro názornost bohatě stačí. Teď se podíváme na slibované bloky příkazů. Tedy jakákoliv množina po sobě jdoucích příkazu je považována za blok příkazů. Pokud máte např. Procedure, tak příkazy v ní obsažené utvářejí blok příkazu. Stejně tak podmínkový blok uzavřený v If příkazech tvoří další blok příkazů.

Každý blok příkazů má své jméno. U Procedure toto jméno určujete použitím parametru ID. Podmínkové bloky mají také své jméno, ale je vygenerované systémem a v současnosti nezměnitelné ani nezjistitelné. A k čemu je to všechno dobré ? Takto pojmenovaný blok příkazů můžete snadno zavolat pomocí příkazu Jump nebo Call.

<Interaction ID="Brandon_Ishar">
  <Procedure ID="dvojklik">
    <Trigger WaitOn="Doubleclick" />
    <Say>Teď zemřeš !</Say>
    <Attack />
  </Procedure>
  <Procedure ID="jsem napaden">
    <Trigger WaitOn="Damage" />
    <Jump Block="dvojklik" />
  </Procedure>
</Interaction>

Menší příklad využívající dvě spouště. Co vlastně dělá ? Pokud hráč dvojklikne na npc, bude okamžitě napaden s patřičnou hláškou. Pokud naopak na npc zautočí a způsobí mu nějaké zranění, dojde k zavolání bloku příkazu „dvojklik“ a hráč je napaden stejně jakoby dvojkliknul.

<Interaction ID="Brandon_Ishar">
  <Procedure ID="dvojklik">
    <Trigger WaitOn="Doubleclick" />
    <Trigger WaitOn="Damage" />
    <Say>Teď zemřeš !</Say>
    <Attack />
  </Procedure>
</Interaction>

Malá odbočka od tématu ukazující zkrácenou verzi předchozího příkladu. Tedy do Procedure můžete takto jednoduše zapsat více spouští, které mají mít stejnou reakci.

Aby toto všechno mělo větší smysl, tak samozřejmě můžete utvářet vlastní bloky příkazů, které lze následně volat. Toto se velmi hodí, pokud máte v interakci nějakou část, která se opakuje na více místech. Abyste nemuseli vše kopírovat na několik míst, tak vytvoříte vlastní blok příkazů.

<Interaction ID="Brandon_Ishar">
  <Command ID="dej odmenu">
    <AddExperience Amount="60" />
    <Give Item="Carrot" Amount="10" />
    <Say>Děkuji ti za vyřešení mého problému</Say>
    <Emote>uklonila se</Emote>
  </Command>
  <Procedure ID="dvojklik">
    <Trigger WaitOn="Doubleclick" />
    <Call Block="dej odmenu" />
    <Say>A přístě na mě neklikej !</Say>
  </Procedure>
</Interaction>

Takže jak vidíte, je to velmi snadné. Samozřejmě příklad je záměrně jednoduchý. V reálné situaci nebudete blok příkazů volat takhle přímo z procedury, to by ztrácelo smysl. Všimněte si, že Command je definován na stejné úrovni jako Procedure. Nelze ho vytvořit např. uvnitř této procedury, to systém nedovolí.

Ještě vysvětlím rozdíl mezi příkazy Jump a Call. Oba mají společné, že skočí do požadovaného bloku, ale při použití Jump se pomyslenému skokanovi neotevře padák a na zemi se rozplácne. Tedy po provedení celého bloku příkazů interakce skončí. Naopak použitím Call se provede zadaný blok a interakce pokračuje od místa, kde se blok příkazů zavolal.

Snadno to vidíte také na příkazu výše. Pokud by misto Call bylo Jump, tak už npc neřekne „A přístě na mě neklikej !“.

Bloky příkazů můžete volat téměř odkukoliv, dokonce i z jiných bloků, jen dejte pozor abyste se v tom nezamotali a nevolali dva bloky navzájem Smile

10. Tvorba první interakce

Jelikoz nejsem taková expertka na všechny ty pojmy, které Fredy používá, vezmu vše z trochu jiného pohledu a to z pohledu lajka. Při tvorbě první interakce si musíme nejprve uvědomit co chceme udělat za interakci. Pro začátek by mohl stačit jednoduchy diagram, ktery si nacrtnete treba na papir. Diagram by mel obsahovat nejaky vstup/vstupy (triggery), dale bloky, dialogy a podminky. Vse je dobre dopredu promyslet, sice vysledek vetsinou vypada uplne jinak, ale aspon mate z ceho vychazet.

Jak postupovat dále: 1) Vytvoříme si prázdný xml soubor. (pokud nemáte vhodný editor na úravu textu doporučuji stáhnout PSPad)

2) Kódování a verze: Na začátek každe interakce je třeba vložit. Bez toho by vám interakce nemuse fungovat, při použití znaků, které jsou celkem hojné.

<?xml version="1.0" encoding="utf-8"?>

Dále si zkontrolujte, zda máte v PSPadu také zatrhnutý UTF-8 (Formát/UTF-8). Také je vhodné zmínit, že diakritika nepatří do ID ani různých názvů tagů, pouze do textu, který se zobrazí hráčům. Mezeru v názvech a ID nahrazujeme podtržítkem _. Ne, že by to bylo vysloveně nutné, ale může se zde pak vyskytnout chyba.

3) Tag interakce: Vše je nutné zapisovat mezi tyto tagy. / vždy znamená konec tagu.

<Interaction ID="ZDE NAPÍŠETE JMÉNO INTERAKCE">
ZDE JE CELÁ INTERAKCE KROMĚ KÓDOVÁNÍ
</Interaction>

Jména interakce se dávají následovně: „jménoNPC_Město(popř. konkrétní místo)“ existují i vyjímky, ale pojmenování není nejdůležitější a dá se vždy upravit.

4) Dále tu máme 6 částí interakce Zápisky, Předměty, NPC, Spouště, Příkazy, Dialogy. Je dobré označit v interakci, kde co začíná a končí. Před začátkem určitého úseku se vloží <!–########## ##########–

>. U zápisků to bude vypadat asi takto:

Kód: <!–########## Zápisky ##########–

>

Tento zápis slouží k lepší orientaci v interakci. Nebude mít žádný vliv na chod, zároveň je vlastně komentářem, ale to si probereme až za chvíli.

5) Kaskádování tagů a uspořádání textu: Je dobré kaskádovat tagy podle toho, který je „nadřazený“ a „podřazený“. Počátek interakce pak může vypadat třeba takto:

<?xml version="1.0" encoding="utf-8"?>
<Interaction ID="Aurane_TzirUlar">
  <!--########## Zápisky ##########-->
  <Stage Name="Pavučiny pro Aurane" MWQEposition="0">
    <Objective ID="-1">Konečně to mám za sebou.</Objective>
    <Objective ID="1">Mám donést sto pavučinek abych potěšila Lloth.</Objective>
    <Objective ID="2">Sakra, Aurane předstírá, že řekla o padesát víc. </Objective>
    <Objective ID="3">Vypadá to, že si na mne zasedla. Zas mám donést o padesát víc.</Objective>
  </Stage>
...

Obykle se kaskáduje TABem. Všimněte si, jak to jde hezky zkopce a do kopce. Interaction je nadřazené všemu, tudíž je úplně na začátku, Zápisky jsou Interakci podřazené, Stage má stejnou podřazenou jako Zápisky. Objective je zase podřazený ke Stage a když má stage skončit, je na stejné úrovni jako začínal. Z toho plyne, že tag, který je nadřazený na začátku, bude nadřazený i na konci a podžazený také.

Můžete si tu také všimnout, že každý tag má svůj řádek. Pokud tedy Stage bude obsahovat další tagy jako je Objective, jeho ukončení bude na samostatném řádku až úplně na konci, kdy už žádný Objective nechceme vložit. Objective v sobě již žádný tag nemá, takže jeho ukončení se může napsat na stejný řádek jako počátek.

Někdy není nutné psát ukončení tagu samostatně a místo <End></End>, se může napsat jen <End />.

Tyto „typografická“ pravidla není nutné dodržovat pro chod interakce, při její údržbě a editaci je to však celkem nutná záležitost.

6) Komentáře: Vkládají se většinou za tagy a mají upřesňovat situaci editorovi. Pokud víte, že na interakci budete chtít pokračovat třeba za týden, je to také celkem nezbytná věc, abyste nezapoměli, jak interakce funguje a nepokoušeli jste se jí celou pochopit od začátku. Má také objasňovat situaci, pokud je editorem jiné GM, které interakci netvořilo. Já osobně komentáře nepoužívám, ale to je asi věc každého. Pokud jsou udělané kvalitně, můžu editaci zjednodušit, pokud nejsou, pak to mohou jeětě zhoršit. Komentář vypadá třeba takto:

<!--########## Zde se kontroluje, zda má hráč dostatečný level ##########-->

7) Diagram:

Diagram si můžete udělat i v hlavě. Je důležitý hlavně proto, abyste nezapoměli na nějaké podmínky například a vše si řádně promysleli, co s čím bude propojené a podobně. Blocky jak vidíte jsou spojené se Stage, protože z nich kontrolují průběh questu. Samotné podmínky už jsou obsažené přímo v blocích. Nyní si zkusíme interakci pro takový diagram vytvořit. Jen se omlouvám v Blocku Kontrola_Questu ma být místo „Questu“ být slovo „Ukolu“ Smile.

8) Interakce:

<?xml version="1.0" encoding="utf-8"?>
<Interaction ID="Kovar_Zikmund_Ishar">

<!--########## Zápisky ##########-->
  <Stage Name="Prubeh_Ukolu" Title="Kladivo pro kováře">
    <Objective ID="-1">#Dokončil#Dokončila# jsem úkol pro kováře Zikmunda. Konečně má své kladivo.</Objective>
    <Objective ID="1">Kovář mě poprosil, jestli bych mu nepřinesl##a# nové kovářské kladivo.</Objective>
  </Stage>
  
<!--########## Spouště ##########-->  
  <Procedure ID="Zikmund_OnDoubleClick">
    <Trigger WaitOn="OnDoubleClick" Range="3" />
    <Jump Block="Kontrola_Ukolu_Block" />
  </Procedure>

<!--########## Příkazy ##########-->
  <Command ID="Kontrola_Ukolu_Block">
    <If>
      <Req>stage("Prubeh_Ukolu")==-1</Req>
      <Jump Block="Ukonceny_Ukol_Block" />
    </If>
    <If>
      <Req>stage("Prubeh_Ukolu")==1</Req>
      <Req>HasItem("SmithHammer", 1)</Req>
      <Jump Block="Odmena_Block" />
    </If>
    <If>
      <Req>stage("Prubeh_Ukolu")==0</Req>
      <Show Dialog="Zadani_Ukolu_Dialog" />
    </If>
    <End />
  </Command>
  
  <Command ID="Ukonceny_Ukol_Block">
    <Say>Zdravím tě!</Say>
    <Emote>buši kladivem do kovadliny</Emote>
    <Animation Play="11" Duration="10" Target="this" />
    <End />
  </Command>
  
  <Command ID="Odmena_Block">
    <Say>A vidím, že máš mé nové kladivo, tady máš něco od cesty.</Say>
    <Emote>podává váček s penězi</Emote>
    <GiveMoney Gold="0" Silver="200" />
    <AddExperience Amount="50" />
    <SetStage Name="Prubeh_Ukolu" ID="-1" />
    <End />
  </Command>

  <Command ID="Neprijeti_Ukolu_Block">
    <Say>Jakej dědula!</Say>
    <Emote>mává po tobě kladivem</Emote>
    <End />
  </Command>
  
  <Command ID="Zadani_Ukolu_Block">
    <SetStage Name="Prubeh_Ukolu" ID="1" />
    <Say>Vrať se brzy.</Say>
    <End />
  </Command>
  
<!--########## Dialogy ##########-->
  <Dialog ID="Zadani_Ukolu_Dialog">
    <Text>A helemese. Zdravim. Já jsem Zikmund, místní kovář. Neměl##a# bzste chvíli čas? Potřebuji totiž sehnat nové kladivo. Staré dosluhuje. *přehodil poničené kladivo s jedné ruky do druhé a pak zase zpět* Odměna vás nemine.</Text>
    <Choice>
      <Text>Stejně teď nemám co dělat. Hned jsem zpět s novým.</Text>
      <Jump Block="Zadani_Ukolu_Block" />
    </Choice>
    <Choice>
      <Text>Nejsem poslíček dědulo.</Text>
      <Jump Block="Neprijeti_Ukolu_Block" />
    </Choice>
  </Dialog>
  
</Interaction>

Snad z tohoto nemusím nic vysvětlovat. Není zde použito nic neobvyklého, ale případné dotazy zodpovím na SZ. Interakci jsem nekontrolovala, takže tam může být nějaká menší chyba Smile, ale neměla by.

9) Větší a menší: Místo < (menší) a > (větší) při porovnávání tagů ve hře (něco jiné než tag v interakci), skillů, statů a jiných vlasnosti se používá &lt; (lower than) a &gt; (greater than). Je to jistější forma, protože < a > zároveň uzavírají tagy.

[size=large][u]Něco málo od Fredyho:[/u][/size] UseWorldObject Prepracovan prikaz UseWorldObject, ktery slouzi pro vynuceni dvojkliku na predmet danym npc. Tedy muze napriklad otevrit dvere nebo stisknout paku. Mejte vsak na pameti, ze je nutne dodrzet stejna pravidla jako u hrace. Takze musi byt dodrzena vzdalenost, pri ktere muze pouzit dany predmet hrac. Stejne tak pokud jsou treba zamcene dvere, tak npc u sebe musi mit klic, neumi otevrit dvere, ktere maji jen nastaveno Blocked. Pro otestovani si tedy stoupnete na stejne misto jako npc a vypnete gm mod.

<UseWorldObject Location="1254,2548" Item="BaseDoor" />

Princip je tedy zalozen na hledani predmetu urciteho typu (nebo typu z nej pochazejiciho) na danych souradnicich (X,Y). Do Item tedy muzete primo urcit treba WoodenDoor, coz najdete v zahlavi [props daneho objektu. Hleda se pouze na tom jednom policku, nikde jinde a pouziji se vsechny nalezene objekty, nejen prvni.

Jeste ohledne dveri. Je to zvlastni, ale zavrene dvere jsou na jinych souradnicich nez otevrene. To ma tedy za nasledek, ze kdyz npc dvere otevre, tak uz je neumi zavrit. Zatim me nenapada jak to poresit. Chtel jsem zvysit dosah pro hledani na 1, ale pak jsem narazil na problem u linknutych dvoukridlych dveri, ktere se otevreli a ihned zase zavreli.

Teoreticky je mozne dvojkliknout i na jine npc, ale netestoval jsem co se stane. Mozna by takto slo iniciovat rozhovor, ale moc tomu neverim Smile Kód: <UseWorldObject Location=„1254,2548“ Mobile=„BaseGuard“ />

AllowIgnored Se zavedenim noveho typu trestu se neaktivuje zadny trigger pro hrace, ktery je v danem meste ignorovan. Toto chovani lze zmenit u kazdeho triggeru zvlast pomoci noveho atributu AllowIgnored, ktery nastavite na „true“. Toho lze vyuzit u NPC, kteri maji predstavovat pomocniky pro tyhle ruzne padouchy, na ktere byl uvalen trest. Kód: <Trigger WaitOn=„DoubleClick“ AllowIgnored=„true“ /> Dale tu mame drobne rozsireni prikazu Visible a Invisible, ktere doposud slouzilo k hidnuti, resp. odhidnuti npc. Toto je vsak globalniho razu a neprilis vhodne pro questy, kde se npc ukaze hracum, kteri postoupili dal v questu. Takze byl pridan atribut Single, kterym povolite pouziti tzv. VisibleListu. To znamena, ze npc se bude skryvat/odkryvat pouze pro daneho hrace, se kterym je prave spustena interakce. Mejte vsak na pameti, ze pokud pouzijete takove skryvani, meli byste ho pouzit na vsech mistech interakce. Systemu to sice nevadi, ale vysledek by nebyl prilis zajimavy.

Soubory http://www.manawydan.cz/wiki/Interakce.rar Tady můžete stáhnout editor interakcí. Já osobně ho nepoužívám, ale je celkem srovnatelný s PSPadem, nedá se v něm však vyhledávat ve vice souborech a podobně, ale pro začátek dobré. Dále tam je seznam všech tagů a jejich stručný popis. Ne vždy je věe správně a ne vždy vše funguje jak má (něco nefunguje vůbec, tak to berte trochu s rezervou), ale hodí se to když něco zapomenete a podobně. Hlavně vidíte co vše a jak můžete použít.

Zbytek je o praxi. Věe bohužel popsat nejde, z toho by byla kniha, takže jestli máte jakěkoli otázky ohledně interakcí šup s nima na SZ. Na vše se pokusím odpovědět. Kdo má ICQ, může i na ICQ Smile. Něco málo od Zlaté Rybičky (tušim):

ZÁKLAD soubor: Jméno (popis) - Telian (starý bylinkář) id: Jmenomesto - Telianeldamar

altGr + X

~ altGr + 1

odevzdala##a# rád#$a#

PŘÍKAZY

<Say>Zdravím tě!</Say>
<Emote>vrazil ti do rukou bednu přestal si tě všímat</Emote>
<Emote Target="Target">začíná se rozplývat ve vzduchu</Emote>
<Wait Time="1"/>

<Give Item="Apple" Amount="20" />
<Get Item="Bread" Amount="10" />
<Req>target.GetItem("Bread", 10)</Req>

<GiveMoney Silver="150" />
<AddExperience Amount="150" />
<AddExperience NoMessage=1 Amount="150" />

<Animation Play="Bow" Target="this" Duration="3" />
<Animation Play="11" Target="This" Duration="1"/>
<Sound Play="498" Target="This" />

<Move x="5903" y="3170" z="0"/>
<Direction Location="Down" Target="This"/>
<Direction Location="South" Target="This"/>
<Turn Target="This" To="target" />
<Invisible Target="this"/>
<Visible Target="this"/>

<Go Location="Target" MaxRange="10" />
<Go Location="(3060,1801,0)" />
<Run Location="(3075,1780,0)" />
<Wait TargetInRange="3" MaxRange="16" />

<Log>Port postavy z města Eldamar do města Ishar.</Log>
<Message>Ziskal##a# jsi bednu zboží pro Tiluara.</Message>
<VendorBuy/>

<Show Dialog="e1" />
<Call Block="goto16" />
<End/>

PODMÍNKY

<Req>Stage("Poprvé ve městě")==3</Req>
<Req>Stage("Eldroth~Poprvé ve městě")==1</Req>

<Req>this.NumericTag("pracuje")==0</Req>
<Req>this.Tag("Hráč co mě navštívil")=="Fredy"</Req>


<Req>target.GetItem("Bread",10)</Req>
<Req>target.HasItem("Bread", 10)</Req>
<Req>target.ObjectItem("ZboziSolur", "inpack", "target")</Req>
<Req>target.Object("Questovní postava","props","Hits")>10</Req>    
zda questovní postava má víc než 10 hp

<Req>target.Female</Req>        InGuild, IsPriest, IsCraft
<Req>target.Str==20</Req>
<Req>target.Str>=30</Req>
                Str,Int,Dex,Hits,HitsMax,Mana,ManaMax,Stam,StamMax, Level
            BodyValue, Alignment(přesvědčení), Race, Profession, Faith(víra), Skill, Perk
<Req>target.Profession=="Nobody"</Req>
<Req>target.Race =="Special"</Req>
<Req>target.Race !="Elf"</Req>
<Req>target.Level==0</Req>
<Req>target.Level &gt;= 31</Req>


<Req>target.Hits < target.HitsMax</Req>
<Req>target.Race=="Elf" or Stage("Zboží kapitána Solura")>0</Req>
<Req>target.Hits &lt; target.HitsMax</Req>
<Req>target.Hunt("hunters") >= target.NumericTag("hunters_pocet")</Req>


<Req>Random(50)==20</Req>

<Req>this.Expire("pauza")</Req>                pokud už  vypršela doba
<Req>IsInStageTime("Utek z vezeni",2,0,0,0)</Req>    je to méně než 2 dny

<Req>target.Hunt("ork_grotdob_udaflug_lov_2")>19</Req>
<Req>target.Hunt("Krysy_pole") &gt;= 3</Req>

SET

<SetStage Name="Poprvé ve městě" ID="5" />
<Set>target.NumericTag("EldrothUkol")=2</Set>
<Set>this.NumericTag("Drevo")=this.NumericTag("Drevo")+5</Set>

<Set>this.Tag("Hráč co mě navštívil")=target.Name</Set>
<Req>this.Tag("Hráč co mě navštívil")=="Fredy"</Req>

<Set>target.Hits = target.Hits + 200</Set>

RANDOM

<Text>bla bla @RandomString('prvni text','druhy text','treti text')@</Text>
<Say>@RandomString('prvni text','druhy text','treti text')@</Say>
<Emote>@RandomString('prvni text','druhy text','treti text')@</Emote>

<Req>Random(50)==20</Req>    od nuly do padesáti
<Req>Random(1,10)==5</Req>

<Trigger WaitOn="Doubleclick" />
<Set>this.NumericTag("nahoda")=Random(3)</Set>
<If>
  <Req>this.NumericTag("nahoda")==1</Req>
  <Show Dialog="1" />
</If>

EXPIRE

<Expire Target="this" Name="pauza" Minutes="1" />
<Expire Target="target" Name="pauza_dungeon_sidlo_lapku" Hours="22"/>
<Expire Target="this" Name="Za dve a pul hodiny" Hours="2" Minutes="30" />

<Req>!target.Expire("pauza")</req>
<Req>this.Expire("pauza")</Req>
<Req>target.Expire("pauza_dungeon_sidlo_lapku")</Req>

<If>
<Req>target.Expire("pauza")</Req>
<Say>
</If>
<Emote>
pokud časovač vypršel, bude sayovat, pokud ještě nevypršel, bude emotovat
pokud už vypršelo 5 dní, řekni

<Req>IsInStageTime("Navsteva souseda",3,30)</Req>
<Req>IsInStageTime("Utek z vezeni",2,0,0,0)</Req>

je to méně než 3 minuty a 30 sekund / 2 dny

HUNT

<Hunt Name="Krysy_pole" Type="GiantRat"  Location="Manawydan(5887,2650,5891,2658)" />
<Hunt Name="sin_hrdinu_kralovny" Type="OphidianQueen" Location="Manawydan(10,10,6738,6563)"/>

<Req>target.Hunt("sin_hrdinu_balori")>0</Req>
<Req>target.Hunt("ork_grotdob_udaflug_lov_2")>19</Req>
<Req>target.Hunt("Krysy_pole") &gt;= 3</Req>

<HuntEnd Name="sin_hrdinu_vzdusni_elementalove"/>
<HuntEnd Name="ghuloveuhobitu"/>

ITEMCREATOR, MOBILECREATOR

<ItemCreator Name="ZboziSolur" Type="QuestItem">
<Props Name="Name" Value="Bedna látek pro Tiluara" />
<Props Name="Movable" Value="false" />
<Props Name="ItemID" Value="3645" />
<Props Name="DisplayQuality" Value="False"/>
<Props Name="Hue" Value="60"/>
<Props Name="Blocked" Value="true" />
</ItemCreator>

<Command ID="setstage5" MWQEposition="5">
<CreateItem Name="ZboziSolur" />
<AddToBackPack Name="ZboziSolur" Target="target" />
<Emote>vrazil ti do rukou bednu přestal si tě všímat</Emote>
<Message>Ziskal##a# jsi bednu zboží pro Tiluara.</Message>
<SetStage Name="Zboží kapitána Solura" ID="5" />
<End />
</Command>

<CreateItem Name="NejakyItem" Location="1111;2222;20" />
<CreateNPC Name="NejakaPostava" Location="1099;1980;20" />
<AddInteraction Name="NejakaPostava" Interaction="JinaInterakce" Trigger="OnKill" />

<Req>target.ObjectItem( "ZboziSolur", "inpack", "target")</Req>
<DeleteItem Target="target" Name="ZboziSolur" />


<ItemCreator Name="klic" Type="GuardKey" >
<Props Name="Name" Value="Klíč od vobludy"/>
<Props Name="ItemID" Value="4115"/>
<Props Name="Hue" Value="2590"/>
<Props Name="MaxUses" Value="1"/>                 počet použití
<Props Name="KeyValue" Value="660660"/>          tady zadat hodnotu zámku
</ItemCreator>


<MobileCreator Name="NalezcePodkovy" Type="NPC_Human" Unique="true">
<Props Name="Name" Value="Pepa z depa" />
<Props Name="Home" Value="(1099,1980,20)" />
<Props Name="RangeHome" Value="11" />
<Quest Interaction="Tarnel" Trigger="nalezceVidi" />
<Quest Interaction="Tarnel" Trigger="nalezceMluvi" />
</MobileCreator>    


<ItemCreator Name="zed_1" Type="QuestItem" Unique="yes">        unikátní, nebudou se tvořit kopie
<ItemCreator Name="klic" Type="GuardKey" Multiple="yes">        ne do tagu, tvoří se kolik chceš
<ItemCreator Name="NejakyPredmet" Type="QuestItem" Global="yes" />     lze najít i v jiné interakci pokud:
<ItemCreator Name="ZboziSolur" Type="QuestItem" Global=“yes“ />

TRIGGERY

<Trigger WaitOn="Doubleclick" Target="Player.Durinova zhouba" />

Doubleclick – Range (3) Damage – zraněno, MinDamage (1), MaxDamage (999) Emote – Text (nic), Range (20) GameTime – Moon (Toru, Novu, Sarva, Luna), Hour (0-5), Min (0-59) Heal – léčena, MinHeal (1), MaxHeal (999) Kill Pass – X (horní), Y, Z (0), RX (dolní), RY, PlacedItem – X, Y, Z (kontejner) RealTime – Hour (0-23), Min (0-59) Say – Text (nic), Range (20) See – Range (3) Skill – činnost, Name ( Názvy akcí definovány ve skriptech. Za akci je považována pouze IexclusiveAction), Range (20) TargetedByEffect – Effect TargetedBySpell – kouzlo nebo modlitba, Spell ZAJÍMAVÉ PASÁŽE <code><If> <Req>this.Tag(„Plni quest“)!=““</Req> <Req>this.Tag(„Plni quest“)==target.Name</Req> <SetStage Name=„Jsem na questu“ ID=„1“ /> <Set>this.Tag(„Plni quest“)=target.Name</Set> <Say>Pospeš si</Say> </If> A tohle bude na tom druhem NPC <If> <Req>Stage(„Jsem na questu“)==1</Req> <Say>Nazdar bačkoro ! Tady to máš a padej zpátky !</Say> <SetStage Name=„Jsem na questu“ ID=„2“ /> </If> Nakonec navrat k prvnim NPC a splneny quest <If> <Req>Stage(„Jsem na questu“)==2</Req> <Req>this.Tag(„Plni quest“)!=„“</Req> <Req>this.Tag(„Plni quest“)==target.Name</Req> <SetStage Name=„Jsem na questu“ ID=„-1“ /> <Set>this.Tag(„Plni quest“)=„“</Set> <Say>A máš to za sebou</Say> </If> <Req>Stage(„Lovci nestvůr“) >= 1</Req> <Req>target.HasItem(„QuestItem“,1,„Oprávnění k lovu nestvůr vydané cechem lovců“)</Req> <Req>target.Hunt(„hunters“) >= target.NumericTag(„hunters_pocet“)</Req> <HuntEnd Name=„hunters“/> <SetStage Name=„Lovci nestvůr“ ID=„-1“/> <DeleteItem Target=„target“ Name=„smlouva“/> <Req>target.Expire(„pauza_hunters“)</Req> <Command ID=„urcenileveluaschopnosti“> <Set>this.NumericTag(„nahodahunters“)=RANDOM(0, 4)</Set> <If> <Req>target.Level = 1</Req> <Jump Block=„level_1_4“/>
</If> <Command ID=„level14“> <If> <Req>this.NumericTag(„nahodahunters“)=0</Req> <Show Dialog=„lov1_0“/>
</If> <Dialog ID=„lov10“> <Text>„Tak, jediné co tu pro tebe mám je smlouva na 25 Slizů.“</Text> <Choice> <Text>Jo, to beru. Hned jdu na ně.</Text> <Hunt Name=„hunters“ Type=„Slime“ Location=„Manawydan(10,10,6142,4094)“/> <Set>target.NumericTag(„hunterspocet“)=25</Set> <SetStage Name=„Lovci nestvůr“ ID=„1“/> <CreateItem Target=„target“ Name=„smlouva“/> <AddToBackPack Name=„smlouva“ Target=„target“/> <Say>Nezapomeň že bez loveckého oprávnění ti nemohu vyplatit tvou odměnu. Neztrať ho!</Say> <Expire Target=„target“ Name=„pauzahunters“ Hours=„10“/><Jump Block=„konec“/> </Choice> <Choice> <Text>Rozmyslel@ifString(target.Female, „a“, „“)@ jsem si to.</Text> <Expire Target=„target“ Name=„pauza_hunters“ Hours=„10“/> <Say>No dobře, tak zmiz a neotravuj!</Say> <Jump Block=„konec“/> </Choice> </Dialog> <Give Target=„target“ Item=„SilverCoin“ Amount=„target.Level * 127“/> <AddExperience Target=„target“ Type=„M“ Amount=„target.Level * 73“/> <Set>this.NumericTag(„pocetpenez“)=target.Level * 127</Set> <Message Target=„target“>@IfString(target.Female, „Získala“, „Získal“)@ jsi odměnu ve výši @this.Tag(„pocetpenez“)@ stříbrných.</Message> </code> OTAZNÍKY ExecuteInteraction <code><ExecuteInteraction ProcedureID=„Procedura“ /> <UseWorldObject Serial=„xxx“ /></code> Hodnotu pro atribut Serial zjistite pochopitelne z [props konkretniho objektu. Toto ma samozrejme nevyhodu, ze pokud objekt prestane existovat, prestane vase interakce fungovat. Ale z kodu jsem pochopil, ze zpusobi Doubleclick na libovolnem NPC nebo predmetu ve svete. Tedy podobne jakoby na dany objekt poklikal hrac. </code> Jednoduchy prikaz, ktery spusti libovolny trigger v dane interakci. Nelze tedy spustit trigger na jinem NPC (krome tech dynamicky vytvorenych interakci). <code><Interaction ID=„NejakaInterakce“> <Procedure ID=„Procedura“> <Trigger WaitOn=„Code“ /> <Say>Jsem k nicemu</Say> <End /> </Procedure> <Command ID=„Prikaz“> <Say>Jsem taky k nicemu, ale furt lepsi nez ta procedura nademnou</Say> <End /> </Command> <Command ID=„PrikazVola“> <ExecuteInteraction ProcedureID=„Procedura“ /> <Call Block=„Prikaz“ /> </Command> </Interaction></code> [u]UseWorldObject[/u] Skryty prikaz, na ktery jsem narazil nedavno. Jeho vyuziti je mi taky zahadou. Ale z kodu jsem pochopil, ze zpusobi Doubleclick na libovolnem NPC nebo predmetu ve svete. Tedy podobne jakoby na dany objekt poklikal hrac. Tohle je prvni prikaz, ktery umoznuje pristup k jinym objektum nez tem co vznikly v interakci. Mozna se casem dockame dalsich. <UseWorldObject Serial=„xxx“ /> Hodnotu pro atribut Serial zjistite pochopitelne z [props konkretniho objektu. Toto ma samozrejme nevyhodu, ze pokud objekt prestane existovat, prestane vase interakce fungovat. Kouzlení <code><Cast Spell=„LightSpell“ Affect=„target“ Formula=„Budiž světlo!“ /></code> Povinné atributy: Spell … systémový název třídy kouzla, můžete jej zjistit např. v Bestiáři, v souboru Spells.xml, Prayer.xml, nebo ve skriptech. Nepovinné atributy: Target … kdo kouzlo sesílá, implicitně „this“ (npc) Affect … na koho kouzlo působí, implicitně „target“. Formula … implicitně formule kouzla. U modliteb je záhodno text psát, mělo by tam jít použít interaktivní text (klasika #usmál se#usmála se#) Příklad je použit v interakci Example01.xml ====== 11. Perky ====== Celý systém je založený na interakčním systému díky čemuž je možné každého učitele vytvořit na míru aby to nebyl jen panák co učí perky. Doporučené minimum je interakce, kde se učitel trochu představí, popíše svoje zkušenosti, oznámí hráči cenu za výuku a spustí samotnou výuku. Výuka se spouští následovně: Kód: <ExecuteCode Class=„Server.Gumps.PerkTeachingGump“ Method=„Offer“ Price=„$this.Tag(„price“)“ /> Všimněte si parametru Price, kde je místo konkretní hodnoty použitý výraz (nutné aby na začátku byl znak $). Je to kvůli tomu abyste mohli měnit cenu za výuku bez nutnosti změny interakce. Jen nastavíte na tag na učiteli. Ovšem můžete tam napsat i normální číslo nebo parametr úplně vynechat a pak je výuka zadarmo. Cena je pochopitelně ve stříbrných a odečítá se sama ihned po výběru perku. Než však bude NPC schopné něco naučit, musíte ho naucit vy požadované perky. To se provádí přes příkaz [setperk (detaily v dokumentaci). Příkazem [perks si pak můžete zobrazit aktuální nastavení (funguje i na hráče). Klíčový tady je perk Teacher (Učitel). Bez něj nebude NPC schopné naučit nic. Platí také, že pro výuku perku 1. stupně potřebuje npc učitelský perk na minimálně 1. úrovni. Tedy s učitelskou úrovni 3 bude NPC schopné naučit až do 3. stupně vybraného perku. Ovšem to pouze za předpokladu, ze vybraný perk opravdu umí na 3. stupni. Nyní zpět k příkazu spouštějící výuku. Tento je unikátní v tom, že jako jediný vyvolává zpětnou reakci přes interakční systém. Tedy např. když si hráč vybere určitý perk, dostanete na to odezvu v interakci a můžete na ni reagovat. Zároveň je však zajištěno, že pokud nevytvoříte vlastní reakci, použije se předdefinovaná, kterou najdete v souboru Data\Interaction\PerkTeachingTemplate.xml. Pokud se na soubor podíváte blíže, uvidíte zde sérii Command bloku. Zvláštní pozornost věnujte jejich pojmenováni. To označuje právě reakci na určitou událost vyvolanou ve výuce. Nad každým příkazem máte stručný komentář, kdy dojde k vyvolání daného příkazu. Pokud tedy chcete nějakým způsobem změnit reakci, jednoduše okopírujte požadovaný blok příkazů a umístěte do vaší interakce. Poté už ho můžete upravit dle libosti. Standardní reakce se bude ignorovat. Jestliže pouze chcete přidat k reakci něco navíc aniž byste měnili tu standardní (např. nastaveni stage), použijte ve vaší interakci následující zápis: <code><Command ID=„OnPerkSelection“> <Call Block=„PerkTeachingTemplate.OnPerkSelection“ /> <SetStage Name=„vyuka“ ID=„1“ /> </Command></code> Na závěr bych zmínil dva nové výrazy související s učením perků, které můžete v interakci využít. První obsahuje český název perku jehož výuka právě probíhá. <code><Say>Učím se @LearningPerkName@</Say> <Req>LearningPerkName!=„“</Req> Druhý zápis je spíš jen pro pořádek indikující, že probíhá výuka nějakého perku, ale vhodnější je použít následující: Kód: <Req>IsLearningPerk</Req></code> Ten navíc ověřuje, zda současná výuka probíhá u tohoto učitele. Seznam perků (systémové názvy pro použití v Interakci) …. příklad použití naleznete v TEST_PERKU.XML Obecné: <code>SkillFocus UseLightArmor ImprovedLore Persuation Bodybuilding Acrobatics MentalTraining Languages BlowingWeapon ExplosiveMastery Concentration Teacher</code> Bojové <code>UseMediumArmor UseHeavyArmor UseShield CombatReflexes DefensiveCombat MissileDeflected MountedCombat Trample RidingAttack Aim StrongArm RainOfArrows MovingShot QuickMotion StrongBlow Berserker AnimalMastery BloodPact AnimalSense WeaponFinesse CrushingAttack StunningAttack WhirlwindAttack Disarm LightningAttack DirectAttack Drill Leadership RacialEnemy Taunt</code> Magické: <code>CombatCasting MaximizeSpell ExtendSpell CorpseSkin ImprovedMeditation PyroMaster HieloMaster JiMaster EnergyChange SoulThief AnimateDead StrongWill StrongCommand AstralLink ElementalHarmony ElementalMasteries LordOfElements MaximizePrayer TurnUndead HealMaster DestructionMaster SoulMaster</code> Tulácké: <code>LegendaryLore ChangeIdentity MusicTalent ImprovedStealth CombatTraining Backstab Alertness LightningReflexes SilverHand Mobility DefenceStance Counterstrike ScrollKnowledge ArcaneKnowledge MagicShackles</code> Řemeslné: <code>Haggling CarefulCraftsman PrecisionCraftsman MasterSmelter Metalurgy Engineer JewelMaster WeaponSmith ArmorSmith MasterTanner MasterSkinner MasterWeaver MasterTailor MasterCarver MasterCarpenter MasterAnimalHandler AnimalBreeding MasterFarmer Cultivate HerbMaster MasterCook Botany HealthScienceMastery EnchantingMastery ExplosivesMastery PoisonsMastery QuackDoctor</code> ====== 12. Propojení interakcí ====== Propojení interakcí je jednoduché…buď toho docílíme skrze tagy, které jsou nastavené na hráče či NPC a nebo pomocí stage. Propojení pomocí stage funguje tak, že před požadované ID stage (jméno) se vloží jméno ID interakce a za něj „~“. V praxi to pak vypadá nějak takhle: <code> <Req>Stage(„Eldroth~Poprvé ve městě“)==1</Req> </code> kde „Eldroth“ je ID interakce a „Poprvé ve městě“ je ID stage v dané interakci…nic složitého :-).