Last active
June 21, 2017 17:09
-
-
Save SteveKoontz/6953050 to your computer and use it in GitHub Desktop.
roll20.net World of Darkness God Machine Chronicle Scripts
This file contains hidden or 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
// WoD Damage/Status Tracker v1.2 | |
// Bashing, Lethal, and Aggrivated damage are marked on the selected token | |
// The 'API' commands are, "!b", "!l", "!a" respectively. | |
// I.E. "!b 3" would put 3 bashing on the token. | |
// If there is a character attached to the token and it has the attirbutes 'Bashing','Lethal','Aggrivated','Health','Vitae' | |
// then the script will record and update the sheet as well as automatically applying a wound penalty status icon. | |
// The status icons being used are Bashing = 'fist', Lethal = 'skull', Aggrivated = 'chemical-bolt', Wounded = 'pummeled' | |
on('chat:message', function(msg) { | |
if(msg.type != 'api') return; | |
var parts = msg.content.toLowerCase().split(' '); | |
var command = parts.shift().substring(1); | |
var selected = msg.selected; | |
if(!selected) return; // have one or more things selected | |
var damage = +parts[0]; | |
if(!damage) damage = 0; // if no damage is returned, treat as 0 | |
_.each(selected, function(obj) { | |
if(obj._type != 'graphic') return; // only damage graphics | |
var tok = getObj("graphic", obj._id); | |
if(tok.get('subtype') != 'token') return; // don't try to damage cards | |
var oCharacter = getObj("character", tok.get("represents")); | |
if (oCharacter != undefined ) { | |
oBashing = findObjs({name: "Bashing",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; | |
oLethal = findObjs({name: "Lethal",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; | |
oAggrivated = findObjs({name: "Aggrivated",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; | |
oHealth = findObjs({name: "Health",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; | |
oVitae = findObjs({name: "Vitae",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; | |
if (command == 'b') var oDmg = oBashing | |
else if (command == 'l') var oDmg = oLethal | |
else if (command == 'a') var oDmg = oAggrivated | |
} | |
if (oDmg != undefined ) { | |
oDmg.set('current', damage); | |
if (oBashing != undefined && oLethal != undefined && oAggrivated != undefined && oHealth != undefined) { | |
Clear_Status(tok); | |
Status_wSheet(tok,oBashing,oLethal,oAggrivated,oHealth,oVitae)}; } | |
else {Status_woSheet(tok,command,damage) } | |
}); | |
}); | |
// Update changes from sheet on token update | |
on('change:token', function(tok) { | |
var oCharacter = getObj("character", tok.get("represents")); | |
if (oCharacter != undefined ) { | |
oBashing = findObjs({name: "Bashing",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; | |
oLethal = findObjs({name: "Lethal",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; | |
oAggrivated = findObjs({name: "Aggrivated",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; | |
oHealth = findObjs({name: "Health",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; | |
oVitae = findObjs({name: "Vitae",_type: "attribute", _characterid: oCharacter.id}, {caseInsensitive: true})[0]; } | |
if (oBashing != undefined && oLethal != undefined && oAggrivated != undefined && oHealth != undefined) { | |
Clear_Status(tok); | |
Status_wSheet(tok,oBashing,oLethal,oAggrivated,oHealth,oVitae)} | |
else {Status_woSheet(tok) }; | |
}); | |
// Apply Status for a token assigned to a functional Character Sheet | |
function Status_wSheet(tok,oBashing,oLethal,oAggrivated,oHealth,oVitae) { | |
// Check if Hungry or Starving | |
if (oVitae != undefined ) { | |
if (oVitae.get('current') <= 0) {tok.set('status_half-heart', '2')} | |
else if (oVitae.get('current') <= 4) {tok.set('status_half-heart', '1')} }; | |
// Check for Wound Penalties | |
var oEffHealth = parseInt((oHealth.get('current')),10) - (parseInt((oBashing.get('current')),10) + parseInt((oLethal.get('current')),10) + parseInt((oAggrivated.get('current')),10)) | |
var oCrtHealth = parseInt((oHealth.get('current')),10) - (parseInt((oLethal.get('current')),10) + parseInt((oAggrivated.get('current')),10)) | |
if(oCrtHealth <= 0) {tok.set('status_dead', true)} | |
else if(oEffHealth == 2) {tok.set('status_pummeled', '1');} | |
else if(oEffHealth == 1) {tok.set('status_pummeled', '2');} | |
else if(oEffHealth <= 0) {tok.set('status_pummeled', '3');}; | |
// Set Damage in correct order | |
if (oBashing.get('current') > 0) {Apply_Damage(tok,oBashing.get('current'),'fist')}; | |
if (oLethal.get('current') > 0) {Apply_Damage(tok,oLethal.get('current'),'skull')}; | |
if (oAggrivated.get('current') > 0) {Apply_Damage(tok,oAggrivated.get('current'),'chemical-bolt')}; | |
} | |
// Apply Status for a token without a Character Sheet | |
function Status_woSheet(tok,command,damage) { | |
if (command == 'b') {tok.set('status_fist', false); | |
Apply_Damage(tok,damage,'fist')} | |
else if (command == 'l') {tok.set('status_skull', false); | |
Apply_Damage(tok,damage,'skull')} | |
else if (command == 'a') {tok.set('status_chemical-bolt', false); | |
Apply_Damage(tok,damage,'chemical-bolt')}; | |
} | |
function Clear_Status(tok) { | |
tok.set('status_fist', false); | |
tok.set('status_skull', false); | |
tok.set('status_chemical-bolt', false); | |
tok.set('status_pummeled', false); | |
tok.set('status_red', false); | |
tok.set('status_half-heart', false); | |
tok.set('status_dead', false); | |
} | |
function Apply_Damage(tok,damage,icontype) { | |
var dmgicon = ''; | |
while(damage > 0) | |
{ | |
// get current digit, starting from ones | |
var digit = damage / 10; | |
digit -= Math.floor(digit); | |
digit = Math.round(digit * 10); | |
// shift damage | |
damage = Math.floor(damage / 10); | |
dmgicon += icontype+'@'+digit+','; | |
} | |
if(dmgicon.length > 0) dmgicon = dmgicon.substring(0, dmgicon.length - 1); // trim trailing comma | |
var markers = tok.get('statusmarkers'); | |
if(markers != '') markers += ','; | |
markers += dmgicon; | |
tok.set('statusmarkers', markers); | |
} |
This file contains hidden or 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
// WoD Auto Sheet v1.0 | |
// The sheet is using the latest God Machine and Strix Chronciles rules and attributes. | |
// The script is called by the 'API' command of !sheet (Character Name) (template type). | |
// I.E. "!sheet Testy McTesterson vampire" | |
// The command only works on pre-existing characters created in the journal. | |
// I've only created two templates (mortal,vampire) | |
attributes = [ | |
'Intelligence','Wits','Resolve', | |
'Strength','Dexterity','Stamina', | |
'Presence','Manipulation','Composure' | |
]; | |
skills_mental = [ | |
'Academics','Computer','Crafts','Investigation','Medicine','Occult','Politics','Science' | |
] | |
skills_other = [ | |
'Athletics','Brawl','Drive','Firearms','Larceny','Stealth','Survival','Weaponry', | |
'Animal Ken','Empathy','Expression','Intimidation','Persuasion','Socialize','Streetwise','Subterfuge' | |
] | |
other = [ | |
'Health','Bashing','Lethal','Aggrivated','Willpower','Size','Speed','Defense','Initiative','Armor','Armor-Balistic','Fast Reflexes' | |
] | |
mortal = [ | |
'Virtue','Vice','Concept','Integrity' | |
] | |
vampire = [ | |
'Mask','Dirge','Concept','Clan','Bloodline','Covenant','Humanity','Blood Potency','Vitae' | |
] | |
disciplines = [ | |
'Animalism','Auspex','Celerity','Dominate','Majesty','Nightmare','Obfuscate','Protean','Resilience','Vigor' | |
] | |
on('chat:message', function(msg) { | |
if(msg.type != 'api') return; | |
var oParts = msg.content.toLowerCase().split(' '); | |
var oCommand = oParts.shift().substring(1); | |
if(oCommand != 'sheet') return; //Confirms the message used the '!sheet' command | |
var oTemplate = oParts.pop(); //Pulls the template setting from the API command | |
if (oParts.length > 0) { | |
oCharName = oParts[0]; // Recombine the name if it's more than one word | |
for (i=1; i<oParts.length; i++) { | |
oCharName = oCharName + ' ' + oParts[i];} | |
} | |
else {oCharName = oParts}; | |
if(!oCharName) { | |
sendChat('System', 'Error: No character name given'); //Returns an error if no character name was chosen | |
return;}; | |
var oChar = findObjs({name: oCharName, _type: 'character'}, {caseInsensitive: true})[0]; //Finds the character object | |
if(oChar == undefined) { | |
sendChat('System', 'Error: No character by the name of ' + oCharName + ' found.'); | |
return;}; | |
if (oTemplate == undefined || oTemplate == 'mortal') { //Checks which template of stats you want to add | |
CheckAddAttr(oChar,mortal,'','');} | |
else if (oTemplate == 'vampire') { | |
CheckAddAttr(oChar,vampire,'','');} | |
else {sendChat('System', 'Error: Invalid Template ' + oTemplate); | |
return;} | |
CheckAddAttr(oChar,attributes,'1','5'); // Add Attributes to character sheet | |
CheckAddAttr(oChar,skills_mental,'-3','5'); // Add Mental skills to character sheet | |
CheckAddAttr(oChar,skills_other,'-1','5'); // Add Physical and Social skills to character sheet | |
CheckAddAttr(oChar,other,'0',''); // Add Other Traits to character sheet | |
if (oTemplate == 'vampire') { | |
CheckAddAttr(oChar,disciplines,'0','5');} // Add disciplines to the vampire template | |
CheckAddAbil(oChar,'Chance','/r {1d10!}>10'); // Adding macros of useful rolls to character sheet. | |
CheckAddAbil(oChar,'Normal-Roll','/r {?{Number of Dice to Roll}d10!}>8'); | |
CheckAddAbil(oChar,'9-Again-Roll','/r {?{Number of Dice to Roll}d10!>9}>8'); | |
CheckAddAbil(oChar,'8-Again-Roll','/r {?{Number of Dice to Roll}d10!>8}>8'); | |
CheckAddAbil(oChar,'Initiative','/em @{selected|token_name} rolls initiative.\n/r 1d10+@{selected|Initiative}+@{selected|Fast Reflexes}-?{Weapon Initiative Penalty|0} &{tracker}'); | |
CheckAddAbil(oChar,'Perception','/me rolls for Perception.\n/r {(@{Wits}+@{Composure}+@{Auspex}+?{Modifier|0})d10!}>8'); | |
if (oTemplate == 'vampire') {CheckAddAbil(oChar,'Full-Dodge','/me full dodges!\n/r {(((@{Defense}+@{Celerity})*2)+?{Modifier|0})d10!}>8');} | |
else {CheckAddAbil(oChar,'Full-Dodge','/me full dodges!\n/r {((@{Defense}*2)+?{Modifier|0})d10!}>8');}; | |
if (oTemplate == 'vampire') { | |
CheckAddAbil(oChar,'Will/Degeneration/Frenzy','/me makes a will check.\n/r {(@{Resolve}+@{Composure}+?{Modifier|0})d10!}>8');} | |
else {CheckAddAbil(oChar,'Will-Check','/me makes a will check.\n/r {(@{Resolve}+@{Composure}+?{Modifier|0})d10!}>8');} | |
sendChat('System', 'You have successfully added the ' + oTemplate + ' template to ' + oCharName + '.'); | |
}); | |
function CheckAddAttr(oChar, oNames, oCur, oMax) { | |
_.each(oNames, function(oName){ | |
var oAttrChk = findObjs({_type: 'attribute', _characterid: oChar.id, name: oName})[0]; | |
if (oAttrChk == undefined) {createObj('attribute', {name: oName, current: oCur, max: oMax, characterid: oChar.id}) }; | |
}); | |
} | |
function CheckAddAbil(oChar, oNames, oAction) { | |
var oAbilChk = findObjs({_type: 'ability', _characterid: oChar.id, name: oNames})[0]; | |
if (oAbilChk == undefined) {createObj('ability', {name: oNames, characterid: oChar.id, action: oAction}) }; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment