Skip to content

Commit

Permalink
[#2504] Convert source on items & actors into object (#2534)
Browse files Browse the repository at this point in the history
  • Loading branch information
arbron authored Oct 31, 2023
1 parent f6f2531 commit 60714c3
Show file tree
Hide file tree
Showing 19 changed files with 114 additions and 21 deletions.
18 changes: 16 additions & 2 deletions module/data/actor/npc.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FormulaField } from "../fields.mjs";
import SourceField from "../shared/source-field.mjs";
import AttributesFields from "./templates/attributes.mjs";
import CreatureTemplate from "./templates/creature.mjs";
import DetailsFields from "./templates/details.mjs";
Expand Down Expand Up @@ -27,7 +28,7 @@ import TraitsFields from "./templates/traits.mjs";
* @property {string} details.environment Common environments in which this NPC is found.
* @property {number} details.cr NPC's challenge rating.
* @property {number} details.spellLevel Spellcasting level of this NPC.
* @property {string} details.source What book or adventure is this NPC from?
* @property {SourceField} details.source Adventure or sourcebook where this NPC originated.
* @property {object} resources
* @property {object} resources.legact NPC's legendary actions.
* @property {number} resources.legact.value Currently available legendary actions.
Expand Down Expand Up @@ -85,7 +86,7 @@ export default class NPCData extends CreatureTemplate {
spellLevel: new foundry.data.fields.NumberField({
required: true, nullable: false, integer: true, min: 0, initial: 0, label: "DND5E.SpellcasterLevel"
}),
source: new foundry.data.fields.StringField({required: true, label: "DND5E.Source"})
source: new SourceField()
}, {label: "DND5E.Details"}),
resources: new foundry.data.fields.SchemaField({
legact: new foundry.data.fields.SchemaField({
Expand Down Expand Up @@ -123,12 +124,25 @@ export default class NPCData extends CreatureTemplate {
/** @inheritdoc */
static _migrateData(source) {
super._migrateData(source);
NPCData.#migrateSource(source);
NPCData.#migrateTypeData(source);
AttributesFields._migrateInitiative(source.attributes);
}

/* -------------------------------------------- */

/**
* Convert source string into custom object.
* @param {object} source The candidate source data from which the model will be constructed.
*/
static #migrateSource(source) {
if ( source.details?.source && (foundry.utils.getType(source.details.source) !== "Object") ) {
source.details.source = { custom: source.details.source };
}
}

/* -------------------------------------------- */

/**
* Migrate the actor type string to type object.
* @param {object} source The candidate source data from which the model will be constructed.
Expand Down
18 changes: 17 additions & 1 deletion module/data/actor/vehicle.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FormulaField } from "../fields.mjs";
import SourceField from "../shared/source-field.mjs";
import AttributesFields from "./templates/attributes.mjs";
import CommonTemplate from "./templates/common.mjs";
import DetailsFields from "./templates/details.mjs";
Expand Down Expand Up @@ -37,6 +38,8 @@ import TraitsFields from "./templates/traits.mjs";
* @property {object} cargo Details on this vehicle's crew and cargo capacities.
* @property {PassengerData[]} cargo.crew Creatures responsible for operating the vehicle.
* @property {PassengerData[]} cargo.passengers Creatures just takin' a ride.
* @property {object} details
* @property {SourceField} details.source Adventure or sourcebook where this vehicle originated.
*/
export default class VehicleData extends CommonTemplate {

Expand Down Expand Up @@ -99,7 +102,7 @@ export default class VehicleData extends CommonTemplate {
}, {label: "DND5E.Attributes"}),
details: new foundry.data.fields.SchemaField({
...DetailsFields.common,
source: new foundry.data.fields.StringField({required: true, label: "DND5E.Source"})
source: new SourceField()
}, {label: "DND5E.Details"}),
traits: new foundry.data.fields.SchemaField({
...TraitsFields.common,
Expand All @@ -124,6 +127,19 @@ export default class VehicleData extends CommonTemplate {
static _migrateData(source) {
super._migrateData(source);
AttributesFields._migrateInitiative(source.attributes);
VehicleData.#migrateSource(source);
}

/* -------------------------------------------- */

/**
* Convert source string into custom object.
* @param {object} source The candidate source data from which the model will be constructed.
*/
static #migrateSource(source) {
if ( source.details?.source && (foundry.utils.getType(source.details.source) !== "Object") ) {
source.details.source = { custom: source.details.source };
}
}
}

Expand Down
11 changes: 7 additions & 4 deletions module/data/item/templates/item-description.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import SystemDataModel from "../../abstract.mjs";
import SourceField from "../../shared/source-field.mjs";

/**
* Data model template with item description & source.
Expand All @@ -7,7 +8,7 @@ import SystemDataModel from "../../abstract.mjs";
* @property {string} description.value Full item description.
* @property {string} description.chat Description displayed in chat card.
* @property {string} description.unidentified Description displayed if item is unidentified.
* @property {string} source Adventure or sourcebook where this item originated.
* @property {SourceField} source Adventure or sourcebook where this item originated.
* @mixin
*/
export default class ItemDescriptionTemplate extends SystemDataModel {
Expand All @@ -21,7 +22,7 @@ export default class ItemDescriptionTemplate extends SystemDataModel {
required: true, nullable: true, label: "DND5E.DescriptionUnidentified"
})
}),
source: new foundry.data.fields.StringField({required: true, label: "DND5E.Source"})
source: new SourceField()
};
}

Expand All @@ -38,10 +39,12 @@ export default class ItemDescriptionTemplate extends SystemDataModel {
/* -------------------------------------------- */

/**
* Convert null source to the blank string.
* Convert source string into custom object.
* @param {object} source The candidate source data from which the model will be constructed.
*/
static #migrateSource(source) {
if ( source.source === null ) source.source = "";
if ( foundry.utils.getType(source.source) !== "Object" ) {
source.source = { custom: source.source };
}
}
}
1 change: 1 addition & 0 deletions module/data/shared/_module.mjs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export {default as CurrencyTemplate} from "./currency.mjs";
export {default as SourceField} from "./source-field.mjs";
48 changes: 48 additions & 0 deletions module/data/shared/source-field.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const { SchemaField, StringField } = foundry.data.fields;

