###########################################################################
## Talk System v 0.8  - by Masklin Jun-2003
###########################################################################



Descripcin.
---------------------------------------------------------------------------

El Sistema de Conversacin (Talk System o TS) es un mdulo que aade
a los mapas Blade la posibilidad de incluir dilogos entre los
personajes.

El objetivo bsico ha sido que Talk System sea un mdulo independiente
que pueda aadirse fcilmente a cualquier mapa, liberando al programador
del control de las conversaciones. Slo es necesario disear y escribir
el flujo de la conversacin: TS se encargar del resto.

Esto es un Leeme, no un manual. Puede que en alguna versin aparezca
una documentacin mejor. Pero de momento se trata de un Mod de uso 
interno para Moria y no es necesario esmerarse en la documentacin.


Interfaz.
---------------------------------------------------------------------------

TS aade una nueva tecla a Blade (la tecla T por defecto) que permite
al jugador iniciar una conversacin con el NPC encarado. Si no hay nadie
en los alrededores o el NPC no tiene ninguna conversacin asociada ( o ha
agotado las disponibles), entonces TS muestra soliloquios al azar
predefinidos por el programador.

Si el NPC tiene un dilogo asociado entonces se inicia una conversacin. 
El dialogo puede mostrar, opcionalmente, varias respuestas alternativas.
El usuario podr moverse entre las distintas respuestas con el botn
derecho del ratn y activar la elegida con el botn izquierdo. Una 
respuesta puede finalizar la conversacin o continuar con nuevos dilogos.

Si el texto mostrado en pantalla no puede visualizarse completamente 
porque son demasiadas lneas, el jugador puede usar la rueda del ratn
para desplazar las lineas y poder visualizar todo el texto. En estos casos
se muestra una flecha a la derecha indicando que el texto no es completo.

Las conversaciones tambin pueden iniciarse como respuesta a determinados
eventos sin necesidad de que el jugador use la tecla de hablar.

El mapa de teclado es el siguiente:

	T		Iniciar conversacin
	
	PgUp		Desplazar el texto hacia arriba
	WheelUp	
	
	PgDown		Desplazar el texto hacia abajo
	WHeelDown  
	
	Tab		Siguiente respuesta
	R-Click
	
	Enter		Seleccionar respuesta
	L-Click
	
	Esc		Cancelar conversacin


TS aade tambin un Diario que se activa con la letra J (por defecto) que
el programador utiliza para mostrar la informacin ms relevante de las
conversaciones.

Funcionamiento general.
---------------------------------------------------------------------------

El programador disea uno o varios dilogos para cada NPC. Luego usa la
funcin 

Talk.Assign (pers.Name, 'Hola')    

para asignarle al personaje pers.Name el identificador (dlgId) del
dilogo inicial: en el ejemplo 'Hola'. Cada NPC mantiene el dlgId en
su estructura de datos de modo que al acercarse el player y pulsar
la tecla de hablar entra en funcionamiento TS y dispara el dilogo
asociado. El programador ya no tiene que intervenir para nada durante
el dilogo hasta que ste finaliza.

La estructura en la que se soportan los dilogos es bastante rica en
funciones, y se puede ampliar si resulta necesario. Es el propio TS
el que se encarga de todo pero el programador puede intervenir si lo
necesita.


Creacin de un dilogo.
---------------------------------------------------------------------------

Los dilogos se almacenan en estructuras definidas en un fichero python.
Por defecto, estos ficheros se encuentran en el directorio TS dentro del 
propio directorio del mapa actual. Existe a su vez un subdirectorio para
cada lenguaje de modo que TS carga los dilogos correspondientes al
lenguaje actual.

Un mapa puede almacenar todos los dilogos en un nico fichero o bien
crear un fichero para cada situacin. Esto depender de la cantidad y
longitud de las conversaciones. En principio tendran que definirse
cientos de conversaciones para que el rendimiento sea un factor a
considerar.

Cada dilogo se viene identificado por un cdigo elegido por el 
programador llamado dlgId que es nico para cada personaje. La estructura
de las conversaciones es compleja y viene explicada en el ejemplo que
se acompaa (example.py).


Asignacin de un dilogo.
---------------------------------------------------------------------------

Una vez creado una base de datos con los dilogos para usar TS basta con
importar:

import Talk

y cargar el dilogo:

Talk.Load ('example')

Ahora, al crear los NPC se le asigna el dlgId del dilogo inicial:

