Files
2025-01-25 19:04:23 -05:00

455 lines
20 KiB
JavaScript

const debug=1
/* Campaign Options */
const campaignSettings = ["ability_system", "action_points_calc", "affiliations_enabled", "dependencies_enabled", "extended_conflict_enabled", "herculean_mod", "luck_points_rank", "reach_enabled", "simplified_combat_enabled", "social_conflict_enabled", "special_effects", "spirits_enabled", "tenacity_enabled", "vehicle_type"];
const campaginSettingDefaults = {
"default": {
"ability_system": "core",
"action_points_calc": "calculate",
"affiliations_enabled": 0,
"dependencies_enabled": 0,
"extended_conflict_enabled": 0,
"herculean_mod": ".1",
"luck_points_rank": 0,
"reach_enabled": 1,
"simplified_combat_enabled": 0,
"shaping_traits": "^{combine}: @{shaped_combine}\n^{duration}: @{shaped_duration}\n^{magnitude}: @{shaped_magnitude}\n^{range}: @{shaped_range}\n^{targets}: @{shaped_targets}",
"spirits_enabled": 1,
"standard_skills": ['athletics','boating','brawn','conceal','customs','dance','deceit','drive','endurance','evade','first_aid','influence','insight','locale','native_tongue','perception','ride','sing','spectral_combat','stealth','swim','unarmed','willpower'],
"social_conflict_enabled": 1,
"special_effects": "core",
"tenacity_enabled": 0,
"traditions_enabled": 1,
"vehicle_type": "mythras"
},
"after_the_vampire_wars": {
"ability_system": "after_the_vampire_wars",
"shaping_traits": "^{combine}: @{shaped_combine}\n^{duration}: @{shaped_duration} | ^{extended}: @{extended_duration}\n^{magnitude}: @{shaped_magnitude}\n^{range}: @{shaped_range} | ^{sympathetic}: @{sympathetic_range}\n^{targets}: @{shaped_targets}",
"tenacity_enabled": 1
},
"classic_fantasy": {
"ability_system": "classic_fantasy",
"luck_points_rank": 1
},
"destined": {
"ability_system": "destined",
"spirits_enabled": 0,
"special_effects": "destined",
"standard_skills": ['athletics','brawn','conceal','deceit','drive','endurance','evade','first_aid','influence','insight','perception','research','spectral_combat','stealth','streetwise','unarmed','willpower']
},
"fioracitta": {},
"luther_arkwright": {
"ability_system": "luther_arkwright",
"dependencies_enabled": 1,
"spirits_enabled": 0,
"standard_skills": ['athletics','brawn','conceal','customs','dance','deceit','endurance','evade','first_aid','home_parallel','influence','insight','native_tongue','perception','ride','sing','spectral_combat','stealth','swim','unarmed','willpower'],
"tenacity_enabled": 1
},
"lyonesse": {
"ability_system": "lyonesse",
"special_effects": "lyonesse",
"standard_skills": ['athletics','boating','brawn','common_tongue','conceal','customs','dance','deceit','drive','eloquence','endurance','evade','first_aid','folk_lore','influence','insight','perception','ride','sing','spectral_combat','stealth','swim','unarmed','willpower']
},
"m-space": {
"ability_system": "m-space",
"action_points_calc": "set_2",
"extended_conflict_enabled": 1,
"herculean_mod": ".2",
"reach_enabled": 0,
"special_effects": "imperative",
"spirits_enabled": 0,
"vehicle_type": "mspace"
},
"monster_island": {},
"mythic_babylon": {
"ability_system": "mythic_babylon",
"shaping_traits": " ",
"standard_skills": ['athletics','boating','brawn','commerce','conceal','customs','dance','deceit','drive','endurance','evade','first_aid','gaming','influence','insight','locale','native_tongue','perception','purity','ride','sing','spectral_combat','stealth','swim','unarmed','willpower']
},
"mythic_britain": {
"ability_system": "mythic_britain",
"standard_skills": ['athletics','boating','brawn','conceal','customs','dance','deceit','drive','endurance','evade','first_aid','influence','insight','locale','native_tongue','perception','ride','sing','spectral_combat','stealth','superstition','swim','unarmed','willpower']
},
"mythic_constantinople": {
"affiliations_enabled": 1
},
"mythras_imperative": {
"ability_system": "mythra_imperative",
"action_points_calc": "set_2",
"herculean_mod": ".2",
"reach_enabled": 0,
"special_effects": "imperative",
"spirits_enabled": 0
},
"mythic_rome": {
"ability_system": "mythic_rome",
"spirits_enabled": 0,
"standard_skills": ['athletics','boating','brawn','conceal','customs','dance','deceit','drive','endurance','evade','first_aid','influence','insight','locale','native_tongue','perception','ride','status','sing','spectral_combat','stealth','swim','unarmed','willpower']
},
"odd_soot": {
"ability_system": "odd_soot",
"action_points_calc": "set_2",
"extended_conflict_enabled": 1,
"herculean_mod": ".2",
"reach_enabled": 0,
"special_effects": "imperative",
"spirits_enabled": 0,
"vehicle_type": "mspace"
},
"perceforest": {
"shaping_traits": "^{combine}: @{shaped_combine}\n^{duration}: @{shaped_duration}\n^{magnitude}: @{shaped_magnitude}\n^{range}: @{shaped_range}\n^{targets}: @{shaped_targets}\n^{wonders}: @{shaped_wonders}"
},
"thennla": {
"ability_system": "thennla",
},
"worlds_united": {
"ability_system": "worlds_united",
"tenacity_enabled": 1,
"spirits_enabled": 0
}
}
/**
* Will either return the campaignSettingOption if overridden, otherwise will get the setting default value
* @param campaignSetting the variable name of the campaign setting
* @param campaignSettingOption the value of the campaign setting option variable
* @param setting the selected campaign setting
* @returns {*} object of new calculated attributes
*/
function calcCampaignSetting(campaignSetting, campaignSettingOption, setting) {
if (campaignSettingOption === 'default') {
if ((setting in campaginSettingDefaults) && (campaignSetting in campaginSettingDefaults[setting])) {
return {[`${campaignSetting}`]: campaginSettingDefaults[setting][campaignSetting]};
} else {
return {[`${campaignSetting}`]: campaginSettingDefaults['default'][campaignSetting]};
}
} else {
return {[`${campaignSetting}`]: campaignSettingOption};
}
}
/* Trigger setting change */
on(`change:setting_option`, function(event) {
/* Get an array of option values to get */
const campaignSettingOptions = campaignSettings.map(function(campaignSetting){
return `${campaignSetting}_option`;
})
getAttrs(campaignSettingOptions, function(v) {
let newAttrs = {};
campaignSettings.forEach(campaignSetting => { /* Gather all setting values per new setting */
newAttrs = {...newAttrs,
...calcCampaignSetting(campaignSetting, v[`${campaignSetting}_option`], event.newValue)
}
});
/* Set the default shaping traits per setting */
if (event.newValue in campaginSettingDefaults && 'shaping_traits' in campaginSettingDefaults[event.newValue]) {
newAttrs['shaping_traits'] = campaginSettingDefaults[event.newValue]['shaping_traits'];
} else {
newAttrs['shaping_traits'] = campaginSettingDefaults['default']['shaping_traits'];
}
setAttrs(newAttrs);
});
});
/* Trigger for all the individual campaign setting option values */
campaignSettings.forEach(campaignSetting => {
on(`change:${campaignSetting}_option`, function(event) {
getAttrs(['setting_option'], function(v) {
setAttrs(calcCampaignSetting(`${campaignSetting}`, event.newValue, v['setting_option']));
});
});
});
/* Sheet Type Triggers */
on("change:sheet_type change:vehicle_type", function(event) {
if (event.sourceType === "sheetworker") {return;}
if (event.sourceAttribute === 'sheet_type') {
getAttrs(['pow', 'cha', 'sheet_type', 'vehicle_type'].concat(spiritDamageGetAttrs), function(v) {
let newAttrs = {};
/* Set hit table rolls */
if (v['sheet_type'] === 'pc' || v['sheet_type'] === 'creature') {
newAttrs['hit_location_roll'] = '@{creature_hit_location_roll}';
newAttrs['hit_location_low_roll'] = '@{creature_hit_location_low_roll}';
newAttrs['hit_location_high_roll'] = '@{creature_hit_location_high_roll}';
} else if (v['sheet_type'] === 'vehicle' && v['vehicle_type'] === 'mythras') {
newAttrs['hit_location_roll'] = '@{vehicle_system_roll}';
newAttrs['hit_location_low_roll'] = '@{vehicle_system_roll}';
newAttrs['hit_location_high_roll'] = '@{vehicle_system_roll}';
} else if (v['sheet_type'] === 'vehicle' && v['vehicle_type'] === 'mspace') {
newAttrs['hit_location_roll'] = '@{d100_hit_location_roll}';
newAttrs['hit_location_low_roll'] = '@{d100_hit_location_low_roll}';
newAttrs['hit_location_high_roll'] = '@{d100_hit_location_hight_roll';
} else {
newAttrs['hit_location_roll'] = '@{none_hit_location_roll}';
newAttrs['hit_location_low_roll'] = '@{none_hit_location_roll}';
newAttrs['hit_location_high_roll'] = '@{none_hit_location_roll}';
}
/* Set standard skills posessed to sheet_type defaults and set default attribute_mode */
if (event.newValue === "pc") {
newAttrs['attribute_mode'] = 'physical';
stdSkillIds.forEach(skillId => {
newAttrs[`${skillId}_possessed`] = 1;
});
} else if (event.newValue === "creature" || event.newValue === "spirit") {
stdSkillIds.forEach(skillId => {
newAttrs[`${skillId}_possessed`] = 0;
});
if (event.newValue === "creature") {
newAttrs['attribute_mode'] = 'physical';
newAttrs['athletics_possessed'] = 1;
newAttrs['brawn_possessed'] = 1;
newAttrs['endurance_possessed'] = 1;
newAttrs['evade_possessed'] = 1;
newAttrs['perception_possessed'] = 1;
newAttrs['willpower_possessed'] = 1;
} else {
newAttrs['attribute_mode'] = 'spiritual';
newAttrs['spectral_combat_possessed'] = 1;
newAttrs['willpower_possessed'] = 1;
}
}
/* Set default spirit combat skill */
const pow = parseInt(v['pow']) || 0;
if (event.newValue === "pc" || event.newValue === "creature") {
newAttrs['willpower'] = pow * 2;
newAttrs['willpower_other'] = 0;
newAttrs['willpower_notes'] = '';
newAttrs['spirit_combat_skill_id'] = 'willpower';
newAttrs['spirit_combat_skill_name'] = getTranslationByKey('willpower');
newAttrs['spirit_combat_skill_total'] = pow * 2;
newAttrs['spirit_combat_skill_notes'] = '';
} else if (event.newValue === "spirit") {
const cha = parseInt(v['cha']) || 0;
newAttrs['willpower'] = pow * 2 + 50;
newAttrs['willpower_other'] = 50;
newAttrs['willpower_notes'] = '';
newAttrs['spirit_combat_skill_id'] = 'spectral_combat';
newAttrs['spirit_combat_skill_name'] = getTranslationByKey('spectral_combat');
newAttrs['spirit_combat_skill_total'] = pow + cha + 50;
newAttrs['spirit_combat_skill_notes'] = '';
}
setAttrs({
...newAttrs,
...calcSpiritDamage({...v, ...newAttrs})
});
});
}
});
/* Option Bar Action Buttons */
on('clicked:reset-augmentation', function(event) {
setAttrs({set_augmentation: 0});
});
on('clicked:reset-penalty', function(event) {
setAttrs({set_penalty: 0});
});
/* Utility Functions */
function getSectionIDsOrdered(sectionName, callback) {
'use strict';
getAttrs([`_reporder_${sectionName}`], function (v) {
getSectionIDs(sectionName, function (idArray) {
let reporderArray = v[`_reporder_${sectionName}`] ? v[`_reporder_${sectionName}`].toLowerCase().split(',') : [],
ids = [...new Set(reporderArray.filter(x => idArray.includes(x)).concat(idArray))];
callback(ids);
});
});
}
function damageModTable(step) {
const stepAbs = Math.abs(step);
const die_steps = [0, '1d2','1d4','1d6','1d8'];
const d10s = Math.floor(stepAbs/5);
const damageModd10s = Math.floor((stepAbs-1)/5);
const notd10s = stepAbs % 5; // % calculates remainder after division.
const notDamageModd10s = (stepAbs-1) % 5; // % calculates remainder after division.
let mod;
if (stepAbs <= 5) {
mod = (d10s ? `${d10s}d10` : '') + (d10s && notd10s ? '+' : '') + (notd10s ? die_steps[notd10s] : (d10s ? '' : 0));
} else if (stepAbs === 6) {
mod = '1d12';
} else if (stepAbs === 7) {
mod = '2d6';
} else if (stepAbs === 8) {
mod = '1d8+1d6';
} else if (stepAbs === 9) {
mod = '2d8';
} else if (stepAbs === 10) {
mod = '1d10+1d8';
} else {
mod = (damageModd10s ? `${damageModd10s}d10` : '') + (damageModd10s && notDamageModd10s ? '+' : '') + (notDamageModd10s ? die_steps[notDamageModd10s] : (damageModd10s ? '' : 0));
}
if (step >= 0) {
return mod;
} else {
return '-' + mod;
}
}
/* The damage table differs slightly from the damageModTable because damage mod has an extra step of 1d12. */
function damageTable(step) {
const stepAbs = Math.abs(step);
const die_steps = [0, '1d2','1d4','1d6','1d8'];
const d10s = Math.floor(stepAbs/5);
const notd10s = stepAbs % 5; // % calculates remainder after division.
let mod;
if (stepAbs === 6) {
mod = '2d6';
} else if (stepAbs === 7) {
mod = '1d8+1d6';
} else if (stepAbs === 8) {
mod = '2d8';
} else if (stepAbs === 9) {
mod = '1d10+1d8';
} else {
mod = (d10s ? `${d10s}d10` : '') + (d10s && notd10s ? '+' : '') + (notd10s ? die_steps[notd10s] : (d10s ? '' : 0));
}
if (step >= 0) {
return mod;
} else {
return '-' + mod;
}
}
/* Type Specific Scripts */
{% include 'sheet_types/battle_unit/battle_unit.js' %}
{% include 'sheet_types/character/character.js' %}
{% include 'sheet_types/character/character_import.js' %}
{% include 'sheet_types/character/character_versioning.js' %}
{% include 'sheet_types/ship/ship.js' %}
{% include 'sheet_types/vehicle/vehicle.js' %}
{% include 'sheet_types/star_system/star_system.js' %}
/* Generic versioning functions */
/**
* Make the changes needs to get a sheet updated from 3.0 to 3.1
*/
function upgradeGeneric3Dot1() {
if (debug) {
console.log("Upgrading sheet to 3.1");
}
/* Fetch attrs */
getAttrs(['sheet_notes'], function (v) {
let newAttrs = {'version': '3.1'};
/* Move shet_notes to sheetnotes to avoid conflicts with repeating items using _notes */
if (v['sheet_notes']) {
newAttrs['sheetnotes'] = v['sheet_notes'];
newAttrs['sheet_notes'] = "";
}
setAttrs(newAttrs);
});
}
/* Versioning */
/**
* Compares current sheet version to latest and performs necessary changes to bring the sheet up to date
* @param sheet_type the sheet sheet_type attribute
* @param version the sheet version already parse to a float or 0 if not a valid float
*/
function versioning(sheet_type, version) {
const latestVersion = '3.8';
if (!sheet_type) {
sheet_type = "pc";
}
if (debug) {console.log(`Current sheet version = ${version}`);}
version = parseFloat(version) || 0;
/* Eval sheet version and run upgrade functions as needed, note we have dropped functions of old versions */
if(version === 0) {
if (debug) {console.log(`Current version invalid, setting to 2.7`);}
setAttrs({['version']: '2.7'});
versioning(sheet_type, '3.0');
} else if (version < 3.0) {
if (sheet_type === 'pc') {upgradeCharacter3Dot0();}
else if (sheet_type === 'battle_unit') {upgradeBattleUnit3Dot0();}
else if (sheet_type === 'ship') {upgradeShip3Dot0();}
else if (sheet_type === 'solar_system') {upgradeStarSystem3Dot0();}
else if (sheet_type === 'vehicle') {upgradeVehicle3Dot0();}
versioning(sheet_type, '3.0');
}
else if (version < 3.1) {
if (sheet_type === 'character' || sheet_type === 'pc') {upgradeCharacter3Dot1();}
else if (sheet_type === 'battle_unit') {upgradeGeneric3Dot1();}
else if (sheet_type === 'ship') {upgradeGeneric3Dot1();}
else if (sheet_type === 'solar_system') {upgradeGeneric3Dot1();}
else if (sheet_type === 'vehicle') {upgradeGeneric3Dot1();}
versioning(sheet_type, '3.1');
} else if (version < 3.4) {
console.log("sheet type is = " + sheet_type);
if (sheet_type === 'character' || sheet_type === 'pc' || sheet_type === 'creature' || sheet_type === 'spirit') {
console.log("run character 3.4 update");
upgradeCharacter3Dot4();
}
versioning(sheet_type, '3.4');
} else if (version < 3.6) {
if (sheet_type === 'character' || sheet_type === 'pc' || sheet_type === 'creature' || sheet_type === 'spirit') {
console.log("running character 3.6 update");
upgradeCharacter3Dot6();
}
versioning(sheet_type, '3.6');
} else if (version < 3.8) { /* TODO change this when we next introduce a version that requires updating */
if (sheet_type === 'character' || sheet_type === 'pc' || sheet_type === 'creature' || sheet_type === 'spirit') {
console.log("running character 3.8 update");
upgradeCharacter3Dot8();
}
versioning(sheet_type, '3.8');
} else {
setAttrs({"version": 3.8})
}
}
/**
* Sets a number of attributes containing translations for prompts which normally can't use the i18n systems
* @returns {} an object of translation attributes
*/
const i18nVars = ['ablation', 'area', 'casting_time', 'combine', 'condition', 'conditions', 'days', 'dose', 'doses', 'duration', 'effects', 'enhance', "focus", 'fortune', 'hours', 'intensity', 'magnitude', 'months', 'none', 'precision', 'radius', 'range', 'rolls', 'rounds', 'service', 'services', 'shelf_life', 'spells', 'step', 'steps', 'swiftness', 'target', 'targets', 'term', 'terms', 'touch', 'turns', 'weeks', 'wonder', 'wonders', 'years'];
function setTranslationAttrs() {
let i18nAttrs = {};
i18nVars.forEach(i18nVar => {
i18nAttrs[`${i18nVar}_i18n`] = getTranslationByKey(i18nVar);
});
/* ones that don't match the key pattern */
i18nAttrs['point_a_i18n'] = getTranslationByKey('point-a');
i18nAttrs['points_a_i18n'] = getTranslationByKey('points-a');
i18nAttrs['pow_u_i18n'] = getTranslationByKey('pow-u');
i18nAttrs['minutes_a_i18n'] = getTranslationByKey('minutes-a');
i18nAttrs['meters_a_i18n'] = getTranslationByKey('meters-a');
i18nAttrs['kilometers_a_i18n'] = getTranslationByKey('kilometers-a');
return i18nAttrs;
}
/* On Open Triggers */
on("sheet:opened", function() {
getAttrs(['type', 'sheet_type', 'version', 'character_id'], function(v) {
const version = parseFloat(v['version']) || 0;
if (version < 3.0) {
let sheet_type = (typeof v['type'] === 'undefined') ? "pc" : v['type'];
versioning(sheet_type, version);
} else {
let sheet_type = (typeof v['sheet_type'] === 'undefined') ? "pc" : v['type'];
versioning(sheet_type, version);
}
let newAttrs = setTranslationAttrs();
/* Was seeing errors in the console about not being able to eval @{character_id} for some formula, but it did seem to actually work.
Adding this to specifically set the value in the sheet to avoid those errors just to be safe.
*/
newAttrs['character_id'] = v['character_id'];
setAttrs(newAttrs);
});
});
on('clicked:redo-v3-upgrade', function(event) {
console.log("redoing v3 upgrade");
getAttrs(['type', 'version'], function(v) {
console.log("redoing v3 upgrade");
let sheet_type = (typeof v['type'] === 'undefined') ? "pc" : v['type'];
console.log("redoing v3 upgrade");
versioning(sheet_type, '2.7');
});
});