mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-25 00:43:38 +02:00
Compare commits
No commits in common. "2fde61a1d5aac62d812b7e1e6862c565e952c515" and "7d5cdeb09ddafcfefff618198703b232fa9b4f17" have entirely different histories.
2fde61a1d5
...
7d5cdeb09d
25 changed files with 87 additions and 207 deletions
|
|
@ -213,9 +213,6 @@
|
||||||
"headerTitle": "Adversary Reaction Roll"
|
"headerTitle": "Adversary Reaction Roll"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Base": {
|
|
||||||
"CannotAddType": "Cannot add {itemType} items to {actorType} actors."
|
|
||||||
},
|
|
||||||
"Character": {
|
"Character": {
|
||||||
"advantageSources": {
|
"advantageSources": {
|
||||||
"label": "Advantage Sources",
|
"label": "Advantage Sources",
|
||||||
|
|
@ -2881,10 +2878,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Keybindings": {
|
"Keybindings": {
|
||||||
"partySheet": {
|
|
||||||
"name": "Toggle Party Sheet",
|
|
||||||
"hint": "Open or close the active party's sheet"
|
|
||||||
},
|
|
||||||
"spotlight": {
|
"spotlight": {
|
||||||
"name": "Spotlight Combatant",
|
"name": "Spotlight Combatant",
|
||||||
"hint": "Move the spotlight to a hovered or selected token that's present in an active encounter"
|
"hint": "Move the spotlight to a hovered or selected token that's present in an active encounter"
|
||||||
|
|
|
||||||
|
|
@ -123,10 +123,6 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
context.advantage = this.config.roll?.advantage;
|
context.advantage = this.config.roll?.advantage;
|
||||||
context.disadvantage = this.config.roll?.disadvantage;
|
context.disadvantage = this.config.roll?.disadvantage;
|
||||||
context.diceOptions = CONFIG.DH.GENERAL.diceTypes;
|
context.diceOptions = CONFIG.DH.GENERAL.diceTypes;
|
||||||
context.dieFaces = CONFIG.DH.GENERAL.dieFaces.reduce((acc, face) => {
|
|
||||||
acc[face] = `d${face}`;
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
context.isLite = this.config.roll?.lite;
|
context.isLite = this.config.roll?.lite;
|
||||||
context.extraFormula = this.config.extraFormula;
|
context.extraFormula = this.config.extraFormula;
|
||||||
context.formula = this.roll.constructFormula(this.config);
|
context.formula = this.roll.constructFormula(this.config);
|
||||||
|
|
@ -156,7 +152,9 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
}
|
}
|
||||||
if (this.config.uses) this.config.uses = foundry.utils.mergeObject(this.config.uses, rest.uses);
|
if (this.config.uses) this.config.uses = foundry.utils.mergeObject(this.config.uses, rest.uses);
|
||||||
if (rest.roll?.dice) {
|
if (rest.roll?.dice) {
|
||||||
this.roll = foundry.utils.mergeObject(this.roll, rest.roll.dice);
|
Object.entries(rest.roll.dice).forEach(([key, value]) => {
|
||||||
|
this.roll[key] = value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (rest.hasOwnProperty('trait')) {
|
if (rest.hasOwnProperty('trait')) {
|
||||||
this.config.roll.trait = rest.trait;
|
this.config.roll.trait = rest.trait;
|
||||||
|
|
@ -175,15 +173,6 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
this.disadvantage = advantage === -1;
|
this.disadvantage = advantage === -1;
|
||||||
|
|
||||||
this.config.roll.advantage = this.config.roll.advantage === advantage ? 0 : advantage;
|
this.config.roll.advantage = this.config.roll.advantage === advantage ? 0 : advantage;
|
||||||
|
|
||||||
if (this.config.roll.advantage === 1 && this.config.data.rules.roll.defaultAdvantageDice) {
|
|
||||||
const faces = Number.parseInt(this.config.data.rules.roll.defaultAdvantageDice);
|
|
||||||
this.roll.advantageFaces = Number.isNaN(faces) ? this.roll.advantageFaces : faces;
|
|
||||||
} else if (this.config.roll.advantage === -1 && this.config.data.rules.roll.defaultDisadvantageDice) {
|
|
||||||
const faces = Number.parseInt(this.config.data.rules.roll.defaultDisadvantageDice);
|
|
||||||
this.roll.advantageFaces = Number.isNaN(faces) ? this.roll.advantageFaces : faces;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,15 +38,13 @@ export default class ItemTransferDialog extends HandlebarsApplicationMixin(Appli
|
||||||
originActor ??= item?.actor;
|
originActor ??= item?.actor;
|
||||||
const homebrewKey = CONFIG.DH.SETTINGS.gameSettings.Homebrew;
|
const homebrewKey = CONFIG.DH.SETTINGS.gameSettings.Homebrew;
|
||||||
const currencySetting = game.settings.get(CONFIG.DH.id, homebrewKey).currency?.[currency] ?? null;
|
const currencySetting = game.settings.get(CONFIG.DH.id, homebrewKey).currency?.[currency] ?? null;
|
||||||
const max = item?.system.quantity ?? originActor.system.gold[currency] ?? 0;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
originActor,
|
originActor,
|
||||||
targetActor,
|
targetActor,
|
||||||
itemImage: item?.img,
|
itemImage: item?.img,
|
||||||
currencyIcon: currencySetting?.icon,
|
currencyIcon: currencySetting?.icon,
|
||||||
max,
|
max: item?.system.quantity ?? originActor.system.gold[currency] ?? 0,
|
||||||
initial: targetActor.system.metadata.quantifiable?.includes(item.type) ? max : 1,
|
|
||||||
title: item?.name ?? currencySetting?.label
|
title: item?.name ?? currencySetting?.label
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
||||||
.hideAttribution;
|
.hideAttribution;
|
||||||
|
|
||||||
// Prepare inventory data
|
// Prepare inventory data
|
||||||
if (this.document.system.metadata.hasInventory) {
|
if (['party', 'character'].includes(this.document.type)) {
|
||||||
context.inventory = {
|
context.inventory = {
|
||||||
currencies: {},
|
currencies: {},
|
||||||
weapons: this.document.itemTypes.weapon.sort((a, b) => a.sort - b.sort),
|
weapons: this.document.itemTypes.weapon.sort((a, b) => a.sort - b.sort),
|
||||||
|
|
@ -283,7 +283,11 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
||||||
async _onDropItem(event, item) {
|
async _onDropItem(event, item) {
|
||||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||||
const originActor = item.actor;
|
const originActor = item.actor;
|
||||||
if (!originActor || originActor.uuid === this.document.uuid || !this.document.system.metadata.hasInventory) {
|
if (
|
||||||
|
item.actor?.uuid === this.document.uuid ||
|
||||||
|
!originActor ||
|
||||||
|
!['character', 'party'].includes(this.document.type)
|
||||||
|
) {
|
||||||
return super._onDropItem(event, item);
|
return super._onDropItem(event, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,77 +302,45 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the actual transfer, showing a dialog when doing it
|
if (item.system.metadata.isQuantifiable) {
|
||||||
const availableQuantity = Math.max(1, item.system.quantity);
|
const actorItem = originActor.items.get(data.originId);
|
||||||
const actorItem = originActor.items.get(data.originId) ?? item;
|
const quantityTransfered = await game.system.api.applications.dialogs.ItemTransferDialog.configure({
|
||||||
if (availableQuantity > 1) {
|
|
||||||
const quantityTransferred = await game.system.api.applications.dialogs.ItemTransferDialog.configure({
|
|
||||||
item,
|
item,
|
||||||
targetActor: this.document
|
targetActor: this.document
|
||||||
});
|
});
|
||||||
return this.#transferItem(actorItem, quantityTransferred);
|
|
||||||
} else {
|
|
||||||
return this.#transferItem(actorItem, availableQuantity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (quantityTransfered) {
|
||||||
* Helper to perform the actual transfer of an item to this actor, including stack/unstack logic based on target quantifiability.
|
const existingItem = this.document.items.find(x => itemIsIdentical(x, item));
|
||||||
* Make sure item is the actor item before calling this method or there will be issues
|
if (existingItem) {
|
||||||
*/
|
await existingItem.update({
|
||||||
async #transferItem(item, quantity) {
|
'system.quantity': existingItem.system.quantity + quantityTransfered
|
||||||
const originActor = item.actor;
|
|
||||||
const targetActor = this.document;
|
|
||||||
const allowStacking = targetActor.system.metadata.quantifiable?.includes(item.type);
|
|
||||||
|
|
||||||
const batch = [];
|
|
||||||
|
|
||||||
// First add/update the item to the target actor
|
|
||||||
const existing = allowStacking ? targetActor.items.find(x => itemIsIdentical(x, item)) : null;
|
|
||||||
if (existing) {
|
|
||||||
batch.push({
|
|
||||||
action: 'update',
|
|
||||||
documentName: 'Item',
|
|
||||||
parent: targetActor,
|
|
||||||
updates: [{ '_id': existing.id, 'system.quantity': existing.system.quantity + quantity }]
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const itemsToCreate = [];
|
const createData = item.toObject();
|
||||||
if (allowStacking) {
|
await this.document.createEmbeddedDocuments('Item', [
|
||||||
itemsToCreate.push(foundry.utils.mergeObject(item.toObject(true), { system: { quantity } }));
|
{
|
||||||
} else {
|
...createData,
|
||||||
const createData = new Array(Math.max(1, quantity))
|
system: {
|
||||||
.fill(0)
|
...createData.system,
|
||||||
.map(() => foundry.utils.mergeObject(item.toObject(), { system: { quantity: 1 } }));
|
quantity: quantityTransfered
|
||||||
itemsToCreate.push(...createData);
|
|
||||||
}
|
}
|
||||||
batch.push({
|
}
|
||||||
action: 'create',
|
]);
|
||||||
documentName: 'Item',
|
|
||||||
parent: targetActor,
|
|
||||||
data: itemsToCreate
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the item from the original actor (by either deleting it, or updating its quantity)
|
if (quantityTransfered === actorItem.system.quantity) {
|
||||||
if (quantity >= item.system.quantity) {
|
await originActor.deleteEmbeddedDocuments('Item', [data.originId]);
|
||||||
batch.push({
|
|
||||||
action: 'delete',
|
|
||||||
documentName: 'Item',
|
|
||||||
parent: originActor,
|
|
||||||
ids: [item.id]
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
batch.push({
|
await actorItem.update({
|
||||||
action: 'update',
|
'system.quantity': actorItem.system.quantity - quantityTransfered
|
||||||
documentName: 'Item',
|
|
||||||
parent: originActor,
|
|
||||||
updates: [{ '_id': item.id, 'system.quantity': item.system.quantity - quantity }]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return foundry.documents.modifyBatch(batch);
|
} else {
|
||||||
|
await this.document.createEmbeddedDocuments('Item', [item.toObject()]);
|
||||||
|
await originActor.deleteEmbeddedDocuments('Item', [data.originId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,11 @@ export default class AncestrySheet extends DHHeritageSheet {
|
||||||
if (data.type === 'ActiveEffect') return super._onDrop(event);
|
if (data.type === 'ActiveEffect') return super._onDrop(event);
|
||||||
|
|
||||||
const target = event.target.closest('fieldset.drop-section');
|
const target = event.target.closest('fieldset.drop-section');
|
||||||
if (target) {
|
|
||||||
const typeField =
|
const typeField =
|
||||||
this.document.system[target.dataset.type === 'primary' ? 'primaryFeature' : 'secondaryFeature'];
|
this.document.system[target.dataset.type === 'primary' ? 'primaryFeature' : 'secondaryFeature'];
|
||||||
|
|
||||||
if (!typeField) {
|
if (!typeField) {
|
||||||
super._onDrop(event);
|
super._onDrop(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
export const keybindings = {
|
export const keybindings = {
|
||||||
spotlight: 'DHSpotlight',
|
spotlight: 'DHSpotlight'
|
||||||
partySheet: 'DHPartySheet'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const menu = {
|
export const menu = {
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ export default class DhpAdversary extends DhCreature {
|
||||||
}
|
}
|
||||||
|
|
||||||
isItemValid(source) {
|
isItemValid(source) {
|
||||||
return super.isItemValid(source) || source.type === 'feature';
|
return source.type === 'feature';
|
||||||
}
|
}
|
||||||
|
|
||||||
async _preUpdate(changes, options, user) {
|
async _preUpdate(changes, options, user) {
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,7 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
|
||||||
hasResistances: true,
|
hasResistances: true,
|
||||||
hasAttribution: false,
|
hasAttribution: false,
|
||||||
hasLimitedView: true,
|
hasLimitedView: true,
|
||||||
usesSize: false,
|
usesSize: false
|
||||||
hasInventory: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,11 +168,6 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
isItemValid(source) {
|
|
||||||
const inventoryTypes = ['weapon', 'armor', 'consumable', 'loot'];
|
|
||||||
return this.metadata.hasInventory && inventoryTypes.includes(source.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain a data object used to evaluate any dice rolls associated with this Item Type
|
* Obtain a data object used to evaluate any dice rolls associated with this Item Type
|
||||||
* @param {object} [options] - Options which modify the getRollData method.
|
* @param {object} [options] - Options which modify the getRollData method.
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,7 @@ export default class DhCharacter extends DhCreature {
|
||||||
label: 'TYPES.Actor.character',
|
label: 'TYPES.Actor.character',
|
||||||
type: 'character',
|
type: 'character',
|
||||||
settingSheet: DHCharacterSettings,
|
settingSheet: DHCharacterSettings,
|
||||||
isNPC: false,
|
isNPC: false
|
||||||
hasInventory: true,
|
|
||||||
quantifiable: ["loot", "consumable"]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,23 +284,7 @@ export default class DhCharacter extends DhCreature {
|
||||||
guaranteedCritical: new fields.BooleanField({
|
guaranteedCritical: new fields.BooleanField({
|
||||||
label: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.label',
|
label: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.label',
|
||||||
hint: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.hint'
|
hint: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.hint'
|
||||||
}),
|
})
|
||||||
defaultAdvantageDice: new fields.NumberField({
|
|
||||||
nullable: true,
|
|
||||||
required: true,
|
|
||||||
integer: true,
|
|
||||||
choices: CONFIG.DH.GENERAL.dieFaces,
|
|
||||||
initial: null,
|
|
||||||
label: 'DAGGERHEART.ACTORS.Character.defaultAdvantageDice'
|
|
||||||
}),
|
|
||||||
defaultDisadvantageDice: new fields.NumberField({
|
|
||||||
nullable: true,
|
|
||||||
required: true,
|
|
||||||
integer: true,
|
|
||||||
choices: CONFIG.DH.GENERAL.dieFaces,
|
|
||||||
initial: null,
|
|
||||||
label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice'
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
@ -447,11 +429,6 @@ export default class DhCharacter extends DhCreature {
|
||||||
return attack;
|
return attack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All items are valid on characters */
|
|
||||||
isItemValid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
isItemAvailable(item) {
|
isItemAvailable(item) {
|
||||||
if (!super.isItemAvailable(this)) return false;
|
if (!super.isItemAvailable(this)) return false;
|
||||||
|
|
|
||||||
|
|
@ -61,24 +61,6 @@ export default class DhCompanion extends DhCreature {
|
||||||
initial: false,
|
initial: false,
|
||||||
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.vulnerable'
|
label: 'DAGGERHEART.GENERAL.Rules.conditionImmunities.vulnerable'
|
||||||
})
|
})
|
||||||
}),
|
|
||||||
roll: new fields.SchemaField({
|
|
||||||
defaultAdvantageDice: new fields.NumberField({
|
|
||||||
nullable: true,
|
|
||||||
required: true,
|
|
||||||
integer: true,
|
|
||||||
choices: CONFIG.DH.GENERAL.dieFaces,
|
|
||||||
initial: null,
|
|
||||||
label: 'DAGGERHEART.ACTORS.Character.defaultAdvantageDice'
|
|
||||||
}),
|
|
||||||
defaultDisadvantageDice: new fields.NumberField({
|
|
||||||
nullable: true,
|
|
||||||
required: true,
|
|
||||||
integer: true,
|
|
||||||
choices: CONFIG.DH.GENERAL.dieFaces,
|
|
||||||
initial: null,
|
|
||||||
label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice'
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
attack: new ActionField({
|
attack: new ActionField({
|
||||||
|
|
@ -136,6 +118,10 @@ export default class DhCompanion extends DhCreature {
|
||||||
return this.levelupChoicesLeft > 0;
|
return this.levelupChoicesLeft > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isItemValid() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
prepareBaseData() {
|
prepareBaseData() {
|
||||||
super.prepareBaseData();
|
super.prepareBaseData();
|
||||||
this.attack.roll.bonus = this.partner?.system?.spellcastModifier ?? 0;
|
this.attack.roll.bonus = this.partner?.system?.spellcastModifier ?? 0;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ export default class DhEnvironment extends BaseDataActor {
|
||||||
}
|
}
|
||||||
|
|
||||||
isItemValid(source) {
|
isItemValid(source) {
|
||||||
return super.isItemValid(source) || source.type === 'feature';
|
return source.type === 'feature';
|
||||||
}
|
}
|
||||||
|
|
||||||
_onUpdate(changes, options, userId) {
|
_onUpdate(changes, options, userId) {
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,6 @@ import GroupRollData from '../groupRollData.mjs';
|
||||||
import { GoldField } from '../fields/actorField.mjs';
|
import { GoldField } from '../fields/actorField.mjs';
|
||||||
|
|
||||||
export default class DhParty extends BaseDataActor {
|
export default class DhParty extends BaseDataActor {
|
||||||
/** @inheritdoc */
|
|
||||||
static get metadata() {
|
|
||||||
return foundry.utils.mergeObject(super.metadata, {
|
|
||||||
hasInventory: true,
|
|
||||||
quantifiable: ["weapon", "armor", "loot", "consumable"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
|
|
@ -37,6 +29,10 @@ export default class DhParty extends BaseDataActor {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
isItemValid(source) {
|
||||||
|
return ['weapon', 'armor', 'consumable', 'loot'].includes(source.type);
|
||||||
|
}
|
||||||
|
|
||||||
prepareBaseData() {
|
prepareBaseData() {
|
||||||
super.prepareBaseData();
|
super.prepareBaseData();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
* @property {string} label - A localizable label used on application.
|
* @property {string} label - A localizable label used on application.
|
||||||
* @property {string} type - The system type that this data model represents.
|
* @property {string} type - The system type that this data model represents.
|
||||||
* @property {boolean} hasDescription - Indicates whether items of this type have description field
|
* @property {boolean} hasDescription - Indicates whether items of this type have description field
|
||||||
|
* @property {boolean} isQuantifiable - Indicates whether items of this type have quantity field
|
||||||
* @property {boolean} isInventoryItem- Indicates whether items of this type is a Inventory Item
|
* @property {boolean} isInventoryItem- Indicates whether items of this type is a Inventory Item
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -23,6 +24,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
|
||||||
type: 'base',
|
type: 'base',
|
||||||
hasDescription: false,
|
hasDescription: false,
|
||||||
hasResource: false,
|
hasResource: false,
|
||||||
|
isQuantifiable: false,
|
||||||
isInventoryItem: false,
|
isInventoryItem: false,
|
||||||
hasActions: false,
|
hasActions: false,
|
||||||
hasAttribution: true
|
hasAttribution: true
|
||||||
|
|
@ -81,7 +83,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.metadata.isInventoryItem)
|
if (this.metadata.isQuantifiable)
|
||||||
schema.quantity = new fields.NumberField({ integer: true, initial: 1, min: 0, required: true });
|
schema.quantity = new fields.NumberField({ integer: true, initial: 1, min: 0, required: true });
|
||||||
|
|
||||||
if (this.metadata.hasActions) schema.actions = new ActionsField();
|
if (this.metadata.hasActions) schema.actions = new ActionsField();
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ export default class DHConsumable extends BaseDataItem {
|
||||||
label: 'TYPES.Item.consumable',
|
label: 'TYPES.Item.consumable',
|
||||||
type: 'consumable',
|
type: 'consumable',
|
||||||
hasDescription: true,
|
hasDescription: true,
|
||||||
|
isQuantifiable: true,
|
||||||
isInventoryItem: true,
|
isInventoryItem: true,
|
||||||
hasActions: true
|
hasActions: true
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ export default class DHLoot extends BaseDataItem {
|
||||||
label: 'TYPES.Item.loot',
|
label: 'TYPES.Item.loot',
|
||||||
type: 'loot',
|
type: 'loot',
|
||||||
hasDescription: true,
|
hasDescription: true,
|
||||||
|
isQuantifiable: true,
|
||||||
isInventoryItem: true,
|
isInventoryItem: true,
|
||||||
hasActions: true
|
hasActions: true
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import D20Roll from './d20Roll.mjs';
|
||||||
import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
|
import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
|
||||||
|
|
||||||
export default class DualityRoll extends D20Roll {
|
export default class DualityRoll extends D20Roll {
|
||||||
|
_advantageFaces = 6;
|
||||||
_advantageNumber = 1;
|
_advantageNumber = 1;
|
||||||
_rallyIndex;
|
_rallyIndex;
|
||||||
|
|
||||||
|
|
@ -10,9 +11,6 @@ export default class DualityRoll extends D20Roll {
|
||||||
super(formula, data, options);
|
super(formula, data, options);
|
||||||
this.rallyChoices = this.setRallyChoices();
|
this.rallyChoices = this.setRallyChoices();
|
||||||
this.guaranteedCritical = options.guaranteedCritical;
|
this.guaranteedCritical = options.guaranteedCritical;
|
||||||
|
|
||||||
const advantageFaces = data.rules?.roll?.defaultAdvantageDice ? Number.parseInt(data.rules.roll.defaultAdvantageDice) : 6
|
|
||||||
this.advantageFaces = Number.isNaN(advantageFaces) ? 6 : advantageFaces;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static messageType = 'dualityRoll';
|
static messageType = 'dualityRoll';
|
||||||
|
|
@ -53,6 +51,14 @@ export default class DualityRoll extends D20Roll {
|
||||||
return this.dice[2] instanceof game.system.api.dice.diceTypes.DisadvantageDie ? this.dice[2] : null;
|
return this.dice[2] instanceof game.system.api.dice.diceTypes.DisadvantageDie ? this.dice[2] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get advantageFaces() {
|
||||||
|
return this._advantageFaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
set advantageFaces(faces) {
|
||||||
|
this._advantageFaces = this.getFaces(faces);
|
||||||
|
}
|
||||||
|
|
||||||
get advantageNumber() {
|
get advantageNumber() {
|
||||||
return this._advantageNumber;
|
return this._advantageNumber;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ export default class DhpActor extends Actor {
|
||||||
_onUpdate(changes, options, userId) {
|
_onUpdate(changes, options, userId) {
|
||||||
super._onUpdate(changes, options, userId);
|
super._onUpdate(changes, options, userId);
|
||||||
for (const party of this.parties) {
|
for (const party of this.parties) {
|
||||||
party.render({ parts: ['partyMembers'] });
|
party.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,7 +132,7 @@ export default class DhpActor extends Actor {
|
||||||
_onDelete(options, userId) {
|
_onDelete(options, userId) {
|
||||||
super._onDelete(options, userId);
|
super._onDelete(options, userId);
|
||||||
for (const party of this.parties) {
|
for (const party of this.parties) {
|
||||||
party.render({ parts: ['partyMembers'] });
|
party.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,8 @@ export default class DHItem extends foundry.documents.Item {
|
||||||
static async createDocuments(sources, operation) {
|
static async createDocuments(sources, operation) {
|
||||||
// Ensure that items being created are valid to the actor its being added to
|
// Ensure that items being created are valid to the actor its being added to
|
||||||
const actor = operation.parent;
|
const actor = operation.parent;
|
||||||
const filtered = actor ? sources.filter(s => actor.system.isItemValid(s)) : sources;
|
sources = actor?.system?.isItemValid ? sources.filter(s => actor.system.isItemValid(s)) : sources;
|
||||||
if (actor && filtered.length === 0 && sources.length > 0) {
|
return super.createDocuments(sources, operation);
|
||||||
const itemType = _loc(`TYPES.Item.${sources[0].type}`);
|
|
||||||
const actorType = _loc(`TYPES.Actor.${actor.type}`);
|
|
||||||
ui.notifications.error('DAGGERHEART.ACTORS.Base.CannotAddType', { format: { itemType, actorType } });
|
|
||||||
}
|
|
||||||
return super.createDocuments(filtered, operation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
|
||||||
|
|
@ -52,27 +52,6 @@ export const registerKeyBindings = () => {
|
||||||
reservedModifiers: [],
|
reservedModifiers: [],
|
||||||
precedence: CONST.KEYBINDING_PRECEDENCE.NORMAL
|
precedence: CONST.KEYBINDING_PRECEDENCE.NORMAL
|
||||||
});
|
});
|
||||||
|
|
||||||
game.keybindings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.keybindings.partySheet, {
|
|
||||||
name: _loc('DAGGERHEART.SETTINGS.Keybindings.partySheet.name'),
|
|
||||||
hint: _loc('DAGGERHEART.SETTINGS.Keybindings.partySheet.hint'),
|
|
||||||
editable: [{ key: "KeyP" }],
|
|
||||||
onDown: () => {
|
|
||||||
const controlled = canvas.ready ? canvas.tokens.controlled : [];
|
|
||||||
const selectedParty = controlled.find((c) => c.actor?.type === 'party')?.actor;
|
|
||||||
const party = selectedParty ?? game.actors.party;
|
|
||||||
if (!party) return;
|
|
||||||
|
|
||||||
const sheet = party.sheet;
|
|
||||||
if (!sheet.rendered) {
|
|
||||||
sheet.render(true);
|
|
||||||
} else if (sheet.minimized) {
|
|
||||||
sheet.maximize();
|
|
||||||
} else {
|
|
||||||
sheet.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const registerMenuSettings = () => {
|
const registerMenuSettings = () => {
|
||||||
|
|
|
||||||
|
|
@ -157,8 +157,8 @@
|
||||||
<option value="{{add this 1}}" {{#if (eq @root.roll.advantageNumber (add this 1))}} selected{{/if}}>{{add this 1}}</option>
|
<option value="{{add this 1}}" {{#if (eq @root.roll.advantageNumber (add this 1))}} selected{{/if}}>{{add this 1}}</option>
|
||||||
{{/times}}
|
{{/times}}
|
||||||
</select>
|
</select>
|
||||||
<select name="roll.dice.advantageFaces"{{#unless advantage}} disabled{{/unless}} data-dtype="Number">
|
<select name="roll.dice.advantageFaces"{{#unless advantage}} disabled{{/unless}}>
|
||||||
{{selectOptions dieFaces selected=@root.roll.advantageFaces}}
|
{{selectOptions diceOptions selected=(concat 'd' @root.roll.advantageFaces)}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{{#if abilities}}
|
{{#if abilities}}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{localize "DAGGERHEART.GENERAL.quantity"}}</label>
|
<label>{{localize "DAGGERHEART.GENERAL.quantity"}}</label>
|
||||||
<div class="form-fields">
|
<div class="form-fields">
|
||||||
<range-picker step="1" min="1" max="{{max}}" name="quantity" value="{{initial}}"></range-picker>
|
<range-picker step="1" min="1" max="{{max}}" name="quantity" value="{{max}}"></range-picker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@
|
||||||
collection=@root.inventory.consumables
|
collection=@root.inventory.consumables
|
||||||
isGlassy=true
|
isGlassy=true
|
||||||
canCreate=true
|
canCreate=true
|
||||||
isQuantifiable=true
|
|
||||||
}}
|
}}
|
||||||
{{> 'daggerheart.inventory-items'
|
{{> 'daggerheart.inventory-items'
|
||||||
title='TYPES.Item.loot'
|
title='TYPES.Item.loot'
|
||||||
|
|
@ -48,7 +47,6 @@
|
||||||
isGlassy=true
|
isGlassy=true
|
||||||
canCreate=true
|
canCreate=true
|
||||||
showActions=true
|
showActions=true
|
||||||
isQuantifiable=true
|
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
canCreate=true
|
canCreate=true
|
||||||
hideResources=true
|
hideResources=true
|
||||||
hideContextMenu=true
|
hideContextMenu=true
|
||||||
isQuantifiable=true
|
|
||||||
}}
|
}}
|
||||||
{{> 'daggerheart.inventory-items'
|
{{> 'daggerheart.inventory-items'
|
||||||
title='TYPES.Item.armor'
|
title='TYPES.Item.armor'
|
||||||
|
|
@ -40,7 +39,6 @@
|
||||||
canCreate=true
|
canCreate=true
|
||||||
hideResources=true
|
hideResources=true
|
||||||
hideContextMenu=true
|
hideContextMenu=true
|
||||||
isQuantifiable=true
|
|
||||||
}}
|
}}
|
||||||
{{> 'daggerheart.inventory-items'
|
{{> 'daggerheart.inventory-items'
|
||||||
title='TYPES.Item.consumable'
|
title='TYPES.Item.consumable'
|
||||||
|
|
@ -50,7 +48,6 @@
|
||||||
isGlassy=true
|
isGlassy=true
|
||||||
canCreate=true
|
canCreate=true
|
||||||
hideContextMenu=true
|
hideContextMenu=true
|
||||||
isQuantifiable=true
|
|
||||||
}}
|
}}
|
||||||
{{> 'daggerheart.inventory-items'
|
{{> 'daggerheart.inventory-items'
|
||||||
title='TYPES.Item.loot'
|
title='TYPES.Item.loot'
|
||||||
|
|
@ -60,7 +57,6 @@
|
||||||
isGlassy=true
|
isGlassy=true
|
||||||
canCreate=true
|
canCreate=true
|
||||||
hideContextMenu=true
|
hideContextMenu=true
|
||||||
isQuantifiable=true
|
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -66,7 +66,6 @@ Parameters:
|
||||||
showLabels=../showLabels
|
showLabels=../showLabels
|
||||||
isAction=../isAction
|
isAction=../isAction
|
||||||
hideResources=../hideResources
|
hideResources=../hideResources
|
||||||
isQuantifiable=../isQuantifiable
|
|
||||||
showActions=../showActions
|
showActions=../showActions
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ Parameters:
|
||||||
{{#if (and (not hideResources) (not (eq item.system.resource.type 'diceValue')))}}
|
{{#if (and (not hideResources) (not (eq item.system.resource.type 'diceValue')))}}
|
||||||
{{> "systems/daggerheart/templates/sheets/global/partials/item-resource.hbs"}}
|
{{> "systems/daggerheart/templates/sheets/global/partials/item-resource.hbs"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (or isQuantifiable (or (eq item.system.quantity 0) (gt item.system.quantity 1)))}}
|
{{#if (and (not hideResources) (gte item.system.quantity 0))}}
|
||||||
<div class="item-resource">
|
<div class="item-resource">
|
||||||
<input type="number" id="{{item.uuid}}-quantity" class="inventory-item-quantity" value="{{item.system.quantity}}" min="0" />
|
<input type="number" id="{{item.uuid}}-quantity" class="inventory-item-quantity" value="{{item.system.quantity}}" min="0" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue