mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-18 16:09:03 +01:00
Added Character-Settings
This commit is contained in:
parent
798cf8c761
commit
8555b7a044
17 changed files with 258 additions and 58 deletions
|
|
@ -167,6 +167,10 @@
|
|||
"backgroundTitle": "Background",
|
||||
"characteristics": "Characteristics",
|
||||
"connectionsTitle": "Connections"
|
||||
},
|
||||
"experienceDataRemoveConfirmation": {
|
||||
"title": "Remove Experience Data",
|
||||
"text": "The experience you are about to remove has levelup data linked to it (assumably because you did levelups with the 'levelupAuto' automation setting on). Removing it will remove this automation data aswell. Do you want to proceed?"
|
||||
}
|
||||
},
|
||||
"Companion": {
|
||||
|
|
@ -1859,6 +1863,7 @@
|
|||
"levelUp": "Level Up",
|
||||
"loadout": "Loadout",
|
||||
"max": "Max",
|
||||
"maxWithThing": "Max {thing}",
|
||||
"multiclass": "Multiclass",
|
||||
"newCategory": "New Category",
|
||||
"none": "None",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
export { default as ActionConfig } from './action-config.mjs';
|
||||
export { default as CharacterSettings } from './character-settings.mjs';
|
||||
export { default as AdversarySettings } from './adversary-settings.mjs';
|
||||
export { default as CompanionSettings } from './companion-settings.mjs';
|
||||
export { default as DowntimeConfig } from './downtimeConfig.mjs';
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ export default class DHCharacterSettings extends DHBaseActorSettings {
|
|||
static DEFAULT_OPTIONS = {
|
||||
classes: ['character-settings'],
|
||||
position: { width: 455, height: 'auto' },
|
||||
actions: {},
|
||||
actions: {
|
||||
addExperience: DHCharacterSettings.#addExperience,
|
||||
removeExperience: DHCharacterSettings.#removeExperience
|
||||
},
|
||||
dragDrop: [
|
||||
{ dragSelector: null, dropSelector: '.tab.features' },
|
||||
{ dragSelector: '.feature-item', dropSelector: null }
|
||||
|
|
@ -18,33 +21,111 @@ export default class DHCharacterSettings extends DHBaseActorSettings {
|
|||
static PARTS = {
|
||||
header: {
|
||||
id: 'header',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/header.hbs'
|
||||
template: 'systems/daggerheart/templates/sheets-settings/character-settings/header.hbs'
|
||||
},
|
||||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||
details: {
|
||||
id: 'details',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/details.hbs'
|
||||
},
|
||||
attack: {
|
||||
id: 'attack',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/attack.hbs'
|
||||
template: 'systems/daggerheart/templates/sheets-settings/character-settings/details.hbs'
|
||||
},
|
||||
experiences: {
|
||||
id: 'experiences',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/experiences.hbs'
|
||||
},
|
||||
features: {
|
||||
id: 'features',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs'
|
||||
template: 'systems/daggerheart/templates/sheets-settings/character-settings/experiences.hbs'
|
||||
}
|
||||
};
|
||||
|
||||
/** @override */
|
||||
static TABS = {
|
||||
primary: {
|
||||
tabs: [{ id: 'details' }, { id: 'attack' }, { id: 'experiences' }, { id: 'features' }],
|
||||
tabs: [{ id: 'details' }, { id: 'experiences' }],
|
||||
initial: 'details',
|
||||
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
|
||||
}
|
||||
};
|
||||
|
||||
/**@inheritdoc */
|
||||
async _prepareContext(options) {
|
||||
const context = await super._prepareContext(options);
|
||||
context.levelupAuto = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Adds a new experience entry to the actor.
|
||||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #addExperience() {
|
||||
const newExperience = {
|
||||
name: 'Experience',
|
||||
modifier: 0
|
||||
};
|
||||
await this.actor.update({ [`system.experiences.${foundry.utils.randomID()}`]: newExperience });
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an experience entry from the actor.
|
||||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #removeExperience(_, target) {
|
||||
const experience = this.actor.system.experiences[target.dataset.experience];
|
||||
const updates = {};
|
||||
|
||||
const relinkData = Object.keys(this.actor.system.levelData.levelups).reduce((acc, key) => {
|
||||
const level = this.actor.system.levelData.levelups[key];
|
||||
const selectionIndex = level.selections.findIndex(
|
||||
x => x.optionKey === 'experience' && x.data[0] === target.dataset.experience
|
||||
);
|
||||
if (selectionIndex !== -1)
|
||||
acc.push({ levelKey: key, selectionIndex, experience: target.dataset.experience });
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
if (relinkData.length > 0) {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.localize('DAGGERHEART.ACTORS.Character.experienceDataRemoveConfirmation.title')
|
||||
},
|
||||
content: game.i18n.localize('DAGGERHEART.ACTORS.Character.experienceDataRemoveConfirmation.text')
|
||||
});
|
||||
if (!confirmed) return;
|
||||
|
||||
relinkData.forEach(data => {
|
||||
updates[`system.levelData.levelups.${data.levelKey}.selections`] = this.actor.system.levelData.levelups[
|
||||
data.levelKey
|
||||
].selections.reduce((acc, selection, index) => {
|
||||
if (
|
||||
index === data.selectionIndex &&
|
||||
selection.optionKey === 'experience' &&
|
||||
selection.data.includes(data.experience)
|
||||
) {
|
||||
acc.push({ ...selection, data: selection.data.filter(x => x !== data.experience) });
|
||||
} else {
|
||||
acc.push(selection);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
});
|
||||
} else {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.title', {
|
||||
type: game.i18n.localize(`DAGGERHEART.GENERAL.Experience.single`),
|
||||
name: experience.name
|
||||
})
|
||||
},
|
||||
content: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.text', { name: experience.name })
|
||||
});
|
||||
if (!confirmed) return;
|
||||
}
|
||||
|
||||
await this.actor.update({
|
||||
...updates,
|
||||
[`system.experiences.-=${target.dataset.experience}`]: null
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
toggleEquipItem: CharacterSheet.#toggleEquipItem,
|
||||
toggleResourceDice: CharacterSheet.#toggleResourceDice,
|
||||
handleResourceDice: CharacterSheet.#handleResourceDice,
|
||||
openConfig: CharacterSheet.#openConfig,
|
||||
useDowntime: this.useDowntime
|
||||
},
|
||||
window: {
|
||||
|
|
@ -717,20 +716,14 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the character config sheet.
|
||||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #openConfig() {}
|
||||
|
||||
/**
|
||||
* Open the downtime application.
|
||||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static useDowntime(_, button) {
|
||||
new game.system.api.applications.dialogs.Downtime(this.document, button.dataset.type === 'shortRest').render(
|
||||
true
|
||||
);
|
||||
new game.system.api.applications.dialogs.Downtime(this.document, button.dataset.type === 'shortRest').render({
|
||||
force: true
|
||||
});
|
||||
}
|
||||
|
||||
async _onDragStart(event) {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ export default class DhpAdversary extends BaseDataActor {
|
|||
experiences: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField(),
|
||||
value: new fields.NumberField({ required: true, integer: true, initial: 1 })
|
||||
value: new fields.NumberField({ required: true, integer: true, initial: 1 }),
|
||||
description: new fields.StringField()
|
||||
})
|
||||
),
|
||||
bonuses: new fields.SchemaField({
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import DhLevelData from '../levelData.mjs';
|
|||
import BaseDataActor from './base.mjs';
|
||||
import { attributeField, resourceField, stressDamageReductionRule, bonusField } from '../fields/actorField.mjs';
|
||||
import { ActionField } from '../fields/actionField.mjs';
|
||||
import DHCharacterSettings from '../../applications/sheets-configs/character-settings.mjs';
|
||||
|
||||
export default class DhCharacter extends BaseDataActor {
|
||||
static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Character'];
|
||||
|
|
@ -12,6 +13,7 @@ export default class DhCharacter extends BaseDataActor {
|
|||
return foundry.utils.mergeObject(super.metadata, {
|
||||
label: 'TYPES.Actor.character',
|
||||
type: 'character',
|
||||
settingSheet: DHCharacterSettings,
|
||||
isNPC: false
|
||||
});
|
||||
}
|
||||
|
|
@ -56,7 +58,8 @@ export default class DhCharacter extends BaseDataActor {
|
|||
experiences: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
name: new fields.StringField(),
|
||||
value: new fields.NumberField({ integer: true, initial: 0 })
|
||||
value: new fields.NumberField({ integer: true, initial: 0 }),
|
||||
description: new fields.StringField()
|
||||
})
|
||||
),
|
||||
gold: new fields.SchemaField({
|
||||
|
|
@ -538,9 +541,9 @@ export default class DhCharacter extends BaseDataActor {
|
|||
this.proficiency += selection.value;
|
||||
break;
|
||||
case 'experience':
|
||||
Object.keys(this.experiences).forEach(key => {
|
||||
const experience = this.experiences[key];
|
||||
experience.value += selection.value;
|
||||
selection.data.forEach(id => {
|
||||
const experience = this.experiences[id];
|
||||
if (experience) experience.value += selection.value;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
@ -568,7 +571,7 @@ export default class DhCharacter extends BaseDataActor {
|
|||
this.attack.roll.trait = this.rules.attack.roll.trait ?? this.attack.roll.trait;
|
||||
|
||||
this.resources.armor = {
|
||||
value: this.armor.system.marks.value,
|
||||
value: this.armor?.system?.marks?.value ?? 0,
|
||||
max: this.armorScore,
|
||||
isReversed: true
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,11 @@ const attributeField = label =>
|
|||
const resourceField = (max = 0, label, reverse = false) =>
|
||||
new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, min: 0, integer: true, label }),
|
||||
max: new fields.NumberField({ initial: max, integer: true }),
|
||||
max: new fields.NumberField({
|
||||
initial: max,
|
||||
integer: true,
|
||||
label: game.i18n.format('DAGGERHEART.GENERAL.maxWithThing', { thing: game.i18n.localize(label) })
|
||||
}),
|
||||
isReversed: new fields.BooleanField({ initial: reverse })
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -9,21 +9,30 @@
|
|||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.experience-list {
|
||||
.experience-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
gap: 5px;
|
||||
|
||||
.experience-item {
|
||||
.experience-inner-item {
|
||||
display: grid;
|
||||
grid-template-columns: 3fr 1fr 30px;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
|
||||
&.no-controls {
|
||||
grid-template-columns: 3fr 1fr;
|
||||
}
|
||||
|
||||
a {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
36
styles/less/sheets-settings/character-settings/sheet.less
Normal file
36
styles/less/sheets-settings/character-settings/sheet.less
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
.application.daggerheart.dh-style.dialog {
|
||||
.tab.details {
|
||||
.traits-inner-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
gap: 8px;
|
||||
|
||||
.trait-container {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: url(../assets/svg/trait-shield.svg) no-repeat;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
div {
|
||||
filter: drop-shadow(0 0 3px black);
|
||||
text-shadow: 0 0 3px black;
|
||||
font-family: @font-body;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
input {
|
||||
text-align: center;
|
||||
width: 32px;
|
||||
height: 24px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
@import './adversary-settings/sheet.less';
|
||||
@import './adversary-settings/experiences.less';
|
||||
@import './adversary-settings/features.less';
|
||||
@import './character-settings/sheet.less';
|
||||
|
||||
@import './environment-settings/features.less';
|
||||
@import './environment-settings/adversaries.less';
|
||||
|
|
|
|||
|
|
@ -12,9 +12,13 @@
|
|||
<ul class="experience-list">
|
||||
{{#each document.system.experiences as |experience key|}}
|
||||
<li class="experience-item">
|
||||
<input class="name" type="text" name="system.experiences.{{key}}.name" value="{{experience.name}}" />
|
||||
<input class="modifier" type="text" name="system.experiences.{{key}}.value" value="{{experience.value}}" data-dtype="Number" />
|
||||
<a data-action="removeExperience" data-experience="{{key}}" data-tooltip="{{localize 'CONTROLS.CommonDelete'}}"><i class="fa-solid fa-trash"></i></a>
|
||||
<div class="experience-inner-item">
|
||||
<input class="name" type="text" name="system.experiences.{{key}}.name" value="{{experience.name}}" />
|
||||
<input class="modifier" type="text" name="system.experiences.{{key}}.value" value="{{experience.value}}" data-dtype="Number" />
|
||||
<a data-action="removeExperience" data-experience="{{key}}" data-tooltip="{{localize 'CONTROLS.CommonDelete'}}"><i class="fa-solid fa-trash"></i></a>
|
||||
</div>
|
||||
|
||||
<textarea name="system.experiences.{{key}}.description">{{experience.description}}</textarea>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
|
|
|||
34
templates/sheets-settings/character-settings/details.hbs
Normal file
34
templates/sheets-settings/character-settings/details.hbs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<section
|
||||
class='tab {{tabs.details.cssClass}} {{tabs.details.id}}'
|
||||
data-tab='{{tabs.details.id}}'
|
||||
data-group='{{tabs.details.group}}'
|
||||
>
|
||||
<fieldset class="one-column">
|
||||
<legend>{{localize 'DAGGERHEART.GENERAL.Trait.plural'}}</legend>
|
||||
|
||||
<div class="nest-inputs">
|
||||
<div class="traits-inner-container">
|
||||
{{#each document.system.traits as | trait key |}}
|
||||
<div class="trait-container">
|
||||
<div>{{localize (concat "DAGGERHEART.CONFIG.Traits." key ".name" )}}</div>
|
||||
<input type="text" data-dtype="Number" name="{{concat "system.traits." key ".value"}}" value="{{trait.value}}" />
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="one-column">
|
||||
<legend>{{localize 'DAGGERHEART.GENERAL.basics'}}</legend>
|
||||
|
||||
<div class="two-columns even">
|
||||
{{formGroup systemFields.resources.fields.hitPoints.fields.value value=document.system.resources.hitPoints.value localize=true}}
|
||||
{{formGroup systemFields.resources.fields.hitPoints.fields.max value=document.system.resources.hitPoints.max localize=true}}
|
||||
|
||||
{{formGroup systemFields.resources.fields.stress.fields.value value=document.system.resources.stress.value localize=true}}
|
||||
{{formGroup systemFields.resources.fields.stress.fields.max value=document.system.resources.stress.max localize=true}}
|
||||
|
||||
{{formGroup systemFields.proficiency value=document.proficiency localize=true}}
|
||||
</div>
|
||||
</fieldset>
|
||||
</section>
|
||||
26
templates/sheets-settings/character-settings/experiences.hbs
Normal file
26
templates/sheets-settings/character-settings/experiences.hbs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<section
|
||||
class='tab {{tabs.experiences.cssClass}} {{tabs.experiences.id}}'
|
||||
data-tab='{{tabs.experiences.id}}'
|
||||
data-group='{{tabs.experiences.group}}'
|
||||
>
|
||||
<button type="button" class="add-experience-btn" type="button" data-action="addExperience">
|
||||
<span>{{localize "DOCUMENT.New" type=(localize "DAGGERHEART.GENERAL.experience.single")}}</span>
|
||||
</button>
|
||||
|
||||
<fieldset>
|
||||
<legend>{{localize tabs.experiences.label}}</legend>
|
||||
<ul class="experience-list">
|
||||
{{#each document.system.experiences as |experience key|}}
|
||||
<li class="experience-item">
|
||||
<div class="experience-inner-item {{#if @root.levelupAuto}}no-controls{{/if}}">
|
||||
<input class="name" type="text" name="system.experiences.{{key}}.name" value="{{experience.name}}" />
|
||||
<input class="modifier" type="text" name="system.experiences.{{key}}.value" value="{{experience.value}}" data-dtype="Number" />
|
||||
{{#unless @root.levelupAuto}}<a data-action="removeExperience" data-experience="{{key}}" data-tooltip="{{localize 'CONTROLS.CommonDelete'}}"><i class="fa-solid fa-trash"></i></a>{{/unless}}
|
||||
</div>
|
||||
|
||||
<textarea name="system.experiences.{{key}}.description">{{experience.description}}</textarea>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
</section>
|
||||
3
templates/sheets-settings/character-settings/header.hbs
Normal file
3
templates/sheets-settings/character-settings/header.hbs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<header class="dialog-header">
|
||||
<h1>{{document.name}}</h1>
|
||||
</header>
|
||||
|
|
@ -97,17 +97,17 @@
|
|||
</div>
|
||||
<div class="experience-list">
|
||||
{{#each source.system.experiences as |experience id|}}
|
||||
<div class="experience-row">
|
||||
<div class="experience-value">
|
||||
+{{experience.value}}
|
||||
<div class="experience-row" data-tooltip-text="{{experience.description}}">
|
||||
<div class="experience-value">
|
||||
+{{experience.value}}
|
||||
</div>
|
||||
<span class="experience-name">{{experience.name}}</span>
|
||||
<div class="controls">
|
||||
<a data-action="sendExpToChat" data-id="{{id}}">
|
||||
<i class="fa-regular fa-message"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<span class="experience-name">{{experience.name}}</span>
|
||||
<div class="controls">
|
||||
<a data-action="sendExpToChat" data-id="{{id}}">
|
||||
<i class="fa-regular fa-message"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
<div class='level-div'>
|
||||
<h3 class='label'>
|
||||
<button data-action="openConfig">Temp</button>
|
||||
<button data-action="openSettings">Temp</button>
|
||||
{{#if (or document.system.needsCharacterSetup document.system.levelData.canLevelUp)}}
|
||||
<button
|
||||
type="button"
|
||||
|
|
|
|||
|
|
@ -142,18 +142,17 @@
|
|||
</div>
|
||||
<div class="experience-list">
|
||||
{{#each document.system.experiences as |experience id|}}
|
||||
<div class="experience-row">
|
||||
<div class="experience-value">
|
||||
+{{experience.value}}
|
||||
<div class="experience-row" data-tooltip-text="{{experience.description}}">
|
||||
<div class="experience-value">
|
||||
+{{experience.value}}
|
||||
</div>
|
||||
<div>{{experience.name}}</div>
|
||||
<div class="controls">
|
||||
<a data-action="sendExpToChat" data-type="experience" data-id="{{id}}">
|
||||
<i class="fa-regular fa-message"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<input name="system.experiences.{{id}}.name" data-experience={{id}}
|
||||
value="{{experience.name}}" type="text" />
|
||||
<div class="controls">
|
||||
<a data-action="sendExpToChat" data-type="experience" data-id="{{id}}">
|
||||
<i class="fa-regular fa-message"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue