Added a button to spend/restore uses of an action

This commit is contained in:
WBHarry 2025-08-06 17:37:14 +02:00
parent d186c62ee5
commit aef9828f86
7 changed files with 91 additions and 14 deletions

View file

@ -2345,7 +2345,8 @@
"pendingSaves": "Pending Reaction Rolls", "pendingSaves": "Pending Reaction Rolls",
"openSheetSettings": "Open Settings", "openSheetSettings": "Open Settings",
"rulesOn": "Rules On", "rulesOn": "Rules On",
"rulesOff": "Rules Off" "rulesOff": "Rules Off",
"remainingUses": "Uses refresh on {type}"
} }
} }
} }

View file

@ -22,7 +22,8 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
}, },
actions: { actions: {
openSettings: DHBaseActorSheet.#openSettings, openSettings: DHBaseActorSheet.#openSettings,
sendExpToChat: DHBaseActorSheet.#sendExpToChat sendExpToChat: DHBaseActorSheet.#sendExpToChat,
increaseActionUses: event => DHBaseActorSheet.#modifyActionUses(event, true)
}, },
contextMenus: [ contextMenus: [
{ {
@ -70,6 +71,15 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
return context; return context;
} }
/**@inheritdoc */
_attachPartListeners(partId, htmlElement, options) {
super._attachPartListeners(partId, htmlElement, options);
htmlElement.querySelectorAll('.item-button .action-uses-button').forEach(element => {
element.addEventListener('contextmenu', DHBaseActorSheet.#modifyActionUses);
});
}
/** /**
* Prepare render context for the Effect part. * Prepare render context for the Effect part.
* @param {ApplicationRenderContext} context * @param {ApplicationRenderContext} context
@ -154,6 +164,20 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
cls.create(msg); cls.create(msg);
} }
/**
*
*/
static async #modifyActionUses(event, increase) {
event.stopPropagation();
event.preventDefault();
const actionId = event.target.dataset.itemUuid;
const action = await foundry.utils.fromUuid(actionId);
const newValue = (action.uses.value ?? 0) + (increase ? 1 : -1);
await action.update({ 'uses.value': Math.min(Math.max(newValue, 0), action.uses.max ?? 0) });
this.render();
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Application Drag/Drop */ /* Application Drag/Drop */
/* -------------------------------------------- */ /* -------------------------------------------- */

View file

@ -164,6 +164,12 @@ export function ActionMixin(Base) {
return foundry.utils.getProperty(this.parent, this.systemPath) instanceof Collection; return foundry.utils.getProperty(this.parent, this.systemPath) instanceof Collection;
} }
get remainingUses() {
if (!this.uses) return null;
return Math.max((this.uses.max ?? 0) - (this.uses.value ?? 0), 0);
}
static async create(data, operation = {}) { static async create(data, operation = {}) {
const { parent, renderSheet } = operation; const { parent, renderSheet } = operation;
let { type } = data; let { type } = data;

View file

@ -486,8 +486,43 @@
flex-wrap: wrap; flex-wrap: wrap;
margin-top: 2px; margin-top: 2px;
.item-button {
display: flex;
border: 1px solid light-dark(#18162e, #18162e);
color: light-dark(#18162e, #18162e);
outline: none;
box-shadow: none;
border-radius: 6px;
button { button {
padding: 6px 6px 6px 10px;
border-radius: 3px 0px 0px 3px;
color: light-dark(@dark-blue, @dark-blue);
white-space: nowrap; white-space: nowrap;
border: 0;
font-family: @font-body;
&:hover {
color: light-dark(@dark-blue, @golden);
}
&:last-child {
padding: 6px;
background: light-dark(@dark-blue-10, @golden-secondary);
border-radius: 0px 3px 3px 0px;
color: light-dark(@dark-blue, @dark-golden);
&:hover {
background: light-dark(@light-black, @dark-blue);
color: light-dark(@dark-blue, @golden-secondary);
}
}
}
.spacer {
border-right: 1px solid black;
content: '';
}
} }
} }
} }

View file

@ -24,8 +24,9 @@
width: 100%; width: 100%;
list-style-type: none; list-style-type: none;
&:not(.single-img):hover { &:not(.single-img) {
.inventory-item-header .img-portait { .inventory-item-header:hover {
.img-portait {
.roll-img { .roll-img {
opacity: 1; opacity: 1;
} }
@ -34,6 +35,7 @@
} }
} }
} }
}
.inventory-item-header { .inventory-item-header {
display: flex; display: flex;

View file

@ -5,6 +5,7 @@
@golden-10: #f3c26710; @golden-10: #f3c26710;
@golden-40: #f3c26740; @golden-40: #f3c26740;
@golden-bg: #f3c2671a; @golden-bg: #f3c2671a;
@golden-secondary: #eaaf42;
@chat-blue: #8f87ee; @chat-blue: #8f87ee;
@chat-blue-10: #8f87ee10; @chat-blue-10: #8f87ee10;

View file

@ -146,9 +146,17 @@ Parameters:
{{#if (and showActions (eq item.type 'feature'))}} {{#if (and showActions (eq item.type 'feature'))}}
<div class="item-buttons"> <div class="item-buttons">
{{#each item.system.actions as | action |}} {{#each item.system.actions as | action |}}
<div class="item-button">
<button type="button" data-action="useItem" data-item-uuid="{{action.uuid}}"> <button type="button" data-action="useItem" data-item-uuid="{{action.uuid}}">
{{action.name}} {{action.name}}
</button> </button>
{{#if action.uses.max}}
<div class="spacer"></div>
<button type="button" class="action-uses-button" data-action="increaseActionUses" data-item-uuid="{{action.uuid}}">
{{action.remainingUses}}/{{action.uses.max}}
</button>
{{/if}}
</div>
{{/each}} {{/each}}
</div> </div>
{{/if}} {{/if}}