Created
March 22, 2020 03:42
-
-
Save shdwjk/2d757d5ea4c8649bfa1708feca24f6c2 to your computer and use it in GitHub Desktop.
King's Summon with Last Created ID/IDs
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
/* | |
This is an improved Summoning API that was built upon. | |
Original author: Brandon W. | |
Original here: https://app.roll20.net/forum/post/466778/scipt-auto-create-a-token#post-466778 | |
Special thanks to Brian for helping me with some of the script. | |
I hope this serves others well, do not hesistate to contact me regarding bugs or improvements. | |
-GM King | |
Usage: | |
1. Select token you want the monster to appear next to. | |
2. In chat, type "!summon (name of monster) (number to summon)" without brackets or quotation marks. | |
3. By default the monster will take up a 5x5 ft square (medium or small creature). To summon larger creatures add a letter to the end of the message: | |
F= Fine, D = Diminutive, T= Tiny, L = large, H = Huge, G = Gargantuan, C = Colossal, cust = customised size (this tag must be followed by two numbers, see examples). | |
4. You can also summon a torch that will give 40 ft of vision with 20 ft of dim light (torch must be in the name). | |
NB. The name of the monster must be in your character sheet list and the image must be the token image you wish to use (marketplace images do not work). | |
Examples: | |
!summon torch | |
!summon eagle | |
!summon eagle 2 | |
!summon eagle 1d3 | |
!summon eagle 1d3+1 | |
!summon cave troll 1d3+1 H | |
!summon flame sphere cust 140 140 | |
NB. When making a custom size every 70 = 1 square. | |
*/ | |
on('ready',()=>{ | |
const assureObj = (o) => findObjs(o)[0] || createObj(o.type,o); | |
const summonCharacter = assureObj({ type: "character", name: "Summon" }); | |
const lastIDAttr = assureObj({ type: "attribute", name: "LastId", characterid: summonCharacter.id }); | |
const lastGroupIDsAttr = assureObj({ type: "attribute", name: "LastGroupIds", characterid: summonCharacter.id }); | |
on("chat:message", function(msg) | |
{ | |
if (msg.type == "api" && msg.content.indexOf("!summon ") === 0) | |
{ | |
var GM = ""; | |
var size1 = 0; | |
var size2 = size1; | |
var s = 0; | |
var inputName = ""; | |
var howMuch = 0; | |
var amount = 0; // Amount of summoned monsters. | |
var mod = 0; // Modifier to amount. | |
var skip = false; | |
var action = "Summons "; | |
var section = msg.content.split(" "); // Breaks API call into sections. | |
if (section.length > 1) | |
{ | |
for (var j=1;j<section.length;j++) | |
{ | |
if (typeof parseInt(section[j]) === 'number' && Math.round(parseInt(section[j])) % 1 == 0 || section[j].length <= 4 && section[j].toLowerCase().search("d") != -1 && /\dd/.test(section[j]) || section[j].toLowerCase() == 'cust') | |
{ | |
if (section[j].toLowerCase() == 'cust') | |
{ | |
howMuch = j; | |
break; | |
} | |
else | |
{ | |
if (j != section.length-1) | |
{ | |
for (var m = j+1; m < section.length; m++) | |
{ | |
if (typeof parseInt(section[m]) === 'number' && Math.round(parseInt(section[m])) % 1 == 0 || section[m].length <= 4 && section[m].toLowerCase().search("d") != -1 && /\dd/.test(section[m])) | |
{ | |
skip = true; | |
} | |
else | |
{ | |
skip = false; | |
} | |
} | |
} | |
else | |
{ | |
skip = false; | |
} | |
if (skip == false) | |
{ | |
howMuch = j; | |
break; | |
} | |
} | |
} | |
} | |
if (howMuch > 0) | |
{ | |
for (let k=1;k<howMuch;k++) | |
{ | |
if (k == howMuch-1) | |
{ | |
inputName = inputName + section[k]; | |
} | |
else | |
{ | |
inputName = inputName + section[k] + " "; | |
} | |
} | |
if (section[howMuch].toLowerCase().search("d") != -1) // If user chose to roll. | |
{ | |
if (section[howMuch].indexOf("+") != -1) | |
{ | |
mod = section[howMuch].split("+"); // If user specified a modfier. | |
section[howMuch] = mod[0]; | |
mod = parseInt(mod[1],10); | |
} | |
var count = 0; | |
var diceRoll = section[howMuch].split("d"); | |
diceRoll[0] = diceRoll[0].replace(/\D/g,''); | |
diceRoll[1] = diceRoll[1].replace(/\D/g,''); | |
var lowEnd = parseInt(diceRoll[0]); | |
var highEnd = parseInt(diceRoll[1]); | |
while (count < lowEnd) | |
{ | |
amount = amount + randomInteger(highEnd); // Rolls dice. | |
count++; | |
log("Summoner: rolls a " + amount); | |
} | |
} | |
else if (section[howMuch].toLowerCase() != 'cust') | |
{ | |
amount = parseInt(section[howMuch],10); // Creates variable for number of summoned monsters. | |
} | |
else | |
{ | |
amount == 1; | |
} | |
amount = amount + mod; | |
} | |
else if (howMuch == 0) | |
{ | |
if (section[section.length-1].length == 1) | |
{ | |
s = 1; | |
howMuch = section.length - 2; | |
} | |
amount = 1; | |
for (let key=1;key<section.length-s;key++) | |
{ | |
if (key == section.length-1-s) | |
{ | |
inputName = inputName + section[key]; | |
} | |
else | |
{ | |
inputName = inputName + section[key] + " "; | |
} | |
} | |
} | |
if (section.length > (howMuch+1) && section[howMuch].toLowerCase() != "cust") | |
{ | |
if (section[howMuch+1].toLowerCase() == "f") | |
{ | |
size1 = -63; | |
size2 = size1; | |
} | |
else if (section[howMuch+1].toLowerCase() == "d") | |
{ | |
size1 = -56; | |
size2 = size1; | |
} | |
else if (section[howMuch+1].toLowerCase() == "t") | |
{ | |
size1 = -35; | |
size2 = size1; | |
} | |
else if (section[howMuch+1].toLowerCase() == "l") | |
{ | |
size1 = 70; | |
size2 = size1; | |
} | |
else if (section[howMuch+1].toLowerCase() == "h") | |
{ | |
size1 = 140; | |
size2 = size1; | |
} | |
else if (section[howMuch+1].toLowerCase() == "g") | |
{ | |
size1 = 210; | |
size2 = size1; | |
} | |
else if (section[howMuch+1].toLowerCase() == "c") | |
{ | |
size1 = 280; | |
size2 = size1; | |
} | |
else if (section[howMuch+1].toLowerCase() == "cust") | |
{ | |
if (typeof section[howMuch+2] != 'undefined') | |
{ | |
size1 = parseInt(section[howMuch+2]); | |
} | |
else | |
{ | |
sendChat(msg.who, "/w gm Please ensure the \"cust\" tag is followed by two values (every 70 = 1 square)."); // If monster is not in character list. | |
} | |
if (typeof section[howMuch+3] != 'undefined') | |
{ | |
size2 = parseInt(section[howMuch+3]); | |
} | |
else | |
{ | |
sendChat(msg.who, "/w gm Please ensure the \"cust\" tag is followed by two values (every 70 = 1 square)."); // If monster is not in character list. | |
} | |
} | |
} | |
else if (section[howMuch].toLowerCase() == "cust") | |
{ | |
if (typeof section[howMuch+1] != 'undefined') | |
{ | |
size1 = parseInt(section[howMuch+1]); | |
} | |
else | |
{ | |
sendChat(msg.who, "/w gm Please ensure the \"cust\" tag is followed by two values (every 70 = 1 square)."); // If monster is not in character list. | |
} | |
if (typeof section[howMuch+2] != 'undefined') | |
{ | |
size2 = parseInt(section[howMuch+2]); | |
} | |
else | |
{ | |
sendChat(msg.who, "/w gm Please ensure the \"cust\" tag is followed by two values (every 70 = 1 square)."); // If monster is not in character list. | |
} | |
} | |
} | |
else | |
{ | |
sendChat(msg.who, "/w gm No monsters specified to summon"); // If user writes too many things. | |
} | |
var check = findObjs({ _type: "character", name: inputName },{caseInsensitive: true})[0]; | |
if (typeof check == 'undefined') | |
{ | |
sendChat(msg.who, "/w gm Monster of name \"" + inputName + "\" does not exist."); // If monster is not in character list. | |
} | |
else | |
{ | |
var list = findObjs({ _type: "character", name: inputName},{caseInsensitive: true}); | |
var characterId = list[0].id; // Extract character ID from character sheet | |
var characterName = list[0].get('name'); // Extract character name from character sheet | |
var characterImage = list[0].get('avatar'); // Extract character image URL from character sheet | |
if (characterImage.indexOf("marketplace") != -1) | |
{ | |
sendChat(msg.who, "/w gm Monster of name \"" + inputName + "\" has a marketplace image."); // Error message | |
} | |
else | |
{ | |
characterImage = characterImage.replace("med","thumb"); // Change character image to thumb if med | |
characterImage = characterImage.replace("max","thumb"); // Change character image to thumb if max | |
var selected = msg.selected; | |
_.each(selected, function(obj) | |
{ | |
var tok = getObj("graphic", obj._id); // Create variable for selected token (for summoned monster positioning) | |
var HP = findObjs({ _type: "attribute", name: "HP", _characterid: characterId },{caseInsensitive: true})[0]; //finds the health from charactersheet | |
if (typeof HP == 'undefined') | |
{ | |
HP = "-1"; | |
} | |
else | |
{ | |
HP = (HP) ? HP.get("current") : 0; // Changes HP to useable string | |
} | |
var AC = findObjs({ _type: "attribute", name: "AC", _characterid: characterId },{caseInsensitive: true})[0]; // finds the ac from charactersheet | |
if (typeof AC == 'undefined') | |
{ | |
AC = "-1"; | |
} | |
else | |
{ | |
AC = (AC) ? AC.get("current") : 0; // Changes AC to useable string | |
} | |
if (amount == 0) | |
{ | |
amount = 1; | |
} | |
else if (amount > 20) | |
{ | |
var tooMany = amount; | |
amount = 20; | |
log("Summoner: User specified " + tooMany + " monsters. Scaling to 20."); // If user spams the field. | |
} | |
let sumIDs = []; | |
for (var i=0;i<amount;i++) | |
{ | |
if (HP == "-1" && AC == "-1" && msg.content.toLowerCase().search("torch") != -1) | |
{ | |
action = "Lights"; | |
let o = createObj("graphic", | |
{ | |
represents: characterId, // Links new token to charactersheet | |
left: tok.get("left")+70, | |
top: tok.get("top"), | |
width: 70+size1, | |
height: 70+size2, | |
name: characterName, | |
pageid: tok.get("pageid"), | |
imgsrc: characterImage, | |
layer: "objects", | |
light_radius: 40, | |
light_dimradius: 20, | |
light_otherplayers: true | |
}); | |
sumIDs.push(o.id); | |
} | |
else if (HP == "-1" && AC == "-1") | |
{ | |
sendChat(msg.who, "/w gm HP or AC value not set (if this is a torch please include \"torch\" in name."); // Error message | |
let o = createObj("graphic", | |
{ | |
represents: characterId, // Links new token to charactersheet | |
left: tok.get("left")+70, | |
top: tok.get("top"), | |
width: 70+size1, | |
height: 70+size2, | |
name: characterName, | |
showname: true, | |
showplayers_name: true, | |
showplayers_bar1: true, | |
pageid: tok.get("pageid"), | |
imgsrc: characterImage, | |
layer: "objects" | |
}); | |
sumIDs.push(o.id); | |
} | |
else | |
{ | |
let o = createObj("graphic", | |
{ | |
represents: characterId, // Links new token to charactersheet | |
left: tok.get("left")+70, | |
top: tok.get("top"), | |
width: 70+size1, | |
height: 70+size2, | |
name: characterName, | |
bar2_value: AC, | |
bar3_value: HP, | |
bar3_max: HP, | |
showname: true, | |
showplayers_name: true, | |
showplayers_bar1: true, | |
pageid: tok.get("pageid"), | |
imgsrc: characterImage, | |
layer: "objects" | |
}); | |
sumIDs.push(o.id); | |
} | |
} | |
// update character | |
lastGroupIDsAttr.set({current: sumIDs.join(' ')}); | |
lastIDAttr.set({current: sumIDs.pop()}); | |
}); | |
if (amount > 1) | |
{ | |
inputName = inputName + "s"; // If more than 1 summon, adds plural. | |
} | |
else if (amount == 1 && action == "Lights") | |
{ | |
amount = " a"; | |
inputName = "torch"; | |
} | |
if (typeof amount === 'number') | |
{ | |
amount = amount.toString(); | |
} | |
sendChat(msg.who, GM + action + amount + " " + inputName + "!"); // Announces how many and what Summoner has summoned. | |
} | |
} | |
} | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment