Updated attack rolls and damage rolls for adversaries

This commit is contained in:
WBHarry 2025-05-24 10:25:40 +02:00
parent ee6c97d134
commit faab60b45b
22 changed files with 356 additions and 204 deletions

View file

@ -74,6 +74,7 @@ Hooks.once('init', () => {
CONFIG.ChatMessage.dataModels = { CONFIG.ChatMessage.dataModels = {
dualityRoll: models.DhpDualityRoll, dualityRoll: models.DhpDualityRoll,
adversaryRoll: models.DhpAdversaryRoll, adversaryRoll: models.DhpAdversaryRoll,
damageRoll: models.DhpDamageRoll,
abilityUse: models.DhpAbilityUse abilityUse: models.DhpAbilityUse
}; };
CONFIG.ChatMessage.documentClass = applications.DhpChatMessage; CONFIG.ChatMessage.documentClass = applications.DhpChatMessage;

View file

@ -86,7 +86,8 @@
"SecondaryEquipWhileTwohanded": "A secondary weapon can't be equipped together with a Two-Handed weapon.", "SecondaryEquipWhileTwohanded": "A secondary weapon can't be equipped together with a Two-Handed weapon.",
"TwohandedEquipWhileSecondary": "Can't equip a Two-Handed weapon together with a secondary weapon.", "TwohandedEquipWhileSecondary": "Can't equip a Two-Handed weapon together with a secondary weapon.",
"SelectClassBeforeSubclass": "Select a Class before selecting a Subclass.", "SelectClassBeforeSubclass": "Select a Class before selecting a Subclass.",
"SubclassNotOfClass": "This Subclass doesn't belong to your current Class." "SubclassNotOfClass": "This Subclass doesn't belong to your current Class.",
"AttackTargetDoesNotExist": "The target token no longer exists"
}, },
"Error": { "Error": {
"NoClassSelected": "Your character has no class selected!", "NoClassSelected": "Your character has no class selected!",
@ -101,8 +102,14 @@
"Hope": "Hope", "Hope": "Hope",
"Fear": "Fear", "Fear": "Fear",
"CriticalSuccess": "Critical Success", "CriticalSuccess": "Critical Success",
"Advantage": "Advantage", "Advantage": {
"Disadvantage": "Disadvantage", "Full": "Advantage",
"Short": "Adv"
},
"Disadvantage": {
"Full": "Disadvantage",
"Short": "Dis"
},
"OK": "OK", "OK": "OK",
"Cancel": "Cancel", "Cancel": "Cancel",
"Or": "Or", "Or": "Or",
@ -748,6 +755,7 @@
"AdvantageChooseTitle": "Select Hope Dice" "AdvantageChooseTitle": "Select Hope Dice"
}, },
"DamageRoll": { "DamageRoll": {
"DealDamageToTargets": "Damage Hit Targets",
"DealDamage": "Deal Damage" "DealDamage": "Deal Damage"
}, },
"HealingRoll": { "HealingRoll": {
@ -899,8 +907,8 @@
"Stress": "Stress", "Stress": "Stress",
"Experience": "Experience", "Experience": "Experience",
"Experiences": "Experiences", "Experiences": "Experiences",
"Moves": "Moves", "Features": "Features",
"NewMove": "New Move" "NewFeature": "New Feature"
}, },
"Environment": { "Environment": {
"ToneAndFeel": "Tone And feel", "ToneAndFeel": "Tone And feel",

View file

@ -1,6 +1,11 @@
export default class DhpChatMesssage extends ChatMessage { export default class DhpChatMesssage extends ChatMessage {
async renderHTML() { async renderHTML() {
if (this.type === 'dualityRoll' || this.type === 'adversaryRoll' || this.type === 'abilityUse') { if (
this.type === 'dualityRoll' ||
this.type === 'adversaryRoll' ||
this.type === 'damageRoll' ||
this.type === 'abilityUse'
) {
this.content = await foundry.applications.handlebars.renderTemplate(this.content, this.system); this.content = await foundry.applications.handlebars.renderTemplate(this.content, this.system);
} }

View file

@ -1,7 +1,7 @@
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
export default class DamageSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) { export default class DamageSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(rollString, bonusDamage, hope, resolve) { constructor(rollString, bonusDamage, resolve, hope = 0) {
super({}); super({});
this.data = { this.data = {

View file

@ -6,7 +6,6 @@ export default class NpcRollSelectionDialog extends FormApplication {
this.resolve = resolve; this.resolve = resolve;
this.selectedExperiences = []; this.selectedExperiences = [];
this.data = { this.data = {
nrDice: 1,
advantage: null advantage: null
}; };
} }
@ -19,7 +18,7 @@ export default class NpcRollSelectionDialog extends FormApplication {
const defaults = super.defaultOptions; const defaults = super.defaultOptions;
const overrides = { const overrides = {
height: 'auto', height: 'auto',
width: 400, width: 500,
id: 'roll-selection', id: 'roll-selection',
template: 'systems/daggerheart/templates/views/npcRollSelection.hbs', template: 'systems/daggerheart/templates/views/npcRollSelection.hbs',
closeOnSubmit: false, closeOnSubmit: false,
@ -34,11 +33,11 @@ export default class NpcRollSelectionDialog extends FormApplication {
async getData() { async getData() {
const context = super.getData(); const context = super.getData();
context.nrDice = this.data.nrDice;
context.advantage = this.data.advantage; context.advantage = this.data.advantage;
context.experiences = this.experiences.map(x => ({ context.experiences = Object.values(this.experiences).map(x => ({
...x, ...x,
selected: this.selectedExperiences.find(selected => selected.id === x.id) selected: this.selectedExperiences.find(selected => selected.id === x.id),
value: `${x.value >= 0 ? '+' : '-'}${x.value}`
})); }));
return context; return context;
@ -47,17 +46,10 @@ export default class NpcRollSelectionDialog extends FormApplication {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
html.find('.increase').click(_ => this.updateNrDice(1));
html.find('.decrease').click(_ => this.updateNrDice(-1));
html.find('.advantage').click(_ => this.updateIsAdvantage(true)); html.find('.advantage').click(_ => this.updateIsAdvantage(true));
html.find('.disadvantage').click(_ => this.updateIsAdvantage(false)); html.find('.disadvantage').click(_ => this.updateIsAdvantage(false));
html.find('.roll-button').click(this.finish.bind(this)); html.find('.roll-button').click(this.finish.bind(this));
html.find('.roll-dialog-chip').click(this.selectExperience.bind(this)); html.find('.experience-chip').click(this.selectExperience.bind(this));
}
updateNrDice(value) {
this.data.nrDice += value;
this.render();
} }
updateIsAdvantage(advantage) { updateIsAdvantage(advantage) {
@ -66,9 +58,9 @@ export default class NpcRollSelectionDialog extends FormApplication {
} }
selectExperience(event) { selectExperience(event) {
const experience = this.experiences[event.currentTarget.dataset.key]; const experience = Object.values(this.experiences).find(experience => experience.id === event.currentTarget.id);
this.selectedExperiences = this.selectedExperiences.find(x => x.name === experience.name) this.selectedExperiences = this.selectedExperiences.find(x => x.id === experience.id)
? this.selectedExperiences.filter(x => x.name !== experience.name) ? this.selectedExperiences.filter(x => x.id !== experience.id)
: [...this.selectedExperiences, experience]; : [...this.selectedExperiences, experience];
this.render(); this.render();

View file

@ -349,7 +349,7 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
static async attackRoll(event, button) { static async attackRoll(event, button) {
const modifier = Number.parseInt(button.dataset.value); const modifier = Number.parseInt(button.dataset.value);
const { roll, diceResults, modifiers } = await this.actor.diceRoll( const { roll, dice, advantageState, modifiers } = await this.actor.diceRoll(
{ title: `${this.actor.name} - Attack Roll`, value: modifier }, { title: `${this.actor.name} - Attack Roll`, value: modifier },
event.shiftKey event.shiftKey
); );
@ -365,11 +365,14 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
const cls = getDocumentClass('ChatMessage'); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
type: 'adversaryRoll', type: 'adversaryRoll',
sound: CONFIG.sounds.dice,
system: { system: {
origin: this.document.id,
roll: roll._formula, roll: roll._formula,
advantageState,
total: roll._total, total: roll._total,
modifiers: modifiers, modifiers: modifiers,
diceResults: diceResults, dice: dice,
targets: targets, targets: targets,
damage: { value: button.dataset.damage, type: button.dataset.damageType } damage: { value: button.dataset.damage, type: button.dataset.damageType }
}, },
@ -381,16 +384,15 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
} }
static async addExperience() { static async addExperience() {
const experienceId = foundry.utils.randomID();
await this.document.update({ await this.document.update({
'system.experiences': [...this.document.system.experiences, { name: 'Experience', value: 1 }] [`system.experiences.${experienceId}`]: { id: experienceId, name: 'Experience', value: 1 }
}); });
} }
static async removeExperience(_, button) { static async removeExperience(_, button) {
await this.document.update({ await this.document.update({
'system.experiences': this.document.system.experiences.filter( [`system.experiences.-=${button.dataset.experience}`]: null
(_, index) => index !== Number.parseInt(button.dataset.experience)
)
}); });
} }

View file

@ -14,5 +14,6 @@ export { default as DhpWeapon } from './weapon.mjs';
export { default as DhpArmor } from './armor.mjs'; export { default as DhpArmor } from './armor.mjs';
export { default as DhpDualityRoll } from './dualityRoll.mjs'; export { default as DhpDualityRoll } from './dualityRoll.mjs';
export { default as DhpAdversaryRoll } from './adversaryRoll.mjs'; export { default as DhpAdversaryRoll } from './adversaryRoll.mjs';
export { default as DhpDamageRoll } from './damageRoll.mjs';
export { default as DhpAbilityUse } from './abilityUse.mjs'; export { default as DhpAbilityUse } from './abilityUse.mjs';
export { default as DhpEnvironment } from './environment.mjs'; export { default as DhpEnvironment } from './environment.mjs';

View file

@ -35,20 +35,20 @@ export default class DhpAdversary extends foundry.abstract.TypeDataModel {
}), }),
difficulty: new fields.NumberField({ initial: 1, integer: true }), difficulty: new fields.NumberField({ initial: 1, integer: true }),
damageThresholds: new fields.SchemaField({ damageThresholds: new fields.SchemaField({
minor: new fields.NumberField({ initial: 0, integer: true }),
major: new fields.NumberField({ initial: 0, integer: true }), major: new fields.NumberField({ initial: 0, integer: true }),
severe: new fields.NumberField({ initial: 0, integer: true }) severe: new fields.NumberField({ initial: 0, integer: true })
}), }),
experiences: new fields.ArrayField( experiences: new fields.TypedObjectField(
new fields.SchemaField({ new fields.SchemaField({
name: new fields.StringField({}), id: new fields.StringField({ required: true }),
name: new fields.StringField(),
value: new fields.NumberField({ integer: true, nullable: true, initial: null }) value: new fields.NumberField({ integer: true, nullable: true, initial: null })
}) })
) )
}; };
} }
get moves() { get features() {
return this.parent.items.filter(x => x.type === 'feature'); return this.parent.items.filter(x => x.type === 'feature');
} }
} }

View file

@ -3,6 +3,7 @@ export default class DhpAdversaryRoll extends foundry.abstract.TypeDataModel {
const fields = foundry.data.fields; const fields = foundry.data.fields;
return { return {
origin: new fields.StringField({ required: true }),
roll: new fields.StringField({}), roll: new fields.StringField({}),
total: new fields.NumberField({ integer: true }), total: new fields.NumberField({ integer: true }),
modifiers: new fields.ArrayField( modifiers: new fields.ArrayField(
@ -12,12 +13,8 @@ export default class DhpAdversaryRoll extends foundry.abstract.TypeDataModel {
title: new fields.StringField({}) title: new fields.StringField({})
}) })
), ),
diceResults: new fields.ArrayField( advantageState: new fields.NumberField({ required: true, choices: [0, 1, 2], initial: 0 }),
new fields.SchemaField({ dice: new fields.EmbeddedDataField(DhpAdversaryRollDice),
value: new fields.NumberField({ integer: true }),
discarded: new fields.BooleanField({ initial: false })
})
),
targets: new fields.ArrayField( targets: new fields.ArrayField(
new fields.SchemaField({ new fields.SchemaField({
id: new fields.StringField({}), id: new fields.StringField({}),
@ -39,17 +36,17 @@ export default class DhpAdversaryRoll extends foundry.abstract.TypeDataModel {
} }
prepareDerivedData() { prepareDerivedData() {
const diceKeys = Object.keys(this.diceResults); const diceKeys = Object.keys(this.dice.rolls);
const highestIndex = 0; const highestIndex = 0;
for (var index in diceKeys) { for (var index in diceKeys) {
const resultIndex = Number.parseInt(index); const resultIndex = Number.parseInt(index);
if (highestIndex === resultIndex) continue; if (highestIndex === resultIndex) continue;
const current = this.diceResults[resultIndex]; const current = this.dice.rolls[resultIndex];
const highest = this.diceResults[highestIndex]; const highest = this.dice.rolls[highestIndex];
if (current.value > highest.value) this.diceResults[highestIndex].discarded = true; if (current.value > highest.value) this.dice.rolls[highestIndex].discarded = true;
else this.diceResults[resultIndex].discarded = true; else this.dice.rolls[resultIndex].discarded = true;
} }
this.targets.forEach(target => { this.targets.forEach(target => {
@ -57,3 +54,23 @@ export default class DhpAdversaryRoll extends foundry.abstract.TypeDataModel {
}); });
} }
} }
class DhpAdversaryRollDice extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
type: new fields.StringField({ required: true }),
rolls: new fields.ArrayField(
new fields.SchemaField({
value: new fields.NumberField({ required: true, integer: true }),
discarded: new fields.BooleanField({ initial: false })
})
)
};
}
get rollTotal() {
return this.rolls.reduce((acc, roll) => acc + roll.value, 0);
}
}

View file

@ -0,0 +1,42 @@
export default class DhpDamageRoll extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
roll: new fields.StringField({ required: true }),
damage: new fields.SchemaField({
total: new fields.NumberField({ required: true, integer: true }),
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false })
}),
dice: new fields.ArrayField(new fields.EmbeddedDataField(DhpDamageDice)),
modifiers: new fields.ArrayField(
new fields.SchemaField({
value: new fields.NumberField({ required: true, integer: true }),
operator: new fields.StringField({ required: true, choices: ['+', '-', '*', '/'] })
})
),
targets: new fields.ArrayField(
new fields.SchemaField({
id: new fields.StringField({ required: true }),
name: new fields.StringField(),
img: new fields.StringField()
})
)
};
}
}
class DhpDamageDice extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
type: new fields.StringField({ required: true }),
rolls: new fields.ArrayField(new fields.NumberField({ required: true, integer: true }))
};
}
get rollTotal() {
return this.rolls.reduce((acc, roll) => acc + roll, 0);
}
}

View file

@ -68,7 +68,6 @@ export default class DhpActor extends Actor {
} }
async npcRoll(modifier, shiftKey) { async npcRoll(modifier, shiftKey) {
let nrDice = 1;
let advantage = null; let advantage = null;
const modifiers = [ const modifiers = [
@ -84,7 +83,6 @@ export default class DhpActor extends Actor {
}); });
const result = await dialogClosed; const result = await dialogClosed;
nrDice = result.nrDice;
advantage = result.advantage; advantage = result.advantage;
result.experiences.forEach(x => result.experiences.forEach(x =>
modifiers.push({ modifiers.push({
@ -95,13 +93,20 @@ export default class DhpActor extends Actor {
); );
} }
const roll = new Roll( const roll = Roll.create(
`${nrDice}d20${advantage === true ? 'kh' : advantage === false ? 'kl' : ''} ${modifiers.map(x => `+ ${x.value}`).join(' ')}` `${advantage === true || advantage === false ? 2 : 1}d20${advantage === true ? 'kh' : advantage === false ? 'kl' : ''} ${modifiers.map(x => `+ ${x.value}`).join(' ')}`
); );
let rollResult = await roll.evaluate(); let rollResult = await roll.evaluate();
const diceResults = rollResult.dice.flatMap(x => x.results.flatMap(result => ({ value: result.result }))); const dice = [];
for (var i = 0; i < rollResult.terms.length; i++) {
const term = rollResult.terms[i];
if (term.faces) {
dice.push({ type: `d${term.faces}`, rolls: term.results.map(x => ({ value: x.result })) });
}
}
return { roll, diceResults: diceResults, modifiers: modifiers }; // There is Only ever one dice term here
return { roll, dice: dice[0], modifiers, advantageState: advantage === true ? 1 : advantage === false ? 2 : 0 };
} }
async dualityRoll(modifier, shiftKey, bonusDamage = []) { async dualityRoll(modifier, shiftKey, bonusDamage = []) {
@ -245,14 +250,12 @@ export default class DhpActor extends Actor {
}; };
} }
async damageRoll(damage, shiftKey) { async damageRoll(damage, targets, shiftKey) {
let rollString = damage.value; let rollString = damage.value;
let bonusDamage = damage.bonusDamage?.filter(x => x.initiallySelected) ?? []; let bonusDamage = damage.bonusDamage?.filter(x => x.initiallySelected) ?? [];
if (!shiftKey) { if (!shiftKey) {
const dialogClosed = new Promise((resolve, _) => { const dialogClosed = new Promise((resolve, _) => {
new DamageSelectionDialog(rollString, bonusDamage, this.system.resources.hope.value, resolve).render( new DamageSelectionDialog(rollString, bonusDamage, resolve).render(true);
true
);
}); });
const result = await dialogClosed; const result = await dialogClosed;
bonusDamage = result.bonusDamage; bonusDamage = result.bonusDamage;
@ -274,23 +277,30 @@ export default class DhpActor extends Actor {
for (var i = 0; i < rollResult.terms.length; i++) { for (var i = 0; i < rollResult.terms.length; i++) {
const term = rollResult.terms[i]; const term = rollResult.terms[i];
if (term.faces) { if (term.faces) {
dice.push({ type: `d${term.faces}`, value: term.total }); dice.push({ type: `d${term.faces}`, rolls: term.results.map(x => x.result) });
} else if (term.operator) { } else if (term.operator) {
} else if (term.number) { } else if (term.number) {
const operator = i === 0 ? '' : rollResult.terms[i - 1].operator; const operator = i === 0 ? '' : rollResult.terms[i - 1].operator;
modifiers.push(`${operator}${term.number}`); modifiers.push({ value: term.number, operator: operator });
} }
} }
const cls = getDocumentClass('ChatMessage'); const cls = getDocumentClass('ChatMessage');
const msg = new cls({ const msg = new cls({
type: 'damageRoll',
user: game.user.id, user: game.user.id,
content: await renderTemplate('systems/daggerheart/templates/chat/damage-roll.hbs', { sound: CONFIG.sounds.dice,
system: {
roll: rollString, roll: rollString,
total: rollResult.total, damage: {
total: rollResult.total,
type: damage.type
},
dice: dice, dice: dice,
modifiers: modifiers modifiers: modifiers,
}), targets: targets
},
content: 'systems/daggerheart/templates/chat/damage-roll.hbs',
rolls: [roll] rolls: [roll]
}); });

View file

@ -17,16 +17,21 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
html.querySelectorAll('.roll-damage-button').forEach(element => html.querySelectorAll('.roll-damage-button').forEach(element =>
element.addEventListener('click', event => this.onRollDamage(event, data.message)) element.addEventListener('click', event => this.onRollDamage(event, data.message))
); );
html.querySelectorAll('.target-container').forEach(element => html.querySelectorAll('.target-container').forEach(element => {
element.addEventListener('hover', hover(this.hoverTarget, this.unhoverTarget)) element.addEventListener('mouseenter', this.hoverTarget);
); // ???? element.addEventListener('mouseleave', this.unhoverTarget);
// html.find('.target-container').mouseout(this.unhoverTarget); element.addEventListener('click', this.clickTarget);
html.querySelectorAll('.damage-button').forEach(element => element.addEventListener('click', this.onDamage)); });
html.querySelectorAll('.damage-button').forEach(element =>
element.addEventListener('click', event => this.onDamage(event, data.message))
);
html.querySelectorAll('.healing-button').forEach(element => element.addEventListener('click', this.onHealing)); html.querySelectorAll('.healing-button').forEach(element => element.addEventListener('click', this.onHealing));
html.querySelectorAll('.target-indicator').forEach(element => html.querySelectorAll('.target-indicator').forEach(element =>
element.addEventListener('click', this.onToggleTargets) element.addEventListener('click', this.onToggleTargets)
); );
html.querySelectorAll('.advantage').forEach(element => element.hover(this.hoverAdvantage)); // ?? html.querySelectorAll('.advantage').forEach(element =>
element.addEventListener('mouseenter', this.hoverAdvantage)
);
html.querySelectorAll('.advantage').forEach(element => html.querySelectorAll('.advantage').forEach(element =>
element.addEventListener('click', event => this.selectAdvantage.bind(this)(event, data.message)) element.addEventListener('click', event => this.selectAdvantage.bind(this)(event, data.message))
); );
@ -46,31 +51,49 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
onRollDamage = async (event, message) => { onRollDamage = async (event, message) => {
event.stopPropagation(); event.stopPropagation();
const actor = game.actors.get(message.system.origin);
if (!actor || !game.user.isGM) return true;
await game.user.character.damageRoll(message.system.damage, event.shiftKey); await actor.damageRoll(
message.system.damage,
message.system.targets.filter(x => x.hit).map(x => ({ id: x.id, name: x.name, img: x.img })),
event.shiftKey
);
}; };
hoverTarget = event => { hoverTarget = event => {
event.stopPropagation(); event.stopPropagation();
const token = canvas.tokens.get(event.currentTarget.dataset.token); const token = canvas.tokens.get(event.currentTarget.dataset.token);
if (!token.controlled) token._onHoverIn(event, { hoverOutOthers: true }); if (!token?.controlled) token._onHoverIn(event, { hoverOutOthers: true });
}; };
unhoverTarget = event => { unhoverTarget = event => {
const token = canvas.tokens.get(event.currentTarget.dataset.token); const token = canvas.tokens.get(event.currentTarget.dataset.token);
if (!token.controlled) token._onHoverOut(event); if (!token?.controlled) token._onHoverOut(event);
}; };
onDamage = async event => { clickTarget = event => {
event.stopPropagation(); event.stopPropagation();
const damage = Number.parseInt(event.currentTarget.dataset.value); const token = canvas.tokens.get(event.currentTarget.dataset.token);
const targets = Array.from(game.user.targets); if (!token) {
ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.AttackTargetDoesNotExist'));
return;
}
game.canvas.pan(token);
};
onDamage = async (event, message) => {
event.stopPropagation();
const targets = event.currentTarget.dataset.targetHit
? message.system.targets.map(target => game.canvas.tokens.get(target.id))
: Array.from(game.user.targets);
if (targets.length === 0) if (targets.length === 0)
ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.NoTargetsSelected')); ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.NoTargetsSelected'));
for (var target of targets) { for (var target of targets) {
await target.actor.takeDamage(damage, event.currentTarget.dataset.type); await target.actor.takeDamage(message.system.damage.total, message.system.damage.type);
} }
}; };

View file

@ -296,6 +296,7 @@ div.daggerheart.views.multiclass {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: @fullMargin; margin-bottom: @fullMargin;
gap: 16px;
.dice-container { .dice-container {
display: flex; display: flex;
@ -306,6 +307,7 @@ div.daggerheart.views.multiclass {
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center;
i { i {
font-size: 18px; font-size: 18px;
@ -319,12 +321,24 @@ div.daggerheart.views.multiclass {
.dice-number { .dice-number {
position: absolute; position: absolute;
top: calc(50% - 14px);
left: calc(50% - 7px);
font-size: 24px; font-size: 24px;
font-weight: bold; font-weight: bold;
} }
} }
.advantage-container {
display: flex;
flex-direction: column;
gap: 2px;
flex: 1;
.advantage-button {
&.active,
&:hover {
background: var(--button-hover-background-color);
}
}
}
} }
} }
@ -333,33 +347,19 @@ div.daggerheart.views.multiclass {
align-items: flex-start; align-items: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
gap: @halfMargin; gap: @halfMargin;
flex: 2; flex: 1;
height: 100%; height: 100%;
.roll-dialog-chip { .experience-chip {
border: @thinBorder solid black; opacity: 0.6;
border-radius: 6px; border-radius: 16px;
flex-basis: calc(50% - 2px); width: calc(50% - 4px);
display: flex; white-space: nowrap;
align-items: center;
justify-content: space-between;
cursor: pointer;
padding: @fullPadding;
background: grey;
overflow: hidden;
&.hover { &.active,
filter: drop-shadow(0 0 3px @mainShadow); &:hover {
} opacity: 1;
background: var(--button-hover-background-color);
span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&.selected i {
color: green;
} }
} }
} }

View file

@ -30,7 +30,7 @@
&.roll { &.roll {
.dice-tooltip { .dice-tooltip {
.dice-rolls { .dice-rolls.duality {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-around; justify-content: space-around;
@ -93,6 +93,11 @@
font-size: 16px; font-size: 16px;
} }
} }
.attack-roll-advantage-container {
text-align: end;
font-weight: bold;
}
} }
.dice-total { .dice-total {
@ -159,8 +164,20 @@
} }
} }
.roll-damage-button { .dice-actions {
margin-top: 5px; display: flex;
gap: 4px;
button {
flex: 1;
}
}
.dice-result {
.roll-damage-button,
.damage-button {
margin-top: 5px;
}
} }
} }

View file

@ -1760,55 +1760,59 @@
.daggerheart.chat.downtime .downtime-refresh-container .refresh-title { .daggerheart.chat.downtime .downtime-refresh-container .refresh-title {
font-weight: bold; font-weight: bold;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-around; justify-content: space-around;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .dice-hope-container { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .dice-hope-container {
display: flex; display: flex;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .dice-hope-container .roll.die:not(:last-of-type) { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .dice-hope-container .roll.die:not(:last-of-type) {
margin-right: 8px; margin-right: 8px;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .modifiers-container { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .modifiers-container {
display: flex; display: flex;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .modifiers-container .modifier-value:not(:last-of-type) { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .modifiers-container .modifier-value:not(:last-of-type) {
margin-right: 8px; margin-right: 8px;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .roll.die.hope { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .roll.die.hope {
color: white; color: white;
-webkit-text-stroke-color: #008080; -webkit-text-stroke-color: #008080;
-webkit-text-stroke-width: 1.5px; -webkit-text-stroke-width: 1.5px;
font-weight: 400; font-weight: 400;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .roll.die.fear { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .roll.die.fear {
color: white; color: white;
-webkit-text-stroke-color: #430070; -webkit-text-stroke-color: #430070;
-webkit-text-stroke-width: 1.5px; -webkit-text-stroke-width: 1.5px;
font-weight: 400; font-weight: 400;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .roll.die.disadvantage { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .roll.die.disadvantage {
color: white; color: white;
-webkit-text-stroke-color: #b30000; -webkit-text-stroke-color: #b30000;
-webkit-text-stroke-width: 1.5px; -webkit-text-stroke-width: 1.5px;
font-weight: 400; font-weight: 400;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .roll.die.advantage { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .roll.die.advantage {
color: white; color: white;
-webkit-text-stroke-color: green; -webkit-text-stroke-color: green;
-webkit-text-stroke-width: 1.5px; -webkit-text-stroke-width: 1.5px;
font-weight: 400; font-weight: 400;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .roll.die.unused { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .roll.die.unused {
opacity: 0.3; opacity: 0.3;
} }
.daggerheart.chat.roll .dice-tooltip .dice-rolls .modifier-value { .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .modifier-value {
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
font-size: 16px; font-size: 16px;
} }
.daggerheart.chat.roll .dice-tooltip .attack-roll-advantage-container {
text-align: end;
font-weight: bold;
}
.daggerheart.chat.roll .dice-total .dice-total-value .hope { .daggerheart.chat.roll .dice-total .dice-total-value .hope {
color: #008080; color: #008080;
} }
@ -1859,7 +1863,15 @@
justify-content: center; justify-content: center;
margin-right: 32px; margin-right: 32px;
} }
.daggerheart.chat.roll .roll-damage-button { .daggerheart.chat.roll .dice-actions {
display: flex;
gap: 4px;
}
.daggerheart.chat.roll .dice-actions button {
flex: 1;
}
.daggerheart.chat.roll .dice-result .roll-damage-button,
.daggerheart.chat.roll .dice-result .damage-button {
margin-top: 5px; margin-top: 5px;
} }
.daggerheart.chat.domain-card { .daggerheart.chat.domain-card {
@ -2227,6 +2239,7 @@ div.daggerheart.views.multiclass {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 8px; margin-bottom: 8px;
gap: 16px;
} }
.daggerheart.views.npc-roll-selection .npc-roll-dialog-container .selection-container .dice-container { .daggerheart.views.npc-roll-selection .npc-roll-dialog-container .selection-container .dice-container {
display: flex; display: flex;
@ -2241,6 +2254,7 @@ div.daggerheart.views.multiclass {
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center;
} }
.daggerheart.views.npc-roll-selection .daggerheart.views.npc-roll-selection
.npc-roll-dialog-container .npc-roll-dialog-container
@ -2267,52 +2281,57 @@ div.daggerheart.views.multiclass {
.dice-inner-container .dice-inner-container
.dice-number { .dice-number {
position: absolute; position: absolute;
top: calc(50% - 14px);
left: calc(50% - 7px);
font-size: 24px; font-size: 24px;
font-weight: bold; font-weight: bold;
} }
.daggerheart.views.npc-roll-selection
.npc-roll-dialog-container
.selection-container
.dice-container
.advantage-container {
display: flex;
flex-direction: column;
gap: 2px;
flex: 1;
}
.daggerheart.views.npc-roll-selection
.npc-roll-dialog-container
.selection-container
.dice-container
.advantage-container
.advantage-button.active,
.daggerheart.views.npc-roll-selection
.npc-roll-dialog-container
.selection-container
.dice-container
.advantage-container
.advantage-button:hover {
background: var(--button-hover-background-color);
}
.daggerheart.views.npc-roll-selection .npc-roll-dialog-container .roll-dialog-experience-container { .daggerheart.views.npc-roll-selection .npc-roll-dialog-container .roll-dialog-experience-container {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
gap: 4px; gap: 4px;
flex: 2; flex: 1;
height: 100%; height: 100%;
} }
.daggerheart.views.npc-roll-selection .npc-roll-dialog-container .roll-dialog-experience-container .roll-dialog-chip { .daggerheart.views.npc-roll-selection .npc-roll-dialog-container .roll-dialog-experience-container .experience-chip {
border: 1px solid black; opacity: 0.6;
border-radius: 6px; border-radius: 16px;
flex-basis: calc(50% - 2px); width: calc(50% - 4px);
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
padding: 4px;
background: grey;
overflow: hidden;
}
.daggerheart.views.npc-roll-selection
.npc-roll-dialog-container
.roll-dialog-experience-container
.roll-dialog-chip.hover {
filter: drop-shadow(0 0 3px red);
}
.daggerheart.views.npc-roll-selection
.npc-roll-dialog-container
.roll-dialog-experience-container
.roll-dialog-chip
span {
overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis;
} }
.daggerheart.views.npc-roll-selection .daggerheart.views.npc-roll-selection
.npc-roll-dialog-container .npc-roll-dialog-container
.roll-dialog-experience-container .roll-dialog-experience-container
.roll-dialog-chip.selected .experience-chip.active,
i { .daggerheart.views.npc-roll-selection
color: green; .npc-roll-dialog-container
.roll-dialog-experience-container
.experience-chip:hover {
opacity: 1;
background: var(--button-hover-background-color);
} }
.daggerheart.views.multiclass .multiclass-container { .daggerheart.views.multiclass .multiclass-container {
margin-bottom: 16px; margin-bottom: 16px;

View file

@ -37,9 +37,10 @@
"combat": {} "combat": {}
}, },
"ChatMessage": { "ChatMessage": {
"types": ["dualityRoll", "adversaryRoll", "abilityUse"], "types": ["dualityRoll", "adversaryRoll", "damageRoll", "abilityUse"],
"dualityRoll": {}, "dualityRoll": {},
"adversaryRoll": {}, "adversaryRoll": {},
"damageRoll": {},
"abilityUse": {} "abilityUse": {}
} }
} }

View file

@ -1,20 +1,27 @@
<div class="dice-roll daggerheart chat roll"> <div class="dice-roll daggerheart chat roll" data-action="expandRoll">
<div class="dice-result"> <div class="dice-result">
<div class="dice-formula">{{roll}}</div> <div class="dice-formula">{{roll}}</div>
<div class="dice-tooltip"> <div class="dice-tooltip">
<ol class="dice-rolls"> <div class="wrapper">
<div class="dice-hope-container"> <section class="tooltip-part">
{{#each diceResults}} <div class="dice">
<li class="roll die d20 {{#if this.discarded}}discarded{{/if}}">{{this.value}}</li> <header class="part-header flexrow">
{{/each}} <span class="part-formula">{{this.dice.rolls.length}}{{this.dice.type}}</span>
</div> <span class="part-total">{{this.total}}</span>
<div class="modifiers-container"> </header>
{{#each modifiers}} <div class="flexrow">
<li class="modifier-value" data-value="{{this.value}}" title="{{this.title}}">{{this.label}}</li> <ol class="dice-rolls">
{{/each}} {{#each this.dice.rolls}}
</div> <li class="roll die {{../dice.type}} {{#if this.discarded}}discarded{{/if}} min">{{this.value}}</li>
</ol> {{/each}}
</ol>
<div class="attack-roll-advantage-container">{{#if (eq this.advantageState 1)}}{{localize "DAGGERHEART.General.Advantage.Full"}}{{/if}}{{#if (eq this.advantageState 2)}}{{localize "DAGGERHEART.General.Disadvantage.Full"}}{{/if}}</div>
</div>
</div>
</section>
</div>
</div> </div>
<div class="dice-total"> <div class="dice-total">
<div class="dice-total-value">{{total}}</div> <div class="dice-total-value">{{total}}</div>
</div> </div>
@ -30,6 +37,8 @@
{{/each}} {{/each}}
</div> </div>
{{/if}} {{/if}}
<button class="roll-damage-button" data-value="{{this.total.normal}}" data-damage="{{this.damage.value}}" data-damage-type="{{this.damage.type}}" {{#if this.damage.disabled}}disabled{{/if}}><span>Roll Damage</span></button> <div class="flexrow">
<button class="roll-damage-button" data-value="{{this.total.normal}}" data-damage="{{this.damage.value}}" data-damage-type="{{this.damage.type}}" {{#if this.damage.disabled}}disabled{{/if}}><span>Roll Damage</span></button>
</div>
</div> </div>
</div> </div>

View file

@ -1,19 +1,32 @@
<div class="dice-roll daggerheart chat roll"> <div class="dice-roll daggerheart chat roll" data-action="expandRoll">
<div class="dice-result"> <div class="dice-result">
<div class="dice-formula">{{this.roll}}</div> <div class="dice-formula">{{this.roll}}</div>
<div class="dice-tooltip"> <div class="dice-tooltip">
<ol class="dice-rolls"> <div class="wrapper">
{{#each dice}} <section class="tooltip-part">
<li class="roll die {{this.type}}">{{this.value}}</li> {{#each dice}}
{{/each}} <div class="dice">
{{#each modifiers}} <header class="part-header flexrow">
<li class="modifier-value">{{this}}</li> <span class="part-formula">{{this.rolls.length}}{{this.type}}</span>
{{/each}}
</ol> <span class="part-total">{{this.rollTotal}}</span>
</header>
<ol class="dice-rolls">
{{#each this.rolls}}
<li class="roll die {{../type}} min">{{this}}</li>
{{/each}}
</ol>
</div>
{{/each}}
</section>
</div>
</div> </div>
<div class="dice-total">{{this.total}}</div>
<div class="flexrow"> <div class="dice-total">{{this.damage.total}}</div>
<button class="damage-button" data-value="{{this.total}}" data-type="{{this.type}}"><span>{{localize "DAGGERHEART.Chat.DamageRoll.DealDamage"}}</span></button> <div class="dice-actions">
<button class="damage-button" data-target-hit="true" {{#if (eq this.targets.length 0)}}disabled{{/if}}>{{localize "DAGGERHEART.Chat.DamageRoll.DealDamageToTargets"}}</button>
<button class="damage-button">{{localize "DAGGERHEART.Chat.DamageRoll.DealDamage"}}</button>
</div> </div>
</div> </div>
</div> </div>

View file

@ -2,15 +2,15 @@
<div class="dice-result"> <div class="dice-result">
<div class="dice-formula">{{roll}}</div> <div class="dice-formula">{{roll}}</div>
<div class="dice-tooltip {{#if advantage.value}}expanded{{/if}}"> <div class="dice-tooltip {{#if advantage.value}}expanded{{/if}}">
<ol class="dice-rolls"> <ol class="dice-rolls duality">
<div class="dice-hope-container"> <div class="dice-hope-container">
<li id="hope" class="roll die {{hope.dice}} hope" title="{{localize "DAGGERHEART.General.Hope"}}">{{hope.value}}</li> <li id="hope" class="roll die {{hope.dice}} hope" title="{{localize "DAGGERHEART.General.Hope"}}">{{hope.value}}</li>
<li class="roll die {{fear.dice}} fear" title="{{localize "DAGGERHEART.General.Fear"}}">{{fear.value}}</li> <li class="roll die {{fear.dice}} fear" title="{{localize "DAGGERHEART.General.Fear"}}">{{fear.value}}</li>
{{#if advantage.value}} {{#if advantage.value}}
<li class="roll die {{advantage.dice}} advantage" title="{{localize "DAGGERHEART.General.Advantage"}}">{{ advantage.value}}</li> <li class="roll die {{advantage.dice}} advantage" title="{{localize "DAGGERHEART.General.Advantage.Full"}}">{{ advantage.value}}</li>
{{/if}} {{/if}}
{{#if disadvantage.value}} {{#if disadvantage.value}}
<li class="roll die {{disadvantage.dice}} disadvantage" title="{{localize "DAGGERHEART.General.Disadvantage"}}">{{disadvantage.value}}</li> <li class="roll die {{disadvantage.dice}} disadvantage" title="{{localize "DAGGERHEART.General.Disadvantage.Full"}}">{{disadvantage.value}}</li>
{{/if}} {{/if}}
</div> </div>
<div class="modifiers-container"> <div class="modifiers-container">

View file

@ -94,8 +94,6 @@
<div class="form-group"> <div class="form-group">
<label>{{localize "DAGGERHEART.Sheets.Adversary.DamageThresholds.Title"}}</label> <label>{{localize "DAGGERHEART.Sheets.Adversary.DamageThresholds.Title"}}</label>
<div class="form-fields adversary-damage-threshold-container"> <div class="form-fields adversary-damage-threshold-container">
<label>{{localize "DAGGERHEART.Sheets.Adversary.DamageThresholds.Minor"}}</label>
<input type="text" name="system.damageThresholds.minor" value="{{source.system.damageThresholds.minor}}" data-dtype="Number" />
<label>{{localize "DAGGERHEART.Sheets.Adversary.DamageThresholds.Major"}}</label> <label>{{localize "DAGGERHEART.Sheets.Adversary.DamageThresholds.Major"}}</label>
<input type="text" name="system.damageThresholds.major" value="{{source.system.damageThresholds.major}}" data-dtype="Number" /> <input type="text" name="system.damageThresholds.major" value="{{source.system.damageThresholds.major}}" data-dtype="Number" />
<label>{{localize "DAGGERHEART.Sheets.Adversary.DamageThresholds.Severe"}}</label> <label>{{localize "DAGGERHEART.Sheets.Adversary.DamageThresholds.Severe"}}</label>
@ -124,21 +122,21 @@
<div class="experience-chip"> <div class="experience-chip">
<input class="experience.value" type="text" name="system.experiences.{{index}}.name" value="{{experience.name}}" /> <input class="experience.value" type="text" name="system.experiences.{{index}}.name" value="{{experience.name}}" />
<input class="experience-value" type="text" name="system.experiences.{{index}}.value" value="{{experience.value}}" data-dtype="Number" /> <input class="experience-value" type="text" name="system.experiences.{{index}}.value" value="{{experience.value}}" data-dtype="Number" />
<button class="experience-button"><i data-action="removeExperience" data-experience="{{index}}" class="fa-solid fa-x"></i></button> <button class="experience-button" data-action="removeExperience" data-experience="{{experience.id}}"><i class="fa-solid fa-x"></i></button>
</div> </div>
{{/each}} {{/each}}
</div> </div>
<div class="adversary-moves-container"> <div class="adversary-moves-container">
<h2 class="moves-edit-container">{{localize "DAGGERHEART.Sheets.Adversary.Moves"}} <i class="fa-solid fa-plus" data-action="addMove"></i></h2> <h2 class="moves-edit-container">{{localize "DAGGERHEART.Sheets.Adversary.Features"}} <i class="fa-solid fa-plus" data-action="addMove"></i></h2>
{{#each this.data.moves as |move key|}} {{#each this.data.features as |feature key|}}
<div class="chip-container"> <div class="chip-container">
<div class="chip-inner-container"> <div class="chip-inner-container">
<img src="{{move.img}}" /> <img src="{{feature.img}}" />
<div class="move-title">{{move.name}}</div> <div class="move-title">{{feature.name}}</div>
</div> </div>
<div class="chip-inner-container"> <div class="chip-inner-container">
<button data-action="viewMove" data-move={{move.uuid}}><i class="fa-solid fa-fw fa-search"></i></button> <button data-action="viewMove" data-move={{feature.uuid}}><i class="fa-solid fa-fw fa-search"></i></button>
<button data-action="removeMove" data-move={{move.uuid}}><i class="fa-solid fa-trash"></i></button> <button data-action="removeMove" data-move={{feature.uuid}}><i class="fa-solid fa-trash"></i></button>
</div> </div>
</div> </div>
{{/each}} {{/each}}
@ -186,9 +184,6 @@
</div> </div>
<div class="statistic-section"> <div class="statistic-section">
<div class="statistic-row"> <div class="statistic-row">
<label class="statistic-title">{{localize "DAGGERHEART.Sheets.PC.Health.Minor"}}</label>
<span class="statistic-value">{{this.data.damageThresholds.minor}}</span>
<div class="vertical-separator" style="height: 16px; margin: 0 4px;"></div>
<label class="statistic-title">{{localize "DAGGERHEART.Sheets.PC.Health.Major"}}</label> <label class="statistic-title">{{localize "DAGGERHEART.Sheets.PC.Health.Major"}}</label>
<span class="statistic-value">{{this.data.damageThresholds.major}}</span> <span class="statistic-value">{{this.data.damageThresholds.major}}</span>
<div class="vertical-separator" style="height: 16px; margin: 0 4px;"></div> <div class="vertical-separator" style="height: 16px; margin: 0 4px;"></div>
@ -228,11 +223,11 @@
</div> --}} </div> --}}
</div> </div>
<div class="adversary-moves-container"> <div class="adversary-moves-container">
<div class="moves-title">{{localize "DAGGERHEART.Sheets.Adversary.Moves"}}</div> <div class="moves-title">{{localize "DAGGERHEART.Sheets.Adversary.Features"}}</div>
{{#each this.data.moves as |move index|}} {{#each this.data.features as |feature index|}}
<div class="move-container"> <div class="move-container">
<label class="moves-name">{{move.name}}</label> <label class="moves-name">{{feature.name}}</label>
<div class="move-description">{{{move.system.description}}}</div> <div class="move-description">{{{feature.system.description}}}</div>
</div> </div>
{{/each}} {{/each}}
</div> </div>

View file

@ -48,7 +48,7 @@
<textarea name="system.potentialAdversaries">{{source.system.potentialAdversaries}}</textarea> <textarea name="system.potentialAdversaries">{{source.system.potentialAdversaries}}</textarea>
</div> </div>
<div class="adversary-moves-container"> <div class="adversary-moves-container">
<h2 class="moves-edit-container">{{localize "DAGGERHEART.Sheets.Adversary.Moves"}} <i class="fa-solid fa-plus" data-action="addFeature"></i></h2> <h2 class="moves-edit-container">{{localize "DAGGERHEART.Sheets.Adversary.Features"}} <i class="fa-solid fa-plus" data-action="addFeature"></i></h2>
{{#each data.features as |feature key|}} {{#each data.features as |feature key|}}
<div class="chip-container"> <div class="chip-container">
<div class="chip-inner-container"> <div class="chip-inner-container">
@ -97,7 +97,7 @@
</div> </div>
</div> </div>
<div class="adversary-moves-container"> <div class="adversary-moves-container">
<div class="moves-title">{{localize "DAGGERHEART.Sheets.Adversary.Moves"}}</div> <div class="moves-title">{{localize "DAGGERHEART.Sheets.Adversary.Features"}}</div>
{{#each data.features as |feature index|}} {{#each data.features as |feature index|}}
<div class="move-container" data-action="useFeature" data-feature="{{feature.uuid}}" data-action-type="{{feature.system.actionType}}"> <div class="move-container" data-action="useFeature" data-feature="{{feature.uuid}}" data-action-type="{{feature.system.actionType}}">
<label class="moves-name">{{feature.name}} - {{feature.system.actionType}}</label> <label class="moves-name">{{feature.name}} - {{feature.system.actionType}}</label>

View file

@ -4,23 +4,20 @@
<div class="dice-container"> <div class="dice-container">
<div class="dice-inner-container"> <div class="dice-inner-container">
<img src="icons/svg/d20-grey.svg" /> <img src="icons/svg/d20-grey.svg" />
<div class="dice-number">{{this.nrDice}}</div> <div class="dice-number">d20</div>
</div> </div>
<div class="flexcol" style="margin-right: 4px;"> <div class="advantage-container">
<i class="fa-solid fa-chevron-up icon-button increase"></i> <button class="advantage-button {{#if this.advantage}}active{{/if}} advantage">{{localize "DAGGERHEART.General.Advantage.Full"}}</button>
<i class="fa-solid fa-chevron-down icon-button decrease"></i> <button class="advantage-button {{#if (eq this.advantage false)}}active{{/if}} disadvantage">{{localize "DAGGERHEART.General.Disadvantage.Full"}}</button>
</div>
<div class="flexcol">
<div class="icon-button {{#if this.advantage}}active{{/if}} advantage">Adv</div>
<div class="icon-button {{#if (eq this.advantage false)}}active{{/if}} disadvantage">Dis</div>
</div> </div>
</div> </div>
<div class="roll-dialog-experience-container"> <div class="roll-dialog-experience-container">
{{#each this.experiences as |experience key|}} {{#each this.experiences as |experience|}}
<div class="roll-dialog-chip {{#if experience.selected}}selected{{/if}}" data-action="selectExperience" data-key="{{key}}"> <button class="experience-chip {{#if experience.selected}}active{{/if}}" data-action="selectExperience" id="{{id}}">{{experience.name}} {{experience.value}}</button>
{{!-- <div class="roll-dialog-chip {{#if experience.selected}}selected{{/if}}" data-action="selectExperience" data-key="{{key}}">
<span>{{experience.name}}</span> <span>{{experience.name}}</span>
<i class="fa-solid fa-circle-check"></i> <i class="fa-solid fa-circle-check"></i>
</div> </div> --}}
{{/each}} {{/each}}
</div> </div>
</div> </div>