feat: use the selected token as speaker when performing a roll
This commit is contained in:
parent
3b2a7857e1
commit
0fa9d838e2
13 changed files with 57 additions and 61 deletions
|
@ -294,33 +294,43 @@ export class DS4Actor extends Actor {
|
|||
/**
|
||||
* Roll for a given check.
|
||||
* @param check - The check to perform
|
||||
* @param options - Additional options to customize the roll
|
||||
*/
|
||||
async rollCheck(check: Check): Promise<void> {
|
||||
async rollCheck(
|
||||
check: Check,
|
||||
options: { speaker?: { token?: TokenDocument; alias?: string } } = {},
|
||||
): Promise<void> {
|
||||
const speaker = ChatMessage.getSpeaker({ actor: this, ...options.speaker });
|
||||
await createCheckRoll(this.data.data.checks[check], {
|
||||
rollMode: getGame().settings.get("core", "rollMode"),
|
||||
maximumCoupResult: this.data.data.rolling.maximumCoupResult,
|
||||
minimumFumbleResult: this.data.data.rolling.minimumFumbleResult,
|
||||
flavor: "DS4.ActorCheckFlavor",
|
||||
flavorData: { actor: this.name, check: DS4.i18nKeys.checks[check] },
|
||||
flavorData: { actor: speaker.alias ?? this.name, check: DS4.i18nKeys.checks[check] },
|
||||
speaker,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll a generic check. A dialog is presented to select the combination of
|
||||
* Attribute and Trait to perform the check against.
|
||||
* @param options - Additional options to customize the roll
|
||||
*/
|
||||
async rollGenericCheck(): Promise<void> {
|
||||
async rollGenericCheck(options: { speaker?: { token?: TokenDocument; alias?: string } } = {}): Promise<void> {
|
||||
const { attribute, trait } = await this.selectAttributeAndTrait();
|
||||
const checkTargetNumber = this.data.data.attributes[attribute].total + this.data.data.traits[trait].total;
|
||||
const speaker = ChatMessage.getSpeaker({ actor: this, ...options.speaker });
|
||||
await createCheckRoll(checkTargetNumber, {
|
||||
rollMode: getGame().settings.get("core", "rollMode"),
|
||||
maximumCoupResult: this.data.data.rolling.maximumCoupResult,
|
||||
minimumFumbleResult: this.data.data.rolling.minimumFumbleResult,
|
||||
flavor: getGame().i18n.format("DS4.ActorGenericCheckFlavor", {
|
||||
actor: this.name,
|
||||
flavor: "DS4.ActorGenericCheckFlavor",
|
||||
flavorData: {
|
||||
actor: speaker.alias ?? this.name,
|
||||
attribute: DS4.i18n.attributes[attribute],
|
||||
trait: DS4.i18n.traits[trait],
|
||||
}),
|
||||
},
|
||||
speaker,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ export class DS4ItemSheet extends ItemSheet<ItemSheet.Options, DS4ItemSheetData>
|
|||
}
|
||||
|
||||
/** @override */
|
||||
setPosition(options: Partial<Application.Position> = {}): (Application.Position & { height: number }) | undefined {
|
||||
setPosition(options: Partial<Application.Position> = {}): (Application.Position & { height: number }) | void {
|
||||
const position = super.setPosition(options);
|
||||
if (position) {
|
||||
const sheetBody = this.element.find(".sheet-body");
|
||||
|
|
|
@ -64,13 +64,14 @@ export class DS4Item extends Item {
|
|||
|
||||
/**
|
||||
* Roll a check for an action with this item.
|
||||
* @param options - Additional options to customize the roll
|
||||
*/
|
||||
async roll(): Promise<void> {
|
||||
async roll(options: { speaker?: { token?: TokenDocument; alias?: string } } = {}): Promise<void> {
|
||||
switch (this.data.type) {
|
||||
case "weapon":
|
||||
return this.rollWeapon();
|
||||
return this.rollWeapon(options);
|
||||
case "spell":
|
||||
return this.rollSpell();
|
||||
return this.rollSpell(options);
|
||||
default:
|
||||
throw new Error(
|
||||
getGame().i18n.format("DS4.ErrorRollingForItemTypeNotPossible", { type: this.data.type }),
|
||||
|
@ -78,7 +79,7 @@ export class DS4Item extends Item {
|
|||
}
|
||||
}
|
||||
|
||||
protected async rollWeapon(): Promise<void> {
|
||||
protected async rollWeapon(options: { speaker?: { token?: TokenDocument; alias?: string } } = {}): Promise<void> {
|
||||
if (!(this.data.type === "weapon")) {
|
||||
throw new Error(
|
||||
getGame().i18n.format("DS4.ErrorWrongItemType", {
|
||||
|
@ -109,16 +110,18 @@ export class DS4Item extends Item {
|
|||
const combatValue = await this.getCombatValueKeyForAttackType(this.data.data.attackType);
|
||||
const checkTargetNumber = ownerDataData.combatValues[combatValue].total + weaponBonus;
|
||||
|
||||
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
|
||||
await createCheckRoll(checkTargetNumber, {
|
||||
rollMode: getGame().settings.get("core", "rollMode"),
|
||||
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
||||
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
||||
flavor: "DS4.ItemWeaponCheckFlavor",
|
||||
flavorData: { actor: this.actor.name, weapon: this.name },
|
||||
flavorData: { actor: speaker.alias ?? this.actor.name, weapon: this.name },
|
||||
speaker,
|
||||
});
|
||||
}
|
||||
|
||||
protected async rollSpell(): Promise<void> {
|
||||
protected async rollSpell(options: { speaker?: { token?: TokenDocument; alias?: string } } = {}): Promise<void> {
|
||||
if (!(this.data.type === "spell")) {
|
||||
throw new Error(
|
||||
getGame().i18n.format("DS4.ErrorWrongItemType", {
|
||||
|
@ -157,12 +160,14 @@ export class DS4Item extends Item {
|
|||
const spellType = this.data.data.spellType;
|
||||
const checkTargetNumber = ownerDataData.combatValues[spellType].total + (spellBonus ?? 0);
|
||||
|
||||
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
|
||||
await createCheckRoll(checkTargetNumber, {
|
||||
rollMode: getGame().settings.get("core", "rollMode"),
|
||||
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
||||
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
||||
flavor: "DS4.ItemSpellCheckFlavor",
|
||||
flavorData: { actor: this.actor.name, spell: this.name },
|
||||
flavorData: { actor: speaker.alias ?? this.actor.name, spell: this.name },
|
||||
speaker,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -6,20 +6,18 @@ import { DS4Actor } from "../actor/actor";
|
|||
import { getCanvas, getGame } from "../helpers";
|
||||
|
||||
/**
|
||||
* Gets the currently active actor based on how {@link ChatMessage} determines
|
||||
* the current speaker.
|
||||
* @returns The currently active {@link DS4Actor} if any, and `undefined` otherwise.
|
||||
* Gets the currently active actor and token based on how {@link ChatMessage}
|
||||
* determines the current speaker.
|
||||
* @returns The currently active {@link DS4Actor} and {@link TokenDocument}.
|
||||
*/
|
||||
export function getActiveActor(): DS4Actor | undefined {
|
||||
export function getActiveActorAndToken(): { actor?: DS4Actor; token?: TokenDocument } {
|
||||
const speaker = ChatMessage.getSpeaker();
|
||||
|
||||
const speakerToken = speaker.token ? getCanvas().tokens?.get(speaker.token) : undefined;
|
||||
const speakerToken = speaker.token ? getCanvas().tokens?.get(speaker.token)?.document : undefined;
|
||||
if (speakerToken) {
|
||||
return speakerToken.actor ?? undefined;
|
||||
return { actor: speakerToken.actor ?? undefined, token: speakerToken };
|
||||
}
|
||||
|
||||
const speakerActor = speaker.actor ? getGame().actors?.get(speaker.actor) : undefined;
|
||||
if (speakerActor) {
|
||||
return speakerActor;
|
||||
}
|
||||
return { actor: speakerActor };
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Check } from "../actor/actor-data-properties";
|
|||
import { DS4 } from "../config";
|
||||
import { getGame } from "../helpers";
|
||||
import notifications from "../ui/notifications";
|
||||
import { getActiveActor } from "./helpers";
|
||||
import { getActiveActorAndToken } from "./helpers";
|
||||
|
||||
/**
|
||||
* Creates a macro from a check drop.
|
||||
|
@ -45,10 +45,10 @@ async function getOrCreateRollCheckMacro(check: Check): Promise<Macro | undefine
|
|||
* Executes the roll check macro for the given check.
|
||||
*/
|
||||
export async function rollCheck(check: Check): Promise<void> {
|
||||
const actor = getActiveActor();
|
||||
const { actor, token } = getActiveActorAndToken();
|
||||
if (!actor) {
|
||||
return notifications.warn(getGame().i18n.localize("DS4.WarningMustControlActorToUseRollCheckMacro"));
|
||||
}
|
||||
|
||||
return actor.rollCheck(check).catch((e) => notifications.error(e, { log: true }));
|
||||
return actor.rollCheck(check, { speaker: { token } }).catch((e) => notifications.error(e, { log: true }));
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
|
||||
import { getGame } from "../helpers";
|
||||
import notifications from "../ui/notifications";
|
||||
import { getActiveActor } from "./helpers";
|
||||
import { getActiveActorAndToken } from "./helpers";
|
||||
|
||||
/**
|
||||
* Executes the roll generic check macro.
|
||||
*/
|
||||
export async function rollGenericCheck(): Promise<void> {
|
||||
const actor = getActiveActor();
|
||||
const { actor, token } = getActiveActorAndToken();
|
||||
if (!actor) {
|
||||
return notifications.warn(getGame().i18n.localize("DS4.WarningMustControlActorToUseRollCheckMacro"));
|
||||
}
|
||||
|
||||
return actor.rollGenericCheck().catch((e) => notifications.error(e, { log: true }));
|
||||
return actor.rollGenericCheck({ speaker: { token } }).catch((e) => notifications.error(e, { log: true }));
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
import { getGame } from "../helpers";
|
||||
import notifications from "../ui/notifications";
|
||||
import { getActiveActor } from "./helpers";
|
||||
import { getActiveActorAndToken } from "./helpers";
|
||||
|
||||
/**
|
||||
* Creates a macro from an item drop.
|
||||
|
@ -41,7 +41,7 @@ async function getOrCreateRollItemMacro(itemData: foundry.data.ItemData["_source
|
|||
* Executes the roll item macro for the item associated to the given `itemId`.
|
||||
*/
|
||||
export async function rollItem(itemId: string): Promise<void> {
|
||||
const actor = getActiveActor();
|
||||
const { actor, token } = getActiveActorAndToken();
|
||||
if (!actor) {
|
||||
return notifications.warn(getGame().i18n.localize("DS4.WarningMustControlActorToUseRollItemMacro"));
|
||||
}
|
||||
|
@ -57,5 +57,5 @@ export async function rollItem(itemId: string): Promise<void> {
|
|||
);
|
||||
}
|
||||
|
||||
return item.roll().catch((e) => notifications.error(e, { log: true }));
|
||||
return item.roll({ speaker: { token } }).catch((e) => notifications.error(e, { log: true }));
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class CheckFactory {
|
|||
);
|
||||
const formula = this.options.useSlayingDice ? `{${innerFormula}}x` : innerFormula;
|
||||
const roll = Roll.create(formula);
|
||||
const speaker = ChatMessage.getSpeaker();
|
||||
const speaker = this.options.speaker ?? ChatMessage.getSpeaker();
|
||||
|
||||
return roll.toMessage(
|
||||
{
|
||||
|
@ -96,6 +96,7 @@ export async function createCheckRoll(
|
|||
rollMode: gmModifierData.rollMode ?? options.rollMode,
|
||||
flavor: options.flavor,
|
||||
flavorData: options.flavorData,
|
||||
speaker: options.speaker,
|
||||
};
|
||||
|
||||
// Create Factory
|
||||
|
@ -230,4 +231,5 @@ export interface DS4CheckFactoryOptions {
|
|||
rollMode: foundry.CONST.DiceRollMode;
|
||||
flavor?: string;
|
||||
flavorData?: Record<string, string | number | null>;
|
||||
speaker?: ReturnType<typeof ChatMessage.getSpeaker>;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue