Skip to content

Commit

Permalink
qol: Migrated D&D5e Vehicle Weights
Browse files Browse the repository at this point in the history
  • Loading branch information
flamewave000 committed Feb 23, 2025
1 parent e0c1214 commit 40c0c39
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 115 deletions.
7 changes: 4 additions & 3 deletions .doit-files/dev.doit
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ dev {
cp -Lr "./$$module" "$$fdata"
$doit_dev proc_sass "$$fdata"
$doit_dev proc_module "$$fdata"
echo "Copied $$module to $$fdata"
echo "$$(date --iso-8601=seconds) Copied $$module to $$fdata"
$$$
}
watch {
$$$
module=`$doit_env tgt -r`
find "$$module"/**/* | entr $doit_dev dev
find "$$module"/* | entr $doit_dev dev
$$$
}
pack {
Expand Down Expand Up @@ -71,7 +71,8 @@ with open(out_file + "/module.json", "w") as manifest:
proc_sass {
$$$
if [ -e "$1/css" ]; then
for file in $$(ls "$1"/css/*.scss > /dev/null 2>&1 || echo ''); do
for file in $$(find "$1"/css/ -name '*.scss'); do
echo "Processing SASS: $$file"
npx sass --no-source-map "$$file" "$1"/css/$$(basename "$$file" .scss).css
rm -f "$$file"
done
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package-lock.json
.devenv*
.vscode/settings.json
*foundry-reference*
fvtt-scripts
fvtt-scripts/
release/
.doit/
node_modules/
Expand Down
10 changes: 10 additions & 0 deletions common/foundry.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
declare interface EntityConfigData<T> {
blankLabel: string
defaultClass: string
entityName: string
isGM: true
object: T
options: object
sheetClass: string
sheetClasses: object
}
1 change: 0 additions & 1 deletion df-logger/module.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"changelog":"https://dragonflagon.cafe/mods/chg/df-logger",
"bugs": "https://dragonflagon.cafe/mods/bug/df-logger",
"socket": true,
"manifestPlusVersion": "1.0.0",
"media": [
{ "type": "icon", "url": "https://raw.githubusercontent.com/flamewave000/dragonflagon-fvtt/master/.assets/logo.png" },
{ "type": "screenshot", "url": "https://raw.githubusercontent.com/flamewave000/dragonflagon-fvtt/master/.assets/df-logger/message.png" },
Expand Down
4 changes: 4 additions & 0 deletions df-qol/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# DragonFlagon Quality of Life

## Release 2.0.0 (2025-02-22)
- **UPDATE:** Migrated to v12.
- **UPDATE:** Downgraded TS -> JS (such sad).

## Release 1.8.0 (2022-10-16)
- **UPDATE:** Migrated to v10.
- **NEW:** Quick Roll button added to rolltable list items (in addition to the one still in the context menu).
Expand Down
2 changes: 1 addition & 1 deletion df-qol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Adds various Quality of Life improvements. These are all small, light-weight, ad

Each feature is not only self-contained, but when disabled will completely and cleanly remove itself from Foundry. This is so that if any one feature happens to conflict with another module, disabling it guarantees the conflict will be resolved. There are currently no reported conflicts though, so have fun!

##### [![become a patron](../.assets/patreon-image.png)](https://www.patreon.com/bePatron?u=46113583) If you want to support me or just help me buy doggy treats! Also, you can keep up to date on what I'm working on. I will be announcing any new modules or pre-releases there for anyone wanting to help me test things out!
**[![become a patron](../.assets/patreon-image.png)](https://www.patreon.com/bePatron?u=46113583) If you want to support me or just help me buy doggy treats! Also, you can keep up to date on what I'm working on. I will be announcing any new modules or pre-releases there for anyone wanting to help me test things out!**

## Token Locking

Expand Down
2 changes: 1 addition & 1 deletion df-qol/module.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "df-qol",
"version": "1.8.0",
"version": "2.0.0",
"title": "DF Quality of Life",
"description": "A set of various small Quality of Life changes that don't quite fit in my other larger modules.",
"authors": [ { "name": "flamewave000", "discord": "flamewave000", "url": "https://github.com/flamewave000" } ],
Expand Down
169 changes: 70 additions & 99 deletions df-qol/src/DnD5eVehicleCapacity.mjs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { ActorData } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs";
/// <reference path="../../fvtt-scripts/foundry.js" />
/// <reference path="../../fvtt-scripts/foundry-esm.js" />
/// <reference path="../../common/foundry.d.ts" />
/// <reference path="../../common/libWrapper.d.ts" />

import SETTINGS from "../common/Settings.mjs";

interface DND5E {
encumbrance: {
currencyPerWeight: { imperial: number, metric: number };
vehicleWeightMultiplier: { imperial: number, metric: number };
}
}
/**
* @typedef {object} WeightCategory
* @property {number} factor
* @property {string} shortLabel
* @property {string} longLabel
*/

interface EntityConfigData<T> {
blankLabel: string
defaultClass: string
entityName: string
isGM: true
object: T
options: object
sheetClass: string
sheetClasses: object
/** @type { { [key: string]: WeightCategory } } */
const WEIGHTS = {
lt: { factor: 2240, shortLabel: 'L.Ton', longLabel: 'DF_QOL.VehicleUnit.Units_LongTon' },
st: { factor: 2000, shortLabel: 'S.Ton', longLabel: 'DF_QOL.VehicleUnit.Units_ShortTon' },
lb: { factor: 1, shortLabel: 'lb.', longLabel: 'DF_QOL.VehicleUnit.Units_Pounds' }
}
const DEFAULT_UNIT = 'st';

export default class DnD5eVehicleCapacity {
static init() {
// If we have D&D5e running
// @ts-ignore
if (game.dnd5e) {
SETTINGS.register('vehicle-unit', {
scope: 'world',
Expand All @@ -39,110 +39,81 @@ export default class DnD5eVehicleCapacity {

static ready() {
// If we have D&D5e running
// @ts-ignore
if (game.dnd5e)
DnD5eVehicleCapacity.DF_VEHICLE_UNITS();
}

static DF_VEHICLE_UNITS() {
const clazz = (<any>CONFIG.Actor).sheetClasses.vehicle['dnd5e.ActorSheet5eVehicle'].cls;
if (!SETTINGS.get('vehicle-unit')) {
if (!clazz.prototype.dfqol_computeEncumbrance) return;
clazz.prototype._computeEncumbrance = clazz.prototype.dfqol_computeEncumbrance;
delete clazz.prototype.dfqol_computeEncumbrance;
if (SETTINGS.get('vehicle-unit')) {
Hooks.on('renderActorSheet5eVehicle', DnD5eVehicleCapacity.renderActorSheet5eVehicle);
CONFIG.DND5E.encumbrance.baseUnits.vehicle.imperial = 'lb';
}
else {
Hooks.off('renderActorSheet5eVehicle', DnD5eVehicleCapacity.renderActorSheet5eVehicle);
return;
CONFIG.DND5E.encumbrance.baseUnits.vehicle.imperial = 'tn';
}
if (clazz.prototype.dfqol_computeEncumbrance) return;
clazz.prototype.dfqol_computeEncumbrance = clazz.prototype._computeEncumbrance;
clazz.prototype._computeEncumbrance = DnD5eVehicleCapacity.VehicleComputeEncumbrance;
Hooks.on('renderActorSheet5eVehicle', DnD5eVehicleCapacity.renderActorSheet5eVehicle);
}
static VehicleComputeEncumbrance(this: ActorSheet, totalWeight: number, actorData: ActorData) {
// @ts-ignore
const DND5E = <DND5E>CONFIG.DND5E;
// Compute currency weight
// @ts-ignore
const totalCoins = Object.values((<Record<string, number>>actorData.system.currency)).reduce((acc, denom) => acc + denom, 0);
totalWeight += totalCoins / DND5E.encumbrance.currencyPerWeight.imperial;

// Vehicle weights are an order of magnitude greater.
// @ts-ignore
totalWeight /= <number>this.document.getFlag(SETTINGS.MOD_NAME, 'unit') || DND5E.encumbrance.vehicleWeightMultiplier.imperial;

// Compute overall encumbrance
// @ts-ignore
const max = actorData.system.attributes.capacity.cargo;
const pct = Math.clamped((totalWeight * 100) / max, 0, 100);
return { value: totalWeight.toNearest(0.01), max, pct };
}
static renderActorSheet5eVehicle(app: ActorSheet, html: JQuery<HTMLElement>, _data: any) {
// @ts-ignore
let unit: any = app.object.getFlag(SETTINGS.MOD_NAME, 'unit') || (<DND5E>CONFIG.DND5E).encumbrance.vehicleWeightMultiplier.imperial;
switch (unit) {
case 2240: unit = ['L.Ton', 'DF_QOL.VehicleUnit.Units_LongTon']; break;
case 2000: unit = ['S.Ton', 'DF_QOL.VehicleUnit.Units_ShortTon']; break;
case 1: unit = ['lb.', 'DF_QOL.VehicleUnit.Units_Pounds']; break;
/**
* @param {ActorSheet} app
* @param {JQuery<HTMLElement>} html
* @param { {encumbrance:{value:number,max:number,mod:number,pct:number}} } data
*/
static async renderActorSheet5eVehicle(app, html, data) {
const unitSelection = app.object.getFlag(SETTINGS.MOD_NAME, 'unit');
if (!unitSelection) {
await app.object.setFlag(SETTINGS.MOD_NAME, 'unit', DEFAULT_UNIT);
await app.object.update({'system.attributes.capacity.cargo': app.object.system.attributes.capacity.cargo * WEIGHTS[DEFAULT_UNIT].factor});
return;
}
html.find('input[name="system.attributes.capacity.cargo"]')
.after(`<label class="df-qol-cargo-unit" title="${game.i18n.localize(unit[1])}">${unit[0]}</label>`);

const unit = WEIGHTS[unitSelection || DEFAULT_UNIT];
const originalField = html.find('input[name="system.attributes.capacity.cargo"]').hide();
originalField.attr('step', '0.1')
$(`<input type="number" value="${(app.object.system.attributes.capacity.cargo / unit.factor).toNearest(0.01)}" min="0" step="0.01">`)
.on("change", el => {
const unit = WEIGHTS[app.object.getFlag(SETTINGS.MOD_NAME, 'unit') || DEFAULT_UNIT];
const input = $(el.target);
const weight = parseFloat(input.val()).toNearest(0.01);
const actual = (weight * unit.factor).toNearest(1);
originalField.val(actual);
})
.insertAfter(originalField)
.after(`<label class="df-qol-cargo-unit" title="${game.i18n.localize(unit.longLabel)}">${unit.shortLabel}</label>`);
html.find('div.encumbrance label')
.text(`${(data.encumbrance.value / unit.factor).toNearest(0.01)} / ${(data.encumbrance.max / unit.factor).toNearest(0.01)} ${unit.shortLabel}`);
}
static DF_VEHICLE_UNIT_CONFIG(app: EntitySheetConfig, html: JQuery<HTMLElement>, data: EntityConfigData<ActorData>) {

/**
*
* @param {EntitySheetConfig} app
* @param {JQuery<HTMLElement>} html
* @param {EntityConfigData<ActorData>} data
* @returns
*/
static DF_VEHICLE_UNIT_CONFIG(app, html, data) {
if (data.object.type !== "vehicle") return;
const submitButton = html.find('section > form > button');
let current = !!data.object.flags && !!(<any>data.object.flags[SETTINGS.MOD_NAME]) ? (<any>data.object.flags[SETTINGS.MOD_NAME]).unit : null;
// @ts-ignore
if (!current) current = (<DND5E>CONFIG.DND5E).encumbrance.vehicleWeightMultiplier.imperial;

let current = !!data.object.flags && !!data.object.flags[SETTINGS.MOD_NAME] ? data.object.flags[SETTINGS.MOD_NAME].unit : DEFAULT_UNIT;
const unitSelector = $(`<div class="form-group">
<label>${game.i18n.localize('DF_QOL.VehicleUnit.ConfigName')}</label>
<select name="units">
<option value="lt"${current === 2240 ? ' selected' : ''}>${game.i18n.localize('DF_QOL.VehicleUnit.Units_LongTon')}</option>
<option value="st"${current === 2000 ? ' selected' : ''}>${game.i18n.localize('DF_QOL.VehicleUnit.Units_ShortTon')}</option>
<option value="lb"${current === 1 ? ' selected' : ''}>${game.i18n.localize('DF_QOL.VehicleUnit.Units_Pounds')}</option>
<option value="lt"${current === 'lt' ? ' selected' : ''}>${game.i18n.localize(WEIGHTS.lt.longLabel)}</option>
<option value="st"${current === 'st' ? ' selected' : ''}>${game.i18n.localize(WEIGHTS.st.longLabel)}</option>
<option value="lb"${current === 'lb' ? ' selected' : ''}>${game.i18n.localize(WEIGHTS.lb.longLabel)}</option>
</select>
<p class="notes">${game.i18n.localize('DF_QOL.VehicleUnit.ConfigHint')}</p>
</div>`);
submitButton.before(unitSelector);
const newHeight = unitSelector.outerHeight(true) + 8;
app.setPosition(<any>mergeObject(app.position, <any>{ height: <number>app.position.height + newHeight }));
// @ts-ignore
app.setPosition(foundry.utils.mergeObject(app.position, { height: app.position.height + newHeight }));

const core = app._updateObject.bind(app);
// @ts-ignore
app._updateObject = async function (event?: Event, formData?: any) {
// @ts-ignore
const current = <number>(<Actor>this.object).getFlag(SETTINGS.MOD_NAME, 'unit') || (<DND5E>CONFIG.DND5E).encumbrance.vehicleWeightMultiplier.imperial;
let unit = 0;
let newLabel = '';
switch (formData.units) {
case 'lt': unit = 2240; newLabel = 'L.Ton'; break;
case 'st': unit = 2000; newLabel = 'S.Ton'; break;
case 'lb': unit = 1; newLabel = 'lbs'; break;
}
let oldLabel = '';
switch (current) {
case 2240: oldLabel = 'L.Ton'; break;
case 2000: oldLabel = 'S.Ton'; break;
case 1: oldLabel = 'lbs'; break;
}
// Ignore if the unit has not been changed
if (current === unit) {
return core(event, formData);
}
// Ask if they would like us to convert the current value to the new unit of measure.
const confirm = await Dialog.confirm({
title: game.i18n.localize('DF_QOL.VehicleUnit.ConvertTitle'),
content: game.i18n.localize('DF_QOL.VehicleUnit.ConvertContent')
.replace('{{OLD}}', oldLabel).replace('{{NEW}}', newLabel),
defaultYes: true
});
// Convert the data
if (confirm) {
// @ts-expect-error
const pounds = Math.round(this.object.system.attributes.capacity.cargo * current);
await this.object.update({ 'system.attributes.capacity.cargo': (pounds / unit).toNearest(0.01) });
}
await this.object.setFlag(SETTINGS.MOD_NAME, 'unit', unit);
app._updateObject = async function (/**@type {Event|undefined}*/event, /**@type {any|undefined}*/formData) {
const current = this.object.getFlag(SETTINGS.MOD_NAME, 'unit') || DEFAULT_UNIT;
// Only update if the unit has been changed
if (current !== formData.units)
await this.object.setFlag(SETTINGS.MOD_NAME, 'unit', formData.units);
return core(event, formData);
};
}
Expand Down
3 changes: 2 additions & 1 deletion df-qol/src/TokenLock.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/// <reference path="../../foundry-reference-v12.331.js" />
/// <reference path="../../fvtt-scripts/foundry.js" />
/// <reference path="../../fvtt-scripts/foundry-esm.js" />

import SETTINGS from "../common/Settings.mjs";

Expand Down
6 changes: 3 additions & 3 deletions df-qol/src/df-qol.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import FolderColours from './FolderColours.mjs';
import BetterToggle from './BetterToggle.mjs';
import DayNightTransition from './DayNightTransition.mjs';
import DnD5eBetterAttackDialog from './DnD5eBetterAttackDialog.mjs';
// import DnD5eVehicleCapacity from './DnD5eVehicleCapacity.mjs';
import DnD5eVehicleCapacity from './DnD5eVehicleCapacity.mjs';

import SETTINGS from "../common/Settings.mjs";
import TokenLock from './TokenLock.mjs';
Expand All @@ -16,7 +16,7 @@ Hooks.once('init', function () {
BetterToggle.init();
DayNightTransition.init();
DnD5eBetterAttackDialog.init();
// DnD5eVehicleCapacity.init();
DnD5eVehicleCapacity.init();
TokenLock.init();
});

Expand All @@ -27,6 +27,6 @@ Hooks.once('ready', function () {
ui.notifications.error(game.i18n.localize('DF-QOL.errorLibWrapperMissing'));
return;
}
// DnD5eVehicleCapacity.ready();
DnD5eVehicleCapacity.ready();
TokenLock.ready();
});
1 change: 0 additions & 1 deletion df-settings-clarity/module.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"readme": "https://dragonflagon.cafe/mods/doc/df-settings-clarity",
"changelog":"https://dragonflagon.cafe/mods/chg/df-settings-clarity",
"bugs": "https://dragonflagon.cafe/mods/bug/df-settings-clarity",
"manifestPlusVersion": "1.0.0",
"media": [
{ "type": "cover", "url": "https://raw.githubusercontent.com/flamewave000/dragonflagon-fvtt/master/.assets/df-settings-clarity/cover.png" },
{ "type": "icon", "url": "https://raw.githubusercontent.com/flamewave000/dragonflagon-fvtt/master/.assets/logo.png" }
Expand Down
18 changes: 13 additions & 5 deletions doit
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@ doit_utl = "doit -t .doit-files/utl.doit"

init {
@ Initializes the currently targetted module
opt -s @ This is for my own environment to swap filesystems within WSL2
opt -g @ This is to initlaize the global environment
$$$
if ( [ "$1" = "-s" ] || [ "$2" = "-s" ] ) && [ ! "$(pwd)" = "/mnt/c/Projects/dragonflagon-fvtt" ] ; then
cd "/mnt/c/Projects/dragonflagon-fvtt"
fi
if [ "$1" = "-g" ] || [ "$2" = "-g" ]; then
if [ "$1" = "-g" ]; then
npm install
exit
fi
Expand Down Expand Up @@ -76,6 +72,18 @@ env {
$ $doit_env env $@
}

getref {
@@@
Create a sym-link to the foundry.js file found in the set environment.
This reference is used for type hinting and for checking on how Foundry does
certain things.
@@@
$$$
rm -f fvtt-scripts
ln -s "$$(jq -r .foundry.path .devenv)/resources/app/public/scripts/" fvtt-scripts
$$$
}

launch {
@ Launch the foundry server
$ sudo $$(which node) "$$(jq -r .foundry.path .devenv)/resources/app/main.js" --dataPath="$$(jq -r .foundry.data .devenv)"
Expand Down

0 comments on commit 40c0c39

Please sign in to comment.