finish actions setting tab

This commit is contained in:
moliloo 2025-07-01 00:42:34 -03:00
parent 3b159d7c0c
commit f48459114a
23 changed files with 365 additions and 175 deletions

View file

@ -227,14 +227,15 @@
"details": "Details",
"attack": "Attack",
"experiences": "Experiences",
"features": "Features"
"features": "Features",
"actions": "Actions"
},
"basics": "Basics"
},
"ActionType": {
"Passive": "Passive",
"Action": "Action",
"Reaction": "Reaction"
"passive": "Passive",
"action": "Action",
"reaction": "Reaction"
},
"Abilities": {
"agility": {
@ -1530,6 +1531,7 @@
"sendToChat": "Send to Chat",
"moreOptions": "More Options",
"equip": "Equip",
"edit": "Edit",
"unequip": "Unequip",
"delete": "Delete",
"sendToVault": "Send to Vault",
@ -1537,29 +1539,29 @@
},
"Actions": {
"Types": {
"Attack": {
"Name": "Attack"
"attack": {
"name": "Attack"
},
"Spellcast": {
"Name": "Spellcast"
"spellcast": {
"name": "Spellcast"
},
"Resource": {
"Name": "Resource"
"resource": {
"name": "Resource"
},
"Damage": {
"Name": "Damage"
"damage": {
"name": "Damage"
},
"Healing": {
"Name": "Healing"
"healing": {
"name": "Healing"
},
"Summon": {
"Name": "Summon"
"summon": {
"name": "Summon"
},
"Effect": {
"Name": "Effect"
"effect": {
"name": "Effect"
},
"Macro": {
"Name": "Macro"
"macro": {
"name": "Macro"
}
},
"Settings": {

View file

@ -28,19 +28,19 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
static PARTS = {
sidebar: { template: 'systems/daggerheart/templates/sheets/actors/adversary/sidebar.hbs' },
header: { template: 'systems/daggerheart/templates/sheets/actors/adversary/header.hbs' },
features: { template: 'systems/daggerheart/templates/sheets/actors/adversary/features.hbs' },
actions: { template: 'systems/daggerheart/templates/sheets/actors/adversary/actions.hbs' },
notes: { template: 'systems/daggerheart/templates/sheets/actors/adversary/notes.hbs' },
effects: { template: 'systems/daggerheart/templates/sheets/actors/adversary/effects.hbs' }
};
static TABS = {
features: {
actions: {
active: true,
cssClass: '',
group: 'primary',
id: 'features',
id: 'actions',
icon: null,
label: 'DAGGERHEART.Sheets.Adversary.Tabs.features'
label: 'DAGGERHEART.General.tabs.actions'
},
notes: {
active: false,

View file

@ -1,5 +1,7 @@
import DHActionConfig from '../../config/Action.mjs';
import DaggerheartSheet from '../daggerheart-sheet.mjs';
import DHBaseItemSheet from '../api/base-item.mjs';
import { actionsTypes } from '../../../data/_module.mjs';
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
@ -24,8 +26,11 @@ export default class DHAdversarySettings extends HandlebarsApplicationMixin(Appl
},
position: { width: 455, height: 'auto' },
actions: {
addExperience: this.addExperience,
removeExperience: this.removeExperience
addExperience: this.#addExperience,
removeExperience: this.#removeExperience,
addAction: this.#addAction,
editAction: this.#editAction,
removeAction: this.#removeAction
},
form: {
handler: this.updateForm,
@ -52,9 +57,9 @@ export default class DHAdversarySettings extends HandlebarsApplicationMixin(Appl
id: 'experiences',
template: 'systems/daggerheart/templates/sheets/applications/adversary-settings/experiences.hbs'
},
features: {
id: 'features',
template: 'systems/daggerheart/templates/sheets/applications/adversary-settings/features.hbs'
actions: {
id: 'actions',
template: 'systems/daggerheart/templates/sheets/applications/adversary-settings/actions.hbs'
}
};
@ -83,13 +88,13 @@ export default class DHAdversarySettings extends HandlebarsApplicationMixin(Appl
icon: null,
label: 'DAGGERHEART.General.tabs.experiences'
},
features: {
actions: {
active: false,
cssClass: '',
group: 'primary',
id: 'features',
id: 'actions',
icon: null,
label: 'DAGGERHEART.General.tabs.features'
label: 'DAGGERHEART.General.tabs.actions'
}
};
@ -114,7 +119,7 @@ export default class DHAdversarySettings extends HandlebarsApplicationMixin(Appl
return tabs;
}
static async addExperience() {
static async #addExperience() {
const newExperience = {
name: 'Experience',
modifier: 0
@ -123,11 +128,55 @@ export default class DHAdversarySettings extends HandlebarsApplicationMixin(Appl
this.render();
}
static async removeExperience(_, target) {
static async #removeExperience(_, target) {
await this.actor.update({ [`system.experiences.-=${target.dataset.experience}`]: null });
this.render();
}
static async #addAction(_event, _button) {
const actionType = await DHBaseItemSheet.selectActionType();
if (!actionType) return;
try {
const cls = actionsTypes[actionType] ?? actionsTypes.attack,
action = new cls(
{
_id: foundry.utils.randomID(),
type: actionType,
name: game.i18n.localize(SYSTEM.ACTIONS.actionTypes[actionType].name),
...cls.getSourceConfig(this.actor)
},
{
parent: this.actor
}
);
console.log(action);
await this.actor.update({ 'system.actions': [...this.actor.system.actions, action] });
await new DHActionConfig(this.actor.system.actions[this.actor.system.actions.length - 1]).render({
force: true
});
this.render();
} catch (error) {
console.log(error);
}
}
static async #editAction(event, target) {
event.stopPropagation();
const actionIndex = target.dataset.index;
await new DHActionConfig(this.actor.system.actions[actionIndex]).render({
force: true
});
}
static async #removeAction(event, target) {
event.stopPropagation();
const actionIndex = target.dataset.index;
await this.actor.update({
'system.actions': this.actor.system.actions.filter((_, index) => index !== Number.parseInt(actionIndex))
});
this.render();
}
static async updateForm(event, _, formData) {
await this.actor.update(formData.object);
this.render();

View file

@ -1,42 +1,42 @@
export const actionTypes = {
attack: {
id: 'attack',
name: 'DAGGERHEART.Actions.Types.Attack.Name',
name: 'DAGGERHEART.Actions.Types.attack.name',
icon: 'fa-swords'
},
// spellcast: {
// id: 'spellcast',
// name: 'DAGGERHEART.Actions.Types.Spellcast.Name',
// name: 'DAGGERHEART.Actions.Types.spellcast.name',
// icon: 'fa-book-sparkles'
// },
healing: {
id: 'healing',
name: 'DAGGERHEART.Actions.Types.Healing.Name',
name: 'DAGGERHEART.Actions.Types.healing.name',
icon: 'fa-kit-medical'
},
// resource: {
// id: 'resource',
// name: 'DAGGERHEART.Actions.Types.Resource.Name',
// name: 'DAGGERHEART.Actions.Types.resource.name',
// icon: 'fa-honey-pot'
// },
damage: {
id: 'damage',
name: 'DAGGERHEART.Actions.Types.Damage.Name',
name: 'DAGGERHEART.Actions.Types.damage.name',
icon: 'fa-bone-break'
},
summon: {
id: 'summon',
name: 'DAGGERHEART.Actions.Types.Summon.Name',
name: 'DAGGERHEART.Actions.Types.summon.name',
icon: 'fa-ghost'
},
effect: {
id: 'effect',
name: 'DAGGERHEART.Actions.Types.Effect.Name',
name: 'DAGGERHEART.Actions.Types.effect.name',
icon: 'fa-person-rays'
},
macro: {
id: 'macro',
name: 'DAGGERHEART.Actions.Types.Macro.Name',
name: 'DAGGERHEART.Actions.Types.macro.name',
icon: 'fa-scroll'
}
};
@ -76,7 +76,7 @@ export const damageOnSave = {
label: 'Full damage',
mod: 1
}
}
};
export const diceCompare = {
below: {
@ -104,4 +104,4 @@ export const diceCompare = {
label: 'Above',
operator: '>'
}
}
};

View file

@ -712,14 +712,14 @@ export const valueTypes = {
export const actionTypes = {
passive: {
id: 'passive',
label: 'DAGGERHEART.ActionType.Passive'
label: 'DAGGERHEART.ActionType.passive'
},
action: {
id: 'action',
label: 'DAGGERHEART.ActionType.Action'
label: 'DAGGERHEART.ActionType.action'
},
reaction: {
id: 'reaction',
label: 'DAGGERHEART.ActionType.Reaction'
label: 'DAGGERHEART.ActionType.reaction'
}
};

View file

@ -43,6 +43,7 @@ export default class DhpAdversary extends BaseDataActor {
hitPoints: resourceField(),
stress: resourceField()
}),
actions: new fields.ArrayField(new ActionField()),
attack: new ActionField({
initial: {
name: 'Attack',

View file

@ -4333,42 +4333,6 @@ div.daggerheart.views.multiclass {
padding: 0;
margin-bottom: 15px;
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-header-sheet .character-traits {
display: flex;
justify-content: space-between;
padding: 0;
margin-bottom: 15px;
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-header-sheet .character-traits .trait {
height: 60px;
width: 60px;
background: url(../assets/svg/trait-shield.svg) no-repeat;
cursor: pointer;
}
.theme-light .application.sheet.daggerheart.actor.dh-style.adversary .adversary-header-sheet .character-traits .trait {
background: url('../assets/svg/trait-shield-light.svg') no-repeat;
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-header-sheet .character-traits .trait .trait-name {
display: flex;
padding-top: 5px;
color: light-dark(#18162e, #f3c267);
font-size: 14px;
font-weight: 600;
align-items: center;
justify-content: center;
gap: 3px;
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-header-sheet .character-traits .trait .trait-name i {
line-height: 17px;
font-size: 10px;
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-header-sheet .character-traits .trait .trait-value {
font-family: 'Montserrat', sans-serif;
font-style: normal;
font-weight: 400;
font-size: 20px;
text-align: center;
}
.application.sheet.daggerheart.actor.dh-style.adversary .window-content {
display: grid;
grid-template-columns: 275px 1fr;
@ -4628,6 +4592,9 @@ div.daggerheart.views.multiclass {
gap: 10px;
align-items: center;
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-sidebar-sheet .experience-section {
margin-bottom: 20px;
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-sidebar-sheet .experience-section .title {
display: flex;
gap: 15px;
@ -4651,19 +4618,13 @@ div.daggerheart.views.multiclass {
align-items: center;
justify-content: space-between;
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-sidebar-sheet .experience-section .experience-list .experience-row input[type='text'] {
height: 32px;
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-sidebar-sheet .experience-section .experience-list .experience-row .experience-name {
width: 180px;
border: 1px solid transparent;
outline: 2px solid transparent;
text-align: start;
font-size: 14px;
font-family: 'Montserrat', sans-serif;
transition: all 0.3s ease;
color: light-dark(#222, #efe6d8);
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-sidebar-sheet .experience-section .experience-list .experience-row input[type='text']:hover {
outline: 2px solid light-dark(#222, #efe6d8);
}
.application.sheet.daggerheart.actor.dh-style.adversary .adversary-sidebar-sheet .experience-section .experience-list .experience-value {
height: 25px;
width: 35px;
@ -4709,6 +4670,71 @@ div.daggerheart.views.multiclass {
display: flex;
gap: 16px;
}
.application.daggerheart.dh-style.dialog .tab.experiences .add-experience-btn {
width: 100%;
margin-bottom: 12px;
}
.application.daggerheart.dh-style.dialog .tab.experiences .experience-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.application.daggerheart.dh-style.dialog .tab.experiences .experience-list .experience-item {
display: grid;
grid-template-columns: 3fr 1fr 30px;
align-items: center;
gap: 5px;
}
.application.daggerheart.dh-style.dialog .tab.experiences .experience-list .experience-item a {
text-align: center;
}
.application.daggerheart.dh-style.dialog .tab.actions .add-action-btn {
width: 100%;
margin-bottom: 12px;
}
.application.daggerheart.dh-style.dialog .tab.actions .action-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.application.daggerheart.dh-style.dialog .tab.actions .action-list .action-item {
display: grid;
grid-template-columns: 40px 1fr auto;
align-items: center;
gap: 5px;
}
.application.daggerheart.dh-style.dialog .tab.actions .action-list .action-item .label {
font-family: 'Montserrat', sans-serif;
}
.application.daggerheart.dh-style.dialog .tab.actions .action-list .action-item .label .tags {
display: flex;
gap: 10px;
}
.application.daggerheart.dh-style.dialog .tab.actions .action-list .action-item .label .tags .tag {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 3px 5px;
font-size: 12px;
background: light-dark(#22222215, #efe6d815);
border: 1px solid light-dark(#222, #efe6d8);
border-radius: 3px;
}
.application.daggerheart.dh-style.dialog .tab.actions .action-list .action-item .label .tags .label {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 12px;
}
.application.daggerheart.dh-style.dialog .tab.actions .action-list .action-item .controls {
display: flex;
gap: 5px;
}
.application.daggerheart.dh-style.dialog .tab.actions .action-list .action-item .controls a {
text-align: center;
}
.application.sheet.daggerheart.actor.dh-style.adversary .window-content {
overflow: auto;
}
@ -5717,13 +5743,13 @@ div.daggerheart.views.multiclass {
transition: all 0.3s ease;
color: #efe6d8;
}
.application.sheet.daggerheart.actor.dh-style.character .items-list {
.application.daggerheart.dh-style .items-list {
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
}
.application.sheet.daggerheart.actor.dh-style.character .card-list {
.application.daggerheart.dh-style .card-list {
display: flex;
flex-direction: row;
gap: 10px;

View file

@ -30,7 +30,9 @@
@import './less/actors/adversary/sidebar.less';
@import './less/applications/header.less';
@import './less/applications/adversary/sheet.less';
@import './less/applications/adversary-settings/sheet.less';
@import './less/applications/adversary-settings/experiences.less';
@import './less/applications/adversary-settings/actions.less';
@import './less/actors/adversary.less';
@import './less/actors/environment.less';

View file

@ -0,0 +1,20 @@
@import '../../utils/colors.less';
@import '../../utils/fonts.less';
.application.sheet.daggerheart.actor.dh-style.adversary {
.tab.actions {
.action-section {
display: flex;
flex-direction: column;
gap: 10px;
overflow-y: auto;
mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%);
padding: 20px 0;
padding-top: 10px;
height: 95%;
scrollbar-width: thin;
scrollbar-color: light-dark(@dark-blue, @golden) transparent;
}
}
}

View file

@ -148,49 +148,5 @@
padding: 0;
margin-bottom: 15px;
}
.character-traits {
display: flex;
justify-content: space-between;
padding: 0;
margin-bottom: 15px;
.trait {
height: 60px;
width: 60px;
background: url(../assets/svg/trait-shield.svg) no-repeat;
cursor: pointer;
.theme-light & {
background: url('../assets/svg/trait-shield-light.svg') no-repeat;
}
.trait-name {
display: flex;
align-items: center;
padding-top: 5px;
color: light-dark(@dark-blue, @golden);
font-size: 14px;
font-weight: 600;
align-items: center;
justify-content: center;
gap: 3px;
i {
line-height: 17px;
font-size: 10px;
}
}
.trait-value {
font-family: @font-body;
font-style: normal;
font-weight: 400;
font-size: 20px;
text-align: center;
}
}
}
}
}

View file

@ -277,6 +277,8 @@
}
.experience-section {
margin-bottom: 20px;
.title {
display: flex;
gap: 15px;
@ -302,19 +304,12 @@
align-items: center;
justify-content: space-between;
input[type='text'] {
height: 32px;
.experience-name {
width: 180px;
border: 1px solid transparent;
outline: 2px solid transparent;
text-align: start;
font-size: 14px;
font-family: @font-body;
transition: all 0.3s ease;
color: light-dark(@dark, @beige);
&:hover {
outline: 2px solid light-dark(@dark, @beige);
}
}
}

View file

@ -0,0 +1,62 @@
@import '../../utils/colors.less';
@import '../../utils/fonts.less';
.application.daggerheart.dh-style.dialog {
.tab.actions {
.add-action-btn {
width: 100%;
margin-bottom: 12px;
}
.action-list {
display: flex;
flex-direction: column;
gap: 10px;
.action-item {
display: grid;
grid-template-columns: 40px 1fr auto;
align-items: center;
gap: 5px;
.label {
font-family: @font-body;
.tags {
display: flex;
gap: 10px;
.tag {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 3px 5px;
font-size: 12px;
background: light-dark(@dark-15, @beige-15);
border: 1px solid light-dark(@dark, @beige);
border-radius: 3px;
}
.label {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 12px;
}
}
}
.controls {
display: flex;
gap: 5px;
a {
text-align: center;
}
}
}
}
}
}

View file

@ -0,0 +1,28 @@
@import '../../utils/colors.less';
@import '../../utils/fonts.less';
.application.daggerheart.dh-style.dialog {
.tab.experiences {
.add-experience-btn {
width: 100%;
margin-bottom: 12px;
}
.experience-list {
display: flex;
flex-direction: column;
gap: 10px;
.experience-item {
display: grid;
grid-template-columns: 3fr 1fr 30px;
align-items: center;
gap: 5px;
a {
text-align: center;
}
}
}
}
}

View file

@ -1,7 +1,7 @@
@import '../utils/colors.less';
@import '../utils/fonts.less';
.application.sheet.daggerheart.actor.dh-style.character {
.application.daggerheart.dh-style {
.items-list {
display: flex;
flex-direction: column;

View file

@ -0,0 +1,11 @@
<section
class='tab {{tabs.actions.cssClass}} {{tabs.actions.id}}'
data-tab='{{tabs.actions.id}}'
data-group='{{tabs.actions.group}}'
>
<div class="action-section">
{{#if document.system.actions}}
{{> 'systems/daggerheart/templates/sheets/global/partials/inventory-fieldset-items.hbs' title=(localize tabs.actions.label) type='action'}}
{{/if}}
</div>
</section>

View file

@ -1,10 +0,0 @@
<section
class='tab {{tabs.features.cssClass}} {{tabs.features.id}}'
data-tab='{{tabs.features.id}}'
data-group='{{tabs.features.group}}'
>
<h2>features</h2>
{{#debug document}}
{{/debug}}
</section>

View file

@ -96,7 +96,7 @@
<div class="experience-value">
+{{experience.modifier}}
</div>
<span>{{experience.name}}</span>
<span class="experience-name">{{experience.name}}</span>
<div class="controls">
<a data-action="toChat" data-type="experience" data-uuid="{{id}}"><i class="fa-regular fa-message"></i></a>
</div>

View file

@ -0,0 +1,34 @@
<section
class='tab {{tabs.actions.cssClass}} {{tabs.actions.id}}'
data-tab='{{tabs.actions.id}}'
data-group='{{tabs.actions.group}}'
>
<button class="add-action-btn" data-action="addAction">
New Action
</button>
<fieldset>
<legend>{{localize tabs.actions.label}}</legend>
<ul class="action-list">
{{#each document.system.actions as |action index|}}
<li class="action-item">
<img src="{{action.img}}" alt="">
<div class="label">
<span>{{action.name}}</span>
<div class="tags">
<div class="tag">
{{localize (concat 'DAGGERHEART.Actions.Types.' action.type '.name')}}
</div>
<div class="tag">
{{localize (concat 'DAGGERHEART.ActionType.' action.actionType)}}
</div>
</div>
</div>
<div class="controls">
<a data-action="editAction" data-index="{{index}}" data-tooltip="{{localize 'DAGGERHEART.Tooltip.edit'}}"><i class="fa-solid fa-pen-to-square"></i></a>
<a data-action="removeAction" data-index="{{index}}" data-tooltip="{{localize 'DAGGERHEART.Tooltip.delete'}}"><i class="fa-solid fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</fieldset>
</section>

View file

@ -3,15 +3,21 @@
data-tab='{{tabs.experiences.id}}'
data-group='{{tabs.experiences.group}}'
>
<button type="button" data-action="addExperience">
New Experience
<button class="add-experience-btn" type="button" data-action="addExperience">
<span>New Experience</span>
</button>
{{#each document.system.experiences as |experience key|}}
<div class="experience-chip">
<input class="experience.value" type="text" name="system.experiences.{{key}}.name" value="{{experience.name}}" />
<input class="experience-value" type="text" name="system.experiences.{{key}}.modifier" value="{{experience.modifier}}" data-dtype="Number" />
<button type="button" class="experience-button" data-action="removeExperience" data-experience="{{key}}"><i class="fa-solid fa-x"></i></button>
</div>
{{/each}}
<fieldset>
<legend>{{localize tabs.experiences.label}}</legend>
<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}}.modifier" value="{{experience.modifier}}" data-dtype="Number" />
<a data-action="removeExperience" data-experience="{{key}}" data-tooltip="{{localize 'DAGGERHEART.Tooltip.delete'}}"><i class="fa-solid fa-trash"></i></a>
</li>
{{/each}}
</ul>
</fieldset>
</section>

View file

@ -1,7 +0,0 @@
<section
class='tab {{tabs.features.cssClass}} {{tabs.features.id}}'
data-tab='{{tabs.features.id}}'
data-group='{{tabs.features.group}}'
>
<h2>Features</h2>
</section>

View file

@ -34,6 +34,11 @@
{{> 'systems/daggerheart/templates/sheets/global/partials/inventory-item.hbs' item=effect type=../type}}
{{/if}}
{{/each}}
{{#each document.system.actions as |action|}}
{{#if (or (eq ../type 'action'))}}
{{> 'systems/daggerheart/templates/sheets/global/partials/inventory-item.hbs' item=action type=../type}}
{{/if}}
{{/each}}
{{/unless}}
</ul>

View file

@ -100,6 +100,16 @@
{{/each}}
</div>
{{/if}}
{{#if (eq type 'action')}}
<div class="item-tags">
<div class="tag">
{{localize (concat 'DAGGERHEART.Actions.Types.' item.type '.name')}}
</div>
<div class="tag">
{{localize (concat 'DAGGERHEART.ActionType.' item.actionType)}}
</div>
</div>
{{/if}}
</div>
<div class="controls">
{{#if (eq type 'weapon')}}