Last active
September 8, 2020 18:32
-
-
Save stephaned68/6cda403867a49619c2a9864d7e7b9223 to your computer and use it in GitHub Desktop.
A Roll20 API script to convert the page and the lighting settings of all NPC tokens from imperial to metric system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Syntax: !metric | |
* This script loops through all tokens in the current page | |
* Any token attached to a character has its lighting properties converted from feet to meters | |
* The page settings are also converted to using 'm' instead of 'ft' | |
* This script must be run by the GM of the campaign | |
* @version : 1.0.0 | |
*/ | |
on('chat:message', function (msg) { | |
const [cmd, ...args] = msg.content.split(/\s+/); | |
const playerId = msg.playerid; | |
// check entered command | |
if (msg.type == 'api' && cmd.indexOf('!metric') === 0) { | |
// make sure we are GM | |
if (!playerIsGM(playerId)) { | |
sendChat('API', 'Must be run as GM'); | |
return; | |
} | |
// retrieve GM player object | |
const player = findObjs({ | |
_type: 'player', | |
_id: playerId, | |
}); | |
if (player.length !== 1) { | |
sendChat('API', 'Cound not find current player info'); | |
return; | |
} | |
// retrieve current page GM is on | |
const pages = findObjs({ | |
_type: 'page', | |
_id: player[0].get('_lastpage'), | |
}); | |
if (pages.length !== 1) { | |
sendChat('API', 'Cound not find current page for GM'); | |
return; | |
} | |
// check if dynamic lighting is on | |
const page = pages[0]; | |
if (!page.get('dynamic_lighting_enabled')) { | |
sendChat('API', 'Dynamic lighting is not enabled on this page'); | |
return; | |
} | |
// check args | |
let tokens = []; | |
if (args.indexOf('--selected') !== -1) { | |
if (msg.selected.length === 0) { | |
sendChat('API', 'You must select one or more token(s) to convert'); | |
return; | |
} else { | |
msg.selected.forEach((item) => { | |
tokens.push(getObj(item._type, item._id)); | |
}); | |
} | |
} | |
// check current UoM | |
if (page.get('scale_units') === 'm' && tokens.length === 0) { | |
sendChat('API', 'Page already set to "m"eters.'); | |
return; | |
} | |
// run the conversion process | |
sendChat('API', `Starting conversion of page ${page.get('name')}`); | |
convertToMetric(page, tokens); | |
} | |
}); | |
/** | |
* Convert scale in page settings | |
* @param {object} page Roll20 API page object | |
*/ | |
function convertPage(page) { | |
let scale_number = parseInt(page.get('scale_number')) || 0; | |
let scale_metric = 0; | |
switch (scale_number) { | |
case 5: | |
scale_metric = 1.5; | |
break; | |
case 10: | |
scale_metric = 3; | |
break; | |
case 15: | |
scale_metric = 4.5; | |
break; | |
case 20: | |
scale_metric = 6; | |
break; | |
default: | |
scale_metric = scale_number; | |
break; | |
} | |
page.set({ | |
scale_units: 'm', | |
scale_number: scale_metric, | |
}); | |
sendChat('API', `/w gm Page ${page.get('name')} converted to metric system.`); | |
return; | |
} | |
/** | |
* Convert a list of token properties from feet to meters | |
* @param {object} token Roll20 graphics/token object | |
* @param {array} props List of object properties to convert | |
*/ | |
function convert(token, props) { | |
const result = {}; | |
for (prop of props) { | |
value = parseInt(token.get(prop)) || 0; | |
if (value !== 0) { | |
result[prop] = Math.floor(value / 3.28); | |
} | |
} | |
return result; | |
} | |
/** | |
* Convert scale property values from feet to meters for all token on a page | |
* @param {string} page Roll20 API Page object | |
* @param {array<object>} selected List of currently selected token objects, if any | |
*/ | |
function convertToMetric(page, selected) { | |
let tokens = selected || []; | |
// get all tokens on the page | |
if (tokens.length === 0) { | |
tokens = findObjs({ | |
_type: 'graphic', | |
_subtype: 'token', | |
_pageid: page.get('_id'), | |
}); | |
} | |
// async conversion worker | |
const convertNextToken = () => { | |
if (tokens.length > 0) { | |
token = tokens.shift(); | |
const charId = token.get('represents'); | |
if (charId !== '') { | |
// get the linked character object | |
const char = findObjs({ | |
_type: 'character', | |
_id: charId, | |
}); | |
if (char.length === 1) { | |
// convert the measures to metric | |
const converted = convert(token, [ | |
'light_radius', | |
'light_dimradius', | |
'night_vision_distance', | |
'bright_light_distance', | |
'low_light_distance', | |
]); | |
token.set(converted); | |
sendChat('API', `${char[0].get('name')} ...converted`); | |
} | |
} | |
setTimeout(convertNextToken, 0); | |
} else { | |
convertPage(page); | |
} | |
}; | |
convertNextToken(); | |
/* | |
for (const token of tokens) { | |
// filter tokens with a linked character | |
const charId = token.get('represents'); | |
if (charId !== '') { | |
// get the linked character object | |
const char = findObjs({ | |
_type: 'character', | |
_id: charId, | |
}); | |
if (char.length === 1) { | |
// convert the measures to metric | |
const converted = convert(token, [ | |
'light_radius', | |
'light_dimradius', | |
'night_vision_distance', | |
'bright_light_distance', | |
'low_light_distance', | |
]); | |
token.set(converted); | |
sendChat('API', `${char[0].get('name')} ...converted`); | |
} | |
} | |
} | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
2020-09-08 -- Version 1.0.0