> 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/conceptos-centrales-del-motor/social-features.md).

# Funciones sociales

All Out ofrece chat de texto y chat de voz opcional para que los uses en tus juegos

### Lectura del chat

Usa `core_globals.server_on_chat_message_received` cuando el código del juego necesita reaccionar a mensajes normales de chat en el servidor:

```go
ao_before_scene_load :: proc() {
    core_globals.server_on_chat_message_received = on_chat_message;
}

on_chat_message :: proc(player: Player, message: string) {
    log_info("% dijo %", {player.get_username(), message});
}
```

### Referencia de la API de chat

```go
Chat :: struct {
    Mode :: enum {
        DEFAULT;
        BUBBLE_ONLY;
    }

    set_mode :: proc(mode: Mode);
    server_send_message :: proc(message: string, player: Player = null);
    is_open :: proc() -> bool;
}
```

`Chat.server_send_message` es para código del lado del servidor, como controladores de comandos de chat. Pasa `jugador` para dirigirlo a un jugador, o déjalo `null` para enviarlo ampliamente. Usa `Chat.set_mode(.BUBBLE_ONLY)` en el cliente local para juegos que quieran chat en burbujas sin el panel de chat estándar.

### Comandos de chat

Los comandos de chat son principalmente una **herramienta de desarrollador/admin** para pruebas y operaciones en vivo:

* Iniciar rondas antes / omitir oleadas
* Otorgar conjuntos de objetos de prueba o moneda
* Activar eventos del juego para depuración

Para crear un comando, escribe una `proc` y анota la función con `@chat_command`.

El nombre del procedimiento es el nombre del comando: `start_round` se invoca como `/start_round`. La invocación ignora los espacios en blanco alrededor y prefiere un nombre con el mismo uso de mayúsculas y minúsculas exacto; luego recurre a una coincidencia sin distinguir mayúsculas y minúsculas.

Los jugadores pueden escribir comandos en el chat con una `/`:

* `/start_round`
* `/grant_test_loadout`
* `/trigger_event meteor_shower`

{% hint style="info" %}
Los comandos de chat se ejecutan en el servidor. Usa `Notifier.notify(player, "...")` para enviar una respuesta a un solo jugador.
{% endhint %}

{% hint style="warning" %}
No todos los jugadores tendrán el chat de texto habilitado (los controles parentales y los silencios de moderación pueden desactivar el cuadro de texto), así que no deberías depender de los comandos de chat para sistemas críticos de juego.
{% endhint %}

#### Comandos comunes de desarrollo/admin

```go
// Iniciar una ronda antes de tiempo (solo admin)
start_round :: proc(player: Player) {
    g_round_manager.start_round();
    Notifier.notify(player, "Ronda iniciada.");
} @chat_command

// Otorgarte un conjunto de prueba (solo admin)
grant_test_loadout :: proc(player: Player) {
    // Ejemplo: usa aquí tu propia lógica para otorgar objetos
    // item := Items.create_item_instance(sword_defn);
    // Items.move_item_to_inventory(item, player.default_inventory);
    Notifier.notify(player, "Conjunto de prueba otorgado.");
} @chat_command

// Activar un evento por nombre (solo admin, con un argumento opcional)
trigger_event :: proc(player: Player, event_name: string = "meteor_shower") {
    g_event_system.trigger(event_name);
    Notifier.notify(player, "Evento activado: %", {event_name});
} @chat_command
```

#### Permisos

Usa anotaciones de permisos para controlar quién puede ejecutar un comando:

| Anotación          | Quién puede usarlo                                |
| ------------------ | ------------------------------------------------- |
| `@any`             | Todos los jugadores                               |
| `@vip`             | Jugadores VIP y administradores                   |
| `@youtuber`        | Jugadores y administradores youtubers             |
| `@owner`           | Propietario del juego y administradores           |
| `@owner_or_editor` | Propietario del juego, editores y administradores |
| (ninguno)          | Solo administradores                              |

