Skip to content
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
50 changes: 24 additions & 26 deletions src/module/actor/character/apps/attack-popout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import type { ApplicationV1HeaderButton } from "@client/appv1/api/application-v1
import type { ActorSheetOptions } from "@client/appv1/sheets/actor-sheet.d.mts";
import type { EffectTrait } from "@item/abstract-effect/types.ts";
import { ErrorPF2e, htmlClosest, htmlQuery } from "@util";
import type { CharacterStrike } from "../data.ts";
import type { CharacterAttack } from "../data.ts";
import type { CharacterPF2e } from "../document.ts";
import type { ElementalBlastConfig } from "../elemental-blast.ts";
import { CharacterSheetPF2e, type CharacterSheetData } from "../sheet.ts";

class AttackPopout<TActor extends CharacterPF2e> extends CharacterSheetPF2e<TActor> {
type: "strike" | "blast" = "strike";
#strikeItemId = "";
#strikeSlug = "";
#strike?: CharacterStrike;
type: AttackPopoutOptions["type"] = "strike";
#itemId = "";
#slug = "";
#attack?: CharacterAttack;
#elementTrait?: EffectTrait;
#blasts: ElementalBlastConfig[] = [];

Expand All @@ -21,9 +21,9 @@ class AttackPopout<TActor extends CharacterPF2e> extends CharacterSheetPF2e<TAct

override get id(): string {
const id = super.id;
return this.type === "strike"
? `${id}-strike-${this.#strikeItemId}-${this.#strikeSlug}`
: `${id}-blast-${this.#elementTrait}`;
return this.type === "blast"
? `${id}-blast-${this.#elementTrait}`
: `${id}-${this.type}-${this.#itemId}-${this.#slug}`;
}

static override get defaultOptions(): ActorSheetOptions {
Expand All @@ -43,7 +43,7 @@ class AttackPopout<TActor extends CharacterPF2e> extends CharacterSheetPF2e<TAct
if (this.type === "blast") {
return this.#blasts.at(0)?.label ?? null;
}
return this.#strike?.label ?? null;
return this.#attack?.label ?? null;
}

constructor(object: TActor, options: AttackPopoutOptions) {
Expand All @@ -59,14 +59,14 @@ class AttackPopout<TActor extends CharacterPF2e> extends CharacterSheetPF2e<TAct
}
this.#elementTrait = options.elementTrait;
} else {
if (!options.strikeSlug) {
throw ErrorPF2e('AttackPopout of type "strike" is missing mandatory "strikeSlug" option.');
if (!options.slug) {
throw ErrorPF2e('AttackPopout of type "strike" is missing mandatory "slug" option.');
}
if (!options.strikeItemId) {
throw ErrorPF2e('AttackPopout of type "strike" is missing mandatory "strikeItemId" option.');
if (!options.itemId) {
throw ErrorPF2e('AttackPopout of type "strike" is missing mandatory "itemId" option.');
}
this.#strikeSlug = options.strikeSlug;
this.#strikeItemId = options.strikeItemId;
this.#slug = options.slug;
this.#itemId = options.itemId;
}
this.type = options.type;
}
Expand All @@ -80,17 +80,15 @@ class AttackPopout<TActor extends CharacterPF2e> extends CharacterSheetPF2e<TAct
base.toggles.actions = base.toggles.actions?.filter((t) => t.domain === "elemental-blast") ?? [];
} else {
base.elementalBlasts = [];
if (this.#strikeSlug && this.#strikeItemId) {
this.#strike = base.data.actions.find(
(a) => a.item.id === this.#strikeItemId && a.slug === this.#strikeSlug,
);
if (this.#slug && this.#itemId) {
this.#attack = base.data.actions.find((a) => a.item.id === this.#itemId && a.slug === this.#slug);
}
}

return {
...base,
strike: this.#strike,
strikeIndex: base.data.actions.findIndex((a) => a === this.#strike),
attack: this.#attack,
index: base.data.actions.findIndex((a) => a === this.#attack),
popoutType: this.type,
};
}
Expand Down Expand Up @@ -120,9 +118,9 @@ interface BaseAttackPopoutOptions extends Partial<ActorSheetOptions> {
}

interface StrikePopoutOptions extends BaseAttackPopoutOptions {
type: "strike";
strikeSlug?: string;
strikeItemId?: string;
type: "strike" | "area-fire" | "auto-fire";
slug?: string;
itemId?: string;
}

interface BlastPopoutOptions extends BaseAttackPopoutOptions {
Expand All @@ -133,8 +131,8 @@ interface BlastPopoutOptions extends BaseAttackPopoutOptions {
type AttackPopoutOptions = StrikePopoutOptions | BlastPopoutOptions;

interface AttackPopoutData<TActor extends CharacterPF2e> extends CharacterSheetData<TActor> {
strike?: CharacterStrike;
strikeIndex?: number;
attack?: CharacterAttack;
index?: number;
popoutType: AttackPopoutOptions["type"];
}

Expand Down
28 changes: 21 additions & 7 deletions src/module/actor/character/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { CreatureInitiativeSource, Language } from "@actor/creature/index.ts";
import {
ActorAttributesSource,
ActorFlagsPF2e,
AreaAttack,
AttributeBasedTraceData,
HitPointsStatistic,
InitiativeData,
Expand Down Expand Up @@ -268,7 +269,7 @@ interface CharacterSystemData extends Omit<CharacterSystemSource, SourceOmission
skills: Record<string, CharacterSkillData>;

/** Special strikes which the character can take. */
actions: CharacterStrike[];
actions: CharacterAttack[];

resources: CharacterResources;

Expand Down Expand Up @@ -388,22 +389,33 @@ interface ClassDCData extends Required<AttributeBasedTraceData> {
primary: boolean;
}

/** The full data for a character strike */
interface CharacterStrike extends StrikeData {
item: WeaponPF2e<CharacterPF2e>;
interface BasicAttackData {
/** Whether this attack is visible on the sheet */
visible: boolean;
auxiliaryActions: WeaponAuxiliaryAction[];
weaponTraits: TraitViewData[];
}

/** The full data for a character strike */
interface CharacterStrike extends StrikeData, BasicAttackData {
item: WeaponPF2e<CharacterPF2e>;
/** Domains/selectors from which modifiers are drawn */
domains: string[];
/** Whether the character has sufficient hands available to wield this weapon or use this unarmed attack */
handsAvailable: boolean;
altUsages: CharacterStrike[];
auxiliaryActions: WeaponAuxiliaryAction[];
weaponTraits: TraitViewData[];
altUsages: CharacterAttack[];
doubleBarrel: { selected: boolean } | null;
versatileOptions: VersatileWeaponOption[];
}

interface CharacterAreaAttack extends AreaAttack, BasicAttackData {
item: WeaponPF2e<CharacterPF2e>;
/** Whether this attack is visible on the sheet */
altUsages: CharacterAttack[];
}

type CharacterAttack = CharacterStrike | CharacterAreaAttack;

interface VersatileWeaponOption {
value: DamageType;
selected: boolean;
Expand Down Expand Up @@ -504,6 +516,8 @@ export type {
BaseWeaponProficiencyKey,
CategoryProficiencies,
CharacterAbilities,
CharacterAreaAttack,
CharacterAttack,
CharacterAttributes,
CharacterAttributesSource,
CharacterBiography,
Expand Down
Loading