Merge pull request #64 from Eldritch-Oliver/feature/haste-roll-shortcut
Added a button to roll for hasty turns in the Actor Stats sheet
This commit is contained in:
commit
a6047ff009
12 changed files with 169 additions and 18 deletions
|
|
@ -1,7 +1,6 @@
|
|||
import { CraftCardV1 } from "./CraftCardV1.mjs";
|
||||
import { filePath } from "../../consts.mjs";
|
||||
import { GenericAppMixin } from "../GenericApp.mjs";
|
||||
import { Logger } from "../../utils/Logger.mjs";
|
||||
import { SkillsCardV1 } from "./SkillsCardV1.mjs";
|
||||
import { StatsCardV1 } from "./StatsCardV1.mjs";
|
||||
|
||||
|
|
@ -23,7 +22,9 @@ export class CombinedHeroSheet extends GenericAppMixin(HandlebarsApplicationMixi
|
|||
window: {
|
||||
resizable: false,
|
||||
},
|
||||
actions: {},
|
||||
actions: {
|
||||
...StatsCardV1.DEFAULT_OPTIONS.actions,
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { deleteItemFromElement, editItemFromElement } from "../utils.mjs";
|
||||
import { DelveDiceHUD } from "../DelveDiceHUD.mjs";
|
||||
import { filePath } from "../../consts.mjs";
|
||||
import { gameTerms } from "../../gameTerms.mjs";
|
||||
import { GenericAppMixin } from "../GenericApp.mjs";
|
||||
|
|
@ -25,6 +26,7 @@ export class StatsCardV1 extends GenericAppMixin(HandlebarsApplicationMixin(Acto
|
|||
resizable: false,
|
||||
},
|
||||
actions: {
|
||||
rollForHaste: DelveDiceHUD.rollForHaste,
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { Logger } from "../utils/Logger.mjs";
|
|||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
const { ContextMenu } = foundry.applications.ux;
|
||||
const { Roll } = foundry.dice;
|
||||
const { FatePath } = gameTerms;
|
||||
|
||||
const CompassRotations = {
|
||||
|
|
@ -189,18 +190,7 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
/** @this {DelveDiceHUD} */
|
||||
static async #tourDelta(_event, element) {
|
||||
const delta = parseInt(element.dataset.delta);
|
||||
const initial = game.settings.get(`ripcrypt`, `sandsOfFateInitial`);
|
||||
let newSands = this._sandsOfFate + delta;
|
||||
|
||||
if (newSands > initial) {
|
||||
Logger.info(`Cannot go to a previous Delve Tour above the initial value`);
|
||||
return;
|
||||
};
|
||||
|
||||
if (newSands === 0) {
|
||||
newSands = initial;
|
||||
await this.alertCrypticEvent();
|
||||
};
|
||||
await this.sandsOfFateDelta(delta);
|
||||
|
||||
switch (Math.sign(delta)) {
|
||||
case -1: {
|
||||
|
|
@ -212,9 +202,6 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
break;
|
||||
}
|
||||
};
|
||||
|
||||
this.#animateSandsTo(newSands);
|
||||
game.settings.set(`ripcrypt`, `sandsOfFate`, newSands);
|
||||
};
|
||||
|
||||
/** @this {DelveDiceHUD} */
|
||||
|
|
@ -247,5 +234,63 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
game.togglePause(true, { broadcast: true });
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the current Sands of Fate by an amount provided, animating the
|
||||
* @param {number} delta The amount of change
|
||||
*/
|
||||
async sandsOfFateDelta(delta) {
|
||||
const initial = game.settings.get(`ripcrypt`, `sandsOfFateInitial`);
|
||||
let newSands = this._sandsOfFate + delta;
|
||||
|
||||
if (newSands > initial) {
|
||||
Logger.info(`Cannot increase the Sands of Fate to a value about the initial`);
|
||||
return;
|
||||
};
|
||||
|
||||
if (newSands === 0) {
|
||||
newSands = initial;
|
||||
await this.alertCrypticEvent();
|
||||
};
|
||||
|
||||
this.#animateSandsTo(newSands);
|
||||
game.settings.set(`ripcrypt`, `sandsOfFate`, newSands);
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper method that rolls the dice required for hasty turns while delving
|
||||
* and adjusts the Sands of Fate accordingly
|
||||
*/
|
||||
static async rollForHaste() {
|
||||
const shouldUpdateSands = game.settings.get(`ripcrypt`, `allowUpdateSandsSocket`);
|
||||
if (shouldUpdateSands && game.users.activeGM == null) {
|
||||
ui.notifications.error(localizer(`RipCrypt.notifs.error.no-active-gm`));
|
||||
return;
|
||||
};
|
||||
|
||||
const roll = new Roll(`1d8xo=1`);
|
||||
await roll.evaluate();
|
||||
|
||||
let delta = 0;
|
||||
if (roll.dice[0].results[0].exploded) {
|
||||
delta = -1;
|
||||
if (roll.dice[0].results[1].result === 1) {
|
||||
delta = -2;
|
||||
};
|
||||
};
|
||||
|
||||
roll.toMessage({ flavor: `Haste Check` });
|
||||
|
||||
// Change the Sands of Fate setting if required
|
||||
if (delta === 0 || !shouldUpdateSands) { return };
|
||||
if (game.user.isActiveGM) {
|
||||
ui.delveDice.sandsOfFateDelta(delta);
|
||||
} else {
|
||||
game.socket.emit(`system.ripcrypt`, {
|
||||
event: `updateSands`,
|
||||
payload: { delta },
|
||||
});
|
||||
};
|
||||
};
|
||||
// #endregion
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import { Logger } from "../utils/Logger.mjs";
|
|||
import { registerCustomComponents } from "../Apps/components/_index.mjs";
|
||||
import { registerDevSettings } from "../settings/devSettings.mjs";
|
||||
import { registerMetaSettings } from "../settings/metaSettings.mjs";
|
||||
import { registerSockets } from "../sockets/_index.mjs";
|
||||
import { registerUserSettings } from "../settings/userSettings.mjs";
|
||||
import { registerWorldSettings } from "../settings/worldSettings.mjs";
|
||||
|
||||
|
|
@ -127,6 +128,7 @@ Hooks.once(`init`, () => {
|
|||
CONFIG.Actor.trackableAttributes.hero = HeroData.trackableAttributes;
|
||||
// #endregion
|
||||
|
||||
registerSockets();
|
||||
registerCustomComponents();
|
||||
Handlebars.registerHelper(helpers);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -39,4 +39,14 @@ export function registerWorldSettings() {
|
|||
},
|
||||
}),
|
||||
});
|
||||
|
||||
game.settings.register(`ripcrypt`, `allowUpdateSandsSocket`, {
|
||||
name: `RipCrypt.setting.allowUpdateSandsSocket.name`,
|
||||
hint: `RipCrypt.setting.allowUpdateSandsSocket.hint`,
|
||||
scope: `world`,
|
||||
config: true,
|
||||
requiresReload: false,
|
||||
type: Boolean,
|
||||
default: true,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
27
module/sockets/_index.mjs
Normal file
27
module/sockets/_index.mjs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { localizer } from "../utils/Localizer.mjs";
|
||||
import { Logger } from "../utils/Logger.mjs";
|
||||
import { updateSands } from "./updateSands.mjs";
|
||||
|
||||
const events = {
|
||||
updateSands,
|
||||
};
|
||||
|
||||
export function registerSockets() {
|
||||
Logger.info(`Setting up socket listener`);
|
||||
|
||||
game.socket.on(`system.ripcrypt`, (data, userID) => {
|
||||
const { event, payload } = data ?? {};
|
||||
if (event == null || payload === undefined) {
|
||||
ui.notifications.error(localizer(`RipCrypt.notifs.error.invalid-socket`));
|
||||
return;
|
||||
};
|
||||
|
||||
if (events[event] == null) {
|
||||
ui.notifications.error(localizer(`RipCrypt.notifs.error.unknown-socket-event`, { event }));
|
||||
return;
|
||||
};
|
||||
|
||||
const user = game.users.get(userID);
|
||||
events[event](payload, user);
|
||||
});
|
||||
};
|
||||
37
module/sockets/updateSands.mjs
Normal file
37
module/sockets/updateSands.mjs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { clamp } from "../utils/clamp.mjs";
|
||||
import { localizer } from "../utils/Localizer.mjs";
|
||||
|
||||
export function updateSands(payload) {
|
||||
if (!game.user.isActiveGM) { return };
|
||||
if (!game.settings.get(game.system.id, `allowUpdateSandsSocket`)) { return };
|
||||
|
||||
// Assert payload validity
|
||||
const { value, delta } = payload;
|
||||
if (value == null && delta == null) {
|
||||
ui.notifications.error(localizer(
|
||||
`RipCrypt.notifs.error.malformed-socket-payload`,
|
||||
{
|
||||
event: `updateSands`,
|
||||
details: `Either value or delta must be provided`,
|
||||
},
|
||||
));
|
||||
return;
|
||||
};
|
||||
|
||||
// Take action
|
||||
if (value != null) {
|
||||
const initial = game.settings.get(game.system.id, `sandsOfFateInitial`);
|
||||
let sands = clamp(0, value, initial);
|
||||
if (sands === 0) {
|
||||
ui.delveDice.alertCrypticEvent();
|
||||
sands = initial;
|
||||
};
|
||||
game.settings.set(
|
||||
game.system.id,
|
||||
`sandsOfFate`,
|
||||
sands,
|
||||
);
|
||||
} else if (delta != null) {
|
||||
ui.delveDice.sandsOfFateDelta(delta);
|
||||
};
|
||||
};
|
||||
3
module/utils/clamp.mjs
Normal file
3
module/utils/clamp.mjs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export function clamp(min, ideal, max) {
|
||||
return Math.max(min, Math.min(ideal, max));
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue