Skriptování: Porovnání verzí

Z EreborWiki
Přejít na: navigace, hledání
(Založena nová stránka s textem „Na této stránce naleznete nějaká doporučení a informace o skriptování, která se snažíme dodržovat. Pokud se chystáte provádět nějaké změn…“)
 
(Vyhodnocování podmínek)
 
(Není zobrazeno 5 mezilehlých verzí od stejného uživatele.)
Řádka 1: Řádka 1:
 
Na této stránce naleznete nějaká doporučení a informace o skriptování, která se snažíme dodržovat. Pokud se chystáte provádět nějaké změny, ujistěte se, že znáte i [[Scripting standard]].
 
Na této stránce naleznete nějaká doporučení a informace o skriptování, která se snažíme dodržovat. Pokud se chystáte provádět nějaké změny, ujistěte se, že znáte i [[Scripting standard]].
 +
 +
Doporučuji si projít stránku [[Skripty - názvosloví]], kde jsou uvedeny některé běžně používané termíny.
  
 
== Na co si dát pozor ==
 
== Na co si dát pozor ==
Řádka 28: Řádka 30:
 
=== Pořadí vyhodnocení ===
 
=== Pořadí vyhodnocení ===
  
Sphere vyhodnocuje argumenty podmínek zleva. Výraz @IF (f_one && f_two)@ tedy nejprve vyhodnotí @f_one@ a poté @f_two@
+
Sphere vyhodnocuje argumenty podmínek zleva. Výraz <code>IF (f_one && f_two)</code> tedy nejprve vyhodnotí <code>f_one</code> a poté <code>f_two</code>
  
 
=== Eval - magické slovo ===
 
=== Eval - magické slovo ===
  
Ve spoustě podmínek a vyhodnocení výpočtů se používá klíčové slovo @eval@. Co ale znamená a kdy ho (ne)použít?
+
Ve spoustě podmínek a vyhodnocení výpočtů se používá klíčové slovo <code>eval</code>. Co ale znamená a kdy ho (ne)použít?
  
@Eval@ je zkrácením anglického evaluate = vyhodnotit/ohodnotit. Výsledkem operace eval je '''vždycky''' decimální '''neprázdná''' hodnota. Použití tohoto klíčového slova je tedy vhodné na místech, kde sphere
+
<code>Eval</code> je zkrácením anglického evaluate = vyhodnotit/ohodnotit. Výsledkem operace eval je '''vždycky''' decimální '''neprázdná''' hodnota. Použití tohoto klíčového slova je tedy vhodné na místech, kde sphere
  
 
# sama nedokáže rozhodnout, že se má zadaný výraz vyhodnotit jako číslo
 
# sama nedokáže rozhodnout, že se má zadaný výraz vyhodnotit jako číslo
Řádka 40: Řádka 42:
 
<pre>
 
<pre>
 
if (<eval src.qtag(q001_borek)> == 0)
 
if (<eval src.qtag(q001_borek)> == 0)
</pre> Tento kód by byl *bez* použití volání @eval@ nekorektní, protože volání @<src.qtag(q001_borek)>@ nad hráčem, který daný tag vůbec nemá, vrátí prázdný string, tedy žádnou hodnotu. Sphere by tím pádem po vyhodnocení levé strany rovnosti porovnávala kód:<pre>
+
</pre> Tento kód by byl '''bez''' použití volání <code>eval</code> nekorektní, protože volání <code><src.qtag(q001_borek)></code> nad hráčem, který daný tag vůbec nemá, vrátí prázdný string, tedy žádnou hodnotu. Sphere by tím pádem po vyhodnocení levé strany rovnosti porovnávala kód:
 +
<pre>
 
if ("" == 0)
 
if ("" == 0)
</pre> což je zcela nevalidní podmínka a takový běh vyhodí ERROR. Volání funkce @eval@ na prázdný string ovšem vrátí nulu, což je již korektní podmínkou:<pre>
+
</pre>
if (0 == 0)
+
což je zcela nevalidní podmínka a takový běh vyhodí ERROR. Volání funkce <code>eval</code> na prázdný string ovšem vrátí nulu, což je již korektní podmínkou. Takto bude sphere postupovat ve vyhodnocování výrazu s <code>eval</code>em:
 +
