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
|
@ -56,7 +56,7 @@
|
|||
"devDependencies": {
|
||||
"@commitlint/cli": "13.1.0",
|
||||
"@commitlint/config-conventional": "13.1.0",
|
||||
"@league-of-foundry-developers/foundry-vtt-types": "0.8.8-9",
|
||||
"@league-of-foundry-developers/foundry-vtt-types": "0.8.9-3",
|
||||
"@types/fs-extra": "9.0.12",
|
||||
"@types/jest": "27.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "4.31.1",
|
||||
|
|
|
@ -274,6 +274,7 @@
|
|||
"DS4.SettingUseSlayingDiceForAutomatedChecksHint": "Benutze Slayende Würfel bei automatisierten Proben.",
|
||||
"DS4.SettingShowSlayerPointsName": "Slayerpunkte",
|
||||
"DS4.SettingShowSlayerPointsHint": "Zeige Slayerpunkte im Charakterbogen an.",
|
||||
"DS4.Checks": "Proben",
|
||||
"DS4.ChecksAppraise": "Schätzen",
|
||||
"DS4.ChecksChangeSpell": "Zauber Wechseln",
|
||||
"DS4.ChecksClimb": "Klettern",
|
||||
|
|
|
@ -274,6 +274,7 @@
|
|||
"DS4.SettingUseSlayingDiceForAutomatedChecksHint": "Use Slaying Dice for automated checks.",
|
||||
"DS4.SettingShowSlayerPointsName": "Slayer Points",
|
||||
"DS4.SettingShowSlayerPointsHint": "Show Slayer Points in the character sheet.",
|
||||
"DS4.Checks": "Checks",
|
||||
"DS4.ChecksAppraise": "Appraise",
|
||||
"DS4.ChecksChangeSpell": "Change Spell",
|
||||
"DS4.ChecksClimb": "Climb",
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"bugs": "https://git.f3l.de/dungeonslayers/ds4/-/issues",
|
||||
"changelog": "https://git.f3l.de/dungeonslayers/ds4/-/releases/1.5.0",
|
||||
"version": "1.5.0",
|
||||
"minimumCoreVersion": "0.8.8",
|
||||
"minimumCoreVersion": "0.8.9",
|
||||
"compatibleCoreVersion": "0.8.9",
|
||||
"esmodules": ["module/ds4.js"],
|
||||
"styles": ["css/ds4.css"],
|
||||
|
|
31
yarn.lock
31
yarn.lock
|
@ -868,9 +868,9 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@league-of-foundry-developers/foundry-vtt-types@npm:0.8.8-9":
|
||||
version: 0.8.8-9
|
||||
resolution: "@league-of-foundry-developers/foundry-vtt-types@npm:0.8.8-9"
|
||||
"@league-of-foundry-developers/foundry-vtt-types@npm:0.8.9-3":
|
||||
version: 0.8.9-3
|
||||
resolution: "@league-of-foundry-developers/foundry-vtt-types@npm:0.8.9-3"
|
||||
dependencies:
|
||||
"@types/jquery": ~3.5.6
|
||||
"@types/simple-peer": ~9.11.1
|
||||
|
@ -879,8 +879,7 @@ __metadata:
|
|||
pixi.js: 5.3.4
|
||||
socket.io-client: 4.1.2
|
||||
tinymce: 5.8.1
|
||||
typescript: ^4.3.5
|
||||
checksum: 0c217a2bb2a1f9ae87548511d5e835648aee03522e0ea7c374bbc3c9152ad8a6568cc4f421fbd14c6b81434df9057eae2e6217371accd417a7455a993a7c4108
|
||||
checksum: 01f4bd4ea4b01a51a1f0572a683817ad63dc4daa46bbf0ed5fa6854bc88eb57269d0940575efbf58e984f0b6a16c78d166dbd19c7d0719a9750e7bbe1c2b66ac
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -3366,7 +3365,7 @@ __metadata:
|
|||
dependencies:
|
||||
"@commitlint/cli": 13.1.0
|
||||
"@commitlint/config-conventional": 13.1.0
|
||||
"@league-of-foundry-developers/foundry-vtt-types": 0.8.8-9
|
||||
"@league-of-foundry-developers/foundry-vtt-types": 0.8.9-3
|
||||
"@types/fs-extra": 9.0.12
|
||||
"@types/jest": 27.0.1
|
||||
"@typescript-eslint/eslint-plugin": 4.31.1
|
||||
|
@ -9160,16 +9159,6 @@ typescript@4.4.3:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
typescript@^4.3.5:
|
||||
version: 4.3.5
|
||||
resolution: "typescript@npm:4.3.5"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: bab033b5e2b0790dd35b77fd005df976ef80b8d84fd2c6e63cc31808151875beae9216e5a315fe7068e8499905c3c354248fe83272cdfc13b7705635f0c66c97
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@4.4.3#~builtin<compat/typescript>":
|
||||
version: 4.4.3
|
||||
resolution: "typescript@patch:typescript@npm%3A4.4.3#~builtin<compat/typescript>::version=4.4.3&hash=32657b"
|
||||
|
@ -9180,16 +9169,6 @@ typescript@^4.3.5:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@^4.3.5#~builtin<compat/typescript>":
|
||||
version: 4.3.5
|
||||
resolution: "typescript@patch:typescript@npm%3A4.3.5#~builtin<compat/typescript>::version=4.3.5&hash=32657b"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 4e2edec3c9b7b9a22ad9cbf9371339d9e13bfe44731f0e2d6a5287f991c3b0e3e0ac0c0ebbf9bf6fc2051e30559c789bfc9cf572cd6b836a0222ae141fac1dba
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"uglify-js@npm:^3.1.4":
|
||||
version: 3.14.1
|
||||
resolution: "uglify-js@npm:3.14.1"
|
||||
|
|
Loading…
Reference in a new issue