Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
schultzcole committed Jun 5, 2021
2 parents 0132fb4 + 613a54e commit 75330f1
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 99 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# CHANGELOG

## [2.0.0] 2021-06-05

*Core 0.8.x and dnd5e 1.3.x compatibility*

### FIXED

- Fixed usages of a number of deprecated and renamed core functions.
- Fixed some issues that would cause item cards with embedded rolls and combined damage roll cards from rendering in the chat log.
- Fixed an issue that would cause the "show dialog" modifier key to not function if the default roll dialog behavior was set to "skip".

## [1.0.9] 2021-04-07

### FIXED
Expand Down
42 changes: 24 additions & 18 deletions lib/libWrapper/shim.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// SPDX-License-Identifier: MIT
// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro


Expand All @@ -18,7 +18,7 @@ Hooks.once('init', () => {
libWrapper = class {
static get is_fallback() { return true };

static register(module, target, fn, type="MIXED") {
static register(package_id, target, fn, type="MIXED", {chain=undefined}={}) {
const is_setter = target.endsWith('#set');
target = !is_setter ? target : target.slice(0, -4);
const split = target.split('.');
Expand All @@ -34,10 +34,10 @@ Hooks.once('init', () => {
if(descriptor) break;
iObj = Object.getPrototypeOf(iObj);
}
if(!descriptor) throw `libWrapper Shim: '${target}' does not exist or could not be found.`;
if(!descriptor || descriptor?.configurable === false) throw `libWrapper Shim: '${target}' does not exist, could not be found, or has a non-configurable descriptor.`;

let original = null;
const wrapper = (type == 'OVERRIDE') ? function() { return fn.call(this, ...arguments); } : function() { return fn.call(this, original.bind(this), ...arguments); }
const wrapper = (chain ?? type != 'OVERRIDE') ? function() { return fn.call(this, original.bind(this), ...arguments); } : function() { return fn.apply(this, arguments); };

if(!is_setter) {
if(descriptor.value) {
Expand Down Expand Up @@ -67,39 +67,45 @@ Hooks.once('init', () => {
// Set up the ready hook that shows the "libWrapper not installed" warning dialog
if(WARN_FALLBACK) {
//************** USER CUSTOMIZABLE:
// Module ID - by default attempts to auto-detect, but you might want to hardcode your module ID here to avoid potential auto-detect issues
const MODULE_ID = ((import.meta?.url ?? Error().stack)?.match(/(?<=\/)modules\/.+(?=\/)/i)??[])[0]?.split('/')?.find(n => n && game.modules.has(n));
if(!MODULE_ID) {
console.error("libWrapper Shim: Could not auto-detect module ID. The libWrapper fallback warning dialog will be disabled.");
// Package ID & Package Title - by default attempts to auto-detect, but you might want to hardcode your package ID and title here to avoid potential auto-detect issues
const [PACKAGE_ID, PACKAGE_TITLE] = (()=>{
const match = (import.meta?.url ?? Error().stack)?.match(/\/(worlds|systems|modules)\/(.+)(?=\/)/i);
if(match?.length !== 3) return [null,null];
const dirs = match[2].split('/');
if(match[1] === 'worlds') return dirs.find(n => n && game.world.id === n) ? [game.world.id, game.world.title] : [null,null];
if(match[1] === 'systems') return dirs.find(n => n && game.system.id === n) ? [game.system.id, game.system.data.title] : [null,null];
const id = dirs.find(n => n && game.modules.has(n));
return [id, game.modules.get(id)?.data?.title];
})();

if(!PACKAGE_ID || !PACKAGE_TITLE) {
console.error("libWrapper Shim: Could not auto-detect package ID and/or title. The libWrapper fallback warning dialog will be disabled.");
return;
}

Hooks.once('ready', () => {
// Module title
const MODULE_TITLE = game.modules.get(MODULE_ID).data.title;

//************** USER CUSTOMIZABLE:
// Title and message for the dialog shown when the real libWrapper is not installed.
const FALLBACK_MESSAGE_TITLE = MODULE_TITLE;
const FALLBACK_MESSAGE_TITLE = PACKAGE_TITLE;
const FALLBACK_MESSAGE = `
<p><b>'${MODULE_TITLE}' depends on the 'libWrapper' module, which is not present.</b></p>
<p><b>'${PACKAGE_TITLE}' depends on the 'libWrapper' module, which is not present.</b></p>
<p>A fallback implementation will be used, which increases the chance of compatibility issues with other modules.</p>
<small><p>'libWrapper' is a library which provides module developers with a simple way to modify core Foundry VTT code, while reducing the likelihood of conflict with other modules.</p>
<small><p>'libWrapper' is a library which provides package developers with a simple way to modify core Foundry VTT code, while reducing the likelihood of conflict with other packages.</p>
<p>You can install it from the "Add-on Modules" tab in the <a href="javascript:game.shutDown()">Foundry VTT Setup</a>, from the <a href="https://foundryvtt.com/packages/lib-wrapper">Foundry VTT package repository</a>, or from <a href="https://github.com/ruipin/fvtt-lib-wrapper/">libWrapper's Github page</a>.</p></small>
`;

// Settings key used for the "Don't remind me again" setting
const DONT_REMIND_AGAIN_KEY = "libwrapper-dont-remind-again";

// Dialog code
console.warn(`${MODULE_TITLE}: libWrapper not present, using fallback implementation.`);
game.settings.register(MODULE_ID, DONT_REMIND_AGAIN_KEY, { name: '', default: false, type: Boolean, scope: 'world', config: false });
if(game.user.isGM && !game.settings.get(MODULE_ID, DONT_REMIND_AGAIN_KEY)) {
console.warn(`${PACKAGE_TITLE}: libWrapper not present, using fallback implementation.`);
game.settings.register(PACKAGE_ID, DONT_REMIND_AGAIN_KEY, { name: '', default: false, type: Boolean, scope: 'world', config: false });
if(game.user.isGM && !game.settings.get(PACKAGE_ID, DONT_REMIND_AGAIN_KEY)) {
new Dialog({
title: FALLBACK_MESSAGE_TITLE,
content: FALLBACK_MESSAGE, buttons: {
ok: { icon: '<i class="fas fa-check"></i>', label: 'Understood' },
dont_remind: { icon: '<i class="fas fa-times"></i>', label: "Don't remind me again", callback: () => game.settings.set(MODULE_ID, DONT_REMIND_AGAIN_KEY, true) }
dont_remind: { icon: '<i class="fas fa-times"></i>', label: "Don't remind me again", callback: () => game.settings.set(PACKAGE_ID, DONT_REMIND_AGAIN_KEY, true) }
}
}).render(true);
}
Expand Down
14 changes: 7 additions & 7 deletions module.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "mre-dnd5e",
"title": "Minimal Rolling Enhancements for D&D5e",
"description": "Some minimalist enhancements to the core D&D5e rolling workflow. Attempts to stay as close to core as possible while improving convenience.",
"version": "1.0.9",
"version": "2.0.0",
"author": "Cole Schultz (cole#9640)",
"systems": [ "dnd5e" ],
"esmodules": [
Expand All @@ -21,13 +21,13 @@
"path": "lang/en.json"
}
],
"minimumCoreVersion": "0.7.5",
"compatibleCoreVersion": "0.7.9",
"minimumCoreVersion": "0.8.5",
"compatibleCoreVersion": "0.8.6",
"url": "https://github.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E",
"manifest": "https://raw.githubusercontent.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E/master/module.json",
"download": "https://github.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E/archive/1.0.9.zip",
"license": "https://github.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E/blob/1.0.9/LICENSE",
"readme": "https://github.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E/blob/1.0.9/README.md",
"changelog": "https://github.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E/blob/1.0.9/CHANGELOG.md"
"download": "https://github.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E/archive/2.0.0.zip",
"license": "https://github.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E/blob/2.0.0/LICENSE",
"readme": "https://github.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E/blob/2.0.0/README.md",
"changelog": "https://github.com/schultzcole/FVTT-Minimal-Rolling-Enhancements-DND5E/blob/2.0.0/CHANGELOG.md"
}

23 changes: 16 additions & 7 deletions mre-styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
display: flex;
}


.dnd5e.sheet.item .mre-damage-header-container .damage-header,
.tidy5e.sheet.item .mre-damage-header-container .damage-header {
flex: 1;
Expand All @@ -128,10 +129,15 @@

.dnd5e.sheet.item .mre-auto-roll,
.tidy5e.sheet.item .mre-auto-roll {
display: flex;
flex: 0 0 60px;
max-height: 24px;
}

.tidy5e.sheet.item .mre-damage-header-container .mre-auto-roll {
margin: 3px;
}

.dnd5e.sheet.item .mre-auto-roll span.label,
.tidy5e.sheet.item .mre-auto-roll span.label {
display: inline-block;
Expand All @@ -146,23 +152,26 @@
color: #7a7971;
}

.dnd5e.sheet.item .mre-damage-header-container .mre-auto-roll,
.tidy5e.sheet.item .mre-damage-header-container .mre-auto-roll {
display: inline-block;
}

.dnd5e.sheet.item .mre-auto-roll button.checkbox,
.tidy5e.sheet.item .mre-auto-roll button.checkbox {
flex: 1;
position: relative;
width: 16px;
max-width: 16px;
height: 16px;
top: -2px;
border: none;
background: none;
margin: 5px 2px 5px 10px;
padding: 0;
margin: 5px;
cursor: pointer;
}

.tidy5e.sheet.item .config-formula-groups {
color: #7a7971;
font-size: 16px;
margin-right: 4px;
}

.dnd5e.sheet.item .mre-auto-roll button.checkbox:hover,
.tidy5e.sheet.item .mre-auto-roll button.checkbox:hover {
box-shadow: none;
Expand Down
36 changes: 19 additions & 17 deletions scripts/apps/formula-group-config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { createNewFormulaGroup } from "../formula-group.mjs";

const MAX_FORMULA_GROUPS = 7;

export class FormulaGroupConfig extends BaseEntitySheet {
export class FormulaGroupConfig extends DocumentSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: [ "dnd5e", "mre-formula-group-config" ],
template: "modules/mre-dnd5e/templates/formula-group-config.hbs",
width: "auto",
Expand All @@ -18,11 +18,11 @@ export class FormulaGroupConfig extends BaseEntitySheet {
}

/** @override */
get title() { return `${game.i18n.localize(`${MODULE_NAME}.FORMULA-GROUP.DialogTitle`)}: ${this.entity.name}`; }
get title() { return `${game.i18n.localize(`${MODULE_NAME}.FORMULA-GROUP.DialogTitle`)}: ${this.document.name}`; }

/** @override */
getData(options) {
const itemData = this.entity.data.data;
const itemData = this.document.data.data;
const formulaGroupData = this._getFormulaGroupData();
const emptyString = game.i18n.localize(`${MODULE_NAME}.FORMULA-GROUP.Empty`)
return {
Expand All @@ -38,8 +38,8 @@ export class FormulaGroupConfig extends BaseEntitySheet {

_getFormulaGroupData() {
/** @type FormulaGroup[] */
const groups = duplicate(this.entity.getFlag(MODULE_NAME, "formulaGroups"));
const totalFormulaCount = this.entity.data.data.damage.parts.length;
const groups = foundry.utils.deepClone(this.document.getFlag(MODULE_NAME, "formulaGroups"));
const totalFormulaCount = this.document.data.data.damage.parts.length;
return groups.map(g => ({
label: g.label,
containsFormula: (new Array(totalFormulaCount)).fill(false).map((_, i) => g.formulaSet.includes(i)),
Expand Down Expand Up @@ -68,27 +68,25 @@ export class FormulaGroupConfig extends BaseEntitySheet {
}

async _handleAddFormulaGroup() {
const groups = duplicate(this.entity.data.flags[MODULE_NAME].formulaGroups);
const groups = foundry.utils.deepClone(this.document.data.flags[MODULE_NAME].formulaGroups);
groups.push(createNewFormulaGroup({ index: groups.length }));
await this.entity.update({ [`flags.${MODULE_NAME}.formulaGroups`]: groups });
this.position.width = "auto";
this.render(false);
await this.document.update({ [`flags.${MODULE_NAME}.formulaGroups`]: groups });
this.renderResetWidth();
}

async _handleDeleteFormulaGroup(event) {
const index = event.currentTarget.dataset.groupIndex;
const groups = duplicate(this.entity.data.flags[MODULE_NAME].formulaGroups);
const groups = foundry.utils.deepClone(this.document.data.flags[MODULE_NAME].formulaGroups);
groups.splice(index, 1);
await this.entity.update({ [`flags.${MODULE_NAME}.formulaGroups`]: groups });
this.position.width = "auto";
this.render(false);
await this.document.update({ [`flags.${MODULE_NAME}.formulaGroups`]: groups });
this.renderResetWidth();
}

/** @override */
async _updateObject(event, formData) {
if (!this.isEditable) return;

formData = expandObject(formData);
formData = foundry.utils.expandObject(formData);

// If there are no formula groups in the form or no formulae to be in groups, quit early
if (!formData.formulaGroupLabels?.length || !formData.formulaGroupContains) return;
Expand All @@ -111,8 +109,12 @@ export class FormulaGroupConfig extends BaseEntitySheet {
return;
}

await this.entity.setFlag(MODULE_NAME, "formulaGroups", formulaGroups);
this.position.width = "auto";
await this.document.setFlag(MODULE_NAME, "formulaGroups", formulaGroups);
this.renderResetWidth();
}

renderResetWidth() {
this.element[0].style.width = null
this.render(true);
}
}
2 changes: 1 addition & 1 deletion scripts/formula-group.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { MODULE_NAME } from "./const.mjs";
export function createNewFormulaGroup({ label=undefined, index=undefined, initialSet=[] }={}) {
return {
label: label ?? game.i18n.localize(formulaGroupNameKeys[index] ?? `${MODULE_NAME}.FORMULA-GROUP.NewFormulaGroup`),
formulaSet: duplicate(initialSet),
formulaSet: foundry.utils.deepClone(initialSet),
}
}

Expand Down
6 changes: 3 additions & 3 deletions scripts/hooks/render-chat-log.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Hooks.on("renderChatLog", (app, html, data) => _handleRenderChatLog(html));
Hooks.on("renderChatPopout", (app, html, data) => _handleRenderChatLog(html));

function _handleRenderChatLog(html) {
html.on('click', '.card-buttons button', (event) => {
html.on('click', '.card-buttons button', async (event) => {
const button = event.currentTarget;
const action = button.dataset.action;

Expand All @@ -13,12 +13,12 @@ function _handleRenderChatLog(html) {
const message = game.messages.get(messageId);

// Recover the actor for the chat card
const actor = CONFIG.Item.entityClass._getChatCardActor(card);
const actor = await CONFIG.Item.documentClass._getChatCardActor(card);
if ( !actor ) return;

// Get the Item from stored flag data or by the item ID on the Actor
const storedData = message.getFlag("dnd5e", "itemData");
const item = storedData ? CONFIG.Item.entityClass.createOwned(storedData, actor) : actor.getOwnedItem(card.dataset.itemId);
const item = storedData ? new CONFIG.Item.documentClass(storedData, actor) : actor.items.get(card.dataset.itemId);
if ( !item ) {
return ui.notifications.error(game.i18n.format("DND5E.ActionWarningNoItem", {item: card.dataset.itemId, name: actor.name}))
}
Expand Down
12 changes: 6 additions & 6 deletions scripts/hooks/render-item-5e-sheet.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Hooks.on("renderItemSheet5e", (itemSheet, html, _) => {
html.find(".tab.details .damage-header").prepend(`<a title="${tooltip}" class="config-formula-groups"><i class="fas fa-tasks"></i></a>`);

// Open the formula group config when the user clicks on the button
html.find(".config-formula-groups").click(() => new FormulaGroupConfig(itemSheet.entity, { editable: itemSheet.isEditable }).render(true) );
html.find(".config-formula-groups").click(() => new FormulaGroupConfig(itemSheet.document, { editable: itemSheet.isEditable }).render(true) );

// Remove versatile fields
html.find(`.tab.details input[name="data.damage.versatile"]`).closest(".form-group").remove();
Expand All @@ -17,19 +17,19 @@ Hooks.on("renderItemSheet5e", (itemSheet, html, _) => {
// Only show the auto-roll checkbox button if actionType is populated
const actionType = html.find(`.tab.details`).find(`[name="data.actionType"]`);
actionType.wrap(`<div class="form-fields">`);
actionType.after(_makeAutoRollCheckboxElement(itemSheet.entity, "Attack", true));
actionType.after(_makeAutoRollCheckboxElement(itemSheet.document, "Attack", true));
}

const damageHeader = html.find(".tab.details .damage-header");
damageHeader.wrap(`<div class="mre-damage-header-container">`);
damageHeader.after(_makeAutoRollCheckboxElement(itemSheet.entity, "Damage", true));
damageHeader.after(_makeAutoRollCheckboxElement(itemSheet.document, "Damage", true));

const otherFormula = html.find(`.tab.details`).find(`[name="data.formula"]`);
otherFormula.after(_makeAutoRollCheckboxElement(itemSheet.entity, "Other", false));
otherFormula.after(_makeAutoRollCheckboxElement(itemSheet.document, "Other", false));

// Handle "checkbox" button clicks
html.find(`.tab.details button.checkbox:not(.three-way)`).click((event) => _handleTwoWayCheckboxButtonPress(event, itemSheet.entity));
html.find(`.tab.details button.checkbox.three-way`).click((event) => _handleThreeWayCheckboxButtonPress(event, itemSheet.entity));
html.find(`.tab.details button.checkbox:not(.three-way)`).click((event) => _handleTwoWayCheckboxButtonPress(event, itemSheet.document));
html.find(`.tab.details button.checkbox.three-way`).click((event) => _handleThreeWayCheckboxButtonPress(event, itemSheet.document));
});

function _makeAutoRollCheckboxElement(item, target, threeWay) {
Expand Down
28 changes: 14 additions & 14 deletions scripts/patches/ability-check-patches.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { getSettingLocalOrDefault, SETTING_NAMES } from "../settings.mjs";
import { modifiers } from "../modifiers.mjs";

const d20RollsToPatch = [
{ path: "CONFIG.Item.entityClass.prototype.rollAttack", optionsIndex: 0 },
{ path: "CONFIG.Item.entityClass.prototype.rollToolCheck", optionsIndex: 0 },
{ path: "CONFIG.Actor.entityClass.prototype.rollSkill", optionsIndex: 1 },
{ path: "CONFIG.Actor.entityClass.prototype.rollAbilityTest", optionsIndex: 1 },
{ path: "CONFIG.Actor.entityClass.prototype.rollAbilitySave", optionsIndex: 1 },
{ path: "CONFIG.Actor.entityClass.prototype.rollDeathSave", optionsIndex: 0 },
{ path: "CONFIG.Item.documentClass.prototype.rollAttack", optionsIndex: 0 },
{ path: "CONFIG.Item.documentClass.prototype.rollToolCheck", optionsIndex: 0 },
{ path: "CONFIG.Actor.documentClass.prototype.rollSkill", optionsIndex: 1 },
{ path: "CONFIG.Actor.documentClass.prototype.rollAbilityTest", optionsIndex: 1 },
{ path: "CONFIG.Actor.documentClass.prototype.rollAbilitySave", optionsIndex: 1 },
{ path: "CONFIG.Actor.documentClass.prototype.rollDeathSave", optionsIndex: 0 },
]

export function patchAbilityChecks() {
Expand All @@ -29,24 +29,24 @@ function generateD20RollPatch(optionsIndex) {
let advModifier = getSettingLocalOrDefault(SETTING_NAMES.ADV_MOD);
let disAdvModifier = getSettingLocalOrDefault(SETTING_NAMES.DISADV_MOD);

if (!options.event) options.event = duplicate(modifiers);
const evt = options.event ?? foundry.utils.deepClone(modifiers);
delete options.event;

const optionsOverride = {
advantage: options.event[advModifier],
disadvantage: options.event[disAdvModifier],
advantage: evt[advModifier],
disadvantage: evt[disAdvModifier],
}

// The wrapped call will set the position of the dialog using dialogOptions, however if clientX and clientY are not defined,
// It will place it in a weird location. For this reason, when clientX and Y are not defined, we override the dialog to be at
// null, null, which will place it in the center of the window.
if (!options.event?.clientX || !options.event?.clientY) {
if (!evt?.clientX || !evt?.clientY) {
optionsOverride.dialogOptions = { top: null, left: null };
}
mergeObject(options, optionsOverride, { overwrite: false });
foundry.utils.mergeObject(options, optionsOverride, { overwrite: false });

let fastForward = dialogBehaviorSetting === "skip"
? !options.event[noFastForwardModifier]
: null;
let fastForward = evt[noFastForwardModifier];
if (dialogBehaviorSetting === "skip") fastForward = !fastForward;

options.fastForward = options.advantage || options.disadvantage || fastForward;

Expand Down
Loading

0 comments on commit 75330f1

Please sign in to comment.