# Mods de jogabilidade

> Um esquema não precisa ser uma IA que joga por você; também pode ser um conjunto de regras: você mesmo joga na janela do jogo, e o mod prepara o início, gera inimigos, dá recompensas, põe botões e cartões de escolha na tela e decide o resultado. Herde de openwar3.Mod: um arquivo é uma jogabilidade inteira.

Fonte: https://war3ai.com/pt/docs/mods/

Os [esquemas de IA](https://war3ai.com/pt/docs/schemes/) são de dois tipos: `kind: bot` é uma IA que joga por você; `kind: mod` é **um conjunto de regras** — você mesmo joga na janela do jogo, e o mod cria os desafios: como a partida começa, quando gerar inimigos (por tempo ou por evento), que recompensas dar, que botões e cartões de escolha pôr na tela, quando a vitória acontece.

Um mod usa só recursos que já existem: [Interface e entrada](https://war3ai.com/pt/docs/ui-input/) (botões e cartões clicáveis, teclas de atalho, cliques no chão), o [canvas](https://war3ai.com/pt/docs/canvas/) (painéis, barras de progresso, rotas), o [canal JASS](https://war3ai.com/pt/docs/jass/) (criar unidades, mudar atributos, dar itens) e o fluxo de eventos (mortes, subidas de nível, feitiços lançados, chat).

## Dois exemplos

Dá para escolher no Farsight, em “Esquemas de IA” → “Embutidos”:

| Mod | Como se joga | Recursos usados |
|---|---|---|
| **Roguelike de Heróis** `builtin/hero-roguelike` | Você só tem um paladino, e ondas de monstros vêm de todos os lados; a cada nível, escolha um de três reforços no meio da tela (o jogo pausa durante a escolha); sobreviva a 10 ondas para vencer; se o herói morrer, você perde | `g.ui.choice` (cartões clicáveis + pausa), eventos `hero.levelup` / `killed` / `spell.cast`, `-help` no chat, JASS para mudar atributos do herói e dar itens |
| **Defesa Infinita** `builtin/endless-defense` | Os monstros saem do ponto de início oposto e correm pela linha vermelha no chão até a sua base; cada onda contida rende ouro; clique no botão na tela ou aperte F7 para chamar a próxima onda antes, com recompensa ×1.5; aperte F8 e clique com o botão esquerdo no chão para pôr uma torre de flechas grátis (botão direito cancela) | `g.ui.button`, `g.ui.hotkey`, `g.ui.mouse` (captura de cliques no chão), painel / barra de progresso / rota do canvas, JASS para gerar monstros e dar ouro |

Cada exemplo tem cerca de 150 linhas; o código está em `brains/examples/mod_hero_roguelike.py` e `brains/examples/mod_endless_defense.py`.

```bash
python tools/play.py --bot brains/examples/mod_hero_roguelike.py --inst 9     # inicia uma partida, o mod assume, e você joga na janela do jogo
```

## Escreva um mod

```python
from openwar3 import Mod

class Survive(Mod):
    name = "survive"

    def on_start(self, g):
        super().on_start(g)                        # verificação de partida solo + neutraliza o computador adversário
        self.foe = self.wave_player(g)             # um slot vazio vira o "jogador das ondas": sem aliança com ninguém, sem IA do computador
        self.every(30, self.wave)                  # uma onda a cada 30 s de jogo (não corre durante a pausa)
        g.ui.hotkey("F7", lambda g, ev: self.wave(g))

    def wave(self, g):
        self.spawn_ring(g, self.foe, "ugho", 6, self.home(g), 1400, attack_to=self.home(g))

    def on_event(self, g, ev):
        if ev.kind == "unit.died" and ev.type == "htow":
            self.finish("loss", "A prefeitura caiu")
```

Em relação a `Bot`, `Mod` acrescenta:

| Método / atributo | Descrição |
|---|---|
| `on_start / on_tick / on_event / on_end` | Iguais aos do Bot; ao sobrescrever `on_start` / `on_tick`, chame `super()` primeiro |
| `every(segundos, fn, first=)` / `after(segundos, fn)` | Timers que correm pelo **tempo de jogo**; o callback é `fn(g)` |
| `finish(result, reason)` | Encerra a partida (`'win'` / `'loss'` / `'unknown'`): o executor para no tick seguinte, um painel de resultado é desenhado no meio da tela, e os resultados do esquema são registrados com base nisso |
| `wave_player(g)` | O primeiro slot de jogador vazio, para usar como jogador das ondas |
| `spawn_ring(g, jogador, unidade, quantidade, centro, raio, attack_to=)` | Gera unidades num círculo, sem travar mesmo com dezenas por onda; retorna os handles JASS |
| `alive_of(g, jogador)` / `attack_move_all(g, jogador, ponto)` | As unidades vivas de um jogador / manda todas em ataque-movimento até lá (chame a cada poucos segundos para os monstros irem atrás) |
| `home(g)` / `hud(g, título, linhas)` | A posição da nossa base / o painel de informações no canto superior direito |
| `neutralize_ai = True` | Neutraliza o computador adversário no início: as unidades dele são pausadas a cada 5 segundos, e o ouro e a madeira dele são zerados. Mapas de confronto sempre têm um computador, e quando o mod define as próprias regras, ele só atrapalha |
| `single_player_only = True` | Se houver outros jogadores humanos, recusa-se a rodar (o JASS que altera o mundo tiraria os outros de sincronia) |
| `linger_s = 6` | Depois de decidido o resultado, quantos segundos esperar na tela de resultado antes de encerrar |

`finish()` também funciona em `Bot`: um Bot comum também pode declarar o fim da partida por conta própria.

## Transformar em esquema e compartilhar

Escreva `"kind": "mod"` no `scheme.json` e defina uma subclasse de `Mod` no arquivo de entrada:

```json
{"id": "survive", "name": "Aguente 10 ondas", "kind": "mod", "entry": "survive.py", "class": "Survive"}
```

Um mod **nunca usa o modo justo** (ele é o árbitro que cria os desafios, precisa ver o mapa inteiro e alterar o mundo) e **não tem o resultado decidido pelas regras de confronto** (quem informa o resultado é `finish`); `fair` / `judge` no manifesto não têm efeito. Exportar zip, importar, confiar e os resultados funcionam exatamente como nos esquemas de Bot; veja [Esquemas de IA](https://war3ai.com/pt/docs/schemes/). Um mod também é código: o mod de outra pessoa também exige confirmar a confiança antes da primeira execução.

## Medições

2026-09-25, numa instância de teste:

- **Roguelike de Heróis**: a primeira onda aparece, e o painel no canto superior direito se atualiza; levar o herói ao nível 3 → cartões aparecem no meio da tela, e o relógio do jogo para; dois cliques em cartões → dois reforços aplicados (força 22 → 27), e o relógio volta a correr.
- **Defesa Infinita**: painel, rota no chão e botão aparecem; F8 + clique no chão → surge uma torre de defesa ao lado da base; clicar no botão antes de limpar a onda atual → aparece o aviso “esta onda ainda não foi limpa”.

## Limites

- **Só partidas solo**: criar unidades e mudar atributos passam pelo canal JASS e, em partidas multijogador, causam dessincronização. Isso decorre do modelo lockstep; jogabilidade multijogador depende de um canal de sincronização (veja o [roadmap](https://war3ai.com/pt/roadmap/)).
- O mod vê o mapa inteiro — ele cria os desafios, não é um jogador.
- O computador adversário nos mapas de confronto só é “neutralizado”, não removido (removê-lo acionaria a vitória pelas regras de confronto).
