Dink Smallwood Italia

  • Aumenta dimensione caratteri
  • Dimensione caratteri predefinita
  • Diminuisci dimensione caratteri

Parte 9: Un mercante e un guaritore

(0 voti, media 0 di 5)
In questa parte della guida imparerete come creare menu selettivi, mercanti e come interagire con gli oggetti dell’inventario.
Come prima cosa dal WinDinkEdit posizionatevi all’interno del villaggio che avete creato e costruite una bottega per il vostro mercante. Costruitene gli interni, arredatela come volete, quindi inserite il mercante e create per lui uno script. Se volete fate in modo che si muova, quindi modificate lo script come segue:

void main (void)
{
   say_stop("`6Buongiorno!", ¤t_sprite);
}

void talk (void)
{
   int &itemp;

   freeze(1);
   freeze(¤t_sprite);
   say_stop("`6Salve! Posso fare qualcosa?", ¤t_sprite);
   wait(300);
   choice_start();
   set_y 240
   set_title_color 6
   title_start();
   Salve! Posso fare qualcosa?
   title_end();
   "Vorrei comprare qualcosa"
   "Lascia perdere"
   choice_end();

   if (&result == 1)
   {
      &itemp = count_item("item-sw1");
      say_stop("Vorrei comprare qualcosa... Cosa vendete?", 1);
      wait(300);
      if (&itemp > 0)
      {
         say_stop("`6Al momento non ho nulla...", ¤t_sprite);
         wait(300);
         say_stop("Ah capisco...", 1);
  } else
  {
  say_stop("`6Vediamo... Al momento ho soltanto questa splendida spada...", ¤t_sprite);
  wait(300);
  say_stop("Fantastico! Quanto costa?", 1);
  wait(300);
  say_stop("`6Beh costa soltanto 400 monete. La vuoi comprare?", ¤t_sprite);
  wait(300);

  if (&gold < 400)
  {
  say_stop("Peccato, non ho abbastanza denaro...", 1);
  wait(300);
  say_stop("`6E allora non farmi perdere altro tempo!", ¤t_sprite);
  goto endtalk;
  }

  choice_start();
  set_y 240
  set_title_color 15
  title_start();
  Vuoi comprare la spada per 400 monete?
  title_end();
  "Si'"
  "No"
  choice_end();

  if (&result == 1)
  {
  &itemp = free_items();
  if (&itemp < 1)
  {
  say_stop("Non ho abbastanza spazio nell'inventario!", 1);
  wait(300);
  say_stop("`6E allora non farmi perdere altro tempo!", ¤t_sprite);
  goto endtalk;
  }

  say_stop("Certo! Ecco il denaro!", 1);
  &gold -= 400;
  wait(300);
  say_stop("`6Perfetto! Prendi pure la spada!", ¤t_sprite);
  add_item("item-sw1", 438, 7);
  } else
  {
  say_stop("No grazie!", 1);
  wait(300);
  say_stop("`6Bene, se tu dovessi cambiare idea io sono sempre qui");
  }
  }
  } else
  {
  say_stop("No, grazie!", 1);
  }
  endtalk:
  unfreeze(1);
  unfreeze(¤t_sprite);
  return;
}

Lo script appena presentato contiene numerosi comandi nuovi, ma prima di partire all'analisi accurata procedete con la costruzione del D-Mod. Create un'altra abitazione che sarà la dimora del guaritore, quindi inserite un personaggio che faccia da guaritore e collegategli il seguente script:

void main (void)
{
  say_stop("`7Salve buon uomo!", ¤t_sprite);
}