/**
* Data fields that stores information on the adventure or sourcebook where this document originated.
*
* @property {string} book Book/publication where the item originated.
* @property {string} page Page or section where the item can be found.
* @property {string} custom Fully custom source label.
* @property {string} uuid Upstream source of this data if it originated in another compendium.
* @property {string} license Type of license that covers this item.
*/
export default class SourceTemplate extends SchemaField {
constructor(fields={}, options={}) {
super({
book: new StringField(),
page: new StringField(),
custom: new StringField(),
uuid: new StringField(), // TODO: Convert to UUIDField with v12
license: new StringField(),
...fields
}, { label: "DND5E.Source", ...options });
}

/* -------------------------------------------- */

initialize(value, model, options={}) {
const obj = super.initialize(value, model, options);

Object.defineProperty(obj, "label", {
get() {
if ( this.custom ) return this.custom;
// TODO: Improve this logic
return this.book ? this.page ? `${this.book} ${this.page}` : this.book : "";
},
enumerable: false
});
Object.defineProperty(obj, "toString", {
value: () => {
foundry.utils.logCompatibilityWarning("Source has been converted to an object, the label can now be accessed "
+ "using the `source#label` property.", { since: "DnD5e 2.4", until: "DnD5e 2.6" });
return obj.label;
},
enumerable: false
});

return obj;
}
}
2 changes: 1 addition & 1 deletion template.json
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@
"chat": "",
"unidentified": ""
},
"source": ""
"source": {}
},
"physicalItem": {
"quantity": 1,
Expand Down
2 changes: 1 addition & 1 deletion templates/actors/npc-sheet.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
</a>
</li>
<li class="source">
<input type="text" name="system.details.source" value="{{system.details.source}}"
<input type="text" name="system.details.source.custom" value="{{system.details.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}"/>
</li>
</ul>
Expand Down
2 changes: 1 addition & 1 deletion templates/actors/vehicle-sheet.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
placeholder="{{localize 'DND5E.Dimensions'}}">
</li>
<li class="source">
<input type="text" name="system.details.source" value="{{system.details.source}}"
<input type="text" name="system.details.source.custom" value="{{system.details.source.custom}}"
placeholder="{{localize 'DND5E.Source'}}">
</li>
</ul>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/background.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

<ul class="summary flexrow">
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/backpack.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
</select>
</li>
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/class.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

<ul class="summary flexrow">
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/consumable.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
</select>
</li>
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}">
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/equipment.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
</select>
</li>
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/feat.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
<input type="text" name="system.requirements" value="{{system.requirements}}" placeholder="{{ localize 'DND5E.Requirements' }}"/>
</li>
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/loot.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
</select>
</li>
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/spell.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
{{labels.school}}
</li>
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/subclass.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

<ul class="summary flexrow">
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/tool.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
</select>
</li>
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down
3 changes: 2 additions & 1 deletion templates/items/weapon.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
</select>
</li>
<li>
<input type="text" name="system.source" value="{{system.source}}" placeholder="{{ localize 'DND5E.Source' }}"/>
<input type="text" name="system.source.custom" value="{{system.source.custom}}"
placeholder="{{ localize 'DND5E.Source' }}">
</li>
</ul>
</div>
Expand Down

0 comments on commit 60714c3

Please sign in to comment.