@@ -5182,7 +5199,7 @@
// 2. Define the character-level attributes needed for both.
const globalAttrsToGet = prefix === 'repeating_npcabilities'
- ? [] // Monster abilities need nothing
+ ? ['kit_melee_damage_1','kit_melee_damage_2','kit_melee_damage_3'] // Companions need melee kit values
: ['resource_name','kit_melee_damage_1','kit_melee_damage_2','kit_melee_damage_3','kit_ranged_damage_1','kit_ranged_damage_2','kit_ranged_damage_3', 'mag_psi_dam', 'sanct_weap' ]; // Player abilities need resource names and kit damage info
const characteristics = isPowerRoll ? ['might', 'agility', 'reason', 'intuition', 'presence'] : [];
@@ -5237,7 +5254,7 @@
parseInt(attrs[`kit_${type}_damage_2`]) || 0,
parseInt(attrs[`kit_${type}_damage_3`]) || 0
];
-
+
if (attrs['sanct_weap']) {
otherDamage += `+${attrs['sanct_weap']}[${getTranslationByKey('sanct-weap')}]`;
}
@@ -6004,6 +6021,7 @@
CHARACTERISTIC_BONUS: 'Characteristic Bonus',
MALICE_ABILITY: 'Malice Ability',
CONDITION_IMMUNITY: 'Condition Immunity',
+ SUMMON_CHOICE: 'Summon Choice',
};
/**
@@ -6372,7 +6390,87 @@
}
});
-
+ // --- Import Companion Event Listener ---
+ on('clicked:importcompanion', async () => {
+ try {
+ // Get the raw JSON string from the character sheet attributes.
+ const data = await loadForgeSteelData();
+ if (!data) { return };
+
+ // Check if the data is for a single monster or a monster group
+ if (data.hasOwnProperty('class')) {
+ const allFeatures = getFeatures(data);
+ //Get relevant player chaaracter 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) => {
+ acc[s.toLowerCase()] = calculateCharacteristic(allFeatures, s, baseStats[s]);
+ return acc;
+ }, {});
+ const stamina_max = calculateModifiedStat('Stamina', 0, level, characteristics ,allFeatures);
+
+ const classAbilities = allFeatures
+ .filter(f => f.type === FEATURE_TYPES.CLASS_ABILITY)
+ .flatMap(f => f.data.selectedIDs)
+ .reduce((acc, id) => {
+ const abilityData = extractClassAbility(data, id);
+ console.log(abilityData.keywords);
+ if (abilityData.keywords.includes('Beastheart')) {
+ return { ...acc };
+ }
+ return { ...acc, ...processMonsterAbility(abilityData) };
+ }, {});
+
+ const abilityFeatures = allFeatures
+ .filter(f => f.type === FEATURE_TYPES.ABILITY)
+ .reduce((acc, f) => {
+ if (f.data.ability.keywords.includes('Beastheart')) {
+ return { ...acc };
+ }
+ 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.");
+
+ // Extract the companion data
+ const companionData = companionFeature[0].data?.selected[0];
+
+ if (!companionData) {
+ 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 newAttrs = {
+ level,
+ stamina_max,
+ stamina: stamina_max,
+ npc_freestrike: parseInt(companionData.monster.freeStrikeDamage) + characteristics['might'],
+ ...abilityFeatures,
+ ...classAbilities,
+ };
+
+ // Set the altered attributes on the character sheet.
+ await setAttrsAsync(newAttrs);
+
+ //Last bit of character sheet setup
+ calculateWinded();
+ console.log('Companion import successful!', newAttrs);
+ } else {
+ console.error('No companion information.');
+ return;
+ }
+ } catch (error) {
+ console.error("Failed to import monster data.", error);
+ }
+ });
/**
* Imports player data from a loaded JSON file
* @param {object} data the loaded and validated JSON file
@@ -6642,6 +6740,7 @@
size: sizeString,
speed: dataSpeed.value ?? 5,
stamina,
+ stamina_max: stamina,
stability,
npc_freestrike: freeStrikeDamage,
immunity: getDamageModifiers(data.features, 1, 'Immunity'),
@@ -7040,6 +7139,8 @@
convertRepeatingKits();
// Set new Damage Calculation option (v1.3)
+ // Set new Sticky Charactersitic Panel option (v1.4)
+ // Set new Monster Malice Tab option (v1.5)
setNewOptions();
//Sets the sheet's new version
diff --git a/Draw Steel/translation.json b/Draw Steel/translation.json
index 0c7c3d1123..a7d7a5b5b1 100644
--- a/Draw Steel/translation.json
+++ b/Draw Steel/translation.json
@@ -585,5 +585,6 @@
"beastheart-rampage-table-20": "20 (7th level)",
"beastheart-rampage-table-20-text": "As a free maneuver, your companion can increase their size up to size 2, or increase their size by 1 if their original size is already 2 or larger. This size increase lasts until your companion’s rampage ends or they use a free maneuver to end it. While your companion’s size is increased, they gain a +2 bonus to speed and stability, the potencies of their abilities increase by 1, and the size of their Feral Strike ability’s burst increases by 1.",
"beastheart-rampage-table-24": "24 (10th level)",
- "beastheart-rampage-table-24-text": "When your companion increases their size, they can increase it up to size 3, or increase their size by 1 if their original size is already 3 or larger. Whenever they make a power roll while their size is increased this way, they can roll 3d10 and discard the lowest roll."
+ "beastheart-rampage-table-24-text": "When your companion increases their size, they can increase it up to size 3, or increase their size by 1 if their original size is already 3 or larger. Whenever they make a power roll while their size is increased this way, they can roll 3d10 and discard the lowest roll.",
+ "import-companion": "Import Companion (Beastheart)"
}