void talk (void)
{
  int &var;
  freeze(1);
  freeze(¤t_sprite);
  say_stop("`7Salve, che posso fare per te?", ¤t_sprite);
  wait(300);
  choice_start();
  set_y 240
  set_title_color 7
  title_start();
  Salve, che posso fare per te?
  title_end();
  (&life < &lifemax) "Curami"
  "Vorrei comprare un elisir ($25)"
  "Lascia perdere"
  choice_end();

  if (&result == 1)
  {
     &var = &lifemax;
     &var -= &life;
     say_stop("Ho bisogno di cure!", 1);
     wait(300);
     say_stop("`7Vediamo... Si', sei ferito!", ¤t_sprite);
     wait(300);
     say_stop("`7Ti guariro' per &var monete...", ¤t_sprite);
     if (&gold < &var)
     {
        wait(300);
        say_stop("Non posso permettermi le cure!", 1);
        wait(300);
        say_stop("`7Beh mi dispiace ma qui la sanita' costa!", ¤t_sprite);
        goto endtalk;
     }
     choice_start();
     set_y 240
     set_title_color 15
     title_start();
     Vuoi essere curato per &var monete?
     title_end();
     "Si'"
     "No"
     choice_end();

     if (&result == 1)
     {
     say_stop("Ecco il denaro! Curami!", 1);
     wait(300);
     say_stop("`7Sara' fatto!", ¤t_sprite);
     spawn("mag-star");
     &gold -= &var;
     &life = &lifemax;
     wait(300);
     say_stop("Grazie", 1);
     goto endtalk;
     } else
     {
     say_stop("No, dopotutto non sto cosi' male!", 1);
      wait(300);
     say_stop("`7Ehi la vita e' tua!", ¤t_sprite);
     goto endtalk;
     }
  }

     if (&result == 2)
     {
     &var = count_item("item-eli");
     &var -= 5;
     say_stop("Vorrei comprare un elisir curativo...", 1);
     wait(300);
     if (&var >= 0)
     {
     say_stop("`7Mi dispiace ma devo ancora prepararne!", ¤t_sprite);
     wait(300);
     say_stop("Oh... capisco...", 1);
     wait(300);
     say_stop("Tornero' piu' tardi...", 1);
     goto endtalk;
     }
     say_stop("`7Si' si' ne ho appena creato qualcuno... 25 monete...", ¤t_sprite);
     wait(300);
     if (&gold < 25)
     {
     say_stop("Diamine non ho abbastanza denaro!", 1);
     wait(300);
     say_stop("`7Beh mi dispiace ma qui la sanita' costa!", ¤t_sprite);
     goto endtalk;
     }
     &var = free_items();
     if (&var == 0)
     {
     say_stop("Non ho abbastanza spazio nell'inventario!", 1);
     wait(300);
     say_stop("`7Allora dovresti fare un po' di spazio, non credi?", ¤t_sprite);
     goto endtalk;
     }
     say_stop("Ecco il denaro!", 1);
     &gold -= 25;
     wait(300);
     say_stop("`7Ed ecco l'elisir! Spero che tu non debba mai usarlo!", ¤t_sprite);
     add_item("item-eli", 438, 11);
     wait(300);
     say_stop("Grazie!", 1);
     goto endtalk;
   }

  if (&result == 3)
  {
     say_stop("No, grazie!", 1);
  }
  endtalk:
  unfreeze(1);
  unfreeze(¤t_sprite);
  return;
}

Dopo che avrete esaminato i due script presentati si potrà passare all'analisi accurata delle novità in essi contenute.

Menu selettivi
Le scelte sono una parte cruciale di ogni videogioco di ruolo che si rispetti e Dink Smallwood include un semplice sistema di menu selettivi che può fare al caso. Si prenda in esame la porzione di codice dello script del guaritore:

choice_start();
set_y 240
set_title_color 7
title_start();
Salve, che posso fare per te?
title_end();
(&life < &lifemax) "Curami"
"Vorrei comprare un elisir ($25)"
"Lascia perdere"
choice_end();

Noterete che la sintassi del frammento qui presentato in parte differisce dalla solita sintassi del DinkC. Per prima cosa è fondamentale che tutto ciò che deve far parte di un menu a selezione sia contenuto tra il comando choice_start() e il comando choice_end(). I due comandi altro non fanno che dire al programma che tutto ciò che si troverà fra di essi dovrà essere interpretato come dati relativi al menu.
Ora, i menu si suddividono in due parti: il titolo e le scelte, la prima facoltativa, la seconda – ovviamente – obbligatoria. Il testo del titolo deve trovarsi fra i due comandi title_start() e title_stop() e non deve essere delimitato da nulla. Il programma interpreterà tutto ciò che è contenuto fra i due comandi come mero titolo ad eccezione della stringa “title_end();” e delle variabili. È inoltre possibile impostare il colore del titolo utilizzando il comando (al di fuori del gruppo title_start() - title_end()) set_title_color. La sintassi del comando differisce da quella dei comandi standard in quanto l'attributo non deve essere contenuto fra parentesi tonde e non deve essere seguito dal punto e virgola. Per cui:

