mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
Feature/chat message styles (#514)
* style items and action chat messages * enhance death move chat message and fix border bottom from title actions * fix padding bottom * Added basic chat-message.hbs * . * style remaing chat messages * style action messages * remove console log * add colapsable descriptions in chat messages * inital style for message rolls * fix deal damage button style * add new partchments * Roll Chat message new design template * j * l * p * y * fix _getTags type error and add a alias label for non base messages * Fix damage & healing roll * Fix conflict * Deleting old templates * Good for now * fix labels in duality rolls messages and style experience and effects messages --------- Co-authored-by: WBHarry <williambjrklund@gmail.com> Co-authored-by: Dapoolp <elcatnet@gmail.com>
This commit is contained in:
parent
a4b1130142
commit
74df2c4e87
72 changed files with 1661 additions and 996 deletions
|
|
@ -152,8 +152,8 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
this.config.roll.type = this.reactionOverride
|
||||
? CONFIG.DH.ITEM.actionTypes.reaction.id
|
||||
: this.config.roll.type === CONFIG.DH.ITEM.actionTypes.reaction.id
|
||||
? null
|
||||
: this.config.roll.type;
|
||||
? null
|
||||
: this.config.roll.type;
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,20 +47,31 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application
|
|||
|
||||
static async takeMove() {
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const msg = new cls({
|
||||
const msg = {
|
||||
user: game.user.id,
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/deathMove.hbs',
|
||||
{
|
||||
player: this.actor.name,
|
||||
actor: { name: this.actor.name, img: this.actor.img },
|
||||
author: game.users.get(game.user.id),
|
||||
title: game.i18n.localize(this.selectedMove.name),
|
||||
img: this.selectedMove.img,
|
||||
description: game.i18n.localize(this.selectedMove.description)
|
||||
}
|
||||
)
|
||||
});
|
||||
),
|
||||
title: game.i18n.localize(
|
||||
'DAGGERHEART.UI.Chat.deathMove.title'
|
||||
),
|
||||
speaker: cls.getSpeaker(),
|
||||
flags: {
|
||||
daggerheart: {
|
||||
cssClass: 'dh-chat-message dh-style'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cls.create(msg.toObject());
|
||||
cls.create(msg);
|
||||
|
||||
this.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,22 +133,34 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
|||
});
|
||||
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const msg = new cls({
|
||||
const msg = {
|
||||
user: game.user.id,
|
||||
system: {
|
||||
moves: moves,
|
||||
actor: this.actor.uuid
|
||||
},
|
||||
speaker: cls.getSpeaker(),
|
||||
title: game.i18n.localize(
|
||||
`DAGGERHEART.APPLICATIONS.Downtime.${this.shortrest ? 'shortRest' : 'longRest'}.title`
|
||||
),
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/downtime.hbs',
|
||||
{
|
||||
title: `${this.actor.name} - ${game.i18n.localize(`DAGGERHEART.APPLICATIONS.Downtime.${this.shortrest ? 'shortRest' : 'longRest'}.title`)}`,
|
||||
title: game.i18n.localize(
|
||||
`DAGGERHEART.APPLICATIONS.Downtime.${this.shortrest ? 'shortRest' : 'longRest'}.title`
|
||||
),
|
||||
actor: { name: this.actor.name, img: this.actor.img },
|
||||
moves: moves
|
||||
}
|
||||
)
|
||||
});
|
||||
),
|
||||
flags: {
|
||||
daggerheart: {
|
||||
cssClass: 'dh-chat-message dh-style'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cls.create(msg.toObject());
|
||||
cls.create(msg);
|
||||
|
||||
// Reset selection and update number of taken moves
|
||||
for (const [catName, category] of Object.entries(this.moveData)) {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ export default class ResourceDiceDialog extends HandlebarsApplicationMixin(Appli
|
|||
this.resetUsed = true;
|
||||
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const msg = new cls({
|
||||
const msg = {
|
||||
user: game.user.id,
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/resource-roll.hbs',
|
||||
|
|
@ -83,9 +83,9 @@ export default class ResourceDiceDialog extends HandlebarsApplicationMixin(Appli
|
|||
name: this.item.name
|
||||
}
|
||||
)
|
||||
});
|
||||
};
|
||||
|
||||
cls.create(msg.toObject());
|
||||
cls.create(msg);
|
||||
this.close();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'dh-style', 'dialog'],
|
||||
classes: ['daggerheart', 'dh-style', 'dialog', 'max-800'],
|
||||
window: {
|
||||
icon: 'fa-solid fa-wrench',
|
||||
resizable: false
|
||||
|
|
|
|||
|
|
@ -108,17 +108,15 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
|||
*/
|
||||
static #reactionRoll(event) {
|
||||
const config = {
|
||||
event: event,
|
||||
event,
|
||||
title: `Reaction Roll: ${this.actor.name}`,
|
||||
headerTitle: 'Adversary Reaction Roll',
|
||||
roll: {
|
||||
type: 'reaction'
|
||||
},
|
||||
chatMessage: {
|
||||
type: 'adversaryRoll',
|
||||
template: 'systems/daggerheart/templates/ui/chat/adversary-roll.hbs',
|
||||
mute: true
|
||||
}
|
||||
type: 'trait',
|
||||
hasRoll: true,
|
||||
data: this.actor.getRollData()
|
||||
};
|
||||
|
||||
this.actor.diceRoll(config);
|
||||
|
|
|
|||
|
|
@ -611,9 +611,16 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
}),
|
||||
roll: {
|
||||
trait: button.dataset.attribute
|
||||
}
|
||||
},
|
||||
hasRoll: true
|
||||
};
|
||||
this.document.diceRoll(config);
|
||||
this.document.diceRoll({
|
||||
...config,
|
||||
headerTitle: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${this.actor.name}`,
|
||||
title: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: abilityLabel
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
//TODO: redo toggleEquipItem method
|
||||
|
|
|
|||
|
|
@ -121,21 +121,37 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
|||
*/
|
||||
static async #sendExpToChat(_, button) {
|
||||
const experience = this.document.system.experiences[button.dataset.id];
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
|
||||
const systemData = {
|
||||
name: game.i18n.localize('DAGGERHEART.GENERAL.Experience.single'),
|
||||
description: `${experience.name} ${experience.value.signedString()}`
|
||||
actor: { name: this.actor.name, img: this.actor.img },
|
||||
author: game.users.get(game.user.id),
|
||||
action: {
|
||||
name: `${experience.name} ${experience.value.signedString()}`,
|
||||
img: '/icons/sundries/misc/admission-ticket-blue.webp'
|
||||
},
|
||||
itemOrigin: {
|
||||
name: game.i18n.localize('DAGGERHEART.GENERAL.Experience.single')
|
||||
},
|
||||
description: experience.description
|
||||
};
|
||||
|
||||
foundry.documents.ChatMessage.implementation.create({
|
||||
type: 'abilityUse',
|
||||
const msg = {
|
||||
user: game.user.id,
|
||||
system: systemData,
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/ability-use.hbs',
|
||||
'systems/daggerheart/templates/ui/chat/action.hbs',
|
||||
systemData
|
||||
)
|
||||
});
|
||||
),
|
||||
title: game.i18n.localize('DAGGERHEART.ACTIONS.Config.displayInChat'),
|
||||
speaker: cls.getSpeaker(),
|
||||
flags: {
|
||||
daggerheart: {
|
||||
cssClass: 'dh-chat-message dh-style'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cls.create(msg);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -15,11 +15,16 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
this.setupHooks();
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ['daggerheart']
|
||||
};
|
||||
|
||||
addChatListeners = async (app, html, data) => {
|
||||
html.querySelectorAll('.duality-action-damage').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollDamage(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.target-save-container').forEach(element =>
|
||||
html.querySelectorAll('.target-save').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollSave(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.roll-all-save-button').forEach(element =>
|
||||
|
|
@ -28,6 +33,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
html.querySelectorAll('.duality-action-effect').forEach(element =>
|
||||
element.addEventListener('click', event => this.onApplyEffect(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.simple-roll-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollSimple(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.target-container').forEach(element => {
|
||||
element.addEventListener('mouseenter', this.hoverTarget);
|
||||
element.addEventListener('mouseleave', this.unhoverTarget);
|
||||
|
|
@ -119,7 +127,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
event.stopPropagation();
|
||||
if (!game.user.isGM) return;
|
||||
const targets = event.target.parentElement.querySelectorAll(
|
||||
'.target-section > [data-token] .target-save-container'
|
||||
'[data-token] .target-save'
|
||||
);
|
||||
const actor = await this.getActor(message.system.source.actor),
|
||||
action = this.getAction(actor, message.system.source.item, message.system.source.action);
|
||||
|
|
@ -160,8 +168,8 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
const targetSelection = Boolean(event.target.dataset.targetHit),
|
||||
msg = ui.chat.collection.get(message._id);
|
||||
if (msg.system.targetSelection === targetSelection) return;
|
||||
if (targetSelection !== true && !Array.from(game.user.targets).length)
|
||||
return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected'));
|
||||
// if (targetSelection !== true && !Array.from(game.user.targets).length)
|
||||
// return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected'));
|
||||
msg.system.targetSelection = targetSelection;
|
||||
msg.system.prepareDerivedData();
|
||||
ui.chat.updateMessage(msg);
|
||||
|
|
@ -224,8 +232,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected'));
|
||||
|
||||
for (let target of targets) {
|
||||
let damages = foundry.utils.deepClone(message.system.damage?.roll ?? message.system.roll);
|
||||
let damages = foundry.utils.deepClone(message.system.damage);
|
||||
if (
|
||||
!message.system.hasHealing &&
|
||||
message.system.onSave &&
|
||||
message.system.targets.find(t => t.id === target.id)?.saved?.success === true
|
||||
) {
|
||||
|
|
@ -244,6 +253,33 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
}
|
||||
}
|
||||
|
||||
async onRollSimple(event, message) {
|
||||
const buttonType = event.target.dataset.type ?? 'damage',
|
||||
total = message.rolls.reduce((a,c) => a + Roll.fromJSON(c).total, 0),
|
||||
damages = {
|
||||
'hitPoints': {
|
||||
parts: [
|
||||
{
|
||||
applyTo: 'hitPoints',
|
||||
damageTypes: [],
|
||||
total
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
targets = Array.from(game.user.targets);
|
||||
|
||||
if (targets.length === 0)
|
||||
return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected'));
|
||||
|
||||
targets.forEach(target => {
|
||||
if(buttonType === 'healing')
|
||||
target.actor.takeHealing(damages);
|
||||
else
|
||||
target.actor.takeDamage(damages);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle visibility of target containers.
|
||||
* @param {MouseEvent} event
|
||||
|
|
|
|||
|
|
@ -8,10 +8,6 @@ export default class DHAttackAction extends DHDamageAction {
|
|||
return parent.parent.type === 'weapon' ? 'attack' : 'spellcast';
|
||||
}
|
||||
|
||||
get chatTemplate() {
|
||||
return 'systems/daggerheart/templates/ui/chat/duality-roll.hbs';
|
||||
}
|
||||
|
||||
prepareData() {
|
||||
super.prepareData();
|
||||
if (!!this.item?.system?.attack) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import DhpActor from '../../documents/actor.mjs';
|
||||
import D20RollDialog from '../../applications/dialogs/d20RollDialog.mjs';
|
||||
import { ActionMixin } from '../fields/actionField.mjs';
|
||||
import { abilities } from '../../config/actorConfig.mjs';
|
||||
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
|
|
@ -69,10 +70,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
: this.item?.actor;
|
||||
}
|
||||
|
||||
get chatTemplate() {
|
||||
return 'systems/daggerheart/templates/ui/chat/duality-roll.hbs';
|
||||
}
|
||||
|
||||
static getRollType(parent) {
|
||||
return 'trait';
|
||||
}
|
||||
|
|
@ -161,21 +158,26 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
prepareConfig(event) {
|
||||
return {
|
||||
event,
|
||||
title: this.item.name,
|
||||
title: `${this.item.name}: ${this.name}`,
|
||||
source: {
|
||||
item: this.item._id,
|
||||
action: this._id,
|
||||
actor: this.actor.uuid
|
||||
},
|
||||
dialog: {},
|
||||
dialog: {
|
||||
configure: this.hasRoll
|
||||
},
|
||||
type: this.type,
|
||||
hasRoll: this.hasRoll,
|
||||
hasDamage: this.damage?.parts?.length && this.type !== 'healing',
|
||||
hasHealing: this.damage?.parts?.length && this.type === 'healing',
|
||||
hasEffect: !!this.effects?.length,
|
||||
hasSave: this.hasSave,
|
||||
hasTarget: true,
|
||||
selectedRollMode: game.settings.get('core', 'rollMode'),
|
||||
isFastForward: event.shiftKey,
|
||||
data: this.getRollData()
|
||||
data: this.getRollData(),
|
||||
evaluate: this.hasRoll
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +194,9 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
formula: this.roll.getFormula(),
|
||||
advantage: CONFIG.DH.ACTIONS.advantageState[this.roll.advState].value
|
||||
};
|
||||
if (this.roll?.type === 'diceSet') roll.lite = true;
|
||||
if (this.roll?.type === 'diceSet'
|
||||
|| !this.hasRoll
|
||||
) roll.lite = true;
|
||||
|
||||
return roll;
|
||||
}
|
||||
|
|
@ -296,19 +300,27 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
/* SAVE */
|
||||
async rollSave(actor, event, message) {
|
||||
if (!actor) return;
|
||||
const title = actor.isNPC
|
||||
? game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll')
|
||||
: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: game.i18n.localize(abilities[this.save.trait]?.label)
|
||||
});
|
||||
return actor.diceRoll({
|
||||
event,
|
||||
title: 'Roll Save',
|
||||
title,
|
||||
roll: {
|
||||
trait: this.save.trait,
|
||||
difficulty: this.save.difficulty ?? this.actor?.baseSaveDifficulty,
|
||||
type: 'reaction'
|
||||
},
|
||||
type: 'trait',
|
||||
hasRoll: true,
|
||||
data: actor.getRollData()
|
||||
});
|
||||
}
|
||||
|
||||
updateSaveMessage(result, message, targetId) {
|
||||
if(!result) return;
|
||||
const updateMsg = this.updateChatMessage.bind(this, message, targetId, {
|
||||
result: result.roll.total,
|
||||
success: result.roll.success
|
||||
|
|
|
|||
|
|
@ -44,19 +44,14 @@ export default class DHDamageAction extends DHBaseAction {
|
|||
|
||||
formulas = this.formatFormulas(formulas, systemData);
|
||||
|
||||
delete systemData.evaluate;
|
||||
systemData.targets.forEach(t => t.hit = true);
|
||||
const config = {
|
||||
title: game.i18n.format(`DAGGERHEART.UI.Chat.${this.type === 'healing' ? 'healing' : 'damage'}Roll.title`, {
|
||||
damage: game.i18n.localize(this.name)
|
||||
}),
|
||||
...systemData,
|
||||
roll: formulas,
|
||||
targets: systemData.targets?.filter(t => t.hit) ?? data.targets,
|
||||
hasSave: this.hasSave,
|
||||
isCritical: systemData.roll?.isCritical ?? false,
|
||||
isHealing: this.type === 'healing',
|
||||
source: systemData.source,
|
||||
data: this.getRollData(),
|
||||
event
|
||||
};
|
||||
dialog: {},
|
||||
data: this.getRollData()
|
||||
}
|
||||
if (this.hasSave) config.onSave = this.save.damageMod;
|
||||
if (data.system) {
|
||||
config.source.message = data._id;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import DHBaseAction from './baseAction.mjs';
|
||||
import DHDamageAction from './damageAction.mjs';
|
||||
|
||||
export default class DHHealingAction extends DHDamageAction {
|
||||
|
|
@ -7,49 +6,4 @@ export default class DHHealingAction extends DHDamageAction {
|
|||
static getRollType(parent) {
|
||||
return 'spellcast';
|
||||
}
|
||||
|
||||
/* static extraSchemas = [...super.extraSchemas, 'target', 'effects', 'healing', 'roll'];
|
||||
|
||||
static getRollType(parent) {
|
||||
return 'spellcast';
|
||||
}
|
||||
|
||||
getFormulaValue(data) {
|
||||
let formulaValue = this.healing.value;
|
||||
if (this.hasRoll && this.healing.resultBased && data.system.roll.result.duality === -1)
|
||||
return this.healing.valueAlt;
|
||||
return formulaValue;
|
||||
}
|
||||
|
||||
async rollHealing(event, data) {
|
||||
const systemData = data.system ?? data;
|
||||
let formulas = [
|
||||
{
|
||||
formula: this.getFormulaValue(data).getFormula(this.actor),
|
||||
applyTo: this.healing.applyTo
|
||||
}
|
||||
];
|
||||
|
||||
const config = {
|
||||
title: game.i18n.format('DAGGERHEART.UI.Chat.healingRoll.title', {
|
||||
healing: game.i18n.localize(CONFIG.DH.GENERAL.healingTypes[this.healing.applyTo].label)
|
||||
}),
|
||||
roll: formulas,
|
||||
targets: systemData.targets?.filter(t => t.hit),
|
||||
messageType: 'healing',
|
||||
source: systemData.source,
|
||||
data: this.getRollData(),
|
||||
event
|
||||
};
|
||||
|
||||
return CONFIG.Dice.daggerheart.DamageRoll.build(config);
|
||||
}
|
||||
|
||||
get chatTemplate() {
|
||||
return 'systems/daggerheart/templates/ui/chat/healing-roll.hbs';
|
||||
}
|
||||
|
||||
get modifiers() {
|
||||
return [];
|
||||
} */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,11 @@
|
|||
import DHAbilityUse from "./abilityUse.mjs";
|
||||
import DHAdversaryRoll from "./adversaryRoll.mjs";
|
||||
import DHDamageRoll from "./damageRoll.mjs";
|
||||
import DHDualityRoll from "./dualityRoll.mjs";
|
||||
import DHActorRoll from "./adversaryRoll.mjs";
|
||||
import DHApplyEffect from './applyEffects.mjs'
|
||||
|
||||
export {
|
||||
DHAbilityUse,
|
||||
DHAdversaryRoll,
|
||||
DHDamageRoll,
|
||||
DHDualityRoll,
|
||||
DHApplyEffect
|
||||
}
|
||||
|
||||
export const config = {
|
||||
abilityUse: DHAbilityUse,
|
||||
adversaryRoll: DHAdversaryRoll,
|
||||
damageRoll: DHDamageRoll,
|
||||
dualityRoll: DHDualityRoll,
|
||||
adversaryRoll: DHActorRoll,
|
||||
damageRoll: DHActorRoll,
|
||||
dualityRoll: DHActorRoll,
|
||||
applyEffect: DHApplyEffect
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
const fields = foundry.data.fields;
|
||||
|
||||
export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel {
|
||||
export default class DHActorRoll extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
return {
|
||||
title: new fields.StringField(),
|
||||
|
|
@ -20,22 +20,29 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel {
|
|||
})
|
||||
})
|
||||
),
|
||||
targetSelection: new fields.BooleanField({ initial: true }),
|
||||
targetSelection: new fields.BooleanField({ initial: false }),
|
||||
hasRoll: new fields.BooleanField({ initial: false }),
|
||||
hasDamage: new fields.BooleanField({ initial: false }),
|
||||
hasHealing: new fields.BooleanField({ initial: false }),
|
||||
hasEffect: new fields.BooleanField({ initial: false }),
|
||||
hasSave: new fields.BooleanField({ initial: false }),
|
||||
hasTarget: new fields.BooleanField({ initial: false }),
|
||||
isCritical: new fields.BooleanField({ initial: false }),
|
||||
onSave: new fields.StringField(),
|
||||
source: new fields.SchemaField({
|
||||
actor: new fields.StringField(),
|
||||
item: new fields.StringField(),
|
||||
action: new fields.StringField()
|
||||
}),
|
||||
damage: new fields.ObjectField()
|
||||
damage: new fields.ObjectField(),
|
||||
costs: new fields.ArrayField(
|
||||
new fields.ObjectField()
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
get messageTemplate() {
|
||||
return 'systems/daggerheart/templates/ui/chat/adversary-roll.hbs';
|
||||
return 'systems/daggerheart/templates/ui/chat/roll.hbs';
|
||||
}
|
||||
|
||||
prepareDerivedData() {
|
||||
|
|
@ -46,5 +53,15 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel {
|
|||
game.system.api.fields.ActionFields.TargetField.formatTarget(t)
|
||||
)
|
||||
: this.targets;
|
||||
if(this.targetSelection === true) {
|
||||
this.targetShort = this.targets.reduce((a,c) => {
|
||||
if(c.hit) a.hit += 1;
|
||||
else c.miss += 1;
|
||||
return a;
|
||||
}, {hit: 0, miss: 0})
|
||||
}
|
||||
this.pendingSaves = this.targets.filter(
|
||||
target => target.hit && target.saved.success === null
|
||||
).length > 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
export default class DHDamageRoll extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
return {
|
||||
messageType: new fields.StringField({ initial: 'damage' }),
|
||||
title: new fields.StringField(),
|
||||
roll: new fields.DataField({}),
|
||||
targets: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
id: new fields.StringField({ required: true }),
|
||||
actorId: new fields.StringField({}),
|
||||
name: new fields.StringField(),
|
||||
img: new fields.StringField(),
|
||||
hit: new fields.BooleanField({ initial: false }),
|
||||
saved: new fields.SchemaField({
|
||||
result: new fields.NumberField(),
|
||||
success: new fields.BooleanField({ nullable: true, initial: null })
|
||||
})
|
||||
})
|
||||
),
|
||||
targetSelection: new fields.BooleanField({ initial: true }),
|
||||
hasSave: new fields.BooleanField({ initial: false }),
|
||||
isHealing: new fields.BooleanField({ initial: false }),
|
||||
onSave: new fields.StringField(),
|
||||
source: new fields.SchemaField({
|
||||
actor: new fields.StringField(),
|
||||
item: new fields.StringField(),
|
||||
action: new fields.StringField(),
|
||||
message: new fields.StringField()
|
||||
}),
|
||||
directDamage: new fields.BooleanField({ initial: true })
|
||||
};
|
||||
}
|
||||
|
||||
get messageTemplate() {
|
||||
return `systems/daggerheart/templates/ui/chat/${this.messageType}-roll.hbs`;
|
||||
}
|
||||
|
||||
prepareDerivedData() {
|
||||
this.hasHitTarget = this.targets.filter(t => t.hit === true).length > 0;
|
||||
this.currentTargets =
|
||||
this.targetSelection !== true
|
||||
? Array.from(game.user.targets).map(t =>
|
||||
game.system.api.fields.ActionFields.TargetField.formatTarget(t)
|
||||
)
|
||||
: this.targets;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
import DHAdversaryRoll from './adversaryRoll.mjs';
|
||||
|
||||
export default class DHDualityRoll extends DHAdversaryRoll {
|
||||
get messageTemplate() {
|
||||
return 'systems/daggerheart/templates/ui/chat/duality-roll.hbs';
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ export default class CostField extends fields.ArrayField {
|
|||
}
|
||||
|
||||
static calcCosts(costs) {
|
||||
console.log(costs, CostField.getResources.call(this, costs));
|
||||
// console.log(costs, CostField.getResources.call(this, costs));
|
||||
const resources = CostField.getResources.call(this, costs);
|
||||
return costs.map(c => {
|
||||
c.scale = c.scale ?? 1;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export class DHActionRollData extends foundry.abstract.DataModel {
|
|||
this.diceRolling.multiplier === 'flat'
|
||||
? this.diceRolling.flatMultiplier
|
||||
: `@${this.diceRolling.multiplier}`;
|
||||
if (this.diceRolling.compare && this.diceRolling.threshold) {
|
||||
if (this.diceRolling.compare && this.diceRolling.treshold) {
|
||||
formula = `${multiplier}${this.diceRolling.dice}cs${CONFIG.DH.ACTIONS.diceCompare[this.diceRolling.compare].operator}${this.diceRolling.treshold}`;
|
||||
} else {
|
||||
formula = `${multiplier}${this.diceRolling.dice}`;
|
||||
|
|
|
|||
|
|
@ -252,19 +252,27 @@ export function ActionMixin(Base) {
|
|||
const systemData = {
|
||||
title: game.i18n.localize('DAGGERHEART.CONFIG.ActionType.action'),
|
||||
origin: origin,
|
||||
img: this.img,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
actions: []
|
||||
action: { name: this.name, img: this.img, tags: this.tags ? this.tags : ['Spell', 'Arcana', 'Lv 10'] },
|
||||
itemOrigin: this.item,
|
||||
description: this.description
|
||||
};
|
||||
const msg = {
|
||||
type: 'abilityUse',
|
||||
user: game.user.id,
|
||||
actor: { name: this.actor.name, img: this.actor.img },
|
||||
author: this.author,
|
||||
speaker: cls.getSpeaker(),
|
||||
title: game.i18n.localize('DAGGERHEART.UI.Chat.action.title'),
|
||||
system: systemData,
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/ability-use.hbs',
|
||||
'systems/daggerheart/templates/ui/chat/action.hbs',
|
||||
systemData
|
||||
)
|
||||
),
|
||||
flags: {
|
||||
daggerheart: {
|
||||
cssClass: 'dh-chat-message dh-style'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cls.create(msg);
|
||||
|
|
|
|||
|
|
@ -13,12 +13,16 @@ export default class D20Roll extends DHRoll {
|
|||
DISADVANTAGE: -1
|
||||
};
|
||||
|
||||
static messageType = 'adversaryRoll';
|
||||
|
||||
static CRITICAL_TRESHOLD = 20;
|
||||
|
||||
static DefaultDialog = D20RollDialog;
|
||||
|
||||
get title() {
|
||||
return game.i18n.localize(
|
||||
"DAGGERHEART.GENERAL.d20Roll"
|
||||
);
|
||||
}
|
||||
|
||||
get d20() {
|
||||
if (!(this.terms[0] instanceof foundry.dice.terms.Die)) this.createBaseDice();
|
||||
return this.terms[0];
|
||||
|
|
@ -136,7 +140,9 @@ export default class D20Roll extends DHRoll {
|
|||
|
||||
static postEvaluate(roll, config = {}) {
|
||||
const data = super.postEvaluate(roll, config);
|
||||
data.type = config.roll?.type;
|
||||
if (config.targets?.length) {
|
||||
config.targetSelection = true;
|
||||
config.targets.forEach(target => {
|
||||
const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion;
|
||||
target.hit = this.isCritical || roll.total >= difficulty;
|
||||
|
|
@ -145,7 +151,6 @@ export default class D20Roll extends DHRoll {
|
|||
data.difficulty = config.roll.difficulty;
|
||||
data.success = roll.isCritical || roll.total >= config.roll.difficulty;
|
||||
}
|
||||
data.type = config.roll.type;
|
||||
data.advantage = {
|
||||
type: config.roll.advantage,
|
||||
dice: roll.dAdvantage?.denomination,
|
||||
|
|
@ -159,7 +164,7 @@ export default class D20Roll extends DHRoll {
|
|||
rerolls: dice.results.filter(x => x.rerolled)
|
||||
}
|
||||
}));
|
||||
data.isCritical = roll.isCritical;
|
||||
data.isCritical = config.isCritical = roll.isCritical;
|
||||
data.extra = roll.dice
|
||||
.filter(d => !roll.baseTerms.includes(d))
|
||||
.map(d => {
|
||||
|
|
|
|||
|
|
@ -6,23 +6,17 @@ export default class DamageRoll extends DHRoll {
|
|||
super(formula, data, options);
|
||||
}
|
||||
|
||||
static messageType = 'damageRoll';
|
||||
|
||||
static DefaultDialog = DamageDialog;
|
||||
|
||||
static async buildEvaluate(roll, config = {}, message = {}) {
|
||||
if (config.evaluate !== false) {
|
||||
// if (config.dialog.configure === false) roll.constructFormula(config);
|
||||
if (config.evaluate !== false)
|
||||
for (const roll of config.roll) await roll.roll.evaluate();
|
||||
}
|
||||
|
||||
roll._evaluated = true;
|
||||
const parts = [];
|
||||
for (let r of config.roll) {
|
||||
const part = this.postEvaluate(r);
|
||||
parts.push(part);
|
||||
}
|
||||
const parts = config.roll.map(r => this.postEvaluate(r));
|
||||
|
||||
config.roll = this.unifyDamageRoll(parts);
|
||||
config.damage = this.unifyDamageRoll(parts);
|
||||
config.targetSelection = config.targets?.length
|
||||
}
|
||||
|
||||
static postEvaluate(roll, config = {}) {
|
||||
|
|
@ -37,11 +31,18 @@ export default class DamageRoll extends DHRoll {
|
|||
}
|
||||
|
||||
static async buildPost(roll, config, message) {
|
||||
if (game.modules.get('dice-so-nice')?.active) {
|
||||
const pool = foundry.dice.terms.PoolTerm.fromRolls(
|
||||
Object.values(config.damage).flatMap(r => r.parts.map(p => p.roll))
|
||||
),
|
||||
diceRoll = Roll.fromTerms([pool]);
|
||||
await game.dice3d.showForRoll(diceRoll, game.user, true);
|
||||
}
|
||||
await super.buildPost(roll, config, message);
|
||||
if (config.source?.message) {
|
||||
const chatMessage = ui.chat.collection.get(config.source.message);
|
||||
chatMessage.update({ 'system.damage': config });
|
||||
}
|
||||
chatMessage.update({ 'system.damage': config.damage });
|
||||
}
|
||||
}
|
||||
|
||||
static unifyDamageRoll(rolls) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@ export default class DHRoll extends Roll {
|
|||
if (!this.data || !Object.keys(this.data).length) this.data = options.data;
|
||||
}
|
||||
|
||||
get title() {
|
||||
return game.i18n.localize(
|
||||
"DAGGERHEART.GENERAL.Roll.basic"
|
||||
);
|
||||
}
|
||||
|
||||
static messageType = 'adversaryRoll';
|
||||
|
||||
static DefaultDialog = D20RollDialog;
|
||||
|
|
@ -46,8 +52,10 @@ export default class DHRoll extends Roll {
|
|||
}
|
||||
|
||||
static async buildEvaluate(roll, config = {}, message = {}) {
|
||||
if (config.evaluate !== false) await roll.evaluate();
|
||||
config.roll = this.postEvaluate(roll, config);
|
||||
if (config.evaluate !== false) {
|
||||
await roll.evaluate();
|
||||
config.roll = this.postEvaluate(roll, config);
|
||||
}
|
||||
}
|
||||
|
||||
static async buildPost(roll, config, message) {
|
||||
|
|
@ -56,15 +64,8 @@ export default class DHRoll extends Roll {
|
|||
}
|
||||
|
||||
// Create Chat Message
|
||||
if (roll instanceof CONFIG.Dice.daggerheart.DamageRoll && Object.values(config.roll)?.length) {
|
||||
const pool = foundry.dice.terms.PoolTerm.fromRolls(
|
||||
Object.values(config.roll).flatMap(r => r.parts.map(p => p.roll))
|
||||
);
|
||||
roll = Roll.fromTerms([pool]);
|
||||
}
|
||||
if (config.source?.message) {
|
||||
if (game.modules.get('dice-so-nice')?.active) await game.dice3d.showForRoll(roll, game.user, true);
|
||||
} else config.message = await this.toMessage(roll, config);
|
||||
if (!config.source?.message)
|
||||
config.message = await this.toMessage(roll, config);
|
||||
}
|
||||
|
||||
static postEvaluate(roll, config = {}) {
|
||||
|
|
@ -85,11 +86,14 @@ export default class DHRoll extends Roll {
|
|||
msg = {
|
||||
type: this.messageType,
|
||||
user: game.user.id,
|
||||
title: roll.title,
|
||||
speaker: cls.getSpeaker(),
|
||||
sound: config.mute ? null : CONFIG.sounds.dice,
|
||||
system: config,
|
||||
rolls: [roll]
|
||||
};
|
||||
return await cls.create(msg, { rollMode: config.selectedRollMode });
|
||||
if(roll._evaluated) return await cls.create(msg, { rollMode: config.selectedRollMode });
|
||||
return msg;
|
||||
}
|
||||
|
||||
static applyKeybindings(config) {
|
||||
|
|
@ -178,7 +182,7 @@ export default class DHRoll extends Roll {
|
|||
|
||||
export const registerRollDiceHooks = () => {
|
||||
Hooks.on(`${CONFIG.DH.id}.postRollDuality`, async (config, message) => {
|
||||
const hopeFearAutomation = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).hopeFear;
|
||||
const hopeFearAutomation = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).hopeFear;
|
||||
if (
|
||||
!config.source?.actor ||
|
||||
(game.user.isGM ? !hopeFearAutomation.gm : !hopeFearAutomation.players) ||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@ export default class DualityRoll extends D20Roll {
|
|||
|
||||
static DefaultDialog = D20RollDialog;
|
||||
|
||||
get title() {
|
||||
return game.i18n.localize(
|
||||
"DAGGERHEART.GENERAL.dualityRoll"
|
||||
);
|
||||
}
|
||||
|
||||
get dHope() {
|
||||
// if ( !(this.terms[0] instanceof foundry.dice.terms.Die) ) return;
|
||||
if (!(this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice();
|
||||
|
|
|
|||
|
|
@ -115,24 +115,26 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
|
|||
|
||||
async toChat(origin) {
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const actor = game.actors.get(cls.getSpeaker().actor);
|
||||
const systemData = {
|
||||
title: game.i18n.localize('DAGGERHEART.CONFIG.ActionType.action'),
|
||||
action: { img: this.img, name: this.name },
|
||||
actor: { name: actor.name, img: actor.img },
|
||||
author: this.author,
|
||||
speaker: cls.getSpeaker(),
|
||||
origin: origin,
|
||||
img: this.img,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
actions: []
|
||||
};
|
||||
const msg = new cls({
|
||||
type: 'abilityUse',
|
||||
const msg = {
|
||||
title: game.i18n.localize('DAGGERHEART.GENERAL.Effect.single'),
|
||||
user: game.user.id,
|
||||
system: systemData,
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/ability-use.hbs',
|
||||
'systems/daggerheart/templates/ui/chat/action.hbs',
|
||||
systemData
|
||||
)
|
||||
});
|
||||
};
|
||||
|
||||
cls.create(msg.toObject());
|
||||
cls.create(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -541,12 +541,12 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
|
||||
canResist(type, resistance) {
|
||||
if (!type) return 0;
|
||||
if (!type?.length) return false;
|
||||
return type.every(t => this.system.resistance[t]?.[resistance] === true);
|
||||
}
|
||||
|
||||
getDamageTypeReduction(type) {
|
||||
if (!type) return 0;
|
||||
if (!type?.length) return 0;
|
||||
const reduction = Object.entries(this.system.resistance).reduce(
|
||||
(a, [index, value]) => (type.includes(index) ? Math.min(value.reduction, a) : a),
|
||||
Infinity
|
||||
|
|
|
|||
|
|
@ -6,13 +6,18 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
|||
_source: this.system._source
|
||||
});
|
||||
|
||||
const actor = game.actors.get(this.speaker.actor);
|
||||
const actorData = actor ?? {
|
||||
img: this.author.avatar ? this.author.avatar : 'icons/svg/mystery-man.svg',
|
||||
name: ''
|
||||
};
|
||||
/* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */
|
||||
const html = await super.renderHTML();
|
||||
const html = await super.renderHTML({ actor: actorData, author: this.author });
|
||||
this.applyPermission(html);
|
||||
|
||||
if (this.type === 'dualityRoll') {
|
||||
html.classList.add('duality');
|
||||
switch (this.system.roll.result.duality) {
|
||||
switch (this.system.roll?.result?.duality) {
|
||||
case 1:
|
||||
html.classList.add('hope');
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -102,9 +102,9 @@ export default class DHItem extends foundry.documents.Item {
|
|||
* Generate an array of localized tag.
|
||||
* @returns {string[]} An array of localized tag strings.
|
||||
*/
|
||||
getTags() {
|
||||
_getTags() {
|
||||
const tags = [];
|
||||
if (this.system.getTags) tags.push(...this.system.getTags());
|
||||
if (this.system._getTags) tags.push(...this.system._getTags());
|
||||
return tags;
|
||||
}
|
||||
|
||||
|
|
@ -143,20 +143,33 @@ export default class DHItem extends foundry.documents.Item {
|
|||
: game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.subclassFeatureTitle'),
|
||||
origin: origin,
|
||||
img: this.img,
|
||||
name: this.name,
|
||||
item: {
|
||||
name: this.name,
|
||||
img: this.img,
|
||||
tags: this._getTags()
|
||||
},
|
||||
description: this.system.description,
|
||||
actions: []
|
||||
actions: this.system.actions
|
||||
};
|
||||
const msg = new cls({
|
||||
const msg = {
|
||||
type: 'abilityUse',
|
||||
user: game.user.id,
|
||||
actor: game.actors.get(cls.getSpeaker().actor),
|
||||
author: this.author,
|
||||
speaker: cls.getSpeaker(),
|
||||
system: systemData,
|
||||
title: game.i18n.localize('DAGGERHEART.ACTIONS.Config.displayInChat'),
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/ability-use.hbs',
|
||||
systemData
|
||||
)
|
||||
});
|
||||
),
|
||||
flags: {
|
||||
daggerheart: {
|
||||
cssClass: 'dh-chat-message dh-style'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cls.create(msg.toObject());
|
||||
cls.create(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,9 +93,8 @@ export const enrichedDualityRoll = async (
|
|||
advantage,
|
||||
type: reaction ? 'reaction' : null
|
||||
},
|
||||
chatMessage: {
|
||||
template: 'systems/daggerheart/templates/ui/chat/duality-roll.hbs'
|
||||
}
|
||||
type: 'trait',
|
||||
hasRoll: true
|
||||
};
|
||||
|
||||
if (target) {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ export default class RegisterHandlebarsHelpers {
|
|||
damageSymbols: this.damageSymbols,
|
||||
rollParsed: this.rollParsed,
|
||||
hasProperty: foundry.utils.hasProperty,
|
||||
setVar: this.setVar
|
||||
setVar: this.setVar,
|
||||
empty: this.empty
|
||||
});
|
||||
}
|
||||
static add(a, b) {
|
||||
|
|
@ -65,4 +66,9 @@ export default class RegisterHandlebarsHelpers {
|
|||
static setVar(name, value, context) {
|
||||
this[name] = value;
|
||||
}
|
||||
|
||||
static empty(object) {
|
||||
if(!(typeof object === 'object')) return true;
|
||||
return Object.keys(object).length === 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,11 +26,15 @@ export const preloadHandlebarsTemplates = async function () {
|
|||
'systems/daggerheart/templates/actionTypes/effect.hbs',
|
||||
'systems/daggerheart/templates/actionTypes/beastform.hbs',
|
||||
'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/tooltipChips.hbs',
|
||||
'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs',
|
||||
'systems/daggerheart/templates/dialogs/downtime/activities.hbs',
|
||||
'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs'
|
||||
'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs',
|
||||
|
||||
|
||||
'systems/daggerheart/templates/ui/chat/parts/roll-part.hbs',
|
||||
'systems/daggerheart/templates/ui/chat/parts/damage-part.hbs',
|
||||
'systems/daggerheart/templates/ui/chat/parts/target-part.hbs',
|
||||
'systems/daggerheart/templates/ui/chat/parts/button-part.hbs',
|
||||
]);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue