Files
fvtt-ftl-nomad/module/utils.mjs
LeRatierBretonnien d2cbe71731
All checks were successful
Release Creation / build (release) Successful in 1m34s
Fix enc for equipments/weapons
2025-07-13 19:30:28 +02:00

709 lines
24 KiB
JavaScript

import { SYSTEM } from "./config/system.mjs"
export default class FTLNomadUtils {
static registerSettings() {
game.settings.register("fvtt-ftl-nomad", "settings-era", {
name: game.i18n.localize("FTLNOMAD.Settings.era"),
hint: game.i18n.localize("FTLNOMAD.Settings.eraHint"),
default: "jazz",
scope: "world",
type: String,
choices: SYSTEM.AVAILABLE_SETTINGS,
config: true,
onChange: _ => window.location.reload()
});
}
static async loadCompendiumData(compendium) {
const pack = game.packs.get(compendium)
return await pack?.getDocuments() ?? []
}
static async loadCompendium(compendium, filter = item => true) {
let compendiumData = await FTLNomadUtils.loadCompendiumData(compendium)
return compendiumData.filter(filter)
}
static registerHandlebarsHelpers() {
Handlebars.registerHelper('isNull', function (val) {
return val == null;
});
Handlebars.registerHelper('exists', function (val) {
return val != null && val !== undefined;
});
Handlebars.registerHelper('isEmpty', function (list) {
if (list) return list.length === 0;
else return false;
});
Handlebars.registerHelper('notEmpty', function (list) {
return list.length > 0;
});
Handlebars.registerHelper('isNegativeOrNull', function (val) {
return val <= 0;
});
Handlebars.registerHelper('isNegative', function (val) {
return val < 0;
});
Handlebars.registerHelper('isPositive', function (val) {
return val > 0;
});
Handlebars.registerHelper('equals', function (val1, val2) {
return val1 === val2;
});
Handlebars.registerHelper('neq', function (val1, val2) {
return val1 !== val2;
});
Handlebars.registerHelper('gt', function (val1, val2) {
return val1 > val2;
})
Handlebars.registerHelper('lt', function (val1, val2) {
return val1 < val2;
})
Handlebars.registerHelper('gte', function (val1, val2) {
return val1 >= val2;
})
Handlebars.registerHelper('lte', function (val1, val2) {
return val1 <= val2;
})
Handlebars.registerHelper('and', function (val1, val2) {
return val1 && val2;
})
Handlebars.registerHelper('or', function (val1, val2) {
return val1 || val2;
})
Handlebars.registerHelper('or3', function (val1, val2, val3) {
return val1 || val2 || val3;
})
Handlebars.registerHelper('for', function (from, to, incr, block) {
let accum = '';
for (let i = from; i < to; i += incr)
accum += block.fn(i);
return accum;
})
Handlebars.registerHelper('not', function (cond) {
return !cond;
})
Handlebars.registerHelper('count', function (list) {
return list.length;
})
Handlebars.registerHelper('countKeys', function (obj) {
return Object.keys(obj).length;
})
Handlebars.registerHelper('isEnabled', function (configKey) {
return game.settings.get("bol", configKey);
})
Handlebars.registerHelper('split', function (str, separator, keep) {
return str.split(separator)[keep];
})
// If you need to add Handlebars helpers, here are a few useful examples:
Handlebars.registerHelper('concat', function () {
let outStr = '';
for (let arg in arguments) {
if (typeof arguments[arg] != 'object') {
outStr += arguments[arg];
}
}
return outStr;
})
Handlebars.registerHelper('add', function (a, b) {
return parseInt(a) + parseInt(b);
});
Handlebars.registerHelper('mul', function (a, b) {
return parseInt(a) * parseInt(b);
})
Handlebars.registerHelper('sub', function (a, b) {
return parseInt(a) - parseInt(b);
})
Handlebars.registerHelper('abbrev2', function (a) {
return a.substring(0, 2);
})
Handlebars.registerHelper('abbrev3', function (a) {
return a.substring(0, 3);
})
Handlebars.registerHelper('valueAtIndex', function (arr, idx) {
return arr[idx];
})
Handlebars.registerHelper('includesKey', function (items, type, key) {
return items.filter(i => i.type === type).map(i => i.system.key).includes(key);
})
Handlebars.registerHelper('includes', function (array, val) {
return array.includes(val);
})
Handlebars.registerHelper('eval', function (expr) {
return eval(expr);
})
Handlebars.registerHelper('isOwnerOrGM', function (actor) {
console.log("Testing actor", actor.isOwner, game.userId)
return actor.isOwner || game.isGM;
})
Handlebars.registerHelper('upperFirst', function (text) {
if (typeof text !== 'string') return text
return text.charAt(0).toUpperCase() + text.slice(1)
})
Handlebars.registerHelper('upperFirstOnly', function (text) {
if (typeof text !== 'string') return text
return text.charAt(0).toUpperCase()
})
Handlebars.registerHelper('isCreature', function (key) {
return key === "creature" || key === "daemon";
})
// Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
const html = options.fn(this);
return html.replace(rgx, "$& selected");
});
}
static setupCSSRootVariables() {
const era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
let eraCSS = SYSTEM.ERA_CSS[era];
if (!eraCSS) eraCSS = SYSTEM.ERA_CSS["jazz"];
document.documentElement.style.setProperty('--font-size-standard', eraCSS.baseFontSize);
document.documentElement.style.setProperty('--font-size-title', eraCSS.titleFontSize);
document.documentElement.style.setProperty('--font-size-result', eraCSS.titleFontSize);
document.documentElement.style.setProperty('--font-primary', eraCSS.primaryFont);
document.documentElement.style.setProperty('--font-secondary', eraCSS.secondaryFont);
document.documentElement.style.setProperty('--font-title', eraCSS.titleFont);
document.documentElement.style.setProperty('--img-icon-color-filter', eraCSS.imgFilter);
document.documentElement.style.setProperty('--background-image-base', `linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8)), url("../assets/ui/${era}_background_main.webp")`);
}
static getTechAgeKeyFromLabel(label) {
return Object.keys(SYSTEM.TECH_AGES).find(key => game.i18n.localize(SYSTEM.TECH_AGES[key].label) === label);
}
static async importPsionics() {
// Create a psionics folder if it doesn't exist
const psionicsFolder = game.folders.getName("Psionics") || await Folder.create({
name: "Psionics", type: "Item"
})
if (!psionicsFolder) {
console.error("Failed to create Psionics folder");
return;
}
// Load the psionics JSON file
const psionicsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/psionics.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load psionics data:", error);
return [];
});
// Import each psionic ability
for (const psionic of psionicsData) {
// Check if the psionic already exists
const existingPsionic = game.items.find(i => i.name === psionic.name && i.type === "psionic");
if (existingPsionic) {
console.warn(`Psionic ${psionic.name} already exists, skipping import.`);
continue;
}
// Create the psionic item
await Item.create({
name: psionic.name,
type: "psionic",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_psionic.svg",
system: {
description: psionic.description,
},
folder: psionicsFolder.id
});
}
}
static async importTalents() {
// Create a talents folder if it doesn't exist
const talentsFolder = game.folders.getName("Talents") || await Folder.create({
name: "Talents", type: "Item"
})
if (!talentsFolder) {
console.error("Failed to create Talents folder");
return;
}
// Load the talents JSON file
const talentsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/talents.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load talents data:", error);
return [];
});
// Import each talent
for (const talent of talentsData) {
// Check if the talent already exists
const existingTalent = game.items.find(i => i.name === talent.name && i.type === "talent");
if (existingTalent) {
console.warn(`Talent ${talent.name} already exists, skipping import.`);
continue;
}
talent.advantage = false;
if (talent.description.includes(" +1D")) {
talent.advantage = true
}
// Create the talent item
await Item.create({
name: talent.name,
type: "talent",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_talent.svg",
system: {
description: talent.description,
isAdvantage: talent.advantage,
},
folder: talentsFolder.id
});
}
}
static async importImplants() {
// Create a implants folder if it doesn't exist
const implantsFolder = game.folders.getName("Implants") || await Folder.create({
name: "Implants", type: "Item"
})
if (!implantsFolder) {
console.error("Failed to create Implants folder");
return;
}
// Load the implants JSON file
const implantsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/implants.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load implants data:", error);
return [];
});
// Import each implant
for (const implant of implantsData) {
// Check if the implant already exists
const existingImplant = game.items.find(i => i.name === implant.name && i.type === "implant");
if (existingImplant) {
console.warn(`Implant ${implant.name} already exists, skipping import.`);
continue;
}
if (!Number(implant.cost)) {
implant.cost = 1000000;
}
// Create the implant item
await Item.create({
name: implant.name,
type: "implant",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_implant.svg",
system: {
cost: implant.cost,
loss: implant.loss,
techAge: this.getTechAgeKeyFromLabel(implant.tech_age),
description: implant.description,
},
folder: implantsFolder.id
});
}
}
static async importDrugs() {
// Create a drugs folder if it doesn't exist
const drugsFolder = game.folders.getName("Drugs") || await Folder.create({
name: "Drugs", type: "Item"
})
if (!drugsFolder) {
console.error("Failed to create Drugs folder");
return;
}
// Load the drugs JSON file
const drugsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/drugs.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load drugs data:", error);
return [];
});
// Import each drug
for (const drug of drugsData) {
// Check if the drug already exists
const existingDrug = game.items.find(i => i.name === drug.name && i.type === "drug");
if (existingDrug) {
console.warn(`Drug ${drug.name} already exists, skipping import.`);
continue;
}
// Create the drug item
await Item.create({
name: drug.name,
type: "equipment",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_equipment.svg",
system: {
description: drug.description,
cost: drug.cost,
techAge: this.getTechAgeKeyFromLabel(drug.tech_age),
},
folder: drugsFolder.id
});
}
}
static async importEquipments() {
// Create a equipments folder if it doesn't exist
const equipmentsFolder = game.folders.getName("Equipments") || await Folder.create({
name: "Equipments", type: "Item"
})
if (!equipmentsFolder) {
console.error("Failed to create Equipments folder");
return;
}
// Load the equipments JSON file
const equipmentsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/exploration_equipment.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load equipments data:", error);
return [];
});
// Import each equipment
for (const equipment of equipmentsData) {
// Check if the equipment already exists
const existingEquipment = game.items.find(i => i.name === equipment.name && i.type === "equipment");
if (existingEquipment) {
console.warn(`Equipment ${equipment.name} already exists, skipping import.`);
continue;
}
if (!Number(equipment.cost)) {
equipment.cost = 1000000;
}
// Create the equipment item
await Item.create({
name: equipment.name,
type: "equipment",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_equipment.svg",
system: {
description: equipment.description,
cost: equipment.cost,
techAge: this.getTechAgeKeyFromLabel(equipment.tech_age),
},
folder: equipmentsFolder.id
});
}
}
static async importDistanceWeapons() {
// Create a distance weapons folder if it doesn't exist
const distanceWeaponsFolder = game.folders.getName("Vehicle Weapons") || await Folder.create({
name: "Vehicle Weapons", type: "Item"
})
if (!distanceWeaponsFolder) {
console.error("Failed to create Distance Weapons folder");
return;
}
// Load the distance weapons JSON file
const distanceWeaponsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/vehicle_weapons.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load distance weapons data:", error);
return [];
});
// Import each distance weapon
for (const weapon of distanceWeaponsData) {
// Check if the weapon already exists
const existingWeapon = game.items.find(i => i.name === weapon.name && i.type === "weapon");
if (existingWeapon) {
console.warn(`Weapon ${weapon.name} already exists, skipping import.`);
continue;
}
// Create the weapon item
await Item.create({
name: weapon.name,
type: "weapon",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_weapon.svg",
system: {
description: weapon.description,
damage: weapon.damage,
techAge: this.getTechAgeKeyFromLabel(weapon.tech_age),
weaponType: SYSTEM.WEAPON_TYPES.vehicle.id,
rangeType: weapon.range.toLowerCase(),
enc: 0,
aspect: weapon.aspects.join(", "),
cost: weapon.cost || 0,
ammoCost: weapon.ammo_cost || 0,
magazine: weapon.mag || 1,
},
folder: distanceWeaponsFolder.id
});
}
}
static async importStarships() {
// Create a starships folder if it doesn't exist
const starshipsFolder = game.folders.getName("Starships") || await Folder.create({
name: "Starships", type: "Actor"
})
if (!starshipsFolder) {
console.error("Failed to create Starships folder");
return;
}
// Load the starships JSON file
const starshipsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/starships.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load starships data:", error);
return [];
});
// Import each starship
for (const starship of starshipsData) {
// Check if the starship already exists
const existingStarship = game.actors.find(a => a.name === starship.name && a.type === "starship");
if (existingStarship) {
console.warn(`Starship ${starship.name} already exists, skipping import.`);
continue;
}
// Create the starship actor
await Actor.create({
name: starship.name,
type: "starship",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_starship.svg",
system: {
description: starship.description,
agility: starship.agility,
hullType: starship.hullType.toLowerCase(),
endurance: starship.endurance,
armor: starship.armor,
crew: starship.crew,
cargo: starship.cargo,
guns: starship.guns,
travelMultiplier: starship.travelMultiplier,
cost: starship.cost || 0,
monthlyCost: starship.monthlyCost || 0,
damages: starship.damages,
},
folder: starshipsFolder.id
});
}
}
static async importVehicles() {
// Create a vehicles folder if it doesn't exist
const vehiclesFolder = game.folders.getName("Vehicles") || await Folder.create({
name: "Vehicles", type: "Actor"
})
if (!vehiclesFolder) {
console.error("Failed to create Vehicles folder");
return;
}
// Load the vehicles JSON file
const vehiclesData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/vehicles.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load vehicles data:", error);
return [];
});
// Import each vehicle
for (const vehicle of vehiclesData) {
// Check if the vehicle already exists
const existingVehicle = game.items.find(i => i.name === vehicle.name && i.type === "vehicle");
if (existingVehicle) {
console.warn(`Vehicle ${vehicle.name} already exists, skipping import.`);
continue;
}
// Create the vehicle item
await Actor.create({
name: vehicle.name,
type: "vehicle",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_vehicle.svg",
system: {
description: vehicle.description,
agility: vehicle.agility,
armor: vehicle.armor,
cargo: vehicle.cargo,
crew: vehicle.crew,
force: vehicle.force,
range: vehicle.range,
speed: vehicle.speed,
techAge: this.getTechAgeKeyFromLabel(vehicle.tech_age),
tonnage: vehicle.tonnage,
damages: vehicle.damages,
cost: vehicle.cost || 0,
},
folder: vehiclesFolder.id
});
}
}
static async importArmors() {
// Create an armors folder if it doesn't exist
const armorsFolder = game.folders.getName("Armors") || await Folder.create({
name: "Armors", type: "Item"
})
if (!armorsFolder) {
console.error("Failed to create Armors folder");
return;
}
// Load the armors JSON file
const armorsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/armors.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load armors data:", error);
return [];
});
// Import each armor
for (const armor of armorsData) {
// Check if the armor already exists
const existingArmor = game.items.find(i => i.name === armor.name && i.type === "armor");
if (existingArmor) {
console.warn(`Armor ${armor.name} already exists, skipping import.`);
continue;
}
// Create the armor item
await Item.create({
name: armor.name,
type: "armor",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_armor.svg",
system: {
description: armor.description,
enc: armor.enc || 0,
techAge: this.getTechAgeKeyFromLabel(armor.tech_age),
cost: armor.cost || 0,
protection: armor.protection || 0,
},
folder: armorsFolder.id
});
}
}
static async importGrenadeWeapons() {
// Create a grenade weapons folder if it doesn't exist
const grenadeWeaponsFolder = game.folders.getName("Grenade") || await Folder.create({
name: "Grenade", type: "Item"
})
if (!grenadeWeaponsFolder) {
console.error("Failed to create Grenade Weapons folder");
return;
}
// Load the grenade weapons JSON file
const grenadeWeaponsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/grenades.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load grenade weapons data:", error);
return [];
});
// Import each grenade weapon
for (const weapon of grenadeWeaponsData) {
// Check if the weapon already exists
const existingWeapon = game.items.find(i => i.name === weapon.name && i.type === "weapon");
if (existingWeapon) {
console.warn(`Weapon ${weapon.name} already exists, skipping import.`);
continue;
}
// Create the weapon item
await Item.create({
name: weapon.name,
type: "weapon",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_weapon.svg",
system: {
description: weapon.description,
damage: weapon.damage,
techAge: this.getTechAgeKeyFromLabel(weapon.tech_age),
weaponType: SYSTEM.WEAPON_TYPES.grenade.id,
rangeType: SYSTEM.WEAPON_RANGE.thrownweapon.id,
enc: 0,
aspect: weapon.aspects.join(", "),
cost: weapon.cost || 0,
ammoCost: 0,
},
folder: grenadeWeaponsFolder.id
});
}
}
static async fixWeaponsEnc() {
// Iterate over all items of type "weapon" from compendium
const weapons = game.items.filter(i => i.type === "weapon");
for (const weapon of weapons) {
// If the weapon's encumbrance is less than 1, set it to 1
if (weapon.system.enc < 1) {
await weapon.update({ "system.enc": 1 });
}
}
}
static async fixEquipmentEnc() {
// Iterate over all items of type "equipment" from compendium
const equipments = game.items.filter(i => i.type === "equipment");
for (const equipment of equipments) {
// If the equipment's encumbrance is less than 1, set it to
if (equipment.system.enc < 1) {
await equipment.update({ "system.enc": 1 });
}
}
}
static async importMeleeWeapons() {
// Create a melee weapons folder if it doesn't exist
const meleeWeaponsFolder = game.folders.getName("Melee Weapons") || await Folder.create({
name: "Melee Weapons", type: "Item"
})
if (!meleeWeaponsFolder) {
console.error("Failed to create Melee Weapons folder");
return;
}
// Load the melee weapons JSON file
const meleeWeaponsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/weapon_melee.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load melee weapons data:", error);
return [];
});
console.log("Melee Weapons Data", meleeWeaponsData);
// Import each melee weapon
for (const weapon of meleeWeaponsData) {
// Check if the weapon already exists
const existingWeapon = game.items.find(i => i.name === weapon.name && i.type === "weapon");
if (existingWeapon) {
console.warn(`Weapon ${weapon.name} already exists, skipping import.`);
continue;
}
// Create the weapon item
await Item.create({
name: weapon.name,
type: "weapon",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_weapon.svg",
system: {
description: weapon.description,
damage: weapon.damage,
techAge: this.getTechAgeKeyFromLabel(weapon.tech_age),
weaponType: SYSTEM.WEAPON_TYPES.melee.id,
rangeType: SYSTEM.WEAPON_RANGE.melee.id,
enc: 0,
aspect: weapon.aspects.join(", "),
cost: weapon.cost || 0,
ammoCost: 0,
},
folder: meleeWeaponsFolder.id
});
}
}
}