Corretto: set_title_color 7
Scorretto: set_title_color(7);

Il testo del titolo potrà inoltre contenere delle variabili così che i rispettivi valori appaiano nel testo finale. Tanto per capire, un codice del tipo:

int &prova = 1;
choce_start();
title_start();
Prova e' &prova
title_end();
“OK”
choice_end();

mostrerà come testo:

“Prova è 1”

Per quanto riguarda le scelte, esse dovranno occupare ognuna una riga differente e dovranno essere contenute all'interno di virgolette. Per cui un menu a tre scelte dovrà apparire come il seguente:

“Scelta 1”
“Scelta 2”
“Scelta 3”

Le scelte possono essere anche condizionali, ovvero appaiono esclusivamente se una certa condizione viene soddisfatta. L'esempio nel frammento di script all'inizio di questo paragrafo è:

(&life < &lifemax) “Curami”

In questo caso la scelta “Curami” apparirà solo ed esclusivamente se il valore della variabile &life, ovvero quella che controlla il numero di punti ferita attuali sia strettamente minore al valore della variabile &lifemax, ovvero quella che controlla il numero massimo di punti ferita. Nell'esempio presentato quindi la scelta “Curami” apparirà soltanto se Dink sarà stato ferito o se in qualunque altro modo il suo valore di punti ferita attuali sia minore a quello dei punti ferita massimi.
A regolare nello script la scelta selezionata è la variabile &result. Essa otterrà un valore differente in base alla scelta selezionata e sarà 1 se si selezionerà la prima voce, 2 se si selezionerà la seconda, 3 se si selezionerà la terza e così via, quindi nel frammento di script precedente:
 
Scelta Valore di &result 
(&life < &lifemax) "Curami"
"Vorrei comprare un elisir ($25)"
"Lascia perdere"
 
È molto importante che sappiate che la variabile &result è unica e vale per tutte le selezioni, per cui fate molta attenzione quando annidate diverse scelte perché potreste trovarvi con errori particolarmente fastidiosi e difficili da rilevare. Un esempio di script pericoloso potrebbe essere il seguente:

void main(void)
{
   freeze(1);
   choice_start();
   "Scelta 1"
   "Scelta 2"
   choice_end();

   if (&result == 1)
   {
      choice_start();
      "Scelta A"
      "Scelta B"
      choice_end();

      if (&result == 1)
      {
         say_stop("1A", 1);
      }
      if (&result == 2)
      {
         say_stop("1B", 1);
      }
   }

   if (&result == 2)
   {
      choice_start();
      "Scelta A"
      "Scelta B"
      choice_end();

      if (&result == 1)
      {
         say_stop("2A", 1);
      }
      if (&result == 2)
      {
         say_stop("2B", 1);
      }
   }
   unfreeze(1);
   kill_this_task();
}

Lo script è perfettamente funzionante, tuttavia un errore logico ne mina l'esecuzione. Se ad esempio il giocatore facesse  la scelta 1B rimarrebbe in memoria la variabile &result con il suo valore 2 (dovuto al secondo menu di scelta), per cui una volta che Dink mostrerebbe “1B” si aprirebbe anche il menu per la scelta 2A o 2B.
Negli script del negoziante e del guaritore il problema viene ovviato mediante un'istruzione di tipo goto. Essa non fa altro che interrompere il flusso regolare dello script per riprenderlo laddove è presente l'etichetta specificata dopo l'istruzione goto. Ecco un esempio per chiarire:

say(“Uno”, 1);
goto three;
say(“Due”, 1);
three:
say(“Tre”, 1);

Se si eseguisse l'esempio appena presentato noterete come Dink salterebbe il due, questo per via dell'istruzione goto che sposta il flusso del codice all'etichetta three. Come noterete l'etichetta usa un tipo di sintassi anomalo costituito dal nome della stessa seguito dai due punti.
Per cui una soluzione al problema precedente potrebbe essere la seguente:

void main(void)
{
   freeze(1);
   choice_start();
   "Scelta 1"
   "Scelta 2"
   choice_end();

   if (&result == 1)
   {
      choice_start();
      "Scelta A"
      "Scelta B"
      choice_end();

      if (&result == 1)
      {
         say_stop("1A", 1);
      }
      if (&result == 2)
      {
         say_stop("1B", 1);
      }
      goto stop;
   }

   if (&result == 2)
   {
      choice_start();
      "Scelta A"
      "Scelta B"
      choice_end();

      if (&result == 1)
      {
         say_stop("2A", 1);
      }
      if (&result == 2)
      {
         say_stop("2B", 1);
      }
   } 
   stop:
   unfreeze(1);
   kill_this_task();
}

