Files
roll20-character-sheets/ShadowbaneInquisition/SheetWorker.js
T
ChtiKenny bbc6e52d17 corrected indentation
and added a separate js file for ease of reading
2021-06-08 12:51:34 +02:00

1271 lines
59 KiB
JavaScript

// repeating sections data array
const BUFF = {
active: 'active_r',
ws: 'WS_mod_r',
bs: 'BS_mod_r',
str: 'STR_mod_r',
tou: 'TOU_mod_r',
agi: 'AGI_mod_r',
int: 'INT_mod_r',
per: 'PER_mod_r',
wp: 'WP_mod_r',
fel: 'FEL_mod_r',
inf: 'INF_mod_r'
},
GEAR = {
carry: 'gear_carry_r',
name: 'gear_name_r',
craftsmanship: 'gear_crafts_r',
quantity: 'gear_quantity_r',
availability: 'gear_avail_r',
weight: 'gear_weight_r'
},
R_WEAPON = {
name : 'R_weapon_name',
class : 'R_weapon_class',
range : 'R_weapon_range',
damage : 'R_weapon_dam-roll',
pen : 'R_weapon_pen',
type : 'R_weapon_type',
max : 'R_weapon_max',
min : 'R_weapon_min',
vengeful : 'R_weapon_vengeful',
accurate : 'R_weapon_accurate',
burst : 'R_weapon_burst',
auto : 'R_weapon_auto',
mag : 'R_weapon_mag',
mag_max : 'R_weapon_mag_max',
trained : 'R_weapon_trained',
mod1 : 'R_weapon_mod1',
reload : 'R_weapon_reload',
weight : 'R_weapon_weight',
domain : 'R_weapon_domain'
}
// ___________________________________________________________________________
// __________________________Script for Ammo API______________________________
// ___________________________________________________________________________
on("sheet:opened change:repeating_rangedweapons:r_weapon_attack change:repeating_rangedweapons:r_weapon_burst change:repeating_rangedweapons:r_weapon_auto remove:repeating_rangedweapons change:repeating_vehiclerangedweapons:v_r_weapon_attack change:repeating_vehiclerangedweapons:v_r_weapon_burst change:repeating_vehiclerangedweapons:v_r_weapon_auto remove:repeating_vehiclerangedweapons", function() {
getSectionIDs("rangedweapons", function(idarray) {
// first get the attribute names for all rows in put in one array
const fieldnames = [];
idarray.forEach(id => fieldnames.push(
`repeating_rangedweapons_${id}_R_weapon_attack`,
`repeating_rangedweapons_${id}_R_weapon_burst`,
`repeating_rangedweapons_${id}_R_weapon_auto`
));
getAttrs(fieldnames, values => {
// create a variable to hold all the attribute values you re going to create.
const attr = {};
// now loop through the rows again
idarray.forEach(id => {
let row = 'repeating_rangedweapons_' + id;
let attack = +values[`${row}_R_weapon_attack`] || 0,
burst = +values[`${row}_R_weapon_burst`] || 0,
auto = +values[`${row}_R_weapon_auto`] || 0;
let ammo = attack === -10 ? -auto : (attack === 0 ? -burst : -1);
attr[`${row}_id`] = id; // id of the repeating element
attr[`${row}_ammo`] = ammo; // number of ammo to use
});
setAttrs(attr);
});
});
getSectionIDs("vehiclerangedweapons", function(idarray) {
// first get the attribute names for all rows in put in one array
const fieldnames = [];
idarray.forEach(id => fieldnames.push(
`repeating_vehiclerangedweapons_${id}_V_R_weapon_attack`,
`repeating_vehiclerangedweapons_${id}_V_R_weapon_burst`,
`repeating_vehiclerangedweapons_${id}_V_R_weapon_auto`
));
getAttrs(fieldnames, values => {
// create a variable to hold all the attribute values you re going to create.
const attr = {};
// now loop through the rows again
idarray.forEach(id => {
let row = 'repeating_vehiclerangedweapons_' + id;
let attack = +values[`${row}_V_R_weapon_attack`] || 0,
burst = +values[`${row}_V_R_weapon_burst`] || 0,
auto = +values[`${row}_V_R_weapon_auto`] || 0;
let ammo = attack === -10 ? -auto : (attack === 0 ? -burst : -1);
attr[`${row}_id`] = id; // id of the repeating element
attr[`${row}_ammo`] = ammo; // number of ammo to use
});
setAttrs(attr);
});
});
});
// ___________________________________________________________________________
// __________________Skills unnatural bonus sheet worker______________________
// ___________________________________________________________________________
/**
* skillRoll description
* @param {string} skill - name of the skill
* @param {string} focus - short name of the characteristic
*/
const skillRoll = (skill, focus) => {
let attr = {};
attr[`${skill}_focus`] = `@{${focus}Total}`;
attr[`${skill}_unnat`]=`@{${focus.toUpperCase()}_unnat}`;
return attr;
};
let skills = [
'acrobatics','athletics','awareness','charm','command','commerce','deceive','dodge','inquiry',
'interrogation','intimidate','logic','medicae','nav_surface','nav_stellar','nav_warp','op_aero','op_surface','op_void',
'parry','psyniscience','scrutiny','security','sleight','stealth','survival','tech_use',
'linguistics','common-lore','scholastic-lore','forbidden-lore','trade'
];
let repeatingSkills = ['skill','linguistics','common-lore','scholastic-lore','forbidden-lore','trade'];
on('sheet:opened ' + skills.map(skill => `change:${skill}_char change:${skill}_name`).join(' ') + repeatingSkills.map(skill => `change:repeating_${skill}:${skill}_r_char change:repeating_${skill}:${skill}_name`).join(' '), function () {
console.log('== UPDATING SKILLS ==');
getAttrs(skills.map( skill => `${skill}_char`), (values) => {
let attr = {};
for (var [skill, focus] of Object.entries(values)) {
attr = {...attr, ...skillRoll(skill.replace('_char', ''), focus)};
}
setAttrs(attr);
});
repeatingSkills.forEach(field => {
var repSkills = [];
getSectionIDs(field, ids => {
ids.forEach( id => {
repSkills.push(`repeating_${field}_${id}_${field}_r_char`);
});
getAttrs(repSkills, (values) => {
let attr = {};
for (var [skill, focus] of Object.entries(values)) {
attr = {...attr, ...skillRoll(skill.replace('_char', ''), focus)};
}
if (attr) setAttrs(attr);
console.table(values)
console.table(attr)
});
});
});
console.log('== SKILLS UPDATED ==');
});
// ___________________________________________________________________________
// ____________________Movement and Weight sheet worker_______________________
// ___________________________and Fatigue Pts_________________________________
let fieldsMWF = [
'size', 'fatigue', 'carry', 'weight_total',
'ws', 'ws_unnat', 'ws_advancement', 'ws_mod',
'bs', 'bs_unnat', 'bs_advancement', 'bs_mod',
'str', 'str_unnat', 'str_advancement', 'str_mod',
'tou', 'tou_unnat', 'tou_advancement', 'tou_mod',
'int', 'int_unnat', 'int_advancement', 'int_mod',
'per', 'per_unnat', 'per_advancement', 'per_mod',
'wp', 'wp_unnat', 'wp_advancement', 'wp_mod',
'fel', 'fel_unnat', 'fel_advancement', 'fel_mod',
'inf', 'inf_unnat',
'agi', 'agi_unnat', 'agi_advancement', 'agi_mod', 'agi_mov_mod', 'armor_agi', 'armor_limit',
'fatigue_ignore', 'psykana_class'
];
on('sheet:opened ' + fieldsMWF.map(field => 'change:' + field).join(' '), function(e) {
// console.log(e);
getAttrs(fieldsMWF, function(values) {
// SIZE
var size = parseInt(values['size'], 10) || 0;
// FATIGUE
var fatigue = parseInt(values['fatigue'], 10) || 0;
var fatigueIgnore = parseInt(values['fatigue_ignore'], 10) || 0;
if (fatigueIgnore) fatigue = 0;
// CARRY
var carry = parseInt(values['carry'], 10) || 0;
var weight_total = parseInt(values['weight_total'], 10) || 0;
// STATS
function Stat(stat) {
this.base = parseInt(values[`${stat}`], 10) || 0
this.modifier = parseInt(values[`${stat}_mod`], 10) || 0
this.advancement = parseInt(values[`${stat}_advancement`], 10) || 0
this.unnat = parseInt(values[`${stat}_unnat`], 10) || 0
this.total = this.base + this.modifier + this.advancement
this.bonus = () => Math.floor(this.total / 10 + this.unnat)
}
// WS
var ws = new Stat('ws')
if (ws.bonus() < fatigue) ws.total = Math.ceil(ws.total / 2)
// BS
var bs = new Stat('bs')
if (bs.bonus() < fatigue) bs.total = Math.ceil(bs.total / 2)
// STR
var str = new Stat('str')
if (str.bonus() < fatigue) str.total = Math.ceil(str.total / 2)
// TOU
var tou = new Stat('tou')
if (tou.bonus() < fatigue) tou.total = Math.ceil(tou.total / 2)
// AGI
var agi = new Stat('agi')
agi_mov_mod = parseInt(values['agi_mov_mod'], 10) || 0,
armor_agi = parseInt(values['armor_agi'], 10) || 0,
armor_limit = parseInt(values['armor_limit'], 10) || 0;
if (weight_total > carry) agi.total -= 10
if (armor_limit) agi.total = (agi.total > armor_agi ) ? armor_agi : agi.total
if (agi.bonus() < fatigue) agi.total = Math.ceil(agi.total / 2)
// INT
var int = new Stat('int')
if (int.bonus() < fatigue) int.total = Math.ceil(int.total / 2)
// PER
var per = new Stat('per')
if (per.bonus() < fatigue) per.total = Math.ceil(per.total / 2)
// WP
var wp = new Stat('wp')
if (wp.bonus() < fatigue) wp.total = Math.ceil(wp.total / 2)
// FEL
var fel = new Stat('fel')
// Blank FEL halfing
var blank = values['psykana_class']
if (blank === '-1') fel.total = Math.ceil(fel.total / 2);
if (fel.bonus() < fatigue) fel.total = Math.ceil(fel.total / 2)
// INF
var inf = new Stat('inf')
if (inf.bonus() < fatigue) inf.total = Math.ceil(inf.total / 2)
var move_mod = agi.bonus() + size + agi_mov_mod;
var carry_mod = str.bonus() + tou.bonus();
var carry_calc;
// 40k system does their carry weight off a sheet-table
switch (carry_mod) {
case 1: carry_calc = 2.25; break;
case 2: carry_calc = 4.5; break;
case 3: carry_calc = 9; break;
case 4: carry_calc = 18; break;
case 5: carry_calc = 27; break;
case 6: carry_calc = 36; break;
case 7: carry_calc = 45; break;
case 8: carry_calc = 56; break;
case 9: carry_calc = 67; break;
case 10: carry_calc = 78; break;
case 11: carry_calc = 90; break;
case 12: carry_calc = 112; break;
case 13: carry_calc = 225; break;
case 14: carry_calc = 337; break;
case 15: carry_calc = 450; break;
case 16: carry_calc = 675; break;
case 17: carry_calc = 900; break;
case 18: carry_calc = 1350; break;
case 19: carry_calc = 1800; break;
case 20: carry_calc = 2250; break;
}
// normal, no unnatural
setAttrs({
half_move: (move_mod),
full_move: (move_mod * 2),
charge_move: (move_mod * 3),
run_move: (move_mod * 6),
carry: (carry_calc * 1), //taking out the * 1 seems to cause attr_carry to freeze when carry_mod is set to 1 or 0
lift: (carry_calc * 2),
push: (carry_calc * 4),
bsTotal: (bs.total),
bsB: (bs.bonus()),
wsTotal: (ws.total),
wsB: (ws.bonus()),
strTotal: (str.total),
strB: (str.bonus()),
touTotal: (tou.total),
touB: (tou.bonus()),
agiTotal: (agi.total),
agiB: (agi.bonus()),
intTotal: (int.total),
intB: (int.bonus()),
perTotal: (per.total),
perB: (per.bonus()),
wpTotal: (wp.total),
wpB: (wp.bonus()),
felTotal: (fel.total),
felB: (fel.bonus()),
infTotal: (inf.total),
infB: (inf.bonus()),
});
// 0 mod movement override
if (move_mod <= 0) {
setAttrs({
half_move: (0.5),
full_move: (1),
charge_move: (2),
run_move: (3)
});
}
// 0 mod carry override
if (carry_mod <=0) {
setAttrs({
carry: (0.9),
lift: (2.25),
push: (4.5)
});
}
});
});
// ___________________________________________________________________________
// ________________________Fatigue and Armor sheet worker_____________________
// ___________________________________________________________________________
let fieldsFA = [
'fatigue_mod',
'tou', 'tou_unnat', 'tou_advancement', 'tou_mod',
'wp', 'wp_unnat', 'wp_advancement',
'armor_head', 'armor_arm_right', 'armor_body', 'armor_arm_left', 'armor_leg_right', 'armor_leg_left'
];
on('sheet:opened ' + fieldsFA.map(field => 'change:' + field).join(' '), function() {
getAttrs(fieldsFA, function(values) {
var fatigue_mod = parseInt(values['fatigue_mod'], 10) || 0;
var toughness = parseInt(values['tou'], 10) || 0;
var toughness_unnat = parseInt(values['tou_unnat'], 10) || 0;
var toughness_advancement = parseInt(values['tou_advancement'], 10) || 0;
var toughness_modifier = parseInt(values['tou_mod'], 10) || 0;
var toughness_bonus = Math.floor((toughness + toughness_advancement + toughness_modifier) / 10 + toughness_unnat);
var toughness_mod = Math.floor((toughness + toughness_advancement) / 10 + toughness_unnat);
var willpower = parseInt(values['wp'], 10) || 0;
var willpower_unnat = parseInt(values['wp_unnat'], 10) || 0;
var willpower_advancement = parseInt(values['wp_advancement'], 10) || 0;
var willpower_mod = Math.floor((willpower + willpower_advancement) / 10 + willpower_unnat);
var armor_head = parseInt(values['armor_head'], 10) || 0;
var armor_arm_right = parseInt(values['armor_arm_right'], 10) || 0;
var armor_body = parseInt(values['armor_body'], 10) || 0;
var armor_arm_left = parseInt(values['armor_arm_left'], 10) || 0;
var armor_leg_right = parseInt(values['armor_leg_right'], 10) || 0;
var armor_leg_left = parseInt(values['armor_leg_left'], 10) || 0;
// normal, no modifiers ___________________________________________________
setAttrs({
soak_head: (armor_head + toughness_bonus),
soak_arm_right: (armor_arm_right + toughness_bonus),
soak_body: (armor_body + toughness_bonus),
soak_arm_left: (armor_arm_left + toughness_bonus),
soak_leg_right: (armor_leg_right + toughness_bonus),
soak_leg_left: (armor_leg_left + toughness_bonus),
fatigue_max: (toughness_mod + willpower_mod + fatigue_mod)
});
});
});
// ___________________________________________________________________________
// ____________________Tabs sheet worker______________________________________
// ___________________________________________________________________________
const buttonlist = ['core','equipment','advancements','journal','vehicle','psykana','settings'];
buttonlist.forEach(button => {
on(`clicked:${button}`, function() {
setAttrs({
sheetTab: button
});
});
});
// ___________________________________________________________________________
// ____________________Inventory Tabs sheet worker____________________________
// ___________________________________________________________________________
const buttonListIventory = ['all', 'weapon', 'armour', 'gear', 'tool', 'consumables', 'ammo', 'cyberntic', 'other'];
buttonListIventory.forEach(button => {
on(`clicked:inv_${button}`, function() {
setAttrs({
equipmentTab: button
});
});
});
// ___________________________________________________________________________
// ____________________insanity/corruption sheet worker_______________________
// ___________________________________________________________________________
on('sheet:opened change:insanity_pts change:corruption_pts', function() {
getAttrs(['insanity_pts', 'corruption_pts'], function(values) {
var insanity_pts = parseInt(values['insanity_pts'], 0) || 0;
var corruption_pts = parseInt(values['corruption_pts'], 10) || 0;
function insanity (points) {
if (points <= 9) return ('Stable')
if (points <= 39) return ('Unsettled')
if (points <= 59) return ('Disturbed')
if (points <= 79) return ('Unhinged')
if (points <= 99) return ('Deranged')
return ('Terminally Insane')
}
function corruption (points) {
if (points <= 9) return ('Pure')
if (points <= 39) return ('Tainted')
if (points <= 59) return ('Soiled')
if (points <= 79) return ('Debased')
if (points <= 99) return ('Profane')
return ('Damned')
}
setAttrs({
insanity_degree: (insanity(insanity_pts)),
corruption_degree: (corruption(corruption_pts))
})
});
});
// ___________________________________________________________________________
// _______________________psychic info sheet worker___________________________
// ___________________________________________________________________________
const PSY_RANK = {}
let fieldsPsy = ['psykana_class', 'psykana_limit', 'psy_push', 'psy_rating','psykana_sustain','psykana_sustain_count'];
on('sheet:opened ' + fieldsPsy.map(field => 'change:' + field).join(' '), function() {
getAttrs(fieldsPsy, function(values) {
var psykana_class = parseInt(values['psykana_class'])||0;
var psykana_limit = parseInt(values['psykana_limit'])||0;
var psy_push = parseInt(values['psy_push'])||0;
var psy_rating = parseInt(values['psy_rating'], 10) || 0;
var psykana_sustain = parseInt(values['psykana_sustain'], 10) || 0;
var psykana_sustain_count = parseInt(values['psykana_sustain_count'], 10) || 0;
var psykana_limit_factor = 0;
var push_addend_epr = 0;
var sustain_count_addend = 0;
var unfettered_addend = 0;
var push_addend_pp = 0;
var sustain_addend = 0;
// psy rating calc
switch (psykana_limit) {
case 0:
psykana_limit_factor = 0.5;
setAttrs({
psy_roll: ('cf>96')
});
break;
case 1:
psykana_limit_factor = 1;
setAttrs({
psy_roll: ('cf11cf22cf33cf44cf55cf66cf77cf88cf99cf100')
});
break;
case 2:
psykana_limit_factor = 1;
push_addend_epr = psy_push;
if (psykana_class == 0) {
setAttrs({
psy_roll: ('cs1cs11cs22cs33cs44cs55cs66cs77cs88cs99cs100cf>0')
//psy_roll: ('cf>0')
});
} else {
setAttrs({
psy_roll: ('cf>0')
});
}
break;
}
if (psykana_sustain == -5) {
sustain_count_addend = psykana_sustain_count;
}
var epr = Math.ceil(psy_rating * psykana_limit_factor) + push_addend_epr;
// phenomena calc
if (psykana_class == 2 && psykana_limit == 1) {
unfettered_addend = 10;
}
if (psykana_class == 0 && psykana_limit == 2) {
push_addend_pp = 10;
}
if (psykana_class == 1 && psykana_limit == 2) {
push_addend_pp = 5 * psy_push;
}
if (psykana_class == 2 && psykana_limit == 2) {
push_addend_pp = 10 * psy_push;
}
if (psykana_sustain == -5) {
sustain_addend = 5 * sustain_count_addend;
}
var pp = unfettered_addend + push_addend_pp + sustain_addend;
//output
setAttrs({
effective_psy_rating: epr,
psykana_phenomena: pp
});
});
});
// ___________________________________________________________________________
// ____________________gear cost/weight sheet worker__________________________
// ___________________________________________________________________________
on('change:repeating_rangedweapons remove:repeating_rangedweapons change:repeating_meleeweapons remove:repeating_meleeweapons', function() {
repeatingWeight("R_weapon_weight_t","rangedweapons",[['weight',"R_weapon_weight"],['carry',"R_weapon_carry"]]),
repeatingWeight("M_weapon_weight_t","meleeweapons",[['weight',"M_weapon_weight"],['carry',"M_weapon_carry"]]);
});
on('change:M_weapon_weight_t change:R_weapon_weight_t change:gear_carry change:gear_weight change:gear_quantity change:repeating_gear remove:repeating_gear', () => {
getSectionIDs(`repeating_gear`, idArray => {
const fieldset_weight = [];
const fieldset_quantity = [];
const fieldset_carry = [];
idArray.forEach(id => fieldset_weight.push (`repeating_gear_${id}_gear_weight_r`));
idArray.forEach(id => fieldset_quantity.push (`repeating_gear_${id}_gear_quantity_r`));
idArray.forEach(id => fieldset_carry.push (`repeating_gear_${id}_gear_carry_r`));
getAttrs(['M_weapon_weight_t','R_weapon_weight_t','weight_total', 'gear_carry', 'gear_weight', 'gear_quantity', ...fieldset_weight, ...fieldset_quantity, ...fieldset_carry], v => {
const getValue = (id, field) => parseFloat(v[`repeating_gear_${id}_${field}`]) || 0
const weight_base = parseFloat(v.gear_weight) * parseFloat(v.gear_quantity) * parseFloat(v.gear_carry)
const weight_repeating = idArray.reduce((total, id) => total + (getValue(id, 'gear_weight_r') * getValue(id, 'gear_quantity_r') * getValue(id, 'gear_carry_r')), 0)
const weapon_weight = parseFloat(v.M_weapon_weight_t) + parseFloat(v.R_weapon_weight_t)
setAttrs({
weight_total: weight_base + weight_repeating + weapon_weight,
});
});
});
});
// ___________________________________________________________________________
// ____________________Advancement XP sheet worker_______________________________
// ___________________________________________________________________________
on('change:xp_total change:advancement_costL change:advancement_costR change:repeating_advancements remove:repeating_advancements', () => {
// get section IDs because of operation both inside and outside of fieldset
getSectionIDs(`repeating_advancements`, idArray => {
const fieldnames = [];
idArray.forEach(id => fieldnames.push (
`repeating_advancements_${id}_advancement_costL_r`,
`repeating_advancements_${id}_advancement_costR_r`
));
// spread operator to get every array value
getAttrs(['xp_total', 'advancement_costL', 'advancement_costR', ...fieldnames], v => {
const getValue = (id, field) => parseFloat(v[`repeating_advancements_${id}_${field}`]) || 0
const cost = parseFloat(v.gear_cost) || 0
const left = parseFloat(v.advancement_costL) || 0
const right = parseFloat(v.advancement_costR) || 0
const left_r = idArray.reduce((total, id) => total + getValue(id,'advancement_costL_r'),0)
const right_r = idArray.reduce((total, id) => total + getValue(id,'advancement_costR_r'),0)
const spent = left + right + left_r + right_r
const total = parseFloat(v.xp_total) || 0
setAttrs({
xp_spent: spent,
xp_current: total - spent
});
});
});
});
// ___________________________________________________________________________
// __________________________General sum sheet worker_________________________
// ___________________________________________________________________________
/**
* [repeatingWeight description]
* @param {[type]} destination [description]
* @param {[type]} section [description]
* @param {[type]} fields [description]
*/
const repeatingWeight = (destination, section, fields) => {
getSectionObjects(section, fields, items => {
const sumTotal = items.filter(item => item.carry !== '0').reduce((total, item) => total + parseFloat(item.weight),0);
setAttrs({[destination]: sumTotal});
})
}
// ___________________________________________________________________________
// _________________________ weapon damage primitive _________________________
// ___________________________________________________________________________
/**
* calculate real damage roll
* @param {string} source row id of the weapon
*/
const calcDmg = function (sources, fields) {
var redice = /^(\d+)?(d\d+)(.*)?/;
getAttrs(fields, v => {
let attr = {};
sources.forEach( source => {
// to avoid retyping long strings because i'm lazy
var dam = source + 'weapon_dam-roll',
ven = source + 'weapon_vengeful', // crit
min = source + 'weapon_min', // proven
max = source + 'weapon_max', // primitive
set = source + 'weapon_setting'; // overcharge/load / maximal
let dmg = redice.exec(v[dam]);
ven = parseInt(v[ven], 10) || 0,
min = parseInt(v[min], 10) || 0,
max = parseInt(v[max], 10) || 0,
set = parseInt(v[set], 10) || 0;
if (!dmg) {
console.log('no damage found');
attr[`${source}weapon_real_dmg`] = v[dam];
} else {
let dicenum = parseInt(dmg[1], 10) || 1,
dicetype = dmg[2],
mod = dmg[3];
let damTotal = '{';
if (set === 3) dicenum ++;
for (var i = 0; i < dicenum; i++) {
if (i) damTotal += ', '
if (min > 0) damTotal += '{';
if (max > 0) damTotal += '{';
damTotal += (dicetype == 'd5') ? 'ceil(1d10/2)' : '1d10';
if (ven > 0) damTotal += 'cs>' + ven;
if (min > 0) damTotal += ', {' + min + '}}kh1';
if (max > 0) damTotal += ', {' + max + '}}kl1';
}
damTotal += '}';
if (mod) damTotal += mod;
if (set === 2) damTotal += '+1';
if (set === 4) {
damTotal += '+2';
attr[`${source}weapon_pen2`] = 2;
} else {
attr[`${source}weapon_pen2`] = 0;
}
attr[`${source}weapon_real_dmg`] = damTotal;
}
});
setAttrs(attr);
});
};
let fieldsDMG = [
'vehiclerangedweapons:V_R_weapon_dam-roll', 'vehiclerangedweapons:V_R_weapon_vengeful', 'vehiclerangedweapons:V_R_weapon_min', 'vehiclerangedweapons:V_R_weapon_max', 'vehiclerangedweapons:V_R_weapon_setting',
'rangedweapons:R_weapon_dam-roll', 'rangedweapons:R_weapon_vengeful', 'rangedweapons:R_weapon_min', 'rangedweapons:R_weapon_max', 'rangedweapons:R_weapon_setting',
'vehiclemeleeweapons:V_M_weapon_dam-roll', 'vehiclemeleeweapons:V_M_weapon_vengeful', 'vehiclemeleeweapons:V_M_weapon_min', 'vehiclemeleeweapons:V_M_weapon_max',
'meleeweapons:M_weapon_dam-roll', 'meleeweapons:M_weapon_vengeful', 'meleeweapons:M_weapon_min', 'meleeweapons:M_weapon_max',
];
on('sheet:opened ' + fieldsDMG.map(field => 'change:repeating_' + field).join(' '), () => {
getSectionIDs('rangedweapons', (idArray) => {
let sources = [];
let fieldnames = [];
idArray.forEach( id => {
sources.push(`repeating_rangedweapons_${id}_R_`);
fieldnames.push(
`repeating_rangedweapons_${id}_R_weapon_dam-roll`,
`repeating_rangedweapons_${id}_R_weapon_vengeful`,
`repeating_rangedweapons_${id}_R_weapon_min`,
`repeating_rangedweapons_${id}_R_weapon_max`,
`repeating_rangedweapons_${id}_R_weapon_setting`
);
});
calcDmg(sources, fieldnames);
});
getSectionIDs('meleeweapons', (idArray) => {
let sources = [];
let fieldnames = [];
idArray.forEach( id => {
sources.push(`repeating_meleeweapons_${id}_M_`);
fieldnames.push(
`repeating_meleeweapons_${id}_M_weapon_dam-roll`,
`repeating_meleeweapons_${id}_M_weapon_vengeful`,
`repeating_meleeweapons_${id}_M_weapon_min`,
`repeating_meleeweapons_${id}_M_weapon_max`
);
});
calcDmg(sources, fieldnames);
});
getSectionIDs('vehiclerangedweapons', (idArray) => {
let sources = [];
let fieldnames = [];
idArray.forEach( id => {
sources.push(`repeating_vehiclerangedweapons_${id}_V_R_`);
fieldnames.push(
`repeating_vehiclerangedweapons_${id}_V_R_weapon_dam-roll`,
`repeating_vehiclerangedweapons_${id}_V_R_weapon_vengeful`,
`repeating_vehiclerangedweapons_${id}_V_R_weapon_min`,
`repeating_vehiclerangedweapons_${id}_V_R_weapon_max`,
`repeating_vehiclerangedweapons_${id}_V_R_weapon_setting`
);
});
calcDmg(sources, fieldnames);
});
getSectionIDs('vehiclemeleeweapons', (idArray) => {
let sources = [];
let fieldnames = [];
idArray.forEach( id => {
sources.push(`repeating_vehiclemeleeweapons_${id}_V_M_`);
fieldnames.push(
`repeating_vehiclemeleeweapons_${id}_V_M_weapon_dam-roll`,
`repeating_vehiclemeleeweapons_${id}_V_M_weapon_vengeful`,
`repeating_vehiclemeleeweapons_${id}_V_M_weapon_min`,
`repeating_vehiclemeleeweapons_${id}_V_M_weapon_max`
);
});
calcDmg(sources, fieldnames);
});
console.log('DAMAGES UPDATED');
});
// ___________________________________________________________________________
// __________________________ get repeating objects __________________________
// ___________________________________________________________________________
// TODO: add class suport
/**
* get the attributes from a repeating section and pass them in an array of objects
* @param {String} section - name of the repeating section
* @param {Array} fields - list of the attributes
* @param {Function} callback - function to pass the array of objects
*/
const getSectionObjects = function (section, fields, callback) {
if (!Array.isArray(fields)) fields = [fields];
getSectionIDs(`repeating_${section}`, idArray => {
const attrArray = idArray.reduce( (m,id) => [...m, ...(Object.values(fields).map(field => `repeating_${section}_${id}_${field}`))],[]);
getAttrs(attrArray, v => {
const objects = [];
idArray.forEach(id => {
let obj = { _id : id, _source: `repeating_${section}_${id}` };
for (var property in fields) {
obj[property] = v[`repeating_${section}_${id}_${fields[property]}`]
}
objects.push(obj)
});
callback(objects);
});
});
}
// ___________________________________________________________________________
// ________________________________ Importer _________________________________
// ___________________________________________________________________________
on('clicked:import_clear', () => {
setAttrs({
import_value: ''
});
});
on('clicked:import', () => {
getAttrs(['import_value'], (v) => {
try {
var data = JSON.parse(v.import_value);
} catch(e) {
setAttrs({import_value: 'ERROR: verify if you have copied the totality of the Export'}); return console.log(e);
}
console.log('Importing Character');
var attributes = {}
// emptying the repeating sections
const sectionList = [
'conditions',
'skill',
'linguistics',
'common-lore',
'scholastic-lore',
'forbidden-lore',
'trade',
'abilities',
'traits',
'rangedweapons',
'meleeweapons',
'gear',
'cybernetics',
'aptitudes',
'advancements',
'disorders',
'mutations',
'objectives',
'notes',
'vehicles',
'vehiclerangedweapons',
'vehiclemeleeweapons',
'minormanifestation',
'psynotes',
'psychicabilities'
];
sectionList.forEach( section => {
getSectionIDs(`repeating_${section}`, idArray => {
idArray.forEach(id => removeRepeatingRow(`repeating_${section}_${id}`))
})
})
// info Block
attributes = {...attributes, ...mapInfo(data)}
// STATS
attributes = {...attributes, ...mapStat('WS', data?.weaponSkill)};
attributes = {...attributes, ...mapStat('BS', data?.ballisticSkill)};
attributes = {...attributes, ...mapStat('STR', data?.strenght)};
attributes = {...attributes, ...mapStat('TOU', data?.toughness)};
attributes = {...attributes, ...mapStat('AGI', data?.agility)};
attributes = {...attributes, ...mapStat('INT', data?.intelligence)};
attributes = {...attributes, ...mapStat('PER', data?.perception)};
attributes = {...attributes, ...mapStat('WP', data?.willpower)};
attributes = {...attributes, ...mapStat('FEL', data?.fellowship)};
attributes = {...attributes, ...mapStat('INF', data?.influence)};
// WOUNDS, FATE, FATIGUE, FORCEFIELD
attributes = {...attributes, ...mapWounds(data?.wounds)};
attributes = {...attributes, ...mapFate(data?.fate)};
attributes = {...attributes, ...mapFatigue(data?.fatigue)};
attributes = {...attributes, ...mapForceField(data?.forcefield)};
// CONDITIONS
data?.conditions?.forEach((condition) => {
attributes = {...attributes, ...mapCondition(condition)};
});
// SKILLS, REPEATING SKILLS
data?.skills?.forEach(skill => {
attributes = {...attributes, ...mapSkill(skill)};
});
data?.lores?.common?.forEach(skill => {
attributes = {...attributes, ...mapRepeatingSkill(skill, 'common-lore')};
});
data?.lores?.scholastic?.forEach(skill => {
attributes = {...attributes, ...mapRepeatingSkill(skill, 'scholastic-lore')};
});
data?.lores?.forbidden?.forEach(skill => {
attributes = {...attributes, ...mapRepeatingSkill(skill, 'forbidden-lore')};
});
data?.linguistics?.forEach(skill => {
attributes = {...attributes, ...mapRepeatingSkill(skill, 'linguistics')};
});
data?.trades?.forEach(skill => {
attributes = {...attributes, ...mapRepeatingSkill(skill, 'trade')};
});
// TALENTS, TRAITS
data?.abilities?.forEach(ability => {
attributes = {...attributes, ...mapAbility(ability, 'abilities')};
});
data?.traits?.forEach(trait => {
attributes = {...attributes, ...mapTrait(trait)};
});
// INVENTORY
data?.inventory?.weapons?.ranged?.forEach( weapon => {
attributes = {...attributes, ...mapRangedWeapon(weapon)};
});
data?.inventory?.weapons?.melee?.forEach( weapon => {
attributes = {...attributes, ...mapMeleeWeapon(weapon)};
});
data?.inventory?.gears?.forEach( gear => {
attributes = {...attributes, ...mapGear(gear)};
});
// data?.inventory?.tools?.forEach( tool => {
// attributes = {...attributes, ...mapTool(tool)};
// });
// data?.inventory?.consumables?.forEach( drug => {
// attributes = {...attributes, ...mapDrug(drug)};
// });
attributes = {...attributes, ...mapOldArmor(data?.inventory?.armor)};
// data?.inventory?.armors?.forEach( armor => {
// attributes = {...attributes, ...mapArmor(armor)};
// });
// data?.inventory?.ammos?.forEach( ammo => {
// attributes = {...attributes, ...mapAmmo(ammo)};
// });
data?.inventory?.cybernetics?.forEach( cybernetic => {
attributes = {...attributes, ...mapCybernetic(cybernetic)};
});
// ADVANCEMENTS
attributes = {...attributes, ...mapAptitudes(data?.advancements?.aptitudes)};
attributes = {...attributes, ...mapAdvance(data?.advancements?.advances)};
for (var training in data?.advancements?.training) {
attributes[`weapons_training_${training}`] = data?.advancements?.training[training];
}
// INSANITY, CORRUPTION
attributes[`insanity_pts`] = data?.insanity?.points;
data?.insanity?.disorders?.forEach( disorder => {
attributes = {...attributes, ...mapDisorder(disorder)};
})
attributes[`corruption_pts`] = data?.corruption?.points;
data?.corruption?.mutations?.forEach( mutation => {
attributes = {...attributes, ...mapMutation(mutation)};
})
// OBJECTIVES, NOTES
data?.objectives?.forEach( objective => {
attributes = {...attributes, ...mapObjective(objective)};
});
data?.notes?.forEach( note => {
attributes = {...attributes, ...mapNote(note)};
});
// VEHICLES
data?.vehicles?.list?.forEach( vehicle => {
attributes = {...attributes, ...mapVehicle(vehicle)};
});
data?.vehicles?.weapons?.ranged?.forEach( weapon => {
attributes = {...attributes, ...mapRangedWeapon(weapon, true)};
});
data?.vehicles?.weapons?.melee?.forEach( weapon => {
attributes = {...attributes, ...mapMeleeWeapon(weapon, true)};
});
// PSYKANA
attributes = {...attributes, ...mapPsykana(data?.psykana)};
data?.psykana?.minor?.forEach( minor => {
attributes = {...attributes, ...mapPsyMinor(minor)}
})
data?.psykana?.notes?.forEach( note => {
attributes = {...attributes, ...mapPsyNote(note)}
})
data?.psykana?.powers?.forEach( power => {
attributes = {...attributes, ...mapPsyPower(power)}
})
console.log('setting attributes');
attributes.import_value = 'Success: Character Imported Successfully\n\nRemember to add the token manually';
setAttrs(attributes, true);
})
})
// Update to new version
let oldVariables = [
'gear_carry','gear_name','gear_crafts', 'gear_quantity','gear_avail','gear_weight','gear_pg#','gear_desc'
]
on('sheet:opened', () => {
getAttrs(oldVariables, values => {
var attributes = {}
let gear = {carry: values['gear_carry'], name: values['gear_name'], craft: values['gear_crafts'], quantity: values['gear_quantity'], avail: values['gear_avail'], weight: values['gear_weight'], desc: values['gear_desc']}
if (!gear.name == '') attributes = {...attributes, ...mapGear(gear)}
console.table(gear)
console.log(attributes)
})
})
// functions
const mapInfo = (data) => {
let attr = {};
attr['character_name'] = data.name || '';
attr['Homeworld'] = data.homeworld || '';
attr['Background'] = data.background || '';
attr['Role'] = data.role || '';
attr['EliteAdvances'] = data.eliteAdvances || '';
attr['Notes'] = data.note || '';
attr['Player'] = data.player || '';
attr['appearance'] = data.appearance || '';
attr['Quirks'] = data.quirks || '';
attr['Divination'] = data.divination || '';
attr['Superstition'] = data.superstition || '';
attr['size'] = data.size || '';
attr['xp_total'] = data.xp || '';
attr['agi_mov_mod'] = data.movementModifier || '';
return attr;
};
const mapStat = (statName, stat) => {
let attr = {};
attr[`${statName}`] = stat.base || 0;
attr[`${statName}_advancement`] = stat.advancement || 0;
attr[`${statName}_mod`] = stat.modifier || 0;
attr[`${statName}_unnat`] = stat.unnatural || 0;
return attr;
};
const mapWounds = (wounds) => {
let attr = {};
attr['wounds'] = wounds.current || '';
attr['wounds_max'] = wounds.max || '';
attr['head'] = wounds.critical?.head || '';
attr['body'] = wounds.critical?.body || '';
attr['arm_left'] = wounds.critical?.arm_left || '';
attr['arm_right'] = wounds.critical?.arm_right || '';
attr['leg_left'] = wounds.critical?.leg_left || '';
attr['leg_right'] = wounds.critical?.leg_right || '';
return attr;
};
const mapFate = (fate) => {
let attr = {};
attr['fate'] = fate.current || '';
attr['fate_max'] = fate.max || '';
attr['settings_fate'] = fate.setting || '';
return attr;
};
const mapFatigue = (fatigue) => {
let attr = {};
attr['fatigue'] = fatigue.current || '';
attr['fatigue_mod'] = fatigue.modifier || '';
return attr;
};
const mapForceField = (forcefield) => {
let attr = {};
attr['forcefield_name'] = forcefield.name || '';
attr['forcefield_protection'] = forcefield.protection || '';
attr['forcefield_overload'] = forcefield.overload || '';
return attr;
};
const mapCondition = (condition) => {
if (!condition) return ;
let attr = {},
section = 'condition',
id = generateRowID();
attr[`repeating_${section}_${id}_condition_r`] = condition.name || '';
attr[`repeating_${section}_${id}_condition_desc_r`] = condition.description || '';
return attr;
};
const mapSkill = (skill) => {
if (!skill) return ;
let attr = {}
attr[`mod2_${skill.name}`] = skill.modifier || 0;
attr[`mod3_${skill.name}`] = skill.level || 0;
return attr;
};
const mapRepeatingSkill = (skill, section) => {
if (!skill) return ;
let attr = {},
id = generateRowID();
attr[`repeating_${section}_${id}_${section}_name`] = skill.name || '';
attr[`repeating_${section}_${id}_${section}_r_mod2`] = skill.modifier || '';
attr[`repeating_${section}_${id}_${section}_r_mod3`] = skill.level || '';
return attr;
};
const mapAbility = (ability) => {
if (!ability) return ;
let attr = {},
section = 'abilities',
id = generateRowID();
attr[`repeating_${section}_${id}_ability_r`] = ability.name || '';
attr[`repeating_${section}_${id}_ability_desc_r`] = ability.description || '';
return attr;
};
const mapTrait = (trait) => {
if (!trait) return ;
let attr = {},
section = 'traits',
id = generateRowID();
attr[`repeating_${section}_${id}_trait_r`] = trait.name || '';
attr[`repeating_${section}_${id}_trait_desc_r`] = trait.description || '';
return attr;
}
const mapAptitudes = (aptitudes) => {
var attr = {};
var section = 'aptitudes';
for (var i = 0; i < aptitudes?.length; i += 3) {
let id = generateRowID();
attr[`repeating_${section}_${id}_aptitude_nameL_r`] = aptitudes[i] || '';
attr[`repeating_${section}_${id}_aptitude_nameM_r`] = aptitudes[i+1] || '';
attr[`repeating_${section}_${id}_aptitude_nameR_r`] = aptitudes[i+2] || '';
}
return attr;
};
const mapRangedWeapon = (weapon, vehicle) => {
if (!weapon) return ;
let attr = {},
section = (vehicle) ? 'vehiclerangedweapons' : 'rangedweapons',
id = generateRowID();
if (vehicle) id += '_V';
attr[`repeating_${section}_${id}_R_weapon_name`] = weapon.name || '';
attr[`repeating_${section}_${id}_R_weapon_class`] = weapon.class || '';
attr[`repeating_${section}_${id}_R_weapon_range`] = weapon.range || '';
attr[`repeating_${section}_${id}_R_weapon_dam-roll`] = weapon.damage || '';
attr[`repeating_${section}_${id}_R_weapon_pen`] = weapon.pen || '';
attr[`repeating_${section}_${id}_R_weapon_type`] = weapon.type || '';
attr[`repeating_${section}_${id}_R_weapon_max`] = weapon.max || '';
attr[`repeating_${section}_${id}_R_weapon_min`] = weapon.min || '';
attr[`repeating_${section}_${id}_R_weapon_vengeful`] = weapon.vengeful || '';
attr[`repeating_${section}_${id}_R_weapon_accurate`] = weapon.accurate || '';
attr[`repeating_${section}_${id}_R_weapon_burst`] = weapon.burst || '';
attr[`repeating_${section}_${id}_R_weapon_auto`] = weapon.auto || '';
attr[`repeating_${section}_${id}_R_weapon_mag`] = weapon.mag || '';
attr[`repeating_${section}_${id}_R_weapon_mag_max`] = weapon.mag_max || '';
attr[`repeating_${section}_${id}_R_weapon_trained`] = weapon.trained || '';
attr[`repeating_${section}_${id}_R_weapon_mod1`] = weapon.mod1 || '';
attr[`repeating_${section}_${id}_R_weapon_reload`] = weapon.reload || '';
attr[`repeating_${section}_${id}_R_weapon_weight`] = weapon.weight || '';
attr[`repeating_${section}_${id}_R_weapon_domain`] = weapon.domain || '';
attr[`repeating_${section}_${id}_R_weapon_mishap_chance`] = weapon.mishap_chance || '';
attr[`repeating_${section}_${id}_R_weapon_carry`] = weapon.carry || '';
attr[`repeating_${section}_${id}_R_weapon_ability_r`] = weapon.special || '';
attr[`repeating_${section}_${id}_R_weapon_ability_desc_r`] = weapon.description || '';
return attr;
}
const mapMeleeWeapon = (weapon, vehicle) => {
if (!weapon) return ;
let attr = {},
section = (vehicle) ? 'vehiclemeleeweapons' : 'meleeweapons',
id = generateRowID();
if (vehicle) id += '_V';
attr[`repeating_${section}_${id}_M_weapon_name`] = weapon.name || '';
attr[`repeating_${section}_${id}_M_weapon_class`] = weapon.class || '';
attr[`repeating_${section}_${id}_M_weapon_reach`] = weapon.reach || '';
attr[`repeating_${section}_${id}_M_weapon_dam-roll`] = weapon.damage || '';
attr[`repeating_${section}_${id}_M_weapon_pen`] = weapon.pen || '';
attr[`repeating_${section}_${id}_M_weapon_type`] = weapon.type || '';
attr[`repeating_${section}_${id}_M_weapon_max`] = weapon.max || '';
attr[`repeating_${section}_${id}_M_weapon_min`] = weapon.min || '';
attr[`repeating_${section}_${id}_M_weapon_vengeful`] = weapon.vengeful || '';
attr[`repeating_${section}_${id}_M_weapon_trained`] = weapon.trained || '';
attr[`repeating_${section}_${id}_M_weapon_mod1`] = weapon.mod1 || '';
attr[`repeating_${section}_${id}_M_weapon_weight`] = weapon.weight || '';
attr[`repeating_${section}_${id}_M_weapon_domain`] = weapon.domain || '';
attr[`repeating_${section}_${id}_M_weapon_carry`] = weapon.carry || '';
attr[`repeating_${section}_${id}_M_weapon_ability_r`] = weapon.special || '';
attr[`repeating_${section}_${id}_M_weapon_ability_desc_r`] = weapon.description || '';
return attr;
}
const mapGear = (gear) => {
if (!gear) return ;
let attr = {},
section = 'gear',
id = generateRowID();
attr[`repeating_${section}_${id}_gear_carry`] = gear.carry || '';
attr[`repeating_${section}_${id}_gear_name_r`] = gear.name || '';
attr[`repeating_${section}_${id}_gear_crafts_r`] = gear.craftsmanship || '';
attr[`repeating_${section}_${id}_gear_quantity_r`] = gear.quantity || '';
attr[`repeating_${section}_${id}_gear_avail_r`] = gear.availability || '';
attr[`repeating_${section}_${id}_gear_weight_r`] = gear.weight || '';
attr[`repeating_${section}_${id}_ability_desc_r`] = gear.description || '';
return attr;
}
const mapCybernetic = (cybernetic) => {
if (!cybernetic) return ;
let attr = {},
section = 'cybernetics',
id = generateRowID();
attr[`repeating_${section}_${id}_cybernetic_name_r`] = cybernetic.name || '';
attr[`repeating_${section}_${id}_cybernetic_location_r`] = cybernetic.location || '';
attr[`repeating_${section}_${id}_cybernetic_desc_r`] = cybernetic.description || '';
return attr;
}
const mapOldArmor = (armor) => {
let attr = {};
attr.armor_AGI = armor.maxAgi || '';
attr.armor_limit = armor.limit || '';
attr.armor_head = armor.head || '';
attr.armor_body = armor.body || '';
attr.armor_arm_right = armor.arm_right || '';
attr.armor_arm_left = armor.arm_left || '';
attr.armor_leg_right = armor.leg_right || '';
attr.armor_leg_left = armor.leg_left || '';
attr.armor_name = armor.description || '';
return attr;
}
const mapAdvance = (advance) => {
var attr = {};
var section = 'advancements';
for (var i = 0; i < advance?.length; i += 2) {
let id = generateRowID();
attr[`repeating_${section}_${id}_advancement_nameL_r`] = advance[i]?.name || '';
attr[`repeating_${section}_${id}_advancement_costL_r`] = advance[i]?.cost || '';
attr[`repeating_${section}_${id}_advancement_nameR_r`] = advance[i+1]?.name || '';
attr[`repeating_${section}_${id}_advancement_costR_r`] = advance[i+1]?.cost || '';
}
return attr;
};
const mapDisorder = (disorder) => {
if (!disorder) return;
let attr = {},
section = 'disorders',
id = generateRowID();
attr[`repeating_${section}_${id}_disorder_r`] = disorder.name || '';
attr[`repeating_${section}_${id}_disorder_desc_r`] = disorder.description || '';
return attr;
}
const mapMutation = (mutation) => {
if (!mutation) return;
let attr = {},
section = 'mutations',
id = generateRowID();
attr[`repeating_${section}_${id}_mutation_r`] = mutation.name || '';
attr[`repeating_${section}_${id}_mutation_desc_r`] = mutation.description || '';
return attr;
}
const mapObjective = (objective) => {
if (!objective) return;
let attr = {},
section = 'objectives',
id = generateRowID();
attr[`repeating_${section}_${id}_objective_r`] = objective.name || '';
attr[`repeating_${section}_${id}_objective_completed`] = objective.complete || '';
return attr;
}
const mapNote = (note) => {
if (!note) return;
let attr = {},
section = 'notes',
id = generateRowID();
attr[`repeating_${section}_${id}_notes`] = note.name || '';
return attr;
}
const mapVehicle = (vehicle) => {
if (!vehicle) return;
let attr = {},
section = 'vehicles',
id = generateRowID();
attr[`repeating_${section}_${id}_vehicle-name`] = vehicle.name || '';
attr[`repeating_${section}_${id}_vehicle-size`] = vehicle.size || '';
attr[`repeating_${section}_${id}_vehicle-world`] = vehicle.world || '';
attr[`repeating_${section}_${id}_vehicle-type`] = vehicle.type || '';
attr[`repeating_${section}_${id}_vehicle-tactical`] = vehicle.tactical || '';
attr[`repeating_${section}_${id}_vehicle-cruising`] = vehicle.cruising || '';
attr[`repeating_${section}_${id}_vehicle-maneuver`] = vehicle.maneuver || '';
attr[`repeating_${section}_${id}_vehicle-crew`] = vehicle.crew || '';
attr[`repeating_${section}_${id}_vehicle-compliment`] = vehicle.compliment || '';
attr[`repeating_${section}_${id}_vehicle-integrity`] = vehicle.integrity || '';
attr[`repeating_${section}_${id}_vehicle-integrity_max`] = vehicle.integrity_max || '';
attr[`repeating_${section}_${id}_vehicle-armor-front`] = vehicle['armor-front'] || '';
attr[`repeating_${section}_${id}_vehicle-armor-side`] = vehicle['armor-side'] || '';
attr[`repeating_${section}_${id}_vehicle-armor-rear`] = vehicle['armor-rear'] || '';
attr[`repeating_${section}_${id}_armaments`] = vehicle.armaments || '';
attr[`repeating_${section}_${id}_armaments_desc`] = vehicle.armaments_desc || '';
attr[`repeating_${section}_${id}_vehicle_traits`] = vehicle.traits || '';
attr[`repeating_${section}_${id}_vehicle_traits_desc`] = vehicle.traits_desc || '';
attr[`repeating_${section}_${id}_modifications`] = vehicle.modifications || '';
attr[`repeating_${section}_${id}_modifications_desc`] = vehicle.modifications_desc || '';
return attr;
}
const mapPsykana = (psykana) => {
let attr = {};
attr[`psykana_class`] = psykana.class || '';
attr[`psykana_limit`] = psykana.limit || '';
attr[`psy_rating`] = psykana.rating || '';
attr[`psy_push`] = psykana.push || '';
attr[`psykana_sustain`] = psykana.sustain || '';
attr[`focus_mod`] = psykana.focus_mod || '';
attr[`psykana_sustain_count`] = psykana.sustain_count || '';
return attr;
};
const mapPsyMinor = (minor) => {
if (!minor) return
let attr = {},
section = 'minormanifestation',
id = generateRowID();
attr[`repeating_${section}_${id}_P_minor_r`] = minor.name || '';
attr[`repeating_${section}_${id}_P_minor_desc_r`] = minor.description || '';
return attr;
}
const mapPsyNote = (note) => {
if (!note) return
let attr = {},
section = 'psynotes',
id = generateRowID();
attr[`repeating_${section}_${id}_P_note_r`] = note.name || '';
attr[`repeating_${section}_${id}_P_note_desc_r`] = note.description || '';
return attr;
}
const mapPsyPower = (power) => {
if (!power) return;
let attr = {},
section = 'psychicabilities',
id = generateRowID();
attr[`repeating_${section}_${id}_P_name`] = power.name || '';
attr[`repeating_${section}_${id}_P_subtype`] = power.subtype || '';
attr[`repeating_${section}_${id}_P_range`] = power.range || '';
attr[`repeating_${section}_${id}_P_dam-roll`] = power.damage || '';
attr[`repeating_${section}_${id}_P_type`] = power.type || '';
attr[`repeating_${section}_${id}_P_pen`] = power.pen || '';
attr[`repeating_${section}_${id}_P_focus`] = power.focus || '';
attr[`repeating_${section}_${id}_P_mod1`] = power.mod || '';
attr[`repeating_${section}_${id}_P_multi`] = power.multi || '';
attr[`repeating_${section}_${id}_P_action`] = power.action || '';
attr[`repeating_${section}_${id}_P_sustained`] = power.sustained || '';
attr[`repeating_${section}_${id}_P_hitloc`] = power.hitloc || '';
attr[`repeating_${section}_${id}_P_ability_r`] = power.ability || '';
attr[`repeating_${section}_${id}_P_desc_r`] = power.desc || '';
return attr;
}