Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Help with a script (auto-add token actions for npc 5ogl)

1534236199
Pantoufle
Pro
Sheet Author
Translator
Hello, I got this script from someone I don't remember the name (sorry :( ) I did try to reach him some months ago but never get answered. This script autopopulate token actions for npc (which send repeating actions from the 5e ogl sheet to the gm) BUT often get twice the repeating action in the chat... don't know why since I'm no good with API scripts :D Anyone? Pleaseeee :) function getCharacterObj(obj) { "use strict"; //send any object and returns the associated character object //returns character object for attribute, token/graphic, and ability, and... character var objType = obj._type, att, characterObj, tok; if ((objType !== "attribute") && (objType !== "graphic") && (objType !== "character")) { sendChat("API"," cannot be associated with a character."); return; } if ((objType === "attribute") || (objType === "ability")) { att = getObj(objType, obj._id); if (att.get("_characterid") !== "") { characterObj = getObj("character", att.get("_characterid")); } } if (objType === "graphic") { tok = getObj("graphic", obj._id); if (tok.get("represents") !== "") { characterObj = getObj("character", tok.get("represents")); } else { sendChat("API"," Selected token does not represent a character."); return; } } if (objType === "character") { characterObj = getObj("character", obj._id); } return characterObj; } on("chat:message", function(msg) { "use strict"; var msg, selected, Parameters, statusName, aName, ids, attributeName, newValue, characterObj, attributeObjArray, tok; if (msg.type === "api" && msg.content.indexOf("!generate-spellbook") !== -1 ) { selected = msg.selected; var parameters = msg.content.split(" "); // Set filter for what spell class to generate a spellbook for // Defaults to -1 for no filter var spellClass = -1; if (parameters.length > 1) spellClass = parameters[1]; // Set the name of the ability the macro will be put into // Defaults to "Spells" var abilityName = "Spells"; if (parameters.length > 2) abilityName = parameters[2]; // Set the title to use in the template header // Defaults to "Spells" var title = "Spells"; if (parameters.length > 3) title = parameters[3]; //loop through selected tokens _.each(selected, function(obj) { tok = getObj("graphic", obj._id); // Get the character token represents characterObj = getCharacterObj(obj); if ( ! characterObj) { return; } var characterName = characterObj.get("name"); var rowIDs = new Array(); // Create array for repeating spell attribute names getAllObjs().forEach(function(obj) { // Filter down to just attribute objects belonging to the character, whose name indicates it's a spell if (obj.get("type") !== "attribute") return; if (obj.get("_characterid") !== characterObj.get("_id")) return; if (obj.get("name").indexOf("repeating_spell-") === -1) return; // If this is a name attribute, use that to add the base repeating attribute name to the array if (obj.get("name").indexOf("_spellname") !== -1) rowIDs.push(obj.get("name").substr(0,obj.get("name").indexOf("_spellname"))); }); // Create arrays for individual spell levels var lvl0 = new Array(); var lvl1 = new Array(); var lvl2 = new Array(); var lvl3 = new Array(); var lvl4 = new Array(); var lvl5 = new Array(); var lvl6 = new Array(); var lvl7 = new Array(); var lvl8 = new Array(); var lvl9 = new Array(); var npc = new Array(); // Sort rowIDs into spell levels rowIDs.forEach(function(entry){ // Grab the spell level from attribute name repeating_spell-1 var lvl = entry.substr(16,1); if(entry.indexOf("cantrip") >= 0){ lvl = "cantrip"; } if(entry.indexOf("npc") >= 0){ lvl = "npc"; } // Put spell into the correct spell level switch (lvl) { case "cantrip": lvl0.push(entry); break; case "1": lvl1.push(entry); break; case "2": lvl2.push(entry); break; case "3": lvl3.push(entry); break; case "4": lvl4.push(entry); break; case "5": lvl5.push(entry); break; case "6": lvl6.push(entry); break; case "7": lvl7.push(entry); break; case "8": lvl8.push(entry); break; case "9": lvl9.push(entry); break; case "npc": npc.push(entry); break; } }); var macroText = "/w @{character_name} @{selected|wtype}&{template:atk} {{rname=Spell List}} {{desc=SPELL LIST:\n\n"; // Base macro text // Add spells to macro by spell level var addSpells = function(spells, title){ if (spells.length > 0) { var lvlText = ""; spells.forEach(function(entry) { // Check for spell name attribute; was having orphaned row_id attributes creating buttons for repeating rows that didn't actually exist if (_.isUndefined(getAttrByName(characterObj.get("_id"), entry + "_spellname"))) return; if(lvlText){ lvlText += ", "; } lvlText = lvlText + "[@{"+entry+"_spellname}](~"+characterName+"|"+entry+"_spell) "; }); if (lvlText !== "") macroText = macroText+title+": "+ lvlText+"\n\n"; } } addSpells(lvl0, "Cantrips"); addSpells(lvl1, "Level 1"); addSpells(lvl2, "Level 2"); addSpells(lvl3, "Level 3"); addSpells(lvl4, "Level 4"); addSpells(lvl5, "Level 5"); addSpells(lvl6, "Level 6"); addSpells(lvl7, "Level 7"); addSpells(lvl8, "Level 8"); addSpells(lvl9, "Level 9"); addSpells(npc, "NPC"); macroText += "}}" // Check for existing ability with chosen ability name var abil = findObjs({ _type: "ability", _characterid: characterObj.get("_id"), name: abilityName }); if (abil.length === 0){ createObj("ability", { name: abilityName, characterid: characterObj.get("_id"), action: macroText, istokenaction: true }); }else{ abil[0].set("action", macroText); } }); } }); on("chat:message", function(msg) { "use strict"; var msg, selected, Parameters, statusName, aName, ids, attributeName, newValue, characterObj, attributeObjArray, tok; if (msg.type === "api" && msg.content.indexOf("!generate-attackbook") !== -1 ) { selected = msg.selected; var parameters = msg.content.split(" "); // Set filter for what spell class to generate a spellbook for // Defaults to -1 for no filter var spellClass = -1; if (parameters.length > 1) spellClass = parameters[1]; // Set the name of the ability the macro will be put into // Defaults to "Spells" var abilityName = "Attacks"; if (parameters.length > 2) abilityName = parameters[2]; // Set the title to use in the template header // Defaults to "Spells" var title = "Attacks"; if (parameters.length > 3) title = parameters[3]; //loop through selected tokens _.each(selected, function(obj) { tok = getObj("graphic", obj._id); // Get the character token represents characterObj = getCharacterObj(obj); if ( ! characterObj) { return; } var characterName = characterObj.get("name"); var attackIds = new Array(); // Create array for repeating spell attribute names var npcActionIds = new Array(); // Create array for repeating spell attribute names var npcReactionIds = new Array(); // Create array for repeating spell attribute names var npcTraitIds = new Array(); // Create array for repeating spell attribute names var legendaryActionIds = new Array(); // Create array for repeating spell attribute names getAllObjs().forEach(function(obj) { // Filter down to just attribute objects belonging to the character, whose name indicates it's a spell if (obj.get("type") !== "attribute") return; if (obj.get("_characterid") !== characterObj.get("_id")) return; if (obj.get("name").indexOf("repeating_attack") === -1 && obj.get("name").indexOf("repeating_npcaction") === -1 && obj.get("name").indexOf("repeating_npcreaction") === -1 && obj.get("name").indexOf("repeating_npctrait") === -1) return; // If this is a name attribute, use that to add the base repeating attribute name to the array if (obj.get("name").indexOf("_atkname") !== -1) attackIds.push(obj.get("name").substr(0,obj.get("name").indexOf("_atkname"))); if (obj.get("name").indexOf("npcaction_") !== -1 && obj.get("name").indexOf("_name") !== -1){ npcActionIds.push(obj.get("name").substr(0,obj.get("name").indexOf("_name"))); } if (obj.get("name").indexOf("npcreaction_") !== -1 && obj.get("name").indexOf("_name") !== -1){ npcReactionIds.push(obj.get("name").substr(0,obj.get("name").indexOf("_name"))); } if (obj.get("name").indexOf("npctrait_") !== -1 && obj.get("name").indexOf("_name") !== -1){ npcTraitIds.push(obj.get("name").substr(0,obj.get("name").indexOf("_name"))); } if (obj.get("name").indexOf("npcaction-l_") !== -1 && obj.get("name").indexOf("_name") !== -1){ legendaryActionIds.push(obj.get("name").substr(0,obj.get("name").indexOf("_name"))); } }); var macroText = "/w @{character_name} @{selected|wtype}&{template:atk} {{rname=Attack List}} {{desc= ATTACK LIST\n"; // Base macro text // Add spells to macro by spell level if (attackIds.length > 0) { var lvlText = ""; attackIds.forEach(function(entry) { // Check for spell name attribute; was having orphaned row_id attributes creating buttons for repeating rows that didn't actually exist if (_.isUndefined(getAttrByName(characterObj.get("_id"), entry + "_atkname"))) return; lvlText = lvlText + "\n[@{"+entry+"_atkname}](~"+characterName+"|"+entry+"_attack) "; }); if (lvlText !== "") macroText = macroText+"Attacks: "+ lvlText+"\n\n"; } if (npcActionIds.length > 0) { var lvlText = ""; npcActionIds.forEach(function(entry) { // Check for spell name attribute; was having orphaned row_id attributes creating buttons for repeating rows that didn't actually exist if (_.isUndefined(getAttrByName(characterObj.get("_id"), entry + "_name"))) return; lvlText = lvlText + "\n[@{"+entry+"_name}](~"+characterName+"|"+entry+"_npc_action) "; }); if (lvlText !== "") macroText = macroText+"Actions: "+ lvlText+"\n\n"; } if (legendaryActionIds.length > 0) { var lvlText = ""; legendaryActionIds.forEach(function(entry) { // Check for spell name attribute; was having orphaned row_id attributes creating buttons for repeating rows that didn't actually exist if (_.isUndefined(getAttrByName(characterObj.get("_id"), entry + "_name"))) return; lvlText = lvlText + "\n[@{"+entry+"_name}](~"+characterName+"|"+entry+"_npc_action) "; }); if (lvlText !== "") macroText = macroText+"Legendary Actions: "+ lvlText+"\n\n"; } macroText += "}}" // Check for existing ability with chosen ability name var abil = findObjs({ _type: "ability", _characterid: characterObj.get("_id"), name: abilityName }); if (abil.length === 0){ createObj("ability", { name: abilityName, characterid: characterObj.get("_id"), action: macroText, istokenaction: true }); }else{ abil[0].set("action", macroText); } }); } }); on("chat:message", function(msg) { "use strict"; var msg, selected, Parameters, statusName, aName, ids, attributeName, newValue, characterObj, attributeObjArray, tok; if (msg.type === "api" && msg.content.indexOf("!generate-checkbook") !== -1 ) { selected = msg.selected; var parameters = msg.content.split(" "); // Set the name of the ability the macro will be put into // Defaults to "Spells" var abilityName = "Other"; // Set the title to use in the template header // Defaults to "Spells" var title = "Other"; //loop through selected tokens _.each(selected, function(obj) { tok = getObj("graphic", obj._id); // Get the character token represents characterObj = getCharacterObj(obj); if ( ! characterObj) { return; } var characterName = characterObj.get("name"); var macroText = "/w @{character_name} @{selected|wtype}&{template:atk} {{rname=Other}} {{desc="; // Base macro text if(getAttrByName(characterObj.get("_id"), "npc") == 1){ macroText += "Checks: \n" macroText += "[Str](~"+characterName+"|npc_str) "; macroText += ", [Dex](~"+characterName+"|npc_dex) "; macroText += ", [Con](~"+characterName+"|npc_con) "; macroText += ", [Wis](~"+characterName+"|npc_wis) "; macroText += ", [Int](~"+characterName+"|npc_int) "; macroText += ", [Cha](~"+characterName+"|npc_cha) "; macroText += "\n\n[Acrobatics](~"+characterName+"|npc_Acrobatics) "; macroText += ", [Animal Handling](~"+characterName+"|npc_Animal_Handling) "; macroText += ", [Arcana](~"+characterName+"|npc_Arcana) "; macroText += ", [Athletics](~"+characterName+"|npc_Athletics) "; macroText += ", [Deception](~"+characterName+"|npc_Deception) "; macroText += ", [History](~"+characterName+"|npc_History) "; macroText += ", [Insight](~"+characterName+"|npc_Insight) "; macroText += ", [Intimidation](~"+characterName+"|npc_Intimidation) "; macroText += ", [Investigation](~"+characterName+"|npc_Investigation) "; macroText += ", [Medicine](~"+characterName+"|npc_Medicine) "; macroText += ", [Nature](~"+characterName+"|npc_Nature) "; macroText += ", [Perception](~"+characterName+"|npc_Perception) "; macroText += ", [Performance](~"+characterName+"|npc_Performance) "; macroText += ", [Persuasion](~"+characterName+"|npc_Persuasion) "; macroText += ", [Religion](~"+characterName+"|npc_Religion) "; macroText += ", [Sleight of Hand](~"+characterName+"|npc_Sleight_of_Hand) "; macroText += ", [Stealth](~"+characterName+"|npc_Stealth) "; macroText += ", [Survival](~"+characterName+"|npc_Survival) "; macroText += "\n\nSaves: \n" macroText += "[Str](~"+characterName+"|npc_str_save) "; macroText += ", [Dex](~"+characterName+"|npc_dex_save) "; macroText += ", [Con](~"+characterName+"|npc_con_save) "; macroText += ", [Wis](~"+characterName+"|npc_wis_save) "; macroText += ", [Int](~"+characterName+"|npc_int_save) "; macroText += ", [Cha](~"+characterName+"|npc_cha_save) "; } else { macroText += "Checks: \n" macroText += "[Str](~"+characterName+"|strength) "; macroText += ", [Dex](~"+characterName+"|dexterity) "; macroText += ", [Con](~"+characterName+"|constitution) "; macroText += ", [Wis](~"+characterName+"|wisdom) "; macroText += ", [Int](~"+characterName+"|intelligence) "; macroText += ", [Cha](~"+characterName+"|charisma) "; macroText += "\n\n[Acrobatics](~"+characterName+"|Acrobatics) "; macroText += ", [Animal Handling](~"+characterName+"|Animal_Handling) "; macroText += ", [Arcana](~"+characterName+"|Arcana) "; macroText += ", [Athletics](~"+characterName+"|Athletics) "; macroText += ", [Deception](~"+characterName+"|Deception) "; macroText += ", [History](~"+characterName+"|History) "; macroText += ", [Insight](~"+characterName+"|Insight) "; macroText += ", [Intimidation](~"+characterName+"|Intimidation) "; macroText += ", [Investigation](~"+characterName+"|Investigation) "; macroText += ", [Medicine](~"+characterName+"|Medicine) "; macroText += ", [Nature](~"+characterName+"|Nature) "; macroText += ", [Perception](~"+characterName+"|Perception) "; macroText += ", [Performance](~"+characterName+"|Performance) "; macroText += ", [Persuasion](~"+characterName+"|Persuasion) "; macroText += ", [Religion](~"+characterName+"|Religion) "; macroText += ", [Sleight of Hand](~"+characterName+"|Sleight_of_Hand) "; macroText += ", [Stealth](~"+characterName+"|Stealth) "; macroText += ", [Survival](~"+characterName+"|Survival) "; macroText += "\n\nSaves: \n" macroText += "[Str](~"+characterName+"|strength_save) "; macroText += ", [Dex](~"+characterName+"|dexterity_save) "; macroText += ", [Con](~"+characterName+"|constitution_save) "; macroText += ", [Wis](~"+characterName+"|wisdom_save) "; macroText += ", [Int](~"+characterName+"|intelligence_save) "; macroText += ", [Cha](~"+characterName+"|charisma_save) "; } macroText += "}}" // Check for existing ability with chosen ability name var abil = findObjs({ _type: "ability", _characterid: characterObj.get("_id"), name: abilityName }); if (abil.length === 0){ createObj("ability", { name: abilityName, characterid: characterObj.get("_id"), action: macroText, istokenaction: true }); }else{ abil[0].set("action", macroText); } }); } });
1534247947
The Aaron
Pro
API Scripter
I think that’s Kevin’s script. In the cases where you get two copies, do you always get two copies of you run it again? Or do you only sometimes get two copies?
1534249443
Pantoufle
Pro
Sheet Author
Translator
Cannot test right now, will do asap. As far as I remember it is only for the "attack book" but for every single one
1534265814

Edited 1534266295
Pantoufle
Pro
Sheet Author
Translator
Ok so the problem is only for the attack button (spellbook and checks are ok). First, every single reapeating action comes twice and there is a problem as well for the spells in the attack section (sometimes x2, sometimes x3 :p) Here are a few exemples :
1534281402
The Aaron
Pro
API Scripter
It must be something with how it's filtering down results.  I notice it's using a series of ifs instead of elseifs.  It's possible the same item is getting added multiple times to some arrays.  I'll have to take a look when I get more time, or maybe the author will wander by...
1534307648
Pantoufle
Pro
Sheet Author
Translator
Thx for your help anyway Aaron, as always :)