
After benefitting from all the great scripts here I thought it is time to give something back. This is my first, fairly simple, script and it does exactly what the title says, it links an attribute to a marker. Of course this is most useful if your Attributes max is typically less than 9. I use it for several things in Savage Worlds, most importantly Wounds and Fatigue. But the script is generic and can easily be configured to link any combination of Attributes and Markers. It is possible to modify this to show values larger than 9 with two symbols, but that would be quite a hack and I did not want to go there in case future changes of the API make that obsolete. Feel free to criticize in case you find bad javascript practices, I am a C programmer and the whole idea of an untyped language still makes me roll my eyes in disbelieve. I am also working on two other scripts I will share eventually, a Savage Worlds dice script for trait, damage, unshake and area of effect deviation rolls as well as a Savage Worlds character/NPC importer, so stay tuned for more! // Configure which attribute should be linked to which marker var CONFIG = [ {attribute: "Wounds", marker: "half-heart"}, {attribute: "Fatigue", marker: "sleepy"}, {attribute: "Pace", marker: "tread"}, {attribute: "Armor", marker: "bolt-shield"} ];
// Helper function to update all the markers on all tokens that are linked // to a character function updateAllTokens(charId, marker, value) { var tokens = findObjs({_type: "graphic", _subtype: "token", represents: charId}); _.each(tokens, function(obj) { obj.set("status_" + marker, value); }); }
// Translate an attribute string to a marker value including some error checking // Returns null if the attribute can't be shown in a marker function attributeToMarker(attributeValue) { var markerValue = 0; attributeValue = attributeValue.trim(); if (attributeValue === "") return false; markerValue = parseInt(attributeValue); if (markerValue === 0) return false; else if (markerValue === 1) return true; else if (!markerValue || markerValue < 0 || markerValue > 9) return null; else return markerValue; }
// Update attributes if the markers change on('change:graphic:statusmarkers', function(obj, prev) { var charId = obj.get("represents"); if (charId) { CONFIG.forEach(function(opts) { var attribute = findObjs({ _type: "attribute", name: opts.attribute, _characterid: charId })[0]; if (attribute) { var markerValue = obj.get("status_" + opts.marker); updateAllTokens(charId, opts.marker, markerValue); var attributeValue = ""; if (markerValue == false) attributeValue = "0"; else if (markerValue == true) attributeValue = "1"; else attributeValue = markerValue; attribute.set("current", attributeValue); } }); } });
// Update tokens if the attribute changes on('change:attribute:current', function(obj, prev) { CONFIG.forEach(function(opts) { if (obj.get("name") == opts.attribute) { var charId = obj.get("_characterid"); var attributeValue = obj.get("current"); var markerValue = attributeToMarker(attributeValue); if (markerValue === null) { log("Attribute value not valid!"); return; } updateAllTokens(charId, opts.marker, markerValue); } }); });
// This is needed to so that tokens that are dragged on the table top from the journal // get markers on('ready', function() { on('add:token', function(obj){ var charId = obj.get("represents"); if (charId) { CONFIG.forEach(function(opts) { var attribute = findObjs({ _type: "attribute", name: opts.attribute, _characterid: charId })[0]; if (attribute) { var attributeValue = attribute.get("current"); var markerValue = attributeToMarker(attributeValue); if (markerValue === null) { log("Attribute value not valid!"); return; } obj.set("status_" + opts.marker, markerValue); } }); } }); });