Skip to content

Commit

Permalink
[#1401] Update ItemChoice using new Advancement data models
Browse files Browse the repository at this point in the history
  • Loading branch information
arbron committed Dec 30, 2022
1 parent a4fb68d commit 436d335
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 36 deletions.
1 change: 1 addition & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
"DND5E.AdvancementDeleteConfirmationMessage": "Deleting this item will also delete all advancement choices made for it. These changes will be removed from your character as long as the checkbox below is checked.",
"DND5E.AdvancementDeleteConfirmationTitle": "Confirm Deletion",
"DND5E.AdvancementFlowDropAreaHint": "Drop an Item here to choose it.",
"DND5E.AdvancementHint": "Hint",
"DND5E.AdvancementHitPointsTitle": "Hit Points",
"DND5E.AdvancementHitPointsHint": "Track the player's hit points for each level in the class.",
"DND5E.AdvancementHitPointsAverage": "Take Average",
Expand Down
4 changes: 2 additions & 2 deletions module/applications/advancement/item-choice-config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default class ItemChoiceConfig extends AdvancementConfig {
for ( const type of this.advancement.constructor.VALID_TYPES ) {
data.validTypes[type] = game.i18n.localize(`ITEM.Type${type.capitalize()}`);
}
data.showSpellConfig = this.advancement.data.configuration.type === "spell";
data.showSpellConfig = this.advancement.configuration.type === "spell";
return data;
}

Expand All @@ -34,7 +34,7 @@ export default class ItemChoiceConfig extends AdvancementConfig {
if ( configuration.choices ) configuration.choices = this.constructor._cleanedObject(configuration.choices);

// Ensure items are still valid if type restriction or spell restriction are changed
configuration.pool ??= this.advancement.data.configuration.pool;
configuration.pool ??= this.advancement.configuration.pool;
configuration.pool = await configuration.pool.reduce(async (pool, uuid) => {
const item = await fromUuid(uuid);
if ( this.advancement._verifyItemType(item, {
Expand Down
16 changes: 8 additions & 8 deletions module/applications/advancement/item-choice-flow.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ export default class ItemChoiceFlow extends AdvancementFlow {
// Prepare initial data
this.selected ??= new Set(
this.retainedData?.items.map(i => foundry.utils.getProperty(i, "flags.dnd5e.sourceId"))
?? Object.values(this.advancement.data.value[this.level] ?? {})
?? Object.values(this.advancement.value[this.level] ?? {})
);
this.pool ??= await Promise.all(this.advancement.data.configuration.pool.map(fromUuid));
this.pool ??= await Promise.all(this.advancement.configuration.pool.map(fromUuid));
this.dropped ??= await (this.retainedData?.items ?? []).reduce(async (arrP, data) => {
const arr = await arrP;
const uuid = foundry.utils.getProperty(data, "flags.dnd5e.sourceId");
Expand All @@ -54,12 +54,12 @@ export default class ItemChoiceFlow extends AdvancementFlow {
return arr;
}, []);

const max = this.advancement.data.configuration.choices[this.level];
const max = this.advancement.configuration.choices[this.level];
const choices = { max, current: this.selected.size, full: this.selected.size >= max };

const previousLevels = {};
const previouslySelected = new Set();
for ( const [level, data] of Object.entries(this.advancement.data.value) ) {
for ( const [level, data] of Object.entries(this.advancement.value) ) {
if ( level > this.level ) continue;
previousLevels[level] = await Promise.all(Object.values(data).map(fromUuid));
Object.values(data).forEach(uuid => previouslySelected.add(uuid));
Expand Down Expand Up @@ -127,7 +127,7 @@ export default class ItemChoiceFlow extends AdvancementFlow {

/** @inheritdoc */
async _onDrop(event) {
if ( this.selected.size >= this.advancement.data.configuration.choices[this.level] ) return false;
if ( this.selected.size >= this.advancement.configuration.choices[this.level] ) return false;

// Try to extract the data
let data;
Expand All @@ -150,14 +150,14 @@ export default class ItemChoiceFlow extends AdvancementFlow {
if ( this.selected.has(item.uuid) ) return false;

// Check to ensure the dropped item hasn't been selected at a lower level
for ( const [level, data] of Object.entries(this.advancement.data.value) ) {
for ( const [level, data] of Object.entries(this.advancement.value) ) {
if ( level >= this.level ) continue;
if ( Object.values(data).includes(item.uuid) ) return;
}

// If spell level is restricted to available level, ensure the spell is of the appropriate level
const spellLevel = this.advancement.data.configuration.spell?.level;
if ( (this.advancement.data.configuration.type === "spell") && spellLevel === "available" ) {
const spellLevel = this.advancement.configuration.spell?.level;
if ( (this.advancement.configuration.type === "spell") && spellLevel === "available" ) {
const maxSlot = this._maxSpellSlotLevel();
if ( item.system.level > maxSlot ) return ui.notifications.error(game.i18n.format(
"DND5E.AdvancementItemChoiceSpellLevelAvailableWarning", { level: CONFIG.DND5E.spellLevels[maxSlot] }
Expand Down
1 change: 1 addition & 0 deletions module/data/advancement/_module.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export {default as BaseAdvancement} from "./base-advancement.mjs";
export {default as SpellConfigurationData} from "./spell-config.mjs";

export {default as ItemChoiceConfigurationData} from "./item-choice.mjs";
export {default as ItemGrantConfigurationData} from "./item-grant.mjs";
export * as scaleValue from "./scale-value.mjs";
27 changes: 27 additions & 0 deletions module/data/advancement/item-choice.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { MappingField } from "../fields.mjs";
import SpellConfigurationData from "./spell-config.mjs";

export default class ItemChoiceConfigurationData extends foundry.abstract.DataModel {
static defineSchema() {
return {
hint: new foundry.data.fields.StringField({label: "DND5E.AdvancementHint"}),
choices: new MappingField(new foundry.data.fields.NumberField(), {
required: true, hint: "DND5E.AdvancementItemChoiceLevelsHint"
}),
allowDrops: new foundry.data.fields.BooleanField({
required: true, initial: true, label: "DND5E.AdvancementConfigureAllowDrops",
hint: "DND5E.AdvancementConfigureAllowDropsHint"
}),
type: new foundry.data.fields.StringField({
required: true, blank: false, nullable: true, initial: null,
label: "DND5E.AdvancementItemChoiceType", hint: "DND5E.AdvancementItemChoiceTypeHint"
}),
pool: new foundry.data.fields.ArrayField(new foundry.data.fields.StringField(), {
required: true, label: "DOCUMENT.Items"
}),
spell: new foundry.data.fields.EmbeddedDataField(SpellConfigurationData, {
required: true, nullable: true, initial: null
})
};
}
}
20 changes: 7 additions & 13 deletions module/documents/advancement/item-choice.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Advancement from "./advancement.mjs";
import ItemChoiceConfig from "../../applications/advancement/item-choice-config.mjs";
import ItemChoiceFlow from "../../applications/advancement/item-choice-flow.mjs";
import ItemChoiceConfigurationData from "../../data/advancement/item-choice.mjs";

/**
* Advancement that presents the player with a choice of multiple items that they can take. Keeps track of which
Expand All @@ -11,15 +12,8 @@ export default class ItemChoiceAdvancement extends Advancement {
/** @inheritdoc */
static get metadata() {
return foundry.utils.mergeObject(super.metadata, {
defaults: {
configuration: {
hint: "",
choices: {},
allowDrops: true,
type: null,
pool: [],
spell: null
}
dataModels: {
configuration: ItemChoiceConfigurationData
},
order: 50,
icon: "systems/dnd5e/icons/svg/item-choice.svg",
Expand Down Expand Up @@ -90,7 +84,7 @@ export default class ItemChoiceAdvancement extends Advancement {
async apply(level, data, retainedData={}) {
const items = [];
const updates = {};
const spellChanges = this.data.configuration.spell ? this._prepareSpellChanges(this.data.configuration.spell) : {};
const spellChanges = this.configuration.spell?.spellChanges ?? {};
for ( const [uuid, selected] of Object.entries(data) ) {
if ( !selected ) continue;

Expand Down Expand Up @@ -130,7 +124,7 @@ export default class ItemChoiceAdvancement extends Advancement {
/** @inheritdoc */
reverse(level) {
const items = [];
for ( const id of Object.keys(this.data.value[level] ?? {}) ) {
for ( const id of Object.keys(this.value[level] ?? {}) ) {
const item = this.actor.items.get(id);
if ( item ) items.push(item.toObject());
this.actor.items.delete(id);
Expand All @@ -152,8 +146,8 @@ export default class ItemChoiceAdvancement extends Advancement {
* @throws An error if the item is invalid and warn is `true`.
*/
_verifyItemType(item, { restriction, spellLevel, error=true }={}) {
restriction ??= this.data.configuration.type;
spellLevel ??= this.data.configuration.spell?.level;
restriction ??= this.configuration.type;
spellLevel ??= this.configuration.spell?.level;

// Type restriction is set and the item type does not match the selected type
if ( restriction && (restriction !== item.type) ) {
Expand Down
20 changes: 10 additions & 10 deletions templates/advancement/item-choice-config.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
<div class="left-column">
{{> "dnd5e.advancement-controls"}}
<div class="form-group">
<label>Hint</label>
<textarea name="data.configuration.hint">{{data.configuration.hint}}</textarea>
<label>{{localize "DND5E.AdvancementHint"}}</label>
<textarea name="configuration.hint">{{configuration.hint}}</textarea>
</div>

<div class="form-group">
<label>{{localize "DND5E.AdvancementConfigureAllowDrops"}}</label>
<div class="form-fields">
<input type="checkbox" name="data.configuration.allowDrops" {{checked data.configuration.allowDrops}}>
<input type="checkbox" name="configuration.allowDrops" {{checked configuration.allowDrops}}>
</div>
<p class="hint">{{localize "DND5E.AdvancementConfigureAllowDropsHint"}}</p>
</div>

<div class="form-group">
<label>{{localize "DND5E.AdvancementItemChoiceType"}}</label>
<div class="form-fields">
<select name="data.configuration.type">
{{selectOptions validTypes selected=data.configuration.type
<select name="configuration.type">
{{selectOptions validTypes selected=configuration.type
blank=(localize "DND5E.AdvancementItemChoiceTypeAny")}}
</select>
</div>
Expand All @@ -29,8 +29,8 @@
<div class="form-group">
<label>{{localize "DND5E.SpellLevel"}}</label>
<div class="form-fields">
<select name="data.configuration.spell.level">
{{#select data.configuration.spell.level}}
<select name="configuration.spell.level">
{{#select configuration.spell.level}}
<option value="">&mdash;</option>
{{#each CONFIG.spellLevels as |label key|}}
<option value="{{key}}">{{label}}</option>
Expand All @@ -49,7 +49,7 @@
<ol class="items-list">
<li class="items-header flexrow"><h3 class="item-name">{{localize "DOCUMENT.Items"}}</h3></li>
<ol class="item-list">
{{#each data.configuration.pool}}
{{#each configuration.pool}}
<li class="item flexrow" data-item-uuid="{{this}}">
<div class="item-name">{{{dnd5e-linkForUuid this}}}</div>
<div class="item-controls flexrow">
Expand All @@ -72,8 +72,8 @@
<div class="form-group">
<label>{{level}}</label>
<div class="form-fields">
{{numberInput (lookup ../data.configuration.choices level) placeholder="0"
name=(concat "data.configuration.choices." level) min=1 step=1}}
{{numberInput (lookup ../configuration.choices level) placeholder="0"
name=(concat "configuration.choices." level) min=1 step=1}}
</div>
</div>
{{/each}}
Expand Down
6 changes: 3 additions & 3 deletions templates/advancement/item-choice-flow.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<h3>{{{title}}}</h3>

<div class="drop-target">
{{#if advancement.data.configuration.hint}}
<p>{{advancement.data.configuration.hint}}</p>
{{#if advancement.configuration.hint}}
<p>{{advancement.configuration.hint}}</p>
{{/if}}

{{#each previousLevels}}
Expand Down Expand Up @@ -40,7 +40,7 @@
</div>
{{/each}}

{{#if advancement.data.configuration.allowDrops}}
{{#if advancement.configuration.allowDrops}}
<p class="hint centered">{{localize "DND5E.AdvancementFlowDropAreaHint"}}</p>
{{/if}}
</div>
Expand Down

0 comments on commit 436d335

Please sign in to comment.