Per chi fosse curioso – ma questo vale più come curiosità e non è strettamente inerente alla guida – viene presentata anche una soluzione alternativa molto più efficiente:

void main(void)
{
  int &var;
  freeze(1);
  choice_start();
  "Scelta 1"
  "Scelta 2"
  choice_end();

  &var = &result;

  choice_start();
  "Scelta A"
  "Scelta B"
  choice_end();

  if (&result == 1)
  {
     say_stop("&varA", 1);
  }
  if (&result == 2)
  {
     say_stop("&varB", 1);
  }

  unfreeze(1);
  kill_this_task();
}

Per concludere il discorso sui menu selettivi è bene spendere qualche ultima parola. Per prima cosa è importante sapere che i numeri dei colori del titolo corrispondono esattamente a quelli delle istruzioni say() e say_stop() con la sola differenza che l'istruzione set_title_color accetta esclusivamente valori numerici. Per cui se per impostare il colore bianco in say() bisognava utilizzare il carattere “%” (percentuale), per set_title_color bisogna utilizzare il valore 15. Ecco una tabella con i codici colore superiori al 9:
 
10 Verde chiaro 
11Giallo 
12 Giallo 
13 Rosa scuro 
14 Giallo 
15 Bianco 
 
Esiste in fine un'istruzione chiamata set_y che determina a che altezza dello schermo dovrà trovarsi il primo elemento del menu. Quindi un'istruzione tipo

set_y 240

imposterà la prima voce del menu alla coordinata y 240.

Oggetti e inventario
In Dink Smallwood ad ogni oggetto nell'inventario è collegato uno script che ne gestisce gli eventi di armo, disarmo e utilizzo. Il nome di questi script può essere utilizzato per riferirsi all'oggetto stesso, ad esempio se lo script che gestisce la spada è item-sw1.c a tutti gli oggetti di tipo spada ci si riferirà con “item-sw1”. Nello script del venditore ad esempio è presente la riga

&itemp = count_item("item-sw1");

Essa non fa altro che affidare alla variabile &itemp un valore pari al numero di oggetti di tipo “item-sw1” contenuti all'interno dell'inventario. Per cui la condizione if (&itemp > 0) è vera solo nel caso in cui Dink abbia almeno una spada all'interno dell'inventario.
Esistono diverse istruzioni che gestiscono gli oggetti e per ognuna di esse esiste il corrispettivo per la magia, generalmente basta sostituire lì dove dice “item” nell'istruzione con “magic”. Ad esempio così come esiste count_item() esiste anche count_magic(). Ecco una lista di tutte le istruzioni relative a oggetti e magia:
 
Istruzione Corrispettivo magia 
add_item() add_magic() 
arm_weapon() arm_magic() 
compare_weapon() Nessun corrispettivo 
count_item() count_magic() 
free_items() free_magic() 
kill_cur_item() kill_cur_magic() 
kill_this_item() kill_this_magic() 
 
Negli esempi precedenti sono state utilizzate solo alcune di queste istruzioni che saranno qui di segutio illustrate.

add_item(), così come add_magic(), consente di aggiungere all'inventario (o all'elenco delle magie) un oggetto. La sua sintassi si costituisce così:

add_item(script, seq, frame);

script altro non è che lo script relativo all'oggetto, mentre seq e frame sono rispettivamente la sequenza e il frame dell'immagine che apparirà nell'inventario. In Dink Smallwood tutte le immagini degli oggetti sono raggruppate nella sequenza 438 (437 per le magie), ma nulla vi vieta di inserire qualunque sequenza o frame vi aggrada. Nelle due immagini seguenti vi sono gli elenchi degli sprite degli oggetti con relativo frame standard:

Magie (sequenza 437)
 
Oggetti (sequenza 438)
 
 
 
Esistono poi in Dink Smallwood una serie di script standard per gli oggetti. Ecco un elenco:
 
