Skip to content

Commit

Permalink
Merge branch 'ctrl-click-roll-npcs' into 'master'
Browse files Browse the repository at this point in the history
Add support for CTRL-clicking (secret) roll buttons from the encounter tracker

See merge request hooking/foundry-vtt---pathfinder-2e!6173
  • Loading branch information
CarlosFdez committed Nov 26, 2021
2 parents 230883a + 9a62fd7 commit 4e854ad
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 10 deletions.
4 changes: 4 additions & 0 deletions src/module/actor/data/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export type SaveType = typeof SAVE_TYPES[number];

export type ModeOfBeing = "living" | "undead" | "construct" | "object";

export interface RollInitiativeOptionsPF2e extends RollInitiativeOptions {
secret?: boolean;
}

export {
AbilityString,
CharacterData,
Expand Down
36 changes: 33 additions & 3 deletions src/module/apps/ui/encounter-tracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,41 @@ export class EncounterTrackerPF2e extends CombatTracker<CombatPF2e> {
});
}

/* -------------------------------------------- */
/* Event Listeners and Handlers */
/* -------------------------------------------- */

/** Allow CTRL-clicking to make the rolls blind */
protected override async _onCombatControl(
event: JQuery.ClickEvent<HTMLElement, HTMLElement, HTMLElement>
): Promise<void> {
const control = event.currentTarget.dataset.control;
if ((control === "rollNPC" || control === "rollAll") && this.viewed && event.ctrlKey) {
await this.viewed[control]({ secret: true });
} else {
await super._onCombatControl(event);
}
}

/** Allow CTRL-clicking to make the roll blind */
protected override async _onCombatantControl(
event: JQuery.ClickEvent<HTMLElement, HTMLElement, HTMLElement>
): Promise<void> {
const control = event.currentTarget.dataset.control;
if (control === "rollInitiative" && this.viewed && event.ctrlKey) {
const li = event.currentTarget.closest<HTMLLIElement>(".combatant");
const combatant = this.viewed.combatants.get(li?.dataset.combatantId ?? "", { strict: true });
await this.viewed.rollInitiative([combatant.id], { secret: true });
} else {
await super._onCombatantControl(event);
}
}

/** Handle the drop event of a dragged & dropped combatant */
private async onDropCombatant(event: SortableEvent): Promise<void> {
this.validateDrop(event);

const combat = game.combat!;
const combat = this.viewed!;
const droppedId = event.item.getAttribute("data-combatant-id") ?? "";
const dropped = combat.combatants.get(droppedId, { strict: true }) as RolledCombatant;
if (typeof dropped.initiative !== "number") {
Expand Down Expand Up @@ -71,10 +101,10 @@ export class EncounterTrackerPF2e extends CombatTracker<CombatPF2e> {
/** Save the new order, or reset the viewed order if no change was made */
private async saveNewOrder(): Promise<void> {
const newOrder = this.getCombatantsFromDOM();
const oldOrder = game.combat?.turns.filter((c) => c.initiative !== null) ?? [];
const oldOrder = this.viewed?.turns.filter((c) => c.initiative !== null) ?? [];
const orderWasChanged = newOrder.some((c) => newOrder.indexOf(c) !== oldOrder.indexOf(c));
if (orderWasChanged) {
await game.combat?.setMultipleInitiatives(newOrder.map((c) => ({ id: c.id, value: c.initiative })));
await this.viewed?.setMultipleInitiatives(newOrder.map((c) => ({ id: c.id, value: c.initiative })));
} else {
console.debug("No order change!?");
this.render();
Expand Down
17 changes: 14 additions & 3 deletions src/module/combat.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CharacterPF2e, HazardPF2e, NPCPF2e } from "@actor";
import { CharacterSheetPF2e } from "@actor/character/sheet";
import { RollInitiativeOptionsPF2e } from "@actor/data";
import { SKILL_DICTIONARY } from "@actor/data/values";
import { LocalizePF2e } from "@system/localize";
import { CombatantPF2e, RolledCombatant } from "./combatant";
Expand Down Expand Up @@ -71,7 +72,7 @@ export class CombatPF2e extends Combat<CombatantPF2e> {
}

/** Roll initiative for PCs and NPCs using their prepared roll methods */
override async rollInitiative(ids: string[], options: RollInitiativeOptions = {}): Promise<this> {
override async rollInitiative(ids: string[], options: RollInitiativeOptionsPF2e = {}): Promise<this> {
const combatants = ids.flatMap((id) => this.combatants.get(id) ?? []);
const fightyCombatants = combatants.filter(
(combatant): combatant is Embedded<CombatantPF2e<CharacterPF2e | NPCPF2e>> =>
Expand All @@ -81,8 +82,16 @@ export class CombatPF2e extends Combat<CombatantPF2e> {
fightyCombatants.map((combatant) => {
const checkType = combatant.actor.data.data.attributes.initiative.ability;
const skills: Record<string, string | undefined> = SKILL_DICTIONARY;
const options = combatant.actor.getRollOptions(["all", "initiative", skills[checkType] ?? checkType]);
return combatant.actor.data.data.attributes.initiative.roll({ options, updateTracker: false });
const rollOptions = combatant.actor.getRollOptions([
"all",
"initiative",
skills[checkType] ?? checkType,
]);
if (options.secret) rollOptions.push("secret");
return combatant.actor.data.data.attributes.initiative.roll({
options: rollOptions,
updateTracker: false,
});
})
);

Expand Down Expand Up @@ -148,4 +157,6 @@ export class CombatPF2e extends Combat<CombatantPF2e> {

export interface CombatPF2e {
readonly data: foundry.data.CombatData<this, CombatantPF2e>;

rollNPC(options: RollInitiativeOptionsPF2e): Promise<this>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,16 @@ declare class CombatTracker<
TCombat extends Combat,
TOptions extends CombatTrackerOptions = CombatTrackerOptions
> extends SidebarTab<TOptions> {
constructor(options?: Partial<TOptions>);

static override get defaultOptions(): CombatTrackerOptions;

/** Record a reference to the currently highlighted Token */
protected _highlighted: CollectionValue<TCombat["combatants"]>["token"];

/** Record the currently tracked Combat encounter */
viewed: TCombat | null;

constructor(options?: Partial<TOptions>);

/** Return an array of Combat encounters which occur within the current Scene. */
get combats(): TCombat[];

Expand Down Expand Up @@ -89,13 +95,13 @@ declare class CombatTracker<
* Handle click events on Combat control buttons
* @param event The originating mousedown event
*/
protected _onCombatControl(event: JQuery.TriggeredEvent<HTMLElement, HTMLElement, HTMLElement>): Promise<void>;
protected _onCombatControl(event: JQuery.ClickEvent<HTMLElement, HTMLElement, HTMLElement>): Promise<void>;

/**
* Handle a Combatant control toggle
* @param event The originating mousedown event
*/
protected _onCombatantControl(event: MouseEvent): Promise<void>;
protected _onCombatantControl(event: JQuery.ClickEvent<HTMLElement, HTMLElement, HTMLElement>): Promise<void>;

/**
* Handle toggling the defeated status effect on a combatant Token
Expand Down

0 comments on commit 4e854ad

Please sign in to comment.