Files
roll20-character-sheets/5eShaped/precompiled/scripts/AbilityChecks.js
T
2016-10-12 22:39:47 +02:00

306 lines
15 KiB
JavaScript

/* global on:false, generateRowID:false, getTranslationByKey:false */
import { getSetItems, getSetRepeatingItems, isUndefinedOrEmpty, getAbilityValue, getAbilityShortName, getIntValue, addArithmeticOperator, showSign, exists, getRepeatingInfo, isUndefined } from './utilities';
import { ABILITIES } from './constants';
import { ProficiencyBonus } from './ProficiencyBonus';
const proficiencyBonus = new ProficiencyBonus();
export class AbilityChecks {
updateMacro() {
const collectionArray = ['ability_checks_query_var', 'ability_checks_macro_var', 'ability_checks_show_totals'];
for (const ability of ABILITIES) {
collectionArray.push(`${ability}_check_mod`);
collectionArray.push(`${ability}_check_mod_with_sign`);
}
getSetRepeatingItems('abilityChecks.updateMacro', {
repeatingItems: ['repeating_skill'],
collectionArray,
collectionArrayAddItems: ['name', 'ability', 'total_with_sign'],
callback: (v, finalSetAttrs, ids, repeatingItem) => {
finalSetAttrs.ability_checks_query_var = '?{Ability Check';
finalSetAttrs.ability_checks_macro_var = '';
finalSetAttrs.skills_macro_var = '';
for (const ability of ABILITIES) {
finalSetAttrs.ability_checks_query_var += `|${getTranslationByKey(ability.toUpperCase())},{{title=${getTranslationByKey(ability.toUpperCase())}}} {{roll1=[[@{shaped_d20} + ${v[`${ability}_check_mod`]}]]}} @{roll_setting} + ${v[`${ability}_check_mod`]}]]}}`;
if (v.ability_checks_show_totals === 'on') {
finalSetAttrs.ability_checks_macro_var += `[${getTranslationByKey(ability.toUpperCase())} ${v[`${ability}_check_mod_with_sign`]}](~shaped_${ability}_check)`;
} else {
finalSetAttrs.ability_checks_macro_var += `[${getTranslationByKey(ability.toUpperCase())}](~shaped_${ability}_check)`;
}
finalSetAttrs.ability_checks_macro_var += ', ';
}
for (const id of ids) {
const repeatingString = `${repeatingItem}_${id}_`;
finalSetAttrs.ability_checks_query_var += `|${v[`${repeatingString}name`]}, {{title=${v[`${repeatingString}name`]} (${getTranslationByKey(getAbilityShortName(v[`${repeatingString}ability`]).toUpperCase())})}} {{roll1=[[@{shaped_d20} + @{${repeatingString}formula}]]}} @{roll_setting} + @{${repeatingString}formula}]]}}`;
if (id !== ids[0]) {
finalSetAttrs.ability_checks_macro_var += ', ';
finalSetAttrs.skills_macro_var += ', ';
}
let skillButton;
if (v.ability_checks_show_totals === 'on') {
skillButton = `[${v[`${repeatingString}name`]} ${v[`${repeatingString}total_with_sign`]}](~repeating_skill_${id}_skill)`;
} else {
skillButton = `[${v[`${repeatingString}name`]}](~repeating_skill_${id}_skill)`;
}
finalSetAttrs.ability_checks_macro_var += skillButton;
finalSetAttrs.skills_macro_var += skillButton;
}
finalSetAttrs.ability_checks_query_var += '}';
},
});
}
updateSkill(rowId) {
const collectionArray = ['jack_of_all_trades_toggle', 'jack_of_all_trades', 'remarkable_athlete_toggle', 'remarkable_athlete', 'pb', 'exp', 'global_check_bonus'];
for (const ability of ABILITIES) {
collectionArray.push(`${ability}_mod`);
collectionArray.push(`${ability}_check_bonus`);
}
getSetRepeatingItems('abilityChecks.updateSkill', {
repeatingItems: ['repeating_skill'],
collectionArray,
collectionArrayAddItems: ['skill_d20', 'skill_info', 'proficiency', 'name', 'storage_name', 'ability', 'bonus', 'ability_key', 'formula', 'total', 'total_with_sign', 'passive_bonus', 'passive_total'],
rowId,
callback: (v, finalSetAttrs, ids, repeatingItem) => {
for (const id of ids) {
const repeatingString = `${repeatingItem}_${id}_`;
const skillName = v[`${repeatingString}name`];
if (isUndefinedOrEmpty(skillName)) {
return;
}
finalSetAttrs[`${repeatingString}ability_key`] = getAbilityShortName(v[`${repeatingString}ability`]).toUpperCase();
let total = 0;
let totalFormula = '';
const proficiency = v[`${repeatingString}proficiency`];
if (!proficiency || proficiency === 'unproficient') {
if ((v[`${repeatingString}ability`] === 'strength' || v[`${repeatingString}ability`] === 'dexterity' || v[`${repeatingString}ability`] === 'constitution') && v.remarkable_athlete_toggle === '@{remarkable_athlete}') {
const remarkableAthlete = getIntValue(v.remarkable_athlete);
total += remarkableAthlete;
totalFormula += `${remarkableAthlete}[remarkable athlete]`;
} else if (v.jack_of_all_trades_toggle === '@{jack_of_all_trades}') {
const jackOfAllTrades = getIntValue(v.jack_of_all_trades);
total += jackOfAllTrades;
totalFormula += `${jackOfAllTrades}[jack of all trades]`;
}
} else if (proficiency === 'proficient') {
const pb = getIntValue(v.pb);
total += pb;
totalFormula += `${pb}[proficient]`;
} else if (proficiency === 'expertise') {
const exp = getIntValue(v.exp);
total += exp;
totalFormula += `${exp}[expertise]`;
}
const abilityValue = getAbilityValue(v, v[`${repeatingString}ability`], 'strength');
if (exists(abilityValue)) {
total += abilityValue;
totalFormula += `${addArithmeticOperator(totalFormula, abilityValue)}[${getAbilityShortName(v[`${repeatingString}ability`])}]`;
}
const skillBonus = getIntValue(v[`${repeatingString}bonus`]);
if (exists(skillBonus)) {
total += skillBonus;
totalFormula += `${addArithmeticOperator(totalFormula, skillBonus)}[bonus]`;
}
if (exists(v[`${repeatingString}ability`])) {
let checkBonus = v[`${v[`${repeatingString}ability`]}_check_bonus`];
if (exists(checkBonus)) {
checkBonus = getIntValue(checkBonus);
total += checkBonus;
totalFormula += `${addArithmeticOperator(totalFormula, checkBonus)}[${getAbilityShortName(v[`${repeatingString}ability`])} check bonus]`;
}
}
const globalCheckBonus = v.global_check_bonus;
if (exists(globalCheckBonus)) {
if (!isNaN(globalCheckBonus)) {
total += getIntValue(globalCheckBonus);
}
if (totalFormula) {
totalFormula += ' + ';
}
totalFormula += '(@{global_check_bonus})[global check bonus]';
}
const passiveBonus = getIntValue(v[`${repeatingString}passive_bonus`]);
let advantageOrDisadvantage = 0;
finalSetAttrs[`${repeatingString}skill_info`] = '';
if (v[`${repeatingString}skill_d20`] && v[`${repeatingString}skill_d20`].indexOf('kh1') !== -1) {
finalSetAttrs[`${repeatingString}skill_info`] = '{{advantage=1}}';
advantageOrDisadvantage = 5;
} else if (v[`${repeatingString}skill_d20`] && v[`${repeatingString}skill_d20`].indexOf('kl1') !== -1) {
finalSetAttrs[`${repeatingString}skill_info`] = '{{disadvantage=1}}';
advantageOrDisadvantage = -5;
} else {
finalSetAttrs[`${repeatingString}skill_info`] = '';
}
const passiveTotal = 10 + total + passiveBonus + advantageOrDisadvantage;
finalSetAttrs[`${repeatingString}total`] = total;
finalSetAttrs[`${repeatingString}passive`] = passiveTotal;
finalSetAttrs[`${repeatingString}total_with_sign`] = showSign(total);
finalSetAttrs[`${repeatingString}formula`] = totalFormula;
}
},
setFinalAttrsCallback: () => {
this.updateMacro();
},
});
}
updateSkillsFromSRD() {
getSetRepeatingItems('abilityChecks.updateSkillsFromSRD', {
repeatingItems: ['repeating_skill'],
collectionArray: ['skills_srd', 'level', 'challenge', 'strength_mod', 'dexterity_mod', 'constitution_mod', 'intelligence_mod', 'wisdom_mod', 'charisma_mod', 'expertise_as_advantage'],
collectionArrayAddItems: ['name', 'ability'],
callback: (v, finalSetAttrs, ids, repeatingItem) => {
const skillsFromSRD = v.skills_srd;
const skillsObj = {};
const pb = proficiencyBonus.get(v.level, v.challenge);
const expertise = pb * 2;
let skillName;
let repeatingString;
if (!isUndefinedOrEmpty(skillsFromSRD)) {
for (const id of ids) {
repeatingString = `${repeatingItem}_${id}_`;
skillName = v[`${repeatingString}name`];
skillsObj[skillName] = id;
}
const re = /(\w+)\s?((?:\+|\-)\d+)/gi;
let match;
while ((match = re.exec(skillsFromSRD)) !== null) {
if (match && match[1] && match[2]) {
skillName = match[1];
if (skillsObj[skillName]) {
const skillId = skillsObj[skillName];
repeatingString = `${repeatingItem}_${skillId}_`;
const skillAbility = v[`${repeatingString}ability`];
const abilityValue = getAbilityValue(v, skillAbility);
const skillBonus = getIntValue(match[2]) - abilityValue;
if (skillBonus >= expertise) {
if (getIntValue(v.expertise_as_advantage) === 1) {
finalSetAttrs[`${repeatingString}skill_d20`] = '2d20@{d20_mod}kh1';
finalSetAttrs[`${repeatingString}proficiency`] = 'proficient';
} else {
finalSetAttrs[`${repeatingString}proficiency`] = 'expertise';
}
if (skillBonus > expertise) {
finalSetAttrs[`${repeatingString}bonus`] = skillBonus - expertise;
}
} else if (skillBonus >= pb) {
finalSetAttrs[`${repeatingString}proficiency`] = 'proficient';
if (skillBonus > pb) {
finalSetAttrs[`${repeatingString}bonus`] = skillBonus - pb;
}
}
} else {
console.warn(`${skillName} does not exist in the list of skills`);
}
}
}
}
},
});
}
updateInitiative() {
const collectionArray = ['initiative', 'initiative_ability', 'initiative_formula', 'initiative_bonus', 'jack_of_all_trades_toggle', 'jack_of_all_trades', 'remarkable_athlete_toggle', 'remarkable_athlete', 'global_check_bonus'];
for (const ability of ABILITIES) {
collectionArray.push(`${ability}_mod`);
collectionArray.push(`${ability}_check_bonus`);
}
getSetItems('abilityChecks.updateInitiative', {
collectionArray,
callback: (v, finalSetAttrs) => {
finalSetAttrs.initiative = 0;
let initiativeAbility = v.initiative_ability;
if (isUndefined(initiativeAbility)) {
initiativeAbility = 'dexterity';
}
const abilityMod = getAbilityValue(v, initiativeAbility);
if (exists(abilityMod)) {
finalSetAttrs.initiative += abilityMod;
}
finalSetAttrs.initiative_formula = `${abilityMod}[${getAbilityShortName(initiativeAbility)}]`;
const abilityCheckBonus = getIntValue(v[`${initiativeAbility}_check_bonus`]);
if (exists(abilityCheckBonus)) {
finalSetAttrs.initiative += abilityCheckBonus;
finalSetAttrs.initiative_formula += `${addArithmeticOperator(finalSetAttrs.initiative_formula, abilityCheckBonus)}[${getAbilityShortName(initiativeAbility)} check bonus]`;
}
const initiativeBonus = v.initiative_bonus;
if (exists(initiativeBonus)) {
if (!isNaN(initiativeBonus)) {
finalSetAttrs.initiative += getIntValue(initiativeBonus);
}
finalSetAttrs.initiative_formula += `${addArithmeticOperator(finalSetAttrs.initiative_formula, initiativeBonus)}[initiative bonus]`;
}
if (v.remarkable_athlete_toggle === '@{remarkable_athlete}') {
const remarkableAthlete = getIntValue(v.remarkable_athlete);
if (exists(remarkableAthlete)) {
finalSetAttrs.initiative += remarkableAthlete;
finalSetAttrs.initiative_formula += `${addArithmeticOperator(finalSetAttrs.initiative_formula, remarkableAthlete)}[remarkable athlete]`;
}
} else if (v.jack_of_all_trades_toggle === '@{jack_of_all_trades}') {
const jackOfAllTrades = getIntValue(v.jack_of_all_trades);
if (exists(jackOfAllTrades)) {
finalSetAttrs.initiative += jackOfAllTrades;
finalSetAttrs.initiative_formula += `${addArithmeticOperator(finalSetAttrs.initiative_formula, jackOfAllTrades)}[jack of all trades]`;
}
}
const globalCheckBonus = v.global_check_bonus;
if (exists(globalCheckBonus)) {
if (finalSetAttrs.initiative_formula) {
finalSetAttrs.initiative_formula += ' + ';
}
finalSetAttrs.initiative_formula += '(@{global_check_bonus})[global check bonus]';
}
},
});
}
setup() {
on('change:repeating_skill', (eventInfo) => {
const repeatingInfo = getRepeatingInfo('repeating_skill', eventInfo);
if (repeatingInfo && repeatingInfo.field !== 'ability_key' && repeatingInfo.field !== 'total' && repeatingInfo.field !== 'total_with_sign' && repeatingInfo.field !== 'passive_total' && repeatingInfo.field !== 'passive_total_with_sign' && repeatingInfo.field !== 'formula') {
this.updateSkill(repeatingInfo.rowId);
}
});
on('change:pb change:jack_of_all_trades_toggle change:jack_of_all_trades change:remarkable_athlete_toggle change:remarkable_athlete change:global_check_bonus change:strength_check_bonus change:dexterity_check_bonus change:constitution_check_bonus change:intelligence_check_bonus change:wisdom_check_bonus change:charisma_check_bonus', () => {
this.updateSkill();
});
on('change:skills_srd', () => {
this.updateSkillsFromSRD();
});
on('remove:repeating_skill change:ability_checks_show_totals', () => {
this.updateMacro();
});
const initiativeWatch = ['change:initiative_ability', 'change:initiative_bonus', 'change:jack_of_all_trades_toggle', 'change:jack_of_all_trades', 'change:remarkable_athlete_toggle', 'change:remarkable_athlete', 'change:global_check_bonus'];
for (const ability of ABILITIES) {
initiativeWatch.push(`change:${ability}_mod`);
initiativeWatch.push(`change:${ability}_check_bonus`);
}
on(initiativeWatch.join(' '), () => {
this.updateInitiative();
});
}
}