<pre>
 +
1.    if (<eval ""> == 0)
 +
2.    if (0 == 0)
 +
</pre>
 +
 
 +
=== Magická nula v podmínkách ===
 +
 
 +
Ve skriptech se můžete setkat s podivnou podmínkou, která vypadá nějak takhle
 +
<pre>
 +
if (0<src.qtag(q001_borek)> == 1)
 +
</pre>
 +
Tato syntaxe řeší stejný problém, který je popsaný v sekci pro Eval. V případě, že <code>src.qtag(q001_borek)</code> není vůbec definovaný, vyhodnocení podmínky bez přidané nuly by způsobilo chybu. Oproti tomu dodatečná nula na začátku podmínky způsobí, že test bude vždy vyhodnocovat porovnání čísel.
 +
 
 +
'''Ovšem pozor!!''' Není pravda, že by platilo následující
 +
<pre>
 +
if (010 == 10)
 +
</pre>
 +
Tato podmínka bude vyhodnocena jako nepravda. Čísla začínající nulou jsou ve sphere interpretována jako šestnáctková, ne desítková. Šestnáctková soustava má tedy v každém řádu šestnáctinásobek. Číslo 010 je tedy ve skutečnosti 16 v desítkové, 011 == 17, 012 == 18, 0A je 11, 0B je 12 atd. Proto pro ošetření testu podmínek na hodnotu tagu, který nemusí existovat, musíte buďto ošetřit očekávánou hodnotu na její šestnáctkový equivalent:
 +
<pre>
 +
if (0<src.qtag(q001_borek)> == 010) // 010 namisto očekávaných 10 -> transformace očekávané hodnoty do 16 soustavy na obou stranách podmínky
 +
</pre>
 +
nebo můžete využít funkci <code>eval</code>, jak bylo zmíněno v předchozí sekci.
 +
<pre>
 +
if (<eval src.qtag(q001_borek)> == 10)
 
</pre>
 
</pre>
  
Řádka 73: Řádka 100:
 
name=nove jmeno
 
name=nove jmeno
 
</pre>
 
</pre>
 +
 +
=== Kontrola Syntaxe ===
 +
 +
Pro kontrolu syntaxe máme k dispozici vlastní [[Analyzer skriptů]], který provede statickou analýzu.

Aktuální verze z 3. 1. 2022, 15:02

Na této stránce naleznete nějaká doporučení a informace o skriptování, která se snažíme dodržovat. Pokud se chystáte provádět nějaké změny, ujistěte se, že znáte i Scripting standard.

Doporučuji si projít stránku Skripty - názvosloví, kde jsou uvedeny některé běžně používané termíny.

Na co si dát pozor

Linkování

Ukládání UID předmětu do proměnné LINK pevně sváže existenci cílového předmětu s předmětem, který má LINK uložený. To znamená, že pokud cílový předmět zmizí (je na hráči a ten si smaže postavu, smaže se chybným scriptováním při timeru nebo jiné akci), pak objekt s LINK proměnnou na toto UID se smaže také!

Best practice

  1. Pro linkování objektů používejte raději tagy vhodného jména, aby bylo jasné, za jakým účelem a co se v dané proměnné drží.
  2. Vždý, když vytváříte odkaz (ať už tagem, nebo linkem), ujistěte se, že linkee vždýcky smaže z linkeru referenci na sebe. V žádném případě nesmí nikdy nic odkazovat na UID, které se již smazalo! Toto UID může ve velmi krátkém sledu dostat naprosto jiný objekt a tím zcela randomizovat chování (kontrola na type nebo ID odkazovaného předmětu není dostatečnou náhradu za nedůsledné odmazávání odkazů)
  3. Pro odkazování skupiny předmětů používejte funkce:
f_customLink_add
f_customLink_remove
f_customLink_target

, případně pro dialogy:

f_item_linkAdder
f_item_LinkRemover
f_dialog_LinkWriter

Vyhodnocování podmínek

Pořadí vyhodnocení

Sphere vyhodnocuje argumenty podmínek zleva. Výraz IF (f_one && f_two) tedy nejprve vyhodnotí f_one a poté f_two