Script Oggetto 
item-axe Asce da lancio 
item-b1Arco 
item-b2Arco massiccio 
item-b3 Arco di fuoco 
item-bom Bomba 
item-bt Stivali 
item-eli Elisir curativo 
item-fb Palla di fuoco (incantesimo) 
item-fst Pugno 
item-ice Pioggia acida (incantesimo) 
item-nut Noce curativa 
item-p1Pergamena (incantesimo) 
item-pig Mangime 
item-sfb Super palla di fuoco (incantesimo) 
item-sw1 Spada 
item-sw2 Spada artigliata 
item-sw3 Spada di luce 

Quindi nello script del venditore c'è l'istruzione

add_item(“item-sw1”, 438, 7);

che si traduce in:

Aggiungi l'oggetto con script item-sw1 (spada) con sequenza 438 e frame 7

count_item() è una funzione che consente di ottenere il numero esatto di oggetti con lo script specificato contenuti nell'inventario. Un esempio di questa funzione è stato già presentato all'inizio del paragrafo.
Il suo utilizzo nello script del guaritore è invece particolare:

&var = count_item("item-eli");
&var -= 5;

Si tratta di un semplice escamotage per evitare che il giocatore possa acquistare altri elisir se già ne possiede 5. Infatti se ad esempio Dink possieda già 4 elisir, il valore finale di &var sarà 4-5 = -1, in questo modo la successiva condizione if (&var >= 0) sarà falsa, e quindi si potrà comprare un altro elisir.

Anche free_items() è una funzione e restituisce come valore il numero di slot dell'inventario (o della lista degli incantesimo per free_magic()) ancora liberi. L'esempio nello script del mercante consente di evitare che venga aggiunta la spada se nell'inventario non c'è spazio sufficiente.

Per quanto riguarda le altre istruzioni al di là di una semplice descrizione non saranno trattate all'interno di questa guida.
  • arm_weapon() arma l'oggetto identificato dalla variabile &cur_weapon;
  • compare_weapon() controlla se lo script specificato è quello dell'oggetto attualmente armato;
  • kill_cur_item() elimina l'oggetto attualmente armato;
  • kill_this_item() elimina il primo oggetto in inventario con lo script specificato;

È anche possibile creare oggetti propri costruendo degli script personalizzati, tuttavia questo argomento non sarà trattato qui.
 
Script esterni
Un'altra istruzione molto importante del DinkC è l'istruzione spawn(). Essa non fa altro che bloccare il flusso dello script, eseguire la procedura main dello script specificato nell'istruzione, quindi riprendere l'esecuzione normale. Nello script del guaritore è presente la riga:

spawn("mag-star");

Questa istruzione non fa altro che eseguire la procedura main contenuta nello script mag-star.c e nel caso specifico non fa altro che far apparire le stelline quando Dink viene curato.
Esiste un'altra istruzione estremamente utile che si chiama external(). Sostanzialmente ha la a stessa funzione di spawn() con la differenza che è possibile specificare anche la procedura da eseguire. Ad esempio un'istruzione del tipo

external(“script”, “talk”);

eseguirà la procedura talk contenuta nel file script.c.

Ricapitolando in questa nona parte della guida avete imparato come creare dei menu selettivi, come lavorare con le variabili di gioco, come lavorare con gli oggetti e come eseguire una procedura da uno script esterno. Giunti a questo punto della guida avete una conoscenza sufficiente sia del DinkC che di WinDinkEdit tale che vi consentirà di cimentarvi voi stessi nella creazione di D-Mod. Ad ogni modo nei capitoli successivi si continuerà la stesura di questo D-Mod di esempio per consolidare ciò che avete imparato e si tratteranno argomenti utili ad abbellire il vostro D-Mod. 

 

Ultime news

Risultati Carnage Contest 2011

Dopo tre mesi di attesa finalmente ecco i D-Mod partecipanti (con relativi download) e i risultati del Carnage Contest 2011!

  1. The Blacksmith's Trail
  2. Power of Blood
  3. Knight Soup
  4. Enter the Dead Dragon Carcass
  5. The End of Snoresville

Godeteveli!

PS: Per via di alcuni problemi con il precedente template, si è deciso di recuperare per qualche tempo quello originale. Si tratta comunque di una soluzione momentanea nell'attesa che vengano risolti i problemi con il vecchio template. Vi chiedo scusa per qualsiasi eventuale disagio. Grazie!


Sondaggio

Se potessi parteciperesti ad un contest di D-Mod?
 

Social

Ecco come contattarci attraverso i maggiori social network:

Facebook