구버전 시트 인프라와 Beacon 시트 인프라 간의 차이점으로 인해, 기존의 모든 Mod 스크립트가 Beacon 시트에서 별다른 설정 없이 바로 작동하는 것은 아닙니다. 아래 참고 사항은 스크립트를 업데이트하여 Beacon 시트(예:&D 2024)에서 작동하도록 하는 데 도움이 될 것입니다. 또한 몇 가지 핵심 스크립트를 업데이트하여, 여러분의 게임에 바로 활용할 수 있는 예제와 스크립트를 마련해 두었습니다. 업데이트된 스크립트:
- 그룹 주도 활동
- TokenMod
- 단체 확인
- 상태 정보
대부분의 스크립트에서 2024 시트와의 호환성을 확보하려면 두 가지 변경 사항만 적용하면 됩니다. 바로 속성을 가져오고 설정하는 방법과, 롤 템플릿 및 채팅 메시지를 파싱하는 방법입니다. 이 문서는 두 가지 방법을 모두 단계별로 설명하고, 자주 발생하는 문제점도 다루고 있으므로, 스크립트를 수정하여 D&D 2014 시트와 D&D 2024 시트 모두에서 작동하도록 할 수 있습니다.
Beacon 계산 속성 및 user.* 사용자 정의 속성을 사용하려면 Mod Script 샌드박스 v1.5 (Campaign().sandboxVersion === "1.5")가 필요합니다. v1.5는 현재 기본 샌드박스입니다. getSheetItem 과 setSheetItem은 v1.0과 v1.5 모두에 존재합니다. v1.0에서는 구버전 속성 get/set 함수로 대체되므로, Beacon 시트가 없는 게임도 여전히 정상적으로 작동합니다. v1.5에서는 비콘(Beacon)의 계산 속성과 user.* 필드도 읽고 쓸 수 있습니다. Mod Script 샌드박스 v1.5 전용입니다. getComputed, setComputed 및 performAction ( Mod 스크립트: 함수 문서 참조).
게임의 샌드박스 드롭다운 메뉴에 여전히 ‘기본’과 ‘실험적’ 레이블이 표시된다면, 레이블 대신 Campaign().sandboxVersion을 사용하여 실행 중인 샌드박스를 확인하십시오. Beacon 계산 속성에는 “1.5”가 필요합니다.
get/set 업데이트
2014년 시트와 2024년 시트의 데이터 접근 방식에서 코드 측면의 주요 변경점은 속성을 가져오고 설정하는 방법입니다. 이제 getSheetItem 및 setSheetItem이라는 비동기 함수 세트가 있습니다. 새로운 함수 사용 예시는 다음과 같습니다:
const getDeathSaveSuccess = async (id) => {
const firstSuccess = await getSheetItem(characterId, "deathsave_succ1");
log(`첫 번째 성공은 ${firstSuccess}`);
}
속성의 최대값(최대값이 존재하는 경우)을 얻으려면, getSheetItem(characterId, "deathsave_succ1", "max");와 같이 max 속성을 전달하면 됩니다.
위의 코드에서 getDeathSaveSuccess가 async로 표시되어 있는 것을 확인하실 수 있습니다. getSheetItem을 사용하는 모든 함수는 이 async/await 패턴을 사용하거나 Promise를 사용해야 합니다. 다음은 동일한 함수를 프라미스로 재작성한 것입니다:
const getDeathSaveSuccess = (id) => {
getSheetItem(characterId, "deathsave_succ1").then((firstSuccess) => {
log(`첫 번째 성공은 ${firstSuccess}`);
});
}
한 번에 여러 개의 값을 가져오려고 하거나(또는 차례로 가져오려고 하거나) 나머지 코드가 해당 데이터에 의존하는 경우, 각 값을 개별적으로 await할 수도 있고, Promise.all을 사용하여 모든 프로미스를 한 번에 해결하고 최종 값을 얻을 수도 있습니다. 그렇지 않으면, 반환되는 값은 실제 속성 값이 아니라 보류 중인 Promise가 됩니다.
const getSuccesses = (id) => {
const promises = [];
promises.push(getSheetItem(characterId, "deathsave_succ1"));
promises.push(getSheetItem(characterId, "deathsave_succ2"));
promises.push(getSheetItem(characterId, "deathsave_succ3"));
Promise.all(promises).then((results) => {
log(`첫 번째 성공 결과는 ${results[0]}, 두 번째 성공 결과는 ${results[1]}, 세 번째 성공 결과는 ${results[2]}`);
});
}
비동기 코드는 코드의 구조에 따라 스크립트를 작성하는 방식에 여러 가지 영향을 미칠 수 있습니다. 예를 들어, 스크립트에서 현재 replace나 맵 내부에서 getAttrByName을 사용하고 있다면, 해당 함수들은 값이 반환될 때까지 기다리지 않고 바로 다음 단계로 진행하기 때문에, 이를 비동기 처리에 더 적합한 루프로 분할해야 합니다.
“여러 값을 한 번에 또는 차례로 가져오려고 하는데, 코드의 나머지 부분이 그 데이터에 의존하는 경우”로 다시 돌아가 보겠습니다. 코드의 나머지 부분은 항상 그 값에 의존하는 것은 아닙니다. getSheetItem을 사용하는 경우, 대부분은 그렇게 됩니다. 왜냐하면 가져온 속성을 이용해 무언가를 처리하려고 하기 때문이죠. 반대로, setSheetItem의 경우 작업이 완료될 때까지 기다릴 필요가 없는 경우가 많습니다. 그렇다면 비동기 처리와 관련된 부분은 무시하고 평소처럼 호출하면 됩니다. 스크립트가 계속 실행되는 동안 해당 속성은 백그라운드에서 업데이트됩니다.
setSheetItem 함수는 getSheetItem과 동일하게 작동하지만, 설정할 값을 지정하는 추가 인자가 있습니다:
setSheetItem(characterId, "HP", 10);
setSheetItem(characterId, "HP", 20, "max");
롤 구문 분석 업데이트
5e 스크립트 중 많은 수가 사용하는 기능 중 업데이트가 필요한 또 다른 부분은 주사위 굴림 결과 분석입니다. 채팅으로 전송된 롤은 형식이 다르기 때문에, 내용에 대한 결과나 세부 정보를 얻으려면 별도의 파싱 과정이 필요합니다. 개발팀은 HTML에 몇 가지 데이터 속성을 추가하여, 대량의 HTML 구문 분석이 필요한 상황을 줄였습니다. 더 복잡한 데이터가 필요한 경우, 채팅으로 전송된 메시지에서 해당 데이터를 파싱해야 할 수도 있습니다. 다음은 몇 가지 일반적인 요구 사항입니다.
표준 롤 템플릿에서 주사위 굴림 결과를 확인하려면:
const rollResultMatch = msg.content.match(/data-result="(.+?)"/);
제목을 보고 어떤 종류의 롤인지 확인하려면:
const deathSaveMatch = msgContent.match(/header__title">여기에 헤더를 입력하세요<\/div>/);
롤 자막을 확인하고 주문 레벨이나 피해 유형 등의 정보를 알아보려면:
const spellLevelMatch = msgContent.match(/header__subtitle">Level (.+?) /);
2024년용 시트는 아직 개발 중이므로, 롤 템플릿이 변경될 수 있으며 이에 따라 스크립트를 추가로 업데이트해야 할 수도 있습니다. HTML을 문자열로 파싱하는 방식이 앞으로도 계속 안정적으로 유지될 것이라고 보장할 수는 없지만, 시트가 발전함에 따라 더욱 표준화된 템플릿을 마련하기 위해 노력하고 있습니다. 간결함을 위해 위의 예시에서는 정규 표현식을 다소 엄격하게 설정했습니다. 템플릿이 아직 확정되지 않은 단계에서는 일치 조건을 더 유연하게 설정하고 와일드카드를 사용하여 일치 결과를 더욱 견고하게 만드는 것이 좋습니다.
흔히 발생하는 문제
오류: character_id(여기에 ID 입력)에 대한 (여기에 속성명 입력)이라는 속성 또는 시트 필드를 찾을 수 없습니다.
추정되는 원인: Mod Script 샌드박스 v1.5가 아닌 v1.0을 사용 중이며, Beacon의 계산 속성에 접근하려고 시도하고 있습니다. Campaign().sandboxVersion 이 "1.5"인지 확인하십시오. 샌드박스 드롭다운 메뉴에 여전히 ‘기본’과 ‘실험용’으로 표시되어 있다면, 해당 라벨이 최신 정보가 아닐 수 있습니다. 드롭다운 메뉴만 믿지 말고, 시스템을 재시작한 후 sandboxVersion (및 재시작 로그) 을 확인하십시오.
getSheetItem의 결과가 값 대신 빈 객체를 로깅하고 있습니다
가능한 원인: getSheetItem 함수에서 .then을 기다리지 않았거나 사용하지 않았기 때문일 가능성이 높습니다. 값이 반환되기 전까지는 코드를 진행할 수 없습니다.