Eval - magické slovo

Ve spoustě podmínek a vyhodnocení výpočtů se používá klíčové slovo eval. Co ale znamená a kdy ho (ne)použít?

Eval je zkrácením anglického evaluate = vyhodnotit/ohodnotit. Výsledkem operace eval je vždycky decimální neprázdná hodnota. Použití tohoto klíčového slova je tedy vhodné na místech, kde sphere

  1. sama nedokáže rozhodnout, že se má zadaný výraz vyhodnotit jako číslo
  2. vyhodnocení výrazu může vést k prázdnému stringu, který by v testech vedl k chybě (ERROR). Příklad:
if (<eval src.qtag(q001_borek)> == 0)
Tento kód by byl bez použití volání eval nekorektní, protože volání <src.qtag(q001_borek)> nad hráčem, který daný tag vůbec nemá, vrátí prázdný string, tedy žádnou hodnotu. Sphere by tím pádem po vyhodnocení levé strany rovnosti porovnávala kód:
if ("" == 0)

což je zcela nevalidní podmínka a takový běh vyhodí ERROR. Volání funkce eval na prázdný string ovšem vrátí nulu, což je již korektní podmínkou. Takto bude sphere postupovat ve vyhodnocování výrazu s evalem:

1.    if (<eval ""> == 0)
2.    if (0 == 0)

Magická nula v podmínkách

Ve skriptech se můžete setkat s podivnou podmínkou, která vypadá nějak takhle

if (0<src.qtag(q001_borek)> == 1)

Tato syntaxe řeší stejný problém, který je popsaný v sekci pro Eval. V případě, že src.qtag(q001_borek) není vůbec definovaný, vyhodnocení podmínky bez přidané nuly by způsobilo chybu. Oproti tomu dodatečná nula na začátku podmínky způsobí, že test bude vždy vyhodnocovat porovnání čísel.

Ovšem pozor!! Není pravda, že by platilo následující

if (010 == 10)

Tato podmínka bude vyhodnocena jako nepravda. Čísla začínající nulou jsou ve sphere interpretována jako šestnáctková, ne desítková. Šestnáctková soustava má tedy v každém řádu šestnáctinásobek. Číslo 010 je tedy ve skutečnosti 16 v desítkové, 011 == 17, 012 == 18, 0A je 11, 0B je 12 atd. Proto pro ošetření testu podmínek na hodnotu tagu, který nemusí existovat, musíte buďto ošetřit očekávánou hodnotu na její šestnáctkový equivalent:

if (0<src.qtag(q001_borek)> == 010) // 010 namisto očekávaných 10 -> transformace očekávané hodnoty do 16 soustavy na obou stranách podmínky

nebo můžete využít funkci eval, jak bylo zmíněno v předchozí sekci.

if (<eval src.qtag(q001_borek)> == 10)

OR Operátor @||@

Vyhodnotí se, pokud je alespoň jedna strana operátoru pravdivá. Vzhledem k pořadí vyhodnocení, použití tohoto operátoru svádí ke klasickému využití línému vyhodnocování. ANI HOVNO přátelé. Sphere vždy vyhodnotí funkce na obou stranách operátoru, a až když má výsledky, vyhodnotí výsledek OR operátoru.

Z výše zmíněného, následující nelze použít:

if (!act || act.isitem) // pokud je act 0 vyhodi ERROR kvuli nemoznosti vyhodnotit 'isitem' nad null objektem
  act.color=012
  act.name=nove jmeno
endif

Podmínku je tedy nutné vyřešit nadmíru hnusně a perverzně, jako správné kodérské prase! Ale protože jsme vzdělaná prasata, stejný kód v podmínce alespoň zabalíme do funkce:

...
if (!act) // pokud je act 0 vleze do podminky
  act.f_manipulateAct
elseif (act.isitem) // uz vime, ze act neni 0, takze volani je bezpecne
  act.f_manipulateAct
endif

// the function is called upon the ACT
// takes NO arguments
[function f_manipulateAct]
color=012
name=nove jmeno

Kontrola Syntaxe

Pro kontrolu syntaxe máme k dispozici vlastní Analyzer skriptů, který provede statickou analýzu.