Skip to content

Commit

Permalink
add public methods to sidebars
Browse files Browse the repository at this point in the history
  • Loading branch information
reonZ committed Nov 14, 2024
1 parent d49c413 commit dbb92ee
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 96 deletions.
38 changes: 2 additions & 36 deletions src/hud/shared/base.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { R, canObserveActor, getSetting, htmlClosest, signedInteger } from "foundry-pf2e";
import { R, canObserveActor, getSetting, signedInteger } from "foundry-pf2e";

const IWR_DATA = [
{ type: "immunities", icon: "fa-solid fa-ankh", label: "PF2E.ImmunitiesLabel" },
Expand Down Expand Up @@ -120,32 +120,6 @@ function getStatistics(actor: ActorPF2e) {
);
}

function getItemFromElement<T extends ItemPF2e>(
el: HTMLElement,
actor: ActorPF2e
): T | null | Promise<T | null> {
const element = htmlClosest(el, ".item");
if (!element) return null;

const { parentId, itemId, itemUuid, itemType, actionIndex, entryId } = element.dataset;

const item = parentId
? actor.inventory.get(parentId, { strict: true }).subitems.get(itemId, { strict: true })
: itemUuid
? fromUuid<T>(itemUuid)
: entryId
? actor.spellcasting?.collections
.get(entryId, { strict: true })
.get(itemId, { strict: true }) ?? null
: itemType === "condition"
? actor.conditions.get(itemId, { strict: true })
: actionIndex
? actor.system.actions?.[Number(actionIndex)].item ?? null
: actor.items.get(itemId ?? "") ?? null;

return item as T | null | Promise<T | null>;
}

function userCanObserveActor(actor: ActorPF2e) {
return (
canObserveActor(actor, true) ||
Expand Down Expand Up @@ -200,13 +174,5 @@ type HealthData = {
max: number;
};

export {
IWR_DATA,
getHealth,
getItemFromElement,
getSpeeds,
getStatistics,
getStatsHeader,
userCanObserveActor,
};
export { IWR_DATA, getHealth, getSpeeds, getStatistics, getStatsHeader, userCanObserveActor };
export type { HealthData, StatsHeader, StatsSpeed, StatsSpeeds, StatsStatistic };
70 changes: 33 additions & 37 deletions src/hud/sidebar/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
} from "foundry-pf2e";
import { getNpcStrikeImage } from "../../utils/npc-attacks";
import { PF2eHudTextPopup } from "../popup/text";
import { getItemFromElement } from "../shared/base";
import { PF2eHudSidebar, SidebarContext, SidebarName, SidebarRenderOptions } from "./base";
import { EXTRAS_ACTIONS_UUIDS } from "./extras";
import { SKILL_ACTIONS_UUIDS } from "./skills";
Expand Down Expand Up @@ -261,41 +260,38 @@ class PF2eHudSidebarActions extends PF2eHudSidebar {
}
}

_activateListeners(html: HTMLElement) {
const actor = this.actor;
getBlastFromElement(el: HTMLElement) {
const { elementTraits, damageTypes } = CONFIG.PF2E;
const melee = el.dataset.melee === "true";
const blast = new game.pf2e.ElementalBlast(this.actor as CharacterPF2e);
const itemRow = htmlClosest(el, ".item")!;
const element = itemRow.dataset.element;
const damageType = el.dataset.value || itemRow.dataset.damageType;

if (!objectHasKey(elementTraits, element)) {
throw ErrorPF2e("Unexpected error retrieve element");
}
if (!objectHasKey(damageTypes, damageType)) {
throw ErrorPF2e("Unexpected error retrieving damage type");
}

const getBlast = (button: HTMLElement, itemRow: HTMLElement) => {
const melee = button.dataset.melee === "true";
const blast = new game.pf2e.ElementalBlast(actor as CharacterPF2e);
const element = itemRow.dataset.element;
const damageType = button.dataset.value || itemRow.dataset.damageType;

if (!objectHasKey(elementTraits, element)) {
throw ErrorPF2e("Unexpected error retrieve element");
}
if (!objectHasKey(damageTypes, damageType)) {
throw ErrorPF2e("Unexpected error retrieving damage type");
}
return [blast, { element, damageType, melee }] as const;
}

return [blast, { element, damageType, melee }] as const;
};
getStrikeFromElement<T extends StrikeData>(el: HTMLElement, readyOnly = false): T | null {
const actionIndex = Number(htmlClosest(el, ".item")?.dataset.actionIndex ?? "NaN");
const strike = this.actor.system.actions?.at(actionIndex) ?? null;
return getStrikeVariant<T>(strike, el, readyOnly);
}

const getStrike = <T extends StrikeData>(
button: HTMLElement,
readyOnly = false
): T | null => {
const actionIndex = Number(htmlClosest(button, ".item")?.dataset.actionIndex ?? "NaN");
const strike = this.actor.system.actions?.at(actionIndex) ?? null;
return getStrikeVariant<T>(strike, button, readyOnly);
};
_activateListeners(html: HTMLElement) {
const actor = this.actor;

const getUUID = (button: HTMLElement) => {
return elementDataset(htmlClosest(button, ".item")!).uuid;
};

addListenerAll(html, "[data-action]", async (event, button) => {
const itemRow = htmlClosest(button, ".item")!;
const action = button.dataset.action as Action;

switch (action) {
Expand All @@ -311,7 +307,7 @@ class PF2eHudSidebarActions extends PF2eHudSidebar {
}

case "toggle-trait": {
const item = await getItemFromElement(button, actor);
const item = await this.getItemFromElement(button);
if (!isOwnedItem(item) || !item.isOfType("action", "feat")) return;

const trait = button.dataset.trait as "mindshift";
Expand All @@ -336,20 +332,20 @@ class PF2eHudSidebarActions extends PF2eHudSidebar {
}

case "blast-attack": {
const [blast, data] = getBlast(button, itemRow);
const [blast, data] = this.getBlastFromElement(button);
const mapIncreases = Math.clamp(Number(button.dataset.mapIncreases), 0, 2);
return blast.attack({ ...data, mapIncreases, event });
}

case "blast-damage": {
const [blast, data] = getBlast(button, itemRow);
const [blast, data] = this.getBlastFromElement(button);
const outcome =
button.dataset.outcome === "success" ? "success" : "criticalSuccess";
return blast.damage({ ...data, outcome, event });
}

case "blast-set-damage-type": {
const [blast, data] = getBlast(button, itemRow);
const [blast, data] = this.getBlastFromElement(button);
return blast.setDamageType(data);
}

Expand All @@ -358,29 +354,29 @@ class PF2eHudSidebarActions extends PF2eHudSidebar {
? button.dataset.altUsage
: null;

const strike = getStrike(button, true);
const strike = this.getStrikeFromElement(button, true);
const variantIndex = Number(button.dataset.variantIndex);
return strike?.variants[variantIndex]?.roll({ event, altUsage });
}

case "strike-damage":
case "strike-critical": {
const strike = getStrike(button);
const strike = this.getStrikeFromElement(button);
const method =
button.dataset.action === "strike-damage" ? "damage" : "critical";
return strike?.[method]?.({ event });
}

case "auxiliary-action": {
const auxiliaryActionIndex = Number(button.dataset.auxiliaryActionIndex ?? NaN);
const strike = getStrike<CharacterStrike>(button);
const strike = this.getStrikeFromElement<CharacterStrike>(button);
const selection = htmlQuery(button, "select")?.value ?? null;
strike?.auxiliaryActions?.at(auxiliaryActionIndex)?.execute({ selection });
break;
}

case "toggle-weapon-trait": {
const weapon = getStrike<CharacterStrike>(button)?.item;
const weapon = this.getStrikeFromElement<CharacterStrike>(button)?.item;
const trait = button.dataset.trait;
const errorMessage = "Unexpected failure while toggling weapon trait";

Expand Down Expand Up @@ -464,12 +460,12 @@ class PF2eHudSidebarActions extends PF2eHudSidebar {
}

case "use-action": {
const item = await getItemFromElement<ActionItem>(button, actor);
const item = await this.getItemFromElement<ActionItem>(button);
return item?.isOfType("feat", "action") && useAction(event, item);
}

case "reset-action": {
const item = await getItemFromElement<ActionItem>(button, actor);
const item = await this.getItemFromElement<ActionItem>(button);
const frequency = item?.frequency;
if (!item || !frequency?.max) return;
return item.update({ "system.frequency.value": frequency.max });
Expand All @@ -483,7 +479,7 @@ class PF2eHudSidebarActions extends PF2eHudSidebar {
"change",
(event, ammoSelect: HTMLSelectElement) => {
event.stopPropagation();
const action = getStrike<CharacterStrike>(ammoSelect);
const action = this.getStrikeFromElement<CharacterStrike>(ammoSelect);
const weapon = action?.item;
const ammo = this.actor.items.get(ammoSelect.value);
weapon?.update({ system: { selectedAmmoId: ammo?.id ?? null } });
Expand Down
31 changes: 27 additions & 4 deletions src/hud/sidebar/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { PF2eHudBaseActor } from "../base/actor";
import { IPF2eHudAdvanced } from "../base/advanced";
import { PF2eHudItemPopup } from "../popup/item";
import { addDragoverListener } from "../shared/advanced";
import { getItemFromElement } from "../shared/base";
import { addEnterKeyListeners } from "../shared/listeners";

const SIDEBARS = [
Expand Down Expand Up @@ -340,6 +339,30 @@ abstract class PF2eHudSidebar extends foundry.applications.api
return super.close(options);
}

getItemFromElement<T extends ItemPF2e>(el: HTMLElement): T | null | Promise<T | null> {
const actor = this.actor;
const element = htmlClosest(el, ".item");
if (!element) return null;

const { parentId, itemId, itemUuid, itemType, actionIndex, entryId } = element.dataset;

const item = parentId
? actor.inventory.get(parentId, { strict: true }).subitems.get(itemId, { strict: true })
: itemUuid
? fromUuid<T>(itemUuid)
: entryId
? actor.spellcasting?.collections
.get(entryId, { strict: true })
.get(itemId, { strict: true }) ?? null
: itemType === "condition"
? actor.conditions.get(itemId, { strict: true })
: actionIndex
? actor.system.actions?.[Number(actionIndex)].item ?? null
: actor.items.get(itemId ?? "") ?? null;

return item as T | null | Promise<T | null>;
}

getMaxHeight(inner?: boolean) {
const { limits } = this.parentHUD.anchor;
const maxHeightRatio = PF2eHudSidebar.getSetting("maxHeight") / 100;
Expand Down Expand Up @@ -370,7 +393,7 @@ abstract class PF2eHudSidebar extends foundry.applications.api

const { label, domain, option } = el.dataset;
const item = (() => {
const item = getItemFromElement(el, this.actor);
const item = this.getItemFromElement(el);
return item instanceof Item ? item : null;
})();

Expand Down Expand Up @@ -407,7 +430,7 @@ abstract class PF2eHudSidebar extends foundry.applications.api
}

addListenerAll(html, "[data-action='send-to-chat']", async (event, el) => {
const item = await getItemFromElement(el, actor);
const item = await this.getItemFromElement(el);
if (!item) return;

if (!isOwnedItem(item)) {
Expand All @@ -431,7 +454,7 @@ abstract class PF2eHudSidebar extends foundry.applications.api

addListenerAll(html, "[data-action='item-description']", async (event, el) => {
const actor = this.actor;
const item = await getItemFromElement(el, actor);
const item = await this.getItemFromElement(el);
if (!item) return;
new PF2eHudItemPopup({ actor, item, event }).render(true);
});
Expand Down
3 changes: 1 addition & 2 deletions src/hud/sidebar/items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
htmlClosest,
tupleHasValue,
} from "foundry-pf2e";
import { getItemFromElement } from "../shared/base";
import { PF2eHudSidebar, SidebarContext, SidebarName, SidebarRenderOptions } from "./base";

class PF2eHudSidebarItems extends PF2eHudSidebar {
Expand Down Expand Up @@ -81,7 +80,7 @@ class PF2eHudSidebarItems extends PF2eHudSidebar {

addListenerAll(html, "[data-action]:not(disabled)", async (event, el) => {
const action = el.dataset.action as ItemsActionEvent;
const item = await getItemFromElement(el, actor);
const item = await this.getItemFromElement(el);
if (!item?.isOfType("physical")) return;

switch (action) {
Expand Down
34 changes: 17 additions & 17 deletions src/hud/sidebar/spells.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ class PF2eHudSidebarSpells extends PF2eHudSidebar {
return target.dataset;
}

getSpellFromElement(target: HTMLElement) {
const spellRow = htmlClosest(target, "[data-item-id]");
const { itemId, entryId, slotId } = spellRow?.dataset ?? {};
const collection = this.actor.spellcasting.collections.get(entryId, {
strict: true,
});

return {
slotId,
collection,
castRank: spellRow?.dataset.castRank,
spell: collection.get(itemId, { strict: true }),
};
}

_activateListeners(html: HTMLElement) {
const actor = this.actor;
const isCharacter = actor.isOfType("character");
Expand Down Expand Up @@ -91,7 +106,7 @@ class PF2eHudSidebarSpells extends PF2eHudSidebar {

switch (action) {
case "cast-spell": {
const { spell, castRank, collection, slotId } = getSpellFromElement(actor, el);
const { spell, castRank, collection, slotId } = this.getSpellFromElement(el);
const maybeCastRank = Number(castRank) || NaN;
if (!Number.isInteger(maybeCastRank) || !maybeCastRank.between(1, 10)) return;

Expand Down Expand Up @@ -125,7 +140,7 @@ class PF2eHudSidebarSpells extends PF2eHudSidebar {
}

case "toggle-signature": {
const { spell } = getSpellFromElement(actor, el);
const { spell } = this.getSpellFromElement(el);
return spell.update({
"system.location.signature": !spell.system.location.signature,
});
Expand All @@ -135,21 +150,6 @@ class PF2eHudSidebarSpells extends PF2eHudSidebar {
}
}

function getSpellFromElement(actor: CreaturePF2e, target: HTMLElement) {
const spellRow = htmlClosest(target, "[data-item-id]");
const { itemId, entryId, slotId } = spellRow?.dataset ?? {};
const collection = actor.spellcasting.collections.get(entryId, {
strict: true,
});

return {
slotId,
collection,
castRank: spellRow?.dataset.castRank,
spell: collection.get(itemId, { strict: true }),
};
}

type SpellDrawData = {
parentId: string;
annotation: NonNullable<AuxiliaryActionPurpose>;
Expand Down

0 comments on commit dbb92ee

Please sign in to comment.