kt=Bladex.CreateEntity("Khor Tao","Knight_N", 4025.9325124, -522.02750974, -1561.13859313, "Person")
kt.Angle=1.63607286472
kt.Life=100
import Basic_Funcs
kt.Data=Basic_Funcs.PlayerPerson(kt)
kt.Data.ResetSounds("Khor Tao")
Talk.Assign (kt.Name, 'Hola')

El nombre de la entidad NPC, Khor Tao en el ejemplo, es importante
porque TS lo utiliza para encontrar el dilogo correspondiente. En 
la base de datos puede haber ms de un dilogo con el identificador
'Hola', pero slo uno asociado a Khor Tao.

El nombre tambin aparece en la conversacin por lo que hay que
evitar nombrar las entidades como Ork_234 y cosas por el estilo.

Una vez creados los NPC's y con su dlgId de inicio asignados, el 
jugador puede empezar su aventura e iniciar una conversacin con
los NPC's con slo pulsar la tecla de hablar.

Como veremos despues, los dilogos tambin pueden empezar como 
respuesta a un evento. Por otra parte, el programador podr llamar
en cualquier momento a la funcin Talk.Say para hacer que se
inicie una conversacin.

Resulta frecuente querer hacer que un NPC inicie una conversacin
cuando ve al jugador. Por eso, la funcin Assign admite un tercer
argumento opcional que le dice a TS el evento que provocar el 
dilogo. De momento slo hay un evento soportado: el NPC ve al
juegador y se indica con Talk.SeeEvent:

Talk.Assign (kt.Name, 'Te he visto', Talk.SeeEvent)

El NPC no empieza a hablar hasta que el jugador no se acerca a
menos de Talk.TSTalkRange (por defecto, 5 metros) y v al jugador.
El NPC no recupera su funcin estndar para SeeFunc hasta que
no finaliza la conversacin.


El comportamiento bsico.
---------------------------------------------------------------------------

En el diseo de la conversacin es posible indicar las diferentes
respuestas asociadas a cada texto de una conversacin. Por cada
respuesta elegida se indica cul es el siguiente dilogo. 

Las respuestas elegidas por el jugador son deshabilitadas para que
no vuelvan a aparecer en las conversaciones.

Para finalizar una conversacin se incluye un dilogo sin respuestas.
De esta forma TS sabe que la conversacin ha terminado. Opcionalmente
se puede indicar cul ser el siguiente dilogo si el jugador vuelve
a hablar con el NPC. De esta forma el programador tiene libertad para
hacer que las conversaciones no se repitan.

Las conversaciones pueden llevar embebidas variables de modo que
puedas crear dilogos del tipo 'Bienvenido %Playername' o 
'veo que llevas el escudo %Shieldname'. Los nombres de las variables
y su contenido los fija el programador.

En cualquier momento se puede incluir un campo adicional, NewDlg, 
indicando el dilogo que iniciar el personaje la prxima vez que
hable. Si se desea que no hable ms se pondr a None.

