mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-17 23:49:02 +01:00
Merge branch 'hotfix' into bug/671-reaction-roll-chat-title
This commit is contained in:
commit
755001df19
42 changed files with 304 additions and 261 deletions
|
|
@ -51,7 +51,7 @@ export default class DhCharacterLevelUp extends LevelUpBase {
|
|||
.filter(exp => exp.data.length > 0)
|
||||
.flatMap(exp =>
|
||||
exp.data.map(data => {
|
||||
const experience = Object.keys(this.actor.system.experiences).find(x => x === data);
|
||||
const experience = Object.keys(this.actor.system.experiences)[data];
|
||||
return this.actor.system.experiences[experience].name;
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export default class DhCompanionLevelUp extends BaseLevelUp {
|
|||
.filter(exp => exp.data.length > 0)
|
||||
.flatMap(exp =>
|
||||
exp.data.map(data => {
|
||||
const experience = Object.keys(this.actor.system.experiences).find(x => x === data);
|
||||
const experience = Object.keys(this.actor.system.experiences)[data];
|
||||
return this.actor.system.experiences[experience].name;
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -98,11 +98,17 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
|
|||
|
||||
async _onDrop(event) {
|
||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||
if (data.fromInternal) return;
|
||||
|
||||
|
||||
const item = await fromUuid(data.uuid);
|
||||
if (item.type === 'feature') {
|
||||
await this.actor.createEmbeddedDocuments('Item', [item]);
|
||||
if (item?.type === 'feature') {
|
||||
if (data.fromInternal && item.parent?.uuid === this.actor.uuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const itemData = item.toObject();
|
||||
delete itemData._id;
|
||||
|
||||
await this.actor.createEmbeddedDocuments('Item', [itemData]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ export default function DHApplicationMixin(Base) {
|
|||
|
||||
const docs = [];
|
||||
for (const docData of this.relatedDocs) {
|
||||
if (!docData) continue;
|
||||
const doc = await foundry.utils.fromUuid(docData.uuid);
|
||||
docs.push(doc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,12 +181,18 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
|
|||
static async #deleteFeature(_, element) {
|
||||
const target = element.closest('[data-item-uuid]');
|
||||
const feature = await getDocFromElement(target);
|
||||
if (!feature) return ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.featureIsMissing'));
|
||||
await this.document.update({
|
||||
'system.features': this.document.system.features
|
||||
.filter(x => target.dataset.type !== x.type || x.item.uuid !== feature.uuid)
|
||||
.map(x => ({ ...x, item: x.item.uuid }))
|
||||
});
|
||||
if (!feature) {
|
||||
await this.document.update({
|
||||
'system.features': this.document.system.features
|
||||
.filter(x => x.item)
|
||||
.map(x => ({ ...x, item: x.item.uuid }))
|
||||
});
|
||||
} else
|
||||
await this.document.update({
|
||||
'system.features': this.document.system.features
|
||||
.filter(x => target.dataset.type !== x.type || x.item.uuid !== feature.uuid)
|
||||
.map(x => ({ ...x, item: x.item.uuid }))
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -259,21 +265,45 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
|
|||
if (data.fromInternal) return;
|
||||
|
||||
const target = event.target.closest('fieldset.drop-section');
|
||||
const item = await fromUuid(data.uuid);
|
||||
let item = await fromUuid(data.uuid);
|
||||
if (item?.type === 'feature') {
|
||||
const cls = foundry.documents.Item.implementation;
|
||||
|
||||
if (this.document.parent?.type === 'character') {
|
||||
const itemData = item.toObject();
|
||||
item = await cls.create(
|
||||
{
|
||||
...itemData,
|
||||
system: {
|
||||
...itemData.system,
|
||||
originItemType: this.document.type,
|
||||
originId: this.document.id,
|
||||
identifier: this.document.system.isMulticlass ? 'multiclass' : null
|
||||
}
|
||||
},
|
||||
{ parent: this.document.parent }
|
||||
);
|
||||
}
|
||||
|
||||
if (target.dataset.type) {
|
||||
await this.document.update({
|
||||
'system.features': [...this.document.system.features, { type: target.dataset.type, item }].map(
|
||||
x => ({
|
||||
...x,
|
||||
item: x.item?.uuid
|
||||
})
|
||||
)
|
||||
});
|
||||
await this.document.update(
|
||||
{
|
||||
'system.features': [...this.document.system.features, { type: target.dataset.type, item }].map(
|
||||
x => ({
|
||||
...x,
|
||||
item: x.item?.uuid
|
||||
})
|
||||
)
|
||||
},
|
||||
{ parent: this.document.parent?.type === 'character' ? this.document.parent : undefined }
|
||||
);
|
||||
} else {
|
||||
await this.document.update({
|
||||
'system.features': [...this.document.system.features, item].map(x => x.uuid)
|
||||
});
|
||||
await this.document.update(
|
||||
{
|
||||
'system.features': [...this.document.system.features, item].map(x => x.uuid)
|
||||
},
|
||||
{ parent: this.document.parent?.type === 'character' ? this.document.parent : undefined }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -533,6 +533,10 @@ export const getDiceSoNicePresets = async (hopeFaces, fearFaces, advantageFaces
|
|||
};
|
||||
|
||||
export const refreshTypes = {
|
||||
scene: {
|
||||
id: 'session',
|
||||
label: 'DAGGERHEART.GENERAL.RefreshType.scene'
|
||||
},
|
||||
session: {
|
||||
id: 'session',
|
||||
label: 'DAGGERHEART.GENERAL.RefreshType.session'
|
||||
|
|
|
|||
|
|
@ -351,6 +351,17 @@ export default class DhCharacter extends BaseDataActor {
|
|||
return [...classDomains, ...multiclassDomains];
|
||||
}
|
||||
|
||||
get domainData() {
|
||||
const allDomainData = CONFIG.DH.DOMAIN.allDomains();
|
||||
return this.domains.map(key => {
|
||||
const domain = allDomainData[key];
|
||||
return {
|
||||
...domain,
|
||||
label: game.i18n.localize(domain.label)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
get domainCards() {
|
||||
const domainCards = this.parent.items.filter(x => x.type === 'domainCard');
|
||||
const loadout = domainCards.filter(x => !x.system.inVault);
|
||||
|
|
|
|||
|
|
@ -60,17 +60,6 @@ export default class DHClass extends BaseDataItem {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
get domainData() {
|
||||
const allDomainData = CONFIG.DH.DOMAIN.allDomains();
|
||||
return this.domains.map(key => {
|
||||
const domain = allDomainData[key];
|
||||
return {
|
||||
...domain,
|
||||
label: game.i18n.localize(domain.label)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
get hopeFeatures() {
|
||||
return this.features.filter(x => x.type === CONFIG.DH.ITEM.featureSubTypes.hope).map(x => x.item);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export default class DHSubclass extends BaseDataItem {
|
|||
integer: false,
|
||||
nullable: true,
|
||||
initial: null,
|
||||
label: "DAGGERHEART.ITEMS.Subclass.spellcastingTrait"
|
||||
label: 'DAGGERHEART.ITEMS.Subclass.spellcastingTrait'
|
||||
}),
|
||||
features: new ItemLinkFields(),
|
||||
featureState: new fields.NumberField({ required: true, initial: 1, min: 1 }),
|
||||
|
|
@ -50,7 +50,8 @@ export default class DHSubclass extends BaseDataItem {
|
|||
|
||||
async _preCreate(data, options, user) {
|
||||
if (this.actor?.type === 'character') {
|
||||
const dataUuid = data.uuid ?? data._stats?.compendiumSource ?? `Item.${data._id}`;
|
||||
const dataUuid =
|
||||
(data.uuid ?? data.folder) ? `Compendium.daggerheart.subclasses.Item.${data._id}` : `Item.${data._id}`;
|
||||
if (this.actor.system.class.subclass) {
|
||||
if (this.actor.system.multiclass.subclass) {
|
||||
ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassesAlreadyPresent'));
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ export default class DhpActor extends Actor {
|
|||
|
||||
await this.update({ 'system.levelData.level.changed': Math.min(newLevel, maxLevel) });
|
||||
} else {
|
||||
const levelupAuto = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto;
|
||||
|
||||
const usedLevel = Math.max(newLevel, 1);
|
||||
if (newLevel < 1) {
|
||||
ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.tooLowLevel'));
|
||||
|
|
@ -95,79 +97,90 @@ export default class DhpActor extends Actor {
|
|||
return acc;
|
||||
}, {});
|
||||
|
||||
const features = [];
|
||||
const domainCards = [];
|
||||
const experiences = [];
|
||||
const subclassFeatureState = { class: null, multiclass: null };
|
||||
let multiclass = null;
|
||||
Object.keys(this.system.levelData.levelups)
|
||||
.filter(x => x > usedLevel)
|
||||
.forEach(levelKey => {
|
||||
const level = this.system.levelData.levelups[levelKey];
|
||||
const achievementCards = level.achievements.domainCards.map(x => x.itemUuid);
|
||||
const advancementCards = level.selections.filter(x => x.type === 'domainCard').map(x => x.itemUuid);
|
||||
domainCards.push(...achievementCards, ...advancementCards);
|
||||
experiences.push(...Object.keys(level.achievements.experiences));
|
||||
features.push(...level.selections.flatMap(x => x.features));
|
||||
if (levelupAuto) {
|
||||
const features = [];
|
||||
const domainCards = [];
|
||||
const experiences = [];
|
||||
const subclassFeatureState = { class: null, multiclass: null };
|
||||
let multiclass = null;
|
||||
Object.keys(this.system.levelData.levelups)
|
||||
.filter(x => x > usedLevel)
|
||||
.forEach(levelKey => {
|
||||
const level = this.system.levelData.levelups[levelKey];
|
||||
const achievementCards = level.achievements.domainCards.map(x => x.itemUuid);
|
||||
const advancementCards = level.selections
|
||||
.filter(x => x.type === 'domainCard')
|
||||
.map(x => x.itemUuid);
|
||||
domainCards.push(...achievementCards, ...advancementCards);
|
||||
experiences.push(...Object.keys(level.achievements.experiences));
|
||||
features.push(...level.selections.flatMap(x => x.features));
|
||||
|
||||
const subclass = level.selections.find(x => x.type === 'subclass');
|
||||
if (subclass) {
|
||||
const path = subclass.secondaryData.isMulticlass === 'true' ? 'multiclass' : 'class';
|
||||
const subclassState = Number(subclass.secondaryData.featureState) - 1;
|
||||
subclassFeatureState[path] = subclassFeatureState[path]
|
||||
? Math.min(subclassState, subclassFeatureState[path])
|
||||
: subclassState;
|
||||
}
|
||||
const subclass = level.selections.find(x => x.type === 'subclass');
|
||||
if (subclass) {
|
||||
const path = subclass.secondaryData.isMulticlass === 'true' ? 'multiclass' : 'class';
|
||||
const subclassState = Number(subclass.secondaryData.featureState) - 1;
|
||||
subclassFeatureState[path] = subclassFeatureState[path]
|
||||
? Math.min(subclassState, subclassFeatureState[path])
|
||||
: subclassState;
|
||||
}
|
||||
|
||||
multiclass = level.selections.find(x => x.type === 'multiclass');
|
||||
});
|
||||
multiclass = level.selections.find(x => x.type === 'multiclass');
|
||||
});
|
||||
|
||||
for (let feature of features) {
|
||||
if (feature.onPartner && !this.system.partner) continue;
|
||||
for (let feature of features) {
|
||||
if (feature.onPartner && !this.system.partner) continue;
|
||||
|
||||
const document = feature.onPartner ? this.system.partner : this;
|
||||
document.items.get(feature.id)?.delete();
|
||||
}
|
||||
|
||||
if (experiences.length > 0) {
|
||||
const getUpdate = () => ({
|
||||
'system.experiences': experiences.reduce((acc, key) => {
|
||||
acc[`-=${key}`] = null;
|
||||
return acc;
|
||||
}, {})
|
||||
});
|
||||
this.update(getUpdate());
|
||||
if (this.system.companion) {
|
||||
this.system.companion.update(getUpdate());
|
||||
const document = feature.onPartner ? this.system.partner : this;
|
||||
document.items.get(feature.id)?.delete();
|
||||
}
|
||||
}
|
||||
|
||||
if (subclassFeatureState.class) {
|
||||
this.system.class.subclass.update({ 'system.featureState': subclassFeatureState.class });
|
||||
}
|
||||
|
||||
if (subclassFeatureState.multiclass) {
|
||||
this.system.multiclass.subclass.update({ 'system.featureState': subclassFeatureState.multiclass });
|
||||
}
|
||||
|
||||
if (multiclass) {
|
||||
const multiclassSubclass = this.items.find(x => x.type === 'subclass' && x.system.isMulticlass);
|
||||
const multiclassItem = this.items.find(x => x.uuid === multiclass.itemUuid);
|
||||
|
||||
multiclassSubclass.delete();
|
||||
multiclassItem.delete();
|
||||
|
||||
this.update({
|
||||
'system.multiclass': {
|
||||
value: null,
|
||||
subclass: null
|
||||
if (experiences.length > 0) {
|
||||
const getUpdate = () => ({
|
||||
'system.experiences': experiences.reduce((acc, key) => {
|
||||
acc[`-=${key}`] = null;
|
||||
return acc;
|
||||
}, {})
|
||||
});
|
||||
this.update(getUpdate());
|
||||
if (this.system.companion) {
|
||||
this.system.companion.update(getUpdate());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (let domainCard of domainCards) {
|
||||
const itemCard = this.items.find(x => x.uuid === domainCard);
|
||||
itemCard.delete();
|
||||
if (subclassFeatureState.class) {
|
||||
this.system.class.subclass.update({ 'system.featureState': subclassFeatureState.class });
|
||||
}
|
||||
|
||||
if (subclassFeatureState.multiclass) {
|
||||
this.system.multiclass.subclass.update({ 'system.featureState': subclassFeatureState.multiclass });
|
||||
}
|
||||
|
||||
if (multiclass) {
|
||||
const multiclassItem = this.items.find(x => x.uuid === multiclass.itemUuid);
|
||||
const multiclassFeatures = this.items.filter(
|
||||
x => x.system.originItemType === 'class' && x.system.identifier === 'multiclass'
|
||||
);
|
||||
const subclassFeatures = this.items.filter(
|
||||
x => x.system.originItemType === 'subclass' && x.system.identifier === 'multiclass'
|
||||
);
|
||||
|
||||
this.deleteEmbeddedDocuments(
|
||||
'Item',
|
||||
[multiclassItem, ...multiclassFeatures, ...subclassFeatures].map(x => x.id)
|
||||
);
|
||||
|
||||
this.update({
|
||||
'system.multiclass': {
|
||||
value: null,
|
||||
subclass: null
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (let domainCard of domainCards) {
|
||||
const itemCard = this.items.find(x => x.uuid === domainCard);
|
||||
itemCard.delete();
|
||||
}
|
||||
}
|
||||
|
||||
await this.update({
|
||||
|
|
@ -315,6 +328,7 @@ export default class DhpActor extends Actor {
|
|||
...multiclassData,
|
||||
system: {
|
||||
...multiclassData.system,
|
||||
features: multiclassData.system.features.filter(x => x.type !== 'hope'),
|
||||
domains: [multiclass.secondaryData.domain],
|
||||
isMulticlass: true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!game.user.isGM && !this.isAuthor && !this.speakerActor?.isOwner) {
|
||||
const buttons = html.querySelectorAll(".ability-card-footer > .ability-use-button");
|
||||
buttons.forEach(b => b.remove());
|
||||
}
|
||||
}
|
||||
|
||||
addChatListeners(html) {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ export default class RegisterHandlebarsHelpers {
|
|||
|
||||
static rollParsed(value, actor, item, numerical) {
|
||||
const isNumerical = typeof numerical === 'boolean' ? numerical : false;
|
||||
const result = itemAbleRollParse(value, actor.getRollData(), item);
|
||||
const result = itemAbleRollParse(value, actor?.getRollData() ?? {}, item);
|
||||
return isNumerical ? (!result ? 0 : Number(result)) : result;
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ export default class RegisterHandlebarsHelpers {
|
|||
}
|
||||
|
||||
static empty(object) {
|
||||
if(!(typeof object === 'object')) return true;
|
||||
if (!(typeof object === 'object')) return true;
|
||||
return Object.keys(object).length === 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,13 +85,12 @@ export const chunkify = (array, chunkSize, mappingFunc) => {
|
|||
|
||||
export const tagifyElement = (element, baseOptions, onChange, tagifyOptions = {}) => {
|
||||
const { maxTags } = tagifyOptions;
|
||||
const options =
|
||||
typeof baseOptions === 'object'
|
||||
? Object.keys(baseOptions).map(optionKey => ({
|
||||
...baseOptions[optionKey],
|
||||
id: optionKey
|
||||
}))
|
||||
: baseOptions;
|
||||
const options = Array.isArray(baseOptions)
|
||||
? baseOptions
|
||||
: Object.keys(baseOptions).map(optionKey => ({
|
||||
...baseOptions[optionKey],
|
||||
id: optionKey
|
||||
}));
|
||||
|
||||
const tagifyElement = new Tagify(element, {
|
||||
tagTextProp: 'name',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue