diff --git a/Draw Steel/draw-steel.html b/Draw Steel/draw-steel.html
index fe72456b96..3dde9e99d6 100644
--- a/Draw Steel/draw-steel.html
+++ b/Draw Steel/draw-steel.html
@@ -101,7 +101,7 @@
-
+
@@ -5024,7 +5024,7 @@
.split(',')
.map(k => k.trim())
.filter(k => k !== "");
- console.log(isActive, modName, modValue, rawKeywords);
+
if (isActive) {
// Logic:
// - If modKeywords is empty, it applies to everything.
@@ -5036,7 +5036,6 @@
}
}
});
- console.log(globalDamage);
return globalDamage;
@@ -5727,6 +5726,12 @@
setAttrs(updateObj);
}
+ function reportError( name, text, extra = {} ) {
+ console.log('~~~ reportError ~~~');
+ directMap = { name, text, ...extra, };
+ buildRoll(ROLLTEMPLATES.SIMPLE, directMap, {}, false);
+ }
+
// Checks whether the ability tab buttons should be displayed on the Monster sheet
async function checkAbilityTabs() {
console.log('~~~ checkAbilityTabs ~~~');
@@ -5828,7 +5833,7 @@
flattenedFeatures.push(currentFeature);
}
}
- console.log(flattenedFeatures);
+
return flattenedFeatures;
}
@@ -5908,7 +5913,7 @@
.filter(f => f.type === FEATURE_TYPES.KIT_STATS)
.map(f => f[statName.toLowerCase()] || 0)
);
- console.log(statName + ':' + baseValue + ' ' + bonusFromFeatures + ' ' + bonusFromKits);
+
return baseValue + bonusFromFeatures + bonusFromKits;
};
@@ -5956,8 +5961,9 @@
.filter(f => f.type === FEATURE_TYPES.KIT_STATS)
.map(f => f[statName.toLowerCase()] || 0)
);
+ const echelonBonus = (statName === 'Stamina') ? echelon : 1;
- return baseValue + bonusFromFeatures + bonusFromKits;
+ return baseValue + bonusFromFeatures + (bonusFromKits * echelonBonus);
};
/**
@@ -6068,7 +6074,7 @@
}
});
- console.log(result);
+
return result;
};
@@ -6224,7 +6230,6 @@
return;
}
await importMonster(data.monsters[choice], data.malice);
- console.log(data.monsters[choice].name);
}
} catch (error) {
@@ -6239,10 +6244,16 @@
const data = await loadForgeSteelData();
if (!data) { return };
- // Check if the data is for a single monster or a monster group
+ // Check to make sure we are working with a player
if (data.hasOwnProperty('class')) {
const allFeatures = getFeatures(data);
- //Get relevant player chaaracter information
+
+ //Get the base companion
+ const companionFeature = allFeatures.filter(f => f.type === FEATURE_TYPES.SUMMON_CHOICE);
+
+ if (!companionFeature) throw new Error("No features found in JSON.");
+
+ //Get relevant player character information
const level = data.class.level;
const baseStats = data.class.characteristics.reduce((acc, i) => ({ ...acc, [i.characteristic]:i.value }), {});
const characteristics = ['Might', 'Agility', 'Reason', 'Intuition', 'Presence'].reduce((acc, s) => {
@@ -6256,7 +6267,6 @@
.flatMap(f => f.data.selectedIDs)
.reduce((acc, id) => {
const abilityData = extractClassAbility(data, id);
- console.log(abilityData.keywords);
if (abilityData.keywords.includes('Beastheart')) {
return { ...acc };
}
@@ -6272,10 +6282,7 @@
return { ...acc, ...processMonsterAbility(f.data.ability) };
}, {});
- //Get the base companion
- const companionFeature = allFeatures.filter(f => f.type === FEATURE_TYPES.SUMMON_CHOICE);
-
- if (!companionFeature) throw new Error("No features found in JSON.");
+ const kits = parseKits(allFeatures);
// Extract the companion data
const companionData = companionFeature[0].data?.selected[0];
@@ -6284,19 +6291,45 @@
throw new Error("Companion Data not found");
return;
}
- console.log(companionData);
- console.log(companionData.monster.freeStrikeDamage, characteristics['might']);
+
// Do the bulk of the import with the monster importer
await importMonster(companionData.monster, []);
+ const companionMight = companionData.monster.characteristics.find(c => c.characteristic === 'Might')?.value || 0;
+ const companionFeatures = Object.entries(companionData.info)
+ .filter(([key]) => {
+ // Extract the number from keys like "level3", "level6", "level10"
+ const featureLevel = parseInt(key.replace('level', ''));
+ // Include the feature only if the companion's level is high enough
+ return !isNaN(featureLevel) && level >= featureLevel;
+ })
+ .flatMap(([_, features]) => features)
+ .reduce((acc, f) => {
+ const id = generateRowID();
+ const prefix = `repeating_npcabilities_${id}`;
+
+ acc[`${prefix}_ability_name`] = f.name;
+ acc[`${prefix}_ability_subtype`] = 'trait';
+ acc[`${prefix}_ability_trait`] = f.description;
+ return acc;
+ }, {});
+
const newAttrs = {
level,
stamina_max,
stamina: stamina_max,
- npc_freestrike: parseInt(companionData.monster.freeStrikeDamage) + characteristics['might'],
+ npc_freestrike: parseInt(companionData.monster.freeStrikeDamage) + parseInt(companionMight),
+ options_is_companion: '1',
+ options_npc_advanced_stamina: '1',
+ kit_melee_damage_1: kits.kit_melee_damage_1,
+ kit_melee_damage_2: kits.kit_melee_damage_2,
+ kit_melee_damage_3: kits.kit_melee_damage_3,
+ speed: parseInt(companionData.monster.speed.value) + parseInt(kits.kit_speed),
+ stability: parseInt(companionData.monster.stability) + parseInt(kits.kit_stability),
...abilityFeatures,
...classAbilities,
+ ...companionFeatures,
};
// Set the altered attributes on the character sheet.
@@ -6307,6 +6340,7 @@
console.log('Companion import successful!', newAttrs);
} else {
console.error('No companion information.');
+ reportError('Import Error', 'No companion information.');
return;
}
} catch (error) {
@@ -6627,7 +6661,6 @@
function _processAbilityCore(abilityData, isNPC = false) {
console.log('~~~ processAbilityCore ~~~');
const id = generateRowID();
- //console.log(abilityData);
const { type: usageData, sections, cost: rawCost, name, description, keywords, target } = abilityData;
// Configuration & Naming