diff --git a/app/imports/api/engine/computation/computeComputation/computeByType.js b/app/imports/api/engine/computation/computeComputation/computeByType.js
index 7597b976..0b5633e3 100644
--- a/app/imports/api/engine/computation/computeComputation/computeByType.js
+++ b/app/imports/api/engine/computation/computeComputation/computeByType.js
@@ -5,6 +5,7 @@ import skill from './computeByType/computeSkill.js';
import pointBuy from './computeByType/computePointBuy.js';
import propertySlot from './computeByType/computeSlot.js';
import container from './computeByType/computeContainer.js';
+import spellList from './computeByType/computeSpellList.js';
import _calculation from './computeByType/computeCalculation.js';
export default Object.freeze({
@@ -17,4 +18,5 @@ export default Object.freeze({
pointBuy,
propertySlot,
spell: action,
+ spellList,
});
diff --git a/app/imports/api/engine/computation/computeComputation/computeByType/computeSpellList.js b/app/imports/api/engine/computation/computeComputation/computeByType/computeSpellList.js
new file mode 100644
index 00000000..63dc6003
--- /dev/null
+++ b/app/imports/api/engine/computation/computeComputation/computeByType/computeSpellList.js
@@ -0,0 +1,6 @@
+export default function computeSpelllist(computation, node) {
+ const prop = node.data;
+
+ const ability = computation.scope[prop.ability];
+ prop.abilityMod = ability?.modifier || 0;
+}
\ No newline at end of file
diff --git a/app/imports/api/properties/SpellLists.js b/app/imports/api/properties/SpellLists.js
index 01434ea2..285832eb 100644
--- a/app/imports/api/properties/SpellLists.js
+++ b/app/imports/api/properties/SpellLists.js
@@ -17,6 +17,12 @@ let SpellListSchema = createPropertySchema({
type: 'fieldToCompute',
optional: true,
},
+ // The variable name of the ability this spell relies on
+ ability: {
+ type: String,
+ optional: true,
+ max: STORAGE_LIMITS.variableName,
+ },
// Calculation of The attack roll bonus used by spell attacks in this list
attackRollBonus: {
type: 'fieldToCompute',
@@ -38,6 +44,12 @@ const ComputedOnlySpellListSchema = createPropertySchema({
type: 'computedOnlyField',
optional: true,
},
+ // Computed value determined by the ability
+ abilityMod: {
+ type: SimpleSchema.Integer,
+ optional: true,
+ removeBeforeCompute: true,
+ },
attackRollBonus: {
type: 'computedOnlyField',
optional: true,
diff --git a/app/imports/ui/creature/character/printedCharacterSheet/components/PrintedSpellList.vue b/app/imports/ui/creature/character/printedCharacterSheet/components/PrintedSpellList.vue
index 0ee80376..e158000f 100644
--- a/app/imports/ui/creature/character/printedCharacterSheet/components/PrintedSpellList.vue
+++ b/app/imports/ui/creature/character/printedCharacterSheet/components/PrintedSpellList.vue
@@ -6,6 +6,12 @@
Spell Save DC: {{ model.dc && model.dc.value }}
+
+ Spell casting ability: {{ model.ability }}
+
+
+ Spell casting ability modifier: {{ model.abilityMod }}
+
Spell Attack Bonus: {{ model.attackRollBonus && model.attackRollBonus.value }}
diff --git a/app/imports/ui/properties/forms/SpellListForm.vue b/app/imports/ui/properties/forms/SpellListForm.vue
index b44ea60c..3855b78a 100644
--- a/app/imports/ui/properties/forms/SpellListForm.vue
+++ b/app/imports/ui/properties/forms/SpellListForm.vue
@@ -27,6 +27,15 @@
$emit('change', {path: ['maxPrepared', ...path], value, ack})"
/>
+
+
import propertyFormMixin from '/imports/ui/properties/forms/shared/propertyFormMixin.js';
+import createListOfProperties from '/imports/ui/properties/forms/shared/lists/createListOfProperties.js';
export default {
mixins: [propertyFormMixin],
+ meteor: {
+ abilityScoreList() {
+ return createListOfProperties({
+ type: 'attribute',
+ attributeType: 'ability',
+ });
+ },
+ },
+ methods: {
+ changeAbility(value, ack) {
+ this.$emit('change', { path: ['ability'], value, ack })
+ const oldValue = this.model.ability;
+
+ const attackRollBonus = this.model.attackRollBonus?.calculation;
+ if (
+ !attackRollBonus ||
+ attackRollBonus === `proficiencyBonus + ${oldValue}.modifier`
+ ) {
+ this.$emit('change', {
+ path: ['attackRollBonus', 'calculation'],
+ value: `proficiencyBonus + ${value}.modifier`
+ });
+ }
+
+ const dc = this.model.dc?.calculation;
+ if (
+ !dc ||
+ dc === `8 + proficiencyBonus + ${oldValue}.modifier`
+ ) {
+ this.$emit('change', {
+ path: ['dc', 'calculation'],
+ value: `8 + proficiencyBonus + ${value}.modifier`
+ });
+ }
+ }
+ }
};
diff --git a/app/imports/ui/properties/viewers/SpellListViewer.vue b/app/imports/ui/properties/viewers/SpellListViewer.vue
index f7c35b57..6aae147e 100644
--- a/app/imports/ui/properties/viewers/SpellListViewer.vue
+++ b/app/imports/ui/properties/viewers/SpellListViewer.vue
@@ -13,6 +13,18 @@
center
:calculation="model.maxPrepared"
/>
+
+
- {{ value }}
+ {{ valueText }}
{{ calculationText }}
@@ -117,6 +117,13 @@ export default {
if (!this.calculation) return;
return typeof this.calculation.value === 'string'
},
+ valueText() {
+ if (this.signed) {
+ return numberToSignedString(this.value);
+ } else {
+ return this.value;
+ }
+ },
calculationText(){
const calculation = this.calculation;
if (!calculation) {
diff --git a/app/private/docs/property/spell-list.md b/app/private/docs/property/spell-list.md
index b36885c8..6216b3c0 100644
--- a/app/private/docs/property/spell-list.md
+++ b/app/private/docs/property/spell-list.md
@@ -18,6 +18,10 @@ Allows [inline calculations](/docs/inline-calculations).
A [computed field](/docs/computed-fields) that determines how many spells can be considered ready to cast in this spell list.
+### Spell casting ability
+
+The spellcasting ablity for this spell list. The variable name of the ability can be accessed using `#spellList.ability` and the ability modifier with `#spellList.abilityMod`. Setting this field will automatically update Spell save DC and Attack roll bonus if they aren't set manually.
+
### Spell save DC
A [computed field](/docs/computed-fields) that determines the DC of saving throws in this spell list. Spells can access the DC of their spell list using `#spellList.dc`