-
Notifications
You must be signed in to change notification settings - Fork 235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[#4604] Rework spellcasting configurations #4947
base: 4.2.x
Are you sure you want to change the base?
Conversation
@@ -212,6 +242,8 @@ export default class SpellData extends ItemDataModel.mixin(ActivitiesTemplate, I | |||
}, { all: [], vsm: [], tags: [] }); | |||
labels.components.vsm = game.i18n.getListFormatter({ style: "narrow" }).format(labels.components.vsm); | |||
|
|||
this.preparation.static = (CONFIG.DND5E.spellcasting[this.preparation.mode] ?? { static: true }).static === true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A spell belongs to a "static" preparation mode if said prep mode does not exist, or is static: true
.
* Does this item scale with any kind of consumption? | ||
* @type {string|null} | ||
*/ | ||
get usageScaling() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wasn't used anywhere.
static prepareLeveledSlots(spells, actor, progression, key) { | ||
const slots = CONFIG.DND5E.spellcasting.calculateSlots(key, progression[key]); | ||
for ( const level of Array.fromRange(Object.keys(CONFIG.DND5E.spellLevels).length - 1, 1) ) { | ||
const slot = spells[`${key}${level}`] ??= { value: 0 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During data prep, if the spellcasting is separate
, then objects with a key of <name><level>
will be created (such as "spell1" through "spell9"), otherwise a single object is created (eg "pact").
This is entirely dynamic, and can be tested by setting pact.table = "spell"
and pact.separate = true
, which results in pact1
through pact9
.
const slots = CONFIG.DND5E.spellcasting.calculateSlots(key, progression[key]); | ||
for ( const level of Array.fromRange(Object.keys(CONFIG.DND5E.spellLevels).length - 1, 1) ) { | ||
const slot = spells[`${key}${level}`] ??= { value: 0 }; | ||
slot.label = CONFIG.DND5E.spellLevels[level]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a better label. It is currently used only in Favorites, I believe.
3fcc95b
to
9924e33
Compare
DND5E.spellcasting
andDND5E.spellcastingTables
.prepared
mode is now justspell
(was initiallyleveled
but it simplified a lot of code throughout to just have it be identical to the name of the object withinActor#system#spells
).always
preparation mode is no more, and is instead part ofSpellData#preparation.prepared
. This property is no longer a boolean but 0, 1, or 2 (unprepared, prepared, always prepared). Migrations are added for spell items and item grant/choice advancements.DND5E.restTypes
instead of in two locations.The
DND5E.spellcasting
object entirely controls the preparation and setup of a spellcasting type. Whether it grants spell slots at all (static
, for ritual/innate/atwill), whether the slots are spread out across multiple levels (separate
, for leveled vs pact slots), whether the spells of this mode can be prepared/always prepared (prepares
), and whether it grants cantrips (cantrips
).Each of these types also have
progression
, identical to how leveled spell progressions are set up. Thepact
progression is considered a "Full" pact caster. This will make it trivial to add for example a type of pact magic caster that gains pact slots at a higher or lower rate. (This has no repercussions for existing warlocks.)Caveats:
The
DND5E.spellcastingTables
object is a bit different than usual. Rather than describing the amount of slots at each level (and level of said slots), it describes the increase of slots (or level of slots) at each level. A method,CONFIG.DND5E.spellcasting.calculateSlots
, is added to get the total configuration of slots at a given level. This makes it easier to make small adjustments such as adding a single 1st-level spell slot at 9th level; you would only need to add1: 1
at level 9 rather than editing each level from 9 and onwards.The new
DND5E.spellPreparationStates
contains the labels and values of the preparation states (0: unprepared; 1: prepared; 2: always prepared). This is localized and used to create the select options. In item grant/choice advancements, "prepared" is omitted.Possibly controversial changes:
A handful of the static method regarding spell slot configuration in the
Actor5e
class have been shuffled around a bit to generalize them for the purpose of this configuration. The hook(s) of course still exist and are technically breaking but only minorly so.Also fixed the fact that
_onDropResetData
was deleting the wrong property.Screenshots of various applications with changes:
TODO:
Actor5e
methods that were renamed.static
andseparate
to a singletype
(string) property to possible help with adding a "spell points" configuration at a later point.DND5E.spellcasting
(and the object itself) as custom data models? There are a lot of various checks throughout the code, it might reduce all this further to encapsulate it in a singleclass
.