/*
* Version 0.1.2
* Made By Robin Kuiper
* Skype: RobinKuiper.eu
* Discord: Atheos#1095
* My Discord Server: https://discord.gg/AcC9VME
* Roll20: https://app.roll20.net/users/1226016/robin
* Github: https://github.com/RobinKuiper/Roll20APIScripts
* Reddit: https://www.reddit.com/user/robinkuiper/
* Patreon: https://patreon.com/robinkuiper
* Paypal.me: https://www.paypal.me/robinkuiper
*/
var AlignmentTracker = AlignmentTracker || (function() {
'use strict';
// Styling for the chat responses.
const styles = {
reset: 'padding: 0; margin: 0;',
menu: 'background-color: #fff; border: 1px solid #000; padding: 5px; border-radius: 5px;',
button: 'background-color: #000; border: 1px solid #292929; border-radius: 3px; padding: 5px; color: #fff; text-align: center;',
list: 'list-style: none;',
float: {
right: 'float: right;',
left: 'float: left;'
},
overflow: 'overflow: hidden;',
fullWidth: 'width: 100%;',
underline: 'text-decoration: underline;',
strikethrough: 'text-decoration: strikethrough'
},
script_name = 'AlignmentTracker',
state_name = 'ALIGNMENTTRACKER',
createRange = (start, end) => {
return Array(end - start + 1).fill().map((_, idx) => start + idx)
},
alignment_positions = {
x: [
{ range: createRange(0, 11), name: 'Lawful' },
{ range: createRange(12, 22), name: 'Neutral' },
{ range: createRange(23, 33), name: 'Chaotic' }
],
y: [
{ range: createRange(0, 11), name: 'Good' },
{ range: createRange(12, 22), name: 'Neutral' },
{ range: createRange(23, 33), name: 'Evil' }
]
},
handleInput = (msg) => {
if (msg.type != 'api') return;
if(!playerIsGM(msg.playerid)) return;
// Split the message into command and argument(s)
let args = msg.content.split(' ');
let command = args.shift().substring(1);
let extracommand = args.shift();
if (command == state[state_name].config.command) {
switch(extracommand){
case 'reset':
state[state_name] = { version: "0.1.2" };
setDefaults(true);
sendConfigMenu();
break;
case 'config':
if(args.length > 0){
let setting = args.shift().split('|');
let key = setting.shift();
let value = (setting[0] === 'true') ? true : (setting[0] === 'false') ? false : setting[0];
state[state_name].config[key] = value;
}
sendConfigMenu();
break;
case 'create':
// TODO: if not selected
msg.selected.forEach(s => {
if(s._type !== 'graphic'){
makeAndSendMenu('This is not a valid token.', '', 'gm');
return;
}
let character = getObj('character', getObj(s._type, s._id).get('represents'));
if(character)
createTable(character);
else{
makeAndSendMenu('This token does not represent a character.', '', 'gm');
}
})
break;
case 'change-alignment':
// TODO: if not selected
let newAlignment = args.shift();
msg.selected.forEach(s => {
let character = getObj('character', getObj(s._type, s._id).get('represents'));
changeAlignment(character, newAlignment);
})
break;
case 'change':
// TODO: if not selected
let morality = args.shift(),
lawfulness = args.shift();
msg.selected.forEach(s => {
let character = getObj('character', getObj(s._type, s._id).get('represents'));
changePosition(character, morality, lawfulness);
})
break;
case 'get':
let chat_text = '';
msg.selected.forEach(s => {
let character = getObj('character', getObj(s._type, s._id).get('represents'));
chat_text += ''+character.get('name')+': ' + getCharacterAlignment(character) + '
';
});
makeAndSendMenu(chat_text, 'Alignment(s)', 'gm');
break;
default:
sendConfigMenu();
break;
}
}
},
changePosition = (character, morality, lawfulness) => {
morality = parseInt(morality); lawfulness = parseInt(lawfulness);
// TODO: Check boundaries
let position = getCharacterAlignmentPosition(character),
x = position.x,
y = position.y;
if(morality){
if(morality + position.x < 0){
x = 0;
}else if(morality + position.x > 32){
x = 32;
}else{
x = morality + position.x;
}
}
if(lawfulness){
if(lawfulness + position.y < 0){
y = 0;
}else if(lawfulness + position.y > 32){
y = 32;
}else{
y = lawfulness + position.y;
}
}
changeAlignment(character, { x, y });
},
changeAlignment = (character, newAlignment) => {
let position;
if(typeof newAlignment === 'object' && newAlignment.x >= 0 && newAlignment.y >= 0){
position = newAlignment;
}else{
position = getPositionFromAlignment(newAlignment);
}
// Set State
state[state_name].characters[strip(character.get('name')).toLowerCase()] = position;
// Set Attribute
let attributes = {};
attributes[state[state_name].config.alignment_attribute] = getAlignmentFromPosition(position);
setAttrs(character.get('id'), attributes);
// Create Table
createTable(character);
},
getCharacterAlignmentPosition = (character) => {
let name = strip(character.get('name')).toLowerCase();
if(!state[state_name].characters[name]){
let alignment = getAttrByName(character.get('id'), state[state_name].config.alignment_attribute, 'current') || '';
state[state_name].characters[name] = getPositionFromAlignment(alignment);
}
return state[state_name].characters[name];
},
getCharacterAlignment = (character) => {
return getAttrByName(character.get('id'), state[state_name].config.alignment_attribute, 'current') || '';
},
getPositionFromAlignment = (alignment) => {
alignment = strip(alignment).toLowerCase();
switch(alignment){
case 'cg': case 'lawfulgood':
return { x: 5, y: 5 };
break;
case 'cn': case 'lawfulneutral':
return { x: 5, y: 16 };
break;
case 'ce': case 'lawfulevil':
return { x: 5, y: 27 };
break;
case 'ng': case 'neutralgood':
return { x: 16, y: 5 };
break;
case 'nn': case 'neutralneutral': case 'tn': case 'trueneutral': case 'neutral':
return { x: 16, y: 16 };
break;
case 'ne': case 'neutralevil':
return { x: 16, y: 27 };
break;
case 'lg': case 'chaoticgood':
return { x: 27, y: 5 };
break;
case 'ln': case 'chaoticneutral':
return { x: 27, y: 16 };
break;
case 'le': case 'chaoticevil':
return { x: 27, y: 27 };
break;
}
// TODO: NOT FOUND SHIT
},
createTable = (character) => {
const border= '2px dotted black',
position = getCharacterAlignmentPosition(character);
let style, mark = '';
if(!position){
makeAndSendMenu(character.get('name') + " doesn't have an alignment. I did not create a table for him/her.");
return;
}
let table = ' \
| \ | Lawful | \Neutral | \Chaotic | \||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Good | '; } if(row === 11){ table += 'Neutral | '; } if(row === 22){ table += 'Evil | '; } for(var column = 0; column <= 32; column++){ style = ''; mark = '' if(column === 11 || column === 22) style += 'border-left: '+border+';'; if(row === 11 || row === 22) style += 'border-top: '+border+';'; if(column === position.x && row === position.y) mark = 'X'; table += ''+mark+' | '; } table += '||||||||||||||||||||||||||||||
'+message+'
' : ''; let contents = message+makeList(listItems, styles.reset + styles.list + styles.overflow, styles.overflow)+'You can always come back to this config by typing `!'+state[state_name].config.command+' config`.