mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
Merge branch 'main' into feature/death-moves
This commit is contained in:
commit
9a3355175b
229 changed files with 2452 additions and 893 deletions
|
|
@ -195,9 +195,9 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
if (this.config.roll) {
|
||||
this.reactionOverride = !this.reactionOverride;
|
||||
this.config.actionType = this.reactionOverride
|
||||
? CONFIG.DH.ITEM.actionTypes.reaction.id
|
||||
: this.config.actionType === CONFIG.DH.ITEM.actionTypes.reaction.id
|
||||
? CONFIG.DH.ITEM.actionTypes.action.id
|
||||
? 'reaction'
|
||||
: this.config.actionType === 'reaction'
|
||||
? 'action'
|
||||
: this.config.actionType;
|
||||
this.render();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
|||
}
|
||||
|
||||
getRefreshables() {
|
||||
const actionItems = this.actor.items.reduce((acc, x) => {
|
||||
const actionItems = this.actor.items.filter(x => this.actor.system.isItemAvailable(x)).reduce((acc, x) => {
|
||||
if (x.system.actions) {
|
||||
const recoverable = x.system.actions.reduce((acc, action) => {
|
||||
if (refreshIsAllowed([this.shortrest ? 'shortRest' : 'longRest'], action.uses.recovery)) {
|
||||
|
|
|
|||
|
|
@ -1,69 +1,61 @@
|
|||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
export default class ItemTransferDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
constructor(item) {
|
||||
constructor(data) {
|
||||
super({});
|
||||
|
||||
this.item = item;
|
||||
this.quantity = item.system.quantity;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
get title() {
|
||||
return this.item.name;
|
||||
return this.data.title;
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'dh-style', 'dialog', 'item-transfer'],
|
||||
position: { width: 300, height: 'auto' },
|
||||
position: { width: 400, height: 'auto' },
|
||||
window: { icon: 'fa-solid fa-hand-holding-hand' },
|
||||
actions: {
|
||||
finish: ItemTransferDialog.#finish
|
||||
},
|
||||
form: { handler: this.updateData, submitOnChange: true, closeOnSubmit: false }
|
||||
}
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
main: { template: 'systems/daggerheart/templates/dialogs/item-transfer.hbs' }
|
||||
main: { template: 'systems/daggerheart/templates/dialogs/item-transfer.hbs', root: true }
|
||||
};
|
||||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
htmlElement.querySelector('.number-display').addEventListener('change', event => {
|
||||
this.quantity = isNaN(event.target.value) ? this.quantity : Number(event.target.value);
|
||||
this.render();
|
||||
});
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.item = this.item;
|
||||
context.quantity = this.quantity;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static async updateData(_event, _element, formData) {
|
||||
const { quantity } = foundry.utils.expandObject(formData.object);
|
||||
this.quantity = quantity;
|
||||
this.render();
|
||||
return foundry.utils.mergeObject(context, this.data);
|
||||
}
|
||||
|
||||
static async #finish() {
|
||||
this.close({ submitted: true });
|
||||
this.selected = this.form.elements.quantity.valueAsNumber || null;
|
||||
this.close();
|
||||
}
|
||||
|
||||
close(options = {}) {
|
||||
if (!options.submitted) this.quantity = null;
|
||||
static #determineTransferOptions({ originActor, targetActor, item, currency }) {
|
||||
originActor ??= item?.actor;
|
||||
const homebrewKey = CONFIG.DH.SETTINGS.gameSettings.Homebrew;
|
||||
const currencySetting = game.settings.get(CONFIG.DH.id, homebrewKey).currency?.[currency] ?? null;
|
||||
|
||||
super.close();
|
||||
return {
|
||||
originActor,
|
||||
targetActor,
|
||||
itemImage: item?.img,
|
||||
currencyIcon: currencySetting?.icon,
|
||||
max: item?.system.quantity ?? originActor.system.gold[currency] ?? 0,
|
||||
title: item?.name ?? currencySetting?.label
|
||||
};
|
||||
}
|
||||
|
||||
static async configure(item) {
|
||||
static async configure(options) {
|
||||
return new Promise(resolve => {
|
||||
const app = new this(item);
|
||||
app.addEventListener('close', () => resolve(app.quantity), { once: true });
|
||||
const data = this.#determineTransferOptions(options);
|
||||
if (data.max <= 1) return resolve(data.max);
|
||||
|
||||
const app = new this(data);
|
||||
app.addEventListener('close', () => resolve(app.selected), { once: true });
|
||||
app.render({ force: true });
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,8 +220,8 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
!roll.system.isCritical && criticalRoll
|
||||
? (await getCritDamageBonus(damage.formula)) + damage.total
|
||||
: damage.total;
|
||||
const updatedDamageParts = damage.parts;
|
||||
if (systemData.damage[key]) {
|
||||
const updatedDamageParts = damage.parts;
|
||||
if (!roll.system.isCritical && criticalRoll) {
|
||||
for (let part of updatedDamageParts) {
|
||||
const criticalDamage = await getCritDamageBonus(part.formula);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
deleteAdversaryType: this.deleteAdversaryType,
|
||||
selectAdversaryType: this.selectAdversaryType,
|
||||
save: this.save,
|
||||
resetTokenSizes: this.resetTokenSizes,
|
||||
reset: this.reset
|
||||
},
|
||||
form: { handler: this.updateData, submitOnChange: true }
|
||||
|
|
@ -424,6 +425,14 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
this.close();
|
||||
}
|
||||
|
||||
static async resetTokenSizes() {
|
||||
await this.settings.updateSource({
|
||||
tokenSizes: this.settings.schema.fields.tokenSizes.initial
|
||||
});
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async reset() {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,18 @@
|
|||
export default class DhPrototypeTokenConfig extends foundry.applications.sheets.PrototypeTokenConfig {
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
tabs: super.PARTS.tabs,
|
||||
identity: super.PARTS.identity,
|
||||
appearance: {
|
||||
template: 'systems/daggerheart/templates/sheets-settings/token-config/appearance.hbs',
|
||||
scrollable: ['']
|
||||
},
|
||||
vision: super.PARTS.vision,
|
||||
light: super.PARTS.light,
|
||||
resources: super.PARTS.resources,
|
||||
footer: super.PARTS.footer
|
||||
};
|
||||
|
||||
/** @inheritDoc */
|
||||
async _prepareResourcesTab() {
|
||||
const token = this.token;
|
||||
|
|
@ -17,4 +31,11 @@ export default class DhPrototypeTokenConfig extends foundry.applications.sheets.
|
|||
turnMarkerAnimations: CONFIG.Combat.settings.turnMarkerAnimations
|
||||
};
|
||||
}
|
||||
|
||||
async _prepareAppearanceTab() {
|
||||
const context = await super._prepareAppearanceTab();
|
||||
context.actorSizeUsed = this.token.actor ? Boolean(this.token.actor.system.size) : false;
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,18 @@
|
|||
export default class DhTokenConfig extends foundry.applications.sheets.TokenConfig {
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
tabs: super.PARTS.tabs,
|
||||
identity: super.PARTS.identity,
|
||||
appearance: {
|
||||
template: 'systems/daggerheart/templates/sheets-settings/token-config/appearance.hbs',
|
||||
scrollable: ['']
|
||||
},
|
||||
vision: super.PARTS.vision,
|
||||
light: super.PARTS.light,
|
||||
resources: super.PARTS.resources,
|
||||
footer: super.PARTS.footer
|
||||
};
|
||||
|
||||
/** @inheritDoc */
|
||||
async _prepareResourcesTab() {
|
||||
const token = this.token;
|
||||
|
|
@ -17,4 +31,11 @@ export default class DhTokenConfig extends foundry.applications.sheets.TokenConf
|
|||
turnMarkerAnimations: CONFIG.Combat.settings.turnMarkerAnimations
|
||||
};
|
||||
}
|
||||
|
||||
async _prepareAppearanceTab() {
|
||||
const context = await super._prepareAppearanceTab();
|
||||
context.actorSizeUsed = this.token.actor ? Boolean(this.token.actor.system.size) : false;
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -675,16 +675,21 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
roll: {
|
||||
trait: button.dataset.attribute
|
||||
},
|
||||
hasRoll: true
|
||||
};
|
||||
const result = await this.document.diceRoll({
|
||||
...config,
|
||||
hasRoll: true,
|
||||
actionType: 'action',
|
||||
headerTitle: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${this.actor.name}`,
|
||||
title: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: abilityLabel
|
||||
})
|
||||
});
|
||||
};
|
||||
const result = await this.document.diceRoll(config);
|
||||
|
||||
/* This could be avoided by baking config.costs into config.resourceUpdates. Didn't feel like messing with it at the time */
|
||||
const costResources = result.costs
|
||||
.filter(x => x.enabled)
|
||||
.map(cost => ({ ...cost, value: -cost.value, total: -cost.total }));
|
||||
config.resourceUpdates.addResources(costResources);
|
||||
await config.resourceUpdates.updateResources();
|
||||
}
|
||||
|
||||
//TODO: redo toggleEquipItem method
|
||||
|
|
|
|||
|
|
@ -183,7 +183,6 @@ export default function DHApplicationMixin(Base) {
|
|||
for (const deltaInput of htmlElement.querySelectorAll('input[data-allow-delta]')) {
|
||||
deltaInput.dataset.numValue = deltaInput.value;
|
||||
deltaInput.inputMode = 'numeric';
|
||||
deltaInput.pattern = '^[+=\\-]?\d*';
|
||||
|
||||
const handleUpdate = (delta = 0) => {
|
||||
const min = Number(deltaInput.min) || 0;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
|||
}
|
||||
}
|
||||
],
|
||||
dragDrop: [{ dragSelector: '.inventory-item[data-type="attack"]', dropSelector: null }]
|
||||
dragDrop: [
|
||||
{ dragSelector: '.inventory-item[data-type="attack"]', dropSelector: null },
|
||||
{ dragSelector: ".currency[data-currency] .drag-handle", dropSelector: null }
|
||||
]
|
||||
};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
@ -254,14 +257,35 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
|||
/* Application Drag/Drop */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
async _onDrop(event) {
|
||||
event.stopPropagation();
|
||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||
if (data.type === 'Currency' && ['character', 'party'].includes(this.document.type)) {
|
||||
const originActor = await foundry.utils.fromUuid(data.originActor);
|
||||
if (!originActor || originActor.uuid === this.document.uuid) return;
|
||||
const currency = data.currency;
|
||||
const quantity = await game.system.api.applications.dialogs.ItemTransferDialog.configure({
|
||||
originActor,
|
||||
targetActor: this.document,
|
||||
currency
|
||||
});
|
||||
if (quantity) {
|
||||
originActor.update({ [`system.gold.${currency}`]: Math.max(0, originActor.system.gold[currency] - quantity) });
|
||||
this.document.update({ [`system.gold.${currency}`]: this.document.system.gold[currency] + quantity });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return super._onDrop(event);
|
||||
}
|
||||
|
||||
async _onDropItem(event, item) {
|
||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||
const physicalActorTypes = ['character', 'party'];
|
||||
const originActor = item.actor;
|
||||
if (
|
||||
item.actor?.uuid === this.document.uuid ||
|
||||
!originActor ||
|
||||
!physicalActorTypes.includes(this.document.type)
|
||||
!['character', 'party'].includes(this.document.type)
|
||||
) {
|
||||
return super._onDropItem(event, item);
|
||||
}
|
||||
|
|
@ -270,10 +294,10 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
|||
if (item.system.metadata.isInventoryItem) {
|
||||
if (item.system.metadata.isQuantifiable) {
|
||||
const actorItem = originActor.items.get(data.originId);
|
||||
const quantityTransfered =
|
||||
actorItem.system.quantity === 1
|
||||
? 1
|
||||
: await game.system.api.applications.dialogs.ItemTransferDialog.configure(item);
|
||||
const quantityTransfered = await game.system.api.applications.dialogs.ItemTransferDialog.configure({
|
||||
item,
|
||||
targetActor: this.document
|
||||
});
|
||||
|
||||
if (quantityTransfered) {
|
||||
if (quantityTransfered === actorItem.system.quantity) {
|
||||
|
|
@ -314,6 +338,16 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
|||
* @param {DragEvent} event - The drag event
|
||||
*/
|
||||
async _onDragStart(event) {
|
||||
// Handle drag/dropping currencies
|
||||
const currencyEl = event.currentTarget.closest(".currency[data-currency]");
|
||||
if (currencyEl) {
|
||||
const currency = currencyEl.dataset.currency;
|
||||
const data = { type: 'Currency', currency, originActor: this.document.uuid };
|
||||
event.dataTransfer.setData('text/plain', JSON.stringify(data));
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle drag/dropping attacks
|
||||
const attackItem = event.currentTarget.closest('.inventory-item[data-type="attack"]');
|
||||
if (attackItem) {
|
||||
const attackData = {
|
||||
|
|
@ -340,4 +374,4 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
|||
|
||||
super._onDragStart(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -77,6 +77,7 @@ export default class BeastformSheet extends DHBaseItemSheet {
|
|||
name: context.document.system.advantageOn[key].value
|
||||
}))
|
||||
);
|
||||
context.dimensionsDisabled = context.document.system.tokenSize.size !== 'custom';
|
||||
break;
|
||||
case 'effects':
|
||||
context.effects.actives = context.effects.actives.map(effect => {
|
||||
|
|
|
|||
|
|
@ -31,4 +31,11 @@ export default class FeatureSheet extends DHBaseItemSheet {
|
|||
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
|
||||
}
|
||||
};
|
||||
//Might be wrong location but testing out if here is okay.
|
||||
/**@override */
|
||||
async _prepareContext(options) {
|
||||
const context = await super._prepareContext(options);
|
||||
context.featureFormChoices = CONFIG.DH.ITEM.featureForm;
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,4 +17,30 @@ export default class DhActorDirectory extends foundry.applications.sidebar.tabs.
|
|||
: null;
|
||||
};
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
_onDragStart(event) {
|
||||
let actor;
|
||||
const { entryId } = event.currentTarget.dataset;
|
||||
if (entryId) {
|
||||
actor = this.collection.get(entryId);
|
||||
if (!actor?.visible) return false;
|
||||
}
|
||||
super._onDragStart(event);
|
||||
|
||||
// Create the drag preview.
|
||||
if (actor && canvas.ready) {
|
||||
const img = event.currentTarget.querySelector('img');
|
||||
const pt = actor.prototypeToken;
|
||||
const usesSize = actor.system.metadata.usesSize;
|
||||
const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes;
|
||||
const width = usesSize ? tokenSizes[actor.system.size] : pt.width;
|
||||
const height = usesSize ? tokenSizes[actor.system.size] : pt.height;
|
||||
|
||||
const w = width * canvas.dimensions.size * Math.abs(pt.texture.scaleX) * canvas.stage.scale.x;
|
||||
const h = height * canvas.dimensions.size * Math.abs(pt.texture.scaleY) * canvas.stage.scale.y;
|
||||
const preview = foundry.applications.ux.DragDrop.implementation.createDragImage(img, w, h);
|
||||
event.dataTransfer.setDragImage(preview, w / 2, h / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,27 +55,28 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
];
|
||||
}
|
||||
|
||||
addChatListeners = async (app, html, data) => {
|
||||
addChatListeners = async (document, html, data) => {
|
||||
const message = data?.message ?? document.toObject(false);
|
||||
html.querySelectorAll('.simple-roll-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollSimple(event, data.message))
|
||||
element.addEventListener('click', event => this.onRollSimple(event, message))
|
||||
);
|
||||
html.querySelectorAll('.ability-use-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.abilityUseButton(event, data.message))
|
||||
element.addEventListener('click', event => this.abilityUseButton(event, message))
|
||||
);
|
||||
html.querySelectorAll('.action-use-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.actionUseButton(event, data.message))
|
||||
element.addEventListener('click', event => this.actionUseButton(event, message))
|
||||
);
|
||||
html.querySelectorAll('.reroll-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.rerollEvent(event, data.message))
|
||||
element.addEventListener('click', event => this.rerollEvent(event, message))
|
||||
);
|
||||
html.querySelectorAll('.group-roll-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.groupRollButton(event, data.message))
|
||||
element.addEventListener('click', event => this.groupRollButton(event, message))
|
||||
);
|
||||
html.querySelectorAll('.group-roll-reroll').forEach(element =>
|
||||
element.addEventListener('click', event => this.groupRollReroll(event, data.message))
|
||||
element.addEventListener('click', event => this.groupRollReroll(event, message))
|
||||
);
|
||||
html.querySelectorAll('.group-roll-success').forEach(element =>
|
||||
element.addEventListener('click', event => this.groupRollSuccessEvent(event, data.message))
|
||||
element.addEventListener('click', event => this.groupRollSuccessEvent(event, message))
|
||||
);
|
||||
html.querySelectorAll('.group-roll-header-expand-section').forEach(element =>
|
||||
element.addEventListener('click', this.groupRollExpandSection)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue