/** * A simple and flexible system for world-building using an arbitrary collection of character and item attributes * Author: Atropos * Software License: GNU GPLv3 */ // Import Modules import { registerSystemSettings } from "./settings.js"; import { preloadHandlebarsTemplates } from "./blades-templates.js"; import { bladesRoll, simpleRollPopup } from "./blades-roll.js"; import { BladesHelpers } from "./blades-helpers.js"; import { BladesActor } from "./blades-actor.js"; import { BladesItem } from "./blades-item.js"; import { BladesItemSheet } from "./blades-item-sheet.js"; import { BladesActorSheet } from "./blades-actor-sheet.js"; import { BladesActiveEffect } from "./blades-active-effect.js"; import { BladesCrewSheet } from "./blades-crew-sheet.js"; import { BladesClockSheet } from "./blades-clock-sheet.js"; import { BladesNPCSheet } from "./blades-npc-sheet.js"; import { BladesFactionSheet } from "./blades-faction-sheet.js"; import * as migrations from "./migration.js"; window.BladesHelpers = BladesHelpers; /* -------------------------------------------- */ /* Foundry VTT Initialization */ /* -------------------------------------------- */ Hooks.once("init", async function() { console.log(`Initializing Blades In the Dark System`); game.blades = { dice: bladesRoll }; game.system.bladesClocks = { sizes: [ 4, 6, 8 ] }; CONFIG.Item.documentClass = BladesItem; CONFIG.Actor.documentClass = BladesActor; CONFIG.ActiveEffect.documentClass = BladesActiveEffect; // Register System Settings registerSystemSettings(); // Register sheet application classes Actors.unregisterSheet("core", ActorSheet); Actors.registerSheet("blades", BladesActorSheet, { types: ["character"], makeDefault: true }); Actors.registerSheet("blades", BladesCrewSheet, { types: ["crew"], makeDefault: true }); Actors.registerSheet("blades", BladesFactionSheet, { types: ["factions"], makeDefault: true }); Actors.registerSheet("blades", BladesClockSheet, { types: ["\uD83D\uDD5B clock"], makeDefault: true }); Actors.registerSheet("blades", BladesNPCSheet, { types: ["npc"], makeDefault: true }); Items.unregisterSheet("core", ItemSheet); Items.registerSheet("blades", BladesItemSheet, {makeDefault: true}); await preloadHandlebarsTemplates(); Actors.registeredSheets.forEach(element => console.log(element.Actor.name)); // Is the value Turf side. Handlebars.registerHelper('is_turf_side', function(value, options) { if (["left", "right", "top", "bottom"].includes(value)) { return options.fn(this); } else { return options.inverse(this); } }); // Multiboxes. Handlebars.registerHelper('multiboxes', function(selected, options) { let html = options.fn(this); // Fix for single non-array values. if ( !Array.isArray(selected) ) { selected = [selected]; } if (typeof selected !== 'undefined') { selected.forEach(selected_value => { if (selected_value !== false) { let escapedValue = RegExp.escape(Handlebars.escapeExpression(selected_value)); let rgx = new RegExp(' value=\"' + escapedValue + '\"'); let oldHtml = html; html = html.replace(rgx, "$& checked"); while( ( oldHtml === html ) && ( escapedValue >= 0 ) ){ escapedValue--; rgx = new RegExp(' value=\"' + escapedValue + '\"'); html = html.replace(rgx, "$& checked"); } } }); } return html; }); // Trauma Counter Handlebars.registerHelper('traumacounter', function(selected, options) { let html = options.fn(this); var count = 0; for (const trauma in selected) { if (selected[trauma] === true) { count++; } } if (count > 4) count = 4; const rgx = new RegExp(' value=\"' + count + '\"'); return html.replace(rgx, "$& checked"); }); // NotEquals handlebar. Handlebars.registerHelper('noteq', (a, b, options) => { return (a !== b) ? options.fn(this) : ''; }); // ReputationTurf handlebar. Handlebars.registerHelper('repturf', (turfs_amount, options) => { let html = options.fn(this); var turfs_amount_int = parseInt(turfs_amount); // Can't be more than 6. if (turfs_amount_int > 6) { turfs_amount_int = 6; } for (let i = 13 - turfs_amount_int; i <= 12; i++) { const rgx = new RegExp(' value=\"' + i + '\"'); html = html.replace(rgx, "$& disabled"); } return html; }); Handlebars.registerHelper('crew_vault_coins', (max_coins, options) => { let html = options.fn(this); for (let i = 1; i <= max_coins; i++) { html += ""; } return html; }); Handlebars.registerHelper('crew_experience', (_id, options) => { let html = options.fn(this); for (let i = 1; i <= 10; i++) { html += ``; } return html; }); // Enrich the HTML replace /n with
Handlebars.registerHelper('html', (options) => { let text = options.hash['text'].replace(/\n/g, "
"); return new Handlebars.SafeString(text); }); // "N Times" loop for handlebars. // Block is executed N times starting from n=1. // // Usage: // {{#times_from_1 10}} // {{this}} // {{/times_from_1}} Handlebars.registerHelper('times_from_1', function(n, block) { var accum = ''; for (var i = 1; i <= n; ++i) { accum += block.fn(i); } return accum; }); // "N Times" loop for handlebars. // Block is executed N times starting from n=0. // // Usage: // {{#times_from_0 10}} // {{this}} // {{/times_from_0}} Handlebars.registerHelper('times_from_0', function(n, block) { var accum = ''; for (var i = 0; i <= n; ++i) { accum += block.fn(i); } return accum; }); // Concat helper // https://gist.github.com/adg29/f312d6fab93652944a8a1026142491b1 // Usage: (concat 'first 'second') Handlebars.registerHelper('concat', function() { var outStr = ''; for(var arg in arguments){ if(typeof arguments[arg]!='object'){ outStr += arguments[arg]; } } return outStr; }); /** * @inheritDoc * Takes label from Selected option instead of just plain value. */ Handlebars.registerHelper('selectOptionsWithLabel', function(choices, options) { const localize = options.hash['localize'] ?? false; let selected = options.hash['selected'] ?? null; let blank = options.hash['blank'] || null; selected = selected instanceof Array ? selected.map(String) : [String(selected)]; // Create an option const option = (key, object) => { if ( localize ) object.label = game.i18n.localize(object.label); let isSelected = selected.includes(key); html += `` }; // Create the options let html = ""; if ( blank ) option("", blank); Object.entries(choices).forEach(e => option(...e)); return new Handlebars.SafeString(html); }); /** * Create appropriate Blades clock */ Handlebars.registerHelper('blades-clock', function(parameter_name, type, current_value, uniq_id) { let html = ''; if (current_value === null || current_value === 'null') { current_value = 0; } if (parseInt(current_value) > parseInt(type)) { current_value = type; } // Label for 0 html += ``; html += `
`; let zero_checked = (parseInt(current_value) === 0) ? 'checked' : ''; html += ``; for (let i = 1; i <= parseInt(type); i++) { let checked = (parseInt(current_value) === i) ? 'checked' : ''; html += ` `; } html += `
`; return html; }); }); /** * Once the entire VTT framework is initialized, check to see if we should perform a data migration */ Hooks.once("ready", function() { // Determine whether a system migration is required const currentVersion = game.settings.get("bitd", "systemMigrationVersion"); const NEEDS_MIGRATION_VERSION = 2.15; let needMigration = (currentVersion < NEEDS_MIGRATION_VERSION) || (currentVersion === null); // Perform the migration if ( needMigration && game.user.isGM ) { migrations.migrateWorld(); } }); /* * Hooks */ // getSceneControlButtons Hooks.on("renderSceneControls", async (app, html) => { let dice_roller = $('
  • '); dice_roller.click( async function() { await simpleRollPopup(); }); html.children().first().append( dice_roller ); });