Files
roll20-character-sheets-tester/TailsOfEquestria/js/worker.js
T

311 lines
7.2 KiB
JavaScript

/**
* Forces an update on a list of numerical fields, also making sure that
* any undefined fields are set to 0.
* @param {string[]} attrs
* @param {function} cb
*/
function forceUpdate(attrs, cb) {
parseAttrs(attrs, values => {
let tempValues = {};
_.each(attrs, attr => {
tempValues[attr] = -9999;
});
setAttrs(tempValues);
setAttrs(values);
});
}
function getRollDiceCount(roll) {
// Extract each die type used in the roll.
var regex = /{(.+?)}k1/;
var match = regex.exec(roll);
if(match)
roll = match[1];
var dice = roll.split(',');
// Count the number of each die type.
var diceCount = {
'D20': 0,
'D12': 0,
'D10': 0,
'D8': 0,
'D6': 0,
'D4': 0
};
_.each(dice, die => {
diceCount[die]++;
});
return diceCount;
}
/**
* Gets the view for some dice value.
* @param {string} roll
* @return {string}
*/
function getRollView(roll) {
var diceCount = getRollDiceCount(roll);
// Produce the appropriate view based on the dice counts.
var view = '';
_.each(['D20', 'D12', 'D10', 'D8', 'D6', 'D4'], die => {
var count = diceCount[die];
if(view && count > 0)
view += '+';
if(count === 1)
view += die;
else if(count > 1)
view += `${count}${die}`;
});
return view;
}
/**
* Gets the upgraded/downgraded dice for a roll.
* @param {string} roll
* The roll expression.
* @param {int} steps
* Positive for upgrade, negative for downgrade.
*/
function getUpDowngradedRoll(roll, steps) {
var diceCount = getRollDiceCount(roll);
// Derive a numerical value for the dice that can be incremented up and down
// by upgrades and downgrades.
var diceValue = diceCount['D20']*6;
var smallDice = ['', 'D4', 'D6', 'D8', 'D10', 'D12'];
_.find(smallDice, (die, index) => {
if(diceCount[die] > 0) {
diceValue += index;
return true;
}
});
// Apply the upgrade/downgrade.
diceValue = Math.max(1, diceValue + steps);
// Change the value back into dice.
var d20Count = Math.floor(diceValue/6);
var smallDieIndex = diceValue%6;
var smallDie = smallDice[smallDieIndex];
// Compose the new roll string.
var diceList = [];
_.each(_.range(d20Count), i => {
diceList.push('D20');
});
if(smallDie)
diceList.push(smallDie);
return `{${diceList.join(',')}}k1`;
}
function onChange(attrs, cb) {
attrs = _.map(attrs, attr => {
return 'change:' + attr;
}).join(' ');
on(attrs, cb);
}
function onChangeParse(attrs, cb) {
onChange(attrs, () => {
parseAttrs(attrs, cb);
});
}
/**
* Gets the specified attributes and parses them as an integer or 0.
*/
function parseAttrs(attrs, cb) {
getAttrs(attrs, function(values) {
_.each(attrs, function(attr) {
if(_.isUndefined(values[attr]))
values[attr] = 0;
else if(!isNaN(values[attr]))
values[attr] = parseInt(values[attr]);
});
cb(values);
});
}
function updateCutieMarkTalent() {
var prefix = 'talent_cutieMark';
_updateTalents(prefix);
}
function updateRacialTalent() {
var prefix = 'talent_racial';
_updateTalents(prefix);
}
function updateTalents() {
updateCutieMarkTalent();
updateRacialTalent();
getSectionIDs('repeating_talents', ids => {
_.each(ids, id => {
var prefix = 'repeating_talents_' + id;
_updateTalents(prefix);
});
});
}
function _updateTalents(prefix) {
// If we just up-ticked or down-ticked the up/downgrade, then quit early
// after handling that.
if(_tickDowngrade(prefix) || _tickUpgrade(prefix))
return;
parseAttrs([prefix + '_name', prefix + '_dice', prefix + '_trait', prefix + '_updowngrade', 'body_equation', 'mind_equation', 'charm_equation'], values => {
var talentName = values[prefix + '_name'];
var talentDice = values[prefix + '_dice'];
var trait = values[prefix + '_trait'];
var traitDice = values[trait + '_equation'] || 'D0';
var updown = parseInt(values[prefix + '_updowngrade']) || 0;
// Apply upgrades/downgrades to talent dice.
var talentDiceModified = talentDice;
if(talentDice && updown)
talentDiceModified = getUpDowngradedRoll(talentDice, updown);
var talentDiceView = getRollView(talentDice);
if(talentDiceModified === 'null')
setAttrs({
[prefix + '_equation']: 0,
[prefix + '_readOnlyView']: `${talentName}(n/a)`
});
else {
//var traitDice = values[trait];
setAttrs({
[prefix + '_equation']: `{${talentDiceModified},${traitDice}}k1`,
[prefix + '_readOnlyView']: `${talentName}(${talentDiceView})`
});
}
});
}
function updateTraits(cb) {
_updateTrait('body', () => {
_updateTrait('mind', () => {
_updateTrait('charm', cb);
});
});
}
function _updateTrait(trait, cb) {
parseAttrs([trait, trait + '_updowngrade'], values => {
var traitDice = values[trait];
if(traitDice === 'null')
setAttrs({
[trait + '_equation']: 0
}, {}, cb);
else {
var updown = values[trait + '_updowngrade'] || 0;
if(updown)
traitDice = getUpDowngradedRoll(traitDice, updown);
setAttrs({
[trait + '_equation']: traitDice
}, {}, cb);
}
});
}
function _tickDowngrade(prefix) {
parseAttrs([prefix + '_tickdown', prefix + '_updowngrade'], values => {
let checked = !!values[prefix + '_tickdown'];
if(checked) {
updown = parseInt(values[prefix + '_updowngrade']) || 0;
setAttrs({
[prefix + '_updowngrade']: updown - 1,
[prefix + '_tickdown']: 0
});
return true;
}
return false;
});
}
function _tickUpgrade(prefix) {
parseAttrs([prefix + '_tickup', prefix + '_updowngrade'], values => {
let checked = !!values[prefix + '_tickup'];
if(checked) {
updown = parseInt(values[prefix + '_updowngrade']) || 0;
setAttrs({
[prefix + '_updowngrade']: updown + 1,
[prefix + '_tickup']: 0
});
return true;
}
return false;
});
}
// Change events
on('change:repeating_talents', evt => {
updateTalents();
});
onChange(['talent_cutieMark_dice', 'talent_cutieMark_trait', 'talent_cutieMark_updowngrade', 'talent_cutieMark_tickup', 'talent_cutieMark_tickdown'], () => {
updateCutieMarkTalent();
});
onChange(['talent_racial_dice', 'talent_racial_trait', 'talent_racial_updowngrade', 'talent_racial_tickup', 'talent_racial_tickdown'], () => {
updateRacialTalent();
});
onChange(['body_equation', 'mind_equation', 'charm_equation'], () => {
updateTalents();
});
on('sheet:opened', () => {
setAttrs({
character_sheet: 'TailsOfEquestria v1.5'
});
updateTraits(() => {
updateTalents();
});
});
// Up/downgrade tick events
onChange(['body_tickup'], () => {
_tickUpgrade('body');
});
onChange(['body_tickdown'], () => {
_tickDowngrade('body');
});
onChange(['body', 'body_updowngrade'], () => {
_updateTrait('body');
});
onChange(['mind_tickup'], () => {
_tickUpgrade('mind');
});
onChange(['mind_tickdown'], () => {
_tickDowngrade('mind');
});
onChange(['mind', 'mind_updowngrade'], () => {
_updateTrait('mind');
});
onChange(['charm_tickup'], () => {
_tickUpgrade('charm');
});
onChange(['charm_tickdown'], () => {
_tickDowngrade('charm');
});
onChange(['charm', 'charm_updowngrade'], () => {
_updateTrait('charm');
});