This is a relatively large script that incorporates some other peoples work with my own and helps DM's to run combat. There might of been others like it befor but this is mine. If anyone thinks theres something I should add i'll be happy to give it a try. //API script designed to aid in combat situations
//--------------------------------------------------------//
//Features:
// 4 Command with configaruble right so playes may use them:
// !HIT
// !HITCHECK
// !DMG
// !HEAL
// Configrable combat states
//--------------------------------------------------------//
//For the !HIT fucntion 4 veribls need to be passed in this order
// 1. Defender Token_id
// 2. Defence type used (ac/fort/ref/will)
// 3. The moderfier to hit
// 4. The attack roll (xdx+mod : 2d8+5)
//This is the macro I use:
// !HIT @{target|token_id} ?{Defence|ac} ?{mod|0} ?{Attack|xdx+mod}
//Example of what this translats
// 12 vs AC, damage: 1d8+6
//--------------------------------------------------------//
//For the !HITCHECK fucntion 3 veribls need to be passed in this order
//The diffrence between HIT and HITCHECK, HITCHECK will announce to everyone if they hit or miss
// 1. Defender Token_id
// 2. Defence type used (ac/fort/ref/will)
// 3. The moderfier to hit
//This is the macro I use:
// !HIT @{target|token_id} ?{Defence|ac} ?{mod|0}
//Example of what this translats
// 12 vs AC, damage: 1d8+6
//--------------------------------------------------------//
//For the !DMG function 2 veribles need to be passed in this order
// 1. Token_id
// 2. Damage to be delt
//This is the macro i use:
// !DMG @{target|token_id} ?{damage?}
//--------------------------------------------------------//
//For the !HEAL function 2 veribles need to be passed in this order
// 1. Token_id
// 2. Damage to be delt
//This is the macro i use:
// !HEAL @{target|token_id} ?{healing?}
//--------------------------------------------------------//
//
// Set various token markers based on bar cur/max ratios
//
// The CONFIG array can have any number of configuration objects. These objects
// are processed in order.
//
// barId - The ID of the bar to look at the values for [1, 2, 3]
// barRatio - The ratio of bar value to max value that triggers setting the status marker [0 - 1]
// status - The name of the status marker to toggle [redmarker, bluemarker, greenmarker, brownmarker, purplemarker, dead]
// whenLow - The state of the marker when the bar value is <= the ratio [true, false]
//--------------------------------------------------------//
var combat = combat || {
version: 1.1,
//message to be loggad at the start of the log (%count is replased for logCount)
logLabel: "Combat event %count: ",
logCount: 0,
//controls who has the rights to use the commands (I leave them as gm only)
useRights: true, //set to true if you want right to be checked
commandHitRights: [
{command: "HIT", rights: "Jacob "}, /*Your name must be added hear*/
{command: "DMG", rights: "Jacob "},
{command: "HEAL", rights: "Jacob "},
],
hasRights: false, //internal verible
informGM: true, //true if you want the gm to be informed when players try and use a command
announceHitCheck: true,
//hold infomatoin about player using the mothod
playerObject: "",
playerName: "",
//array used to cofig states
stateConfig: [
{barId: 1, barRatio: .5, status: "redmarker", whenLow: true},
{barId: 1, barRatio: 0, status: "dead", whenLow: true},
],
//method to log an event and count the mesages sent
logEvent: function(event,DMchatLog,announce) {
//set default values if not value sent
event = event || "No event sent";
DMchatLog = DMchatLog || false;
announce = announce || false;
//set current value
var label = combat.logLabel.replace("%count", combat.logCount);
combat.logCount++;
log(label+event);
//send event to GM if chatlog is true defalts as false and to players if anounnce is true
if(DMchatLog == true && announce == true) {
sendChat(label, event);
}
else if (DMchatLog == true) {
label = label.replace(":", "");
sendChat(label, "/w gm "+event);
}
},
//cheacks if the player sending the command has the rights to use it
checkRights: function(command) {
//reset has rights to defalt
combat.hasRights = false;
if (combat.useRights == false) return;
//set command hit rights to
combat.commandHitRights.forEach(function(opts) {
if(opts.command == command) {
if(opts.rights.search(combat.playerName) != -1) {
combat.hasRights = true;
}
}
})
if(combat.hasRights == false) {
combat.logEvent(combat.playerName+" tryed to use command "+command , combat.informGM);
return;
}
},
//use the playerID to get the players object and name and log them in the veribles
findPlayer: function(playerID) {
combat.playerObject = getObj('player', playerID);
combat.playerName = combat.playerObject.get("_displayname")
},
//checks if health has changed to be above or below threshold state
setState: function(obj) {
//log state changeing
combat.logEvent("Setting state")
combat.stateConfig.forEach(function(opts) {
var maxValue = parseInt(obj.get("bar" + opts.barId + "_max"));
var curValue = parseInt(obj.get("bar" + opts.barId + "_value"));
//log(opts.barId + ": " + curValue + "/" + maxValue);
if (!isNaN(maxValue) && !isNaN(curValue)) {
var markerName = "status_" + opts.status;
if (curValue <= (maxValue * opts.barRatio)) {
obj.set(markerName, opts.whenLow);
}
else {
obj.set(markerName, !opts.whenLow);
}
}
});
},
//find the command and determin if the player has rights then run with nesery infomation
findCommand: function(obj) {
// Exit if not an api command
if (obj.type != "api") return;
// Get the API Chat Command and split up message
var command = obj.content.split(" ");
//get player ID and log name
combat.findPlayer(obj.playerid);
combat.logEvent("Command Reseaved from "+combat.playerName+" : "+command)
if(command[0] == '!HIT') {
//check player have the rights to use the command
combat.checkRights('HIT')
if(combat.hasRights == false) return;
//run the command
combat.HIT(command);
return;
} else if(command[0] == '!DMG') {
combat.checkRights('DMG')
if(combat.hasRights == false) return;
//run the command
combat.DMG(command);
} else if(command[0] == '!HEAL') {
combat.checkRights('HEAL')
if(combat.hasRights == false) return;
//run the command
combat.HEAL(command);
} else if(command[0] == '!HITCHECK') {
//run the command
combat.HITCHECK(command);
} else {
combat.logEvent("No command found for "+command[0])
}
},
//evaluate an attribute and return the value for this, the functoin must have the correct characterID or will return incorect value
evaluateAttribute: function(characterID,attribute) {
//get array form attribute used
var attributeValue = 0;
//get the string with for the attribute wanted
var attributeString = getAttrByName(characterID, attribute);
combat.logEvent("Attribute: "+attribute+" string: "+attributeString)
attributeString = attributeString.split("+");
do {
var buffer = "";
var i = 0;
attributeString.forEach(function(opts) {
//eseption to find half level
if(attributeString[i].search("@{halflevel}") != -1)
{
attributeValue += Math.floor(Number(getAttrByName(characterID, "level"))/2);
}
//eseption to find def-highest ((dex/con/char/dex) - 10)/2
else if(attributeString[i].search("highest}") != -1)
{
if(attributeString[i].search("ac") != -1)
attributeValue += Math.floor(Number(getAttrByName(characterID, "dexterity") - 10)/2);
else if(attributeString[i].search("fort") != -1)
attributeValue += Math.floor(Number(getAttrByName(characterID, "constitution") - 10)/2);
else if(attributeString[i].search("will") != -1)
attributeValue += Math.floor(Number(getAttrByName(characterID, "charisma") - 10)/2);
else if(attributeString[i].search("ref") != -1)
attributeValue += Math.floor(Number(getAttrByName(characterID, "dexterity") - 10)/2);
else
log("unusual value for 'highest'} :"+attributeString[i]); //catchs invaled input
}
//check if an attribute needs to be found and find it
else if(attributeString[i].search("@{") != -1)
{
attributeString[i] = attributeString[i].replace("@{", "");
attributeString[i] = attributeString[i].replace("}", "");
var temp = getAttrByName(characterID, attributeString[i]);
//if temp is another attrabut store it in buffer
if(temp.search("@{") != -1)
{
buffer += temp;
buffer += " ";
}
else // if temp is a value add it to defence
{
//only add it to defence if the valse is grater then 0 this also cathes null values
if(temp > 0)
{
attributeValue += Number(temp);
}
}
}
else //if the target is anything else it must be a number so add it to defence
{
attributeValue += Number(attributeString[i]);
}
i++;
});
//seperate buffer into an array then save it the defence
buffer = buffer.replace("+", " ");
buffer = buffer.split(" ");
attributeString = buffer;
} while(buffer.length > 1)
return attributeValue
},
//method to find roll value from a string ie 2d20+10
roll: function(string) {
var roll = string.replace(" ", "");
combat.logEvent("rolling: "+roll)
var rollTotal = 0;
roll = roll.split("+");
var i = 0;
roll.forEach(function(opts) {
//if there is a dice roll the dice and add to total
if(roll[i].search("d") != -1)
{
//This splits xdx into x * dx where dx is the dice rolled and x in the number of dice
var buffer = roll[i].split("d");
for(i = 0; i < buffer[0]; i++)
rollTotal += randomInteger(Number(buffer[1]));
}
//else add the value on to the total
else
{
rollTotal += Number(roll[i]);
}
});
return rollTotal
},
//method to check if a character has hit this will find the attack then roll for the damage in this form damage is just returnet in the chat
//you can at the !DMG command to take the damage off although I wouldn't recomend this because somethins you might want to smuge a roll
//you can just use the !DMG command to take the damage you want
HIT: function(command) {
combat.logEvent("Hit began")
//target character
var token = getObj("graphic", command[1]);
var character = token.get("represents");
//evaluate the attribute for defence and roll for attack
var defence = combat.evaluateAttribute(character,command[2]);
var attack = randomInteger(20) + Number(command[3]);
if(attack > defence)
{
combat.logEvent("Attack hit: "+attack+">"+defence+"("+command[2]+")", true);
//calculate damage done
var damage = combat.roll(command[4]);
combat.logEvent("Damage: "+damage, true);
}
else
{
combat.logEvent("Attack missed: "+attack+"<"+defence);
combat.logEvent("Attack missed", true)
}
},
//Hit check is the same as hit but dose not roll for damage automoticly and anouns to everyone if they hit or miss
//this is instnded for player use and not just GM use
HITCHECK: function(command) {
combat.logEvent("Hit Check began")
//target character
var token = getObj("graphic", command[1]);
var character = token.get("represents");
//evaluate the attribute for defence and roll for attack
var defence = combat.evaluateAttribute(character,command[2]);
var attack = randomInteger(20) + Number(command[3]);
if(attack > defence)
{
combat.logEvent("Attack hit: "+attack+">"+defence+"("+command[2]+")", true, combat.announceHitCheck);
}
else
{
combat.logEvent("Attack missed: "+attack+"<"+defence);
combat.logEvent("Attack missed", true, combat.announceHitCheck)
}
},
DMG: function(command) {
var current_token = getObj("graphic", command[1]);
//read max hp and current hp along with damage need
var maxValue = Number(current_token.get("bar1_max"));
var curValue = Number(current_token.get("bar1_value"));
var damage = Number(command[2]);
var damageDone;
//deside damage to be delt and if below 0-max/2 ie blooded set to 0;
var newValue = curValue - damage;
if(newValue <= 0-maxValue/2){newValue = 0-maxValue/2;};
damageDone = curValue - newValue;
sendChat("GM", "/desc "+damageDone+"("+damage+") damage was delt");
current_token.set({
"bar1_value": newValue
});
//set state with new values
combat.setState(current_token);
},
HEAL: function(command) {
var current_token = getObj("graphic", command[1]);
//read max hp and current hp along with damage need
var maxValue = current_token.get("bar1_max");
var curValue = Number(current_token.get("bar1_value"));
var healing = Number(command[2]);
var healingDone;
//heal from 0
if(curValue < 0) curValue = 0;
var newValue = curValue + healing;
if(newValue > maxValue){newValue = maxValue;};
healingDone = newValue - curValue;
sendChat("GM", "/desc "+healingDone+"("+healing+") healing done");
current_token.set({
"bar1_value": newValue
});
//set state with new values
combat.setState(current_token);
},
//regesters event handalers this must be run on ready
registerEventHandlers: function() {
combat.logEvent("Events Registered", true);
on('chat:message', combat.findCommand);
on("change:token", combat.setState);
},
};
on('ready',function() {
combat.logEvent("API Running version: "+combat.version);
combat.registerEventHandlers();
});
If anyone has noticed there work thankyou, I probably used it to learn javascript