스크립트 에디터
게임 스크립트를 편집하려면 해당 게임의 게임 세부 정보 페이지에서 "모드(API) 스크립트" 링크를 클릭하세요(이곳은 "채팅 기록" 및 "게임 복사/확장"과 같은 옵션이 있는 곳과 동일합니다). 여러 가지 기능이 제공됩니다:
- 상단에 위치한 탭 목록. 게임은 편리한 관리를 위해 여러 스크립트를 가질 수 있습니다. 모든 스크립트는 동일한 컨텍스트에서 실행된다는 점을 유의하십시오. 즉, 여러 스크립트가 동시에 동일한 값을 덮어쓰려고 시도해서는 안 되며, 그렇지 않으면 의도하지 않은 결과가 발생할 수 있습니다.
- 스크립트 코드 편집기. 이 편집기를 사용하거나 원하는 외부 편집기에서 스크립트를 편집한 후 여기에 붙여넣을 수 있습니다.
- 하단에 위치한 "Mod (API) 콘솔"(아래 참조).
"스크립트 저장" 버튼을 클릭할 때마다 게임의 샌드박스가재시작됩니다(상태객체나 Roll20 객체에 저장되지 않은 메모리 내 데이터는 모두 손실됩니다). 새 스크립트를 추가하거나, 스크립트를 삭제하거나, 스크립트를 활성화/비활성화하기 위해 토글할 때에도 동일하게 적용됩니다.
모드(API) 콘솔
Mod(API) 콘솔은 여러분의 스크립트를 들여다보는 "창"입니다. 모드(API) 스크립트는 샌드박스 환경에서 실행되므로, 스크립트 실행 중에는 스크립트의 결과나 오류 정보를 확인하기 위해 직접 접근할 수 없습니다. 모드(API) 콘솔은 이 정보를 샌드박스 외부에서 표시하므로 스크립트를 편집하는 동안에도 확인할 수 있습니다. 모든 log()명령어는 여기에 표시되며, 스크립트 실행 중 발생하는 모든 오류도 여기에 표시됩니다. 자세한 내용은 스크립트 디버깅에 관한 문서.
반응형 스크립트: 이벤트 수신, 객체 수정
모드(API) 사용의 첫 번째(그리고 가장 단순한 유형)는 테이블탑에서의 변화에 반응하고, 변경된 객체에 대해 추가 기능을 통해 응답하는 것입니다. 이 유형의 스크립트는 게임 진행 중 발생하는 이벤트를 감지하는 여러 함수로 구성됩니다. 그러면 해당 이벤트 중에 전달되는 객체를 수정하게 되며, 이는 테이블탑에서 일어나는 일을 변경할 것입니다.
기본 스크립트는 조각을 추가로 5피트(기본 페이지 설정 기준) 이동시키며, 다음과 같습니다:
on("change:graphic", function(obj) {
obj.set({
left: obj.get("left") + 70
});
});
보시다시피, change:graphic 이벤트가 감지될 때마다 실행될 간단한 on 함수를 생성했습니다. 함수는 그래픽 객체 obj를 인자로 받습니다. 변경을 하려면 set 함수를 사용해 obj를 수정하기만 하면 됩니다. 변경하는 속성은 무엇이든 테이블탑에서 감지되어 변경됩니다.
set및get메서드를 반드시 사용해야 합니다. 그렇지 않으면 변경 사항이 저장되지 않습니다. (아래에서 객체 유형과 그 속성 목록, 그리고 모든 이벤트 목록 및 각 이벤트에 전달되는 인자 목록을 확인할 수 있습니다.)유틸리티 함수에 관한 노트
물론, 이전 예시는 토큰의 위치에 항상 70픽셀을 더하기 때문에 그다지 유용하지 않습니다. 하지만 사용자가 스케일을 변경하여 5피트가 140픽셀이 되도록 설정했다면 어떻게 될까요? Roll20 API는 이러한(및 기타) 일반적인 시나리오를 지원하기 위한 여러 편리한 유틸리티 함수를 제공합니다. 이전 예제를 수정하여distanceToPixels 함수를 사용해 보겠습니다. 이 함수는 테이블탑 위에서 "5피트"(또는 인치, 미터, 기타 설정된 거리 단위)가 몇 픽셀에 해당하는지 알려줍니다.
on("change:graphic", function(obj) {
obj.set({
left: obj.get("left") + distanceToPixels(5);
});
});
현재 페이지가 기본 그리드 크기를 사용하도록 설정된 경우,distanceToPixels(5);는여전히 70픽셀을 반환하지만, 페이지가 일반 크기의 두 배로 확대되도록 설정된 경우 140을 반환합니다.
유틸리티 함수가 사용 가능한 경우 항상 이를 활용하는 것이 좋습니다. 이렇게 하면 페이지나 토큰의 설정이 변경되어도 스크립트가 깨지지 않도록 유지할 수 있습니다.
사전 실행 스크립트: 사용자 개입 없이 작업을 수행합니다
사용자 이벤트에 반응하는 것 외에도, 플레이어의 특정 이벤트와 연결되지 않은 작업을 API를 통해 자동으로 수행할 수 있습니다. 예를 들어, 맵 위를 앞뒤로 순찰하는 토큰을 생각해 보자.
참고: 이 유형의 스크립트는 사용자 상호작용에 의존하지 않지만, 게임의 모드(API) 스크립트는 최소한 한 명의 플레이어가 게임에 연결되어 있을 때만 실행됩니다.
on("ready", function() {
// 게임이 완전히 로드되었음을 알 수 있도록 ready 이벤트가 발생할 때까지 대기합니다.
//순찰 토큰에 대한 참조를 가져옵니다.
var patroltoken = findObjs({_type: "graphic", name: "Guard A"})[0]; // 게임 내에 "Guard A"라는 토큰이 존재함을 알고 있습니다.
var direction = -1 * distanceToPixels(5); // 왼쪽으로 70 픽셀 이동.
var stepstaken = 0; // 현재 방향으로 몇 걸음을 걸었는가?
setInterval(function() {
if(stepstaken > 3) {
//방향 전환!
direction = direction * -1; // 이동 방향을 반전시킵니다.
stepstaken = 0; // 걸음 수를 0으로 초기화합니다.
patroltoken.set("left", patroltoken.get("left") + direction); //걷기!
stepstaken++;
}, 5000); //5초마다 동작 수행
});
비동기 함수에 관한 논문
비동기 함수는 호출 범위로 제어권을 즉시 반환하고 백그라운드에서 특정 작업을 수행하는 함수입니다. 다음은 매우 간단하고 이해하기 쉬운 예시입니다. 이 코드를 모드(API) 스크립트 탭에 붙여넣을 수 있습니다:
on('load', function() {
log('부모 스코프 - 비동기 함수 호출 전.');
setTimeout(function() {
log('비동기 함수 스코프 - 비동기 함수 작업 수행 중.');
}, 10 /* 10 밀리초 */);
log('부모 스코프 - 비동기 함수 호출 후.');
});
모드(API) 로그에는 다음과 같은 내용이 표시됩니다:
부모 범위 - 비동기 함수 호출 전 부모 범위 - 비동기 함수 호출 후. 비동기 함수 범위 - 비동기 함수 작업 수행
그 코드를 보면 "당연히 나중에 실행되겠지, 10밀리초 후에 실행하라고 지시했잖아, 뻔한 거 아냐?"라고 생각하게 된다. 다음은 동일한 로그 메시지를 생성하는 덜 명백한 예시입니다:
on('load', function() {
log('부모 스코프 - 비동기 함수 호출 전.');
sendChat('비동기 함수','다음 표현식을 평가하세요: [[1d6]]',function(msg){
log('비동기 함수 범위 - 비동기 함수 작업 수행 중.');
});
log('부모 범위 - 비동기 함수 호출 후.');
비동기 함수는 API가 항상 멈추는 것을 방지하기 위해 필요합니다. 모든 주사위 굴림을 동기식으로 처리한다면, API는 매우 느리고 반응이 없을 것입니다. 콜백을 받는 거의 모든 함수는 비동기적입니다. 일부 _.map, _.reduce 등의 함수는 예외로, 이들은 대부분의 사람들이 익숙한 절차적 프로그래밍과 대비되는 함수형 프로그래밍의 예시입니다.