tool software online lucidchart examples data database database-design

database - software - Diseño de tablas para almacenar varios requisitos y estadísticas para el juego multijugador



database diagram tool (13)

Pregunta Original:

Hola,

Estoy creando un proyecto de hobby muy simple: un juego para jugadores múltiples basado en navegador. Estoy atrapado en el diseño de tablas para almacenar información sobre los requisitos de misión / habilidad.

Por ahora, diseñé mis tablas de la siguiente manera:

  • usuario de tabla (información básica sobre los usuarios)
  • tabla estadística (variedad de estadísticas)
  • table user_stats (conectando a cada usuario con estadísticas)

Otro ejemplo:

  • monstruos de mesa (información básica sobre enemigos npc)
  • table monster_stats (conecta monstruos con estadísticas, usando la misma tabla de estadísticas desde arriba)

Esos fueron los casos simples. Debo admitir que estoy atascado al diseñar requisitos para diferentes cosas, por ejemplo, misiones. La búsqueda de muestra A puede tener solo requisitos mínimos de nivel de carácter (y eso es fácil de implementar), pero otra, la búsqueda B tiene multitud de otros requisitos (misiones terminadas, habilidades adquiridas, posesión de elementos específicos, etc.): ¿cuál es una buena forma de diseñando tablas para almacenar este tipo de información?

De manera similar, ¿cuál es una forma eficiente de almacenar información sobre los requisitos de habilidades? (clase de personaje específico, nivel mínimo, etc.)

Agradecería cualquier ayuda o información sobre la creación de juegos basados ​​en bases de datos.

Editar:

Gracias por las respuestas, pero me gustaría recibir más. Como estoy teniendo algunos problemas para diseñar un diseño de base de datos bastante complicado para artículos que se pueden crear, estoy comenzando una recompensa máxima por esta pregunta.

Me gustaría recibir enlaces a artículos / fragmentos de código / todo lo relacionado con las mejores prácticas de diseño de bases de datos para almacenar datos de juegos (un buen ejemplo de este tipo de información está disponible en buildingbrowsergames.com ).

Apreciaría cualquier ayuda.


Con respecto a su estructura básica, puede (dependiendo de la naturaleza de su juego) considerar conducir hacia la convergencia de representación entre el personaje jugador y los personajes no jugadores, por lo que ese código que naturalmente operaría igual en cualquiera de ellos no tiene que preocuparse sobre la distinción. Esto sugeriría, en lugar de tener tablas de user y monster , tener una tabla de character que represente todo lo que las PC y NPC tienen en común, y luego una tabla de user para información exclusiva de PC y / o cuentas de usuario. La tabla de user tendría una clave externa character_id , y podría decirle a una fila de caracteres de jugador por el hecho de que existe una fila de user correspondiente.

Para representar misiones en un modelo como el tuyo, la forma en que lo haría se vería así:

quest_model =============== id name [''Quest for the Holy Grail'', ''You Killed My Father'', etc.] etc. quest_model_req_type =============== id name [''Minimum Level'', ''Skill'', ''Equipment'', etc.] etc. quest_model_req =============== id quest_id quest_model_req_type_id value [10 (for Minimum Level), ''Horseback Riding'' (for Skill), etc.] quest =============== id quest_model_id user_id status etc.

Entonces un quest_model es la definición central de la estructura de búsqueda; cada quest_model puede tener 0..n filas quest_model_req asociadas, que son requisitos específicos de ese modelo de búsqueda. Cada quest_model_req está asociado con un quest_model_req_type , que define el tipo general de requisito: lograr un nivel mínimo, tener una habilidad, poseer una pieza de equipo, y así sucesivamente. El quest_model_req también tiene un value , que configura el requisito para esta misión específica; por ejemplo, un requisito de tipo Nivel mínimo puede tener un value de 20, lo que significa que debe tener al menos el nivel 20.

La tabla de quest , entonces, es una instancia individual de misiones que los jugadores están emprendiendo o han emprendido. La quest está asociada con un quest_model y un user (o quizás un character , si alguna vez quieres que los PNJ puedan hacer misiones), y tiene un status indica dónde se encuentra el progreso de la misión y cualquier otro seguimiento que resulte útil.

Esta es una estructura escueta que, por supuesto, tendría que construirse para satisfacer las necesidades de juegos particulares, pero debería ilustrar la dirección que recomendaría.

Ah, y dado que alguien más arrojó sus credenciales, la mía es que he sido un desarrollador de juegos de aficionados en proyectos en vivo y en público desde hace 16 años.


Cuando tienes un problema centrado en los datos, la base de datos es tu amiga. Lo que has hecho hasta ahora parece ser bastante correcto.

Por otro lado, los otros problemas que menciona parecen estar centrados en el comportamiento. En este caso, un análisis orientado a objetos y una solución funcionarán mejor.

Por ejemplo: crea una clase de misión con clases específicas de childQuest. Cada niño debe implementar un bool HasRequirements(Player player) .


El hilo de la answer @Shea Daniel está en el camino correcto: la especificación para una misión no es relacional , y también incluye la lógica y los datos .

Usar XML o Lua son ejemplos, pero la idea más general es desarrollar tu propio lenguaje específico de dominio para codificar misiones. Aquí hay algunos artículos sobre este concepto, relacionados con el diseño del juego:

Puede almacenar el bloque de código para una misión determinada en un campo TEXT en su base de datos, pero no tendrá mucha flexibilidad para usar SQL para consultar partes específicas de la misma. Por ejemplo, dadas las habilidades que un personaje tiene actualmente, ¿qué misiones le quedan abiertas? Esto no será fácil de consultar en SQL, si los requisitos previos de la misión están codificados en su DSL en un campo TEXT .

Puede tratar de codificar prerrequisitos individuales de una manera relacional, pero se sale de control rápidamente. Relacional y orientado a objetos simplemente no van bien juntos. Puede intentar modelarlo de esta manera:

Chars <--- CharAttributes --> AllAttributes <-- QuestPrereqs --> Quests

Y luego haz una combinación LEFT JOIN busca de misiones para las que no faltan prerrequisitos en los atributos del personaje. Aquí está el pseudo-código:

SELECT quest_id FROM QuestPrereqs JOIN AllAttributes LEFT JOIN CharAttributes GROUP BY quest_id HAVING COUNT(AllAttributes) = COUNT(CharAttributes);

Pero el problema con esto es que ahora debes modelar cada aspecto de tu personaje que podría ser un requisito previo (estadísticas, habilidades, nivel, posesiones, misiones completadas) como algún tipo de " Atributo " abstracto que se ajuste a esta estructura.

Esto resuelve este problema de seguimiento de requisitos previos de búsqueda, pero te deja con otro problema: el personaje se modela de una manera no relacional, esencialmente una arquitectura de Entidad-Valor-Atributo que rompe un grupo de reglas relacionales y hace que otros tipos de consultas sean increíblemente difícil.


He hecho algo similar y mi solución general fue utilizar muchos metadatos. Estoy usando el término vagamente para significar que cada vez que necesite nuevos datos para tomar una decisión determinada (permitir una búsqueda, permitir el uso de un elemento, etc.) crearía un nuevo atributo. Esto era básicamente una tabla con un número arbitrario de valores y descripciones. Entonces, cada personaje tendría una lista de estos tipos de atributos.

Ej .: Lista de asesinatos, nivel, regiones visitadas, etc.

Las dos cosas que esto hace a su proceso de desarrollo son:

1) Cada vez que hay un evento en el juego, necesitas tener un gran bloque de conmutadores antiguo que verifique todos estos tipos de atributos para ver si algo necesita actualización.

2) Cada vez que necesite datos, verifique todas las tablas de atributos ANTES de agregar una nueva.

Encontré que esta es una buena estrategia de desarrollo rápido para un juego que crece orgánicamente (no completamente planeado en papel antes de tiempo), pero es una gran limitación que su contenido pasado / actual (niveles / eventos, etc.) no será compatible. con atributos futuros, es decir, ese mapa no le dará una insignia de región porque no había distintivos de región cuando lo codificó. Esto, por supuesto, requiere que actualice el contenido anterior cuando se agregan nuevos atributos al sistema.


Me acercaría a esto desde un punto de vista orientado a objetos, en lugar de un punto de vista centrado en los datos. Parece que podría tener un montón de objetos (poss complejos). Recomiendo primero modelarlos (con sus relaciones) y confiar en un ORM para la persistencia.



Otra opción es algún tipo de motor de reglas (Drools, por ejemplo, si está usando Java).


Parece que está listo para principios generales de diseño orientado a objetos (OOD). Voy a ignorar intencionalmente el contexto (juegos, MMO, etc.) porque realmente no importa cómo se hace un proceso de diseño. Y el hecho de que le proporcione enlaces es menos útil que explicar qué términos serán más útiles para buscar usted mismo, IMO; Pondré esos en negrita.

En OOD, el esquema de la base de datos proviene directamente del diseño de su sistema, y ​​no al revés. Su diseño le dirá cuáles son sus clases de objetos base y qué propiedades pueden vivir en la misma tabla (las que están en relación 1: 1 con el objeto) contra las que crear tablas de asignación para (cualquier cosa con relaciones 1: n o n: m - Por ejemplo, un usuario tiene múltiples estadísticas, por lo que es 1: n). De hecho, si hace el OOD correctamente, tendrá que tomar cero decisiones con respecto al diseño final de la base de datos.

La forma "correcta" de hacer cualquier asignación de OO se aprende como un proceso de varios pasos llamado "Normalización de la base de datos" . Los conceptos básicos son los que acabo de describir: encuentre la "aridad" de las relaciones de objeto (1: 1, 1: n, ...) y cree tablas de asignación para 1: n''s y n: m''s. Para 1: n terminas con dos tablas, la tabla "base" y una tabla "base_subobjects" (por ejemplo, tus "usuarios" y "user_stats" es un buen ejemplo) con la "clave externa" (el Id de la base) objeto) como una columna en la tabla de asignación de subobjetos. Para n: m''s, terminas con tres tablas: "base", "subobjetos" y "base_subobjects_map" donde el mapa tiene una columna para el Id base y otra para el Id del subobjeto. Esto podría ser necesario en su ejemplo para N misiones que pueden tener cada una M requisitos (por lo que las condiciones de requisito se pueden compartir entre misiones).

Eso es 85% de lo que necesita saber. El resto es cómo manejar la herencia, que te aconsejo que saltes a menos que seas masoquista. Ahora imagina cómo quieres que funcione antes de comenzar a codificar cosas y el resto es torta.


Sería extremadamente cuidadoso de lo que realmente almacena en un DB, especialmente para un MMORPG. Tenga en cuenta que estas cosas están diseñadas para ser MASIVAS con miles de usuarios, y el código de juego tiene que ejecutarse excesivamente rápido y enviar una gran cantidad de datos a través de la red, no solo a los jugadores en sus conexiones domésticas sino también entre los servidores. el back-end. También vas a tener que escalar horizontalmente y las bases de datos y la ampliación no son dos cosas que siento que se mezclan particularmente bien, particularmente cuando comienzas a fusionar en diferentes regiones y luego a agregar servidores de instancia a tus fragmentos, y así sucesivamente. Usted termina con una gran cantidad de servidores hablando con bases de datos y pasando una gran cantidad de datos, algunos de los cuales ni siquiera son relevantes para el juego (el texto SQL que va a un servidor SQL es tráfico de red inútil que debe reducir en )

Aquí hay una sugerencia: limite su base de datos SQL a almacenar solo cosas que cambiarán a medida que los jugadores jueguen. Los monstruos y las estadísticas de monstruos no cambiarán. Los ítems y las estadísticas de los ítems no cambiarán. Los objetivos de la misión no cambiarán. No almacene estas cosas en una base de datos SQL, en su lugar guárdelas en el código en alguna parte.

Hacer esto significa que cada servidor que alguna vez viva siempre sabrá toda esta información sin tener que consultar una base de datos. Ahora, no almacena misiones en absoluto, solo almacena los logros del jugador y el juego determina programáticamente los efectos de esas misiones que se completan. No desperdicia la información de transferencia de datos entre servidores porque solo está enviando identificaciones de eventos o algo por el estilo (puede optimizar los datos que pasa utilizando solo suficientes bits para representar todos los ID de eventos y esto reducirá la red tráfico. Puede parecer insignificante, pero nada es insignificante en las aplicaciones de red masivas).

Haz lo mismo con las estadísticas de monstruos y las estadísticas de los objetos. Estas cosas no cambian durante el juego, por lo que no es necesario guardarlas en ningún DB, por lo que esta información NUNCA necesita viajar a través de la red. Lo único que almacena es la identificación de los objetos o monstruos mata o algo así que no es determinista (es decir, puede cambiar durante el juego de una manera que no puede predecir). Puede tener servidores de elementos dedicados o servidores de estadísticas monstruosos o algo así y puede agregarlos a sus fragmentos si termina teniendo una gran cantidad de estos elementos que ocupan demasiada memoria, luego solo pase los datos necesarios para una búsqueda en particular o área al servidor de instancia que está manejando esa cosa para reducir aún más el espacio, pero tenga en cuenta que esto aumentará la cantidad de datos que necesita para pasar la red para poner en cola un servidor de instancia nuevo, por lo que es una solución de compromiso. Siempre que sepa las consecuencias de este compromiso, puede usar su buen juicio y decidir lo que quiere hacer. Otra posibilidad es limitar los servidores de instancia a una misión / región / evento / lo que sea particular y solo equiparlo con información suficiente para lo que es responsable, pero esto es más complejo y potencialmente limita su escalamiento ya que la asignación de recursos se volverá estática en lugar de dinámico (si tienes 50 servidores de cada misión y de repente todos van en la misma misión, tendrás 49 servidores inactivos y un servidor realmente inutilizado). Una vez más, es una compensación, así que asegúrese de comprenderla y tomar buenas decisiones para su aplicación.

Una vez que haya identificado exactamente qué información en su juego no es determinista, entonces puede diseñar una base de datos en torno a esa información. Eso se vuelve un poco más fácil: los jugadores tienen estadísticas, los jugadores tienen elementos, los jugadores tienen habilidades, los jugadores tienen logros, etc., todo bastante fácil de trazar. No necesita descripciones para cosas como habilidades, logros, elementos, etc., ni siquiera sus efectos o nombres ni nada, ya que el servidor puede determinar todo eso para usted a partir de los ID de esas cosas en tiempo de ejecución sin necesidad de una consulta en la base de datos.

Ahora, mucho de esto probablemente suene exagerado para ti. Después de todo, una buena base de datos puede hacer consultas muy rápidamente. Sin embargo, su ancho de banda es extremadamente valioso, incluso en el centro de datos, por lo que debe limitar su uso a solo lo que es absolutamente necesario enviar y solo enviar esos datos cuando sea absolutamente necesario que se envíen.

Ahora, para representar quests en el código, consideraría el patrón de especificación ( http://en.wikipedia.org/wiki/Specification_pattern ). Esto le permitirá construir fácilmente objetivos de búsqueda en términos de qué eventos son necesarios para garantizar que se cumplan las especificaciones para completar esa búsqueda. Luego puedes usar LUA (o algo así) para definir tus misiones a medida que construyes el juego para que no tengas que hacer cambios masivos de código y reconstruir toda la maldita cosa para que sea necesario matar 11 monstruos en lugar de 10 para obtener la Espada de 1000 verdades en una misión particular. Cómo hacer algo así creo que está más allá del alcance de esta respuesta y comienza a afectar mi conocimiento de la programación de juegos, así que tal vez alguien más aquí pueda ayudarte si eliges seguir ese camino.

Además, sé que utilicé muchos términos en esta respuesta, por favor pregunte si hay alguno con el que no esté familiarizado y pueda explicarlos.

Editar: no se dio cuenta de su adición sobre los elementos que se pueden crear. Voy a suponer que estas son cosas que un jugador puede crear específicamente en el juego, como artículos personalizados. Si un jugador puede cambiar continuamente estos elementos, puede combinar los atributos de lo que está diseñado en tiempo de ejecución, pero deberá almacenar el ID de cada atributo en el DB en alguna parte. Si crea un número finito de cosas que puede agregar (como las gemas en Diablo II), puede eliminar una combinación simplemente agregando ese número de columnas a la tabla. Si hay un número finito de elementos que se pueden diseñar y un número finito de formas en que las cosas diferentes se pueden unir en nuevos elementos, cuando se combinan ciertos elementos, no es necesario almacenar los atributos combinados; simplemente se convierte en un nuevo elemento que ya has definido en algún momento. Entonces, solo tienen ese elemento en lugar de sus componentes. Si aclaras el comportamiento de tu juego, puedo agregar sugerencias adicionales si eso fuera útil.


Si estuviera diseñando una base de datos para tal situación, podría hacer algo como esto:

Quest [quest properties like name and description] reqItemsID reqSkillsID reqPlayerTypesID RequiredItems ID item RequiredSkills ID skill RequiredPlayerTypes ID type

En este, el mapa de ID a las tablas respectivas luego recuperas todas las entradas bajo ese ID para obtener la lista de elementos requeridos, habilidades, qué tienes. Si permite la creación dinámica de elementos, entonces debe tener una asignación a otra tabla que contenga todos los elementos posibles.

Otra cosa a tener en cuenta es la normalización. Hay un artículo largo here pero he condensado los primeros tres niveles en más o menos lo siguiente:

  • primera forma normal significa que no hay entradas de la base de datos donde un campo específico tiene más de un elemento en él
  • La segunda forma normal significa que si tiene una clave primaria compuesta, todos los demás campos dependen completamente de la clave completa, no solo de partes de ella en cada tabla.
  • La tercera normal es cuando no tiene campos no clave que dependen de otros campos que no son clave en ninguna tabla

[Descargo de responsabilidad: tengo muy poca experiencia con las bases de datos SQL, y soy nuevo en este campo. Solo espero ser de ayuda.]


Voy a editar esto para agregar tantos otros temas pertinentes como pueda, aunque me gustaría que el OP aborde mi comentario anterior. Hablo desde hace varios años como desarrollador profesional de juegos en línea y muchos años más como desarrollador de juegos en línea, por lo que vale.

Los juegos en línea implican algún tipo de persistencia, lo que significa que tiene ampliamente dos tipos de datos: uno es diseñado por usted, el otro es creado por los jugadores en el transcurso del juego. Lo más probable es que vayas a almacenar ambos en tu base de datos. Asegúrese de tener diferentes tablas para estos y hacer una referencia cruzada de los mismos a través de las reglas habituales de normalización de la base de datos. (Por ejemplo, si su jugador hace una espada ancha, no crea una nueva fila completa con todas las propiedades de una espada. Crea una nueva fila en la tabla player_items con las propiedades por instancia, y se refiere a la fila de ancho de espada en la tabla item_types que contiene las propiedades por tipo de elemento). Si encuentra una fila de datos que contiene algunas cosas que usted diseñó y algunas cosas que el reproductor está cambiando durante la reproducción, necesita normalizarlo en dos tablas.

Este es realmente el típico problema de separación clase / instancia, y se aplica a muchas cosas en tales juegos: una instancia goblin no necesita almacenar todos los detalles de lo que significa ser un duende (por ejemplo, piel verde), solo cosas pertinentes a esa instancia (por ejemplo, ubicación, estado actual). Algunas veces hay una sutileza en el acto de construcción, en esa instancia los datos deben ser creados en base a los datos de clase. (Por ejemplo, establecer la salud de inicio de una instancia goblin basada en la salud máxima de un tipo goblin). Mi consejo es codificarlos en el código que crea las instancias e inserta la fila correspondiente. Esta información solo cambia raramente ya que hay pocos de estos valores en la práctica. (Puntajes iniciales de recursos agotables como salud, resistencia, maná ... eso es todo).

Intenta encontrar una terminología coherente para separar los datos de instancia de los datos de tipo: esto te facilitará la vida más adelante cuando estás aplicando un parche en un juego en vivo y tratando de no arruinar el duro trabajo de tus jugadores al editar las tablas incorrectas. Esto también hace que el almacenamiento en caché sea mucho más fácil: por lo general, puede guardar en caché los datos de clase / tipo con total impunidad, ya que solo cambia cuando usted, el diseñador, envía datos nuevos hasta allí. Puede ejecutarlo a través de memcached , o considerar cargarlo todo en el momento del inicio si su juego tiene un proceso continuo (es decir, no es PHP / ASP / CGI / etc.), etc.

Recuerde que eliminar cualquier cosa de sus datos del lado del diseño es arriesgado una vez que se activa, ya que los datos generados por el jugador pueden referirse a él. Pruebe todo a nivel local antes de implementar en el servidor en vivo, porque una vez que está allí, es difícil quitarlo. Considere formas de marcar filas de dichos datos tal como se eliminaron de manera segura, tal vez una columna booleana ''activa'' que, si se configura como falsa, significa que simplemente no se mostrará en la consulta típica. Piensa en el impacto en los jugadores si deshabilitas los elementos que obtuvieron (y el doble si estos son artículos que pagaron).

El lado de la creación real no puede ser respondido sin saber cómo quieres diseñar tu juego. El diseño de la base de datos debe seguir el diseño del juego. Pero voy a atravesar una idea trivial. Tal vez querrás poder crear un objeto básico y luego aumentarlo con runas o cristales o lo que sea. Para eso, solo necesita una relación de uno a varios entre la instancia del elemento y la instancia de aumento. (Recuerde, también puede tener tablas de tipo de elemento y de tipo de aumento.) Cada aumento puede especificar una propiedad de un elemento (por ejemplo, durabilidad, daño máximo hecho en combate, peso) y un modificador (típicamente como un multiplicador, por ejemplo, 1.1 a agregue un 10% de bonificación). Puedes ver mi explicación sobre cómo implementar estos efectos modificadores here y here : los mismos principios se aplican a la habilidad temporal y a los efectos de hechizo que se aplican a la modificación permanente del elemento.

Para las estadísticas de personajes en un juego basado en una base de datos, generalmente aconsejo mantener el enfoque ingenuo de una columna (entero o flotante) por estadística. Agregar columnas más adelante no es una operación difícil y, dado que va a leer mucho estos valores, es posible que no desee realizar uniones en ellos todo el tiempo. Sin embargo, si realmente necesita la flexibilidad, entonces su método está bien. Esto se parece mucho a la tabla de niveles de habilidades que sugiero a continuación: se pueden modelar muchos datos de juegos de esta manera: asignar una clase o instancia de una cosa a una clase o instancia de otras cosas, a menudo con algunos datos adicionales para describir la asignación (en este caso, el valor de la estadística).

Una vez que tenga estas combinaciones básicas configuradas, y de hecho cualquier otra consulta compleja que resulte de la separación de datos de clase / instancia de una manera que puede no ser conveniente para su código, considere la creación de una vista o un procedimiento almacenado para realizarlos detrás del escenas para que el código de su aplicación ya no tenga que preocuparse más.

Otras buenas prácticas de bases de datos se aplican, por supuesto: use transacciones cuando necesite asegurarse de que ocurran varias acciones atómicamente (por ejemplo, transacciones), coloque índices en los campos que busca con más frecuencia, use VACÍO / OPTIMIZAR TABLA / lo que sea durante períodos de tranquilidad para mantener el rendimiento , etc.

(Respuesta original debajo de este punto)

Para ser sincero, no almacenaría la información de requisitos de búsqueda en la base de datos relacional, sino en algún tipo de script. En última instancia, tu idea de un ''requisito'' adopta varias formas diferentes que pueden basarse en diferentes tipos de datos (por ejemplo, nivel, clase, misiones anteriores completadas, posesión de elementos) y operadores (un nivel puede ser un mínimo o un máximo, algunas misiones puede requerir un elemento mientras que otros pueden requerir su ausencia, etc.) sin mencionar una combinación de conjunciones y disyunciones (algunas búsquedas requieren que se cumplan todos los requisitos, mientras que otras solo pueden requerir 1 de varias). Este tipo de cosas se especifica mucho más fácilmente en un lenguaje imperativo. Eso no quiere decir que no tenga una tabla de misiones en el DB, solo que no intente codificar los requisitos a veces arbitrarios en el esquema. Tendría una columna requirement_script_id para hacer referencia a un script externo. Supongo que podrías poner la secuencia de comandos real en la BD como un campo de texto si así lo deseas.

Sin embargo, los requisitos de habilidades son adecuados para la DB, y bastante triviales dado el típico sistema de juego de habilidades de aprendizaje a medida que progresas a través de los niveles en una determinada clase:

table skill_levels { int skill_id FOREIGN KEY; int class_id FOREIGN KEY; int min_level; } myPotentialSkillList = SELECT * FROM skill_levels INNER JOIN skill ON skill_levels.skill_id = skill.id WHERE class_id = my_skill ORDER BY skill_levels.min_level ASC;

¿Necesitas un árbol de habilidades? Agregue una columna prerequisite_skill_id . Y así.


solo algunos pequeños puntos para su consideración:

1) Siempre trate de simplificar los requisitos de "búsqueda de misiones" y los requisitos de "Búsqueda final".

Parte1 se puede hacer "tratando de hacer tus misiones en orden jerárquico":
ejemplo:

QuestA: (Mata a Raven el demonio) (búsqueda de búsqueda: Lvl1)
QuestA.1: Guarda "desconocido" en el bosque para obtener información ... (búsqueda de misiones: QuestA)
QuestA.2: Craft the sword of Crystal ... etc. (Quest req: QuestA.1 == Done)
QuestA.3: ... etc. (Quest req: QuestA.2 == Hecho)
QuestA.4: ... etc. (Quest req: QuestA.3 == Hecho)
etc ...
QuestB (Encuentra la tumba perdida) (búsqueda de misiones: (QuestA.statues == Done))
QuestC (Ir al hipermercado demonios) (Requisito de la misión: (QuestA.statues == Done && player.level == 10)
etc ....

Hacer esto le ahorraría muchos campos de datos / uniones de tablas.

PENSAMIENTOS ADICIONALES:
si usas el sistema anterior, puedes agregar un campo de recompensa extra a tu tabla de misiones llamada "enableQuests" y agregar el nombre de las misiones que deben habilitarse.
Lógicamente ... tendrías un campo "habilitado" asignado a cada misión.

2) Una solución menor para su problema de creación, crear recetas de elaboración, elementos que contengan requisitos de elaboración de elementos para ser elaborados almacenados en ellos ... por lo que cuando un jugador intenta elaborar un artículo ... necesita comprar una receta primero. . A continuación, intente crear. Un ejemplo simple de dicho elemento Desc sería:
Nombre del elemento: "Espada legendaria de los muertos"
Craftevel req. : 75
Artículos requeridos:
Item_1: Hoja de los muertos
Item_2: un sello maldito
item_3: Holy Gemstone of the dead
etc ...

y cuando presiona la acción "artesanal", puedes analizarla y compararla con su inventario / caja de manualidades ...

por lo tanto, su base de datos de Crafting tendrá solo 1 campo (o 2 si desea agregar una solicitud de LvL, aunque ya estará incluida en la receta).

PENSAMIENTOS ADICIONALES:
Dichos elementos se pueden almacenar en formato xml en la tabla ... lo que haría que sea mucho más fácil de analizar ...

3) Se puede aplicar un sistema XML similar a su sistema de misiones ... para implementar los requisitos de búsqueda de objetivos.


Actualizar:

A juzgar por los comentarios, parece que mucha gente tiene un problema con XML. Sé que es genial criticarlo ahora y tiene sus problemas, pero en este caso creo que funciona. Una de las otras razones por las que elegí es que hay un montón de bibliotecas para analizarlo, por lo que puede hacer la vida más fácil.

El otro concepto clave es que la información es realmente no relacional . Así que sí, puedes almacenar los datos en cualquier ejemplo en particular en varias tablas diferentes con muchas combinaciones, pero eso es un problema. Pero si te sigo dando ejemplos ligeramente diferentes, apuesto a que tendrías que modificar tu diseño ad infinitum. No creo que agregar tablas y modificar sentencias SQL complicadas sea muy divertido. Así que es un poco frustrante que el comentario de @ scheibk haya sido votado.

Publicación original:

Creo que el problema que podrías tener al almacenar información de misiones en la base de datos es que no es realmente relacional (es decir, no encaja fácilmente en una tabla). Esa podría ser la razón por la que tiene problemas para diseñar tablas para los datos.

Por otro lado, si pones tu información de búsqueda directamente en el código, eso significa que tendrás que editar el código y volver a compilar cada vez que quieras agregar una misión. Cojo.

Entonces, si yo fuera tú, podría considerar almacenar mi información de búsqueda en un archivo XML o algo similar. Sé que esa es la solución genérica para casi cualquier cosa, pero en este caso me parece correcto. XML está hecho realmente para almacenar datos jerárquicos y no relacionados, al igual que las cosas que necesita almacenar para su búsqueda.

Resumen: puede crear su propio esquema, crear su archivo XML y luego cargarlo en tiempo de ejecución de alguna manera (o incluso almacenar el XML en la base de datos).

Ejemplo XML:

<quests> <quest name="Return Ring to Mordor"> <characterReqs> <level>60</level> <finishedQuests> <quest name="Get Double Cheeseburger" /> <quest name="Go to Vegas for the Weekend" /> </finishedQuests> <skills> <skill name="nunchuks" /> <skill name="plundering" /> </skills> <items> <item name="genie''s lamp" /> <item name="noise cancelling headphones for robin williams'' voice /> </items> </characterReqs> <steps> <step number="1">Get to Mordor</step> <step number="2">Throw Ring into Lava</step> <step number="3">...</step> <step number="4">Profit</step> </steps> </quest> </quests>