diff --git a/lang/en.json b/lang/en.json index 9ee6b6a..2452916 100644 --- a/lang/en.json +++ b/lang/en.json @@ -172,6 +172,7 @@ "dblclick-open": "Double-Click 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.", diff --git a/lang/no.json b/lang/no.json index f3f456b..8e9bde1 100644 --- a/lang/no.json +++ b/lang/no.json @@ -172,6 +172,7 @@ "dblclick-open": "Dobbelklikk 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.", diff --git a/scripts/actor/character/character-sheet.js b/scripts/actor/character/character-sheet.js index 9c5a491..50e765a 100644 --- a/scripts/actor/character/character-sheet.js +++ b/scripts/actor/character/character-sheet.js @@ -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, { @@ -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({ @@ -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, @@ -160,6 +163,7 @@ 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 @@ -167,6 +171,10 @@ export class CharacterSheet extends SheetMixin(ActorSheet) { 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( @@ -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); @@ -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; @@ -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; } } @@ -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; } } @@ -346,6 +389,27 @@ 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; @@ -353,6 +417,19 @@ export class CharacterSheet extends SheetMixin(ActorSheet) { 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; @@ -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) { diff --git a/scripts/apps/roll-dialog.js b/scripts/apps/roll-dialog.js index 7c86563..bed6567 100644 --- a/scripts/apps/roll-dialog.js +++ b/scripts/apps/roll-dialog.js @@ -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() { @@ -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() { @@ -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( diff --git a/scripts/mixins/sheet-mixin.js b/scripts/mixins/sheet-mixin.js index f04561a..9f65ffd 100644 --- a/scripts/mixins/sheet-mixin.js +++ b/scripts/mixins/sheet-mixin.js @@ -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})`); }; diff --git a/scripts/system/enrichers.js b/scripts/system/enrichers.js index 747280f..09bc60b 100644 --- a/scripts/system/enrichers.js +++ b/scripts/system/enrichers.js @@ -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 $( @@ -39,9 +40,11 @@ export class Enrichers { )[0]; if (tag && status) return $( - `${tag}-${status}`, + `${tag}-${status}`, )[0]; - return $(`${tag}`)[0]; + return $( + `${tag}`, + )[0]; }; CONFIG.TextEditor.enrichers.push({ pattern: CONFIG.litm.tagStringRe, diff --git a/scripts/system/handlebars.js b/scripts/system/handlebars.js index b3b23d2..8331a70 100644 --- a/scripts/system/handlebars.js +++ b/scripts/system/handlebars.js @@ -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, ); @@ -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", ); } } diff --git a/scripts/system/hooks.js b/scripts/system/hooks.js index 86c2284..c07d310 100644 --- a/scripts/system/hooks.js +++ b/scripts/system/hooks.js @@ -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 { @@ -231,7 +231,8 @@ export class LitmHooks { const createEffect = ([key, effect], category) => ({ name: `${t(category)}: ${t(`Litm.effects.${key}.key`)}`, icon: ``, - condition: (li) => li.find("[data-type='tracked']").length, + condition: (li) => + li.find("[data-type='tracked']:not([data-result='failure'])").length, callback: () => { ChatMessage.create({ content: `
{{localize effect.description}}
{{localize effect.action}}
-{{localize 'Litm.other.cost'}}: {{localize effect.cost}}
+{{localize 'Litm.other.cost'}}: + {{localize effect.cost}}
+ {{{localize "Litm.ui.roll-tracked-hint"}}} +
+ {{/if}} {{#if (gt total 9)}} -{{localize 'Litm.ui.roll-tracked-success'}}
++ {{localize 'Litm.ui.roll-tracked-success'}} +
{{/if}} -{{{localize "Litm.ui.roll-tracked-hint"}}}
{{/if}} {{#if (and isOwner hasBurnedTags)}} - + {{/if}} {{#if (and isOwner hasWeaknessTags)}}