JASS 채널
맵 제작자가 쓸 수 있는 JASS 함수 1291개를 이제 게임 밖에서 이름으로 바로 호출할 수 있습니다. 유닛 생성, 속성 변경, 특수 효과, 패널, 대화 상자, 사운드, 카메라, 전장의 안개…… Farsight 콘솔, 명령줄, HTTP, Python 네 가지 방법으로 쓸 수 있습니다.
맵 제작자가 맵 스크립트에서 쓸 수 있는 JASS native 1291개를 이제 모두 게임 밖에서 이름으로 바로 호출할 수 있습니다. 유닛 생성, 속성 변경, 특수 효과 그리기, 패널과 대화 상자 띄우기, 사운드 재생, 카메라 이동, 안개 변경…… 게임을 한층 더 커스터마이즈하는 데 쓰세요 — RPG 보조, AI 동료, 직접 만든 미니 게임, 디버깅 도구.
| 사용법 | 적합한 경우 | 진입점 |
|---|---|---|
| Farsight “JASS 콘솔” 페이지 | 직접 시험해 보기, 보면서 고치기 | 왼쪽 사이드바 “시스템 → JASS 콘솔”: 스크립트를 쓰고 실행을 누름. 오른쪽에서 분류별로 함수를 찾고, 클릭하면 스크립트에 삽입 |
| 명령줄 | 직접 시험해 보기, 또는 스크립트 파일로 만들어 반복 실행 | python -m openwar3 jass --inst 20(대화형), -e "코드", my_script.j, --list 키워드 |
| HTTP | 어떤 언어로 만든 외부 프로그램이든 | POST /api/instances/{n}/jass 등(아래 참고). Farsight 백엔드는 로컬에서만 수신 대기 |
| Python | 스킴, 동료, 도구 작성 | g.jass.함수이름(...). 자주 쓰는 화면·상호작용 기능은 openwar3.visual에 묶여 있음 |
경계는 세 가지이며, 모두 메커니즘상 정해진 것입니다.
- 싱글플레이 게임(이 컴퓨터에서 컴퓨터 상대)에서만 월드를 바꿀 수 있습니다. 이 컴퓨터가 일방적으로 오브젝트를 만들거나 유닛을 바꾸면 멀티플레이 게임에서 다른 플레이어와 동기화가 깨집니다 — 멀티플레이 게임에서는 읽기 전용 함수(
Get*,Is*,Count*……)만 허용합니다. - 이 컴퓨터의 자체 도구 전용입니다. 플레이어 신분으로 연결(
Game(player=N))했거나 공정 모드에서 호출하면 거부됩니다. - 싱글플레이 또는 LAN에서 직접 만든 게임에서만 사용하세요.
멀티플레이 게임에서 화면에 무언가를 더하려면 캔버스를 쓰세요. 런타임이 직접 그리며 게임 상태를 바꾸지 않습니다.
스크립트 작성법
콘솔, 명령줄, HTTP는 같은 스크립트를 씁니다. 한 줄에 한 문장이며, JASS를 그대로 붙여 넣을 수도 있고(call / set / local, true / false / null, 'Hpal' 4자 코드, // 주석) Python 식으로 쓸 수도 있습니다.
set h = hero() // 내장: 아군 주 영웅
local texttag t = CreateTextTag()
call SetTextTagText(t, "|cffffcc00+128 치명타!|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("생성함", u, "영웅 레벨", GetHeroLevel(h))
- 변수는 계속 기억됩니다: 같은 인스턴스, 같은 게임 안에서는 이번 블록에서
set한 변수를 다음 블록에서 이어서 쓸 수 있습니다. 게임이 바뀌면 자동으로 비워지며, 수동으로 비울 수도 있습니다. - 내장 함수:
hero()아군 주 영웅,me()로컬 플레이어,unit('hfoo')유닛 하나 찾기,unit_at(x, y),wait(초),print(...). 유닛에서는.x,.y,.hp,.hp_max,.mana,.type,.owner,.level을 읽을 수 있고, 사칙연산과 비교를 지원합니다. if,loop,function은 지원하지 않습니다 — 로직을 쓰려면 Python의g.jass(평범한 함수 호출입니다)를 쓰거나 스킴으로 만드세요.- 오류가 나면 몇 번째 줄에서 왜 났는지 알려 줍니다(그런 함수가 없음, 인자 개수가 틀림, 정의되지 않은 변수……). 오류 이전의 문장은 이미 적용되어 있습니다.
인자와 반환값:
| 시그니처 | 전달할 값 | 설명 |
|---|---|---|
| 정수 | 숫자. 'Hpal' 4자 코드는 자동 변환 | |
| 실수 | 숫자 | 런타임이 엔진이 요구하는 형식으로 변환 |
| 불리언 | true / false | |
| 문자열 | "..." | 중국어 등 비ASCII 문자와 게임 색상 코드 지원. 게임이 보관하는 문자열(떠다니는 텍스트, 패널, 버튼, 채팅 명령)은 모두 그 자리에서 복사해 두므로 안전 |
| 핸들 | 변수에 담긴 핸들, 또는 유닛(hero() 같은 것은 자동으로 핸들로 변환) | |
| 함수(code) | null만 가능 | 밖에서는 JASS 함수를 넘길 수 없음. TimerStart(t, 60, false, null) 같은 것은 가능 |
| 문자열 반환 | — | 엔진이 반환하는 것은 문자열 테이블 번호라서 텍스트를 읽어 올 수 없음. 유닛 이름은 g.map_data.name_of 사용 |
분류
함수는 이름으로 분류되어 있으며, 콘솔 오른쪽과 --list 모두 이 분류를 따릅니다.
| 분류 | 개수 | 예 |
|---|---|---|
| 화면 효과 | 80 | 떠다니는 텍스트, 번개 연결선, 특수 효과, 지면 이미지, 지면 표식, 유닛 색 변경 / 크기 조절 / 애니메이션 재생 |
| UI 패널 | 146 | 멀티보드, 리더보드, 타이머 창, 대화 상자, 퀘스트, 화면 텍스트, 미니맵 핑, 초상화 대사, 전체 화면 필터 |
| 카메라 | 44 | 카메라 필드, 팬 이동, 카메라 흔들기 |
| 사운드·음악 | 50 | 사운드 생성과 재생, 음악 재생 |
| 안개·시야 | 25 | 가시 영역, 안개 켜기/끄기 |
| 아이템 / 영웅 / 유닛 | 63 / 32 / 161 | 아이템 생성, 영웅 레벨 설정, 소유자 변경, 스킬 추가 |
| 플레이어 / 동맹 / 자원 | 71 | 동맹 설정, 금·목재 변경 |
| 트리거 / 이벤트 / 타이머 | 62 | 트리거 생성, 이벤트 등록, 타이머 |
| 지형 / 날씨 / 파괴 가능 오브젝트 | 45 | 날씨 효과, 지형 변경, 파괴 가능 오브젝트 생성 |
| 게임 진행 | 57 | 게임 속도, 일시정지, 낮밤 시각 |
| 기타 | …… | 유닛 그룹과 영역, 저장소, 컴퓨터 AI 스크립트, 형 변환과 수학, 이벤트 응답…… |
2026-09-24에 하나씩 실제 게임에서 호출해 효과를 눈으로 확인한 것은 94개입니다. 나머지도 같은 경로를 거치지만, 하나하나 효과를 확인하지는 않았습니다.
“이벤트 응답” 계열 함수(GetTriggerUnit, GetClickedButton……)는 트리거가 실행되는 그 순간에만 값이 있어서, 밖에서 호출하면 0이나 빈 값을 받습니다. “일어났는지 여부”를 알고 싶다면 아래의 이벤트 카운트를 쓰세요.
HTTP
Farsight 백엔드(기본 127.0.0.1:8866, 로컬에서만 수신 대기):
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": {...}}
-> 오류: {"ok": false, "error": "第 2 行:...", "line": 2} ("第 2 行" = 2번째 줄)
POST /api/instances/20/jass/call {"name": "SetUnitScale", "args": [{"unit": 599669636}, 1.4, 1.4, 1.4]}
POST /api/instances/20/jass/reset 기억된 변수 지우기
유닛 인자는 {"unit": 주소}로 쓰며, 주소는 스냅샷에 있는 유닛의 addr입니다. 실측 요청 1회에 60 ~ 90 ms.
Python: g.jass와 openwar3.visual
j = g.jass
t = j.CreateTextTag()
j.SetTextTagText(t, "안녕", 0.024) # 인자 규칙은 스크립트와 같음. 스냅샷의 유닛, 아이템 객체를 그대로 넘겨도 됨
j.signature("CreateImage") # 시그니처 조회
openwar3.visual.Visual(g)는 실측으로 확인한 자주 쓰는 화면 효과를 한 줄에 하나씩 쓸 수 있게 묶어 둔 것입니다(틱마다 v.tick()을 한 번 호출하면 만료된 것은 지우고, 유닛을 따라가는 선과 원은 옮겨 줌. v.clear()는 전부 삭제).
| 메서드 | 효과 |
|---|---|
float_text(텍스트, 유닛 또는 지점, ...) | 떠다니는 텍스트: 피해 숫자, 머리 위 알림. 비ASCII 문자와 색상 모두 가능 |
link(a, b, kind) | 두 유닛 사이의 선, 유닛을 따라감: 견인 / 영혼 연결 / 생명력 흡수 / 치유의 물결 |
effect(모델, 유닛 또는 지점, ...) | 특수 효과 모델: 머리 위, 발밑, 또는 한 번 재생(폭발, 빛기둥) |
ring(유닛 또는 지점, 반지름, color) | 지면의 범위 원: 스킬 범위, 위험 지역, 집결 지점. 유닛을 따라가게 할 수 있음 |
ping(지점, color) | 미니맵 핑 |
board(제목, 줄...) | 오른쪽 위 멀티보드(아이콘 포함). 칸 단위로 수정 가능 |
countdown(제목, 초) | 오른쪽 위 타이머 창. 게임이 알아서 초를 셈 |
scene(이름, 대사, portrait) | 초상화 대사: 하단 초상화가 말하는 유닛으로 바뀌고, 화면에 “이름: 대사” 자막이 나옴 |
screen_tint(color, alpha) | 전체 화면 필터(기본값은 가장자리가 붉게 물듦: 체력 경고) |
sound(경로) / reveal(지점, 반지름, 초) / look(유닛, ...) | 사운드 재생 / 안개 일부 걷기 / 유닛 색 변경, 확대, 애니메이션 재생, 번쩍임 |
상호작용: JASS 함수를 쓰지 않고도 플레이어가 한 일 알아내기
JASS에서 플레이어에게 반응하려면 트리거 함수를 써야 하는데, 밖에서는 함수를 넘겨줄 수 없습니다. 해법은 이렇습니다. 조건도 동작도 없는 빈 트리거를 만들어 이벤트만 등록하고, 그 트리거가 몇 번 실행됐는지 셉니다. 실측 결과 빈 트리거도 실행 횟수가 그대로 집계됩니다.
| 메서드 | 용도 |
|---|---|
chat_commands(["-follow", "-stay"]) → .poll() | 플레이어가 채팅창에 입력한 명령(정확히 일치, 또는 앞부분 일치) |
menu(제목, [버튼...]) → .clicked() | 화면 가운데 버튼 메뉴에서 어느 것을 눌렀는지 |
hotkeys(("left", "right", "up", "down", "esc")) → .poll() | 방향키, Esc가 몇 번 눌렸는지 |
on("TriggerRegister...Event", 인자...) → .poll() | 임의의 JASS 이벤트가 몇 번 발생했는지: 유닛 사망, 영역 진입, 피해, 타이머…… |
한계는 “몇 번 일어났는지”만 알 뿐 “누가, 무슨 글자를 입력했는지”는 모른다는 것입니다. 누구인지 구분하려면 대상마다 카운터를 따로 만드세요. AI 동료의 채팅 명령도 이렇게 연결했습니다.
주의
- 만든 것은 직접 지워야 합니다: 떠다니는 텍스트, 연결선, 이미지, 패널, 트리거…… 지우지 않으면 계속 남습니다(
Visual.clear()는 자신이 만든 것을 지웁니다). 게임에는 떠다니는 텍스트를 동시에 최대 약 100개까지 둘 수 있습니다. - BJ 함수는 native가 아닙니다:
CreateTextTagUnitBJ같은 함수는 맵 스크립트에서 native를 조합해 만든 것이라 여기에는 없습니다 — 그 구현을 보고 native를 호출하세요. - 어떤 상수는 먼저 변환해야 합니다: 예를 들어
ConvertPlayerColor(1),ConvertFogState(4)(값은 common.j 참고). - 호출 1회에 약 13 ms(핸들 변환 포함). 프로토콜 계층은 W3P 연산 코드 70 ~ 72이며, W3P 프로토콜을 참고하세요.