Buenas.
Si, habéis leido bien. Voy a enseñaros a hacer script casi tan bien como los hago yo. No aprenderéis a hacer mucho, pero conseguiréis una base que os ayudará a hacer vuestras propias mierdas (c) vosotros mismos.
Si algún scripter considera que hay modo mejor que los que expongo aqui de hacer algo, le pido por favor que explique ese modo en lo máximo posible.
Antes de recordar, simplemente decir que TODOS los comandos (menos el if statement que no es un comando), llevan un punto y coma (;) al final del comando.
Empecemos:
Punto 1: Variables
Las variables son un tipo de dato cuyo valor o contenido es, como indica el nombre, variable. Esto sirve para hacer operaciones con datos de fuera (introducidos por el usuario), o que se modifican a lo largo del proceso. Cuando un dato es creado a base de sumar ,dividir, restar o multiplicar una o varias veces unas cuantas variables, se les llama "algoritmo."
Algoritmo de nivel 1
CARDMAKER_GOLDCOINS+@INSCOIN
Algoritmo complejo
(bStr/2+MaxWeight/300+bAgi/2)-(@Player2DEF-5)
Variable simple temporal:
@hola
Existen varios tipos de variables, de las que destacaré las que suelo usar más:
Variables "at" (@variable)
Son variables que se guardan temporalmente. Se borran al terminarse la ejecución del NPC o script.
Variables "downslash dollar" (_variable$)
Son variables que conllevan un texto. NO son temporales. Se atachan al personaje.
Variables "simple" (variable)
Son variables normales, que se atachan al personaje.
Variables "dollar" ($variable)
Son variables que se atachan al NPC. Si un usuario cambia de valor esta variable, que es mostrada en pantalla cada vez que se ejecuta el script, otro usuario que llegue podrá ver ese mismo valor.
Existen más tipos de variables, como la variable "dot" (.variable), que son globales, y, a su vez, todas estas son mezclables con "at".
Ejemplo de código usando una variable de texto, o downslash dollar:
if(_YourHP$=="Player1hp") goto Player2LifeCheck;
if(_YourHP$=="Player2hp") goto Player1LifeCheck;
Punto 2: Procedural Programming, y Object Oriented Programming (Programación de procedimientos, y programación direccionada a objetos)
Si bien es cierto que la programación en todos los sentidos, se trata de unas ordenes que damos al ordenador, en un orden concreto, los scripts y NPC's de RO siguen también un tipo de programación llamada "OOP" (Programación dirigida a objetos).
Mientras que la programación de procedimiento tiene un orden fijo y es casi inalterable, la programación dirigida a objetos ejecuta una parte de su código cuando un conjunto de condiciones es correcta.
Sin embargo, elijas el modo de programar que elijas, todos los caminos son correctos.
Punto 3: Mes, Menu, Goto, Label.
Estos son los 4 de los 6 pilares de cualquier script medio avanzado. Veremos el quinto pilar después.
MES
Este comando sirve para dar un texto de un NPC, tal como solemos verlo cuando hablamos con un npc. Si, en la cajita blanca.
mes "[Conjuratix]";
mes "Estoy borracho, ¿Ick?";
Cada finalización del comando, equivale a una pulsación de enter. Ese último código, aparecerá como:
[Conjuratix]
Estoy borracho, ¿Ick?";
Es simple el comando, ¿Verdad?. Se puede combinar fácilmente con una variable, de estos modos:
mes "[Conjuratix]";
mes _nombre$ + " , ¿estás bien?";
mes "Es que, "+ _nombre$ + " me preocupas. Cuídate...";
mes "Vale? " + _nombre$;
Fácil, ¿Verdad?
Menu
El menu, hace que salte un menú del cual, el jugador puede escoger una serie de opciones. Cada opción, lleva a un label que nosotros hallamos puesto.
La sintaxis es:
menu "Cosa",label;
Se pueden añadir más opciones al menú, añadiendo más "texto",label .
menu "Cosa 1",label1,"Cosa 2",label2,"Cosa 3",label3;
Ejemplo de código usando menu:
mes "Player's Turn.";
next;
menu "Attack",attack1,"Magic",magic1,"Do nothing",recover1;
GOTO
El comando "goto", se usa mucho en combo con el IF Statement (cosa que veremos más tarde).
La sintaxis es:
goto label;
Simple, ¿Verdad?. Esto hará que se el código de un "salto" hasta donde esté puesta la etiqueta "label".
Label (Etiquetas)
Son una serie de nombres que se les da a una parte del código, para volver a esa parte del código fácilmente.
Super ejemplo mezclando goto y labels:
if(@DisponibleMagic<=150) goto magic1501;
magic151:
menu "Volver",Player1Turn,"Fireball",magicfb1;
magic301:
menu "Volver",Player1Turn,"Fireball",magicfb1,"Jupiter",magicjp1;
magic501:
menu "Volver",Player1Turn,"Fireball",magicfb1,"Jupiter",magicjp1,"Venus",magicvn1;
magic751:
menu "Volver",Player1Turn,"Fireball",magicfb1,"Jupiter",magicjp1,"Venus",magicvn1,"Terra",magictr1;
magic1001:
menu "Volver",Player1Turn,"Fireball",magicfb1,"Jupiter",magicjp1,"Venus",magicvn1,"Terra",magictr1,"Solaris",magicsl1;
magic1501:
menu "Volver",Player1Turn,"Fireball",magicfb1,"Jupiter",magicjp1,"Venus",magicvn1,"Terra",magictr1,"Solaris",magicsl1,"Gaia",magicgay1;
Punto 3: Pilar 5, If statement(Estamento condicional)
Bien, tras esto, estarás CASI preparado para empezar a programar.
El estamento "if", hace que se ejecute una pieza de código en caso de que una condición sea exacta. Se puede hacer que el "if" checkee si se cumples unas condiciones a la vez, o una condición de entre varias. Para esto, entre cada condición, se escribe "||" (OR) o "&&" (AND). Veamos un ejemplo:
if(clave1==5) goto correcto; // Condición simple positiva.
if(clave1==5 || clave2==5) goto correcto; // Condición selectiva. En caso de ser una correcta, va al label correcto.
if(clave1==5 && clave2=55) goto correcto; // Condición aditiva. En caso de ser todas las condiciones correctas se da postivo.
if(clave1==5 && clave2=55 || clave1==4 && clave2=44) goto correcto; Condición mixta. En caso de ser correcta una de las dos combinaciones de condiciones aditivas, se considera positivo.
Como habeis visto, el || tiene preferencia sobre &&. Esto significa que clave1==5 && clave2==55 || clave1=4 && clave2=44, se traduce como:
Si clave 1 es igual a 5, y a su vez, clave2 igual a 55,
O
clave 1 igual a 4, y a su vez, clave2 igual a 44,
positivo.
A este estamento, se le añade un estamento opcional llamado "else" (si no).
if(clave1==4) mes "Clave correcta.";
else mes "Incorrecto.";
Else e If se puede hacer que ejecuten bloques de código, para eso, se añade una llave doble.
if(clave1==4){
mes "Linea 1";
mes "Linea 2";
Set @Variable,5;
mes @Variable;
}
else{
mes "Linea 1";
mes "Linea 2";
Set @Variable,10;
mes @Variable;
}
Punto 4: Set Variable,value
Esto es simplísimo. Este comando hace que una variable tenga un valor en concreto, o un valor según otras variables sumadas, restadas, multiplcadas, o divididas entre otras variables o valores fijos. El límite lo pone tu mente.
// bStat son los puntos de status gastados en STR y demases
Set @Variable, bStr+bVit+bAgi+bInt+bDex+bLuk;
Los códigos de los operadores son:
+ - * /
¿Dudas?
//Edit////////////////////////////////////////////////////////////////
Behind the cameras: Lo que se me olvidó.
La estructura básica de un NPC/Script, en eAthena, consiste de:
mapa.gat,posx,posy,dir<tabulación>script<tabulación>nombrenpc<tabulación>spritenum,{
//código
}
mapa.gat , es el mapa (incluyendo la extensión para npc's tipo script, excepto para npc's tipo script-evento y funciones). Posx y Posy , son las posiciones en el mapa.
En los videojuegos, los mapas usan un sistema de coordenadas diferentes a los que usamos en mates. Mientras que en mates, el centro es 0,0 , en un juego, 0,0 es la esquina superior izquierda.
Sin embargo, en RO, 0,0 es la esquina
inferior izquierda.
Aún así, sería casi imposible calcular el lugar de un npc. Para eso tenemos el comando @where [tu nick aqui] , que te dice mapa y coordenada exacta. ¿Cómodo, verdad? Sólo tendrás que copiar esos datos.
Dir es la dirección en la que aparece el NPC mirando. van de 1 ( o 0, no recuerdo) a 9. Yo suelo usar 5 ya que la gente suele tener la cámara sin moverla, y 1 cuando hay que girar la cámara para ver el npc.
spritenum, es el número de sprite del NPC. Hay una lista ( esta
http://kismet.files.deltaanime.net/npclist.html ), que tiene todos los NPC's. Sin embargo, a veces no funciona, así que os pondré también la página en caché de google ( este
http://64.233.183.104/search?q=cache:lfaAxPKefkoJ:kismet.files.deltaanime.net/npclist.html+NPC+list&hl=es&ct=clnk&cd=1&gl=es ). Para probar un NPC que no aparece su gráfico en el caché de google, simplemente pon @disguise numeronpc . Si te tira error, vuelve al servidor, y verás que no te lo vuelve a tirar porque estas sin el sprite: ya sabes que no tira.
Existen otros tipos de NPC. Los npc tipo shop, que funcionan en una sola línea, que van así:
prontera.gat,223,99,5 shop Forging Shop 748,723:50000,724:5000
(Este código ha sido cogido de un npc existente, en una de las carpetas de mi servidor. No lo hice yo).
Leamos su código
mapa.gat,posx,posy,dir<tabulación>shop<tabulación>Nombre tienda<tabulación>spritenum,itemid:precio,itemid:precio
Aqui lo nuevo es que en vez de poner "script", ponemos "shop", y que ya no hay scripting del que vimos hace poco. Spritenum sigue normal, pero... ¿y el resto?
Tras spritenum, se pone una COMA ( , ), el ID del objeto (@ii objeto), DOS PUNTOS ( : ), y el precio del objeto. Para agregar más objetos al a tienda, se pone OTRA COMA ( , ), otra id, OTROS DOS PUNTOS ( : ), otro precio, y así hasta que no queramos poner más items.
Los scripts tipo función, son scripts que llamas desde otro script, para hacer varias cosas. Estas funciones son útiles cuando tienes varios NPC's, que son diferentes, pero que tienen una parte en común. Por ejemplo, tenemos varias kafras custom que hemos hecho, y queremos que saluden al jugador con su nombre, y un hola.
Para eso, cargamos al servidor como cualquier otro npc. La función que hemos hecho es así:
function<tabulación>script<tabulación>nombrefuncion<tabulación>{
mes "Hola" + strcharinfo(0);
next;
}
Bien, ¿Cómo hacemos para llamar a nuestra función? Fácil. En la kafra, donde queramos que ella diga el nombre del user, ponemos:
callfunc "nombrefuncion";
Para llamar a una función con variables o datos especiales, se usa:
callfunc "nombrefuncion",1,2,3,4;
Añadiendo tantos valores con coma en el medio como hagan falta.
Si en vez de querer poner hola, queremos que la kafra diga otra cosa (un texto en concreto), nos basta con poner la llamada así:
callfunc "nombrefuncion","Oye ";
¿Qué es lo que tendriamos que cambiar en la función? En vez de tener "Hola " + strcharinfo(0); , tendríamos que poner:
mes getarg(0) + strcharinfo(0);
Como verás, hemos puesto un 0 en getarg (coger argumento/variable), en vez de 1, ya que hay 1 argumento. Esto es debido a que se cuenta desde 0.
Algo así, son los array. Los array son un tipo de variable que pueden contener muchos números dentro suya. Pero, en contra de lo que podais pensar, de letras sólo pueden almacenar 1 caractér por parte.
Podemos definir un array de varios modos:
Set array[0], valornumérico;
Esto hará que la parte 0 del array "array", tenga el valor numérico "valornumérico".
Set array[1], valornumérico2;
Esto hará que la parte 1 del array "array", tenga el valor numérico "valornumérico2";.
Sin embargo, esto es muy trabajoso para hacer, así que eA tiene un comando llamado "set array", en el que defines desde que parte se empiezan a introducir valores, y vas poniendo los valores directamente.
setarray array[0],valor1,valor2,valor3;
Se pueden añadir más valores, siguiendo el patrón. En este tipo de definiciones, puedes decidir desde que parte del array empezar ,cambiando "0" por la parte donde quieres.
setarray @mvpid[0],1,2; // MvP's de ejemplo
mes "Baphomet: 1";
mes "Creamy: 2";
next;
input @sacamvp; // input fuera del for para pedirlo sólo una vez.
Set @vuelta,0;
if(@sacamvp<=0 || @sacamvp>=3) goto l_fallo;
do{
if(@sacamvp==@vuelta){// Un sólo check para todos. Ya que @vuelta irá cambiando, es el equivalente a poner muchos if.
Set Zeny,Zeny-2000000; // Menos 2 millones
if(@vuelta==1) atcommand "@monster baphomet";
if(@vuelta==2) atcommand "@monster creamy";
/// y añadimos más IF según más mobs queremos.
}
Set @vuelta,@vuelta+1;
}while(@monstruo<2) // No suelo usar for, es muy complicado XDDD do while suena mejor.
l_fallo:
mes "No permitido.";
close;
^Ejemplo de código usando arrays.
Para práctica personal, te diré que ese script tiene uno o más fallos, pero sólo uno es un error que se comete bastante a menudo cuando se empieza a aprender scripting. ¿Cuál es?
¡Exacto! No chequea el Zeny que tiene el jugador, para cancelar la acción.
Un último punto que daré: do {} while ().
Do while es un loop (vuelta) que se repite cuando llega a lfinal, desde el principio del mismo, mientras se cumpla una o varias condiciones.
prontera.gat,164,169,5 script DOWHILE Ejemplo 46,{
setarray @woot[0],1,2,3,4;
Set @vuelta,0;
do{
mes @woot[@vuelta];
Set @vuelta,@vuelta+1;
}while(@vuelta<=3);
close;
}
^Este código muestra 4 números en pantalla, los 4 del array.
Eso es todo.