이번 내용은 조금 생소할 수 있지만, 이해만 하면 일정한 규칙에 따라 코드를 따라 쓰는 것이 전부입니다. 먼저, javascript로 무엇을 할 수 있길래, 우리가 왜 이것을 커스텀시트에 사용하는지에 대해 알아봅시다. 여기 자바스크립트를 사용하면 편리한 5가지 예시가 있지만, 그 외에도 많은 것을 자동으로 처리하게 할 수 있습니다.
1. 캐릭터의 스킬 이름만 적으면, 나머지 내용이 자동입력 되도록 미리 데이터 목록을 넣고 싶다.
2. 캐릭터의 일부 능력치를 바탕으로, 최대 HP등 변하지 않는 값을 자동으로 계산시키고 싶다.
3. 캐릭터의 특정 스테이터스 값이 바뀔 때마다, 다른 값을 어떤 계산식에 따라 자동으로 바뀌게 하고 싶다.
4. 특정 버튼을 누를 때마다, 캐릭터 시트의 값이 어떤 규칙을 가지고 증감하게 하고 싶다.
5. 시트를 열 때나 어떤 값이 바뀌었을 때, 그것을 채팅창에 출력해서 변동 전후를 기록하고 싶다.
즉, 어떤 상황이나 데이터의 변동을 감지하여 다른 값을 변화시키거나 채팅창에 출력하는 커스텀시트를 만들 수 있게 되는 것입니다. 잘 쓰면 여러모로 유용하겠죠? 그럼 이 js의 처리가 시작되는 트리거 이벤트에는 어떤 것들이 있는지 알아봅시다.
change:★★
js에 on("change:HP change:SAN") {내용}을 적는다면, HP나 SAN 중 무언가가 변동했을 때를 트리거로 하여 {내용} 안의 작업을 처리하게 됩니다.
sheet:opened
js에 on("sheet:opened") {내용}을 적는다면, 시트를 닫고 새로 열 때마다 {내용} 안의 작업을 처리하게 됩니다.
clicked:♥♥
html에 <button type="action" name="act_myattack">공격!</button>이라는 버튼이 있을 때, js에 on("clicked:myattack", function() {내용}을 적는다면 저 버튼이 눌려질 때마다 {내용} 안의 작업을 처리하게 됩니다.
이 3가지 기능이 자주 쓰이는 것이고, 커스텀시트 만들기⑪:무한히 만드는 fieldset에서 설명한 반복 구간에서만 사용 가능한 트리거 이벤트가 2가지 더 있습니다. 반복 구간에서는 +add 버튼과 mod 버튼을 통해 추가/수정을 할 수 있는데, 그 중에서도 mod 버튼을 눌러서 수정하는 경우에 대한 상황을 감지합니다. 우선 html에 <fieldset class="repeating_◇◇">스킬내용</fieldset>과 같은 형태의 코드가 있어야 합니다.
change:_reporder:◈◈
시트에서 mod버튼을 누른 뒤 그 안에 있는 여러 개의 항목들 사이의 순서를 드래그하여 바꿀 수 있습니다. js에 on("change:_reporder:◈◈", function(eventInfo) {내용});을 적는다면, fieldset의 class가 repeating_◈◈인 항목들 간의 순서가 재정렬되었을 때마다 {내용} 안의 작업을 처리하게 됩니다.
remove:repeating_◆◆
시트에서 mod버튼을 누른 뒤 그 안에 있는 여러 개의 항목들 중 어떤 것을 삭제하는 버튼을 눌렀을 때, js에 on("remove:repeating_◆◆", function(eventinfo) {내용});이 있었다면 각 항목이 삭제될 때마다 {내용} 안의 작업을 처리하게 됩니다. 아까 순서변경 때와 다르게, repeating_을 적어야 합니다.
마지막으로 한가지 더, sheet:compendium-drop이라는 기능이 있습니다. 저널에서 캐릭터를 드래그하여 토큰을 맵에 생성할 때를 트리거로 하는 것인데, 우리가 만들 커스텀시트의 대다수는 compendium을 사용할 수 없게 될 것이므로 자세히 설명하지 않겠습니다. 궁금하면 이쪽을 참고하세요.
여기까지 간단히 살펴보았고, 이제부터 조금 어려운 내용을 설명하겠습니다. 줄곧 작성해온 html에서는 쌓인 <태그>들을 순서대로 배치하고, 자식 요소를 내부에 포함해왔습니다. 그리고 css에서는 어떤 요소에 대한 서식을 지정한 뒤, 코드에 또 다시 그 요소에 대한 다른 서식을 지정할 경우 오래된 것을 무시했습니다. js에서는, 비동기 처리라는 특수한 방식이 있습니다. roll20의 일부 함수는 비동기적으로 작업을 수행하기 때문에, 조금 이해하고 넘어갈 필요가 있습니다.
단순히 글로 보아서는 무슨 말인지 이해하기 힘들지요. 컴퓨터가 정보를 처리하고 데이터를 전송하는 인터넷 속도는 아주 빠르기 때문에, 우리는 일반적으로 웹사이트에 들어갔을 때 내용이 로딩되는 순서를 눈으로 볼 일이 별로 없습니다. 하지만 여기, 그 속도가 아주 느리다고 가정하고 처리되는 순서를 2가지의 영상으로 비교해서 보여드리겠습니다.
이렇게 보면, 순서대로 나오는 것과 다함께 동시에 나오는 것의 차이일 뿐이라고 생각되지요? 하지만 이 처리 방식의 차이는 데이터를 받아오던 중 무언가 지체되거나 오류가 발생했을 때 큰 차이를 드러냅니다. 예를 들어, 그림1의 파일이 잘못되어 무한로딩을 일으킨다고 가정해보겠습니다.
동기식 처리의 경우, 그림1의 이전에 해당하는 문단B까지만 불러와지고 그 이후의 내용은 볼 수 없게 될 것입니다. 사용자는 이 문서가 여기까지가 끝이라고 생각하고, 그림1의 로딩을 기다리지 않고 나가버릴지도 모르지요. 반면 비동기식 처리의 경우, 사용자는 그림1을 제외한 다른 모든 것을 확인할 수 있을 것입니다.
단, roll20에서는 모든 js코드 중 점 하나만 잘못찍어도 모든 sheetworker가 동작하지 않습니다. 이것을 이해했든 이해하지 못했든, 이제부터는 따라서 코드를 작성하기만 하면 되니까 html 편집기의 맨 하단에 sheetworker를 입력해 봅시다. html은 태그를 순서대로 처리하므로, <script>가 <input type="number" name="attr_HP">보다 먼저 등장하면 HP값이 존재하지 않는다고 간주할 수도 있기 때문입니다.
<script type="text/worker">
</script>
sheetworker를 의미하는 이 두 줄의 html 태그 사이에, javascript를 작성합니다. 이번에는 저녁노을어스름의 캐릭터 작성을 위해, 8점의 분배치 중 잔여점수을 알려주는 것을 구현해보겠습니다. 먼저, 각 능력치를 적을 칸을 html의 >script<보다 위쪽에 만들어주세요.
요괴
동물
어른
아이
잔여점을 분배하세요.
잔여점을 분배하세요.
<span>요괴</span><input type="number" name="attr_monster">
<span>동물</span><input type="number" name="attr_animal">
<span>어른</span><input type="number" name="attr_adult">
<span>아이</span><input type="number" name="attr_child">
<br>
<span>잔여</span><input type="text" name="attr_remain"><span>점을 분배하세요.</span>
이 요괴·동물·어른·아이 중 어떤 수치가 늘어나면, 잔여점수가 8에서부터 그만큼 감소하게 하려고 합니다. 반대로, 배분한 점수를 다시 빼도 잔여점수가 늘어나도록 다시 계산하게 되겠지요. 이렇게 하기 위해서 사용할 것은 on("change:★★")입니다. 띄어쓰기로 구분해서, 여러 값 중 하나라도 그 값이 변하면 하위 작업을 수행합니다.
on("change:monster change:animal change:adult change:child", function() {
});
이 안에 무엇을 할 것인지 적어야 합니다. 앞서 말한대로, 요괴·동물·어른·아이 중 어떤 항목의 값을 가져와서 계산하려고 합니다. 그것을 위해 getAttrs라는 함수를 사용해서, 시트에 저장된 값을 javascript로 읽어들이고 여기서 부를 이름을 붙힙니다. function(values)라고 적는다면, values.HP라는 식으로 가져올 수 있습니다.
getAttrs(["monster", "animal", "adult", "child"], function(my) {
});
다시 또 이 안에, 가져온 값들을 바탕으로 계산한 최종 잔여점수를 마지막으로 어디에 저장할지 알려주면 끝납니다. 이번에는 setAttrs라는 함수를 사용해서, 저장할 곳의 input name에서 attr_을 제외한 나머지를 적고 콜론(:) 뒤에 그 값에 대해 설명합니다. 만약 우리가 아까 가져온 값이 input[type="text"]에 있는 숫자였다면, Number함수를 써서 숫자로 바꾼 다음 연산해야 합니다. 그렇지 않으면, 5+6이 글자결합으로 56이라는 결과를 도출합니다.
setAttrs({
total: 8-(my.monster+my.animal+my.adult+my.child)
});
이것으로, 여러분도 js를 이용한 간단한 자동계산식을 만들 수 있습니다. 침식률에 따라 상승하는 다이스 값은 if 함수를, 스킬이름에 따른 세부데이터는 switch 함수를 사용하면 쉽게 입력할 수 있습니다. 반복 구간에서 추가된 아이템들의 무게 합계 등은 복잡하기 때문에, roll20위키에 별도의 문서가 존재하니 https://wiki.roll20.net/RepeatingSum 참고하시기 바랍니다.
댓글 없음:
댓글 쓰기
본문과 관련이 적은 댓글은 삭제될 수 있습니다.