> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/all-out-docs/docs-es/datos-y-persistencia/economy.md).

# Economy

* Cada divisa se almacena **por jugador**
* Los saldos se **persisten automáticamente** entre sesiones
* Los saldos se pueden ver/editar en el portal del creador (ver [Editar/ver datos del jugador](/all-out-docs/docs-es/datos-y-persistencia/editing-viewing-player-data.md))

### Referencia de la API de Economy

```go
Economy :: struct {
    register_currency     :: proc(currency: string, icon: Texture_Asset);
    deposit_currency      :: proc(player: Player, currency: string, amount: s64);
    get_balance           :: proc(player: Player, currency: string) -> s64;
    can_withdraw_currency :: proc(player: Player, currency: string, amount: s64) -> bool;
    withdraw_currency     :: proc(player: Player, currency: string, amount: s64);
    delete_save_data      :: proc(player: Player);
}
```

### Registro de una divisa (una sola vez)

Antes de usar un nombre de divisa, regístralo con un icono.

```go
ao_before_scene_load :: proc() {
    // Elige un icono de tu carpeta /res
    coin_icon := get_asset(Texture_Asset, "ui/coin.png");

    Economy.register_currency("Monedas", coin_icon);
    Economy.register_currency("XP", coin_icon); // ejemplo (idealmente usa un icono diferente)
}
```

{% hint style="info" %}
Los nombres de las divisas son solo cadenas. Elige un nombre coherente y manténlo siempre (por ejemplo `"Monedas"` vs `"monedas"`).
{% endhint %}

### Lectura del saldo de un jugador

```go
coins := Economy.get_balance(player, "Monedas");
```

### Otorgar divisas (recompensas)

Usa `deposit_currency` cada vez que un jugador gana divisas.

```go
on_enemy_killed :: proc(player: Player) {
    Economy.deposit_currency(player, "Monedas", 10);
    Economy.deposit_currency(player, "XP", 3);
}
```

### Gastar divisas (tiendas/mejoras)

Comprueba siempre `can_withdraw_currency` antes de retirar. Los importes de depósito y retirada deben ser no negativos.

```go
UPGRADE_COST :: 50;

try_buy_upgrade :: proc(player: Player) -> bool {
    if !Economy.can_withdraw_currency(player, "Monedas", UPGRADE_COST) {
        Notifier.notify(player, "¡No tienes suficientes monedas!");
        return false;
    }

    Economy.withdraw_currency(player, "Monedas", UPGRADE_COST);

    // Otorga la mejora aquí...
    Notifier.notify(player, "¡Mejora comprada!");
    return true;
}
```

## Tiendas integradas

Una tienda contiene categorías, y cada categoría contiene productos. Crea la tienda después de registrar sus divisas. Conserva sus manejadores en campos de toda la escena o en variables globales porque solo son válidos para la escena actual.

```go
shop: u64;

grant_shop_product :: proc(
    player: Player,
    product: u64,
    campo userdata: Object
) -> bool {
    if Game_Product.get_id(product) == "health_upgrade" {
        player.max_health += 10;
        return true;
    }

    // Devolver false cancela la compra y no cobra al jugador.
    return false;
}

ao_before_scene_load :: proc() {
    coin_icon := get_asset(Texture_Asset, "ui/coin.png");
    Economy.register_currency("Monedas", coin_icon);

    shop = Economy.create_shop("upgrade_shop");
    upgrades := Shop.add_category(shop, "Mejoras");

    Shop_Category.add_product(
        upgrades,
        "health_upgrade",
        "Mejora de salud",
        "Añade 10 puntos de salud máxima.",
        "ui/health_upgrade.png",
        "Monedas",
        50,
        "",
        Item_Rarity.COMMON.(s64),
        ""
    );

    Shop.set_purchase_handler(shop, null, grant_shop_product);
}
```

El controlador de compra debe otorgar el producto y devolver `true`. Si se devuelve `false` , se rechaza la compra.

Dibuja la tienda desde el código de la UI del jugador. `Shop.draw` devuelve `true` mientras la tienda permanezca abierta:

```go
Player :: class : Player_Base {
    max_health: int = 100;
    shop_open: bool;

    ao_late_update :: method(dt: float) {
        if !is_local_or_server() return;

        if shop_open {
            shop_open = Shop.draw(shop, UI.get_safe_screen_rect());
        }
    }
}
```

`Shop.set_purchase_modifier` puede cambiar el precio o el botón de un producto por jugador. `Shop.set_custom_display` puede reemplazar el dibujo de la tarjeta del producto. Ambas devoluciones de llamada usan el mismo patrón explícito `de userdata` que el controlador de compra.

### Restablecer los datos de economía de un jugador

Si necesitas borrar todos los saldos de economía de un jugador (por ejemplo, un botón de restablecimiento de administrador o un reinicio del modo de juego), puedes eliminar sus datos guardados de economía:

```go
reset_economy :: proc(player: Player) {
    Economy.delete_save_data(player);
    Notifier.notify(player, "Tus datos de economía se han restablecido.");
}
```

{% hint style="warning" %}
`Economy.delete_save_data` es destructivo. Úsalo con moderación y considera añadir confirmaciones o acceso solo para administradores.
{% endhint %}

### Economy frente a Save

* Usa **Economy** para "divisas" (monedas, gemas, XP, entradas) donde quieres persistencia automática + edición en el portal.
* Usa **Guardado** para todo lo demás (configuración, estado de misiones, listas de desbloqueos, estructuras de progreso complejas). Ver [Sistema de guardado](/all-out-docs/docs-es/datos-y-persistencia/save.md)
