mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-16 13:41:07 +01:00
Added PreCreate/Create/Delete logic for Class/Subclass and set it as foreignUUID fields in PC
This commit is contained in:
parent
53be047e12
commit
a5aa2e914d
11 changed files with 177 additions and 167 deletions
|
|
@ -1178,6 +1178,14 @@
|
||||||
"Description": "Description"
|
"Description": "Description"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Item": {
|
||||||
|
"Errors": {
|
||||||
|
"MissingClass": "The character is missing a class",
|
||||||
|
"SubclassNotInClass": "The subclass does not belong to the character's class",
|
||||||
|
"ClassAlreadySelected": "The character already has a class",
|
||||||
|
"SubclassAlreadySelected": "The character already has a subclass for that class."
|
||||||
|
}
|
||||||
|
},
|
||||||
"Effects": {
|
"Effects": {
|
||||||
"Types": {
|
"Types": {
|
||||||
"health": {
|
"health": {
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
domains:
|
domains:
|
||||||
multiclass?.system?.domains.map(key => {
|
multiclass?.system?.domains.map(key => {
|
||||||
const domain = domains[key];
|
const domain = domains[key];
|
||||||
const alreadySelected = this.actor.system.class.system.domains.includes(key);
|
const alreadySelected = this.actor.system.class.value.system.domains.includes(key);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...domain,
|
...domain,
|
||||||
|
|
@ -480,7 +480,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
const target = event.target.closest('.card-preview-container');
|
const target = event.target.closest('.card-preview-container');
|
||||||
if (item.type === 'domainCard') {
|
if (item.type === 'domainCard') {
|
||||||
if (
|
if (
|
||||||
!this.actor.system.class.system.domains.includes(item.system.domain) &&
|
!this.actor.system.class.value.system.domains.includes(item.system.domain) &&
|
||||||
this.levelup.classUpgradeChoices?.multiclass?.domain !== item.system.domain
|
this.levelup.classUpgradeChoices?.multiclass?.domain !== item.system.domain
|
||||||
) {
|
) {
|
||||||
ui.notifications.error(
|
ui.notifications.error(
|
||||||
|
|
@ -522,7 +522,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
} else if (event.target.closest('.multiclass-cards')) {
|
} else if (event.target.closest('.multiclass-cards')) {
|
||||||
const target = event.target.closest('.multiclass-cards');
|
const target = event.target.closest('.multiclass-cards');
|
||||||
if (item.type === 'class') {
|
if (item.type === 'class') {
|
||||||
if (item.name === this.actor.system.class.name) {
|
if (item.name === this.actor.system.class.value.name) {
|
||||||
ui.notifications.error(
|
ui.notifications.error(
|
||||||
game.i18n.localize('DAGGERHEART.Application.LevelUp.notifications.error.alreadySelectedClass')
|
game.i18n.localize('DAGGERHEART.Application.LevelUp.notifications.error.alreadySelectedClass')
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -198,15 +198,11 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
|
||||||
const item = await fromUuid(data.uuid);
|
const item = await fromUuid(data.uuid);
|
||||||
if (item.type === 'subclass') {
|
if (item.type === 'subclass') {
|
||||||
await this.document.update({
|
await this.document.update({
|
||||||
'system.subclasses': [
|
'system.subclasses': item.uuid
|
||||||
...this.document.system.subclasses, item.uuid
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
} else if (item.type === 'feature') {
|
} else if (item.type === 'feature') {
|
||||||
await this.document.update({
|
await this.document.update({
|
||||||
'system.features': [
|
'system.features': [...this.document.system.features, item.uuid]
|
||||||
...this.document.system.features, item.uuid
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
} else if (item.type === 'weapon') {
|
} else if (item.type === 'weapon') {
|
||||||
if (event.currentTarget.classList.contains('primary-weapon-section')) {
|
if (event.currentTarget.classList.contains('primary-weapon-section')) {
|
||||||
|
|
@ -231,25 +227,19 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
|
||||||
if (item.type === 'miscellaneous' || item.type === 'consumable') {
|
if (item.type === 'miscellaneous' || item.type === 'consumable') {
|
||||||
if (this.document.system.inventory.choiceA.length < 2)
|
if (this.document.system.inventory.choiceA.length < 2)
|
||||||
await this.document.update({
|
await this.document.update({
|
||||||
'system.inventory.choiceA': [
|
'system.inventory.choiceA': [...this.document.system.inventory.choiceA, item.uuid]
|
||||||
...this.document.system.inventory.choiceA, item.uuid
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (item.type === 'miscellaneous') {
|
} else if (item.type === 'miscellaneous') {
|
||||||
if (event.currentTarget.classList.contains('take-section')) {
|
if (event.currentTarget.classList.contains('take-section')) {
|
||||||
if (this.document.system.inventory.take.length < 3)
|
if (this.document.system.inventory.take.length < 3)
|
||||||
await this.document.update({
|
await this.document.update({
|
||||||
'system.inventory.take': [
|
'system.inventory.take': [...this.document.system.inventory.take, item.uuid]
|
||||||
...this.document.system.inventory.take, item.uuid
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
} else if (event.currentTarget.classList.contains('choice-b-section')) {
|
} else if (event.currentTarget.classList.contains('choice-b-section')) {
|
||||||
if (this.document.system.inventory.choiceB.length < 2)
|
if (this.document.system.inventory.choiceB.length < 2)
|
||||||
await this.document.update({
|
await this.document.update({
|
||||||
'system.inventory.choiceB': [
|
'system.inventory.choiceB': [...this.document.system.inventory.choiceB, item.uuid]
|
||||||
...this.document.system.inventory.choiceB, item.uuid
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -215,13 +215,13 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
||||||
context.abilityScoresFinished = context.abilityScoreArray.every(x => x.value === 0);
|
context.abilityScoresFinished = context.abilityScoreArray.every(x => x.value === 0);
|
||||||
|
|
||||||
//FIXME:
|
//FIXME:
|
||||||
context.domains = this.document.system.class
|
context.domains = this.document.system.class.value
|
||||||
? {
|
? {
|
||||||
first: this.document.system.class.system.domains[0]
|
first: this.document.system.class.value.system.domains[0]
|
||||||
? SYSTEM.DOMAIN.domains[this.document.system.class.system.domains[0]].src
|
? SYSTEM.DOMAIN.domains[this.document.system.class.value.system.domains[0]].src
|
||||||
: null,
|
: null,
|
||||||
second: this.document.system.class.system.domains[1]
|
second: this.document.system.class.value.system.domains[1]
|
||||||
? SYSTEM.DOMAIN.domains[this.document.system.class.system.domains[1]].src
|
? SYSTEM.DOMAIN.domains[this.document.system.class.value.system.domains[1]].src
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
: {};
|
: {};
|
||||||
|
|
@ -370,8 +370,8 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
||||||
multiclass: false,
|
multiclass: false,
|
||||||
img: actor.system.subclass.img,
|
img: actor.system.subclass.img,
|
||||||
subtitle: game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'),
|
subtitle: game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'),
|
||||||
domains: actor.system.class.system.domains.map(x => config.DOMAIN.domains[x].src),
|
domains: actor.system.class.value.system.domains.map(x => config.DOMAIN.domains[x].src),
|
||||||
className: actor.system.class.name,
|
className: actor.system.class.value.name,
|
||||||
subclassUuid: actor.system.subclass.uuid,
|
subclassUuid: actor.system.subclass.uuid,
|
||||||
subclassName: actor.system.subclass.name,
|
subclassName: actor.system.subclass.name,
|
||||||
spellcast: config.ACTOR.abilities[actor.system.subclass.system.spellcastingTrait]?.name ?? null,
|
spellcast: config.ACTOR.abilities[actor.system.subclass.system.spellcastingTrait]?.name ?? null,
|
||||||
|
|
@ -402,9 +402,9 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
||||||
: game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'),
|
: game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'),
|
||||||
domains:
|
domains:
|
||||||
firstKey === 'sub'
|
firstKey === 'sub'
|
||||||
? actor.system.class.system.domains.map(x => config.DOMAIN.domains[x].src)
|
? actor.system.class.value.system.domains.map(x => config.DOMAIN.domains[x].src)
|
||||||
: actor.system.multiclass.system.domains.map(x => config.DOMAIN.domains[x].src),
|
: actor.system.multiclass.system.domains.map(x => config.DOMAIN.domains[x].src),
|
||||||
className: firstKey === 'sub' ? actor.system.class.name : actor.system.multiclass.name,
|
className: firstKey === 'sub' ? actor.system.class.value.name : actor.system.multiclass.name,
|
||||||
subclassUuid: firstBase.uuid,
|
subclassUuid: firstBase.uuid,
|
||||||
subclassName: firstBase.name,
|
subclassName: firstBase.name,
|
||||||
spellcast:
|
spellcast:
|
||||||
|
|
@ -456,9 +456,9 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
||||||
: game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'),
|
: game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'),
|
||||||
domains:
|
domains:
|
||||||
secondKey === 'sub'
|
secondKey === 'sub'
|
||||||
? actor.system.class.system.domains.map(x => config.DOMAIN.domains[x].src)
|
? actor.system.class.value.system.domains.map(x => config.DOMAIN.domains[x].src)
|
||||||
: actor.system.multiclass.system.domains.map(x => config.DOMAIN.domains[x].src),
|
: actor.system.multiclass.system.domains.map(x => config.DOMAIN.domains[x].src),
|
||||||
className: secondKey === 'sub' ? actor.system.class.name : actor.system.multiclass.name,
|
className: secondKey === 'sub' ? actor.system.class.value.name : actor.system.multiclass.name,
|
||||||
subclassUuid: secondBase.uuid,
|
subclassUuid: secondBase.uuid,
|
||||||
subclassName: secondBase.name,
|
subclassName: secondBase.name,
|
||||||
spellcast:
|
spellcast:
|
||||||
|
|
@ -644,7 +644,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
openLevelUp() {
|
openLevelUp() {
|
||||||
if (!this.document.system.class || !this.document.system.subclass) {
|
if (!this.document.system.class.value || !this.document.system.subclass) {
|
||||||
ui.notifications.error(game.i18n.localize('DAGGERHEART.Sheets.PC.Errors.missingClassOrSubclass'));
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.Sheets.PC.Errors.missingClassOrSubclass'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1144,7 +1144,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
||||||
const createdItems = [];
|
const createdItems = [];
|
||||||
|
|
||||||
if (item.type === 'domainCard') {
|
if (item.type === 'domainCard') {
|
||||||
if (!this.document.system.class) {
|
if (!this.document.system.class.value) {
|
||||||
ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.NoClassSelected'));
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.NoClassSelected'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1173,63 +1173,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
||||||
|
|
||||||
return createdItem;
|
return createdItem;
|
||||||
} else {
|
} else {
|
||||||
if (!item.system.multiclass && ['class', 'subclass', 'ancestry', 'community'].includes(item.type)) {
|
if (item.type === 'ancestry') {
|
||||||
const existing = this.document.items.find(x => x.type === item.type);
|
|
||||||
await existing?.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.type === 'subclass') {
|
|
||||||
if (!item.system.multiclass) {
|
|
||||||
if (!this.document.system.class) {
|
|
||||||
ui.notifications.info(
|
|
||||||
game.i18n.localize('DAGGERHEART.Notification.Info.SelectClassBeforeSubclass')
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
} else if (!this.document.system.class.system.subclasses.some(x => x.uuid === item.uuid)) {
|
|
||||||
ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.SubclassNotOfClass'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var feature of this.document.items.filter(
|
|
||||||
x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.subclass.id
|
|
||||||
)) {
|
|
||||||
await feature.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const features = [
|
|
||||||
itemData.system.foundationFeature,
|
|
||||||
itemData.system.specializationFeature,
|
|
||||||
itemData.system.masteryFeature
|
|
||||||
];
|
|
||||||
for (var i = 0; i < features.length; i++) {
|
|
||||||
const feature = features[i];
|
|
||||||
for (var ability of feature.abilities) {
|
|
||||||
const data = (await fromUuid(ability.uuid)).toObject();
|
|
||||||
if (i > 0) data.system.disabled = true;
|
|
||||||
data.uuid = itemData.uuid;
|
|
||||||
|
|
||||||
const abilityData = await this._onDropItemCreate(data);
|
|
||||||
ability.uuid = abilityData[0].uuid;
|
|
||||||
|
|
||||||
createdItems.push(abilityData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (item.type === 'class') {
|
|
||||||
if (!item.system.multiclass) {
|
|
||||||
for (var feature of this.document.items.filter(
|
|
||||||
x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id
|
|
||||||
)) {
|
|
||||||
await feature.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var feature of item.system.features) {
|
|
||||||
const data = (await fromUuid(feature.uuid)).toObject();
|
|
||||||
const itemData = await this._onDropItemCreate(data);
|
|
||||||
createdItems.push(itemData);
|
|
||||||
}
|
|
||||||
} else if (item.type === 'ancestry') {
|
|
||||||
for (var feature of this.document.items.filter(
|
for (var feature of this.document.items.filter(
|
||||||
x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.ancestry.id
|
x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.ancestry.id
|
||||||
)) {
|
)) {
|
||||||
|
|
|
||||||
|
|
@ -3,40 +3,39 @@
|
||||||
* that resolves to either the document, the index(for items in compenidums) or the UUID string.
|
* that resolves to either the document, the index(for items in compenidums) or the UUID string.
|
||||||
*/
|
*/
|
||||||
export default class ForeignDocumentUUIDField extends foundry.data.fields.DocumentUUIDField {
|
export default class ForeignDocumentUUIDField extends foundry.data.fields.DocumentUUIDField {
|
||||||
|
/**
|
||||||
|
* @param {foundry.data.types.DocumentUUIDFieldOptions} [options] Options which configure the behavior of the field
|
||||||
|
* @param {foundry.data.types.DataFieldContext} [context] Additional context which describes the field
|
||||||
|
*/
|
||||||
|
constructor(options, context) {
|
||||||
|
super(options, context);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/** @inheritdoc */
|
||||||
* @param {foundry.data.types.DocumentUUIDFieldOptions} [options] Options which configure the behavior of the field
|
static get _defaults() {
|
||||||
* @param {foundry.data.types.DataFieldContext} [context] Additional context which describes the field
|
return foundry.utils.mergeObject(super._defaults, {
|
||||||
*/
|
nullable: true,
|
||||||
constructor(options, context) {
|
readonly: false,
|
||||||
super(options, context);
|
idOnly: false
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
/**@override */
|
||||||
static get _defaults() {
|
initialize(value, _model, _options = {}) {
|
||||||
return foundry.utils.mergeObject(super._defaults, {
|
if (this.idOnly) return value;
|
||||||
nullable: true,
|
return (() => {
|
||||||
readonly: false,
|
try {
|
||||||
idOnly: false,
|
const doc = fromUuidSync(value);
|
||||||
});
|
return doc;
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return value ?? null;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
/**@override */
|
/**@override */
|
||||||
initialize(value, _model, _options = {}) {
|
toObject(value) {
|
||||||
if (this.idOnly) return value;
|
return value?.uuid ?? value;
|
||||||
return () => {
|
}
|
||||||
try {
|
|
||||||
const doc = fromUuidSync(value);
|
|
||||||
return doc;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return value ?? null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**@override */
|
|
||||||
toObject(value) {
|
|
||||||
return value?.uuid ?? value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ export default class DHClass extends BaseDataItem {
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
static get metadata() {
|
static get metadata() {
|
||||||
return foundry.utils.mergeObject(super.metadata, {
|
return foundry.utils.mergeObject(super.metadata, {
|
||||||
label: "TYPES.Item.class",
|
label: 'TYPES.Item.class',
|
||||||
type: "class",
|
type: 'class',
|
||||||
hasDescription: true,
|
hasDescription: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -19,15 +19,22 @@ export default class DHClass extends BaseDataItem {
|
||||||
...super.defineSchema(),
|
...super.defineSchema(),
|
||||||
domains: new fields.ArrayField(new fields.StringField(), { max: 2 }),
|
domains: new fields.ArrayField(new fields.StringField(), { max: 2 }),
|
||||||
|
|
||||||
classItems: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item" })),
|
classItems: new fields.ArrayField(new ForeignDocumentUUIDField({ type: 'Item' })),
|
||||||
evasion: new fields.NumberField({ initial: 0, integer: true }),
|
evasion: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
features: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item" })),
|
features: new fields.ArrayField(new ForeignDocumentUUIDField({ type: 'Item' })),
|
||||||
|
subclasses: new fields.ArrayField(
|
||||||
subclasses: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item", required: false, nullable: true, initial: undefined })),
|
new ForeignDocumentUUIDField({ type: 'Item', required: false, nullable: true, initial: undefined })
|
||||||
|
),
|
||||||
inventory: new fields.SchemaField({
|
inventory: new fields.SchemaField({
|
||||||
take: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item", required: false, nullable: true, initial: undefined })),
|
take: new fields.ArrayField(
|
||||||
choiceA: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item", required: false, nullable: true, initial: undefined })),
|
new ForeignDocumentUUIDField({ type: 'Item', required: false, nullable: true, initial: undefined })
|
||||||
choiceB: new fields.ArrayField(new ForeignDocumentUUIDField({ type: "Item", required: false, nullable: true, initial: undefined })),
|
),
|
||||||
|
choiceA: new fields.ArrayField(
|
||||||
|
new ForeignDocumentUUIDField({ type: 'Item', required: false, nullable: true, initial: undefined })
|
||||||
|
),
|
||||||
|
choiceB: new fields.ArrayField(
|
||||||
|
new ForeignDocumentUUIDField({ type: 'Item', required: false, nullable: true, initial: undefined })
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
characterGuide: new fields.SchemaField({
|
characterGuide: new fields.SchemaField({
|
||||||
suggestedTraits: new fields.SchemaField({
|
suggestedTraits: new fields.SchemaField({
|
||||||
|
|
@ -38,15 +45,11 @@ export default class DHClass extends BaseDataItem {
|
||||||
presence: new fields.NumberField({ initial: 0, integer: true }),
|
presence: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
knowledge: new fields.NumberField({ initial: 0, integer: true })
|
knowledge: new fields.NumberField({ initial: 0, integer: true })
|
||||||
}),
|
}),
|
||||||
suggestedPrimaryWeapon: new ForeignDocumentUUIDField({ type: "Item" }),
|
suggestedPrimaryWeapon: new ForeignDocumentUUIDField({ type: 'Item' }),
|
||||||
suggestedSecondaryWeapon: new ForeignDocumentUUIDField({ type: "Item" }),
|
suggestedSecondaryWeapon: new ForeignDocumentUUIDField({ type: 'Item' }),
|
||||||
suggestedArmor: new ForeignDocumentUUIDField({ type: "Item" }),
|
suggestedArmor: new ForeignDocumentUUIDField({ type: 'Item' })
|
||||||
}),
|
}),
|
||||||
multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true }),
|
isMulticlass: new fields.BooleanField({ initial: false })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get multiclassTier() {
|
|
||||||
return getTier(this.multiclass, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ export default class DHSubclass extends BaseDataItem {
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
static get metadata() {
|
static get metadata() {
|
||||||
return foundry.utils.mergeObject(super.metadata, {
|
return foundry.utils.mergeObject(super.metadata, {
|
||||||
label: "TYPES.Item.subclass",
|
label: 'TYPES.Item.subclass',
|
||||||
type: "subclass",
|
type: 'subclass',
|
||||||
hasDescription: true,
|
hasDescription: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,11 +56,7 @@ export default class DHSubclass extends BaseDataItem {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
multiclass: new fields.NumberField({ initial: null, nullable: true, integer: true })
|
isMulticlass: new fields.BooleanField({ initial: false })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get multiclassTier() {
|
|
||||||
return getTier(this.multiclass);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { getPathValue } from '../helpers/utils.mjs';
|
import { getPathValue } from '../helpers/utils.mjs';
|
||||||
|
import ForeignDocumentUUIDField from './fields/foreignDocumentUUIDField.mjs';
|
||||||
import { LevelOptionType } from './levelTier.mjs';
|
import { LevelOptionType } from './levelTier.mjs';
|
||||||
|
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
|
|
@ -96,6 +97,14 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
|
||||||
max: new fields.NumberField({ initial: 6, integer: true }),
|
max: new fields.NumberField({ initial: 6, integer: true }),
|
||||||
value: new fields.NumberField({ initial: 0, integer: true })
|
value: new fields.NumberField({ initial: 0, integer: true })
|
||||||
}),
|
}),
|
||||||
|
class: new fields.SchemaField({
|
||||||
|
value: new ForeignDocumentUUIDField({ type: 'Item', nullable: true }),
|
||||||
|
subclass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true })
|
||||||
|
}),
|
||||||
|
multiclass: new fields.SchemaField({
|
||||||
|
value: new ForeignDocumentUUIDField({ type: 'Item', nullable: true }),
|
||||||
|
subclass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true })
|
||||||
|
}),
|
||||||
levelData: new fields.EmbeddedDataField(DhPCLevelData)
|
levelData: new fields.EmbeddedDataField(DhPCLevelData)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -108,14 +117,6 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
|
||||||
return this.parent.items.find(x => x.type === 'ancestry') ?? null;
|
return this.parent.items.find(x => x.type === 'ancestry') ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get class() {
|
|
||||||
return this.parent.items.find(x => x.type === 'class' && !x.system.multiclass) ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get multiclass() {
|
|
||||||
return this.parent.items.find(x => x.type === 'class' && x.system.multiclass) ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get multiclassSubclass() {
|
get multiclassSubclass() {
|
||||||
return this.parent.items.find(x => x.type === 'subclass' && x.system.multiclass) ?? null;
|
return this.parent.items.find(x => x.type === 'subclass' && x.system.multiclass) ?? null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,75 @@
|
||||||
export default class DhpItem extends Item {
|
export default class DhpItem extends Item {
|
||||||
_preCreate(data, changes, user) {
|
async _preCreate(data, changes, user) {
|
||||||
super._preCreate(data, changes, user);
|
const allowed = await super._preCreate(data, changes, user);
|
||||||
|
if (allowed === false) return;
|
||||||
|
|
||||||
|
if (data.type === 'class') {
|
||||||
|
if (this.parent?.type === 'pc') {
|
||||||
|
const path = data.system.isMulticlass ? 'system.multiclass.value' : 'system.class.value';
|
||||||
|
if (foundry.utils.getProperty(this.parent, path)) {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.Item.Errors.ClassAlreadySelected'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.type === 'subclass') {
|
||||||
|
if (this.parent?.type === 'pc') {
|
||||||
|
const path = data.system.isMulticlass ? 'system.multiclass' : 'system.class';
|
||||||
|
const classData = foundry.utils.getProperty(this.parent, path);
|
||||||
|
if (!classData.value) {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.Item.Errors.MissingClass'));
|
||||||
|
return false;
|
||||||
|
} else if (classData.subclass) {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.Item.Errors.SubclassAlreadySelected'));
|
||||||
|
return false;
|
||||||
|
} else if (
|
||||||
|
classData.value.system.subclasses.every(x => `${this.parent.uuid}.${x.uuid}` !== this.uuid)
|
||||||
|
) {
|
||||||
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.Item.Errors.SubclassNotInClass'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async _onCreateOperation(documents, operation, user) {
|
||||||
|
await super._onCreateOperation(documents, operation, user);
|
||||||
|
for (var document of documents) {
|
||||||
|
if (document.type === 'class') {
|
||||||
|
if (operation.parent?.type === 'pc') {
|
||||||
|
const path = `system.${document.system.isMulticlass ? 'multiclass.value' : 'class.value'}`;
|
||||||
|
await operation.parent.update({ [path]: document.uuid });
|
||||||
|
}
|
||||||
|
} else if (document.type === 'subclass') {
|
||||||
|
if (operation.parent?.type === 'pc') {
|
||||||
|
const path = `system.${document.system.isMulticlass ? 'multiclass.subclass' : 'class.subclass'}`;
|
||||||
|
await operation.parent.update({ [path]: document.uuid });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async _onDeleteOperation(documents, operation, user) {
|
||||||
|
await super._onDeleteOperation(documents, operation, user);
|
||||||
|
for (var document of documents) {
|
||||||
|
if (document.type === 'class') {
|
||||||
|
if (operation.parent?.type === 'pc') {
|
||||||
|
const path = `system.${document.system.isMulticlass ? 'multiclass' : 'class'}`;
|
||||||
|
await operation.parent.update({
|
||||||
|
[path]: {
|
||||||
|
class: null,
|
||||||
|
subclass: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (document.type === 'subclass') {
|
||||||
|
if (operation.parent?.type === 'pc') {
|
||||||
|
const path = `system.${document.system.isMulticlass ? 'multiclass.subclass' : 'class.subclass'}`;
|
||||||
|
await operation.parent.update({ [path]: null });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareData() {
|
prepareData() {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<fieldset class="left-main-container" style="flex: 1;">
|
<fieldset class="left-main-container" style="flex: 1;">
|
||||||
<legend class="legend">
|
<legend class="legend">
|
||||||
{{#if this.document.system.class}}
|
{{#if this.document.system.class.value}}
|
||||||
{{#if this.document.system.multiclass}}
|
{{#if this.document.system.multiclass.value}}
|
||||||
<span class="class-feature-selectable {{#if this.multiclass}}inactive{{/if}}" data-action="selectFeatureSet" data-multiclass="false">{{this.document.system.class.name}} {{localize "DAGGERHEART.General.Features"}}</span>
|
<span class="class-feature-selectable {{#if this.multiclass}}inactive{{/if}}" data-action="selectFeatureSet" data-multiclass="false">{{this.document.system.class.name}} {{localize "DAGGERHEART.General.Features"}}</span>
|
||||||
/
|
/
|
||||||
<span class="class-feature-selectable {{#if (not this.multiclass)}}inactive{{/if}}" data-action="selectFeatureSet" data-multiclass="true">{{this.document.system.multiclass.name}} {{localize "DAGGERHEART.General.Features"}}</span>
|
<span class="class-feature-selectable {{#if (not this.multiclass)}}inactive{{/if}}" data-action="selectFeatureSet" data-multiclass="true">{{this.document.system.multiclass.name}} {{localize "DAGGERHEART.General.Features"}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{this.document.system.class.name}} {{localize "DAGGERHEART.General.Features"}}</span>
|
<span>{{this.document.system.class.value.name}} {{localize "DAGGERHEART.General.Features"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{localize "DAGGERHEART.Sheets.PC.Features.Title"}}</span>
|
<span>{{localize "DAGGERHEART.Sheets.PC.Features.Title"}}</span>
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,17 @@
|
||||||
<div class="class-info">
|
<div class="class-info">
|
||||||
<div class="flexrow">
|
<div class="flexrow">
|
||||||
<img class="portrait" src="{{document.img}}" alt="{{document.name}}" data-edit="img">
|
<img class="portrait" src="{{document.img}}" alt="{{document.name}}" data-edit="img">
|
||||||
{{#if document.system.class}}
|
{{#if document.system.class.value}}
|
||||||
<div class="flexcol">
|
<div class="flexcol">
|
||||||
<h2 class="class-title flex0" data-action="viewObject" data-value="{{document.system.class.uuid}}" data-tab="guide">
|
<h2 class="class-title flex0" data-action="viewObject" data-value="{{document.system.class.value.uuid}}" data-tab="guide">
|
||||||
<img class="domain-image" src="{{domains.first}}" />
|
<img class="domain-image" src="{{domains.first}}" />
|
||||||
<span>{{document.system.class.name}}</span>
|
<span>{{document.system.class.value.name}}</span>
|
||||||
<img class="domain-image" src="{{domains.second}}" />
|
<img class="domain-image" src="{{domains.second}}" />
|
||||||
</h2>
|
</h2>
|
||||||
<span class="domain-title flex0">
|
<span class="domain-title flex0">
|
||||||
<span>{{document.system.class.system.domains.[0]}}</span>
|
<span>{{document.system.class.value.system.domains.[0]}}</span>
|
||||||
<span>and</span>
|
<span>and</span>
|
||||||
<span>{{document.system.class.system.domains.[1]}}</span>
|
<span>{{document.system.class.value.system.domains.[1]}}</span>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="flexcol">
|
<div class="flexcol">
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
<button data-action="selectAncestry" class="option-select"><i class="fa-solid fa-user-large"></i></button>
|
<button data-action="selectAncestry" class="option-select"><i class="fa-solid fa-user-large"></i></button>
|
||||||
{{/objectSelector}}
|
{{/objectSelector}}
|
||||||
{{#objectSelector title="Subclass" ids=(join document.system.subclass.uuid) values=(join document.system.subclass.name) titleFontSize=14}}
|
{{#objectSelector title="Subclass" ids=(join document.system.subclass.uuid) values=(join document.system.subclass.name) titleFontSize=14}}
|
||||||
<button data-action="selectSubclass" class="option-select" {{#if (not ../document.system.class)}}disabled{{/if}}><i class="fa-solid fa-fw fa-search"></i></button>
|
<button data-action="selectSubclass" class="option-select" {{#if (not ../document.system.class.value)}}disabled{{/if}}><i class="fa-solid fa-fw fa-search"></i></button>
|
||||||
{{/objectSelector}}
|
{{/objectSelector}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue