Skip to content

Commit 29963dc

Browse files
authored
Implement Area Fire and Auto Fire for PCs (#20500)
1 parent eecd1f7 commit 29963dc

File tree

23 files changed

+443
-151
lines changed

23 files changed

+443
-151
lines changed

src/module/actor/character/apps/attack-popout.ts

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ import type { ApplicationV1HeaderButton } from "@client/appv1/api/application-v1
22
import type { ActorSheetOptions } from "@client/appv1/sheets/actor-sheet.d.mts";
33
import type { EffectTrait } from "@item/abstract-effect/types.ts";
44
import { ErrorPF2e, htmlClosest, htmlQuery } from "@util";
5-
import type { CharacterStrike } from "../data.ts";
5+
import type { CharacterAttack } from "../data.ts";
66
import type { CharacterPF2e } from "../document.ts";
77
import type { ElementalBlastConfig } from "../elemental-blast.ts";
88
import { CharacterSheetPF2e, type CharacterSheetData } from "../sheet.ts";
99

1010
class AttackPopout<TActor extends CharacterPF2e> extends CharacterSheetPF2e<TActor> {
11-
type: "strike" | "blast" = "strike";
12-
#strikeItemId = "";
13-
#strikeSlug = "";
14-
#strike?: CharacterStrike;
11+
type: AttackPopoutOptions["type"] = "strike";
12+
#itemId = "";
13+
#slug = "";
14+
#attack?: CharacterAttack;
1515
#elementTrait?: EffectTrait;
1616
#blasts: ElementalBlastConfig[] = [];
1717

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

2222
override get id(): string {
2323
const id = super.id;
24-
return this.type === "strike"
25-
? `${id}-strike-${this.#strikeItemId}-${this.#strikeSlug}`
26-
: `${id}-blast-${this.#elementTrait}`;
24+
return this.type === "blast"
25+
? `${id}-blast-${this.#elementTrait}`
26+
: `${id}-${this.type}-${this.#itemId}-${this.#slug}`;
2727
}
2828

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

4949
constructor(object: TActor, options: AttackPopoutOptions) {
@@ -59,14 +59,14 @@ class AttackPopout<TActor extends CharacterPF2e> extends CharacterSheetPF2e<TAct
5959
}
6060
this.#elementTrait = options.elementTrait;
6161
} else {
62-
if (!options.strikeSlug) {
63-
throw ErrorPF2e('AttackPopout of type "strike" is missing mandatory "strikeSlug" option.');
62+
if (!options.slug) {
63+
throw ErrorPF2e('AttackPopout of type "strike" is missing mandatory "slug" option.');
6464
}
65-
if (!options.strikeItemId) {
66-
throw ErrorPF2e('AttackPopout of type "strike" is missing mandatory "strikeItemId" option.');
65+
if (!options.itemId) {
66+
throw ErrorPF2e('AttackPopout of type "strike" is missing mandatory "itemId" option.');
6767
}
68-
this.#strikeSlug = options.strikeSlug;
69-
this.#strikeItemId = options.strikeItemId;
68+
this.#slug = options.slug;
69+
this.#itemId = options.itemId;
7070
}
7171
this.type = options.type;
7272
}
@@ -80,17 +80,15 @@ class AttackPopout<TActor extends CharacterPF2e> extends CharacterSheetPF2e<TAct
8080
base.toggles.actions = base.toggles.actions?.filter((t) => t.domain === "elemental-blast") ?? [];
8181
} else {
8282
base.elementalBlasts = [];
83-
if (this.#strikeSlug && this.#strikeItemId) {
84-
this.#strike = base.data.actions.find(
85-
(a) => a.item.id === this.#strikeItemId && a.slug === this.#strikeSlug,
86-
);
83+
if (this.#slug && this.#itemId) {
84+
this.#attack = base.data.actions.find((a) => a.item.id === this.#itemId && a.slug === this.#slug);
8785
}
8886
}
8987

9088
return {
9189
...base,
92-
strike: this.#strike,
93-
strikeIndex: base.data.actions.findIndex((a) => a === this.#strike),
90+
attack: this.#attack,
91+
index: base.data.actions.findIndex((a) => a === this.#attack),
9492
popoutType: this.type,
9593
};
9694
}
@@ -120,9 +118,9 @@ interface BaseAttackPopoutOptions extends Partial<ActorSheetOptions> {
120118
}
121119

122120
interface StrikePopoutOptions extends BaseAttackPopoutOptions {
123-
type: "strike";
124-
strikeSlug?: string;
125-
strikeItemId?: string;
121+
type: "strike" | "area-fire" | "auto-fire";
122+
slug?: string;
123+
itemId?: string;
126124
}
127125

128126
interface BlastPopoutOptions extends BaseAttackPopoutOptions {
@@ -133,8 +131,8 @@ interface BlastPopoutOptions extends BaseAttackPopoutOptions {
133131
type AttackPopoutOptions = StrikePopoutOptions | BlastPopoutOptions;
134132

135133
interface AttackPopoutData<TActor extends CharacterPF2e> extends CharacterSheetData<TActor> {
136-
strike?: CharacterStrike;
137-
strikeIndex?: number;
134+
attack?: CharacterAttack;
135+
index?: number;
138136
popoutType: AttackPopoutOptions["type"];
139137
}
140138

src/module/actor/character/data.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { CreatureInitiativeSource, Language } from "@actor/creature/index.ts";
1818
import {
1919
ActorAttributesSource,
2020
ActorFlagsPF2e,
21+
AreaAttack,
2122
AttributeBasedTraceData,
2223
HitPointsStatistic,
2324
InitiativeData,
@@ -268,7 +269,7 @@ interface CharacterSystemData extends Omit<CharacterSystemSource, SourceOmission
268269
skills: Record<string, CharacterSkillData>;
269270

270271
/** Special strikes which the character can take. */
271-
actions: CharacterStrike[];
272+
actions: CharacterAttack[];
272273

273274
resources: CharacterResources;
274275

@@ -388,22 +389,33 @@ interface ClassDCData extends Required<AttributeBasedTraceData> {
388389
primary: boolean;
389390
}
390391

391-
/** The full data for a character strike */
392-
interface CharacterStrike extends StrikeData {
393-
item: WeaponPF2e<CharacterPF2e>;
392+
interface BasicAttackData {
394393
/** Whether this attack is visible on the sheet */
395394
visible: boolean;
395+
auxiliaryActions: WeaponAuxiliaryAction[];
396+
weaponTraits: TraitViewData[];
397+
}
398+
399+
/** The full data for a character strike */
400+
interface CharacterStrike extends StrikeData, BasicAttackData {
401+
item: WeaponPF2e<CharacterPF2e>;
396402
/** Domains/selectors from which modifiers are drawn */
397403
domains: string[];
398404
/** Whether the character has sufficient hands available to wield this weapon or use this unarmed attack */
399405
handsAvailable: boolean;
400-
altUsages: CharacterStrike[];
401-
auxiliaryActions: WeaponAuxiliaryAction[];
402-
weaponTraits: TraitViewData[];
406+
altUsages: CharacterAttack[];
403407
doubleBarrel: { selected: boolean } | null;
404408
versatileOptions: VersatileWeaponOption[];
405409
}
406410

411+
interface CharacterAreaAttack extends AreaAttack, BasicAttackData {
412+
item: WeaponPF2e<CharacterPF2e>;
413+
/** Whether this attack is visible on the sheet */
414+
altUsages: CharacterAttack[];
415+
}
416+
417+
type CharacterAttack = CharacterStrike | CharacterAreaAttack;
418+
407419
interface VersatileWeaponOption {
408420
value: DamageType;
409421
selected: boolean;
@@ -504,6 +516,8 @@ export type {
504516
BaseWeaponProficiencyKey,
505517
CategoryProficiencies,
506518
CharacterAbilities,
519+
CharacterAreaAttack,
520+
CharacterAttack,
507521
CharacterAttributes,
508522
CharacterAttributesSource,
509523
CharacterBiography,

0 commit comments

Comments
 (0)