Wallack
Pornorroleador en sequía
- Registrado
- 13/12/08
- Mensajes
- 569
- Edad
- 40
Buenas!
Hace tiempo me propuse algo parecido y siempre por falta de tiempo, lo voy dejando. Ahora como tengo que escribir una historia para mi nuevo personaje, y no se me ocurre, pues digo, voy a escribir esto otro, que también es una historia XD Además, como me apetece contribuir bien con más cosas y quedar bien, que me quieran y todo eso.
Alguien que haya programado puede aprender por su cuenta, si ha programado algo de más de 10 líneas XD pero para quién ni si quiera haya programado nada, vamos a intentar hacer entender, un poco por encima, como funciona todo, desde lo básico hasta lo más avanzado (siempre dentro de lo básico eh xD).
Empezaremos con pseudocódigo, muy útil para los que no han programado nunca. El pseudocódigo es código en lenguaje puramente humano, para que nos entendamos, un programa en pseudocódigo que sume dos números y luego nos imprima por pantalla el resultado sería:
Como véis es muy sencillo, eso, traducido a un lenguage como podría ser php sería:
Esto es solo para que os hagáis una idea. Vamos a hacer ahora en pseoducódigo un script de NWN que de 1000 de experiencia a quién haga clic en un ubicado cualquiera.
Aprovecho para introduciros los "niveles" en cuanto a lenguajes de programación. Un lenguaje de alto nivel, sería un lenguaje más humano, más legible, con menos líneas a la hora de programar una funcionalidad y que hace o presupone cosas por nosotros para ahorrarnos trabajo.
En muy alto nivel, el script que queremos sería:
Si bajamos un poco de nivel sería algo así:
Un poquito más abajo:
Bien, ya hemos hecho nuestro primer script en pseudocódigo! Vamos a ir un poco más allá, vamos a hacer el pseudocódigo más código con la introducción de variables.
Las variables, son "palabras" que pueden contener información que puede variar con el tiempo. En pseudocódigo vamos a utilizar corchetes para rodearlas e identificarlas (no hay sintaxis oficial del pseudocódigo). Para ello vamos al ejemplo:
¿Se ve un poco mejor? ¿Qué tal si añadimos un condicional? ¡Venga, vamos a ello!
¡Hey, parece más currado ahora! Pero el no hagas nada no me gusta. ¡Vamos a quitarlo!
Así de fácil, basta con no añadir el si no se cumple para hacerlo.
Ahora ¿qué os parece si usamos algo más de lenguaje de programación para ir adaptándonos? ¿os parece bien? ¡pues os jodéis! vamos a ver algo antes, muy importante en el scripting de nwn.
Os podría decir, sin más, que en el lenguaje de programación de NWN para usar variables hay que declararlas primero, pero intentaré ir más allá.
Imaginaros la memoria del ordenador como una enorme ciudad. Cada variable es una casa, una vivienda, con su contenido. Una variable tiene dos cosas (el scripting solo usa una) el nombre, que podría ser "casa de wallack" y la dirección de memoria que podría ser "calle falsa 123". Pues bien, en el scripting del NWN que podríamos considerar como lenguaje de medio-alto nivel, requiere que se declaren las variables antes para poder utilizarlas, es decir, reservamos la dirección "calle falsa 123" para que se conozca como "casa de wallack" y de ese modo, esa dirección esté reservada para nosotros.
¿Qué pasa si no lo hacemos? que podríamos estar pisando datos de otros programas, del sistema operativo ... esto sería un mundo del que hablar pero prefiero que tengáis la idea de porqué hacemos las cosas un poquitín antes de empezar.
Vamos a ello:
Ya tenemos declarada nuestra variable y la podemos usar. ¿Ya está? ¡Venga, casi, vamos un poco más!
Ahora hablaremos del tipado de datos ¿que cosa tan rara? nada más lejos, el tipado de datos o de variables es para eso, para tipar o clasificar las variables, esto es, que cada variable es de un tipo y no se puede cambiar ese tipo (en realidad sí pero no en nwn scripting y no vamos a hablar de ello).
Vamos a tipar nuestra variable:
Joder ¡qué fácil! ¿y para que sirve esto? realmente, no se trata de servir sino de la sintaxis del lenguaje. Un lenguaje cont ipado de datos te obliga a decir para qué serán cada variables. En nuestro caso, [jugador] almacenará jugadores. ¿qué más podría almacenar? pues números, textos, numeros decimales, matrices, imágenes, ficheros ... pero ¿en neverwinter? pues podría numeros, localizaciones, objetos (hablaremos de ello), efectos ...
¿Y jugadores? no has dicho jugadores ¿como guardo jugadores? los jugadores en el NWN son ... OBJETOS ... ¡SI SEÑOR! ¡SOMOS OBJETOS EN MANOS DE LOS DMS! en realidad, la palabra correcta sería entidades, pero los ubicados también y las áreas también, pero ya hablaremos.
Mmh, ya casi lo tenemos ¿como hacemos esto en el NWN? doy por sentado que sabéis hacer un área con ubicados, si no, os mato!
En pseudocódigo, en el ubicado, escribiríamos este script en el evento "onUsed" o "al ser usado" en español.
¡Eventos! ¿Qué es eso? ¡SATAN!
Tranquilidad, el nwnscripting es un lenguaje orientado a eventos. Todos los scripts están desencadenados o disparados (triggered) por algo, en este caso, eventos. Antes de pasar al evento, vamos a traducir un poco más nuestro código, adaptándolo al NWN:
Ostias, como ha cambiado, vamos por partes.
En NWN cada línea tiene que acabar en un ; para que el compilador (quien traduce el código) lo entienda. Vamos por líneas:
objeto [jugador];
Técnicamente los corchetes no los usaríamos más, pero es igual, vamos a ello. En nwnscript se añade en primer lugar el tipo de variable (objeto, numero, efecto) y después el nombre. Realmente lo correcto y traducido a nwn sería:
object jugador;
¿A que parece fácil? si queremos más, o una por línea o sino, esta magia también es posible:
object jugador1, jugador2, jugador3;
object jugador4;
Joder, como mola, ya sabemos declarar objetos de verdad. Ahora, vamos a hacer las cosas bien, notación húngara! O así me lo enseñaron a mi ¿qué es? es sencillamente, esto:
object oJugador1, oJugador2;
¿Habéis visto esa o delante? sirve, para que rápidamente de un vistazo, sepamos que es una variable de tipo object. Imaginemos números (int en el nwnscript) usaríamos una i, por ejemplo:
int iExperiencia;
A que mola, ahora, vamos a hacerlo mejor:
int iExperiencia = 1000;
Tenemos declarada Y ASIGNADA al mismo tiempo una variable, en la cual, guardaremos la experiencia que después queremos dar (esta no está en el pseudocódigo). Vamos a seguir.
[jugador] = damejugadorqueclico;
Aquí llamamos a una función interna del NWN que se llama damejugadorqueclico; Esta me la he inventado pero estamos en pseudocódigo. ¿Cómo funciona esta función por dentro para identificar al jugador? ¡NO LO SÉ Y LO MEJOR ES QUE NO ME IMPORTA! Porque nosotros tenemos un listado de las funciones que queremos y sabemos que necesitan y que nos devuelven.
¡Espera, vas demasiado rápido! ¿Qué es una función?
¿Se os ocurre alguna función? ¿y algún parámetro?
No entraré en muchos detalles de diferenciar procedimientos, funciones y métodos pero diré que una función, es una orden u acción que a veces requiere argumentos y otras no. A veces devuelve valores y a veces no. Ejemplos en pseudocódigo:
fecha(); esta función nos devolvería la fecha actual
fecha(+1); esta función por ejemplo, nos devolvería la fecha con un día sumado.
fecha(+1, MONTH); nos devolvería la fecha con un mes sumado.
¿Véis? parece fácil, pues eso es una función, vamos con nuestro ejemplo:
[jugador] = damejugadorqueclico;
Como antes lo habíamos llamado oJugador en plan correcto y programador pro, pues vamos a ello:
oJugador = damejugadorqueclico;
Vaya, ¿como sería esta función en el nwn? si entramos en el aurora toolset, en el editor de guiones (scripts) tendremos uno en blanco con un listado a la derecha de Funciones, Variables, Constantes y Plantillas. ¿Qué es cada cosa? ... en otro momento, nos interesan las funciones.
Vamos a filtrar por click ... ostias solo salen 2:
GetClickingObject
GetPlaceableLastClickedBy
Así a bote pronto parece que pega mejor la primera ... ¿como lo sabré? fácil, te pones encima y debajo, aparece una descripción:
// Use this in a trigger's OnClick event script to get the object that last
// clicked on it.
// This is identical to GetEnteringObject.
// GetClickingObject() should not be called from a placeable's OnClick event,
// instead use GetPlaceableLastClickedBy();
object GetClickingObject()
¿No sabéis inglés? pues toca aprenderlo porque sino, será difícil programar. Esta función dice que se ejecuta en el evento onclick de un trigger ... ¿qué son triggers? vaya dice que es identica a get entering object ... espera, dice que no debe ser llamada desde el evento onclick de un ubicado, que en su lugar uses la otra. Vamos a ver que dice la otra:
// Get the last object that default clicked (left clicked) on the placeable object
// that is calling this function.
// Should only be called from a placeables OnClick event.
// * Returns OBJECT_INVALID if it is called by something other than a placeable.
object GetPlaceableLastClickedBy()
Parece la elegida. Dice que devuelve el último objeto que clicó en el ubicado. Vamos a usarla, identifiquemos sus partes en la definición de la función:
object GetPlaceableLastClickedBy()
object significa que devuelve un objeto.
El paréntesis vacío indica que no requiere ningún dato para funcionar. Vamos a ello:
oJugador = GetPlaceableLastClickedBy();
Joder como mola, vamos a juntar lo que tenemos:
Bien, sigamos con nuestro pseudocódigo y su transformación:
if (esjugadorhumano([jugador]) == TRUE)
{
daexperiencia(1000, [jugador]);
}
¡Espera! ¡Dijiste línea por línea! Sí claro, pero es que estamos en una condición y tenemos que ver el conjuto.
Las condiciones funcionan así:
Podemos anular todo el bloque del else y dejarlo solo así:
Vale, ya en un momento hemos identificado que es una condición. Analicemos la condición de la condición XD sí sí, lo que está entre paréntesis:
esjugadorhumano([jugador]) == TRUE
Bien, aquí no hay punto y coma ¿porqué? ¿no dijiste ... shht! callad! los condicionales son así, no los juzguéis por ello. Vamos a traducir esto un poco más a nuestro código
esjugadorhumano(oJugador) == TRUE
¿Qué es eso de TRUE? bueno, es una constante, las constantes son palabras "humanas" que contienen valores fijos. Esto seguramente de manera interna sea un TRUE = 1 pero da igual, os quedáis con TRUE. Vamos a buscar una función que nos sirva para nosotros.
¿Cómo es un jugador humano en el NWN? PJ (personaje de jugador o personaje jugable) ¿cómo sería en inglés? PC (playable character) busquemos PC ... buff salen unas cuantas pero mirad la tercera:
// * Returns TRUE if oCreature is a Player Controlled character.
int GetIsPC(object oCreature)
¡Ostias que fácil! ¿véis? analicemos:
int -> devuelve un entero, aunque si os fijáis dice que devuelve TRUE ... eso es porque TRUE contiene 1 como valor, pero da igual, es una anécdota anecdótica, no os quedéis con ello.
¿Véis lo que pone entre paréntesis? object oCreature, eso significa que recibe un object. ¿Véis el oCreature? eso es que la función internamente lo llama así, pero te da igual. ¿Has visto que usan la o? ¡SON PROS COMO NOSOTROS!
Vamos a ello:
esjugadorhumano(oJugador) == TRUE
pasa a ser
GetIsPC(oJugador) == TRUE
Joder, que guapo! En nuestro ejemplo:
if (GetIsPC(oJugador) == TRUE)
{
daexperiencia(1000, [jugador]);
}
¿Y porqué pones == en vez de =? ¡Porque el = es para asignar valores y el == para comparar! ¡Nunca os confundáis!
Una cosa buena de los ifs, es que si no pones el == TRUE lo hace por defecto, esto es que la comparación por defecto:
if (GetIsPC(oJugador))
sería igual que
if (GetIsPC(oJugador) == TRUE)
Entonces ¿para qué ponerla? para que cuando empecéis sepáis lo que comparáis, igual queriáis poner:
if (GetIsPC(oJugador) == FALSE)
Aunque técnicamente no sería FALSE sería otra palabra reservada, pero da igual, vamos a lo nuestro:
Vamos a la siguiente línea:
daexperiencia(1000, [jugador]);
Vamos a buscar rápidamente una función de experiencia, busquemos por XP.
El resultado que aparentemente mejor se ajusta es: GiveXPToCreature
Su descripción es:
// Gives nXpAmount to oCreature.
void GiveXPToCreature(object oCreature, int nXpAmount)
¿véis el void? significa que no devuelve nada. Y requiere dos cosas, un objeto (a quién dar la experiencia) y una cantidad (la experiencia a dar)
En nuestro caso:
GiveXPToCreature(oJugador, 1000);
¡Como mola! ¡Veámoslo completo!
¡Ya hemos hecho un script!
Esto, en el editor de scripts iría todo dentro del void main() { }
Tal que así:
Guardaríamos este script con un nombre, se compilaría y nos daría este mensaje:
20/02/2012 14:16:46: 0 errores. 'test' se ha compilado con éxito
Despues iríamos a nuestro ubicado, lo examinaríamos y en la pantalla de guiones, en el onused pondríamos este script.
¿Qué pasa si lo ponemos en el onphysicalattacked? ¿daría xp cada vez que atacásemos? ¡No! ¿sabéis porqué?
Os lo explico rápidamente. cada vez que atacásemos se ejecutaría el script, este script:
Como el oJugador es el último que hizo click, nunca podría darle XP al atacar, debería ser algo como:
// Get the last attacker of oAttackee. This should only be used ONLY in the
// OnAttacked events for creatures, placeables and doors.
// * Return value on error: OBJECT_INVALID
object GetLastAttacker(object oAttackee=OBJECT_SELF)
¿véis? esta función nos daría quién es el último jugador que atacó el ubicado.
Pero esto sería ir entrando cada vez más y más en detalles, lo importante es que creéis un script y probéis y experimentéis. Poned las dudas que tengáis pero ... ¡CON TODA LA INFORMACIÓN POSIBLE! no seáis escuetos cuando preguntéis, se trata de que todos aprendan con las dudas y las respuestas.
¡No os olvidéis de hacer el objeto usable! (el ubicado) ya que es importante para poder seleccionarlo y hacer click o atacarlo.
¡Todas las dudas al infierno con ellas! Eso sí, cuando vuelvan del averno os dejo que preguntéis.
Un saludo, espero que os guste y perdáis tiempo con ello.
Hace tiempo me propuse algo parecido y siempre por falta de tiempo, lo voy dejando. Ahora como tengo que escribir una historia para mi nuevo personaje, y no se me ocurre, pues digo, voy a escribir esto otro, que también es una historia XD Además, como me apetece contribuir bien con más cosas y quedar bien, que me quieran y todo eso.
Alguien que haya programado puede aprender por su cuenta, si ha programado algo de más de 10 líneas XD pero para quién ni si quiera haya programado nada, vamos a intentar hacer entender, un poco por encima, como funciona todo, desde lo básico hasta lo más avanzado (siempre dentro de lo básico eh xD).
Empezaremos con pseudocódigo, muy útil para los que no han programado nunca. El pseudocódigo es código en lenguaje puramente humano, para que nos entendamos, un programa en pseudocódigo que sume dos números y luego nos imprima por pantalla el resultado sería:
imprime por pantalla suma de numero1 + numero2
Como véis es muy sencillo, eso, traducido a un lenguage como podría ser php sería:
echo $numero1 + $numero2;
o también
print $numero1 + $numero2;
($numero1 y $numero2 son variable que pueden contener cualquier valor).
o también
print $numero1 + $numero2;
($numero1 y $numero2 son variable que pueden contener cualquier valor).
Esto es solo para que os hagáis una idea. Vamos a hacer ahora en pseoducódigo un script de NWN que de 1000 de experiencia a quién haga clic en un ubicado cualquiera.
Aprovecho para introduciros los "niveles" en cuanto a lenguajes de programación. Un lenguaje de alto nivel, sería un lenguaje más humano, más legible, con menos líneas a la hora de programar una funcionalidad y que hace o presupone cosas por nosotros para ahorrarnos trabajo.
En muy alto nivel, el script que queremos sería:
Da 1000 experiencia
Si bajamos un poco de nivel sería algo así:
Da 1000 experiencia a jugador
Un poquito más abajo:
Da 1000 experiencia al jugador que clico en el ubicado
Bien, ya hemos hecho nuestro primer script en pseudocódigo! Vamos a ir un poco más allá, vamos a hacer el pseudocódigo más código con la introducción de variables.
Las variables, son "palabras" que pueden contener información que puede variar con el tiempo. En pseudocódigo vamos a utilizar corchetes para rodearlas e identificarlas (no hay sintaxis oficial del pseudocódigo). Para ello vamos al ejemplo:
guarda en [jugador] jugador que clico el ubicado
da 1000 experiencia a [jugador]
da 1000 experiencia a [jugador]
¿Se ve un poco mejor? ¿Qué tal si añadimos un condicional? ¡Venga, vamos a ello!
guarda en [jugador] jugador que clico el ubicado
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
si no se cumple -> no hagas nada
fin condicional
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
si no se cumple -> no hagas nada
fin condicional
¡Hey, parece más currado ahora! Pero el no hagas nada no me gusta. ¡Vamos a quitarlo!
guarda en [jugador] jugador que clico el ubicado
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
fin condicional
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
fin condicional
Así de fácil, basta con no añadir el si no se cumple para hacerlo.
Ahora ¿qué os parece si usamos algo más de lenguaje de programación para ir adaptándonos? ¿os parece bien? ¡pues os jodéis! vamos a ver algo antes, muy importante en el scripting de nwn.
Os podría decir, sin más, que en el lenguaje de programación de NWN para usar variables hay que declararlas primero, pero intentaré ir más allá.
Imaginaros la memoria del ordenador como una enorme ciudad. Cada variable es una casa, una vivienda, con su contenido. Una variable tiene dos cosas (el scripting solo usa una) el nombre, que podría ser "casa de wallack" y la dirección de memoria que podría ser "calle falsa 123". Pues bien, en el scripting del NWN que podríamos considerar como lenguaje de medio-alto nivel, requiere que se declaren las variables antes para poder utilizarlas, es decir, reservamos la dirección "calle falsa 123" para que se conozca como "casa de wallack" y de ese modo, esa dirección esté reservada para nosotros.
¿Qué pasa si no lo hacemos? que podríamos estar pisando datos de otros programas, del sistema operativo ... esto sería un mundo del que hablar pero prefiero que tengáis la idea de porqué hacemos las cosas un poquitín antes de empezar.
Vamos a ello:
declara [jugador] como variable
guarda en [jugador] jugador que clico el ubicado
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
fin condicional
guarda en [jugador] jugador que clico el ubicado
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
fin condicional
Ya tenemos declarada nuestra variable y la podemos usar. ¿Ya está? ¡Venga, casi, vamos un poco más!
Ahora hablaremos del tipado de datos ¿que cosa tan rara? nada más lejos, el tipado de datos o de variables es para eso, para tipar o clasificar las variables, esto es, que cada variable es de un tipo y no se puede cambiar ese tipo (en realidad sí pero no en nwn scripting y no vamos a hablar de ello).
Vamos a tipar nuestra variable:
declara [jugador] como variable de jugador
guarda en [jugador] jugador que clico el ubicado
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
fin condicional
guarda en [jugador] jugador que clico el ubicado
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
fin condicional
Joder ¡qué fácil! ¿y para que sirve esto? realmente, no se trata de servir sino de la sintaxis del lenguaje. Un lenguaje cont ipado de datos te obliga a decir para qué serán cada variables. En nuestro caso, [jugador] almacenará jugadores. ¿qué más podría almacenar? pues números, textos, numeros decimales, matrices, imágenes, ficheros ... pero ¿en neverwinter? pues podría numeros, localizaciones, objetos (hablaremos de ello), efectos ...
¿Y jugadores? no has dicho jugadores ¿como guardo jugadores? los jugadores en el NWN son ... OBJETOS ... ¡SI SEÑOR! ¡SOMOS OBJETOS EN MANOS DE LOS DMS! en realidad, la palabra correcta sería entidades, pero los ubicados también y las áreas también, pero ya hablaremos.
declara [jugador] como variable de objeto
guarda en [jugador] jugador que clico el ubicado
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
fin condicional
guarda en [jugador] jugador que clico el ubicado
es [jugador] un jugador?
si se cumple -> da 1000 de experiencia a [jugador]
fin condicional
Mmh, ya casi lo tenemos ¿como hacemos esto en el NWN? doy por sentado que sabéis hacer un área con ubicados, si no, os mato!
En pseudocódigo, en el ubicado, escribiríamos este script en el evento "onUsed" o "al ser usado" en español.
¡Eventos! ¿Qué es eso? ¡SATAN!
Tranquilidad, el nwnscripting es un lenguaje orientado a eventos. Todos los scripts están desencadenados o disparados (triggered) por algo, en este caso, eventos. Antes de pasar al evento, vamos a traducir un poco más nuestro código, adaptándolo al NWN:
objeto [jugador];
[jugador] = damejugadorqueclico;
if (esjugadorhumano([jugador]) == TRUE)
{
daexperiencia(1000, [jugador]);
}
[jugador] = damejugadorqueclico;
if (esjugadorhumano([jugador]) == TRUE)
{
daexperiencia(1000, [jugador]);
}
Ostias, como ha cambiado, vamos por partes.
En NWN cada línea tiene que acabar en un ; para que el compilador (quien traduce el código) lo entienda. Vamos por líneas:
objeto [jugador];
Técnicamente los corchetes no los usaríamos más, pero es igual, vamos a ello. En nwnscript se añade en primer lugar el tipo de variable (objeto, numero, efecto) y después el nombre. Realmente lo correcto y traducido a nwn sería:
object jugador;
¿A que parece fácil? si queremos más, o una por línea o sino, esta magia también es posible:
object jugador1, jugador2, jugador3;
object jugador4;
Joder, como mola, ya sabemos declarar objetos de verdad. Ahora, vamos a hacer las cosas bien, notación húngara! O así me lo enseñaron a mi ¿qué es? es sencillamente, esto:
object oJugador1, oJugador2;
¿Habéis visto esa o delante? sirve, para que rápidamente de un vistazo, sepamos que es una variable de tipo object. Imaginemos números (int en el nwnscript) usaríamos una i, por ejemplo:
int iExperiencia;
A que mola, ahora, vamos a hacerlo mejor:
int iExperiencia = 1000;
Tenemos declarada Y ASIGNADA al mismo tiempo una variable, en la cual, guardaremos la experiencia que después queremos dar (esta no está en el pseudocódigo). Vamos a seguir.
[jugador] = damejugadorqueclico;
Aquí llamamos a una función interna del NWN que se llama damejugadorqueclico; Esta me la he inventado pero estamos en pseudocódigo. ¿Cómo funciona esta función por dentro para identificar al jugador? ¡NO LO SÉ Y LO MEJOR ES QUE NO ME IMPORTA! Porque nosotros tenemos un listado de las funciones que queremos y sabemos que necesitan y que nos devuelven.
¡Espera, vas demasiado rápido! ¿Qué es una función?
¿Se os ocurre alguna función? ¿y algún parámetro?
No entraré en muchos detalles de diferenciar procedimientos, funciones y métodos pero diré que una función, es una orden u acción que a veces requiere argumentos y otras no. A veces devuelve valores y a veces no. Ejemplos en pseudocódigo:
fecha(); esta función nos devolvería la fecha actual
fecha(+1); esta función por ejemplo, nos devolvería la fecha con un día sumado.
fecha(+1, MONTH); nos devolvería la fecha con un mes sumado.
¿Véis? parece fácil, pues eso es una función, vamos con nuestro ejemplo:
[jugador] = damejugadorqueclico;
Como antes lo habíamos llamado oJugador en plan correcto y programador pro, pues vamos a ello:
oJugador = damejugadorqueclico;
Vaya, ¿como sería esta función en el nwn? si entramos en el aurora toolset, en el editor de guiones (scripts) tendremos uno en blanco con un listado a la derecha de Funciones, Variables, Constantes y Plantillas. ¿Qué es cada cosa? ... en otro momento, nos interesan las funciones.
Vamos a filtrar por click ... ostias solo salen 2:
GetClickingObject
GetPlaceableLastClickedBy
Así a bote pronto parece que pega mejor la primera ... ¿como lo sabré? fácil, te pones encima y debajo, aparece una descripción:
// Use this in a trigger's OnClick event script to get the object that last
// clicked on it.
// This is identical to GetEnteringObject.
// GetClickingObject() should not be called from a placeable's OnClick event,
// instead use GetPlaceableLastClickedBy();
object GetClickingObject()
¿No sabéis inglés? pues toca aprenderlo porque sino, será difícil programar. Esta función dice que se ejecuta en el evento onclick de un trigger ... ¿qué son triggers? vaya dice que es identica a get entering object ... espera, dice que no debe ser llamada desde el evento onclick de un ubicado, que en su lugar uses la otra. Vamos a ver que dice la otra:
// Get the last object that default clicked (left clicked) on the placeable object
// that is calling this function.
// Should only be called from a placeables OnClick event.
// * Returns OBJECT_INVALID if it is called by something other than a placeable.
object GetPlaceableLastClickedBy()
Parece la elegida. Dice que devuelve el último objeto que clicó en el ubicado. Vamos a usarla, identifiquemos sus partes en la definición de la función:
object GetPlaceableLastClickedBy()
object significa que devuelve un objeto.
El paréntesis vacío indica que no requiere ningún dato para funcionar. Vamos a ello:
oJugador = GetPlaceableLastClickedBy();
Joder como mola, vamos a juntar lo que tenemos:
object oJugador;
oJugador = GetPlaceableLastClickedBy();
oJugador = GetPlaceableLastClickedBy();
Bien, sigamos con nuestro pseudocódigo y su transformación:
if (esjugadorhumano([jugador]) == TRUE)
{
daexperiencia(1000, [jugador]);
}
¡Espera! ¡Dijiste línea por línea! Sí claro, pero es que estamos en una condición y tenemos que ver el conjuto.
Las condiciones funcionan así:
if(condicion)
{
//haz algo
}
else
{
//haz lo que quieras si no se cumple
}
{
//haz algo
}
else
{
//haz lo que quieras si no se cumple
}
Podemos anular todo el bloque del else y dejarlo solo así:
if(condicion)
{
//haz algo
}
{
//haz algo
}
Vale, ya en un momento hemos identificado que es una condición. Analicemos la condición de la condición XD sí sí, lo que está entre paréntesis:
esjugadorhumano([jugador]) == TRUE
Bien, aquí no hay punto y coma ¿porqué? ¿no dijiste ... shht! callad! los condicionales son así, no los juzguéis por ello. Vamos a traducir esto un poco más a nuestro código
esjugadorhumano(oJugador) == TRUE
¿Qué es eso de TRUE? bueno, es una constante, las constantes son palabras "humanas" que contienen valores fijos. Esto seguramente de manera interna sea un TRUE = 1 pero da igual, os quedáis con TRUE. Vamos a buscar una función que nos sirva para nosotros.
¿Cómo es un jugador humano en el NWN? PJ (personaje de jugador o personaje jugable) ¿cómo sería en inglés? PC (playable character) busquemos PC ... buff salen unas cuantas pero mirad la tercera:
// * Returns TRUE if oCreature is a Player Controlled character.
int GetIsPC(object oCreature)
¡Ostias que fácil! ¿véis? analicemos:
int -> devuelve un entero, aunque si os fijáis dice que devuelve TRUE ... eso es porque TRUE contiene 1 como valor, pero da igual, es una anécdota anecdótica, no os quedéis con ello.
¿Véis lo que pone entre paréntesis? object oCreature, eso significa que recibe un object. ¿Véis el oCreature? eso es que la función internamente lo llama así, pero te da igual. ¿Has visto que usan la o? ¡SON PROS COMO NOSOTROS!
Vamos a ello:
esjugadorhumano(oJugador) == TRUE
pasa a ser
GetIsPC(oJugador) == TRUE
Joder, que guapo! En nuestro ejemplo:
if (GetIsPC(oJugador) == TRUE)
{
daexperiencia(1000, [jugador]);
}
¿Y porqué pones == en vez de =? ¡Porque el = es para asignar valores y el == para comparar! ¡Nunca os confundáis!
Una cosa buena de los ifs, es que si no pones el == TRUE lo hace por defecto, esto es que la comparación por defecto:
if (GetIsPC(oJugador))
sería igual que
if (GetIsPC(oJugador) == TRUE)
Entonces ¿para qué ponerla? para que cuando empecéis sepáis lo que comparáis, igual queriáis poner:
if (GetIsPC(oJugador) == FALSE)
Aunque técnicamente no sería FALSE sería otra palabra reservada, pero da igual, vamos a lo nuestro:
object oJugador;
oJugador = GetPlaceableLastClickedBy();
if (GetIsPC(oJugador) == TRUE)
{
daexperiencia(1000, [jugador]);
}
oJugador = GetPlaceableLastClickedBy();
if (GetIsPC(oJugador) == TRUE)
{
daexperiencia(1000, [jugador]);
}
Vamos a la siguiente línea:
daexperiencia(1000, [jugador]);
Vamos a buscar rápidamente una función de experiencia, busquemos por XP.
El resultado que aparentemente mejor se ajusta es: GiveXPToCreature
Su descripción es:
// Gives nXpAmount to oCreature.
void GiveXPToCreature(object oCreature, int nXpAmount)
¿véis el void? significa que no devuelve nada. Y requiere dos cosas, un objeto (a quién dar la experiencia) y una cantidad (la experiencia a dar)
En nuestro caso:
GiveXPToCreature(oJugador, 1000);
¡Como mola! ¡Veámoslo completo!
object oJugador;
oJugador = GetPlaceableLastClickedBy();
if (GetIsPC(oJugador) == TRUE)
{
GiveXPToCreature(oJugador, 1000);
}
oJugador = GetPlaceableLastClickedBy();
if (GetIsPC(oJugador) == TRUE)
{
GiveXPToCreature(oJugador, 1000);
}
¡Ya hemos hecho un script!
Esto, en el editor de scripts iría todo dentro del void main() { }
Tal que así:
void main()
{
object oJugador;
oJugador = GetPlaceableLastClickedBy();
if (GetIsPC(oJugador) == TRUE)
{
GiveXPToCreature(oJugador, 1000);
}
}
{
object oJugador;
oJugador = GetPlaceableLastClickedBy();
if (GetIsPC(oJugador) == TRUE)
{
GiveXPToCreature(oJugador, 1000);
}
}
Guardaríamos este script con un nombre, se compilaría y nos daría este mensaje:
20/02/2012 14:16:46: 0 errores. 'test' se ha compilado con éxito
Despues iríamos a nuestro ubicado, lo examinaríamos y en la pantalla de guiones, en el onused pondríamos este script.
¿Qué pasa si lo ponemos en el onphysicalattacked? ¿daría xp cada vez que atacásemos? ¡No! ¿sabéis porqué?
Os lo explico rápidamente. cada vez que atacásemos se ejecutaría el script, este script:
void main()
{
object oJugador;
oJugador = GetPlaceableLastClickedBy();
if (GetIsPC(oJugador) == TRUE)
{
GiveXPToCreature(oJugador, 1000);
}
}
{
object oJugador;
oJugador = GetPlaceableLastClickedBy();
if (GetIsPC(oJugador) == TRUE)
{
GiveXPToCreature(oJugador, 1000);
}
}
Como el oJugador es el último que hizo click, nunca podría darle XP al atacar, debería ser algo como:
// Get the last attacker of oAttackee. This should only be used ONLY in the
// OnAttacked events for creatures, placeables and doors.
// * Return value on error: OBJECT_INVALID
object GetLastAttacker(object oAttackee=OBJECT_SELF)
¿véis? esta función nos daría quién es el último jugador que atacó el ubicado.
Pero esto sería ir entrando cada vez más y más en detalles, lo importante es que creéis un script y probéis y experimentéis. Poned las dudas que tengáis pero ... ¡CON TODA LA INFORMACIÓN POSIBLE! no seáis escuetos cuando preguntéis, se trata de que todos aprendan con las dudas y las respuestas.
¡No os olvidéis de hacer el objeto usable! (el ubicado) ya que es importante para poder seleccionarlo y hacer click o atacarlo.
¡Todas las dudas al infierno con ellas! Eso sí, cuando vuelvan del averno os dejo que preguntéis.
Un saludo, espero que os guste y perdáis tiempo con ello.