mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-07-24 11:29:54 +02:00
Compare commits
No commits in common. "3dc8379ff5bfb388351baa7fa806fa6bb94bc6e0" and "9eeadba046db52a23bcf882345833d6c8d0eaa16" have entirely different histories.
3dc8379ff5
...
9eeadba046
19 changed files with 138 additions and 166 deletions
|
|
@ -486,13 +486,13 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
const resourceMap = new ResourceUpdateMap(actor);
|
const resourceMap = new ResourceUpdateMap(actor);
|
||||||
if (totalRoll.isCritical) {
|
if (totalRoll.isCritical) {
|
||||||
resourceMap.addResources([
|
resourceMap.addResources([
|
||||||
{ key: 'stress', value: -1 },
|
{ key: 'stress', value: -1, total: 1 },
|
||||||
{ key: 'hope', value: 1 }
|
{ key: 'hope', value: 1, total: 1 }
|
||||||
]);
|
]);
|
||||||
} else if (totalRoll.withHope) {
|
} else if (totalRoll.withHope) {
|
||||||
resourceMap.addResources([{ key: 'hope', value: 1 }]);
|
resourceMap.addResources([{ key: 'hope', value: 1, total: 1 }]);
|
||||||
} else {
|
} else {
|
||||||
resourceMap.addResources([{ key: 'fear', value: 1 }]);
|
resourceMap.addResources([{ key: 'fear', value: 1, total: 1 }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceMap.updateResources();
|
resourceMap.updateResources();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { ResourceUpdateMap } from '../../data/action/baseAction.mjs';
|
|
||||||
import { MemberData } from '../../data/tagTeamData.mjs';
|
import { MemberData } from '../../data/tagTeamData.mjs';
|
||||||
import { getCritDamageBonus, shouldUseHopeFearAutomation } from '../../helpers/utils.mjs';
|
import { getCritDamageBonus, shouldUseHopeFearAutomation } from '../../helpers/utils.mjs';
|
||||||
import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
||||||
|
|
@ -10,7 +9,6 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
constructor(party) {
|
constructor(party) {
|
||||||
super({ id: `TagTeamDialog-${party.id}` });
|
super({ id: `TagTeamDialog-${party.id}` });
|
||||||
|
|
||||||
this.usesTagTeamHopeCost = true;
|
|
||||||
this.party = party;
|
this.party = party;
|
||||||
this.partyMembers = party.system.partyMembers
|
this.partyMembers = party.system.partyMembers
|
||||||
.filter(x => Party.DICE_ROLL_ACTOR_TYPES.includes(x.type))
|
.filter(x => Party.DICE_ROLL_ACTOR_TYPES.includes(x.type))
|
||||||
|
|
@ -22,9 +20,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
owned: member.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
|
owned: member.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.initiator = { cost:
|
this.initiator = { cost: 3 };
|
||||||
this.party.system.schema.fields.tagTeam.fields.initiator.fields.cost.initial
|
|
||||||
};
|
|
||||||
this.openForAllPlayers = true;
|
this.openForAllPlayers = true;
|
||||||
|
|
||||||
this.tabGroups.application = Object.keys(party.system.tagTeam.members).length
|
this.tabGroups.application = Object.keys(party.system.tagTeam.members).length
|
||||||
|
|
@ -98,13 +94,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
?.addEventListener('input', this.updateInitiatorMemberField.bind(this));
|
?.addEventListener('input', this.updateInitiatorMemberField.bind(this));
|
||||||
|
|
||||||
htmlElement
|
htmlElement
|
||||||
.querySelector('.initiator-cost-input')
|
.querySelector('.initiator-cost-field')
|
||||||
?.addEventListener('input', this.updateInitiatorCostField.bind(this));
|
?.addEventListener('input', this.updateInitiatorCostField.bind(this));
|
||||||
|
|
||||||
htmlElement
|
|
||||||
.querySelector('.initiator-cost-enabled-checkbox')
|
|
||||||
?.addEventListener('change', this.toggleInitiatorCostEnabled.bind(this));
|
|
||||||
|
|
||||||
htmlElement
|
htmlElement
|
||||||
.querySelector('.openforall-field')
|
.querySelector('.openforall-field')
|
||||||
?.addEventListener('change', this.updateOpenForAllField.bind(this));
|
?.addEventListener('change', this.updateOpenForAllField.bind(this));
|
||||||
|
|
@ -164,7 +156,6 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
.map(x => ({ value: x.id, label: x.name }));
|
.map(x => ({ value: x.id, label: x.name }));
|
||||||
partContext.initiatorDisabled = !selectedMembers.length;
|
partContext.initiatorDisabled = !selectedMembers.length;
|
||||||
partContext.openForAllPlayers = this.openForAllPlayers;
|
partContext.openForAllPlayers = this.openForAllPlayers;
|
||||||
partContext.usesTagTeamHopeCost = this.usesTagTeamHopeCost;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'tagTeamRoll':
|
case 'tagTeamRoll':
|
||||||
|
|
@ -406,13 +397,6 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleInitiatorCostEnabled(_event) {
|
|
||||||
this.usesTagTeamHopeCost = !this.usesTagTeamHopeCost;
|
|
||||||
this.initiator.cost = this.usesTagTeamHopeCost ?
|
|
||||||
this.party.system.schema.fields.tagTeam.fields.initiator.fields.cost.initial : 0;
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateOpenForAllField(event) {
|
updateOpenForAllField(event) {
|
||||||
this.openForAllPlayers = event.target.checked;
|
this.openForAllPlayers = event.target.checked;
|
||||||
this.render();
|
this.render();
|
||||||
|
|
@ -767,38 +751,35 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
await cls.create(msgData);
|
await cls.create(msgData);
|
||||||
|
|
||||||
/* Handle resource updates from the finished TagTeamRoll */
|
/* Handle resource updates from the finished TagTeamRoll */
|
||||||
const tagTeamData = this.party.system.tagTeam;
|
|
||||||
|
|
||||||
const actorResourceMaps = Object.keys(tagTeamData.members).reduce((acc, key) => {
|
|
||||||
acc[key] = new ResourceUpdateMap(game.actors.get(key));
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
if (shouldUseHopeFearAutomation({ gmAsPlayer: true })) {
|
if (shouldUseHopeFearAutomation({ gmAsPlayer: true })) {
|
||||||
const fearResourceMap = actorResourceMaps[tagTeamData.initiator.memberId];
|
const tagTeamData = this.party.system.tagTeam;
|
||||||
for (const memberId in tagTeamData.members) {
|
const fearUpdate = { key: 'fear', value: null, total: null, enabled: true };
|
||||||
const resourceMap = actorResourceMaps[memberId];
|
for (let memberId in tagTeamData.members) {
|
||||||
if (finalRoll.isCritical) {
|
const resourceUpdates = [];
|
||||||
resourceMap.addResources([
|
const rollGivesHope = finalRoll.isCritical || finalRoll.withHope;
|
||||||
{ key: 'stress', value: -1, enabled: true },
|
if (memberId === tagTeamData.initiator.memberId) {
|
||||||
{ key: 'hope', value: 1, enabled: true }
|
const value = tagTeamData.initiator.cost
|
||||||
]);
|
? rollGivesHope
|
||||||
} else if (finalRoll.withHope) {
|
? 1 - tagTeamData.initiator.cost
|
||||||
resourceMap.addResources([{ key: 'hope', value: 1, enabled: true }]);
|
: -tagTeamData.initiator.cost
|
||||||
} else if (finalRoll.withFear) {
|
: 1;
|
||||||
fearResourceMap.addResources([{ key: 'fear', value: 1, enabled: true }]);
|
resourceUpdates.push({ key: 'hope', value: value, total: -value, enabled: true });
|
||||||
}
|
} else if (rollGivesHope) {
|
||||||
|
resourceUpdates.push({ key: 'hope', value: 1, total: -1, enabled: true });
|
||||||
}
|
}
|
||||||
|
if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true });
|
||||||
|
if (finalRoll.withFear) {
|
||||||
|
fearUpdate.value = fearUpdate.value === null ? 1 : fearUpdate.value + 1;
|
||||||
|
fearUpdate.total = fearUpdate.total === null ? -1 : fearUpdate.total - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Even with Hope/Fear automation off, the hope cost of performing the TagTeamRoll can still optionally be subtracted */
|
game.actors.get(memberId).modifyResource(resourceUpdates);
|
||||||
if (tagTeamData.initiator.cost) {
|
|
||||||
const resourceMap = actorResourceMaps[tagTeamData.initiator.memberId];
|
|
||||||
resourceMap.addResources([{ key: 'hope', value: -tagTeamData.initiator.cost, enabled: true }]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const resourceMap of Object.values(actorResourceMaps))
|
if (fearUpdate.value) {
|
||||||
resourceMap.updateResources();
|
mainActor.modifyResource([fearUpdate]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fin */
|
/* Fin */
|
||||||
this.cancelRoll({ confirm: false });
|
this.cancelRoll({ confirm: false });
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
|
||||||
async _prepareContext(options) {
|
async _prepareContext(options) {
|
||||||
const context = await super._prepareContext(options);
|
const context = await super._prepareContext(options);
|
||||||
|
|
||||||
const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm);
|
const featureForms = ['passive', 'action', 'reaction'];
|
||||||
context.features = context.document.system.features.sort((a, b) =>
|
context.features = context.document.system.features.sort((a, b) =>
|
||||||
a.system.featureForm !== b.system.featureForm
|
a.system.featureForm !== b.system.featureForm
|
||||||
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
|
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
|
||||||
|
|
@ -97,4 +97,32 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
|
||||||
|
|
||||||
await this.actor.update({ [`system.experiences.${target.dataset.experience}`]: _del });
|
await this.actor.update({ [`system.experiences.${target.dataset.experience}`]: _del });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _onDragStart(event) {
|
||||||
|
const featureItem = event.currentTarget.closest('.feature-item');
|
||||||
|
|
||||||
|
if (featureItem) {
|
||||||
|
const feature = this.actor.items.get(featureItem.id);
|
||||||
|
const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true };
|
||||||
|
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
|
||||||
|
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onDrop(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||||
|
|
||||||
|
const item = await fromUuid(data.uuid);
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
|
||||||
dragDrop: [
|
dragDrop: [
|
||||||
{ dragSelector: null, dropSelector: '.category-container' },
|
{ dragSelector: null, dropSelector: '.category-container' },
|
||||||
{ dragSelector: null, dropSelector: '.tab.features' },
|
{ dragSelector: null, dropSelector: '.tab.features' },
|
||||||
{ dragSelector: '.feature-item, .inventory-item[data-type="adversary"]', dropSelector: null }
|
{ dragSelector: '.feature-item', dropSelector: null }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -110,30 +110,33 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDragStart(event) {
|
async _onDragStart(event) {
|
||||||
const element = event.currentTarget.closest('.inventory-item[data-type=adversary]');
|
const featureItem = event.currentTarget.closest('.feature-item');
|
||||||
if (element) {
|
|
||||||
const adversaryData = { type: 'Actor', uuid: element.dataset.itemUuid };
|
if (featureItem) {
|
||||||
event.dataTransfer.setData('text/plain', JSON.stringify(adversaryData));
|
const feature = this.actor.items.get(featureItem.id);
|
||||||
event.dataTransfer.setDragImage(element, 60, 0);
|
const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true };
|
||||||
} else {
|
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
|
||||||
return super._onDragStart(event);
|
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDrop(event) {
|
async _onDrop(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||||
const doc = await fromUuid(data.uuid);
|
const item = await fromUuid(data.uuid);
|
||||||
if (doc?.type === 'adversary' && event.target.closest('.category-container')) {
|
if (data.fromInternal && item?.parent?.uuid === this.actor.uuid) return;
|
||||||
|
|
||||||
|
if (item.type === 'adversary' && event.target.closest('.category-container')) {
|
||||||
const target = event.target.closest('.category-container');
|
const target = event.target.closest('.category-container');
|
||||||
const path = `system.potentialAdversaries.${target.dataset.potentialAdversary}.adversaries`;
|
const path = `system.potentialAdversaries.${target.dataset.potentialAdversary}.adversaries`;
|
||||||
const current = foundry.utils.getProperty(this.actor, path).map(x => x.uuid);
|
const current = foundry.utils.getProperty(this.actor, path).map(x => x.uuid);
|
||||||
if (!current.includes(doc.uuid)) {
|
await this.actor.update({
|
||||||
await this.actor.update({ [path]: [...current, doc.uuid] });
|
[path]: [...current, item.uuid]
|
||||||
}
|
});
|
||||||
return;
|
this.render();
|
||||||
}
|
} else if (item.type === 'feature' && event.target.closest('.tab.features')) {
|
||||||
|
await this.actor.createEmbeddedDocuments('Item', [item]);
|
||||||
return super._onDrop(event);
|
this.render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,4 +52,34 @@ export default class DHNPCSettings extends DHBaseActorSettings {
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
async _onDragStart(event) {
|
||||||
|
const featureItem = event.currentTarget.closest('.feature-item');
|
||||||
|
|
||||||
|
if (featureItem) {
|
||||||
|
const feature = this.actor.items.get(featureItem.id);
|
||||||
|
const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true };
|
||||||
|
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
|
||||||
|
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onDrop(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||||
|
|
||||||
|
const item = await fromUuid(data.uuid);
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
||||||
context.resources.stress.emptyPips =
|
context.resources.stress.emptyPips =
|
||||||
context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0;
|
context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0;
|
||||||
|
|
||||||
const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm);
|
const featureForms = ['passive', 'action', 'reaction'];
|
||||||
context.features = this.document.system.features.sort((a, b) =>
|
context.features = this.document.system.features.sort((a, b) =>
|
||||||
a.system.featureForm !== b.system.featureForm
|
a.system.featureForm !== b.system.featureForm
|
||||||
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
|
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
|
||||||
|
|
|
||||||
|
|
@ -809,7 +809,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
|
|
||||||
/* This could be avoided by baking config.costs into config.resourceUpdates. Didn't feel like messing with it at the time */
|
/* This could be avoided by baking config.costs into config.resourceUpdates. Didn't feel like messing with it at the time */
|
||||||
const costResources =
|
const costResources =
|
||||||
result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value })) ||
|
result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value, total: -cost.total })) ||
|
||||||
{};
|
{};
|
||||||
result.resourceUpdates.addResources(costResources);
|
result.resourceUpdates.addResources(costResources);
|
||||||
await result.resourceUpdates.updateResources();
|
await result.resourceUpdates.updateResources();
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ export default class DhpEnvironment extends DHBaseActorSheet {
|
||||||
switch (partId) {
|
switch (partId) {
|
||||||
case 'header':
|
case 'header':
|
||||||
await this._prepareHeaderContext(context, options);
|
await this._prepareHeaderContext(context, options);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'features':
|
case 'features':
|
||||||
await this._prepareFeaturesContext(context, options);
|
await this._prepareFeaturesContext(context, options);
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,13 @@
|
||||||
import DHApplicationMixin from './application-mixin.mjs';
|
import DHApplicationMixin from './application-mixin.mjs';
|
||||||
const { ActorSheetV2 } = foundry.applications.sheets;
|
const { DocumentSheetV2 } = foundry.applications.api;
|
||||||
|
|
||||||
/**
|
/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */
|
||||||
* @typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base settings sheet for Daggerheart actors.
|
* Base settings sheet for Daggerheart actors.
|
||||||
* @extends {DHApplicationMixin<ActorSheetV2>}
|
* @extends {DHApplicationMixin<DocumentSheetV2>}
|
||||||
*/
|
*/
|
||||||
export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2) {
|
export default class DHBaseActorSettings extends DHApplicationMixin(DocumentSheetV2) {
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
classes: ['dialog'],
|
classes: ['dialog'],
|
||||||
|
|
@ -75,29 +73,4 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDragStart(event) {
|
|
||||||
const featureItemEl = event.currentTarget.closest('.feature-item');
|
|
||||||
const feature = this.actor.items.get(featureItemEl?.dataset.itemId);
|
|
||||||
if (feature && event.target.closest('.tab.features')) {
|
|
||||||
const featureData = { ...feature.toDragData(), fromInternal: true };
|
|
||||||
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
|
|
||||||
event.dataTransfer.setDragImage(featureItemEl.querySelector('img'), 60, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onDrop(event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
|
||||||
const item = await fromUuid(data.uuid);
|
|
||||||
if (item?.type === 'feature') {
|
|
||||||
if (data.fromInternal && item.parent?.uuid === this.actor.uuid) {
|
|
||||||
return super._onDrop(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemData = item.toObject();
|
|
||||||
delete itemData._id;
|
|
||||||
await this.actor.createEmbeddedDocuments('Item', [itemData]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -381,35 +381,12 @@ export default function DHApplicationMixin(Base) {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
_onDrop(event) {
|
_onDrop(event) {
|
||||||
// Potentially handle subclasses that dont descend from actor/item sheet.
|
// Fallback to super, but note that config sheets don't have this option
|
||||||
|
// We still need this to avoid setting apps having issues
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return super._onDrop?.(event);
|
return super._onDrop?.(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
|
||||||
_onSortItem(event, item) {
|
|
||||||
// If we are dragging a feature past its allowed feature form, put it in the front or in the back
|
|
||||||
const doc = this.actor.items.get(item.id);
|
|
||||||
const dropTargetEl = event.target.closest('[data-item-id]');
|
|
||||||
const dropTarget = this.actor.items.get(dropTargetEl?.dataset.itemId);
|
|
||||||
if (doc?.type === 'feature' && dropTarget?.type === 'feature' && doc.system.featureForm !== dropTarget.system.featureForm) {
|
|
||||||
const siblings = this.actor.itemTypes.feature
|
|
||||||
.filter(f => f.system.featureForm === doc.system.featureForm)
|
|
||||||
.sort((a, b) => a.sort - b.sort);
|
|
||||||
if (siblings.length > 1) {
|
|
||||||
const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm);
|
|
||||||
const thisFeatureIdx = featureForms.indexOf(doc.system.featureForm);
|
|
||||||
const targetFeatureIdx = featureForms.indexOf(dropTarget.system.featureForm);
|
|
||||||
const target = targetFeatureIdx < thisFeatureIdx ? siblings[0] : siblings.at(-1);
|
|
||||||
const sortUpdates = foundry.utils.performIntegerSort(doc, { target, siblings });
|
|
||||||
const updateData = sortUpdates.map(u => ({ ...u.update, _id: u.target._id }));
|
|
||||||
return this.actor.updateEmbeddedDocuments('Item', updateData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return super._onSortItem?.(event, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Context Menu */
|
/* Context Menu */
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
|
||||||
|
|
@ -459,7 +459,8 @@ export class ResourceUpdateMap extends Map {
|
||||||
} else if (!existing?.clear) {
|
} else if (!existing?.clear) {
|
||||||
this.set(resource.key, {
|
this.set(resource.key, {
|
||||||
...existing,
|
...existing,
|
||||||
value: existing.value + (resource.value ?? 0)
|
value: existing.value + (resource.value ?? 0),
|
||||||
|
total: existing.total + (resource.total ?? 0)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -315,12 +315,7 @@ export default class DhCharacter extends DhCreature {
|
||||||
label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice'
|
label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}),
|
})
|
||||||
/** Accumulated armor score from all sources */
|
|
||||||
armorScore: new fields.SchemaField({
|
|
||||||
value: new fields.NumberField(),
|
|
||||||
max: new fields.NumberField()
|
|
||||||
}, { persisted: false })
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -332,15 +332,15 @@ export default class DualityRoll extends D20Roll {
|
||||||
const fear =
|
const fear =
|
||||||
(config.roll.result.duality === -1 ? 1 : 0) - (config.rerolledRoll.result.duality === -1 ? 1 : 0);
|
(config.roll.result.duality === -1 ? 1 : 0) - (config.rerolledRoll.result.duality === -1 ? 1 : 0);
|
||||||
|
|
||||||
if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true });
|
if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true });
|
||||||
if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true });
|
if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true });
|
||||||
if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true });
|
if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (config.roll.isCritical || config.roll.result.duality === 1)
|
if (config.roll.isCritical || config.roll.result.duality === 1)
|
||||||
updates.push({ key: 'hope', value: 1, enabled: true });
|
updates.push({ key: 'hope', value: 1, total: -1, enabled: true });
|
||||||
if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, enabled: true });
|
if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, total: 1, enabled: true });
|
||||||
if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, enabled: true });
|
if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, total: -1, enabled: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updates.length) {
|
if (updates.length) {
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ export function updateResourcesForDualityReroll(oldDuality, newDuality, actor) {
|
||||||
const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0);
|
const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0);
|
||||||
const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0);
|
const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0);
|
||||||
|
|
||||||
if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true });
|
if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true });
|
||||||
if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true });
|
if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true });
|
||||||
if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true });
|
if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true });
|
||||||
|
|
||||||
const resourceUpdates = new ResourceUpdateMap(actor);
|
const resourceUpdates = new ResourceUpdateMap(actor);
|
||||||
resourceUpdates.addResources(updates);
|
resourceUpdates.addResources(updates);
|
||||||
|
|
|
||||||
|
|
@ -88,21 +88,9 @@
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
||||||
.inactive {
|
&.inactive {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.initiator-cost-fields {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
.initiator-cost-inputs {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto 1fr;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,10 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="initiator-cost-fields">
|
<div class="form-group">
|
||||||
<label>{{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.FIELDS.initiator.cost.label"}}</label>
|
<label>{{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.FIELDS.initiator.cost.label"}}</label>
|
||||||
<div class="initiator-cost-inputs">
|
<div class="form-fields">
|
||||||
<input type="checkbox" class="initiator-cost-enabled-checkbox {{#if initiatorDisabled}}inactive{{/if}}" {{checked usesTagTeamHopeCost}} {{#if initiatorDisabled}}disabled{{/if}} />
|
<input type="text" data-dtype="Number" value="{{initiator.cost}}" class="initiator-cost-field" {{#if initiatorDisabled}}disabled{{/if}} />
|
||||||
<input
|
|
||||||
type="text" data-dtype="Number" value="{{initiator.cost}}"
|
|
||||||
class="initiator-cost-input {{#if (or initiatorDisabled (not usesTagTeamHopeCost))}}inactive{{/if}}"
|
|
||||||
{{#if (or initiatorDisabled (not usesTagTeamHopeCost))}}disabled{{/if}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<legend>{{localize tabs.features.label}}</legend>
|
<legend>{{localize tabs.features.label}}</legend>
|
||||||
<ul class="feature-list">
|
<ul class="feature-list">
|
||||||
{{#each @root.features as |feature|}}
|
{{#each @root.features as |feature|}}
|
||||||
<li class="feature-item" data-item-id="{{feature.id}}" draggable="true">
|
<li class="feature-item" id="{{feature.id}}" draggable="true">
|
||||||
<img src="{{feature.img}}" alt="">
|
<img src="{{feature.img}}" alt="">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span>{{feature.name}}</span>
|
<span>{{feature.name}}</span>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<legend>{{localize tabs.features.label}}</legend>
|
<legend>{{localize tabs.features.label}}</legend>
|
||||||
<ul class="feature-list">
|
<ul class="feature-list">
|
||||||
{{#each @root.features as |feature|}}
|
{{#each @root.features as |feature|}}
|
||||||
<li class="feature-item" data-item-id="{{feature.id}}">
|
<li class="feature-item" id="{{feature.id}}">
|
||||||
<img src="{{feature.img}}" alt="">
|
<img src="{{feature.img}}" alt="">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span>{{feature.name}}</span>
|
<span>{{feature.name}}</span>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<legend>{{localize tabs.features.label}}</legend>
|
<legend>{{localize tabs.features.label}}</legend>
|
||||||
<ul class="feature-list">
|
<ul class="feature-list">
|
||||||
{{#each @root.features as |feature|}}
|
{{#each @root.features as |feature|}}
|
||||||
<li class="feature-item" data-item-id="{{feature.id}}" draggable="true">
|
<li class="feature-item" id="{{feature.id}}" draggable="true">
|
||||||
<img src="{{feature.img}}" alt="">
|
<img src="{{feature.img}}" alt="">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span>{{feature.name}}</span>
|
<span>{{feature.name}}</span>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue