v
Skip to content

Sistema de logros ​

Cuando el jugador alcanza un hito (más de 100 de oro, más de 5 combates ganados, encontrar una zona oculta), aparece una tarjeta con el nombre del logro y una frase. Cada logro se desbloquea una sola vez, se guarda en una lista, y una página de la interfaz del jugador muestra cuáles ha encontrado y cuáles siguen bloqueados. Todo se puede montar sin código.


Lo que vas a construir ​

  • Una tarjeta que aparece en cuanto se alcanza un hito: con un título, una frase y, si quieres, una imagen
  • Detección automática: los comportamientos vigilan los números y la conversación, así que el jugador no tiene que hacer nada
  • Cada logro se desbloquea una vez: un momento que ya está en su lista no vuelve a salir
  • Una página de logros: aparecen todos; los desbloqueados muestran su texto y los bloqueados, una pista
  • Opcional: logros que siguen desbloqueados aunque se empiece una partida nueva

Cómo funciona ​

El oro del jugador pasa de 95 a 101
  → El comportamiento "Big Spender" vigila Oro (Una variable cruza un umbral, Sube por encima de 100)
  → Su efecto "Desbloquear un momento" muestra la tarjeta "Big Spender"
  → El título "Big Spender" se añade a la variable de lista Achievements
  → La página de logros muestra Big Spender como desbloqueado

La IA mueve los números según avanza la historia, pero quien decide si un logro se desbloquea es el motor, así que un logro no puede olvidarse ni darse dos veces.


Paso a paso ​

Paso 1: Crea las variables ​

En la fila Puedes añadir, abajo en la carta, pulsa + Variable para cada una de estas.

Oro ​

CampoValor
NombreOro
TipoNúmero
Valor inicial0
Rangode 0 a (déjalo vacío)
Reglas de comportamientoEl oro del jugador. Sube cuando le pagan, saquea algo o vende algo; baja cuando gasta.

Combates ganados ​

CampoValor
NombreCombates ganados
TipoNúmero
Valor inicial0
Reglas de comportamientoCuántos combates ha ganado el jugador. Suma 1 cada vez que el jugador gane claramente una pelea.

Achievements ​

CampoValor
NombreAchievements
TipoLista / tabla
Valor inicial[]

Abre Qué hace la IA con ella y pon Acceso de la IA en Solo motor (oculta para la IA). En esta lista solo escriben los comportamientos, y a la IA no le sirve de nada leerla.

Logros que sobreviven a una partida nueva

En esa misma sección, marca Se conserva entre partidas (para cada jugador). Así, cuando un jugador vuelve a empezar, la lista arranca con lo que ya había desbloqueado y esos logros no vuelven a salir. Así funcionan las galerías de ilustraciones y las colecciones de finales.


Paso 2: Crea un comportamiento por logro ​

En la fila Puedes añadir, pulsa + Comportamiento.

Comportamiento 1: Big Spender ​

ParteAjuste
Cuándo se disparaUna variable cruza un umbral: Oro, Sube por encima de, 100
EfectosDesbloquear un momento

Rellena el momento:

CampoValor
TítuloBig Spender
MensajeHas ahorrado más de 100 de oro.
Imagen (enlace)opcional: un enlace https:// o un recurso de Paneles → Recursos
Se guarda en (una lista)Achievements

«Una variable cruza un umbral» se dispara solo en el momento en que el número pasa de 100 o menos a más de 100. Si el oro sigue subiendo de 101 a 150, no se dispara nada. Si el oro baja de 100 y vuelve a subir, se dispararía otra vez, pero el momento ya está en Achievements y no sale nada.

Comportamiento 2: Seasoned Fighter ​

ParteAjuste
Cuándo se disparaUna variable cruza un umbral: Combates ganados, Sube por encima de, 5
EfectosDesbloquear un momento: Título Seasoned Fighter, Mensaje Has ganado más de 5 combates., Se guarda en Achievements

