Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Leaf to add tag/status from character sheet #63

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
"dblclick-open": "<span class='reference'>Double-Click</span> to edit",
"dice-roller": "Dice Roller",
"dice-roller-hint": "Opens the dice roll dialog if a character is attached to the user.",
"drag-apply": "Drag onto Actors or Story Window to apply",
"drop-actors": "Drop actors here.",
"edit": "Edit",
"error-burning-tag": "There was an error trying to burn your tag. Please see the console for more information.",
Expand Down
1 change: 1 addition & 0 deletions lang/no.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
"dblclick-open": "<span class='reference'>Dobbelklikk</span> for å åpne",
"dice-roller": "Terningkast",
"dice-roller-hint": "Åpner terningkast-vinduet for denne karakteren.",
"drag-apply": "Dra til en aktør eller Merke-vinduet for å legge til.",
"drop-actors": "Dra aktører hit",
"edit": "Rediger",
"error-burning-tag": "Det oppstod en feil under brenning av merket. Se konsollen for mer informasjon.",
Expand Down
92 changes: 85 additions & 7 deletions scripts/actor/character/character-sheet.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SheetMixin } from "../../mixins/sheet-mixin.js";
import { confirmDelete, dispatch } from "../../utils.js";
import { localize as t } from "../../utils.js";

export class CharacterSheet extends SheetMixin(ActorSheet) {
static defaultOptions = foundry.utils.mergeObject(ActorSheet.defaultOptions, {
Expand All @@ -14,7 +15,8 @@ export class CharacterSheet extends SheetMixin(ActorSheet) {

#dragAvatarTimeout = null;
#notesEditorOpened = false;
#focusedTags = null;
#tagsFocused = null;
#tagsHovered = false;
#themeHovered = null;
#contextmenu = null;
#roll = game.litm.LitmRollDialog.create({
Expand Down Expand Up @@ -134,7 +136,8 @@ export class CharacterSheet extends SheetMixin(ActorSheet) {
backpack,
note,
themes,
tagsFocused: this.#focusedTags,
tagsFocused: this.#tagsFocused,
tagsHovered: this.#tagsHovered,
themeHovered: this.#themeHovered,
notesEditorOpened: this.#notesEditorOpened,
rollTags: this.#roll.characterTags,
Expand All @@ -160,13 +163,18 @@ export class CharacterSheet extends SheetMixin(ActorSheet) {
.on("mousedown", this.#onDragHandleMouseDown.bind(this));
html.on("mouseover", (event) => {
html.find(".litm--character-theme").removeClass("hovered");
html.find(".litm--character-story-tags").removeClass("hovered");

const t = event.target.classList.contains("litm--character-theme")
? event.target
: event.target.closest(".litm--character-theme");

if (t) this.#themeHovered = t.dataset.id;
else this.#themeHovered = null;

if (event.target.closest(".litm--character-story-tags"))
this.#tagsHovered = true;
else this.#tagsHovered = false;
});

this.#contextmenu = ContextMenu.create(
Expand Down Expand Up @@ -210,6 +218,33 @@ export class CharacterSheet extends SheetMixin(ActorSheet) {
return super._updateObject(event, cleaned);
}

async _onDrop(dragEvent) {
const dragData = dragEvent.dataTransfer.getData("text/plain");
const data = JSON.parse(dragData);

// Handle dropping tags and statuses
if (!["tag", "status"].includes(data.type)) return;

await this.actor.createEmbeddedDocuments("ActiveEffect", [
{
name: data.name,
flags: {
litm: {
type: data.type,
values: data.values,
isBurnt: data.isBurnt,
},
},
},
]);

game.litm.storyTags.render();
dispatch({
app: "story-tags",
type: "render",
});
}

// Prevent dropping more than 4 themes on the character sheet
async _onDropItem(event, data) {
const item = await Item.implementation.fromDropData(data);
Expand Down Expand Up @@ -267,6 +302,9 @@ export class CharacterSheet extends SheetMixin(ActorSheet) {
const id = t.dataset.id;

switch (action) {
case "add-tag":
this.#addTag();
break;
case "increase":
this.#increase(event);
break;
Expand All @@ -288,9 +326,9 @@ export class CharacterSheet extends SheetMixin(ActorSheet) {

switch (action) {
case "return":
this.#focusedTags = null;
this.#tagsFocused = null;
t.classList.remove("focused");
t.style.cssText = this.#focusedTags;
t.style.cssText = this.#tagsFocused;
break;
}
}
Expand All @@ -305,6 +343,11 @@ export class CharacterSheet extends SheetMixin(ActorSheet) {
event.stopPropagation();
this.#decrease(event);
break;
case "remove-effect":
event.preventDefault();
event.stopPropagation();
this.#removeEffect(t.dataset.id);
break;
}
}

Expand Down Expand Up @@ -346,13 +389,47 @@ export class CharacterSheet extends SheetMixin(ActorSheet) {
$(document).on("mouseup", handleMouseUp);
}

async #addTag() {
await this.actor.createEmbeddedDocuments("ActiveEffect", [
{
name: t("Litm.ui.name-tag"),
flags: {
litm: {
type: "tag",
values: new Array(6).fill(false),
isBurnt: false,
},
},
},
]);

game.litm.storyTags.render();
dispatch({
app: "story-tags",
type: "render",
});
}

async #removeItem(id) {
const item = this.items.get(id);
if (!(await confirmDelete(`TYPES.Item.${item.type}`))) return;

return item.delete();
}

async #removeEffect(id) {
const effect = this.actor.effects.get(id);
if (!(await confirmDelete())) return;

await effect.delete();

game.litm.storyTags.render();
dispatch({
app: "story-tags",
type: "render",
});
}

async #increase(event) {
const t = event.currentTarget;
const attrib = t.dataset.id;
Expand Down Expand Up @@ -426,10 +503,11 @@ export class CharacterSheet extends SheetMixin(ActorSheet) {
const t = event.currentTarget;

t.classList.add("focused");
const listener = t.addEventListener("mouseup", () => {
this.#focusedTags = t.style.cssText;
const listener = () => {
this.#tagsFocused = t.style.cssText;
t.removeEventListener("mouseup", listener);
});
};
t.addEventListener("mouseup", listener);
}

async #handleUpdateEmbeddedItems(formData) {
Expand Down
12 changes: 7 additions & 5 deletions scripts/apps/roll-dialog.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Sockets } from "../system/sockets.js";
import { localize as t, sortTags } from "../utils.js";
import { sortTags, localize as t } from "../utils.js";

export class LitmRollDialog extends FormApplication {
static get defaultOptions() {
Expand Down Expand Up @@ -209,9 +209,11 @@ export class LitmRollDialog extends FormApplication {
...tag,
state: this.#tagState.find((t) => t.id === tag.id)?.state || "",
states:
tag.type === "tag" ? ",negative,positive,burned" : ",negative,positive",
tag.type === "tag"
? ",negative,positive,burned"
: ",negative,positive",
}))
.filter(tag => game.user.isGM || tag.state !== "");
.filter((tag) => game.user.isGM || tag.state !== "");
}

get totalPower() {
Expand Down Expand Up @@ -369,8 +371,8 @@ export class LitmRollDialog extends FormApplication {
const tags = LitmRollDialog.#filterTags(data.tags);
const { totalPower } = LitmRollDialog.#calculateTotalPower(tags);
const recipients = Object.entries(this.actor.ownership)
.filter(u => u[1] === 3 && u[0] !== 'default')
.map(u => u[0])
.filter((u) => u[1] === 3 && u[0] !== "default")
.map((u) => u[0]);

ChatMessage.create({
content: await renderTemplate(
Expand Down
8 changes: 7 additions & 1 deletion scripts/mixins/sheet-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,21 @@ export const SheetMixin = (Base) =>
event.originalEvent.type === "pointerdown"
? ["pointermove", "pointerup"]
: ["mousemove", "mouseup"];

const el = this.element;

let previousX = event.screenX;
let delta = 0;

const clampValue = (current, delta) => {
const value = current + delta / 500;
return Math.max(0.3, Math.min(3, value));
};

const mousemove = (event) => {
delta = event.screenX - previousX;
previousX = event.screenX;
this.#currentScale += delta / 500;
this.#currentScale = clampValue(this.#currentScale, delta);

el.css("transform", `scale(${this.#currentScale})`);
};
Expand Down
7 changes: 5 additions & 2 deletions scripts/system/enrichers.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class Enrichers {
}

static #enrichTags() {
const tooltip = game.i18n.localize("Litm.ui.drag-apply");
const enrichTags = ([_text, tag, status]) => {
if (tag.startsWith("-"))
return $(
Expand All @@ -39,9 +40,11 @@ export class Enrichers {
)[0];
if (tag && status)
return $(
`<mark class="litm--status" draggable="true">${tag}-${status}</mark>`,
`<mark class="litm--status" draggable="true" data-tooltip="${tooltip}">${tag}-${status}</mark>`,
)[0];
return $(`<mark class="litm--tag" draggable="true">${tag}</mark>`)[0];
return $(
`<mark class="litm--tag" draggable="true" data-tooltip="${tooltip}">${tag}</mark>`,
)[0];
};
CONFIG.TextEditor.enrichers.push({
pattern: CONFIG.litm.tagStringRe,
Expand Down
6 changes: 3 additions & 3 deletions scripts/system/handlebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class HandlebarsHelpers {
Handlebars.registerHelper("includes", (array, value, path) =>
Array.isArray(array)
? (path && array.some((i) => i[path] === value)) ||
array.includes(value)
array.includes(value)
: false,
);

Expand All @@ -38,8 +38,8 @@ export class HandlebarsHelpers {
tag.isActive
? "Litm.tags.isActive"
: readonly
? "Litm.tags.isInactive"
: "Litm.tags.activate",
? "Litm.tags.isInactive"
: "Litm.tags.activate",
);
}
}
Expand Down
7 changes: 4 additions & 3 deletions scripts/system/hooks.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { error, info } from "../logger.js";
import { localize as t, sleep } from "../utils.js";
import { sleep, localize as t } from "../utils.js";
import { Sockets } from "./sockets.js";

export class LitmHooks {
Expand Down Expand Up @@ -231,7 +231,8 @@ export class LitmHooks {
const createEffect = ([key, effect], category) => ({
name: `${t(category)}: ${t(`Litm.effects.${key}.key`)}`,
icon: `<i class="${effect.icon}"></i>`,
condition: (li) => li.find("[data-type='tracked']").length,
condition: (li) =>
li.find("[data-type='tracked']:not([data-result='failure'])").length,
callback: () => {
ChatMessage.create({
content: `<div class="litm dice-roll">
Expand Down Expand Up @@ -302,7 +303,7 @@ export class LitmHooks {
actorLink: true,
disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY,
texture: { src: tokenImg || img },
}
}
: null;
actor.updateSource({ prototypeToken, img });
});
Expand Down
32 changes: 26 additions & 6 deletions styles/actor/character.css
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,9 @@

& .litm--character-story-tags {
position: absolute;
margin: 0px;
padding: 0px;
list-style: none;
top: 0.625rem;
right: -21.875rem;
rotate: 30deg;
Expand All @@ -414,7 +417,8 @@

&:hover,
&:focus-within,
&.focused {
&.focused,
&.hovered {
display: flex;
flex-direction: column;
pointer-events: all;
Expand Down Expand Up @@ -486,14 +490,31 @@
}
}

& button {
background: none;
border: none;
margin: 0px;
padding: 0px;
position: relative;
font-family: var(--litm-font-accent);
color: var(--litm-color);

& span {
position: absolute;
top: 2rem;
width: 55%;
left: 2.5rem;
}
}

& .litm--story-tag-values {
display: flex;
flex-wrap: nowrap;
align-items: center;
margin-block-start: 13px;
margin-inline-start: -10px;
gap: 8.5px;

margin-block-start: 9px;
margin-inline-start: -8px;
gap: 8.2px;
rotate: -1deg;

& .litm--story-tag-value {
position: relative;
Expand All @@ -505,7 +526,6 @@
font-family: var(--litm-font-primary);
color: color-mix(in hsl, var(--litm-color) 70%, transparent);
font-size: var(--font-size-14);

}
}

Expand Down
Loading