Una opcin interesante es el atributo ExtraDlg que permite aadir
dilogos extra a una conversacin para simular la intervencin de 
otros NPJs. Un dilogo puede tener una entrada ExtraDlg con dos 
campos: el nombre del PNJ que interviene y el texto. Este dilogo
se incluye entre el dilogo original y las respuestas permitidas:

        'ExtraDlg': ['FuManChu 2',
	             """Me gusta incordiar! ...""",

A veces se dan varias respuestas alternativas de modo que al elegir
una las otras ya no son seleccionables. Para conseguir esto se 
utiliza el atributo DisableAns. Una respuesta puede tener este
atributo con una lista de respuestas que se deshabilitan:

        'DisableAns': ['No', 'A veces', 'Muy a menudo']

El ltimo dilogo no contiene respuestas y, por tanto, el TS lo
mantiene activo durante un tiempo antes de desactivarse. Como se
explica ms adelante, este tiempo viene especificado por el
parmetro global TSHideDelay. Sin embargo, para algunos textos
el valor por defecto puede ser pequeo. Por eso, TS utiliza el
atributo HideDelay que le indica los segundos que debe esperar
antes de finalizar el dilogo:

        'HideDelay': 7

Hacer conversaciones con ms de un flujo simultneo es algo 
ms complejo. Para ello se introduce el atributo ReplaceAns
que permite indicar un orden de sustitucin para una determinada
respuesta. As, si en un dilogo indicamos:

        'Answers': ['Montaas'],
	'ReplaceAns':{'Montaas':['Qu pas','Y despus']}

entonces, si cuando se dispara este dilogo la respuesta 
Montaas ya est deshabilitada (normalmente porque el jugador
ya la usado) se ofrecer la respuesta 'Qu pas'. Y si esta 
tampoco es ya vlida, 'Y despus'. Combinando respuestas se
puede obtener as un dilogo bastante rico.	

Talk System ofrece un sistema de callback de modo que el
programador pueda realizar acciones durante una conversacin.
Ya que TS se encarga de controlar todo el flujo de la conversacin,
el programador slo recupera el control al final de la misma.

Por eso, TS introduce un sistema para poder hacer un callback
ante determinadas respuestas o dilogos. Si para una respuesta o
dilogo se ha definido una funcin de callback entonces TS llamar
a esta funcin cuando el jugador seleccione la respuesta o cuando el
NPC diga el dilogo. As, el programador podr realizar acciones
como abrir puertas, reproducir sonidos,... o incluso modificar
la conversacin dinmicamente.

Esta funcin debe declararse con dos argumentos: personName y
ansId/dlgId y debera estar definida en DefFuncs.py. Adems cada
funcin hay que registrala con una llamada a AddCallBackFunc:

	AddCallBackFunc ('MiFuncion', MiFuncion)

en donde 'MiFuncion' es el nombre que se le ha dado en el atributo
CallBack y MiFuncion es la funcin propiamente dicha. Obviamente,
la funcin tiene que definirse antes de llamar a AddCallBackFunc.
Tambin es importante que las funciones se registren directamente en
DefFuncs.py. De esta forma nos aseguramos que se referencian las 
funciones correctas cuando cargamos un juego salvado.

Por motivos de rendimiento, TS no realiza ninguna comprobacin de la
estructura de la base de datos, suponiendo que todo el flujo es 
correcto. Para ayudar a depurar errores, TS incluye una funcin
que realiza una validacin del flujo bsico de la conversacin:

	Talk.Load ('example')
	Talk.Validate ()

Tambin puedes cambiar Talk.Debug=1 para que se muestren mensajes
adicionales que ayuden a depurar la conversacin.


El Diario.
---------------------------------------------------------------------------

TS incluye un sistema para registrar los datos ms importantes de una
conversacin. El usuario puede pulsar la tecla 'J' para mostrar un
Diario con esta informacin.

El programador debe definir previamente las entradas del Diario en
el mismo fichero en el que se cargan las conversaciones. Para habilitar
una entrada del Diario se utiliza la funcin:

	AddToJournal (jrlId)
	
en donde jrlId es el identificador usado para identificar la entrada:

	AddToJournal ('BuscaOrco')

Cuando se aade una nueva entrada se avisa al usuario con un pequeo libro
que aparece en pantalla. Si se quiere evitar este comportamiento se aade
un segundo parmetro:

	AddToJournal ('BuscaOrco', Talk.NoWarning)
	
Las entradas se van aadiendo al Diario secuencialmente y no se borran a
menos que el programador llame a la rutina:

	RemoveFromJournal (jrlId)

El Diario se maneja con teclas similares a las conversaciones, aunque su
comportamiento es ms sencillo.

En los dilogos y en las respuestas se puede aadir un atributo Journal para
que automticamente TS aada la entrada especificada al Diario cuando el 
dilogo se muestra o cuando la respuesta es seleccionada. Este es el mecanismo
preferido para aadir entradas al Diario:

    	'Journal': 'BuscaOrco'
	
Por ltimo, se incluye una funcin para borrar todo el Diario:

	ClearJournal ()


Controlando la conversacin.
---------------------------------------------------------------------------

En algunas conversaciones importantes, el programador puede querer
un mayor control sobre el flujo de la misma. Esto es posible gracias
a los mtodos que TS hace pblicos.

Para iniciar la conversacin asociada a personName se usa la funcin:
	
	Say (personName)
	Say ('FuManChu')
	
Si no se quiere cambiar la conversacin estndar de un NPC pero
se desea que inicie un dilogo diferente:
	Say (personName, dlgId)
	Say ('FuManChu', 'Socorro')
	
Para definir una variable se usa:	

	SetVar (name, value)
	SetVar ('WeaponName', OrcoCabreado.InvRight)

Tambin se puede recuperar su valor actual:

	GetVar (name) return value
	wName = GetVar ('WeaponName')

y borrar todas las variables definidas con:
	ClearVars ()
	

TS deshabilita todas las respuesta usadas por el jugador. Se pueden
volver a habilitar con:

	AnswerEnable (person, ansId)
	AnswerEnable ('FuManChu', 'Soy pesao')

de modo que TS la vuelve a mostrar en los dilogos en los que se
encuentre esta opcin.

Tambin es posible desahabilitar una respuesta aunque el jugador
no la haya visto an:

	AnswerDisable (personName, ansId)
	AnswerDisable ('FuManChu', 'No tiene sentido')
	
por ejemplo, como respuesta a un evento.

Puedes cambiar dinmicamente tanto los dilogos como las respuestas:

	SetDialog (personName, dlgId, text, answers=None)
	SetAnswer (personName, ansId, text, nextdlgId=None)

En principio, lo ms habitual es cambiar el texto para adaptarlo
en funcin de los acontecimientos:

	SetDialog ('FuManChu', 'Ahora vengo', 'Esperame, voya por tabaco')

pero tambin se puede cambiar dinmicamente el flujo de una
conversacin si fuese necesario.

Por ltimo, si quieres utilizar el interfaz de Talk System para
mostrar un mensaje puedes utilizar la funcin ShowMessage:

        ShowMessage (Text, HideDelay=TSHideDelay)

Por ejemplo, para mostrar el mensaje durante 15 segundos:

        ShowMessage ("Esto es un mensaje", 15)

Para ocultar la interfaz usa:

	Hide()

Puedes cambiar un bitmap concreto con la funcin:
     
	SetBitMap (Name, File)

Los bitmaps que puedes cambiar son:
	
	TSBarra1, TSBarra2 y TSBarra3 para el fondo del texto.
	TSJournal: Fondo del Diario.
	TSWarning: Aviso de nueva entrada en el Diario.
	
	
Por ejemplo, para cambiar el bitmap de aviso de entrada en el diario:

	SetBitMap ('TSWarnig', 'MyBook.bmp')


Parmetros configurables.
---------------------------------------------------------------------------

En TS es posible cambiar algunos parmetros para adaptarlo a nuestro
mapa:

* MMP con las texturas usadas como fondo de los dilogos. Las texturas
  son tres de tipo TrueColourAlpha: Barra1, Barra2 y Barra3,
  correspondientes a la zona izquierda, centro y derecha del fondo.
  Para el Diario se utiliza TSJournal y para el libro de aviso TSWarning.
  TSmmp            = "../../Data/TSWidgets.mmp"
  No es posible modificar dinmicamente esta variable porque Talk
  se importa antes que DefFuncs. Y los Widgets se crean al inicio.
* Fuente empleada en los textos.
  TSFont        = "../../Data/letras menu med.bmp"
  No es posible modificar dinmicamente esta variable porque Talk
  se importa antes que DefFuncs. Y los Widgets se crean al inicio.
* Color de los dilogos.
  ColorDlg         = 207,144,49
* Color de las respuestas.
  ColorAns         = 207,144,49
* Color de la respuesta seleccionada (activa).
  ColorAnsSelected = 252,247,167
* Nmero mximo de lineas  
  MaxLines         = 8
* Margen derecho,
  RMargin          = 66
* Posicion horizontal de los dilogos.
  TextXBase        = 35
* Posicin vertical en la que empiezan los dilogos.
  TextYBase        = 300
* Tamao vertical de cada linea de texto.
  TextYSize        = 14
* Parmetros similares para el Diario: 
  jMaxLines, jRMargin,jTextYBase,jTextYSize,jTextXBase 
  ColorjTitle, ColorjText, ColorjTextSelected
* Rango mnimo para que un NPC comience una conversacin.
  TSTalkRange      = 5000
* Tiempo en segundos que tarda en desaparecer la interfaz de TS
  despues de mostrar ltimo dilogo.
  TSHideDelay      = 10
* Distancia mxima a la que puede estar un NPC para poder iniciar
  una conversacin.
  SelectNPCArea    = 10000
  
Puedes agrupar estos cambios en un script llamado TSCustom.py. Si TS encuentra
este script en el directorio del mapa, lo ejecuta. Al ser un script python
puedes aadir todo el cdigo que necesites. En este script s es posible
modificar TSmmp y TSFont.

Un ejemplo.
---------------------------------------------------------------------------

Con la distribucin de este Mod se incluye un pequeo ejemplo de
conversacin. Slo hay que copiar el fichero TestTS.py y el directorio
TS (con toda la estructura) en el directorio de cualquier mapa. Despues
edita TestTS.py y cambia las coordenadas de creacin del Orco para que
se ajusten a tu mapa.

Carga el mapa y en la consola ejecuta:

execfile ('TestTS.py')

Aparecer un orco con el que podrs iniciar varias conversaciones 
pulsando la tecla de hablar (T).

Si quieres probar el comportamiento con Talk.SeeEvent tienes descomentar
la lnea correspondiente en TestTS.py y alejarte de la posicin de
aparicin del Orco antes de ejecutarlo.

Para probar el Diario pulsa J.


Revisiones:
---------------------------------------------------------------------------

0.1   * Primera versin pblica.
0.2   * Se aade una funcin findall independiente de la versin
        de python.
      * Se activan/desactivan los widgets de poder con la 
        conversacin.
0.3   * Se han eliminado algunos defectos de las texturas.
      * Se han ajustado los timers para evitar algunos
        fallos cuando se pulsaba rpidamente Cancelar.
      * Ahora una conversacin puede terminar con una respuesta.
      * Es posible cambiar el Siguiente dilogo en cualquier 
        dilogo o respuesta con el campo NewDlg.
      * Se crea una nueva interfaz (Assign) para asignar
        dilogos a los NPC.
      * Ahora es posible que un NPC inicie la conversacin
        al acercarse el jugador.
0.4   * Corregidos algunos errores.
      * Se aade el atributo CallBack a los dilogos.
      * Se mejora el mtodo de CallBack. Es algo ms complejo
        usarlo pero ahora van funciones, variables globales,...
      * Se aade la variable TSHideDelay. Y el atributo HideDelay.
        Ambos permiten controlar el tiempo que aparece el ltimo
        dilogo.
      * Se habilita la opcin de salvar/cargar. De momento slo se
        salvan algunos atributos de la Clase TSDB que son los nicos
        modificables. Las funciones de CallBack no se salvan pero basta
        con registrarlas a nivel de DefFuncs.
      * Se aade una marca para diferenciar claramente la respuesta
        seleccionada. Un '>' pero estoy abierto a otras sugerencias.
      * Se incluye la opcin ExtraDlg para permitir dilogos en los que
        intervengan varios NPCs.  
      * Atributo DisableAns para que una respuesta pueda deshabilitar
        otras respuestas. Estaba implementado pero no documentado.        
      * Se implementa un mecanismo de sustitucin de respuestas,
        ReplaceAns, que permite mantener varios flujos de conversacin
        activos de forma simultnea.
      * Nuevo sistema de seleccin de NPC para iniciar conversaciones. 
        Ahora no es necesario que est seleccionado, basta con que el
        NPC sea visible y est cerca (SelectNPCArea).
      * Se implementa ShowMessage que permite mostrar mensajes con la
        interfaz de TS.  
0.5   * Hay un problema con la redefinicin de LeftClick. Desenfundo el arma
        al hablar para evitar que ataque.
      * Nueva funcin Hide que oculta la interfaz de TS.
      * Desencara al Player1 despus de una conversacin.
      * Se incluye un ejemplo ms completo.
      * Se ofrece documentacin en ingls, gracias a Prospero.
0.6   * Parece que he conseguido que el ltimo click no suponga un
        ataque. Ahora el juegador enfunda las armas al iniciar una
        conversacin.
      * Aado un Diario en el que el jugador puede consultar los datos
        ms relevantes de una conversacin.
      * Ahora es posible redefinir las teclas desde el men de controles
        de Blade.
      * La posicin y los mrgenes del texto se calcula en funcin de la
        resolucin de la pantalla.
      * Haba un problema de sincronizacin entre los scheds del TS y del Journal.
0.7   * Resuelto un bug por el que no funcionaba las teclas predefinidas despues
        de cargar un juego salvado si las teclas por defecto estaban mapeadas
        para otra accin.
      * Resuelto un bug por el que las teclas se mapeaban mltiples veces.      
0.7a  * Fijado un bug por el que se perdian los controles por defecto cuando
        no exista Control.py.
0.8   * Se aclara que TSmmp y TSFont no pueden modificarse dinmicamente.
      * Se aade una funcin para cambiar un widget concreto (SetBitMap).
      * Se aade el uso del script de adapatacin TSCustom.py.

                