Comportamiento 3: Trailblazer (palabra clave) ​

Este vigila la conversación en lugar de un número. Un comportamiento tiene un solo disparador, así que para pillar tanto lo que dice el jugador como lo que dice la IA, haz dos comportamientos.

3a

ParteAjuste
Cuándo se disparaEl jugador dice una palabra clave: explorar, registrar la cueva
EfectosDesbloquear un momento: Título Trailblazer, Mensaje Fuiste a buscar lo que estaba escondido., Se guarda en Achievements

3b

ParteAjuste
Cuándo se disparaLa IA dice una palabra clave: pasadizo oculto, sala secreta
Efectosel mismo Desbloquear un momento que en 3a, con el mismo título

Las palabras clave se separan con comas, y basta con una cualquiera. Los dos comportamientos guardan en la misma lista con el mismo título, así que el que se dispare primero desbloquea el logro, y el otro se lo encuentra ya ahí y no hace nada. No te hacen falta condiciones de más para esto.

¿Momentos o una notificación?

Mostrar notificación (con el estilo Éxito) también sirve para un aviso de una línea tipo «Logro desbloqueado», pero no recuerda nada: necesitarías un Interruptor por logro, una condición para que no se dispare dos veces y Máx. activaciones en 1. Desbloquear un momento ya se encarga de recordar.


Paso 3: Monta la página de logros ​

Pulsa Interfaz en el centro de la barra superior. Añade una página con Nueva página (una Página en blanco sirve), ponle un título y añade una parte Lista desde Añadir una parte:

  1. En Las filas vienen de, elige Filas que escribo y añade una fila por logro: Big Spender, Seasoned Fighter, Trailblazer, cada una con una frase
  2. Activa Dibujar cada fila como tarjeta
  3. En Bloqueada hasta, activa Mostrar las filas bloqueadas. Pon Vigilar esta variable en Achievements y deja Comparar con este campo de la fila en title. Una fila se desbloquea cuando la lista contiene su título, que es justo lo que mete ahí Desbloquear un momento
  4. En Texto mientras está bloqueada, escribe la pista que ve el jugador antes de desbloquearla, como «Ahorra un poco»
  5. Añade un Botón con Ir a la página de vuelta a la conversación, para que la página no sea un callejón sin salida (si no, la columna de páginas avisa con Sin salida)
  6. En la página de la conversación, añade un Botón con el texto «Logros» cuyo paso sea Ir a la página → tu página nueva

Si los coleccionables los reparte la IA en la historia y no los comportamientos, parte mejor de la plantilla Colección: «Lo que hay que encontrar empieza en gris y se ilumina cuando la historia te lo da.» Trae su propia variable de lista, una ventana emergente y unas Reglas de comportamiento que le dicen a la IA cuándo añadir cosas.

Desactiva Editar arriba para recorrer la página como lo haría un jugador.

Cuéntalos

Añade una variable de Número llamada «Logros desbloqueados» y dale la Fórmula (se calcula sola) len(Achievements). Pon {Logros desbloqueados} / 3 en una parte de Texto de la página y la cuenta se mantiene al día sola.


Paso 4: Pruébalo ​

Pulsa Jugar en la barra superior.

  1. Pulsa Logros: los tres están bloqueados y muestran su pista
  2. Juega hasta que tu oro pase de 100. Sale la tarjeta «Big Spender» y la página lo muestra desbloqueado
  3. Gana seis combates. «Seasoned Fighter» sale cuando Combates ganados pasa de 5 a 6
  4. Envía «Quiero explorar esta cueva». Sale «Trailblazer». Más tarde la IA menciona un pasadizo oculto y no vuelve a salir nada

Este turno, a la derecha de la prueba, te dice qué comportamientos se dispararon y por qué alguno no lo hizo.

Si algo falla:

SíntomaCausa probableSolución
El oro pasa de 100 pero no ha salido nadaEl oro nunca cruzó la línea: empezó por encima de 100El umbral solo se dispara al cruzarlo. Comprueba que el Valor inicial esté en el umbral o por debajo
Salió el momento pero la página no cambióSe guarda en (una lista) está vacío, o la página vigila otra variableElige Achievements en los dos sitios
La página lo muestra bloqueado aunque salióEl título de la fila no coincide exactamente con el del momentoDéjalos idénticos, mayúsculas incluidas
Un logro salió dos vecesLos dos comportamientos usan títulos distintos o listas distintasMismo título, misma lista

Ruta con código propio: un panel de logros debajo del chat ​

Si prefieres dibujar el panel tú, por ejemplo debajo del último mensaje en lugar de en una página aparte, escríbelo en el código de la interfaz. Los comportamientos de arriba se quedan tal cual; el código solo lee la lista Achievements.

Paneles → Código de frontend → abre index.tsx y sustituye el return <Chat /> que viene por defecto:

tsx
export default function MyWorld() {
  const api = useYumina();
  const msgs = api.messages || [];

  // Titles must match the moment titles in your behaviors
  const achievements = [
    { title: "Big Spender", desc: "Save more than 100 gold", icon: "💰" },
    { title: "Seasoned Fighter", desc: "Win more than 5 battles", icon: "⚔️" },
    { title: "Trailblazer", desc: "Find a hidden area or secret", icon: "🗺️" },
  ];

  // The list the moments are collected into, read by its name
  const unlockedList = Array.isArray(api.variables["Achievements"])
    ? api.variables["Achievements"].map(String)
    : [];
  const isUnlocked = (a) => unlockedList.includes(a.title);
  const unlockedCount = achievements.filter(isUnlocked).length;

  return (
    <Chat renderBubble={(msg) => {
      const isLastMsg = msg.messageIndex === msgs.length - 1;
      return (
        <div>
          <div
            style={{ color: "#e2e8f0", lineHeight: 1.7 }}
            dangerouslySetInnerHTML={{ __html: msg.contentHtml }}
          />

          {isLastMsg && (
            <div style={{
              marginTop: "16px",
              padding: "12px 16px",
              background: "linear-gradient(135deg, #1c1917, #292524)",
              border: "1px solid #44403c",
              borderRadius: "10px",
            }}>
              <div style={{
                display: "flex",
                justifyContent: "space-between",
                alignItems: "center",
                marginBottom: "10px",
              }}>
                <span style={{ fontSize: "13px", fontWeight: "bold", color: "#fbbf24" }}>
                  🏆 Achievements
                </span>
                <span style={{ fontSize: "12px", color: "#a8a29e" }}>
                  {unlockedCount} / {achievements.length}
                </span>
              </div>

              <div style={{ display: "flex", flexDirection: "column", gap: "6px" }}>
                {achievements.map((a) => {
                  const unlocked = isUnlocked(a);
                  return (
                    <div
                      key={a.title}
                      style={{
                        display: "flex",
                        alignItems: "center",
                        gap: "10px",
                        padding: "6px 8px",
                        borderRadius: "6px",
                        background: unlocked
                          ? "rgba(251, 191, 36, 0.08)"
                          : "rgba(120, 113, 108, 0.08)",
                      }}
                    >
                      <span style={{ fontSize: "18px", opacity: unlocked ? 1 : 0.3 }}>
                        {unlocked ? a.icon : "🔒"}
                      </span>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{
                          fontSize: "13px",
                          fontWeight: "600",
                          color: unlocked ? "#fbbf24" : "#78716c",
                        }}>
                          {a.title}
                        </div>
                        <div style={{
                          fontSize: "11px",
                          color: unlocked ? "#a8a29e" : "#57534e",
                          marginTop: "1px",
                        }}>
                          {a.desc}
                        </div>
                      </div>
                      {unlocked && (
                        <span style={{ fontSize: "11px", color: "#fbbf24" }}>✓ Unlocked</span>
                      )}
                    </div>
                  );
                })}
              </div>
            </div>
          )}
        </div>
      );
    }} />
  );
}

Qué hace el código:

  • <Chat renderBubble={...} /> conserva la lista de mensajes, el cuadro de texto y el desplazamiento de la plataforma; tú solo dibujas cada burbuja
  • msg.messageIndex === msgs.length - 1 pone el panel solo debajo del último mensaje
  • msg.contentHtml es el mensaje ya convertido en HTML
  • api.variables["Achievements"] lee la lista por el nombre de la variable. Los nombres con espacios o mayúsculas funcionan con los corchetes
  • Un logro cuenta como desbloqueado cuando su título está en la lista, la misma regla que usa el momento

El estado que aparece junto al archivo en Paneles → Código de frontend debería ser un OK verde. Si pone Error, el mensaje de debajo te dice en qué línea.

¿No quieres escribir el código tú?

Pulsa Asistente IA arriba a la derecha del lienzo y describe el panel que quieres. Te escribe el código de la interfaz.


«Una variable cruza un umbral» o «Una variable cambia» ​

Los dos disparadores vigilan variables, pero se disparan en momentos distintos.

Una variable cruza un umbral se dispara en el momento en que un número cruza una línea:

gold: 80 → 95 → 101   ← fires on 95→101 (crossed above 100)
gold: 101 → 150 → 200  ← doesn't fire (already above)
gold: 200 → 50 → 120   ← fires on 50→120 (crossed above 100 again)

Úsalo para hitos, avisos («la salud ha bajado de 20») y comprobaciones de muerte.

Una variable cambia se dispara cada vez que cambia la variable que elijas, tenga el valor que tenga:

gold: 80 → 95   ← fires
gold: 95 → 101  ← fires
gold: 101 → 150 ← fires

Para que sirva de algo necesita una condición en SOLO SI («solo si Oro ≥ 100»), y vuelve a comprobarla con cada cambio. En un logro, lo que te importa es el cruce, así que lo natural es Una variable cruza un umbral.


Más logros ​

Cada logro nuevo es un comportamiento más una fila en la página de logros:

LogroCuándo se dispara
ParlanchínCada N turnos: 50, con Máx. activaciones en 1
AcaparadorUna variable cruza un umbral: Oro sube por encima de 500
Alma socialLa IA dice una palabra clave: confía en ti, os hacéis amigos
De vuelta del abismoUna variable cruza un umbral: con Salud bajando por debajo de 10 se pone en verdadero un Interruptor «Casi muerto»; un segundo comportamiento, con Salud subiendo por encima de 50 y SOLO SI Casi muerto es verdadero, desbloquea el momento

Referencia rápida ​

Lo que quieresCómo hacerlo
Desbloquear cuando un número llega a una metaCuándo se dispara: Una variable cruza un umbral, Sube por encima de
Desbloquear cuando se dice algoEl jugador dice una palabra clave o La IA dice una palabra clave
Mostrar una tarjeta y recordarlaEfecto: Desbloquear un momento, con Se guarda en (una lista)
Que solo se desbloquee una vezMismo título, misma lista. El momento no sale si su título ya está en la lista
Conservar los logros en partidas nuevasMarca Se conserva entre partidas (para cada jugador) en la variable de lista
Mostrar logros encontrados y bloqueadosInterfaz → plantilla Colección, o una parte Lista con Bloqueada hasta
ContarlosUna variable de Número con la fórmula len(Achievements)
Un panel a medidaCódigo de interfaz que lea la lista (la ruta con código propio de arriba)

Esta es la receta n.º 13

Los logros se combinan con las demás recetas: cuenta las victorias de un sistema de combate, vigila el oro de la tienda o desbloquea uno al completar una misión. Los comportamientos no se estorban entre sí, así que añadir logros no cambia cómo funciona el resto de la carta.