
**I think this justifies a new post, but if it should be a comment in my previous thread please let me know and I'll reply to it instead**
With the help of several folks here on the boards, I've come up with a workable scenario to achieve my goal of having a conditional attack modifier based on NPC type. However, I have to make it as painless as possible for my GM, and that's where I'm stuck now.
I need to cycle through every NPC sheet in the game (and any new sheets he adds to the game), and create 2 new attributes that are based off of one existing attribute. Cycling through everything and only acting if npc_type already exists shouldn't hurt anything.
I started with Invincible Spleen's awesome updater (https://app.roll20.net/forum/post/2011765/add-attribute-api/?pageforid=2011765#post-2011765)) but I'm falling short needing to use per-character existing information for the new value, rather than simply having a constant pre-set value.
The default NPC sheets my GM is using all have the following attribute with a multiple string value that can have one of two formats:
npc_type "<size> <type>,<alignment>" // "Medium undead, lawful evil"
npc_type "<size> <type> (<subtype>),<alignment>" // "Small humanoid (goblinoid), neutral evil"
I'll just look at the top case to start, but planning for the second version may change the way the split calls are made.
I need to read in the attribute value, split the resulting string, then create and assign a new attribute value using the split info (and do this to all sheets, already existing and yet to be created)
For example using a skeleton: npc_type = "Medium undead, lawful evil"
The desire is for npc_type_split[x] to fill with
npc_type_split[0] = "Medium"
npc_type_split[1] = "undead" //as I type I realize i'll need another (or more robust) split to remove the ","
npc_type_split[2] = "lawful"
npc_type_split[3] = "evil"
Then push [1] to the new attribute basic_type, resulting in basic_type = "undead"
My butchered attempt at doing so follows if it's of any help. The only changes are to the top two sections. One glaring issue is that there's no definition for characterID since what I have is outside of the loop that cycles through each sheet/assigns the info as a new one is made. The killer is that the script uses attributehash[x] to determine when it has finished with each sheet, so I still need a global variable list so it does something, but the value i want to put in is not constant.
var DefaultAttributes = DefaultAttributes || (function () { 'use strict'; /// /// Original Script by Invincible Spleen (https://app.roll20.net/forum/post/2011765/add-attribute-api/?pageforid=2011765#post-2011765) /// Mangled by Takryn /// /// Usage: /// !initattributes sets attributes to default values listed; creating new attributes if non-existing /// !setAttribute [attribute] [newvalue] sets attribute to value; can use incremental changes ie +1 /// // Pull and parse type value from npc_type var pullandparse = function(characterID) { var npc_type = getObjs({ _characterid: characterid, _type: "attribute", name: "npc_type" })[0]; var npc_type_split = {npc_type.split(' ')}; var basic_type = {npc_type_split[1]}; }, // Attributes all characters should have var attributeHash = { "basic_type": { "current": basic_type, } }, // Set an attribute's value, or create it if it does not exist setAttribute = function(characterID, attributeName, newValue, operator) { var mod_newValue = { "+": function (num) { return num; }, "-": function (num) { return -num; } }, foundAttribute = findObjs({ _characterid: characterID, _type: "attribute", name: attributeName })[0]; if (!foundAttribute) { if (typeof operator !== 'undefined' && !isNaN(newValue)) { log (newValue + " is a number."); newValue = mod_newValue[operator](newValue); } log("DefaultAttributes: Initializing " + attributeName + " on character ID " + characterID + " with a value of " + newValue + "."); sendChat("DefaultAttributes:", "/w GM Initializing " + attributeName + " on character ID " + characterID + " with a value of " + newValue + "."); createObj("attribute", { name: attributeName, current: newValue, characterid: characterID }); } else { if (typeof operator !== 'undefined' && !isNaN(newValue) && !isNaN(foundAttribute.get("current"))) { newValue = parseFloat(foundAttribute.get("current")) + parseFloat(mod_newValue[operator](newValue)); } log("DefaultAttributes: Setting " + attributeName + " on character ID " + characterID + " to a value of " + newValue + "."); sendChat("DefaultAttributes:", "/w GM Setting " + attributeName + " on character ID " + characterID + " to a value of " + newValue + "."); foundAttribute.set("current", newValue); } }, // Add missing attributes and restore exiting ones to their default values initCharacterAttributes = function(char){ log("DefaultAttributes: Initializing default attributes for character ID " + char.id + "."); sendChat("DefaultAttributes:", "/w GM Initializing default attributes for character ID " + char.id + "."); for (var key in attributeHash) { if (attributeHash.hasOwnProperty(key)) { setAttribute(char.id, key, attributeHash[key]["current"]); } } }, showHelp = function () { sendChat("DefaultAttributes:", "/w GM Syntax is !setattribute <i>Attribute</i> [+/-] <i>Value</i>"); }, handleInput = function(msg) { if(msg.type == "api") { var args = msg.content.split(/\s+/); switch(args[0]) { case '!initattributes': if (playerIsGM(msg.playerid)) { log("DefaultAttributes: Initializing default attributes for all existing characters."); sendChat("DefaultAttributes:", "/w GM Initializing default attributes for all existing characters."); var allCharacters = findObjs({ _type: "character" }); _.each(allCharacters, function(char) { initCharacterAttributes(char); }); } break; case '!setattribute': if (args.length < 3 || args.length > 4) { return showHelp(); } var foundCharacter = findObjs({ _type: "character", name: msg.who })[0]; if (foundCharacter) { if (args[2] == "+" || args[2] == "-") { setAttribute(foundCharacter.id, args[1], args[3], args[2]); } else { setAttribute(foundCharacter.id, args[1], args[2]); } } else { log("DefaultAttributes: No character associated with " + msg.who); sendChat("DefaultAttributes:", "/w GM No character associated with " + msg.who); } break; } } }, // Event triggers registerEventHandlers = function() { on("add:character", initCharacterAttributes); on("chat:message", handleInput); }; return { RegisterEventHandlers: registerEventHandlers }; })(); on("ready", function() { 'use strict'; DefaultAttributes.RegisterEventHandlers(); });
As always any help is appreciated!