mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-11 19:25:21 +01:00
Merge branch 'main' into development
This commit is contained in:
commit
2820c96259
157 changed files with 1576 additions and 1286 deletions
|
|
@ -494,7 +494,9 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
|||
this.render();
|
||||
}
|
||||
|
||||
static async finish() {
|
||||
static async finish(_, button) {
|
||||
button.disabled = true;
|
||||
|
||||
const primaryAncestryFeature = this.setup.primaryAncestry.system.primaryFeature;
|
||||
const secondaryAncestryFeature = this.setup.secondaryAncestry?.uuid
|
||||
? this.setup.secondaryAncestry.system.secondaryFeature
|
||||
|
|
|
|||
|
|
@ -650,7 +650,9 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
|||
this.render();
|
||||
}
|
||||
|
||||
static async save() {
|
||||
static async save(_, button) {
|
||||
button.disabled = true;
|
||||
|
||||
const levelupData = Object.keys(this.levelup.levels).reduce((acc, level) => {
|
||||
if (level >= this.levelup.startLevel) {
|
||||
acc[level] = this.levelup.levels[level].toObject();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { getDocFromElement } from '../../../helpers/utils.mjs';
|
||||
import DHBaseActorSheet from '../api/base-actor.mjs';
|
||||
|
||||
/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */
|
||||
|
|
@ -53,6 +54,15 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
|||
return context;
|
||||
}
|
||||
|
||||
/**@inheritdoc */
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
htmlElement.querySelectorAll('.inventory-item-resource').forEach(element => {
|
||||
element.addEventListener('change', this.updateItemResource.bind(this));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare render context for the Biography part.
|
||||
* @param {ApplicationRenderContext} context
|
||||
|
|
@ -121,4 +131,18 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
|||
|
||||
this.actor.diceRoll(config);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Application Listener Actions */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
async updateItemResource(event) {
|
||||
const item = await getDocFromElement(event.currentTarget);
|
||||
if (!item) return;
|
||||
|
||||
const max = event.currentTarget.max ? Number(event.currentTarget.max) : null;
|
||||
const value = max ? Math.min(Number(event.currentTarget.value), max) : event.currentTarget.value;
|
||||
await item.update({ 'system.resource.value': value });
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,8 +209,9 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
}
|
||||
|
||||
async consume(config, successCost = false) {
|
||||
const usefulResources = {
|
||||
...foundry.utils.deepClone(this.actor.system.resources),
|
||||
const actor= this.actor.system.partner ?? this.actor,
|
||||
usefulResources = {
|
||||
...foundry.utils.deepClone(actor.system.resources),
|
||||
fear: {
|
||||
value: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear),
|
||||
max: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxFear,
|
||||
|
|
@ -247,7 +248,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
}
|
||||
}, []);
|
||||
|
||||
await (this.actor.system.partner ?? this.actor).modifyResource(resources);
|
||||
await actor.modifyResource(resources);
|
||||
if (
|
||||
config.uses?.enabled &&
|
||||
((!successCost && (!config.uses?.consumeOnSuccess || config.roll?.success)) ||
|
||||
|
|
|
|||
|
|
@ -93,14 +93,6 @@ export default class DhCharacter extends BaseDataActor {
|
|||
faith: new fields.StringField({})
|
||||
})
|
||||
}),
|
||||
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 })
|
||||
}),
|
||||
attack: new ActionField({
|
||||
initial: {
|
||||
name: 'Unarmed Attack',
|
||||
|
|
@ -314,6 +306,26 @@ export default class DhCharacter extends BaseDataActor {
|
|||
return this.parent.items.find(x => x.type === 'community') ?? null;
|
||||
}
|
||||
|
||||
get class() {
|
||||
const value = this.parent.items.find(x => x.type === 'class' && !x.system.isMulticlass);
|
||||
const subclass = this.parent.items.find(x => x.type === 'subclass' && !x.system.isMulticlass);
|
||||
|
||||
return {
|
||||
value,
|
||||
subclass
|
||||
};
|
||||
}
|
||||
|
||||
get multiclass() {
|
||||
const value = this.parent.items.find(x => x.type === 'Class' && x.system.isMulticlass);
|
||||
const subclass = this.parent.items.find(x => x.type === 'subclass' && x.system.isMulticlass);
|
||||
|
||||
return {
|
||||
value,
|
||||
subclass
|
||||
};
|
||||
}
|
||||
|
||||
get features() {
|
||||
return this.parent.items.filter(x => x.type === 'feature') ?? [];
|
||||
}
|
||||
|
|
@ -323,7 +335,8 @@ export default class DhCharacter extends BaseDataActor {
|
|||
}
|
||||
|
||||
get needsCharacterSetup() {
|
||||
return !(this.class.value || this.class.subclass || this.ancestry || this.community);
|
||||
const { value: classValue, subclass } = this.class;
|
||||
return !(classValue || subclass || this.ancestry || this.community);
|
||||
}
|
||||
|
||||
get spellcastModifierTrait() {
|
||||
|
|
@ -347,7 +360,8 @@ export default class DhCharacter extends BaseDataActor {
|
|||
|
||||
get domains() {
|
||||
const classDomains = this.class.value ? this.class.value.system.domains : [];
|
||||
const multiclassDomains = this.multiclass.value ? this.multiclass.value.system.domains : [];
|
||||
const multiclass = this.multiclass.value;
|
||||
const multiclassDomains = multiclass ? multiclass.system.domains : [];
|
||||
return [...classDomains, ...multiclassDomains];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ export class ActionsField extends MappingField {
|
|||
*/
|
||||
export class ActionField extends foundry.data.fields.ObjectField {
|
||||
getModel(value) {
|
||||
if (value && !value.type) value.type = 'attack';
|
||||
return game.system.api.models.actions.actionsTypes[value.type] ?? null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,26 +102,11 @@ export default class DHClass extends BaseDataItem {
|
|||
if (allowed === false) return;
|
||||
}
|
||||
|
||||
_onCreate(data, options, userId) {
|
||||
super._onCreate(data, options, userId);
|
||||
|
||||
if (userId !== game.user.id) return;
|
||||
|
||||
if (options.parent?.type === 'character') {
|
||||
const path = `system.${data.system.isMulticlass ? 'multiclass.value' : 'class.value'}`;
|
||||
options.parent.update({ [path]: `${options.parent.uuid}.Item.${data._id}` });
|
||||
}
|
||||
}
|
||||
|
||||
_onDelete(options, userId) {
|
||||
super._onDelete(options, userId);
|
||||
|
||||
if (options.parent?.type === 'character') {
|
||||
const path = `system.${this.isMulticlass ? 'multiclass' : 'class'}`;
|
||||
options.parent.update({
|
||||
[`${path}.value`]: null
|
||||
});
|
||||
|
||||
foundry.utils.getProperty(options.parent, `${path}.subclass`)?.delete();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,9 @@ export default class DHFeature extends BaseDataItem {
|
|||
traitValue =
|
||||
this.actor.system.traits[this.actor.items.get(this.originId).system.spellcastingTrait]?.value ?? 0;
|
||||
} else {
|
||||
const subclass =
|
||||
this.actor.system.multiclass.value?.id === this.originId
|
||||
? this.actor.system.multiclass.subclass
|
||||
: this.actor.system.class.subclass;
|
||||
traitValue = this.actor.system.traits[subclass.system.spellcastingTrait]?.value ?? 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,24 +88,4 @@ export default class DHSubclass extends BaseDataItem {
|
|||
const allowed = await super._preCreate(data, options, user);
|
||||
if (allowed === false) return;
|
||||
}
|
||||
|
||||
_onCreate(data, options, userId) {
|
||||
super._onCreate(data, options, userId);
|
||||
|
||||
if (userId !== game.user.id) return;
|
||||
|
||||
if (options.parent?.type === 'character') {
|
||||
const path = `system.${data.system.isMulticlass ? 'multiclass.subclass' : 'class.subclass'}`;
|
||||
options.parent.update({ [path]: `${options.parent.uuid}.Item.${data._id}` });
|
||||
}
|
||||
}
|
||||
|
||||
_onDelete(options, userId) {
|
||||
super._onDelete(options, userId);
|
||||
|
||||
if (options.parent?.type === 'character') {
|
||||
const path = `system.${this.isMulticlass ? 'multiclass.subclass' : 'class.subclass'}`;
|
||||
options.parent.update({ [path]: null });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ export default class DamageRoll extends DHRoll {
|
|||
}
|
||||
|
||||
if (config.isCritical && part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) {
|
||||
const total = part.roll.dice.reduce((acc, term) => acc + term._faces*term._number, 0);
|
||||
const total = part.roll.dice.reduce((acc, term) => acc + term._faces * term._number, 0);
|
||||
if (total > 0) {
|
||||
part.roll.terms.push(...this.formatModifier(total));
|
||||
}
|
||||
|
|
@ -161,11 +161,11 @@ export default class DamageRoll extends DHRoll {
|
|||
if (config.data.parent.appliedEffects) {
|
||||
// Bardic Rally
|
||||
const rallyChoices = config.data?.parent?.appliedEffects.reduce((a, c) => {
|
||||
const change = c.changes.find(ch => ch.key === 'system.bonuses.rally');
|
||||
if (change) a.push({ value: c.id, label: change.value });
|
||||
return a;
|
||||
}, [])
|
||||
if(rallyChoices.length) {
|
||||
const change = c.changes.find(ch => ch.key === 'system.bonuses.rally');
|
||||
if (change) a.push({ value: c.id, label: change.value });
|
||||
return a;
|
||||
}, []);
|
||||
if (rallyChoices.length) {
|
||||
mods.rally = {
|
||||
label: 'DAGGERHEART.CLASS.Feature.rallyDice',
|
||||
values: rallyChoices,
|
||||
|
|
@ -318,15 +318,19 @@ export default class DamageRoll extends DHRoll {
|
|||
});
|
||||
|
||||
const updateMessage = game.messages.get(message._id);
|
||||
const damageParts = updateMessage.system.damage[damageType].parts.map((damagePart, index) => {
|
||||
if (index !== Number(part)) return damagePart;
|
||||
return {
|
||||
...rollPart,
|
||||
total: parsedRoll.total,
|
||||
dice: rerolledDice
|
||||
};
|
||||
});
|
||||
await updateMessage.update({
|
||||
[`system.damage.${damageType}`]: {
|
||||
...updateMessage,
|
||||
total: parsedRoll.total,
|
||||
[`parts.${part}`]: {
|
||||
...rollPart,
|
||||
total: parsedRoll.total,
|
||||
dice: rerolledDice
|
||||
}
|
||||
parts: damageParts
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@ export default class DhpActor extends Actor {
|
|||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @inheritDoc */
|
||||
static migrateData(source) {
|
||||
if(source.system?.attack && !source.system.attack.type) source.system.attack.type = "attack";
|
||||
return super.migrateData(source);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**@inheritdoc */
|
||||
static getDefaultArtwork(actorData) {
|
||||
const { type } = actorData;
|
||||
|
|
@ -564,10 +572,20 @@ export default class DhpActor extends Actor {
|
|||
if (armorSlotResult) {
|
||||
const { modifiedDamage, armorSpent, stressSpent } = armorSlotResult;
|
||||
updates.find(u => u.key === 'hitPoints').value = modifiedDamage;
|
||||
updates.push(
|
||||
...(armorSpent ? [{ value: armorSpent, key: 'armor' }] : []),
|
||||
...(stressSpent ? [{ value: stressSpent, key: 'stress' }] : [])
|
||||
);
|
||||
if(armorSpent) {
|
||||
const armorUpdate = updates.find(u => u.key === 'armor');
|
||||
if(armorUpdate)
|
||||
armorUpdate.value += armorSpent;
|
||||
else
|
||||
updates.push({ value: armorSpent, key: 'armor' });
|
||||
}
|
||||
if(stressSpent) {
|
||||
const stressUpdate = updates.find(u => u.key === 'stress');
|
||||
if(stressUpdate)
|
||||
stressUpdate.value += stressSpent;
|
||||
else
|
||||
updates.push({ value: stressSpent, key: 'stress' });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -632,7 +650,7 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
|
||||
async modifyResource(resources) {
|
||||
if (!resources.length) return;
|
||||
if (!resources?.length) return;
|
||||
|
||||
if (resources.find(r => r.key === 'stress')) this.convertStressDamageToHP(resources);
|
||||
let updates = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue