/* exaltScript for Exalted 3rd Edition Author: Pinmissile Contact: https://app.roll20.net/users/2709/pinmissile Many thanks to The Aaron, because like most API scripters I referenced his code a lot. This script adds general utility and automation to Exalted 3rd Edition campaigns. If you want to suggest features, please send me a PM */ var exaltScript = exaltScript || { version: "1.0", lastUpdated: "23/01/2018", authors: "Pinmissile", gmOnly: true, //Change to false if you want players to be able to run the script CheckInstall: function() { if( ! state.hasOwnProperty('exaltScript') || state.exaltScript.version != exaltScript.version){ state.exaltScript = { version: exaltScript.version, setting: { doInitiative: true, doAnima: true, doNotifications: true, doWoundtracker: true, doStatusSwitch: true, } } sendChat('exaltScript','/w gm New version of exaltScript detected!'); exaltScript.DisplayInterface("gm"); sendChat('exaltScript','/w gm To access the exaltScript UI again, write !exaltScript UI'); } log("--= exaltScript v"+exaltScript.version+" =--"); }, endTurn: function(turnorder){ _.each(turnorder, function (turnorder) { if (turnorder.id != "-1") { //Add 5 motes to all characters in the turn order. var graphic = getObj("graphic", turnorder.id); var character = getObj("character", graphic.get("represents")); if (graphic != undefined && character != undefined) { exaltScript.addMotes(5,character.id); } } }); let order = Campaign().get('turnorder'); //Sort turn order if (order.length) { order = _.sortBy(JSON.parse(order), (t) => -parseInt(t.pr)); } Campaign().set('turnorder', JSON.stringify(order)); if(turnorder[0] == undefined) return; else turnorder = JSON.parse(Campaign().get("turnorder")); if (turnorder[0].id != "-1"){ //Custom token check getObj("graphic", turnorder[0].id).set({ status_purplemarker: false //Remove onslaught from top initiative after sorting }); } }, newTurn: function(turnorder){ getObj("graphic", turnorder[0].id).set({ status_purplemarker: false //Remove Onslaught when the turn order hits a token }); }, checkEndTurnMarker: function(turnorder){ 'use strict'; var yesTurnorder = false; for(var i = 0; i < turnorder.length; i++){ if(turnorder[i].id == "-1" && turnorder[i].pr=="-99" && turnorder[i].custom=="End Turn") return false;; } return true; }, createEndTurnMarker: function(turnorder){ //Pushes an End Turn token to the turn order 'use strict'; turnorder.push({ id: "-1", pr: "-99", custom: "End Turn" }); Campaign().set("turnorder", JSON.stringify(turnorder)); }, findMaxMotes: function (characterID, attribute){ var motePool = getAttrByName(characterID, attribute); //might look something like @{essence} * 7 + 26 OR a flat value if (motePool == undefined) return; if (typeof motePool == "string" ){ if (motePool.match("@{essence}") == "@{essence}"){ motePool = motePool.replace("@{essence}",getAttrByName(characterID,"essence")); } }if (motePool == undefined) motePool = 0; motePool = eval(motePool); if (motePool < 0) return 0; return motePool; }, maxMotes: function (){ var graphic = findObjs({ _pageid: Campaign().get("playerpageid"), _type: "graphic", layer: "objects", }); _.each(graphic, function (graphic) { var toAdd = 0; var character = getObj("character", graphic.get("represents")); if (character != undefined){ var comitted = 1*getAttrByName(character.id, "committedesstotal"); if (getAttrByName(character.id, "personal-essence") == "undefined" || isNaN(getAttrByName(character.id, "personal-essence")) == true) exaltScript.setAttribute("personal-essence",character.id, "0"); if (getAttrByName(character.id, "peripheral-essence") == "undefined" || isNaN(getAttrByName(character.id, "peripheral-essence")) == true) exaltScript.setAttribute("peripheral-essence",character.id, "0"); var maxValue = exaltScript.findMaxMotes(character.id,"peripheral-equation"); if (comitted < maxValue){ toAdd = maxValue - comitted; toAdd = toAdd.toString(); exaltScript.setAttribute("peripheral-essence",character.id, toAdd); toAdd = exaltScript.findMaxMotes(character.id,"personal-equation");; toAdd = toAdd.toString(); exaltScript.setAttribute("personal-essence",character.id, toAdd) } else { exaltScript.setAttribute("peripheral-essence",character.id, "0"); comitted = comitted - maxValue; maxValue = exaltScript.findMaxMotes(character.id,"personal-equation"); if (comitted < maxValue){ toAdd = maxValue - comitted; toAdd = toAdd.toString(); exaltScript.setAttribute("personal-essence",character.id, toAdd); } else exaltScript.setAttribute("personal-essence",character.id, "0"); } } }); exaltScript.NotifyChange("Motes maxed","none"); }, addMotesToCharacters: function(motes){ var graphic = findObjs({ _pageid: Campaign().get("playerpageid"), _type: "graphic", layer: "objects", }); _.each(graphic, function (graphic) { var character = getObj("character", graphic.get("represents")); if(character != undefined){ exaltScript.addMotes(motes,character.id); } }); exaltScript.NotifyChange(motes+" motes added","none"); }, addMotes: function (motes, characterID){ //Generic algorithm for adding motes. var maxPersonal = exaltScript.findMaxMotes(characterID, "personal-equation"); var maxPeripheral = exaltScript.findMaxMotes(characterID, "peripheral-equation"); var comitted = 1*getAttrByName(characterID, "committedesstotal"); var curValue = 0; var diff = 0; if (getAttrByName(characterID, "peripheral-essence") == undefined || isNaN(getAttrByName(characterID, "peripheral-essence")) == true) //In the event that the attribute is set to an undefined value... exaltScript.setAttribute("peripheral-essence",characterID, "0"); //The attribute is set to 0. if (getAttrByName(characterID, "personal-essence") == undefined || getAttrByName(characterID, "personal-essence") == NaN) exaltScript.setAttribute("personal-essence",characterID, "0"); if (getAttrByName(characterID, "committedesstotal") == undefined) exaltScript.setAttribute("committedesstotal",characterID, "0"); if(comitted > maxPeripheral){ //Sorting out max pools maxPersonal = maxPersonal + maxPeripheral - comitted; maxPeripheral = 0; if(maxPersonal < 0) maxPersonal = 0; } else maxPeripheral = maxPeripheral - comitted; curValue = 1*getAttrByName(characterID, "peripheral-essence"); if(curValue == NaN) curValue = 0; diff = maxPeripheral - curValue; if(diff < 5){ exaltScript.setAttribute("peripheral-essence",characterID, maxPeripheral); motes = motes - diff; curValue = 1*getAttrByName(characterID, "personal-essence"); if(curValue == NaN) curValue = 0; diff = maxPersonal - curValue; if (diff > motes){ exaltScript.setAttribute("personal-essence",characterID, motes+curValue); } else exaltScript.setAttribute("personal-essence",characterID, maxPersonal); } else { curValue = curValue + motes; exaltScript.setAttribute("peripheral-essence",characterID, curValue); } }, setAttribute: function (attributeName, characterID, toSet){ //Generic function for setting an attribute to a value. var attribute = findObjs({ _characterid: characterID, _type: "attribute", name: attributeName, }); if(attribute[0] != undefined){ attribute[0].set({ current: toSet }); } }, increaseAnima: function(object, previous){ //Spend five or more peripheral motes, get more anima. var graphic = findObjs({ _represents: object.get("characterid"), _type: "graphic", _pageid: Campaign().get("playerpageid"), layer: "objects" }); var graphic = graphic[0]; if (graphic == undefined ) return; if(previous["current"]-object.get("current") > 4 && graphic.get("status_ninja-mask") == false){ switch(graphic.get("status_aura")) { case false: graphic.set("status_aura",true); break; case true: graphic.set("status_aura","2"); break; case "2": graphic.set("status_aura","3"); break; default: return; } } }, changePenaltyStatus: function(object, previous){ //Spend five or more peripheral motes, get more anima. var graphic = findObjs({ _represents: object.get("characterid"), _type: "graphic", _pageid: Campaign().get("playerpageid"), layer: "objects" }); var graphic = graphic[0]; if (graphic == undefined ) return; if (object.get("current") >= 0 || object.get("current") < -9) graphic.set("status_red",false); else (graphic.set("status_red",-object.get("current"))); }, ClearStatus: function(status){ var graphic = findObjs({ _pageid: Campaign().get("playerpageid"), _type: "graphic", layer: "objects", }); switch (status) { case "onslaught": _.each(graphic, function (graphic){ graphic.set("status_purplemarker",false); }); exaltScript.NotifyChange("Onslaught cleared","none"); break; case "anima": _.each(graphic, function (graphic){ graphic.set("status_aura",false); }); exaltScript.NotifyChange("Anima cleared","none"); break; } }, updateStatuses: function(obj, lastPage){ var oldGraphic = findObjs({ _pageid: lastPage.playerpageid, _type: "graphic", layer: "objects", }); var newGraphic = findObjs({ _pageid: Campaign().get("playerpageid"), _type: "graphic", layer: "objects", }); _.each(oldGraphic, function (oldGraphic) { _.each(newGraphic,function(newGraphic){ if(oldGraphic.get("represents") == newGraphic.get("represents") && oldGraphic.get("represents") != ""){ newGraphic.set("status_aura",oldGraphic.get("status_aura")); newGraphic.set("status_red",oldGraphic.get("status_red")); newGraphic.set("status_purple",oldGraphic.get("status_purple")); } }); }); }, ToggleAnima: function(){ if(state.doAnima == false) state.doAnima = true; else state.doAnima = false; exaltScript.NotifyChange("Anima Increaser",state.doAnima); }, ToggleInitiative: function(){ if(state.doInitiative == false) state.doInitiative = true; else state.doInitiative = false; exaltScript.NotifyChange("Initiative Tracker",state.doInitiative); }, ToggleNotifications: function(){ if(state.doNotifications == false) state.doNotifications = true; else state.doNotifications = false; exaltScript.NotifyChange("Notifications",state.doNotifications); }, ToggleStatusmigration: function(){ if(state.doStatusSwitch == false) state.doStatusSwitch = true; else state.doStatusSwitch = false; exaltScript.NotifyChange("Status Migration",state.doStatusSwitch); }, ToggleWoundtracker: function(){ if(state.doWoundtracker == false) state.doWoundtracker = true; else state.doWoundtracker = false; exaltScript.NotifyChange("Wound Tracker",state.doWoundtracker); }, DisplayInterface: function(target,condensed){ if (state.doAnima == false){ animaColor = "#FF0000"; } else animaColor = "#6B8E23"; if (state.doInitiative == false){ initiativeColor = "#FF0000"; } else initiativeColor = "#6B8E23"; if (state.doNotifications == false){ notificationColor = "#FF0000"; } else notificationColor = "#6B8E23"; if (state.doStatusSwitch == false){ migrationColor = "#FF0000"; } else migrationColor = "#6B8E23"; if (state.doWoundtracker == false){ woundpenaltyColor = "#FF0000"; } else woundpenaltyColor = "#6B8E23"; if(condensed == false) sendChat('exaltScript','/w ' +target +'
'
+'
'
+'