v
Skip to content

Tienda y comercio ​

Una tienda en la que el jugador puede comprar: ve su oro y lo que hay a la venta, pulsa «Comprar», se le descuenta el oro y se le dice qué ha conseguido. Si no le llega el oro, se le dice eso. Un solo comportamiento lleva toda la tienda; cada botón solo le dice qué objeto es y qué precio tiene.


Lo que vas a construir ​

  • El oro en pantalla
  • Una página de tienda con un botón de Comprar por objeto: Poción (20 de oro) y Espada de hierro (50 de oro)
  • Una compra: el oro baja lo que cuesta, un aviso dice qué se ha comprado y se le dice a la IA
  • Oro insuficiente: «No te llega el oro: Espada de hierro cuesta 50.» No se quita nada
  • Lo comprado acaba en el inventario del jugador

Cómo funciona ​

El jugador pulsa "Comprar Espada de hierro"
  → El botón activa el comportamiento "Comprar" y le pasa item = Espada de hierro, price = 50
  → El comportamiento comprueba: ¿Gold ≥ {param.price}?
    → Sí: Gold menos {param.price}, aviso "Has comprado: Espada de hierro", y se le dice a la IA
    → No: el aviso de "Si no se cumplen las condiciones, decir", y no pasa nada más

{param.price} y {param.item} representan lo que haya pasado el botón. Por eso basta con un comportamiento para cualquier cantidad de objetos.


Paso a paso ​

Paso 1: Crea las variables ​

En la fila Puedes añadir, abajo en la carta, pulsa + Variable.

Gold ​

CampoValor
NombreGold
TipoNúmero
Valor inicial100
Rangode 0 a (vacío)
Reglas de comportamientoEl oro del jugador. La tienda descuenta sus precios sola. También puedes cambiarlo en la historia: recompensas de misiones, robos, un cofre del tesoro.

El mínimo de 0 es una red de seguridad: el comportamiento ya comprueba que el jugador puede pagarlo, pero con el rango puesto el oro nunca puede salir en negativo.

Pulsa Mostrar en la pantalla del jugador para que Gold se vea siempre en el chat.

Inventario ​

El inventario más fácil sale de Interfaz → Plantillas → Inventario: una página de mochila, una ventana emergente cuando llega algo nuevo y una variable de lista Inventario cuyas Reglas de comportamiento le dicen a la IA que añada objetos cuando la historia se los da al jugador. Mira la receta Inventario y equipo.


Paso 2: Crea un único comportamiento «Comprar» ​

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

ParteAjuste
Cuándo se disparaEl jugador pulsa un botón, Botón buy
SOLO SIGold ≥ {param.price}
EfectosCambiar variable: Gold menos {param.price}
Mostrar notificación: Has comprado: {param.item}, estilo Éxito
Decirle a la IA: El jugador acaba de comprar {param.item} por {param.price} de oro. Añádelo a su Inventario.
Si no se cumplen las condiciones, decirNo te llega el oro: {param.item} cuesta {param.price}.

Sin esa última línea, un jugador que no pudiera pagar algo pulsaría el botón y no vería que pasa nada.

Decirle a la IA le pasa a la IA una frase para su siguiente respuesta. Con las Reglas de comportamiento de la plantilla Inventario, la IA mete el objeto en la mochila y saca el aviso de «Has conseguido».

Que el objeto llegue al inventario sin fallos

Los efectos de un comportamiento pueden cambiar números y texto, pero no pueden añadir una fila a una lista. Aquí el objeto lo añade la IA, avisada por Decirle a la IA. Si necesitas que sea exacto:

  • Objetos contados como números: dale a las pociones su propia variable de Número y haz un comportamiento aparte, «Comprar poción», que además haga Cambiar variable Pociones más 1
  • Un efecto Código: añade Código a los efectos del comportamiento con una línea como ctx.push("Inventory", { name: "Potion", note: "Heals a little." }). Mira Comportamientos · Comportamientos con código
  • Código de interfaz: la ruta con código propio de más abajo escribe la lista ella misma

Paso 3: Monta la página de la tienda ​

Pulsa Interfaz en el centro de la barra superior. Añade una página con Nueva página (una Página en blanco) y llámala «Tienda».

  1. Añade una parte Texto que diga Oro: {Gold} (usa Insertar el valor de una variable…)
  2. Para cada objeto, añade una parte Texto con su nombre y su descripción, y un Botón con el texto Comprar · 20 de oro
  3. En Al pulsar, en orden del botón, añade Activar un comportamiento → Comprar, y luego + Pasar un valor dos veces: item = Poción y price = 20. Para la espada: Espada de hierro y 50
  4. Añade un botón con Ir a la página de vuelta a la conversación, y en la página de la conversación un botón «Tienda» que lleve a esta

Para mostrar qué objetos no se puede permitir el jugador, duplica un botón de Comprar, haz que la copia se vea en gris y usa Cuándo mostrar → Cuando una variable cumple: Gold es menor que 20 en el gris y Gold es al menos 20 en el normal. El gris también activa el comportamiento, así que al pulsarlo sale el aviso de que no llega el oro.

Desactiva Editar para recorrer la página. La vista previa no llama a la IA, pero verás cómo cambia el oro.

Precios que cambian

Un precio puede salir de una variable: en + Pasar un valor, escribe {{Precio de la poción}} en lugar de 20. Cambia la variable (con un comportamiento durante unas fiestas, por ejemplo) y todos los botones la siguen.


Paso 4: Pruébalo ​

Pulsa Jugar en la barra superior.

  1. Gold está en 100. Abre la Tienda
  2. Compra una poción: Gold 80, «Has comprado: Poción». Envía un mensaje; la IA lo menciona y la poción aparece en la mochila
  3. Compra otra: Gold 60
  4. Compra la espada: Gold 10
  5. Intenta comprar lo que sea: «No te llega el oro: Poción cuesta 20.» Gold se queda en 10

Este turno, a la derecha de la prueba, muestra si se disparó el comportamiento Comprar y, si no, por qué.

Si algo falla:

SíntomaCausa probableSolución
Pulsar Comprar no hace nadaEl Activar un comportamiento del botón apunta a otro sitio, o el comportamiento no está ActivadoRevisa las dos cosas
El oro no cambiaEl valor que se pasa tiene otro nombre que el {param.…} del comportamientoprice en el botón, {param.price} en el comportamiento, escrito igual
No sale ningún mensaje cuando falta oroSi no se cumplen las condiciones, decir está vacíoEscribe la frase
El oro se queda en negativoFalta la condición, o Gold no tiene mínimoDeja el SOLO SI y pon el Rango empezando en 0
El objeto nunca aparece en la mochilaLa IA no lo añadióDeja Decirle a la IA en el comportamiento y las Reglas de comportamiento de la variable Inventario, o usa una de las vías exactas de arriba

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

Esta versión dibuja la tienda en el código de la interfaz. Sigue usando el comportamiento Comprar para comprobar el oro, así que los precios y el mensaje de que no llega el oro siguen en el lienzo, y añade ella misma el objeto a una lista inventory cuando la compra sale bien. Da por hecho que hay una variable de Lista / tabla llamada inventory que empieza en [].

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 || [];

  const gold = Number(api.variables["Gold"] ?? 0);
  const inventory = Array.isArray(api.variables.inventory) ? api.variables.inventory : [];

  const shopItems = [
    { name: "Potion",     price: 20, icon: "🧪", desc: "Restores a little health" },
    { name: "Iron Sword", price: 50, icon: "⚔️", desc: "A plain iron sword" },
  ];

  const buy = async (item) => {
    // Run the "buy" behavior and wait for it; firedIds is empty if its
    // condition failed (it shows its own "not enough gold" notice)
    const result = await api.executeActionAndWait("buy", { item: item.name, price: item.price });
    if (result.firedIds.length > 0) {
      const current = Array.isArray(api.variables.inventory) ? api.variables.inventory : [];
      api.setVariable("inventory", [...current, item.name]);
    }
  };

  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: "16px",
              background: "rgba(15, 23, 42, 0.6)",
              borderRadius: "12px",
              border: "1px solid #334155",
            }}>
              {/* Gold */}
              <div style={{
                display: "flex", alignItems: "center", gap: "8px", marginBottom: "16px",
                padding: "10px 14px", background: "linear-gradient(135deg, #78350f, #92400e)",
                borderRadius: "8px", border: "1px solid #b45309",
              }}>
                <span style={{ fontSize: "20px" }}>💰</span>
                <span style={{ color: "#fde68a", fontSize: "16px", fontWeight: "bold" }}>{gold} Gold</span>
              </div>

              {/* Items for sale */}
              <div style={{ display: "flex", flexDirection: "column", gap: "8px", marginBottom: "16px" }}>
                {shopItems.map((item) => {
                  const affordable = gold >= item.price;
                  return (
                    <div key={item.name} style={{
                      display: "flex", alignItems: "center", justifyContent: "space-between",
                      padding: "10px 14px", background: "rgba(30, 41, 59, 0.8)",
                      borderRadius: "8px", border: "1px solid #475569",
                    }}>
                      <div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
                        <span style={{ fontSize: "22px" }}>{item.icon}</span>
                        <div>
                          <div style={{ color: "#e2e8f0", fontSize: "14px", fontWeight: "600" }}>{item.name}</div>
                          <div style={{ color: "#64748b", fontSize: "12px" }}>{item.desc}</div>
                        </div>
                      </div>
                      <button
                        onClick={() => buy(item)}
                        style={{
                          padding: "6px 16px", borderRadius: "6px", fontSize: "13px", fontWeight: "600", whiteSpace: "nowrap",
                          background: affordable ? "#047857" : "#4b5563",
                          border: "1px solid " + (affordable ? "#10b981" : "#6b7280"),
                          color: affordable ? "#a7f3d0" : "#9ca3af",
                          cursor: "pointer",
                          opacity: affordable ? 1 : 0.6,
                        }}
                      >
                        {item.price} Gold
                      </button>
                    </div>
                  );
                })}
              </div>

              {/* Inventory */}
              {inventory.length === 0 ? (
                <div style={{
                  padding: "20px", textAlign: "center", color: "#475569", fontSize: "13px",
                  background: "rgba(30, 41, 59, 0.4)", borderRadius: "8px", border: "1px dashed #334155",
                }}>
                  Inventory is empty
                </div>
              ) : (
                <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(80px, 1fr))", gap: "8px" }}>
                  {inventory.map((name, idx) => {
                    const def = shopItems.find((s) => s.name === String(name));
                    return (
                      <div key={idx} style={{
                        display: "flex", flexDirection: "column", alignItems: "center", gap: "4px",
                        padding: "10px 6px", background: "rgba(30, 41, 59, 0.8)",
                        borderRadius: "8px", border: "1px solid #475569",
                      }}>
                        <span style={{ fontSize: "24px" }}>{def ? def.icon : "📦"}</span>
                        <span style={{ color: "#cbd5e1", fontSize: "11px", textAlign: "center" }}>{String(name)}</span>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          )}
        </div>
      );
    }} />
  );
}

Qué hace el código:

  • api.executeActionAndWait("buy", { item, price }) activa el comportamiento Comprar con los mismos valores que pasaría un botón de la interfaz del jugador, y espera a que termine
  • result.firedIds enumera los comportamientos que se ejecutaron. Si está vacío, la condición no se cumplió: el comportamiento ya ha mostrado su aviso de que no llega el oro, y no se añade nada
  • api.setVariable("inventory", [...current, item.name]) añade el objeto a la lista
  • Los objetos que no se puede permitir salen en gris pero se pueden pulsar, para que al jugador le llegue el aviso
  • repeat(auto-fill, minmax(80px, 1fr)) mete en cada fila tantas casillas de inventario como quepan en el ancho

Si usas esta ruta, cambia la frase de Decirle a la IA del comportamiento por El jugador acaba de comprar {param.item} por {param.price} de oro. para que la IA no añada también el objeto.

El estado que aparece junto al archivo en Paneles → Código de frontend debería ser un OK verde.

¿No quieres escribir el código tú?

Pulsa Asistente IA arriba a la derecha del lienzo y describe la tienda que quieres.


Para ir más lejos ​

Más objetos ​

Añade un botón (o una línea en shopItems) con su propio objeto y su precio. El comportamiento no cambia.

Vender ​

Un segundo comportamiento, «Vender», con Botón sell, que haga Gold más {param.price} y Decirle a la IA El jugador ha vendido {param.item}. Quítalo de su Inventario.

Ganar oro ​

  • Cada N turnos (por ejemplo, 3): Cambiar variable Gold más 10
  • La IA dice una palabra clave ganas el combate, la recompensa es tuya: Gold más 25 (basta con cualquiera de las palabras clave)
  • La propia IA, con las Reglas de comportamiento de Gold, por el botín y las recompensas de la historia
  • Las recompensas de misiones del rastreador de misiones

Un tendero que regatea ​

Para un comerciante que contesta metido en su papel y a veces hace descuento, añade una IA por interfaz con un campo de Formato de respuesta para el precio, y llámala desde un botón con Llamar a una IA.


Referencia rápida ​

Lo que quieresCómo hacerlo
Llevar la cuenta del oroUna variable de Número con un mínimo de 0
Un solo comportamiento para toda la tiendaEl jugador pulsa un botón, con los valores leídos como {param.item} / {param.price}
Pasar el objeto y el precioPaso de botón Activar un comportamiento → + Pasar un valor
Comprobar que el jugador puede pagarloSOLO SI Gold ≥ {param.price}
Avisarle cuando no puedeSi no se cumplen las condiciones, decir
Confirmar la compraMostrar notificación, estilo Éxito
Meter el objeto en el inventarioDecirle a la IA + la plantilla Inventario, una variable de Número por objeto, un efecto Código o código de interfaz
Poner en gris lo que no se puede permitirDos versiones del botón con Cuándo mostrar
Ejecutar el mismo comportamiento desde códigoapi.executeActionAndWait("buy", { item, price })

Esta es la receta n.º 3

Un botón que le pasa valores a un único comportamiento sirve para todo lo que tenga precio o se elija de un menú: fabricar, entrenar, contratar. Mira Comportamientos · Pasar un valor desde un botón.