Merge branch 'main' into iss4-attach-items

This commit is contained in:
psitacus 2025-07-12 12:14:24 -06:00
commit 78cb5677cd
48 changed files with 307 additions and 170 deletions

View file

@ -678,6 +678,10 @@
"name": "Dice Set"
}
},
"SelectAction": {
"selectType": "Select Action Type",
"selectAction": "Select Action"
},
"Traits": {
"agility": {
"name": "Agility",
@ -988,6 +992,11 @@
"minor": "Minor",
"none": "None"
},
"DamageResistance": {
"none": "None",
"resistance": "Resistance",
"immunity": "Immunity"
},
"DamageThresholds": {
"title": "Damage Thresholds",
"minor": "Minor",

View file

@ -11,7 +11,7 @@ export default class CostSelectionDialog extends HandlebarsApplicationMixin(Appl
static DEFAULT_OPTIONS = {
tag: 'form',
classes: ['daggerheart', 'views', 'damage-selection'],
classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'damage-selection'],
position: {
width: 400,
height: 'auto'

View file

@ -11,11 +11,14 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
static DEFAULT_OPTIONS = {
tag: 'form',
id: 'roll-selection',
classes: ['daggerheart', 'views', 'damage-selection'],
classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'damage-selection'],
position: {
width: 400,
height: 'auto'
},
window: {
icon: 'fa-solid fa-dice'
},
actions: {
submitRoll: this.submitRoll
},
@ -34,9 +37,15 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
}
};
get title() {
return game.i18n.localize('DAGGERHEART.EFFECTS.ApplyLocations.damageRoll.name');
}
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
context.title = this.config.title;
context.title = this.config.title
? this.config.title
: game.i18n.localize('DAGGERHEART.EFFECTS.ApplyLocations.damageRoll.name');
context.extraFormula = this.config.extraFormula;
context.formula = this.roll.constructFormula(this.config);
return context;

View file

@ -11,7 +11,7 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
this.actor = actor;
this.damage = damage;
const canApplyArmor = actor.system.armorApplicableDamageTypes[damageType];
const canApplyArmor = damageType.every(t => actor.system.armorApplicableDamageTypes[t] === true);
const maxArmorMarks = canApplyArmor
? Math.min(
actor.system.armorScore - actor.system.armor.system.marks.value,

View file

@ -23,7 +23,7 @@ export default class DamageSelectionDialog extends HandlebarsApplicationMixin(Ap
static DEFAULT_OPTIONS = {
tag: 'form',
classes: ['daggerheart', 'views', 'damage-selection'],
classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'damage-selection'],
position: {
width: 400,
height: 'auto'

View file

@ -56,10 +56,6 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
id: 'effect',
template: 'systems/daggerheart/templates/sheets-settings/action-settings/effect.hbs'
}
/* form: {
id: 'action',
template: 'systems/daggerheart/templates/config/action.hbs'
} */
};
static TABS = {
@ -161,7 +157,7 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
container = foundry.utils.getProperty(this.action.parent, this.action.systemPath);
let newActions;
if (Array.isArray(container)) {
newActions = foundry.utils.getProperty(this.action.parent, this.action.systemPath).map(x => x.toObject()); // Find better way
newActions = foundry.utils.getProperty(this.action.parent, this.action.systemPath).map(x => x.toObject());
if (!newActions.findSplice(x => x._id === data._id, data)) newActions.push(data);
} else newActions = data;

View file

@ -61,12 +61,17 @@ export default class FeatureSheet extends DHBaseItemSheet {
static async selectActionType() {
const content = await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/actionTypes/actionType.hbs',
{ types: CONFIG.DH.ACTIONS.actionTypes }
{
types: CONFIG.DH.ACTIONS.actionTypes,
itemName: game.i18n.localize('DAGGERHEART.CONFIG.SelectAction.selectType')
}
),
title = 'Select Action Type';
title = game.i18n.localize('DAGGERHEART.CONFIG.SelectAction.selectType');
console.log(this.document);
return foundry.applications.api.DialogV2.prompt({
window: { title },
classes: ['daggerheart', 'dh-style'],
content,
ok: {
label: title,

View file

@ -215,7 +215,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
if (message.system.onSave && message.system.targets.find(t => t.id === target.id)?.saved?.success === true)
damage = Math.ceil(damage * (CONFIG.DH.ACTIONS.damageOnSave[message.system.onSave]?.mod ?? 1));
target.actor.takeDamage(damage, message.system.roll.type);
target.actor.takeDamage(damage, message.system.damage.damageType);
}
};

View file

@ -59,13 +59,13 @@ export const damageTypes = {
id: 'physical',
label: 'DAGGERHEART.CONFIG.DamageType.physical.name',
abbreviation: 'DAGGERHEART.CONFIG.DamageType.physical.abbreviation',
icon: ['fa-hand-fist']
icon: 'fa-hand-fist'
},
magical: {
id: 'magical',
label: 'DAGGERHEART.CONFIG.DamageType.magical.name',
abbreviation: 'DAGGERHEART.CONFIG.DamageType.magical.abbreviation',
icon: ['fa-wand-sparkles']
icon: 'fa-wand-sparkles'
}
};

View file

@ -395,7 +395,7 @@ export const armorFeatures = {
img: 'icons/magic/defensive/barrier-shield-dome-pink.webp',
changes: [
{
key: 'system.bonuses.damageReduction.magical',
key: 'system.resistance.magical.reduction',
mode: 2,
value: '@system.armorScore'
}

View file

@ -76,11 +76,7 @@ export class DHActionDiceData extends foundry.abstract.DataModel {
};
}
getFormula(actor) {
/* const multiplier = this.multiplier === 'flat' ? this.flatMultiplier : actor.system[this.multiplier]?.total;
return this.custom.enabled
? this.custom.formula
: `${multiplier ?? 1}${this.dice}${this.bonus ? (this.bonus < 0 ? ` - ${Math.abs(this.bonus)}` : ` + ${this.bonus}`) : ''}`; */
getFormula() {
const multiplier = this.multiplier === 'flat' ? this.flatMultiplier : `@${this.multiplier}`,
bonus = this.bonus ? (this.bonus < 0 ? ` - ${Math.abs(this.bonus)}` : ` + ${this.bonus}`) : '';
return this.custom.enabled ? this.custom.formula : `${multiplier ?? 1}${this.dice}${bonus}`;
@ -93,7 +89,6 @@ export class DHDamageField extends fields.SchemaField {
parts: new fields.ArrayField(new fields.EmbeddedDataField(DHDamageData)),
includeBase: new fields.BooleanField({ initial: false })
};
// if (hasBase) damageFields.includeBase = new fields.BooleanField({ initial: true });
super(damageFields, options, context);
}
}
@ -102,15 +97,19 @@ export class DHDamageData extends foundry.abstract.DataModel {
/** @override */
static defineSchema() {
return {
// ...super.defineSchema(),
base: new fields.BooleanField({ initial: false, readonly: true, label: 'Base' }),
type: new fields.StringField({
choices: CONFIG.DH.GENERAL.damageTypes,
initial: 'physical',
label: 'Type',
nullable: false,
required: true
}),
type: new fields.SetField(
new fields.StringField({
choices: CONFIG.DH.GENERAL.damageTypes,
initial: 'physical',
nullable: false,
required: true
}),
{
label: 'Type',
initial: 'physical',
}
),
resultBased: new fields.BooleanField({
initial: false,
label: 'DAGGERHEART.ACTIONS.Settings.resultBased.label'

View file

@ -179,16 +179,9 @@ export default class DHBaseAction extends foundry.abstract.DataModel {
getRollData(data = {}) {
const actorData = this.actor.getRollData(false);
// Remove when included directly in Actor getRollData
actorData.prof = actorData.proficiency?.total ?? 1;
actorData.cast = actorData.spellcast?.total ?? 1;
// Add Roll results to RollDatas
actorData.result = data.roll?.total ?? 1;
/* actorData.scale = data.costs?.length
? data.costs.reduce((a, c) => {
a[c.type] = c.value;
return a;
}, {})
: 1; */
actorData.scale = data.costs?.length // Right now only return the first scalable cost.
? (data.costs.find(c => c.scalable)?.total ?? 1)
: 1;

View file

@ -10,7 +10,10 @@ export default class DHDamageAction extends DHBaseAction {
}
async rollDamage(event, data) {
let formula = this.damage.parts.map(p => this.getFormulaValue(p, data).getFormula(this.actor)).join(' + ');
let formula = this.damage.parts.map(p => this.getFormulaValue(p, data).getFormula(this.actor)).join(' + '),
damageTypes = [...new Set(this.damage.parts.reduce((a,c) => a.concat([...c.type]), []))];
damageTypes = !damageTypes.length ? ['physical'] : damageTypes;
if (!formula || formula == '') return;
let roll = { formula: formula, total: formula },
@ -25,6 +28,7 @@ export default class DHDamageAction extends DHBaseAction {
hasSave: this.hasSave,
isCritical: data.system?.roll?.isCritical ?? false,
source: data.system?.source,
damageTypes,
event
};
if (this.hasSave) config.onSave = this.save.damageMod;
@ -32,7 +36,7 @@ export default class DHDamageAction extends DHBaseAction {
config.source.message = data._id;
config.directDamage = false;
}
roll = CONFIG.Dice.daggerheart.DamageRoll.build(config);
}
}

View file

@ -5,6 +5,7 @@ import BaseDataActor from './base.mjs';
const resourceField = () =>
new foundry.data.fields.SchemaField({
value: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
bonus: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
max: new foundry.data.fields.NumberField({ initial: 0, integer: true })
});
@ -22,6 +23,7 @@ export default class DhpAdversary extends BaseDataActor {
static defineSchema() {
const fields = foundry.data.fields;
return {
...super.defineSchema(),
tier: new fields.StringField({
required: true,
choices: CONFIG.DH.GENERAL.tiers,
@ -32,7 +34,6 @@ export default class DhpAdversary extends BaseDataActor {
choices: CONFIG.DH.ACTOR.adversaryTypes,
initial: CONFIG.DH.ACTOR.adversaryTypes.standard.id
}),
description: new fields.StringField(),
motivesAndTactics: new fields.StringField(),
notes: new fields.HTMLField(),
difficulty: new fields.NumberField({ required: true, initial: 1, integer: true }),
@ -63,6 +64,7 @@ export default class DhpAdversary extends BaseDataActor {
damage: {
parts: [
{
type: ['physical'],
value: {
multiplier: 'flat'
}
@ -93,4 +95,9 @@ export default class DhpAdversary extends BaseDataActor {
get features() {
return this.parent.items.filter(x => x.type === 'feature');
}
prepareDerivedData() {
this.resources.hitPoints.maxTotal = this.resources.hitPoints.max + this.resources.hitPoints.bonus;
this.resources.stress.maxTotal = this.resources.stress.max + this.resources.stress.bonus;
}
}

View file

@ -1,5 +1,12 @@
import DHBaseActorSettings from "../../applications/sheets/api/actor-setting.mjs";
const resistanceField = () =>
new foundry.data.fields.SchemaField({
resistance: new foundry.data.fields.BooleanField({ initial: false }),
immunity: new foundry.data.fields.BooleanField({ initial: false }),
reduction: new foundry.data.fields.NumberField({ integer: true, initial: 0 })
});
/**
* Describes metadata about the actor data model type
* @typedef {Object} ActorDataModelMetadata
@ -16,6 +23,7 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
type: 'base',
isNPC: true,
settingSheet: null,
hasResistances: true
};
}
@ -27,10 +35,16 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
/** @inheritDoc */
static defineSchema() {
const fields = foundry.data.fields;
const schema = {};
return {
description: new fields.HTMLField({ required: true, nullable: true })
};
if(this.metadata.isNPC)
schema.description = new fields.HTMLField({ required: true, nullable: true });
if(this.metadata.hasResistances)
schema.resistance = new fields.SchemaField({
physical: resistanceField(),
magical: resistanceField()
})
return schema;
}
/**

View file

@ -36,6 +36,7 @@ export default class DhCharacter extends BaseDataActor {
const fields = foundry.data.fields;
return {
...super.defineSchema(),
resources: new fields.SchemaField({
hitPoints: new fields.SchemaField({
value: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
@ -100,10 +101,6 @@ export default class DhCharacter extends BaseDataActor {
levelData: new fields.EmbeddedDataField(DhLevelData),
bonuses: new fields.SchemaField({
armorScore: new fields.NumberField({ integer: true, initial: 0 }),
damageReduction: new fields.SchemaField({
physical: new fields.NumberField({ integer: true, initial: 0 }),
magical: new fields.NumberField({ integer: true, initial: 0 })
}),
damageThresholds: new fields.SchemaField({
severe: new fields.NumberField({ integer: true, initial: 0 }),
major: new fields.NumberField({ integer: true, initial: 0 })

View file

@ -20,6 +20,7 @@ export default class DhCompanion extends BaseDataActor {
const fields = foundry.data.fields;
return {
...super.defineSchema(),
partner: new ForeignDocumentUUIDField({ type: 'Actor' }),
resources: new fields.SchemaField({
stress: new fields.SchemaField({
@ -66,6 +67,7 @@ export default class DhCompanion extends BaseDataActor {
damage: {
parts: [
{
type: ['physical'],
value: {
dice: 'd6',
multiplier: 'prof'

View file

@ -9,20 +9,21 @@ export default class DhEnvironment extends BaseDataActor {
return foundry.utils.mergeObject(super.metadata, {
label: 'TYPES.Actor.environment',
type: 'environment',
settingSheet: DHEnvironmentSettings
settingSheet: DHEnvironmentSettings,
hasResistances: false
});
}
static defineSchema() {
const fields = foundry.data.fields;
return {
...super.defineSchema(),
tier: new fields.StringField({
required: true,
choices: CONFIG.DH.GENERAL.tiers,
initial: CONFIG.DH.GENERAL.tiers.tier1.id
}),
type: new fields.StringField({ choices: CONFIG.DH.ACTOR.environmentTypes }),
description: new fields.StringField(),
impulses: new fields.StringField(),
difficulty: new fields.NumberField({ required: true, initial: 11, integer: true }),
potentialAdversaries: new fields.TypedObjectField(

View file

@ -56,6 +56,7 @@ export default class DHWeapon extends AttachableItem {
damage: {
parts: [
{
type: ['physical'],
value: {
multiplier: 'prof',
dice: 'd8'

View file

@ -14,6 +14,10 @@ export default class DamageRoll extends DHRoll {
super.postEvaluate(roll, config);
config.roll.type = config.type;
config.roll.modifierTotal = this.calculateTotalModifiers(roll);
}
static async buildPost(roll, config, message) {
await super.buildPost(roll, config, message);
if (config.source?.message) {
const chatMessage = ui.chat.collection.get(config.source.message);
chatMessage.update({ 'system.damage': config });

View file

@ -56,8 +56,8 @@ export default class DHRoll extends Roll {
// Create Chat Message
if (config.source?.message) {
if(game.modules.get('dice-so-nice')?.active) await game.dice3d.showForRoll(roll, game.user, true);
} else {
const messageData = {};
config.message = await this.toMessage(roll, config);
}
}

View file

@ -370,7 +370,10 @@ export default class DhpActor extends Actor {
}
getRollData() {
return this.system;
const rollData = super.getRollData();
rollData.prof = this.system.proficiency?.total ?? 1;
rollData.cast = this.system.spellcast?.total ?? 1;
return rollData;
}
formatRollModifier(roll) {
@ -462,7 +465,7 @@ export default class DhpActor extends Actor {
const canUseArmor =
this.system.armor &&
this.system.armor.system.marks.value < this.system.armorScore &&
this.system.armorApplicableDamageTypes[type];
type.every(t => this.system.armorApplicableDamageTypes[t] === true);
const canUseStress = Object.keys(this.system.rules.damageReduction.stressDamageReduction).reduce((acc, x) => {
const rule = this.system.rules.damageReduction.stressDamageReduction[x];
if (damageKeyToNumber(x) <= hpDamage) return acc || (rule.enabled && availableStress >= rule.cost);
@ -480,11 +483,9 @@ export default class DhpActor extends Actor {
return;
}
const flatReduction = this.system.bonuses.damageReduction[type];
const damage = Math.max(baseDamage - (flatReduction ?? 0), 0);
const hpDamage = this.convertDamageToThreshold(damage);
type = !Array.isArray(type) ? [type] : type;
if (Hooks.call(`${CONFIG.DH.id}.postDamageTreshold`, this, hpDamage, damage, type) === false) return null;
const hpDamage = this.calculateDamage(baseDamage, type);
if (!hpDamage) return;
@ -511,6 +512,35 @@ export default class DhpActor extends Actor {
if (Hooks.call(`${CONFIG.DH.id}.postTakeDamage`, this, damage, type) === false) return null;
}
calculateDamage(baseDamage, type) {
if (Hooks.call(`${CONFIG.DH.id}.preCalculateDamage`, this, baseDamage, type) === false) return null;
/* if(this.system.resistance[type]?.immunity) return 0;
if(this.system.resistance[type]?.resistance) baseDamage = Math.ceil(baseDamage / 2); */
if(this.canResist(type, 'immunity')) return 0;
if(this.canResist(type, 'resistance')) baseDamage = Math.ceil(baseDamage / 2);
// const flatReduction = this.system.resistance[type].reduction;
const flatReduction = this.getDamageTypeReduction(type);
const damage = Math.max(baseDamage - (flatReduction ?? 0), 0);
const hpDamage = this.convertDamageToThreshold(damage);
if (Hooks.call(`${CONFIG.DH.id}.postCalculateDamage`, this, baseDamage, type) === false) return null;
return hpDamage;
}
canResist(type, resistance) {
if(!type) return 0;
return type.every(t => this.system.resistance[t]?.[resistance] === true);
}
getDamageTypeReduction(type) {
if(!type) return 0;
const reduction = Object.entries(this.system.resistance).reduce((a, [index, value]) => type.includes(index) ? Math.min(value.reduction, a) : a, Infinity);
return reduction === Infinity ? 0 : reduction;
}
async takeHealing(resources) {
resources.forEach(r => (r.value *= -1));
await this.modifyResource(resources);
@ -553,18 +583,6 @@ export default class DhpActor extends Actor {
u.resources,
u.target.uuid
);
/* if (game.user.isGM) {
await u.target.update(u.resources);
} else {
await game.socket.emit(`system.${CONFIG.DH.id}`, {
action: socketEvent.GMUpdate,
data: {
action: GMUpdateEvent.UpdateDocument,
uuid: u.target.uuid,
update: u.resources
}
});
} */
}
});
}

View file

@ -80,12 +80,16 @@ export default class DHItem extends foundry.documents.Item {
async selectActionDialog(prevEvent) {
const content = await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/dialogs/actionSelect.hbs',
{ actions: this.system.actionsList }
{
actions: this.system.actionsList,
itemName: this.name
}
),
title = 'Select Action';
title = game.i18n.localize('DAGGERHEART.CONFIG.SelectAction.selectAction');
return foundry.applications.api.DialogV2.prompt({
window: { title },
classes: ['daggerheart', 'dh-style'],
content,
ok: {
label: title,

View file

@ -236,16 +236,7 @@ Roll.replaceFormulaData = function (formula, data = {}, { missing, warn = false
};
export const getDamageKey = damage => {
switch (damage) {
case 3:
return 'severe';
case 2:
return 'major';
case 1:
return 'minor';
case 0:
return 'none';
}
return ['none', 'minor', 'major', 'severe'][damage];
};
export const getDamageLabel = damage => {
@ -253,16 +244,12 @@ export const getDamageLabel = damage => {
};
export const damageKeyToNumber = key => {
switch (key) {
case 'severe':
return 3;
case 'major':
return 2;
case 'minor':
return 1;
case 'none':
return 0;
}
return {
'none': 0,
'minor': 1,
'major': 2,
'severe': 3
}[key];
};
export default function constructHTMLButton({

View file

@ -0,0 +1,19 @@
@import '../../utils/fonts.less';
.application.daggerheart.dh-style {
.actions-list {
display: flex;
flex-direction: column;
gap: 10px;
.action-item {
display: flex;
align-items: center;
gap: 5px;
.label {
font-family: @font-body;
}
}
}
}

View file

@ -0,0 +1,20 @@
@import '../../utils/colors.less';
.daggerheart.dialog.dh-style.views.damage-selection {
.damage-section-container {
display: flex;
flex-direction: column;
gap: 12px;
input[type='text'],
input[type='number'] {
color: light-dark(@dark, @beige);
outline: 2px solid transparent;
transition: all 0.3s ease;
&:hover {
outline: 2px solid light-dark(@dark, @beige);
}
}
}
}

View file

@ -114,15 +114,5 @@
}
}
}
.formula-label {
font-family: @font-body;
font-style: normal;
font-weight: 500;
font-size: 14px;
line-height: 17px;
color: light-dark(@dark, @beige);
}
}
}

View file

@ -4,6 +4,10 @@
@import './level-up/summary-container.less';
@import './level-up/tiers-container.less';
@import './actions/action-list.less';
@import './damage-selection/sheet.less';
@import './downtime/downtime-container.less';
@import './beastform/beastform-container.less';

View file

@ -1,5 +1,6 @@
@import '../utils/colors.less';
@import '../utils/fonts.less';
@import '../utils/mixin.less';
.appTheme({
&.dialog {
@ -40,4 +41,19 @@
}
}
}
.submit-btn {
width: 100%;
height: 38px;
}
.formula-label {
font-family: @font-body;
font-style: normal;
font-weight: 500;
font-size: 14px;
line-height: 17px;
color: light-dark(@dark, @beige);
}
}

View file

@ -35,15 +35,16 @@
}
}
input[type='checkbox'] {
input[type='checkbox'],
input[type='radio'] {
&:checked::after {
color: light-dark(@dark, @golden);
color: light-dark(@dark-40, @golden);
}
&:checked::before {
color: light-dark(transparent, @dark-blue);
color: light-dark(@dark-40, @golden-40);
}
&::before {
color: light-dark(@dark, @beige);
color: light-dark(@dark-40, @golden-40);
}
}
@ -103,6 +104,40 @@
}
}
multi-select {
position: relative;
height: 34px;
.tags {
justify-content: flex-start;
margin: 5px;
height: inherit;
.tag {
box-shadow: 0 0 0 1.1em #E5E5E5 inset;
vertical-align: top;
box-sizing: border-box;
max-width: 100%;
padding: 0.3em 0 0.3em 0.5em;
color: black;
border-radius: 3px;
white-space: nowrap;
transition: .13s ease-out;
height: 22px;
font-size: .9rem;
gap: 0.5em;
z-index: 1;
.remove {
font-size: 10px;
margin-inline: auto 4.6666666667px;
}
}
}
select {
position: absolute;
height: inherit;
outline: initial;
}
}
p {
margin: 0;
}

View file

@ -4,8 +4,8 @@
// Theme handling
.appTheme({
background: @semi-transparent-dark-blue;
backdrop-filter: blur(9px);
background: @dark-blue-60;
backdrop-filter: blur(10px);
}, {
background: url('../assets/parchments/dh-parchment-light.png') no-repeat center;
});
@ -44,6 +44,8 @@
top: -36px;
min-height: -webkit-fill-available;
transition: opacity 0.3s ease;
padding-bottom: 20px;
margin-bottom: -36px;
.tab {
padding: 0 10px;

View file

@ -5,6 +5,7 @@
.tab.experiences {
.add-experience-btn {
width: 100%;
height: 38px;
margin-bottom: 12px;
}

View file

@ -10,6 +10,7 @@
.add-feature-btn {
width: 100%;
height: 38px;
margin-bottom: 12px;
}

View file

@ -10,6 +10,7 @@
.add-action-btn {
width: 100%;
height: 38px;
margin-bottom: 12px;
}

View file

@ -10,6 +10,7 @@
.add-feature-btn {
width: 100%;
height: 38px;
margin-bottom: 12px;
}

View file

@ -9,6 +9,7 @@
gap: 15px 0;
height: 100%;
width: 100%;
padding-bottom: 0;
.adversary-sidebar-sheet {
grid-row: 1 / span 2;

View file

@ -110,10 +110,11 @@
justify-content: space-evenly;
.status-bar {
display: flex;
justify-content: center;
position: relative;
width: 100px;
height: 40px;
justify-items: center;
.status-label {
position: relative;

View file

@ -9,6 +9,7 @@
gap: 15px 0;
height: 100%;
width: 100%;
padding-bottom: 0;
overflow: auto;
.character-sidebar-sheet {

View file

@ -70,10 +70,11 @@
justify-content: space-evenly;
.status-bar {
display: flex;
justify-content: center;
position: relative;
width: 100px;
height: 40px;
justify-items: center;
.status-label {
position: relative;

View file

@ -45,7 +45,9 @@
justify-content: center;
.status-number {
justify-items: center;
display: flex;
flex-direction: column;
align-items: center;
.status-value {
position: relative;
@ -85,6 +87,8 @@
}
.status-bar {
display: flex;
justify-content: center;
position: relative;
width: 100px;
height: 40px;

View file

@ -25,10 +25,12 @@
@dark-blue-10: #18162e10;
@dark-blue-40: #18162e40;
@dark-blue-50: #18162e50;
@dark-blue-60: #18162e60;
@semi-transparent-dark-blue: rgba(24, 22, 46, 0.33);
@dark: #222;
@dark-15: #22222215;
@dark-40: #22222240;
@deep-black: #0e0d15;

View file

@ -1,13 +1,12 @@
<form id="action-type-select">
<ul class="unlist list-select">
<header class="dialog-header">
<h1>{{itemName}}</h1>
</header>
<ul class="actions-list">
{{#each types}}
<li>
<label>
{{! TODO: remove dh-icon}}
<dh-icon class="dh-icon fas {{icon}}"></dh-icon>
<span>{{localize name}}</span>
<input type="radio" name="type" value="{{id}}" {{#if (eq @index 0)}}checked{{/if}}>
</label>
<li class="action-item">
<input type="radio" name="type" value="{{id}}" {{#if (eq @index 0)}}checked{{/if}}>
<span class="label">{{localize name}}</span>
</li>
{{/each}}
</ul>

View file

@ -46,7 +46,7 @@
{{> formula fields=../../fields.value.fields type=../fields.type dmg=dmg source=dmg.value target="value" realIndex=realIndex}}
</fieldset>
{{/if}}
{{formField ../../fields.type value=dmg.type name=(concat "damage.parts." realIndex ".type") localize=true}}
{{formField ../../fields.type value=dmg.type name=(concat "damage.parts." realIndex ".type") localize=true}}
<input type="hidden" name="damage.parts.{{realIndex}}.base" value="{{dmg.base}}">
</fieldset>
{{#unless dmg.base}}<div class="fas fa-trash" data-action="removeDamage" data-index="{{realIndex}}"></div>{{/unless}}

View file

@ -1,12 +1,12 @@
<form id="item-action-select">
<ul class="unlist list-select">
<header class="dialog-header">
<h1>{{itemName}}</h1>
</header>
<ul class="actions-list">
{{#each actions}}
<li>
<label>
<dh-icon><img src="{{ img }}"></dh-icon>
<span>{{ name }}</span>
<input type="radio" name="actionId" value="{{_id}}" {{#if (eq @index 0)}}checked{{/if}}>
</label>
<li class="action-item">
<input type="radio" name="actionId" value="{{_id}}" {{#if (eq @index 0)}}checked{{/if}}>
<span class="label">{{ name }}</span>
</li>
{{/each}}
</ul>

View file

@ -1,33 +1,13 @@
<div>
<section class="damage-section-container">
<header class="dialog-header">
<h1>{{title}}</h1>
</header>
<span class="formula-label"><b>Formula:</b> {{@root.formula}}</span>
<div class="form-group">
<label><strong>{{title}}</strong></label>
<div class="form-fields">
{{!-- <input type="text" value="{{formula}}" disabled /> --}}
<div>{{@root.formula}}</div>
</div>
<div>
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="Situational Bonus">
</div>
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="Situational Bonus">
</div>
{{!-- {{#each bonusDamage as |damage index|}}
<div class="form-group">
<label><strong>{{damage.description}}</strong></label>
<div class="form-fields">
<label>Enabled</label>
<input style="align-self: baseline;" type="checkbox" name="bonusDamage.{{index}}.initiallySelected" {{checked damage.initiallySelected}} />
{{#if (and damage.initiallySelected damage.hopeIncrease)}}
<label>Hope</label>
<div class="hope-container">
<i data-action="decreaseHopeUse" data-index="{{index}}" class="fa-solid fa-caret-left icon-button {{#if (eq damage.hopeUses 0)}}disabled{{/if}}"></i>
<div>{{damage.hopeUses}}</div>
<i data-action="increaseHopeUse" data-index="{{index}}" class="fa-solid fa-caret-right icon-button {{#if (eq ../hopeUsed ../hope)}}disabled{{/if}}"></i>
</div>
{{/if}}
</div>
</div>
{{/each}} --}}
<footer>
<button data-action="submitRoll">Roll</button>
</footer>
</div>
<button class="submit-btn" data-action="submitRoll">
<i class="fa-solid fa-dice"></i>
<span class="label">Roll</span>
</button>
</section>

View file

@ -10,12 +10,12 @@
<div class='status-value'>
<p><input class="bar-input" name="system.resources.hitPoints.value" value="{{source.system.resources.hitPoints.value}}" type="number"></p>
<p>/</p>
<p class="bar-label">{{source.system.resources.hitPoints.max}}</p>
<p class="bar-label">{{source.system.resources.hitPoints.maxTotal}}</p>
</div>
<progress
class='progress-bar'
value='{{source.system.resources.hitPoints.value}}'
max='{{source.system.resources.hitPoints.max}}'
max='{{source.system.resources.hitPoints.maxTotal}}'
></progress>
<div class="status-label">
<h4>HP</h4>
@ -26,12 +26,12 @@
<div class='status-value'>
<p><input class="bar-input" name="system.resources.stress.value" value="{{source.system.resources.stress.value}}" type="number"></p>
<p>/</p>
<p class="bar-label">{{source.system.resources.stress.max}}</p>
<p class="bar-label">{{source.system.resources.stress.maxTotal}}</p>
</div>
<progress
class='progress-bar stress-color'
value='{{source.system.resources.stress.value}}'
max='{{source.system.resources.stress.max}}'
max='{{source.system.resources.stress.maxTotal}}'
></progress>
<div class="status-label">
<h4>Stress</h4>

View file

@ -6,7 +6,7 @@
{{else}}
<div class="item-name">{{item.name}}</div>
{{/if}}
{{#if (eq type 'weapon')}}
{{#if (eq type 'weapon')}}
<div class="item-tags">
{{#if isSidebar}}
<div class="item-labels">
@ -16,11 +16,11 @@
<span> - </span>
{{item.system.attack.damage.parts.0.value.dice}}{{#if item.system.attack.damage.parts.0.value.bonus}} + {{item.system.attack.damage.parts.0.value.bonus}}{{/if}}
{{!-- ({{localize (concat 'DAGGERHEART.CONFIG.DamageType.' item.system.attack.damage.parts.0.type '.abbreviation')}}) --}}
{{#with (lookup @root.config.GENERAL.damageTypes item.system.attack.damage.parts.0.type)}}
{{#each icon}}
<i class="fa-solid {{this}}"></i>
{{/each}}
{{/with}}
{{#each item.system.attack.damage.parts.0.type as | type | }}
{{#with (lookup @root.config.GENERAL.damageTypes type)}}
<i class="fa-solid {{icon}}"></i>
{{/with}}
{{/each}}
</div>
</div>
{{else}}
@ -32,7 +32,11 @@
</div>
<div class="tag">
{{item.system.attack.damage.parts.0.value.dice}}{{#if item.system.attack.damage.parts.0.value.bonus}} + {{item.system.attack.damage.parts.0.value.bonus}}{{/if}}
({{localize (concat 'DAGGERHEART.CONFIG.DamageType.' item.system.attack.damage.parts.0.type '.abbreviation')}})
(
{{#each item.system.attack.damage.parts.0.type}}
{{localize (concat 'DAGGERHEART.CONFIG.DamageType.' this '.abbreviation')}}
{{/each}}
)
</div>
<div class="tag">
{{localize (concat 'DAGGERHEART.CONFIG.Burden.' item.system.burden)}}

View file

@ -15,7 +15,11 @@
{{localize (concat 'DAGGERHEART.CONFIG.Range.' source.system.attack.range '.name')}}
<span>-</span>
{{source.system.attack.damage.parts.0.value.dice}}{{#if source.system.attack.damage.parts.0.value.bonus}} + {{source.system.attack.damage.parts.0.value.bonus}}{{/if}}
({{localize (concat 'DAGGERHEART.CONFIG.DamageType.' source.system.attack.damage.parts.0.type '.abbreviation')}})
(
{{#each source.system.attack.damage.parts.0.type}}
{{localize (concat 'DAGGERHEART.CONFIG.DamageType.' this '.abbreviation')}}
{{/each}}
)
<span>-</span>
{{localize (concat 'DAGGERHEART.CONFIG.Burden.' source.system.burden)}}
</h3>