Implement a button to create items of a specific subtype in the player inventory (closes #120)

This commit is contained in:
Oliver-Akins 2024-03-22 23:35:04 -06:00
parent b3e699bc32
commit 96f5b17785
9 changed files with 73 additions and 21 deletions

View file

@ -49,7 +49,8 @@
"v2": {
"stat-not-chosen": "Select a dice to see the {name} skills",
"skill-roll-locked": "@dotdungeon.trainingLevel.locked",
"toggle-item-information": "Toggle the item's extra information visibility"
"toggle-item-information": "Toggle the item's extra information visibility",
"create-item": "Create @TYPES.Item.{type}"
}
},
"item": {

View file

@ -1,6 +1,7 @@
export class DotDungeonActor extends Actor {
async createEmbeddedItem(defaults, opts = {}) {
let items = await this.createEmbeddedDocuments(`Item`, defaults);
if (!Array.isArray(items)) items = items ? [items] : [];
if (items.length == 0) {
throw new Error(`Failed to create any items`);
};

View file

@ -3,7 +3,7 @@ import { createArray } from "./createArray.mjs";
import { detailsExpanded } from "./detailsExpanded.mjs";
import { objectValue } from "./objectValue.mjs";
import { toFriendlyDuration } from "./toFriendlyDuration.mjs";
import { localizer } from "../utils/localizer.mjs";
import { handlebarsLocalizer } from "../utils/localizer.mjs";
import { options } from "./options.mjs";
export default {
@ -14,7 +14,7 @@ export default {
"dd-toFriendlyDuration": toFriendlyDuration,
"dd-objectValue": objectValue,
"dd-expanded": detailsExpanded,
"dd-i18n": localizer,
"dd-i18n": handlebarsLocalizer,
"dd-options": options,
// Simple helpers

View file

@ -136,6 +136,7 @@ export class PlayerSheetv2 extends GenericActorSheet {
filters[type] = {
label: localizer(`TYPES.Item.${type}`),
active: !this._itemTypesHidden.has(type),
createLabel: localizer(`dotdungeon.sheet.actor.v2.create-item`, {type}),
};
};
return filters;

View file

@ -1,3 +1,4 @@
import { localizer } from "../utils/localizer.mjs";
import DOTDUNGEON from "../config.mjs";
export class GenericActorSheet extends ActorSheet {
@ -127,11 +128,11 @@ export class GenericActorSheet extends ActorSheet {
async genericEmbeddedCreate($event) {
const data = $event.currentTarget.dataset;
if (!this[`createCustom${data.embeddedCreate}`]) {
this.createEmbeddedItem({
this.actor.createEmbeddedItem({
type: data.embeddedCreate,
name: localizer(
`dotdungeon.default.name`,
{ document: `Actor`, type: data.embeddedCreate }
{ document: `Item`, type: data.embeddedCreate }
),
});
} else {

View file

@ -1,8 +1,14 @@
import { localizerConfig } from "../config.mjs";
export function localizer(key, args = {}, depth = 0) {
export function handlebarsLocalizer(key, ...args) {
let data = args[0]
if (args.length === 1) data = args[0].hash;
if (key instanceof Handlebars.SafeString) key = key.toString();
const localized = localizer(key, data);
return localized;
};
export function localizer(key, args = {}, depth = 0) {
/** @type {string} */
let localized = game.i18n.format(key, args);
const subkeys = localized.matchAll(localizerConfig.subKeyPattern);

View file

@ -27,6 +27,40 @@
}
}
.item-group {
&__header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center
}
&__create-item {
@include material.elevate(2);
color: var(--inventory-create-item-font-color);
&:hover {
@include material.elevate(4);
}
&:focus-visible, &:active {
@include material.elevate(8);
}
}
&__list {
&--material {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
&--untyped {
display: flex;
gap: 8px;
flex-direction: column;
}
}
}
.panel {
padding: 8px;
border-radius: 4px;
@ -54,7 +88,7 @@
background: hsl( from currentColor / 50% ); // probably gonna need color-mix
}
&:focus-visible {
&:focus-visible, &:active {
border-width: 2px;
border-color: currentColor;
background: var(--elevation-8dp-bg);
@ -94,18 +128,6 @@
}
}
.material-list {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.untyped-list {
display: flex;
gap: 8px;
flex-direction: column;
}
.material {
@include material.elevate(1);
padding: 8px;
@ -174,6 +196,7 @@
display: flex;
gap: 8px;
align-items: center;
justify-content: space-between;
&:hover {
cursor: pointer;
@ -188,6 +211,7 @@
}
&__name {
flex-grow: 1;
cursor: inherit;
font-family: var(--inventory-item-name-font);
font-size: var(--inventory-item-name-font-size);
}

View file

@ -48,6 +48,9 @@ $body-font: sans-serif;
--skill-training-select-text-color: #{$on-surface};
--skill-roll-button-text-color: #{$on-surface};
/* General variables for inventory tab */
--inventory-create-item-font-color: white;
/* Common Inventory Item Variables */
--inventory-item-name-font: #{$body-font};
--inventory-item-name-font-size: 0.875rem;

View file

@ -7,9 +7,24 @@
{{#each computed.itemFilters as | filter |}}
{{#if filter.active}}
<section class="item-list__group">
<h2>{{filter.label}}</h2>
<div class="item-group__header">
<h2>{{filter.label}}</h2>
<button
type="button"
class="item-group__create-item reduced-padding equal-padding"
data-embedded-create="{{@key}}"
aria-label="{{filter.createLabel}}"
data-tooltip="{{filter.createLabel}}"
data-tooltip-direction="LEFT"
>
<div aria-hidden="true" class="icon icon--16">
{{{ @root.icons.create }}}
</div>
</button>
</div>
<hr>
<div class="{{@key}}-list">
<div class="item-group__list--{{@key}}">
{{#each (lookup @root.items @key) as | item |}}
{{> (concat "dotdungeon.pc.v2." @../key) @root item=item}}
{{else}}