Active Effects (#123)

* Added Dh classes to ActiveEffect/ActiveEffectConfig with some initial logic

* TabFormFooter styling update

* Lowered tab-form-footer padding
This commit is contained in:
WBHarry 2025-06-12 20:53:47 +02:00 committed by GitHub
parent 7799f4f1eb
commit bc3525c970
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 230 additions and 0 deletions

View file

@ -72,6 +72,16 @@ Hooks.once('init', () => {
Actors.registerSheet(SYSTEM.id, applications.DhpAdversarySheet, { types: ['adversary'], makeDefault: true });
Actors.registerSheet(SYSTEM.id, applications.DhpEnvironment, { types: ['environment'], makeDefault: true });
CONFIG.ActiveEffect.documentClass = documents.DhActiveEffect;
DocumentSheetConfig.unregisterSheet(
CONFIG.ActiveEffect.documentClass,
'core',
foundry.applications.sheets.ActiveEffectConfig
);
DocumentSheetConfig.registerSheet(CONFIG.ActiveEffect.documentClass, SYSTEM.id, applications.DhActiveEffectConfig, {
makeDefault: true
});
CONFIG.Combat.dataModels = {
base: models.DhCombat
};

View file

@ -12,3 +12,4 @@ export { default as DhpWeapon } from './sheets/items/weapon.mjs';
export { default as DhpArmor } from './sheets/items/armor.mjs';
export { default as DhpChatMessage } from './chatMessage.mjs';
export { default as DhpEnvironment } from './sheets/environment.mjs';
export { default as DhActiveEffectConfig } from './sheets/activeEffectConfig.mjs';

View file

@ -0,0 +1,62 @@
export default class DhActiveEffectConfig extends ActiveEffectConfig {
static DEFAULT_OPTIONS = {
classes: ['daggerheart', 'sheet', 'dh-style']
};
static PARTS = {
header: { template: 'systems/daggerheart/templates/sheets/activeEffect/header.hbs' },
tabs: { template: 'templates/generic/tab-navigation.hbs' },
details: { template: 'systems/daggerheart/templates/sheets/activeEffect/details.hbs', scrollable: [''] },
duration: { template: 'systems/daggerheart/templates/sheets/activeEffect/duration.hbs' },
changes: {
template: 'systems/daggerheart/templates/sheets/activeEffect/changes.hbs',
scrollable: ['ol[data-changes]']
},
footer: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-form-footer.hbs' }
};
static TABS = {
sheet: {
tabs: [
{ id: 'details', icon: 'fa-solid fa-book' },
{ id: 'duration', icon: 'fa-solid fa-clock' },
{ id: 'changes', icon: 'fa-solid fa-gears' }
],
initial: 'details',
labelPrefix: 'EFFECT.TABS'
}
};
async _preparePartContext(partId, context) {
const partContext = await super._preparePartContext(partId, context);
switch (partId) {
case 'changes':
const fieldPaths = [];
const validFieldPath = fieldPath => this.validFieldPath(fieldPath, this.#unapplicablePaths);
context.document.parent.system.schema.apply(function () {
if (!(this instanceof foundry.data.fields.SchemaField)) {
if (validFieldPath(this.fieldPath)) {
fieldPaths.push(this.fieldPath);
}
}
});
context.fieldPaths = fieldPaths;
break;
}
return partContext;
}
#unapplicablePaths = ['story', 'pronouns', 'description'];
validFieldPath(fieldPath, unapplicablePaths) {
const splitPath = fieldPath.split('.');
if (splitPath.length > 1 && unapplicablePaths.includes(splitPath[1])) return false;
/* The current value of a resource should not be modified */
if (new RegExp(/resources.*\.value/).exec(fieldPath)) return false;
return true;
}
}

View file

@ -1,3 +1,4 @@
export { default as DhpActor } from './actor.mjs';
export { default as DhpItem } from './item.mjs';
export { default as DhpCombat } from './combat.mjs';
export { default as DhActiveEffect } from './activeEffect.mjs';

View file

@ -0,0 +1,14 @@
export default class DhActiveEffect extends ActiveEffect {
async _preCreate(data, options, user) {
const update = {};
if (!data.img) {
update.img = 'icons/magic/life/heart-cross-blue.webp';
}
if (Object.keys(update).length > 0) {
await this.updateSource(update);
}
await super._preCreate(data, options, user);
}
}

View file

@ -2593,6 +2593,9 @@ div.daggerheart.views.multiclass {
width: 40px;
background: white;
}
.application.sheet.daggerheart.dh-style.active-effect-config label {
white-space: nowrap;
}
.daggerheart.sheet .title-container {
display: flex;
gap: 8px;
@ -3385,6 +3388,14 @@ div.daggerheart.views.multiclass {
font-weight: bold;
font-size: smaller;
}
.application.sheet.dh-style .two-columns {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 10px;
}
.application.sheet.dh-style .two-columns.even {
grid-template-columns: 1fr 1fr;
}
.application.sheet.dh-style line-div {
display: block;
height: 1px;
@ -3592,6 +3603,16 @@ div.daggerheart.views.multiclass {
text-shadow: none;
font-family: 'Montserrat', sans-serif;
}
.sheet.daggerheart.dh-style .tab-form-footer {
display: flex;
padding: 0 10px;
position: relative;
bottom: -32px;
}
.sheet.daggerheart.dh-style .tab-form-footer button {
flex: 1;
border-width: 2px;
}
.sheet.daggerheart.dh-style .tab.actions .actions-list {
display: flex;
flex-direction: column;

View file

@ -23,6 +23,7 @@
@import './less/global/sheet.less';
@import './less/global/elements.less';
@import './less/global/tab-navigation.less';
@import './less/global/tab-form-footer.less';
@import './less/global/tab-actions.less';
@import './less/global/item-header.less';
@import './less/global/feature-section.less';

View file

@ -143,6 +143,16 @@
}
}
.two-columns {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 10px;
&.even {
grid-template-columns: 1fr 1fr;
}
}
line-div {
display: block;
height: 1px;

View file

@ -0,0 +1,13 @@
.sheet.daggerheart.dh-style {
.tab-form-footer {
display: flex;
padding: 0 10px;
position: relative;
bottom: -32px;
button {
flex: 1;
border-width: 2px;
}
}
}

View file

@ -0,0 +1,5 @@
.application.sheet.daggerheart.dh-style.active-effect-config {
label {
white-space: nowrap;
}
}

View file

@ -1,6 +1,7 @@
@import './heritage.less';
@import './class.less';
@import './adversary.less';
@import './activeEffect.less';
.daggerheart.sheet {
.title-container {

View file

@ -0,0 +1,36 @@
<section class="tab changes{{#if tab.active}} active{{/if}}" data-group="{{tab.group}}" data-tab="{{tab.id}}">
<header>
<div class="key">{{localize "EFFECT.ChangeKey"}}</div>
<div class="mode">{{localize "EFFECT.ChangeMode"}}</div>
<div class="value">{{localize "EFFECT.ChangeValue"}}</div>
<div class="priority">{{localize "EFFECT.ChangePriority"}}</div>
<div class="controls"><a data-action="addChange"><i class="fa-regular fa-square-plus"></i></a></div>
</header>
<ol class="scrollable" data-changes>
{{#each source.changes as |change i|}}
{{#with ../fields.changes.element.fields as |changeFields|}}
<li data-index="{{i}}">
<div class="key">
<input type="text" name="{{concat "changes." i ".key"}}" value="{{change.key}}" list="change-fields" />
<datalist id="change-fields">
{{#each @root.fieldPaths}}
<option value="{{this}}">{{this}}</option>
{{/each}}
</datalist>
</div>
<div class="mode">
{{formInput changeFields.mode name=(concat "changes." i ".mode") value=change.mode choices=@root.modes}}
</div>
<div class="value">
{{formInput changeFields.value name=(concat "changes." i ".value") value=change.value}}
</div>
<div class="priority">
{{formInput changeFields.priority name=(concat "changes." i ".priority") value=change.priority
placeholder=(lookup ../../priorities change.mode)}}
</div>
<div class="controls"><a data-action="deleteChange"><i class="fa-solid fa-trash"></i></a></div>
</li>
{{/with}}
{{/each}}
</ol>
</section>

View file

@ -0,0 +1,14 @@
<section class="tab scrollable{{#if tab.active}} active{{/if}}" data-group="{{tab.group}}" data-tab="{{tab.id}}">
{{formGroup fields.tint value=source.tint rootId=rootId placeholder="#ffffff"}}
{{formGroup fields.description value=source.description rootId=rootId}}
{{formGroup fields.disabled value=source.disabled rootId=rootId}}
{{#if isActorEffect}}
{{formGroup fields.origin value=source.origin rootId=rootId disabled=true}}
{{/if}}
{{#if isItemEffect}}
{{formGroup fields.transfer value=source.transfer rootId=rootId label=legacyTransfer.label hint=legacyTransfer.hint}}
{{/if}}
{{formGroup fields.statuses value=source.statuses options=statuses rootId=rootId classes="statuses"}}
</section>

View file

@ -0,0 +1,31 @@
<section class="tab{{#if tab.active}} active{{/if}}" data-group="{{tab.group}}" data-tab="{{tab.id}}">
<fieldset class="one-column">
{{formGroup fields.duration.fields.seconds value=source.duration.seconds rootId=rootId}}
{{formGroup fields.duration.fields.startTime value=source.duration.startTime rootId=rootId}}
</fieldset>
<fieldset class="one-column">
<div class="form-group">
<label>{{localize "EFFECT.DurationTurns"}}</label>
<div class="form-fields">
<label for="{{rootId}}-duration.rounds">{{localize "EFFECT.FIELDS.duration.rounds.label"}}</label>
{{formInput fields.duration.fields.rounds value=source.duration.rounds
id=(concat rootId "-duration.rounds")}}
<label for="{{rootId}}-duration.turns">{{localize "EFFECT.FIELDS.duration.turns.label"}}</label>
{{formInput fields.duration.fields.turns value=source.duration.turns
id=(concat rootId "-duration.turns")}}
</div>
</div>
<div class="form-group">
<label>{{localize "EFFECT.StartTurns"}}</label>
<div class="form-fields">
<label for="{{rootId}}-duration.startRound">{{localize "EFFECT.FIELDS.duration.startRound.label"}}</label>
{{formInput fields.duration.fields.startRound value=source.duration.startRound
id=(concat rootId "-duration.startRound")}}
<label for="{{rootId}}-duration.startTurn">{{localize "EFFECT.FIELDS.duration.startTurn.label"}}</label>
{{formInput fields.duration.fields.startTurn value=source.duration.startTurn
id=(concat rootId "-duration.startTurn")}}
</div>
</div>
</fieldset>
</section>

View file

@ -0,0 +1,7 @@
<header class='item-sheet-header'>
<img class='profile' src="{{source.img}}" data-action="editImage" data-edit="img" alt="{{localize "EFFECT.FIELDS.img.label"}}">
<div class='item-info'>
<h1 class='item-name'><input name="name" type="text" value="{{source.name}}" placeholder="{{localize "EFFECT.FIELDS.name.label"}}"
aria-label="{{localize "EFFECT.FIELDS.name.label"}}"></h1>
</div>
</header>

View file

@ -0,0 +1,3 @@
<section class='tab-form-footer'>
<button type="submit"><i class="fa-solid fa-floppy-disk"></i> {{localize "Save"}}</button>
</section>