mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-11 19:25:21 +01:00
[Fix] ItemLink Fix (#1032)
* . * . * Removed outcommented code * Raised to minor version * Added confirmation on import of old character data
This commit is contained in:
parent
218f180fa0
commit
523ecb506b
14 changed files with 122 additions and 81 deletions
|
|
@ -13,6 +13,7 @@ import { enrichedDualityRoll } from './module/enrichers/DualityRollEnricher.mjs'
|
|||
import { registerCountdownHooks } from './module/data/countdowns.mjs';
|
||||
import {
|
||||
handlebarsRegistration,
|
||||
runMigrations,
|
||||
settingsRegistration,
|
||||
socketRegistration
|
||||
} from './module/systemRegistration/_module.mjs';
|
||||
|
|
@ -168,6 +169,8 @@ Hooks.on('ready', async () => {
|
|||
game.user.setFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.welcomeMessage, true);
|
||||
}
|
||||
}
|
||||
|
||||
runMigrations();
|
||||
});
|
||||
|
||||
Hooks.once('dicesoniceready', () => {});
|
||||
|
|
|
|||
|
|
@ -193,7 +193,9 @@
|
|||
"companionLevelup": {
|
||||
"confirmTitle": "Companion Levelup",
|
||||
"confirmText": "Would you like to level up your companion {name} by {levelChange} levels at this time? (You can do it manually later)"
|
||||
}
|
||||
},
|
||||
"InvalidOldCharacterImportTitle": "Old Character Import",
|
||||
"InvalidOldCharacterImportText": "Character data exported prior to system version 1.1 will not generate a complete character. Do you wish to continue?"
|
||||
},
|
||||
"Companion": {
|
||||
"FIELDS": {
|
||||
|
|
|
|||
|
|
@ -591,7 +591,6 @@ export default function DHApplicationMixin(Base) {
|
|||
if (featureOnCharacter) {
|
||||
systemData = {
|
||||
originItemType: this.document.type,
|
||||
originId: this.document.id,
|
||||
identifier: this.document.system.isMulticlass ? 'multiclass' : null
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,12 +149,12 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
|
|||
const { type } = target.dataset;
|
||||
const cls = foundry.documents.Item.implementation;
|
||||
|
||||
const multiclass = this.document.system.isMulticlass ? 'multiclass' : null;
|
||||
let systemData = {};
|
||||
if (this.document.parent?.type === 'character') {
|
||||
systemData = {
|
||||
originItemType: this.document.type,
|
||||
originId: this.document.id,
|
||||
identifier: this.document.system.isMulticlass ? 'multiclass' : null
|
||||
identifier: multiclass ?? type
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -275,14 +275,15 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
|
|||
|
||||
if (this.document.parent?.type === 'character') {
|
||||
const itemData = item.toObject();
|
||||
const multiclass = this.document.system.isMulticlass ? 'multiclass' : null;
|
||||
item = await cls.create(
|
||||
{
|
||||
...itemData,
|
||||
_stats: { compendiumSource: this.document.uuid },
|
||||
system: {
|
||||
...itemData.system,
|
||||
originItemType: this.document.type,
|
||||
originId: this.document.id,
|
||||
identifier: this.document.system.isMulticlass ? 'multiclass' : null
|
||||
identifier: multiclass ?? target.dataset.type
|
||||
}
|
||||
},
|
||||
{ parent: this.document.parent }
|
||||
|
|
|
|||
|
|
@ -26,5 +26,6 @@ export const gameSettings = {
|
|||
Fear: 'ResourcesFear'
|
||||
},
|
||||
LevelTiers: 'LevelTiers',
|
||||
Countdowns: 'Countdowns'
|
||||
Countdowns: 'Countdowns',
|
||||
LastMigrationVersion: 'LastMigrationVersion'
|
||||
};
|
||||
|
|
|
|||
|
|
@ -444,16 +444,12 @@ export default class DhCharacter extends BaseDataActor {
|
|||
} else if (item.system.originItemType === CONFIG.DH.ITEM.featureTypes.subclass.id) {
|
||||
if (this.class.subclass) {
|
||||
const subclassState = this.class.subclass.system.featureState;
|
||||
const subclass =
|
||||
item.system.identifier === 'multiclass' ? this.multiclass.subclass : this.class.subclass;
|
||||
const featureType = subclass
|
||||
? (subclass.system.features.find(x => x.item?.uuid === item.uuid)?.type ?? null)
|
||||
: null;
|
||||
|
||||
if (
|
||||
featureType === CONFIG.DH.ITEM.featureSubTypes.foundation ||
|
||||
(featureType === CONFIG.DH.ITEM.featureSubTypes.specialization && subclassState >= 2) ||
|
||||
(featureType === CONFIG.DH.ITEM.featureSubTypes.mastery && subclassState >= 3)
|
||||
item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.foundation ||
|
||||
(item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.specialization &&
|
||||
subclassState >= 2) ||
|
||||
(item.system.identifier === CONFIG.DH.ITEM.featureSubTypes.mastery && subclassState >= 3)
|
||||
) {
|
||||
subclassFeatures.push(item);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,50 +144,30 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
|
|||
}
|
||||
|
||||
if (this.actor && this.actor.type === 'character' && this.features) {
|
||||
const featureUpdates = {};
|
||||
const features = [];
|
||||
for (let f of this.features) {
|
||||
const fBase = f.item ?? f;
|
||||
const feature = fBase.system ? fBase : await foundry.utils.fromUuid(fBase.uuid);
|
||||
const createData = foundry.utils.mergeObject(
|
||||
feature.toObject(),
|
||||
{
|
||||
system: {
|
||||
originItemType: this.parent.type,
|
||||
originId: data._id,
|
||||
identifier: this.isMulticlass ? 'multiclass' : null
|
||||
}
|
||||
},
|
||||
{ inplace: false }
|
||||
const multiclass = this.isMulticlass ? 'multiclass' : null;
|
||||
features.push(
|
||||
foundry.utils.mergeObject(
|
||||
feature.toObject(),
|
||||
{
|
||||
_stats: { compendiumSource: fBase.uuid },
|
||||
system: {
|
||||
originItemType: this.parent.type,
|
||||
identifier: multiclass ?? (f.item ? f.type : null)
|
||||
}
|
||||
},
|
||||
{ inplace: false }
|
||||
)
|
||||
);
|
||||
const [doc] = await this.actor.createEmbeddedDocuments('Item', [createData]);
|
||||
|
||||
if (!featureUpdates.features)
|
||||
featureUpdates.features = this.features.map(x => (x.item ? { ...x, item: x.item.uuid } : x.uuid));
|
||||
|
||||
if (f.item) {
|
||||
const existingFeature = featureUpdates.features.find(x => x.item === f.item.uuid);
|
||||
existingFeature.item = doc.uuid;
|
||||
} else {
|
||||
const replaceIndex = featureUpdates.features.findIndex(x => x === f.uuid);
|
||||
featureUpdates.features.splice(replaceIndex, 1, doc.uuid);
|
||||
}
|
||||
}
|
||||
|
||||
await this.updateSource(featureUpdates);
|
||||
await this.actor.createEmbeddedDocuments('Item', features);
|
||||
}
|
||||
}
|
||||
|
||||
async _preDelete() {
|
||||
if (!this.actor || this.actor.type !== 'character') return;
|
||||
|
||||
const items = this.actor.items.filter(item => item.system.originId === this.parent.id);
|
||||
if (items.length > 0)
|
||||
await this.actor.deleteEmbeddedDocuments(
|
||||
'Item',
|
||||
items.map(x => x.id)
|
||||
);
|
||||
}
|
||||
|
||||
async _preUpdate(changed, options, userId) {
|
||||
const allowed = await super._preUpdate(changed, options, userId);
|
||||
if (allowed === false) return false;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import BaseDataItem from './base.mjs';
|
||||
import { ActionField, ActionsField } from '../fields/actionField.mjs';
|
||||
|
||||
export default class DHFeature extends BaseDataItem {
|
||||
/** @inheritDoc */
|
||||
|
|
@ -30,24 +29,7 @@ export default class DHFeature extends BaseDataItem {
|
|||
nullable: true,
|
||||
initial: null
|
||||
}),
|
||||
originId: new fields.StringField({ nullable: true, initial: null }),
|
||||
identifier: new fields.StringField()
|
||||
};
|
||||
}
|
||||
|
||||
get spellcastingModifier() {
|
||||
let traitValue = 0;
|
||||
if (this.actor && this.originId && ['class', 'subclass'].includes(this.originItemType)) {
|
||||
if (this.originItemType === 'subclass') {
|
||||
traitValue =
|
||||
this.actor.system.traits[this.actor.items.get(this.originId).system.spellcastingTrait]?.value ?? 0;
|
||||
} else {
|
||||
const { value: multiclass, subclass } = this.actor.system.multiclass;
|
||||
const selectedSubclass = multiclass?.id === this.originId ? subclass : this.actor.system.class.subclass;
|
||||
traitValue = this.actor.system.traits[selectedSubclass.system.spellcastingTrait]?.value ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
return traitValue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { emitAsGM, GMUpdateEvent } from '../systemRegistration/socket.mjs';
|
||||
import { LevelOptionType } from '../data/levelTier.mjs';
|
||||
import DHFeature from '../data/item/feature.mjs';
|
||||
import { damageKeyToNumber } from '../helpers/utils.mjs';
|
||||
import { damageKeyToNumber, versionCompare } from '../helpers/utils.mjs';
|
||||
import DhCompanionLevelUp from '../applications/levelup/companionLevelup.mjs';
|
||||
|
||||
export default class DhpActor extends Actor {
|
||||
|
|
@ -27,7 +27,7 @@ export default class DhpActor extends Actor {
|
|||
|
||||
/** @inheritDoc */
|
||||
static migrateData(source) {
|
||||
if(source.system?.attack && !source.system.attack.type) source.system.attack.type = "attack";
|
||||
if (source.system?.attack && !source.system.attack.type) source.system.attack.type = 'attack';
|
||||
return super.migrateData(source);
|
||||
}
|
||||
|
||||
|
|
@ -571,19 +571,15 @@ export default class DhpActor extends Actor {
|
|||
if (armorSlotResult) {
|
||||
const { modifiedDamage, armorSpent, stressSpent } = armorSlotResult;
|
||||
updates.find(u => u.key === 'hitPoints').value = modifiedDamage;
|
||||
if(armorSpent) {
|
||||
if (armorSpent) {
|
||||
const armorUpdate = updates.find(u => u.key === 'armor');
|
||||
if(armorUpdate)
|
||||
armorUpdate.value += armorSpent;
|
||||
else
|
||||
updates.push({ value: armorSpent, key: 'armor' });
|
||||
if (armorUpdate) armorUpdate.value += armorSpent;
|
||||
else updates.push({ value: armorSpent, key: 'armor' });
|
||||
}
|
||||
if(stressSpent) {
|
||||
if (stressSpent) {
|
||||
const stressUpdate = updates.find(u => u.key === 'stress');
|
||||
if(stressUpdate)
|
||||
stressUpdate.value += stressSpent;
|
||||
else
|
||||
updates.push({ value: stressSpent, key: 'stress' });
|
||||
if (stressUpdate) stressUpdate.value += stressSpent;
|
||||
else updates.push({ value: stressSpent, key: 'stress' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -753,4 +749,26 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
async importFromJSON(json) {
|
||||
if (!this.type === 'character') return await super.importFromJSON(json);
|
||||
|
||||
if (!CONST.WORLD_DOCUMENT_TYPES.includes(this.documentName)) {
|
||||
throw new Error('Only world Documents may be imported');
|
||||
}
|
||||
|
||||
const parsedJSON = JSON.parse(json);
|
||||
if (versionCompare(parsedJSON._stats.systemVersion, '1.1.0')) {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.localize('DAGGERHEART.ACTORS.Character.InvalidOldCharacterImportTitle')
|
||||
},
|
||||
content: game.i18n.localize('DAGGERHEART.ACTORS.Character.InvalidOldCharacterImportText')
|
||||
});
|
||||
if (!confirmed) return;
|
||||
}
|
||||
|
||||
return await super.importFromJSON(json);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -420,3 +420,14 @@ export async function createEmbeddedItemsWithEffects(actor, baseData) {
|
|||
export const slugify = name => {
|
||||
return name.toLowerCase().replaceAll(' ', '-').replaceAll('.', '');
|
||||
};
|
||||
|
||||
export const versionCompare = (current, target) => {
|
||||
const currentSplit = current.split('.').map(x => Number.parseInt(x));
|
||||
const targetSplit = target.split('.').map(x => Number.parseInt(x));
|
||||
for (var i = 0; i < currentSplit.length; i++) {
|
||||
if (currentSplit[i] < targetSplit[i]) return true;
|
||||
if (currentSplit[i] > targetSplit[i]) return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export { preloadHandlebarsTemplates as handlebarsRegistration } from './handlebars.mjs';
|
||||
export * as settingsRegistration from './settings.mjs';
|
||||
export * as socketRegistration from './socket.mjs';
|
||||
export { runMigrations } from './migrations.mjs';
|
||||
|
|
|
|||
41
module/systemRegistration/migrations.mjs
Normal file
41
module/systemRegistration/migrations.mjs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { versionCompare } from '../helpers/utils.mjs';
|
||||
|
||||
export async function runMigrations() {
|
||||
let lastMigrationVersion = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion);
|
||||
if (!lastMigrationVersion) lastMigrationVersion = '1.0.6';
|
||||
|
||||
if (versionCompare(lastMigrationVersion, '1.1.0')) {
|
||||
const compendiumActors = [];
|
||||
for (let pack of game.packs) {
|
||||
const documents = await pack.getDocuments();
|
||||
compendiumActors.push(...documents.filter(x => x.type === 'character'));
|
||||
}
|
||||
|
||||
[...compendiumActors, ...game.actors].forEach(actor => {
|
||||
const items = actor.items.reduce((acc, item) => {
|
||||
if (item.type === 'feature') {
|
||||
const { originItemType, isMulticlass, identifier } = item.system;
|
||||
const base = originItemType
|
||||
? actor.items.find(
|
||||
x => x.type === originItemType && Boolean(isMulticlass) === Boolean(x.system.isMulticlass)
|
||||
)
|
||||
: null;
|
||||
if (base) {
|
||||
const feature = base.system.features.find(x => x.item && x.item.uuid === item.uuid);
|
||||
if (feature && identifier !== 'multiclass') {
|
||||
acc.push({ _id: item.id, system: { identifier: feature.type } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
actor.updateEmbeddedDocuments('Item', items);
|
||||
});
|
||||
|
||||
lastMigrationVersion = '1.1.0';
|
||||
}
|
||||
|
||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion, lastMigrationVersion);
|
||||
}
|
||||
|
|
@ -91,6 +91,12 @@ const registerMenus = () => {
|
|||
};
|
||||
|
||||
const registerNonConfigSettings = () => {
|
||||
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion, {
|
||||
scope: 'world',
|
||||
config: false,
|
||||
type: String
|
||||
});
|
||||
|
||||
game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers, {
|
||||
scope: 'world',
|
||||
config: false,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"id": "daggerheart",
|
||||
"title": "Daggerheart",
|
||||
"description": "An unofficial implementation of the Daggerheart system",
|
||||
"version": "1.0.6",
|
||||
"version": "1.1.0",
|
||||
"compatibility": {
|
||||
"minimum": "13",
|
||||
"verified": "13.347",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue