mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-17 15:39:02 +01:00
Merged with main
This commit is contained in:
commit
51ba94c83a
25 changed files with 398 additions and 159 deletions
42
lang/en.json
42
lang/en.json
|
|
@ -260,8 +260,9 @@
|
|||
"title": "{actor} - Death Move"
|
||||
},
|
||||
"Downtime": {
|
||||
"downtimeHeader": "Downtime Moves ({current}/{max})",
|
||||
"longRest": {
|
||||
"title": "Long Rest",
|
||||
"moves": "Long Rest Moves ({current}/{max})",
|
||||
"clearStress": {
|
||||
"description": "Describe how you blow off steam or pull yourself together, and clear all marked Stress.",
|
||||
"name": "Clear Stress"
|
||||
|
|
@ -278,7 +279,6 @@
|
|||
"description": "Describe how you patch yourself up and remove all marked Hit Points. You may also do this on an ally instead.",
|
||||
"name": "Tend to Wounds"
|
||||
},
|
||||
"title": "Long Rest",
|
||||
"workOnAProject": {
|
||||
"description": "Establish or continue work on a project.",
|
||||
"name": "Work on a Project"
|
||||
|
|
@ -286,6 +286,7 @@
|
|||
},
|
||||
"shortRest": {
|
||||
"title": "Short Rest",
|
||||
"moves": "Short Rest Moves ({current}/{max})",
|
||||
"tendToWounds": {
|
||||
"name": "Tend to Wounds",
|
||||
"description": "Describe how you hastily patch yourself up, then clear a number of Hit Points equal to 1d4 + your tier. You can do this to an ally instead."
|
||||
|
|
@ -302,7 +303,8 @@
|
|||
"name": "Prepare",
|
||||
"description": "Describe how you prepare yourself for the path ahead, then gain a Hope. If you choose to Prepare with one or more members of your party, you each gain 2 Hope."
|
||||
}
|
||||
}
|
||||
},
|
||||
"takeDowntime": "Take Downtime"
|
||||
},
|
||||
"HUD": {
|
||||
"tokenHUD": {
|
||||
|
|
@ -791,7 +793,7 @@
|
|||
"WeaponFeature": {
|
||||
"barrier": {
|
||||
"name": "Barrier",
|
||||
"description": "+{armorScore} to Armor Score; -1 to Evasion"
|
||||
"description": "Gain your character's Tier + 1 to Armor Score; -1 to Evasion"
|
||||
},
|
||||
"bonded": {
|
||||
"name": "Bonded",
|
||||
|
|
@ -907,7 +909,7 @@
|
|||
},
|
||||
"paired": {
|
||||
"name": "Paired",
|
||||
"description": "+{bonusDamage} to primary weapon damage to targets within Melee range"
|
||||
"description": "Add your character's Tier + 1 to primary weapon damage against targets within Melee range"
|
||||
},
|
||||
"parry": {
|
||||
"name": "Parry",
|
||||
|
|
@ -927,7 +929,7 @@
|
|||
},
|
||||
"protective": {
|
||||
"name": "Protective",
|
||||
"description": "+{tier} to Armor Score"
|
||||
"description": "Add your character's Tier to your Armor Score"
|
||||
},
|
||||
"quick": {
|
||||
"name": "Quick",
|
||||
|
|
@ -976,10 +978,6 @@
|
|||
"timebending": {
|
||||
"name": "Timebending",
|
||||
"description": "You can choose the target of your attack after making your attack roll."
|
||||
},
|
||||
"versatile": {
|
||||
"name": "Versatile",
|
||||
"description": "This weapon can also be used with these statistics—{characterTrait}, {range}, {damage}."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -1029,6 +1027,30 @@
|
|||
"singular": "Adversary",
|
||||
"plural": "Adversaries"
|
||||
},
|
||||
"Bonuses": {
|
||||
"rest": {
|
||||
"shortRest": {
|
||||
"shortRestMoves": {
|
||||
"label": "Short Rest: Bonus Short Rest Moves",
|
||||
"hint": "The number of extra Short Rest Moves the character can take during a Short Rest."
|
||||
},
|
||||
"longRestMoves": {
|
||||
"label": "Short Rest: Bonus Long Rest Moves",
|
||||
"hint": "The number of extra Long Rest Moves the character can take during a Short Rest."
|
||||
}
|
||||
},
|
||||
"longRest": {
|
||||
"shortRestMoves": {
|
||||
"label": "Long Rest: Bonus Short Rest Moves",
|
||||
"hint": "The number of extra Short Rest Moves the character can take during a Long Rest."
|
||||
},
|
||||
"longRestMoves": {
|
||||
"label": "Long Rest: Bonus Long Rest Moves",
|
||||
"hint": "The number of extra Long Rest Moves the character can take during a Long Rest."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Character": {
|
||||
"singular": "Character",
|
||||
"plural": "Characters"
|
||||
|
|
|
|||
|
|
@ -7,8 +7,22 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
|||
this.actor = actor;
|
||||
this.shortrest = shortrest;
|
||||
|
||||
const options = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves;
|
||||
this.moveData = shortrest ? options.shortRest : options.longRest;
|
||||
this.moveData = foundry.utils.deepClone(
|
||||
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves
|
||||
);
|
||||
this.nrChoices = {
|
||||
shortRest: {
|
||||
max:
|
||||
(shortrest ? this.moveData.shortRest.nrChoices : 0) +
|
||||
actor.system.bonuses.rest[`${shortrest ? 'short' : 'long'}Rest`].shortMoves
|
||||
},
|
||||
longRest: {
|
||||
max:
|
||||
(!shortrest ? this.moveData.longRest.nrChoices : 0) +
|
||||
actor.system.bonuses.rest[`${shortrest ? 'short' : 'long'}Rest`].longMoves
|
||||
}
|
||||
};
|
||||
this.nrChoices.total = { max: this.nrChoices.shortRest.max + this.nrChoices.longRest.max };
|
||||
}
|
||||
|
||||
get title() {
|
||||
|
|
@ -17,8 +31,8 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
|||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'views', 'downtime'],
|
||||
position: { width: 680, height: 'auto' },
|
||||
classes: ['daggerheart', 'views', 'dh-style', 'dialog', 'downtime'],
|
||||
position: { width: 'auto', height: 'auto' },
|
||||
actions: {
|
||||
selectMove: this.selectMove,
|
||||
takeDowntime: this.takeDowntime
|
||||
|
|
@ -29,7 +43,7 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
|||
static PARTS = {
|
||||
application: {
|
||||
id: 'downtime',
|
||||
template: 'systems/daggerheart/templates/dialogs/downtime.hbs'
|
||||
template: 'systems/daggerheart/templates/dialogs/downtime/downtime.hbs'
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -37,46 +51,83 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
|||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
htmlElement
|
||||
.querySelectorAll('.activity-image')
|
||||
.querySelectorAll('.activity-container')
|
||||
.forEach(element => element.addEventListener('contextmenu', this.deselectMove.bind(this)));
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.title = game.i18n.localize(
|
||||
`DAGGERHEART.APPLICATIONS.Downtime.${this.shortrest ? 'shortRest' : 'longRest'}.title`
|
||||
);
|
||||
context.selectedActivity = this.selectedActivity;
|
||||
context.moveData = this.moveData;
|
||||
context.nrCurrentChoices = Object.values(this.moveData.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0);
|
||||
context.disabledDowntime = context.nrCurrentChoices < context.moveData.nrChoices;
|
||||
context.nrCurrentChoices = Object.values(this.moveData).reduce((acc, category) => {
|
||||
acc += Object.values(category.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0);
|
||||
return acc;
|
||||
}, 0);
|
||||
|
||||
context.nrChoices = {
|
||||
...this.nrChoices,
|
||||
shortRest: {
|
||||
...this.nrChoices.shortRest,
|
||||
current: Object.values(this.moveData.shortRest.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0)
|
||||
},
|
||||
longRest: {
|
||||
...this.nrChoices.longRest,
|
||||
current: Object.values(this.moveData.longRest.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0)
|
||||
}
|
||||
};
|
||||
context.nrChoices.total = {
|
||||
...this.nrChoices.total,
|
||||
current: context.nrChoices.shortRest.current + context.nrChoices.longRest.current
|
||||
};
|
||||
|
||||
context.shortRestMoves = this.nrChoices.shortRest.max > 0 ? this.moveData.shortRest : null;
|
||||
context.longRestMoves = this.nrChoices.longRest.max > 0 ? this.moveData.longRest : null;
|
||||
|
||||
context.disabledDowntime = context.nrChoices.total.current < context.nrChoices.total.max;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static selectMove(_, button) {
|
||||
const nrSelected = Object.values(this.moveData.moves).reduce((acc, x) => acc + (x.selected ?? 0), 0);
|
||||
if (nrSelected === this.moveData.nrChoices) {
|
||||
static selectMove(_, target) {
|
||||
const nrSelected = Object.values(this.moveData[target.dataset.category].moves).reduce(
|
||||
(acc, x) => acc + (x.selected ?? 0),
|
||||
0
|
||||
);
|
||||
|
||||
if (nrSelected === this.nrChoices[target.dataset.category].max) {
|
||||
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.noMoreMoves'));
|
||||
return;
|
||||
}
|
||||
|
||||
const move = button.dataset.move;
|
||||
this.moveData.moves[move].selected = this.moveData.moves[move].selected
|
||||
? this.moveData.moves[move].selected + 1
|
||||
const move = target.dataset.move;
|
||||
this.moveData[target.dataset.category].moves[move].selected = this.moveData[target.dataset.category].moves[move]
|
||||
.selected
|
||||
? this.moveData[target.dataset.category].moves[move].selected + 1
|
||||
: 1;
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
deselectMove(event) {
|
||||
const move = event.currentTarget.dataset.move;
|
||||
this.moveData.moves[move].selected = this.moveData.moves[move].selected
|
||||
? this.moveData.moves[move].selected - 1
|
||||
const button = event.target.closest('.activity-container');
|
||||
const move = button.dataset.move;
|
||||
this.moveData[button.dataset.category].moves[move].selected = this.moveData[button.dataset.category].moves[move]
|
||||
.selected
|
||||
? this.moveData[button.dataset.category].moves[move].selected - 1
|
||||
: 0;
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async takeDowntime() {
|
||||
const moves = Object.values(this.moveData.moves).filter(x => x.selected);
|
||||
const moves = Object.values(this.moveData).flatMap(category => {
|
||||
return Object.values(category.moves)
|
||||
.filter(x => x.selected)
|
||||
.flatMap(move => [...Array(move.selected).keys()].map(_ => move));
|
||||
});
|
||||
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const msg = new cls({
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@ import DHActionConfig from '../../sheets-configs/action-config.mjs';
|
|||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
export default class DhSettingsActionView extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
constructor(resolve, reject, title, name, img, description, actions) {
|
||||
constructor(resolve, reject, title, name, icon, img, description, actions) {
|
||||
super({});
|
||||
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
this.viewTitle = title;
|
||||
this.name = name;
|
||||
this.icon = icon;
|
||||
this.img = img;
|
||||
this.description = description;
|
||||
this.actions = actions;
|
||||
|
|
@ -23,7 +24,7 @@ export default class DhSettingsActionView extends HandlebarsApplicationMixin(App
|
|||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'setting', 'dh-style'],
|
||||
position: { width: '400', height: 'auto' },
|
||||
position: { width: 440, height: 'auto' },
|
||||
actions: {
|
||||
editImage: this.onEditImage,
|
||||
addItem: this.addItem,
|
||||
|
|
@ -46,6 +47,7 @@ export default class DhSettingsActionView extends HandlebarsApplicationMixin(App
|
|||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.name = this.name;
|
||||
context.icon = this.icon;
|
||||
context.img = this.img;
|
||||
context.description = this.description;
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.enrichHTML(context.description);
|
||||
|
|
@ -55,8 +57,9 @@ export default class DhSettingsActionView extends HandlebarsApplicationMixin(App
|
|||
}
|
||||
|
||||
static async updateData(event, element, formData) {
|
||||
const { name, img, description } = foundry.utils.expandObject(formData.object);
|
||||
const { name, icon, description } = foundry.utils.expandObject(formData.object);
|
||||
this.name = name;
|
||||
this.icon = icon;
|
||||
this.description = description;
|
||||
|
||||
this.render();
|
||||
|
|
@ -65,6 +68,7 @@ export default class DhSettingsActionView extends HandlebarsApplicationMixin(App
|
|||
static async saveForm(event) {
|
||||
this.resolve({
|
||||
name: this.name,
|
||||
icon: this.icon,
|
||||
img: this.img,
|
||||
description: this.description,
|
||||
actions: this.actions
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
reject,
|
||||
game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.downtimeMoves'),
|
||||
move.name,
|
||||
move.icon,
|
||||
move.img,
|
||||
move.description,
|
||||
move.actions
|
||||
|
|
@ -87,6 +88,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
|||
await this.settings.updateSource({
|
||||
[`restMoves.${type}.moves.${id}`]: {
|
||||
name: data.name,
|
||||
icon: data.icon,
|
||||
img: data.img,
|
||||
description: data.description
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,9 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac
|
|||
element.value = `system.${item.value}`;
|
||||
},
|
||||
click: e => e.fetch(),
|
||||
customize: function (_input, _inputRect, container) {
|
||||
container.style.zIndex = foundry.applications.api.ApplicationV2._maxZ;
|
||||
},
|
||||
minLength: 0
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
useAction: this.useAction,
|
||||
toggleResourceDice: this.toggleResourceDice,
|
||||
handleResourceDice: this.handleResourceDice,
|
||||
toChat: this.toChat
|
||||
toChat: this.toChat,
|
||||
useDowntime: this.useDowntime
|
||||
},
|
||||
window: {
|
||||
resizable: true
|
||||
|
|
@ -752,6 +753,12 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
}
|
||||
}
|
||||
|
||||
static useDowntime(_, button) {
|
||||
new game.system.api.applications.dialogs.Downtime(this.document, button.dataset.type === 'shortRest').render(
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
async _onDragStart(event) {
|
||||
const item = this.getItem(event);
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ export const defaultRestOptions = {
|
|||
tendToWounds: {
|
||||
id: 'tendToWounds',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.tendToWounds.name'),
|
||||
icon: 'fa-solid fa-bandage',
|
||||
img: 'icons/magic/life/cross-worn-green.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.tendToWounds.description'),
|
||||
actions: [
|
||||
|
|
@ -153,6 +154,7 @@ export const defaultRestOptions = {
|
|||
clearStress: {
|
||||
id: 'clearStress',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.clearStress.name'),
|
||||
icon: 'fa-regular fa-face-surprise',
|
||||
img: 'icons/magic/perception/eye-ringed-green.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.clearStress.description'),
|
||||
actions: [
|
||||
|
|
@ -176,6 +178,7 @@ export const defaultRestOptions = {
|
|||
repairArmor: {
|
||||
id: 'repairArmor',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.repairArmor.name'),
|
||||
icon: 'fa-solid fa-hammer',
|
||||
img: 'icons/skills/trades/smithing-anvil-silver-red.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.repairArmor.description'),
|
||||
actions: []
|
||||
|
|
@ -183,6 +186,7 @@ export const defaultRestOptions = {
|
|||
prepare: {
|
||||
id: 'prepare',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.name'),
|
||||
icon: 'fa-solid fa-dumbbell',
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.shortRest.prepare.description'),
|
||||
actions: []
|
||||
|
|
@ -192,6 +196,7 @@ export const defaultRestOptions = {
|
|||
tendToWounds: {
|
||||
id: 'tendToWounds',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.tendToWounds.name'),
|
||||
icon: 'fa-solid fa-bandage',
|
||||
img: 'icons/magic/life/cross-worn-green.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.tendToWounds.description'),
|
||||
actions: []
|
||||
|
|
@ -199,6 +204,7 @@ export const defaultRestOptions = {
|
|||
clearStress: {
|
||||
id: 'clearStress',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.clearStress.name'),
|
||||
icon: 'fa-regular fa-face-surprise',
|
||||
img: 'icons/magic/perception/eye-ringed-green.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.clearStress.description'),
|
||||
actions: []
|
||||
|
|
@ -206,6 +212,7 @@ export const defaultRestOptions = {
|
|||
repairArmor: {
|
||||
id: 'repairArmor',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.repairArmor.name'),
|
||||
icon: 'fa-solid fa-hammer',
|
||||
img: 'icons/skills/trades/smithing-anvil-silver-red.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.repairArmor.description'),
|
||||
actions: []
|
||||
|
|
@ -213,6 +220,7 @@ export const defaultRestOptions = {
|
|||
prepare: {
|
||||
id: 'prepare',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.name'),
|
||||
icon: 'fa-solid fa-dumbbell',
|
||||
img: 'icons/skills/trades/academics-merchant-scribe.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.prepare.description'),
|
||||
actions: []
|
||||
|
|
@ -220,19 +228,12 @@ export const defaultRestOptions = {
|
|||
workOnAProject: {
|
||||
id: 'workOnAProject',
|
||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.workOnAProject.name'),
|
||||
icon: 'fa-solid fa-diagram-project',
|
||||
img: 'icons/skills/social/thumbsup-approval-like.webp',
|
||||
description: game.i18n.localize('DAGGERHEART.APPLICATIONS.Downtime.longRest.workOnAProject.description'),
|
||||
actions: []
|
||||
}
|
||||
}),
|
||||
custom: {
|
||||
id: 'customActivity',
|
||||
name: '',
|
||||
img: 'icons/skills/trades/academics-investigation-puzzles.webp',
|
||||
description: '',
|
||||
namePlaceholder: 'DAGGERHEART.APPLICATIONS.Downtime.custom.namePlaceholder',
|
||||
placeholder: 'DAGGERHEART.APPLICATIONS.Downtime.custom.placeholder'
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
export const deathMoves = {
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ export const weaponFeatures = {
|
|||
{
|
||||
key: 'system.bonuses.damage.primaryWeapon.bonus',
|
||||
mode: 2,
|
||||
value: '@system.levelData.levels.current'
|
||||
value: '@system.levelData.level.current'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1261,15 +1261,6 @@ export const weaponFeatures = {
|
|||
timebending: {
|
||||
label: 'DAGGERHEART.CONFIG.WeaponFeature.timebending.name',
|
||||
description: 'DAGGERHEART.CONFIG.WeaponFeature.timebending.description'
|
||||
},
|
||||
versatile: {
|
||||
label: 'DAGGERHEART.CONFIG.WeaponFeature.versatile.name',
|
||||
description: 'DAGGERHEART.CONFIG.WeaponFeature.versatile.description'
|
||||
// versatile: {
|
||||
// characterTrait: '',
|
||||
// range: '',
|
||||
// damage: ''
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -164,6 +164,44 @@ export default class DhCharacter extends BaseDataActor {
|
|||
}),
|
||||
rally: new fields.ArrayField(new fields.StringField(), {
|
||||
label: 'DAGGERHEART.CLASS.Feature.rallyDice'
|
||||
}),
|
||||
rest: new fields.SchemaField({
|
||||
shortRest: new fields.SchemaField({
|
||||
shortMoves: new fields.NumberField({
|
||||
required: true,
|
||||
integer: true,
|
||||
min: 0,
|
||||
initial: 0,
|
||||
label: 'DAGGERHEART.GENERAL.Bonuses.rest.shortRest.shortRestMoves.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Bonuses.rest.shortRest.shortRestMoves.hint'
|
||||
}),
|
||||
longMoves: new fields.NumberField({
|
||||
required: true,
|
||||
integer: true,
|
||||
min: 0,
|
||||
initial: 0,
|
||||
label: 'DAGGERHEART.GENERAL.Bonuses.rest.shortRest.longRestMoves.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Bonuses.rest.shortRest.longRestMoves.hint'
|
||||
})
|
||||
}),
|
||||
longRest: new fields.SchemaField({
|
||||
shortMoves: new fields.NumberField({
|
||||
required: true,
|
||||
integer: true,
|
||||
min: 0,
|
||||
initial: 0,
|
||||
label: 'DAGGERHEART.GENERAL.Bonuses.rest.longRest.shortRestMoves.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Bonuses.rest.longRest.shortRestMoves.hint'
|
||||
}),
|
||||
longMoves: new fields.NumberField({
|
||||
required: true,
|
||||
integer: true,
|
||||
min: 0,
|
||||
initial: 0,
|
||||
label: 'DAGGERHEART.GENERAL.Bonuses.rest.longRest.longRestMoves.label',
|
||||
hint: 'DAGGERHEART.GENERAL.Bonuses.rest.longRest.longRestMoves.hint'
|
||||
})
|
||||
})
|
||||
})
|
||||
}),
|
||||
companion: new ForeignDocumentUUIDField({ type: 'Actor', nullable: true, initial: null }),
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
|
|||
moves: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField({ required: true }),
|
||||
icon: new fields.StringField({ required: true }),
|
||||
img: new fields.FilePathField({
|
||||
initial: 'icons/magic/life/cross-worn-green.webp',
|
||||
categories: ['IMAGE'],
|
||||
|
|
@ -70,6 +71,7 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
|
|||
moves: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField({ required: true }),
|
||||
icon: new fields.StringField({ required: true }),
|
||||
img: new fields.FilePathField({
|
||||
initial: 'icons/magic/life/cross-worn-green.webp',
|
||||
categories: ['IMAGE'],
|
||||
|
|
|
|||
|
|
@ -55,10 +55,24 @@ export default class DhActiveEffect extends ActiveEffect {
|
|||
}
|
||||
|
||||
static applyField(model, change, field) {
|
||||
change.value = itemAbleRollParse(change.value, model, change.effect.parent);
|
||||
change.value = this.effectSafeEval(itemAbleRollParse(change.value, model, change.effect.parent));
|
||||
super.applyField(model, change, field);
|
||||
}
|
||||
|
||||
/* Altered Foundry safeEval to allow non-numeric returns */
|
||||
static effectSafeEval(expression) {
|
||||
let result;
|
||||
try {
|
||||
// eslint-disable-next-line no-new-func
|
||||
const evl = new Function('sandbox', `with (sandbox) { return ${expression}}`);
|
||||
result = evl(Roll.MATH_PROXY);
|
||||
} catch (err) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async toChat(origin) {
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const systemData = {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,28 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
|
|||
options.direction = this._determineItemTooltipDirection(element);
|
||||
}
|
||||
} else {
|
||||
const shortRest = element.dataset.tooltip?.startsWith('#shortRest#');
|
||||
const longRest = element.dataset.tooltip?.startsWith('#longRest#');
|
||||
if (shortRest || longRest) {
|
||||
const key = element.dataset.tooltip.slice(shortRest ? 11 : 10);
|
||||
const downtimeOptions = shortRest
|
||||
? CONFIG.DH.GENERAL.defaultRestOptions.shortRest()
|
||||
: CONFIG.DH.GENERAL.defaultRestOptions.longRest();
|
||||
const move = downtimeOptions[key];
|
||||
html = await foundry.applications.handlebars.renderTemplate(
|
||||
`systems/daggerheart/templates/ui/tooltip/downtime.hbs`,
|
||||
{
|
||||
move: move
|
||||
}
|
||||
);
|
||||
|
||||
this.tooltip.innerHTML = html;
|
||||
options.direction = this._determineItemTooltipDirection(
|
||||
element,
|
||||
this.constructor.TOOLTIP_DIRECTIONS.UP
|
||||
);
|
||||
}
|
||||
|
||||
const isAdvantage = element.dataset.tooltip?.startsWith('#advantage#');
|
||||
const isDisadvantage = element.dataset.tooltip?.startsWith('#disadvantage#');
|
||||
if (isAdvantage || isDisadvantage) {
|
||||
|
|
@ -44,9 +66,34 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
|
|||
super.activate(element, { ...options, html: html });
|
||||
}
|
||||
|
||||
_determineItemTooltipDirection(element) {
|
||||
_determineItemTooltipDirection(element, prefered = this.constructor.TOOLTIP_DIRECTIONS.LEFT) {
|
||||
const pos = element.getBoundingClientRect();
|
||||
const dirs = this.constructor.TOOLTIP_DIRECTIONS;
|
||||
return dirs[pos.x - this.tooltip.offsetWidth < 0 ? 'DOWN' : 'LEFT'];
|
||||
switch (prefered) {
|
||||
case this.constructor.TOOLTIP_DIRECTIONS.LEFT:
|
||||
return dirs[
|
||||
pos.x - this.tooltip.offsetWidth < 0
|
||||
? this.constructor.TOOLTIP_DIRECTIONS.DOWN
|
||||
: this.constructor.TOOLTIP_DIRECTIONS.LEFT
|
||||
];
|
||||
case this.constructor.TOOLTIP_DIRECTIONS.UP:
|
||||
return dirs[
|
||||
pos.y - this.tooltip.offsetHeight < 0
|
||||
? this.constructor.TOOLTIP_DIRECTIONS.RIGHT
|
||||
: this.constructor.TOOLTIP_DIRECTIONS.UP
|
||||
];
|
||||
case this.constructor.TOOLTIP_DIRECTIONS.RIGHT:
|
||||
return dirs[
|
||||
pos.x + this.tooltip.offsetWidth > document.body.clientWidth
|
||||
? this.constructor.TOOLTIP_DIRECTIONS.DOWN
|
||||
: this.constructor.TOOLTIP_DIRECTIONS.RIGHT
|
||||
];
|
||||
case this.constructor.TOOLTIP_DIRECTIONS.DOWN:
|
||||
return dirs[
|
||||
pos.y + this.tooltip.offsetHeight > document.body.clientHeight
|
||||
? this.constructor.TOOLTIP_DIRECTIONS.LEFT
|
||||
: this.constructor.TOOLTIP_DIRECTIONS.DOWN
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export const preloadHandlebarsTemplates = async function () {
|
|||
'systems/daggerheart/templates/settings/components/settings-item-line.hbs',
|
||||
'systems/daggerheart/templates/ui/chat/parts/damage-chat.hbs',
|
||||
'systems/daggerheart/templates/ui/chat/parts/target-chat.hbs',
|
||||
'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs'
|
||||
'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs',
|
||||
'systems/daggerheart/templates/dialogs/downtime/activities.hbs'
|
||||
]);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,81 +1,75 @@
|
|||
@import '../../utils/spacing.less';
|
||||
@import '../../utils/colors.less';
|
||||
|
||||
.daggerheart.views {
|
||||
.theme-light .daggerheart.dh-style.views.downtime {
|
||||
.downtime-container .activity-container .activity-selected-marker {
|
||||
background-image: url(../assets/parchments/dh-parchment-light.png);
|
||||
}
|
||||
}
|
||||
|
||||
.daggerheart.dh-style.views.downtime {
|
||||
font-family: @font-body;
|
||||
|
||||
.downtime-container {
|
||||
.downtime-header {
|
||||
margin: 0;
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
text-align: center;
|
||||
.activities-grouping {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.activity-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
.activities-container {
|
||||
width: 100%;
|
||||
|
||||
.activity-title {
|
||||
flex: 1;
|
||||
.activity-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px;
|
||||
|
||||
.activity-title-text {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.activity-image {
|
||||
width: 80px;
|
||||
position: relative;
|
||||
.activity-inner-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-right: 8px;
|
||||
border: 2px solid black;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
.activity-select-label {
|
||||
position: absolute;
|
||||
top: -9px;
|
||||
font-size: 14px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
color: light-dark(@beige, @dark);
|
||||
background-image: url(../assets/parchments/dh-parchment-light.png);
|
||||
padding: 0 8px;
|
||||
line-height: 1;
|
||||
font-weight: bold;
|
||||
.activity-marker {
|
||||
font-size: 8px;
|
||||
flex: none;
|
||||
color: light-dark(#18162e, #f3c267);
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.activity-select-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
&:hover,
|
||||
&.selected {
|
||||
filter: drop-shadow(0 0 6px gold);
|
||||
.activity-icon {
|
||||
min-width: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-name-input {
|
||||
font-size: 24px;
|
||||
.activity-selected-marker {
|
||||
font-size: 14px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
color: light-dark(@dark, @beige);
|
||||
background-image: url(../assets/parchments/dh-parchment-dark.png);
|
||||
padding: 0 8px;
|
||||
line-height: 1;
|
||||
font-weight: bold;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
color: rgb(239, 230, 216);
|
||||
}
|
||||
}
|
||||
|
||||
.activity-body {
|
||||
flex: 1;
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.downtime {
|
||||
.activity-text-area {
|
||||
resize: none;
|
||||
footer {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,22 @@
|
|||
height: 40px;
|
||||
width: 100%;
|
||||
|
||||
.feature-tab {
|
||||
border: none;
|
||||
.navigation-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
a {
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
font-family: @font-body;
|
||||
.navigation-inner-container {
|
||||
flex: 1;
|
||||
|
||||
.feature-tab {
|
||||
border: none;
|
||||
|
||||
a {
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
font-family: @font-body;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,5 +193,14 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.character-downtime-container {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
border-color: light-dark(@dark, @beige);
|
||||
border-radius: 6px;
|
||||
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||
z-index: 200;
|
||||
max-height: 400px !important;
|
||||
width: fit-content !important;
|
||||
overflow-y: auto;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,20 @@
|
|||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
.tooltip-title-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
|
||||
.tooltip-image {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid @golden;
|
||||
}
|
||||
}
|
||||
|
||||
.tooltip-title {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
<div>
|
||||
<div class="downtime-container">
|
||||
<h2 class="downtime-header">{{localize "DAGGERHEART.APPLICATIONS.Downtime.downtimeHeader" current=nrCurrentChoices max=moveData.nrChoices}}</h2>
|
||||
{{#each moveData.moves as |move key|}}
|
||||
<div class="activity-container">
|
||||
<div class="activity-title">
|
||||
<div class="activity-image {{#if this.selected}}selected{{/if}}" data-action="selectMove" data-move="{{key}}">
|
||||
{{#if this.selected}}<div class="activity-select-label">{{move.selected}}</div>{{/if}}
|
||||
<img src="{{move.img}}" />
|
||||
</div>
|
||||
|
||||
<span class="activity-title-text">{{localize this.name}}</span>
|
||||
</div>
|
||||
<div class="activity-body">
|
||||
{{localize this.description}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<footer class="flexrow">
|
||||
<button type="button" data-action="close">{{localize "DAGGERHEART.Application.Cancel"}}</button>
|
||||
<button type="button" data-action="takeDowntime" {{#if this.disabledDowntime}}disabled{{/if}}>{{localize "DAGGERHEART.Application.Downtime.TakeDowntime"}}</button>
|
||||
</footer>
|
||||
</div>
|
||||
18
templates/dialogs/downtime/activities.hbs
Normal file
18
templates/dialogs/downtime/activities.hbs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<fieldset class="one-column activities-grouping">
|
||||
<legend>{{localize (concat "DAGGERHEART.APPLICATIONS.Downtime." category ".moves") max=nrChoices.max current=nrChoices.current}}</legend>
|
||||
|
||||
<div class="activities-container">
|
||||
{{#each moves as |move key|}}
|
||||
<a class="activity-container" data-action="selectMove" data-category="{{../category}}" data-move="{{key}}" data-tooltip="{{concat "#" ../category "#" key}}">
|
||||
<div class="activity-inner-container">
|
||||
<i class="{{#if move.selected}}fa-solid{{else}}fa-regular{{/if}} fa-circle activity-marker"></i>
|
||||
<div class="activity-select-section">
|
||||
<i class="{{move.icon}} activity-icon"></i>
|
||||
<div>{{move.name}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if move.selected}}<div class="activity-selected-marker">{{move.selected}}</div>{{/if}}
|
||||
</a>
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
14
templates/dialogs/downtime/downtime.hbs
Normal file
14
templates/dialogs/downtime/downtime.hbs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<div>
|
||||
<header class="dialog-header">
|
||||
<h1>{{title}}</h1>
|
||||
</header>
|
||||
|
||||
<div class="downtime-container {{#if (and shortRestMoves.moves longRestMoves.moves)}}two-columns even{{else}}one-column{{/if}}">
|
||||
{{#if shortRestMoves.moves}}{{> "systems/daggerheart/templates/dialogs/downtime/activities.hbs" moves=shortRestMoves.moves category='shortRest' nrChoices=nrChoices.shortRest}}{{/if}}
|
||||
{{#if longRestMoves.moves}}{{> "systems/daggerheart/templates/dialogs/downtime/activities.hbs" moves=longRestMoves.moves category='longRest' nrChoices=nrChoices.longRest}}{{/if}}
|
||||
</div>
|
||||
<footer>
|
||||
<button type="button" data-action="close">{{localize "Cancel"}}</button>
|
||||
<button type="button" data-action="takeDowntime" {{#if disabledDowntime}}disabled{{/if}}>{{localize "DAGGERHEART.APPLICATIONS.Downtime.takeDowntime"}}</button>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
@ -1,18 +1,17 @@
|
|||
<div>
|
||||
<div class="form-group">
|
||||
<label>{{localize "Icon"}}</label>
|
||||
|
||||
<div class="form-field">
|
||||
<input type="text" name="icon" value="{{icon}}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<fieldset>
|
||||
<legend>{{localize "Description"}}</legend>
|
||||
|
||||
<prose-mirror name="description" value="{{description}}" toggled=true>
|
||||
<prose-mirror name="description" value="{{description}}">
|
||||
{{{ enrichedDescription }}}
|
||||
</prose-mirror>
|
||||
</fieldset>
|
||||
{{!-- <fieldset>
|
||||
<legend>{{localize "Actions"}} <a data-action="addItem"><i class="fa-solid fa-plus"></i></a></legend>
|
||||
|
||||
<div class="settings-items">
|
||||
{{#each this.actions as |action index|}}
|
||||
{{> "systems/daggerheart/templates/settings/components/settings-item-line.hbs" action type="actions" id=index }}
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset> --}}
|
||||
</div>
|
||||
|
|
@ -116,5 +116,14 @@
|
|||
{{/each}}
|
||||
</div>
|
||||
|
||||
{{> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
|
||||
{{#> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
|
||||
<div class="character-downtime-container">
|
||||
<button data-action="useDowntime" data-type="shortRest" data-tooltip="{{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}}">
|
||||
<i class="fa-solid fa-chair"></i>
|
||||
</button>
|
||||
<button data-action="useDowntime" data-type="longRest" data-tooltip="{{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}}">
|
||||
<i class="fa-solid fa-bed"></i>
|
||||
</button>
|
||||
</div>
|
||||
{{/'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
|
||||
</header>
|
||||
|
|
@ -1,11 +1,18 @@
|
|||
<section class='tab-navigation'>
|
||||
<line-div></line-div>
|
||||
<nav class='feature-tab sheet-tabs tabs' data-group='primary'>
|
||||
{{#each tabs as |tab|}}
|
||||
<a class='{{tab.id}} {{tab.cssClass}}' data-action='tab' data-group='{{tab.group}}' data-tab='{{tab.id}}'>
|
||||
{{localize tab.label}}
|
||||
</a>
|
||||
{{/each}}
|
||||
</nav>
|
||||
<line-div></line-div>
|
||||
<div class='navigation-container'>
|
||||
<div class="navigation-inner-container">
|
||||
<line-div></line-div>
|
||||
<nav class='feature-tab sheet-tabs tabs' data-group='primary'>
|
||||
{{#each tabs as |tab|}}
|
||||
<a class='{{tab.id}} {{tab.cssClass}}' data-action='tab' data-group='{{tab.group}}' data-tab='{{tab.id}}'>
|
||||
{{localize tab.label}}
|
||||
</a>
|
||||
{{/each}}
|
||||
</nav>
|
||||
<line-div></line-div>
|
||||
</div>
|
||||
{{#if @partial-block}}
|
||||
{{> @partial-block }}
|
||||
{{/if}}
|
||||
</div>
|
||||
</section>
|
||||
7
templates/ui/tooltip/downtime.hbs
Normal file
7
templates/ui/tooltip/downtime.hbs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<div class="daggerheart dh-style tooltip">
|
||||
<div class="tooltip-title-container">
|
||||
<img class="tooltip-image" src="{{move.img}}" />
|
||||
<h2 class="tooltip-title">{{move.name}}</h2>
|
||||
</div>
|
||||
<div class="tooltip-description">{{{move.description}}}</div>
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue