Skip to content

Instantly share code, notes, and snippets.

@nolivo
nolivo / spiritualWeapon.js
Last active January 4, 2022 06:55
A script for use with Roll20 to summon a spiritual weapon to the right of a selected character's token
on("ready",function()
{
on("chat:message",function(msg){
if(msg.type=="api" && msg.content.indexOf("!spiritualWeapon")==0 && playerIsGM(msg.playerid))
{
var selected = msg.selected;
if (selected===undefined)
{
sendChat("API","Please select a character.");
return;
@nolivo
nolivo / mapSizer.js
Last active May 31, 2022 19:04
mapSizer.js A script that resizes an image and page to specific dimensions, centers the image on the page and puts it on the map layer.
//usage - !mapSizer imageWidthInPixels imageHeightInPixels
on("ready",function(){
on("chat:message",function(msg){
if(msg.type=="api" && msg.content.indexOf("!mapSizer")==0){
var args = msg.content.split(" ");
var mapWidth = Number(args[1]);
var mapHeight = Number(args[2]);
var selected = msg.selected;
if(selected===undefined){
sendChat("API","Please select a graphic");
on("ready",function(){
on("change:campaign:playerpageid",function(){
setTimeout(function(){
pingStartToken();
},1500);
});
on("chat:message",function(msg){
if(msg.type=="api" && msg.content.indexOf("!pingStart")==0){
pingStartToken();
on("ready",function(){
var isItRunning;
on("change:campaign:playerpageid",function(){
var currentPage = getObj("page",Campaign().get("playerpageid"));
if (currentPage.get("name")=="breakScreen"){
var textBox;
var token = findObjs({
name:"textLocation",
type:"graphic",
pageid:Campaign().get("playerpageid")
on("ready",function(){
on("chat:message",function(msg){
if(msg.type=="api" && msg.content.indexOf("!exportMacros")==0){
var existingMacros = findObjs({type:"character",name:"MrMacro"});
if (existingMacros!==undefined){
_.each(existingMacros,function(mrMacro){
mrMacro.remove();
})
}
on("chat:message",function(msg){
if(msg.type=="api" && msg.content.indexOf("!pingMe")==0){
var characterList = findObjs({type:"character",controlledby:msg.playerid});
var playerName = getObj("player",msg.playerid).get("displayname");
if(characterList.length==1){
sendChat("PingMeAPI","!pingCharacter " + characterList[0].get("id") + " " + msg.playerid + " " + playerName);
}
else{
var pingList="";
_.each(characterList,function(character){
on("ready",function(){
on("chat:message", function(msg)
{
if (msg.type !== "api"){
return;
}
var args = msg.content.split(" ");
if (args[0] == "!multiTokenFx"){
if(msg.selected===undefined){
sendChat("MultiFX","/w gm please select some tokens");
!power {{
--name|Ray of Frost
--leftsub|Ranged Spell Attack
--rightsub|60 ft Range
--npc_qualities_summary @{target|character_id}
--Attack:|[[ [$Atk] ?{Attack|Standard,1d20|Advantage,2d20kh1|Disadvantage,2d20kl1} + @{spell_attack_bonus} ]] vs AC @{target|AC}
--?? $Atk >= @{target|AC} AND $Atk.base <> 20 ?? Damage:|[[ [$Dmg] 2d8 ]]
--?? $Atk.base == 20 ?? Critical Hit|[[ [$CritDmg] 4d8 ]]
--soundfx|_audio,play,nomenu|freezeRay
--vfx_opt|@{selected|token_id} @{target|token_id} beam-frost
on("chat:message",function(msg){
if(msg.type=="api" && msg.content=="!partyMover"){
buildPartyMoverMacro();
}
});
on("change:page:name",function(){
buildPartyMoverMacro();
sendChat("API","!mc refresh");
})
on("chat:message", function(msg)
{
if (msg.type == "api" && msg.content.indexOf("!customSpellbook") == 0){
var args = msg.content.split(/\s+/);
var spellName = args[1].toLowerCase();
var spellLevel = Number(args[2]);
var tokenid = msg.selected[0]._id;
var token = getObj("graphic",tokenid);
var charID = token.get("represents");
var tokenName = token.get("name");