Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions module/basicfantasyrpg.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { BasicFantasyRPGItemSheet } from './sheets/item-sheet.mjs';
// Import helper/utility classes and constants.
import { preloadHandlebarsTemplates } from './helpers/templates.mjs';
import { BASICFANTASYRPG } from './helpers/config.mjs';
import { asElement } from './helpers/compat.mjs';

/* -------------------------------------------- */
/* Init Hook */
Expand Down Expand Up @@ -117,8 +118,12 @@ Hooks.once('ready', async function() {

// Hide certain types from being created through the UI
Hooks.on("renderDialog", (dialog, html) => {
let hiddenTypes = ["floor", "wall"];
Array.from(html.find("#document-create option")).forEach(i => {if (hiddenTypes.includes(i.value)) i.remove()});
const hiddenTypes = ["floor", "wall"];
const select = asElement(html).querySelector("#document-create");
if (!select) return;
Array.from(select.options).forEach(option => {
if (hiddenTypes.includes(option.value)) option.remove();
});
});

/* -------------------------------------------- */
Expand Down Expand Up @@ -156,7 +161,7 @@ Hooks.on('createActor', async function(actor) {
Hooks.on('createToken', async function(token, options, id) {
if (token.actor.type === 'monster') {
let newHitPoints = new Roll(`${token.actor.system.hitDice.number}${token.actor.system.hitDice.size}+${token.actor.system.hitDice.mod}`);
await newHitPoints.evaluate({ async: true });
await newHitPoints.evaluate();
token.actor.system.hitPoints.value = Math.max(1, newHitPoints.total);
token.actor.system.hitPoints.max = Math.max(1, newHitPoints.total);
}
Expand Down
4 changes: 2 additions & 2 deletions module/documents/item.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ export class BasicFantasyRPGItem extends Item {
// Retrieve roll data and invoke the roll
const rollData = item.getRollData();
const roll = new Roll(rollData.item.formula.value, rollData);
await roll.roll();
await roll.evaluate();

let targetParsed = rollData.item.targetNumber.value;
// targetNumber may be a formula - use a Roll object to parse it if it's not a number already
if (targetParsed && isNaN(targetParsed) && typeof targetParsed === 'string') {
try {
const rollTN = new Roll(targetParsed, rollData);
await rollTN.roll();
await rollTN.evaluate();
targetParsed = rollTN.total;
} catch {
ui.notifications.warn(`${game.i18n.localize('ERROR.InvalidTargetNumber')} ${game.i18n.localize('TYPES.Item.' + item.type)} - ${item.name}: ${targetParsed}`, {localize: false, permanent: true});
Expand Down
61 changes: 61 additions & 0 deletions module/helpers/compat.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Foundry version compatibility helpers for v13/v14 API differences.
*/

export const FVTT = {
get major() {
return Number(game.version.split(".")[0]);
},

get isV14() {
return this.major >= 14;
}
};

/**
* @param {jQuery|HTMLElement} html
* @returns {jQuery}
*/
export function asJQuery(html) {
return html instanceof jQuery ? html : $(html);
}

/**
* @param {jQuery|HTMLElement} html
* @returns {HTMLElement}
*/
export function asElement(html) {
return html instanceof jQuery ? html[0] : html;
}

/**
* @param {ActiveEffect} effect
* @returns {string}
*/
export function getEffectName(effect) {
return effect.name ?? effect.label;
}

/**
* @param {ActiveEffect} effect
* @returns {string}
*/
export function getEffectImage(effect) {
return effect.img ?? effect.icon;
}

/**
* @param {ActiveEffect} effect
* @returns {boolean}
*/
export function isEffectDisabled(effect) {
return effect.disabled ?? effect.data?.disabled ?? false;
}

/**
* @param {Roll} roll
* @returns {Promise<Roll>}
*/
export async function evaluateRoll(roll) {
return roll.evaluate();
}
20 changes: 14 additions & 6 deletions module/helpers/effects.mjs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import {FVTT, getEffectImage, getEffectName, isEffectDisabled} from './compat.mjs';

/**
* Manage Active Effect instances through the Actor Sheet via effect control buttons.
* @param {MouseEvent} event The left-click event on the effect control
* @param {Actor|Item} owner The owning document which manages this effect
*/
export function onManageActiveEffect(event, owner) {
export function onManageActiveEffect(event, owner) {
event.preventDefault();
const a = event.currentTarget;
const li = a.closest('li');
const effect = li.dataset.effectId ? owner.effects.get(li.dataset.effectId) : null;
switch ( a.dataset.action ) {
case 'create':
return owner.createEmbeddedDocuments('ActiveEffect', [{
label: 'New Effect',
icon: 'icons/svg/aura.svg',
...(FVTT.isV14
? {name: 'New Effect', img: 'icons/svg/aura.svg'}
: {label: 'New Effect', icon: 'icons/svg/aura.svg'}),
origin: owner.uuid,
'duration.rounds': li.dataset.effectType === 'temporary' ? 1 : undefined,
disabled: li.dataset.effectType === 'inactive'
Expand All @@ -22,7 +25,7 @@
case 'delete':
return effect.delete();
case 'toggle':
return effect.update({disabled: !effect.data.disabled});
return effect.update({disabled: !isEffectDisabled(effect)});
}
}

Expand Down Expand Up @@ -55,9 +58,14 @@ export function prepareActiveEffectCategories(effects) {
// Iterate over active effects, classifying them into categories
for ( let e of effects ) {
e._getSourceName(); // Trigger a lookup for the source name
if ( e.data.disabled ) categories.inactive.effects.push(e);
e.sheet = {
name: getEffectName(e),
img: getEffectImage(e),
disabled: isEffectDisabled(e)
};
if ( isEffectDisabled(e) ) categories.inactive.effects.push(e);
else if ( e.isTemporary ) categories.temporary.effects.push(e);
else categories.passive.effects.push(e);
}
return categories;
}
}
1 change: 1 addition & 0 deletions module/helpers/templates.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
'systems/basicfantasyrpg/templates/actor/parts/actor-spells.html',
'systems/basicfantasyrpg/templates/actor/parts/actor-features.html',
'systems/basicfantasyrpg/templates/actor/parts/actor-floors.html',
'systems/basicfantasyrpg/templates/actor/parts/actor-effects.html',
]);
};
10 changes: 6 additions & 4 deletions module/sheets/actor-sheet.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {successChatMessage} from '../helpers/chat.mjs';
import {asJQuery} from '../helpers/compat.mjs';
import {onManageActiveEffect, prepareActiveEffectCategories} from '../helpers/effects.mjs';

/**
Expand Down Expand Up @@ -66,7 +67,7 @@ export class BasicFantasyRPGActorSheet extends ActorSheet {
this._prepareItems(context);
}

// Add roll data for TinyMCE editors.
// Add roll data for rich text editors.
context.rollData = context.actor.getRollData();

// Prepare active effects
Expand Down Expand Up @@ -202,6 +203,7 @@ export class BasicFantasyRPGActorSheet extends ActorSheet {
/** @override */
activateListeners(html) {
super.activateListeners(html);
html = asJQuery(html);

// Render the item sheet for viewing/editing prior to the editable check.
html.find('.item-edit').click(ev => {
Expand Down Expand Up @@ -299,10 +301,10 @@ export class BasicFantasyRPGActorSheet extends ActorSheet {
const itemData = {
name: name,
type: type,
data: data
system: data
};
// Remove the type from the dataset since it's in the itemData.type prop.
delete itemData.data['type'];
delete itemData.system['type'];

// Finally, create the item!
return await Item.create(itemData, {parent: this.actor});
Expand Down Expand Up @@ -354,7 +356,7 @@ export class BasicFantasyRPGActorSheet extends ActorSheet {
if (dataset.roll) {
let label = dataset.label ? `<span class="chat-item-name">${game.i18n.localize('BASICFANTASYRPG.Roll')}: ${dataset.label}</span>` : '';
let roll = new Roll(dataset.roll, this.actor.getRollData());
await roll.roll();
await roll.evaluate();
label += successChatMessage(roll.total, dataset.targetNumber, dataset.rollUnder);
roll.toMessage({
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
Expand Down
2 changes: 1 addition & 1 deletion module/sheets/item-sheet.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class BasicFantasyRPGItemSheet extends ItemSheet {
// Use a safe clone of the item data for further operations.
const itemData = context.item;

// Retrieve the roll data for TinyMCE editors.
// Retrieve the roll data for rich text editors.
context.rollData = {};
let actor = this.object?.parent ?? null;
if (actor) {
Expand Down
10 changes: 4 additions & 6 deletions system.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"id": "basicfantasyrpg",
"title": "Basic Fantasy RPG",
"description": "The Basic Fantasy RPG system for FoundryVTT!",
"version": "r15",
"version": "r16",
"compatibility": {
"minimum": "11",
"verified": "13"
"minimum": "13",
"verified": "14"
},
"authors": [
{
Expand Down Expand Up @@ -39,12 +39,10 @@
"distance": 5,
"units": "ft"
},
"gridDistance": 5,
"gridUnits": "ft",
"primaryTokenAttribute": "hitPoints",
"secondaryTokenAttribute": null,
"url": "https://github.com/orffen/basicfantasyrpg",
"manifest": "https://raw.githubusercontent.com/orffen/basicfantasyrpg/main/system.json",
"download": "https://github.com/orffen/basicfantasyrpg/archive/refs/tags/r15.zip",
"download": "https://github.com/orffen/basicfantasyrpg/archive/refs/tags/r16.zip",
"license": "LICENSE.txt"
}
6 changes: 3 additions & 3 deletions templates/actor/parts/actor-effects.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ <h3 class="item-name effect-name flexrow">{{localize section.label}}</h3>
{{#each section.effects as |effect|}}
<li class="item effect flexrow" data-effect-id="{{effect.id}}">
<div class="item-name effect-name flexrow">
<img class="item-image" src="{{effect.data.icon}}"/>
<h4>{{effect.data.label}}</h4>
<img class="item-image" src="{{effect.sheet.img}}"/>
<h4>{{effect.sheet.name}}</h4>
</div>
<div class="effect-source">{{effect.sourceName}}</div>
<div class="effect-duration">{{effect.duration.label}}</div>
<div class="item-controls effect-controls flexrow">
<a class="effect-control" data-action="toggle" title="{{localize 'BASICFANTASYRPG.EffectToggle'}}">
<i class="fas {{#if effect.data.disabled}}fa-check{{else}}fa-times{{/if}}"></i>
<i class="fas {{#if effect.sheet.disabled}}fa-check{{else}}fa-times{{/if}}"></i>
</a>
<a class="effect-control" data-action="edit" title="{{localize 'BASICFANTASYRPG.EffectEdit'}}">
<i class="fas fa-edit"></i>
Expand Down