```go
// Los VIP y administradores pueden usar esto
skip_wave :: proc(player: Player) {
    g_wave_manager.skip_to_next_wave();
    Notifier.notify(player, "Oleada omitida.");
} @chat_command @vip
```

{% hint style="info" %}
Al iniciar desde el editor, los comandos de chat están permitidos para una iteración/pruebas más rápidas.
{% endhint %}

#### Argumentos y parámetros opcionales

El primer parámetro siempre debe ser `Player`. Después de eso puedes agregar argumentos (y darles valores predeterminados para hacerlos opcionales).

De forma predeterminada, los comandos son **solo administradores**.

Los tipos de argumento admitidos son `string`, tipos enteros, tipos de coma flotante, `bool`y `Player`.

Un `Player` el argumento usa el token completo delimitado por espacios o entre comillas y coincide exactamente con el nombre visible del jugador. Los nombres que contienen dígitos o guiones bajos funcionan directamente; pon entre comillas los nombres que contienen espacios.

```go
// Solo administradores (predeterminado)
give_currency :: proc(player: Player, amount: s64 = 100) {
    if amount < 0 {
        Notifier.notify(player, "La cantidad debe ser cero o mayor.");
        return;
    }

    Economy.deposit_currency(player, "Coins", amount);
    Notifier.notify(player, "Te di % monedas.", {amount});
} @chat_command
```

Los administradores pueden usar:

* `/give_currency` → otorga 100 monedas
* `/give_currency 500` → otorga 500 monedas

#### Cadenas con espacios

Pon las cadenas entre comillas si contienen espacios:

```go
say :: proc(player: Player, message: string) {
    // Tu propia función de difusión/mensaje del juego aquí
    log_info("% dice: %", {player.get_username(), message});
} @chat_command @any
```

Ejemplo:

```
/say "¡Hola a todos!"
```

#### Obtener el uso de un comando

Los jugadores pueden añadir `?` a un comando para ver la información de los parámetros:

```
/spawn_enemy?
```

### Activación del chat de voz

Los jugadores controlan el chat de voz a través de la configuración de su cuenta y dispositivo. Los juegos no pueden forzarlo ni eludir los permisos del micrófono, los controles parentales o las restricciones de moderación.

La voz es posicional. El alcance audible predeterminado es de 10 unidades del mundo:

```go
Voice :: struct {
    set_range :: proc(range: float);
    get_range :: proc() -> float;
}
```

Establece un alcance positivo durante el inicio de la escena:

```go
ao_start :: proc() {
    Voice.set_range(14);
}
```

`Voice.set_range` cambia el alcance de toda la escena. Los valores no positivos se ignoran.

### Canales de comunicación

Cada jugador tiene máscaras de habla y escucha que se aplican tanto al chat de voz como al de texto. Dos jugadores pueden comunicarse cuando la máscara de habla del emisor se superpone con la máscara de escucha del receptor.

```go
TEAM_RED  :: 1.(u64) << 0;
TEAM_BLUE :: 1.(u64) << 1;

put_on_red_team :: proc(player: Player) {
    player.comms_channel_speak_mask = TEAM_RED;
    player.comms_channel_listen_mask = TEAM_RED;
}
```

Los jugadores escuchan y hablan en todos los canales por defecto.

### Moderación

All Out supervisa automáticamente el chat de texto y de voz para detectar comportamientos que infrinjan nuestras [normas de la comunidad](https://help.allout.game/hc/en-us/articles/27854798873243-Code-Of-Conduct) y desactivará las funciones sociales en las primeras infracciones o aplicará suspensiones a los infractores reincidentes.

Si ves comportamiento malo repetido o comportamiento que haya eludido nuestra detección automática, por favor repórtalo usando el sistema de denuncias del juego o desde su perfil.

Si un jugador ha sido suspendido por accidente, por favor indícale que [se ponga en contacto con nosotros](https://help.allout.game/) para revertir la acción.
