inmensia |
MMORPG DB: Misiones (1/4)
Juan Mellado, 12 Julio, 2008 - 09:36
¿Quién no ha tenido que matar alguna vez 10 ratas negras portadoras de la peste en un huerto de calabazas de un granjero perezoso para subir de nivel? ¡Ah!, ese popular mecanismo de adquisición de puntos de experiencia a través de la realización de misiones. Adorado y odiado a partes iguales, ¿pero qué no lo es hoy en día? Existen muchos tipos de misiones (quests), aunque suelen abundar las de matar a un número determinado de criaturas, las de recolectar un número determinado de objetos, las de buscar a un determinado personaje, las de escoltar a un determinado personaje, y así sucesivamente. Hace un tiempo Astaroth se marcó un bonito post acerca de los sidequests más populares. Es decir, las misiones secundarias que pueden realizarse dentro de la trama principal. Una de las características principales de las misiones es que deben estar perfectamente definidas, aunque las indicaciones que se le den al jugador puedan ser un poco ambiguas. O sea, siempre hay un algo concreto que comienza la misión, y siempre hay un algo concreto que la termina. Lo que varía enormemente son esos "algos" concretos de un tipo de misión a otro. Esta variedad hace que sean difíciles de modelar siguiendo un enfoque relacional clásico. No obstante, para ayudar con el diseño pueden extraerse una serie de características comunes a todas ellas: - Iniciador: Debe de haber una forma de empezar una misión, y lo más habitual es que algún personaje nos la ofrezca cuando hablemos con él, aunque también puede ofrecérsenos cuando realicemos una determinada acción sobre un objeto. Un diseño que recogería sin mayor problema este tipo de relación consistiría en crear dos tablas. Una primera que relacionase personajes y misiones, y una segunda que relacionase objetos y misiones. Cuando se hablase con un personaje bastaría ir a la primera tabla a ver las misiones que ofrece, y de igual forma, cuando se interactuase con un objeto bastaría ir a la segunda tabla. - Requisito: No todos los jugadores pueden realizar todas las misiones. Estas se ofrecen normalmente de una forma secuencial en función de la experiencia o nivel que se tenga. Es más, algunas misiones sólo están disponibles para una determinada facción, raza o clase. E incluso algunas misiones sólo se pueden coger si se han completado previamente otras. Es decir, los requisitos que se deben cumplir para tomar una misión pueden ser de casi cualquier tipo. En este punto yo creo que lo mejor es poner un límite y sacar factor común en función de las características concretas del juego que estemos desarrollando. Si el juego contempla facción, raza, clase y nivel, por ejemplo, entonces bastaría con añadir columnas a la tabla de misiones con cada uno de esos atributos, y ofrecer a los jugadores sólo las misiones para las que cumplan con los requerimientos mínimos de las mismas. Para el caso de misiones que dependen de una previa bastaría con añadir de igual forma una nueva columna a la tabla de misiones que apuntase a la misión previa (si aplica), y crear una nueva tabla en la que se guardase para cada jugador las misiones que está realizando o ya ha realizado. - Recompensa: Cada misión debe ofrecer algún tipo de premio por su finalización. Normalmente un puñado de monedas, un objeto o varios, o una combinación de los dos anteriores. A veces la recompensa es fija, y otras veces se nos permite elegir en el momento de cobrar. De igual forma, los puntos de experiencia adquiridos suelen ser variables, dependiendo normalmente del nivel que se tenga en el momento que se realice la misión. Para reflejar todo esto en el modelo de base de datos bastaría con crear una nueva tabla que relacionase objetos con misiones. En dicha tabla además haría falta indicar por cada objeto si pertenece a la parte de la recompensa fija o a la parte variable, y la cantidad de ellos. Por su parte, el dinero y los puntos de experiencia se incluirían directamente como nuevas columnas dentro de la tabla de misiones, aunque los puntos de experiencia finales retribuidos al jugador pueden ser muy distintos a los almacenados en la tabla. - Objetivo: Todas las misiones deben de ser de algún tipo concreto: matanza, recolección, escolta, ... Aunque es fácil reflejar esto en el modelo de base de datos, con una columna de tipo en la tabla de misiones, es más complicado guardar el objetivo concreto de cada tipo de misión. Es decir, si se tienen que matar un número determinado de criaturas entonces se debe almacenar en base de datos la clase de criatura y el número de ellas a matar, pero si se tienen que recolectar objetos entonces se tienen que almacenar el tipo de objeto y el número de ellos a recolectar. Reflejar todos los posibles tipos de misiones en la base de datos requiere realizar un esfuerzo de abstracción bastante importante, y a la postre puede que resulte inútil si se diseña un nuevo tipo de misión que no case con ninguno de los anteriores. Este es uno de los pocos casos en los que de buen gusto me saltaría la normalización y simplemente añadiría columnas genéricas a la tabla de misiones: objetivo1, objetivo2, objetivo3, ... para que fueran interpretadas en función del tipo de misión. Una veces objetivo1 será el ID de una criatura, y otras veces será el ID de un personaje. Unas veces objetivo2 será el número de criaturas a matar, y otras veces simplemente no tendrá ningún valor. Una alternativa a este planteamiento es crear una columna de tipo TEXT (e incluso BLOB) y guardar en ella esa información en algún tipo de formato procesable como puede ser XML. El problema de todas estas soluciones es que el modelo no reflejará de un forma obvia las relaciones entre las misiones y el resto de entidades. - Seguimiento: Mientras que los tipos de misiones es obvio que se pueden acabar guardando de alguna forma en base de datos, es necesario entender que el seguimiento de las misma ha de realizarse por código. Es decir, para cada tipo de misión habrá que hacer un código a medida que vaya interpretando las acciones de los jugadores y poniéndolas en correspondencia con los objetivos de las misiones que estén realizando. Por ejemplo, para algunas misiones se puede establecer un límite de tiempo, y es claro que debe ser el programa el que lleve esa cuenta. Como ya se comentó anteriormente, habrá que crear una tabla en la que se guarde para cada jugador las misiones que está realizando, y las que ya ha realizado, indicando los objetivos alcanzados para cada una de ella en cada momento concreto: criaturas matadas, objetos recolectados, ... En dicha tabla podría almacenarse además información adicional a efectos estadísticos, como el nivel con el que finalmente la realizó, el tiempo que tardó en realizarla, la recompensa que escogió, ... ¿No encontró lo que buscaba?Utilice el buscador para encontrar más páginas en esta web o en toda Internet. |
Mi comentario va dedicado a los que deseen crear realizar una estructura "sólida" de misiones.
Deberemos centrarnos en que la cualidad "más variable" de las misiones debe de ser el objetivo.
Por lo tanto la estructura más desarrollada del conjunto misiones debería de ser los objetivos, cosa que, a mi juicio, practicamente has pasado por alto.
Personalmente me decantaría por crear una tabla llamada objetivos que tendría de clave primaria objetivo_id, de clave foránea quest_id y tipo_objetivo como indicador del tipo.
Para definir cada tipo crearía tablas auxiliares definiendo sus cualidades específicas ya que prefiero llenar la base de datos de tablas "auxiliares" que de campos vacios/nulos.
De este modo adquirimos la opción de que existan objetivos de diferentes tipos e incluso varios del mismo tipo en la misma quest.
Bueno, en realidad al principio indico que para cada tipo de misión habría que guardar los objetivos concretos. Quizás me faltaría haber añadido: "cada uno en su propia tabla". (Excusas, excusas, excusas, ...)
Desde el punto de vista del modelado esa solución que propones es la que mejor deja normalizado el modelo. Totalmente de acuerdo. Añadir además, que para el seguimiento, habría que crear también el mismo número de tablas que para los objetivos, pero relacionadas de alguna forma con el personaje/misión.
Lo de mezclar tipos de objetivos creo que eso es cuestión ya del juego concreto que se esté desarrollando y los tipos de misiones que se quieran implementar. ¿"Matar" y "recolectar" dentro de una misma misión?
Esta mañana cuando he escrito el post estaba pensando más en como resolver toda la gestión de misiones por código [con un sólo acceso a base de datos] en vez de como diseñar una base de datos normalizada.
Muchas gracias por tu aportación.