Canal JASS
Las 1291 funciones JASS que tienen los autores de mapas ahora se pueden llamar por su nombre desde fuera del juego: crear unidades, cambiar atributos, efectos, paneles, cuadros de diálogo, sonido, cámara, niebla… Cuatro formas de uso: consola Farsight, línea de comandos, HTTP y Python.
Las 1291 natives de JASS que los autores de mapas pueden usar en el script del mapa ahora se pueden llamar todas por su nombre desde fuera del juego: crear unidades, cambiar atributos, dibujar efectos, abrir paneles y cuadros de diálogo, reproducir sonidos, mover la cámara, cambiar la niebla… Sirven para personalizar el juego un paso más: ayudas para RPG, el compañero IA, minijuegos propios, herramientas de depuración.
| Forma | Ideal para | Por dónde se entra |
|---|---|---|
| Página “Consola JASS” de Farsight | Probar a mano, ajustando mientras miras | Barra lateral izquierda “Sistema → Consola JASS”: escribe un script y pulsa ejecutar; a la derecha buscas funciones por categoría y con un clic las insertas en el script |
| Línea de comandos | Probar a mano, o guardar scripts en archivos y ejecutarlos una y otra vez | python -m openwar3 jass --inst 20 (interactivo), -e "código", my_script.j, --list palabra_clave |
| HTTP | Programas externos en cualquier lenguaje | POST /api/instances/{n}/jass, etc. (ver más abajo); el backend de Farsight solo escucha en local |
| Python | Escribir esquemas, compañeros o herramientas | g.jass.CualquierNative(...); los efectos visuales y las interacciones habituales están empaquetados en openwar3.visual |
Tres límites, todos impuestos por el propio mecanismo:
- Solo las partidas de un jugador (contra el ordenador, en tu equipo) pueden cambiar el mundo. Crear objetos o modificar unidades de forma unilateral desde tu equipo desincronizaría a los demás jugadores en multijugador, así que ahí solo se permiten funciones de solo lectura (
Get*,Is*,Count*…). - Solo para las herramientas de tu propio equipo; las llamadas desde una conexión como jugador (
Game(player=N)) o en modo justo se rechazan. - Solo para partidas sin conexión o en LAN creadas por ti.
Para añadir cosas a la imagen en multijugador, usa el lienzo: lo dibuja el propio runtime y no cambia el estado del juego.
Cómo escribir scripts
La consola, la línea de comandos y HTTP usan el mismo lenguaje de script. Una sentencia por línea; puedes pegar JASS tal cual (call / set / local, true / false / null, códigos de cuatro caracteres como 'Hpal', comentarios //), o escribirlo al estilo de Python:
set h = hero() // integrada: nuestro héroe principal
local texttag t = CreateTextTag()
call SetTextTagText(t, "|cffffcc00+128 ¡Crítico!|r", 0.024)
call SetTextTagPosUnit(t, h, 60)
call SetTextTagVelocity(t, 0, 0.03)
call SetTextTagPermanent(t, false)
call SetTextTagLifespan(t, 4)
call SetTextTagVisibility(t, true)
call PingMinimapEx(h.x, h.y + 300, 3, 255, 0, 0, false)
set u = CreateUnit(Player(0), 'hfoo', h.x + 200, h.y, 270)
print("Creada", u, "nivel del héroe", GetHeroLevel(h))
- Las variables se recuerdan: en la misma instancia y la misma partida, las variables que un fragmento asigna con
setse pueden usar en el siguiente; se borran solas al cambiar de partida, y también se pueden borrar a mano. - Funciones integradas:
hero()nuestro héroe principal,me()el jugador local,unit('hfoo')busca una unidad,unit_at(x, y),wait(segundos),print(...). De una unidad se pueden leer.x,.y,.hp,.hp_max,.mana,.type,.ownery.level; se admiten las cuatro operaciones aritméticas y las comparaciones. - No se admiten
if,loopnifunction: para escribir lógica, usag.jassdesde Python (son llamadas a funciones normales) o conviértelo en un esquema. - Si hay un error, te dice en qué línea y por qué (no existe esa función, número de parámetros incorrecto, variable no definida…); las sentencias anteriores al error ya se han aplicado.
Parámetros y valores de retorno:
| En la firma | Qué pasar | Notas |
|---|---|---|
| Entero | Un número; los códigos de cuatro caracteres como 'Hpal' se convierten solos | |
| Real | Un número | El runtime lo convierte al formato que espera el motor |
| Booleano | true / false | |
| Cadena | "..." | Admite chino y los códigos de color del juego; las que el juego guarda (texto flotante, paneles, botones, comandos de chat) se copian en el momento, así que es seguro |
| Handle | Un handle guardado en una variable, o una unidad (cosas como hero() se convierten solas en handle) | |
| Función (code) | Solo null | Desde fuera no se puede pasar una función JASS; algo como TimerStart(t, 60, false, null) sí funciona |
| Devuelve cadena | — | El motor devuelve un índice de la tabla de cadenas y el texto no se puede leer. Para nombres de unidades, usa g.map_data.name_of |
Categorías
Las funciones están clasificadas por su nombre; la parte derecha de la consola y --list usan esta clasificación:
| Categoría | Cantidad | Ejemplos |
|---|---|---|
| Efectos visuales | 80 | Texto flotante, rayos entre unidades, efectos, imágenes en el suelo, marcas en el suelo, color / escala / animaciones de unidades |
| Paneles de interfaz | 146 | Paneles multilínea, tabla de clasificación, ventana de cuenta atrás, cuadros de diálogo, misiones, texto en pantalla, avisos en el minimapa, diálogo con retrato, filtros de pantalla completa |
| Cámara | 44 | Campos de cámara, desplazamiento, temblor de cámara |
| Sonido y música | 50 | Crear y reproducir sonidos, poner música |
| Niebla y visión | 25 | Zonas visibles, activar / desactivar la niebla |
| Objetos / héroes / unidades | 63 / 32 / 161 | Crear objetos, fijar el nivel de un héroe, cambiar de dueño, añadir habilidades |
| Jugadores / alianzas / recursos | 71 | Fijar alianzas, cambiar el oro y la madera |
| Disparadores / eventos / temporizadores | 62 | Crear disparadores, registrar eventos, temporizadores |
| Terreno / clima / destructibles | 45 | Efectos de clima, modificar el terreno, crear destructibles |
| Flujo de la partida | 57 | Velocidad de juego, pausa, hora del día |
| Otros | … | Grupos de unidades y regiones, almacenamiento, scripts de IA del ordenador, conversión de tipos y matemáticas, respuestas a eventos… |
El 24 de septiembre de 2026 se llamaron una a una en partida real, comprobando el efecto a simple vista, 94; el resto siguen exactamente el mismo camino, solo que no se ha revisado su efecto una por una.
Las funciones de “respuesta a eventos” (GetTriggerUnit, GetClickedButton…) solo tienen valor en el instante en que se ejecuta el disparador; llamadas desde fuera devuelven 0 o vacío. Para saber “si ha ocurrido algo”, usa los contadores de eventos que se explican más abajo.
HTTP
Backend de Farsight (por defecto 127.0.0.1:8866, solo escucha en local):
GET /api/jass/natives?q=TextTag&cat=visual
POST /api/instances/20/jass {"code": "set h = hero()\ncall PingMinimapEx(h.x, h.y, 3, 255, 0, 0, false)"}
-> {"ok": true, "rows": [...], "printed": [...], "vars": {...}}
-> si hay error: {"ok": false, "error": "第 2 行:...", "line": 2} (error = "línea 2: ...")
POST /api/instances/20/jass/call {"name": "SetUnitScale", "args": [{"unit": 599669636}, 1.4, 1.4, 1.4]}
POST /api/instances/20/jass/reset borra las variables recordadas
Los parámetros de unidad se escriben {"unit": dirección}, donde la dirección es el addr de la unidad en la instantánea. Medido: 60 ~ 90 ms por petición.
Python: g.jass y openwar3.visual
j = g.jass
t = j.CreateTextTag()
j.SetTextTagText(t, "Hola", 0.024) # mismas reglas de parámetros que en los scripts; las unidades y objetos de la instantánea se pasan tal cual
j.signature("CreateImage") # consultar la firma
openwar3.visual.Visual(g) empaqueta los efectos visuales habituales ya probados, una línea para cada uno (llama a v.tick() en cada tick: borra lo que ha caducado y mueve las líneas y los círculos que siguen a unidades; v.clear() lo borra todo):
| Método | Efecto |
|---|---|
float_text(texto, unidad_o_punto, ...) | Texto flotante: números de daño, avisos sobre la cabeza; admite chino y colores |
link(a, b, kind) | Una línea entre dos unidades que las sigue: correa / vínculo espiritual / drenaje de vida / ola de curación |
effect(modelo, unidad_o_punto, ...) | Modelo de efecto: sobre la cabeza, a los pies, o de una sola vez (explosión, columna de luz) |
ring(unidad_o_punto, radio, color) | Círculo de alcance en el suelo: alcance de una habilidad, zona peligrosa, punto de reunión; puede seguir a una unidad |
ping(punto, color) | Aviso en el minimapa |
board(título, líneas...) | Panel multilínea arriba a la derecha (con iconos); se puede modificar celda a celda |
countdown(título, segundos) | Ventana de cuenta atrás arriba a la derecha; el propio juego lleva la cuenta |
scene(nombre, frase, portrait) | Diálogo con retrato: el retrato de abajo cambia a una unidad que habla y aparece en pantalla el subtítulo “nombre: frase” |
screen_tint(color, alpha) | Filtro de pantalla completa (por defecto, bordes rojizos: aviso de poca vida) |
sound(ruta) / reveal(punto, radio, segundos) / look(unidad, ...) | Reproducir un sonido / despejar la niebla de una zona / cambiar el color de una unidad, agrandarla, reproducir una animación, hacerla destellar |
Interacción: saber qué hace el jugador sin escribir funciones JASS
En JASS, para responder al jugador hay que escribir funciones de disparador, y desde fuera no se pueden pasar funciones. La solución: crear un disparador vacío, sin condiciones ni acciones, registrar solo el evento y contar cuántas veces se ejecuta. Medido: un disparador vacío cuenta igual.
| Método | Uso |
|---|---|
chat_commands(["-follow", "-stay"]) → .poll() | Comandos que el jugador escribe en el chat (coincidencia exacta o por prefijo) |
menu(título, [botones...]) → .clicked() | Menú de botones en el centro de la pantalla: cuál se ha pulsado |
hotkeys(("left", "right", "up", "down", "esc")) → .poll() | Cuántas veces se han pulsado las flechas y Esc |
on("TriggerRegister...Event", args...) → .poll() | Cuántas veces ha ocurrido cualquier evento JASS: muerte de una unidad, entrada en una región, daño recibido, temporizadores… |
La limitación es que solo sabes “cuántas veces ha ocurrido”, no “quién ha sido ni qué ha escrito”. Para distinguir quién, crea un contador para cada objeto. Así es como se conectan los comandos de chat del compañero IA.
Precauciones
- Lo que crees, bórralo tú: texto flotante, líneas, imágenes, paneles, disparadores… si no los borras, se quedan ahí (
Visual.clear()borra lo que ha creado él). El juego admite como mucho unos 100 textos flotantes a la vez. - Las funciones BJ no son natives: las del tipo
CreateTextTagUnitBJestán montadas con natives dentro del script del mapa y aquí no existen; mira su implementación y llama directamente a las natives. - Algunas constantes hay que convertirlas antes: por ejemplo,
ConvertPlayerColor(1),ConvertFogState(4)(los valores están en common.j). - Una llamada tarda unos 13 ms (incluida la conversión de handles); en la capa del protocolo son los códigos de operación 70 ~ 72 de W3P; ver Protocolo W3P.