From ef2e6349b85a3912f6f0f84da92f48769dde258b Mon Sep 17 00:00:00 2001 From: Felix Date: Fri, 12 Jun 2020 17:29:59 +0200 Subject: [PATCH] Add files via upload --- compendium-browser.css | 73 ++++--- compendium-browser.js | 398 +++++++++++++++++++++++++++++++++--- compendium-browser.less | 70 ++++--- item-packs.json | 10 + lang/en.json | 2 +- module.json | 6 +- sub-classes.json | 15 ++ template/feat-browser.html | 38 ++++ template/item-browser.html | 37 ++++ template/npc-browser.html | 2 +- template/settings.html | 8 + template/spell-browser.html | 6 +- template/template.html | 6 +- 13 files changed, 581 insertions(+), 90 deletions(-) create mode 100644 item-packs.json create mode 100644 sub-classes.json create mode 100644 template/feat-browser.html create mode 100644 template/item-browser.html diff --git a/compendium-browser.css b/compendium-browser.css index 61b2be6..0619c1a 100644 --- a/compendium-browser.css +++ b/compendium-browser.css @@ -1,33 +1,38 @@ -/* core foundry changes -#compendium.flexcolumn.active { - display: flex; - flex-direction: column; -} -#compendium.flexcolumn > .directory-list { - width: 100%; - height: auto; - flex-basis: 0; - flex-grow: 1; -} -#compendium.flexcolumn > .directory-footer { - height: auto; -} -#compendium.flexcolumn > .directory-footer > * { - margin-top: 5px; -} -*/ #compendium .directory-footer .compendium-browser-btn { margin-top: 5px; } #compendium .directory-footer { display: block; } -/* spellbrowser */ -/* resizing */ .compendium-browser { + overflow-y: hidden!important; max-width: 1100px; max-height: 90vh; } +.compendium-browser .window-content { + overflow-y: hidden!important; + height: 100%; +} +.compendium-browser .window-content .parent { + overflow-y: hidden!important; + height: 100%; +} +.compendium-browser .window-content .parent .content { + overflow-y: hidden!important; + height: calc(100% - 2em); +} +.compendium-browser .window-content .parent .content .tab { + overflow-y: hidden!important; + height: 100%; +} +.compendium-browser .window-content .parent .content .tab .browser { + overflow-y: hidden!important; + height: 100%; +} +.compendium-browser .window-content .parent .content .tab .browser ul { + overflow-y: auto; + height: 100%; +} .compendium-browser .tabs { max-height: 2em; border-bottom: solid #782e22; @@ -109,6 +114,10 @@ .compendium-browser .control-area .filtercontainer .small-select { width: 40px; } +.compendium-browser .browser { + height: 100%; + overflow-y: hidden!important; +} .compendium-browser .browser .window-content { overflow-y: hidden!important; } @@ -137,20 +146,38 @@ display: inline-block; min-width: 15px; } -.compendium-browser .spell-browser .spell { +.compendium-browser .item-browser li, +.compendium-browser .feat-browser li, +.compendium-browser .spell-browser li { cursor: default; vertical-align: middle; line-height: 32px; margin: 2px 0; } -.compendium-browser .spell-browser .spell .spell-image { +.compendium-browser .item-browser li .item-image, +.compendium-browser .feat-browser li .item-image, +.compendium-browser .spell-browser li .item-image { max-width: 32px; height: 32px; } -.compendium-browser .spell-browser .spell .spell-name { +.compendium-browser .item-browser li .item-name, +.compendium-browser .feat-browser li .item-name, +.compendium-browser .spell-browser li .item-name { height: 32px; padding-left: 5px; } +.compendium-browser .item-browser li .feat-tags, +.compendium-browser .feat-browser li .feat-tags, +.compendium-browser .spell-browser li .feat-tags, +.compendium-browser .item-browser li .item-tags, +.compendium-browser .feat-browser li .item-tags, +.compendium-browser .spell-browser li .item-tags { + text-align: right; + margin-right: 3px; + margin-left: 3px; + text-transform: capitalize; + height: 32px; +} .compendium-browser .spell-browser .spell .spell-level { text-align: center; font-weight: 900; diff --git a/compendium-browser.js b/compendium-browser.js index a0955da..69304f3 100644 --- a/compendium-browser.js +++ b/compendium-browser.js @@ -10,7 +10,7 @@ class SpellBrowser extends Application { if (this.settings === undefined) { this.initSettings(); } - this.loadSpells().then(obj => { + this.loadItems().then(obj => { this.spells = obj; }); this.loadNpcs().then(obj => { @@ -19,6 +19,8 @@ class SpellBrowser extends Application { await loadTemplates([ "modules/compendium-browser/template/spell-browser.html", "modules/compendium-browser/template/npc-browser.html", + "modules/compendium-browser/template/feat-browser.html", + "modules/compendium-browser/template/item-browser.html", "modules/compendium-browser/template/filter-container.html", "modules/compendium-browser/template/settings.html" ]); @@ -33,6 +35,14 @@ class SpellBrowser extends Application { registeredFilterCategorys: {}, activeFilters: {} }; + this.featFilters = { + registeredFilterCategorys: {}, + activeFilters: {} + }; + this.itemFilters = { + registeredFilterCategorys: {}, + activeFilters: {} + }; } static get defaultOptions() { @@ -77,14 +87,20 @@ class SpellBrowser extends Application { async getData() { if (!this.spellsLoaded) { // spells will be stored locally to not require full loading each time the browser is opened - this.spells = await this.loadSpells(); + this.items = await this.loadItems(); this.spellsLoaded = true; } let data = {}; - data.spells = this.spells; + data.spells = this.items.spells; data.spellFilters = this.spellFilters; data.showSpellBrowser = (game.user.isGM || this.settings.allowSpellBrowser); + data.feats = this.items.feats; + data.featFilters = this.featFilters; + data.showFeatBrowser = (game.user.isGM || this.settings.allowFeatBrowser); + data.items = this.items.items; + data.itemFilters = this.itemFilters; + data.showItemBrowser = (game.user.isGM || this.settings.allowItemBrowser); data.npcs = this.npcs; data.npcFilters = this.npcFilters; data.showNpcBrowser = (game.user.isGM || this.settings.allowNpcBrowser); @@ -93,8 +109,8 @@ class SpellBrowser extends Application { return data; } - async loadSpells() { - console.log('Spell Browser | Started loading spells'); + async loadItems() { + console.log('Spell Browser | Started loading items'); if (this.classList === undefined) { this.classList = await fetch('modules/compendium-browser/spell-classes.json').then(result => { @@ -104,45 +120,135 @@ class SpellBrowser extends Application { }); } + if (this.packList === undefined) { + this.packList = await fetch('modules/compendium-browser/item-packs.json').then(result => { + return result.json(); + }).then(obj => { + return this.packList = obj; + }); + } + + if (this.subClasses === undefined) { + this.subClasses = await fetch('modules/compendium-browser/sub-classes.json').then(result => { + return result.json(); + }).then(obj => { + return this.subClasses = obj; + }); + } + this.spellsLoaded = false; this.spellsLoading = true; let unfoundSpells = ''; - let spells = {}; + let items = { + spells: {}, + feats: {}, + items: {} + }; + + for (let pack of game.packs) { if (pack['metadata']['entity'] == "Item" && this.settings.loadedSpellCompendium[pack.collection].load) { await pack.getContent().then(content => { - for (let spell of content) { - spell = spell.data; - if (spell.type == 'spell') { + for (let item5e of content) { + let item = item5e.data; + if (item.type == 'spell') { - spell.compendium = pack.collection; + item.compendium = pack.collection; // determining classes that can use the spell - let cleanSpellName = spell.name.toLowerCase().replace(/[^一-龠ぁ-ゔァ-ヴーa-zA-Z0-9a-zA-Z0-9々〆〤]/g, '').replace("'", '').replace(/ /g, ''); + let cleanSpellName = item.name.toLowerCase().replace(/[^一-龠ぁ-ゔァ-ヴーa-zA-Z0-9a-zA-Z0-9々〆〤]/g, '').replace("'", '').replace(/ /g, ''); //let cleanSpellName = spell.name.toLowerCase().replace(/[^a-zA-Z0-9\s:]/g, '').replace("'", '').replace(/ /g, ''); if (this.classList[cleanSpellName] !== undefined) { let classes = this.classList[cleanSpellName]; - spell.data.classes = classes.split(','); + item.data.classes = classes.split(','); } else { unfoundSpells += cleanSpellName + ','; } // getting damage types - spell.damageTypes = []; - if (spell.data.damage && spell.data.damage.parts.length > 0) { - for (let part of spell.data.damage.parts) { + item.damageTypes = []; + if (item.data.damage && item.data.damage.parts.length > 0) { + for (let part of item.data.damage.parts) { let type = part[1]; - if (spell.damageTypes.indexOf(type) === -1) { - spell.damageTypes.push(type); + if (item.damageTypes.indexOf(type) === -1) { + item.damageTypes.push(type); } } } - spells[(spell._id)] = spell; - } + items.spells[(item._id)] = item; + } else if (item.type == 'feat' || item.type == 'class') { + item.compendium = pack.collection; + // getting damage types + item.damageTypes = []; + if (item.data.damage && item.data.damage.parts.length > 0) { + for (let part of item.data.damage.parts) { + let type = part[1]; + if (item.damageTypes.indexOf(type) === -1) { + item.damageTypes.push(type); + } + } + } + + // getting class + let reqString = item.data.requirements.replace(/[0-9]/g, '').trim(); + let matchedClass = []; + for (let c in this.subClasses) { + if (reqString.toLowerCase().indexOf(c) !== -1) { + matchedClass.push(c); + } else { + for (let subClass of this.subClasses[c]) { + if (reqString.indexOf(subClass) !== -1) { + matchedClass.push(c); + break; + } + } + } + } + item.classRequirement = matchedClass; + item.classRequirementString = matchedClass.join(', '); + + // getting uses/ressources status + item.usesRessources = item5e.hasLimitedUses; + + item.hasSave = item5e.hasSave; + + + items.feats[(item._id)] = item; + } else { + item.compendium = pack.collection; + // getting damage types + item.damageTypes = []; + if (item.data.damage && item.data.damage.parts.length > 0) { + for (let part of item.data.damage.parts) { + let type = part[1]; + if (item.damageTypes.indexOf(type) === -1) { + item.damageTypes.push(type); + } + } + } + + // getting pack + let matchedPacks = []; + for (let pack in this.packList) { + for (let packItem of this.packList[pack]) { + if (item.name.toLowerCase() === packItem.toLowerCase()) { + matchedPacks.push(pack); + break; + } + } + } + item.matchedPacks = matchedPacks; + item.matchedPacksString = matchedPacks.join(', '); + + // getting uses/ressources status + item.usesRessources = item5e.hasLimitedUses + + items.items[(item._id)] = item; + } } }); } @@ -151,19 +257,21 @@ class SpellBrowser extends Application { console.log(`Spell Browser | List of Spells that don't have a class assosiated to them:`); console.log(unfoundSpells); } - console.log('Spell Browser | Finished loading spells'); - return spells; + console.log('Spell Browser | Finished loading items'); + return items; } async loadNpcs() { - console.log('NPC Browser | Started loading spells'); + console.log('NPC Browser | Started loading NPCs'); let npcs = {}; for (let pack of game.packs) { if (pack['metadata']['entity'] == "Actor" && this.settings.loadedNpcCompendium[pack.collection].load) { await pack.getContent().then(async content => { + for (let npc of content) { + //console.log('%c '+npc.name, 'background: white; color: red') npc = npc.data; // add needed data npc.compendium = pack.collection; @@ -267,6 +375,32 @@ class SpellBrowser extends Application { }); html.find('.spell-browser select[name=sortorder]').trigger('change'); + // sort feat list + html.find('.feat-browser select[name=sortorder]').on('change', ev => { + let featList = html.find('.feat-browser li'); + let byName = (ev.target.value == 'true'); + let sortedList = this.sortFeats(featList, byName); + let ol = $(html.find('.feat-browser ul')); + ol[0].innerHTML = []; + for (let element of sortedList) { + ol[0].append(element); + } + }); + html.find('.feat-browser select[name=sortorder]').trigger('change'); + + // sort item list + html.find('.item-browser select[name=sortorder]').on('change', ev => { + let itemList = html.find('.item-browser li'); + let byName = (ev.target.value == 'true'); + let sortedList = this.sortItems(itemList, byName); + let ol = $(html.find('.item-browser ul')); + ol[0].innerHTML = []; + for (let element of sortedList) { + ol[0].append(element); + } + }); + html.find('.item-browser select[name=sortorder]').trigger('change'); + // sort npc list html.find('.npc-browser select[name=sortorder]').on('change', ev => { let npcList = html.find('.npc-browser li'); @@ -286,6 +420,16 @@ class SpellBrowser extends Application { this.render(); }); + html.find('#reset-feat-filter').click(ev => { + this.featFilters.activeFilters = {}; + this.render(); + }); + + html.find('#reset-item-filter').click(ev => { + this.itemFilters.activeFilters = {}; + this.render(); + }); + html.find('#reset-npc-filter').click(ev => { this.npcFilters.activeFilters = {}; this.render(); @@ -298,7 +442,7 @@ class SpellBrowser extends Application { if (setting === 'spell-compendium-setting') { let key = ev.target.dataset.key; this.settings.loadedSpellCompendium[key].load = value; - this.loadSpells().then((spells) => { + this.loadItems().then((spells) => { this.spells = spells; this.render(); }); @@ -315,6 +459,12 @@ class SpellBrowser extends Application { if (setting === 'allow-spell-browser') { this.settings.allowSpellBrowser = value; } + if (setting === 'allow-feat-browser') { + this.settings.allowFeatBrowser = value; + } + if (setting === 'allow-item-browser') { + this.settings.allowItemBrowser = value; + } if (setting === 'allow-npc-browser') { this.settings.allowNpcBrowser = value; } @@ -349,10 +499,16 @@ class SpellBrowser extends Application { let subjects = null; if (itemType === 'spell') { list = html.find('.spell-browser li'); - subjects = this.spells; + subjects = this.items.spells; } else if (itemType === 'npc') { list = html.find('.npc-browser li'); subjects = this.npcs; + } else if (itemType === 'feat') { + list = html.find('.feat-browser li'); + subjects = this.items.feats; + } else if (itemType === 'item') { + list = html.find('.item-browser li'); + subjects = this.items.items; } this.filterElements(list, subjects, this[filterTarget].activeFilters); }); @@ -386,10 +542,16 @@ class SpellBrowser extends Application { let subjects = null; if (itemType === 'spell') { list = html.find('.spell-browser li'); - subjects = this.spells; + subjects = this.items.spells; } else if (itemType === 'npc') { list = html.find('.npc-browser li'); subjects = this.npcs; + } else if (itemType === 'feat') { + list = html.find('.feat-browser li'); + subjects = this.items.feats; + } else if (itemType === 'item') { + list = html.find('.item-browser li'); + subjects = this.items.items; } this.filterElements(list, subjects, this[filterTarget].activeFilters); }); @@ -429,10 +591,16 @@ class SpellBrowser extends Application { let subjects = null; if (itemType === 'spell') { list = html.find('.spell-browser li'); - subjects = this.spells; + subjects = this.items.spells; } else if (itemType === 'npc') { list = html.find('.npc-browser li'); subjects = this.npcs; + } else if (itemType === 'feat') { + list = html.find('.feat-browser li'); + subjects = this.items.feats; + } else if (itemType === 'item') { + list = html.find('.item-browser li'); + subjects = this.items.items; } this.filterElements(list, subjects, this[filterTarget].activeFilters); }); @@ -466,21 +634,45 @@ class SpellBrowser extends Application { let subjects = null; if (itemType === 'spell') { list = html.find('.spell-browser li'); - subjects = this.spells; + subjects = this.items.spells; } else if (itemType === 'npc') { list = html.find('.npc-browser li'); subjects = this.npcs; + } else if (itemType === 'feat') { + list = html.find('.feat-browser li'); + subjects = this.items.feats; + } else if (itemType === 'item') { + list = html.find('.item-browser li'); + subjects = this.items.items; } this.filterElements(list, subjects, this[filterTarget].activeFilters); }); + + // lazy load images + const observer = new IntersectionObserver((entries, observer) => { + for (let e of entries) { + if (!e.isIntersecting) continue; + const img = e.target; + // Avatar image + //const img = li.querySelector("img"); + if (img && img.dataset.src) { + img.src = img.dataset.src; + delete img.dataset.src; + } + + // No longer observe the target + observer.unobserve(e.target); + } + }); + html.find("img").each((i, img) => observer.observe(img)); } sortSpells(list, byName) { if(byName) { list.sort((a, b) => { - let aName = $(a).find('.spell-name a')[0].innerHTML; - let bName = $(b).find('.spell-name a')[0].innerHTML; + let aName = $(a).find('.item-name a')[0].innerHTML; + let bName = $(b).find('.item-name a')[0].innerHTML; if (aName < bName) return -1; if (aName > bName) return 1; return 0; @@ -492,8 +684,62 @@ class SpellBrowser extends Application { if (aVal < bVal) return -1; if (aVal > bVal) return 1; if (aVal == bVal) { - let aName = $(a).find('.spell-name a')[0].innerHTML; - let bName = $(b).find('.spell-name a')[0].innerHTML; + let aName = $(a).find('.item-name a')[0].innerHTML; + let bName = $(b).find('.item-name a')[0].innerHTML; + if (aName < bName) return -1; + if (aName > bName) return 1; + return 0; + } + }); + } + return list; + } + + sortFeats(list, byName) { + if (byName) { + list.sort((a, b) => { + let aName = $(a).find('.item-name a')[0].innerHTML; + let bName = $(b).find('.item-name a')[0].innerHTML; + if (aName < bName) return -1; + if (aName > bName) return 1; + return 0; + }); + } else { + list.sort((a, b) => { + let aVal = $(a).find('input[name=class]').val(); + let bVal = $(b).find('input[name=class]').val(); + if (aVal < bVal) return -1; + if (aVal > bVal) return 1; + if (aVal == bVal) { + let aName = $(a).find('.item-name a')[0].innerHTML; + let bName = $(b).find('.item-name a')[0].innerHTML; + if (aName < bName) return -1; + if (aName > bName) return 1; + return 0; + } + }); + } + return list; + } + + sortItems(list, byName) { + if (byName) { + list.sort((a, b) => { + let aName = $(a).find('.item-name a')[0].innerHTML; + let bName = $(b).find('.item-name a')[0].innerHTML; + if (aName < bName) return -1; + if (aName > bName) return 1; + return 0; + }); + } else { + list.sort((a, b) => { + let aVal = $(a).find('input[name=type]').val(); + let bVal = $(b).find('input[name=type]').val(); + if (aVal < bVal) return -1; + if (aVal > bVal) return 1; + if (aVal == bVal) { + let aName = $(a).find('.item-name a')[0].innerHTML; + let bName = $(b).find('.item-name a')[0].innerHTML; if (aName < bName) return -1; if (aName > bName) return 1; return 0; @@ -572,6 +818,7 @@ class SpellBrowser extends Application { } if (filter.valIsArray === false) { if (filter.type === 'text') { + if (prop === undefined) return false; if (prop.toLowerCase().indexOf(filter.value.toLowerCase()) === -1) { return false; } @@ -599,7 +846,6 @@ class SpellBrowser extends Application { } } } else { - console.log(prop); for (let val of filter.values) { if (prop === val) { continue; @@ -666,10 +912,15 @@ class SpellBrowser extends Application { defaultSettings.loadedNpcCompendium[compKey].load = settings.loadedNpcCompendium[compKey].load; } } - defaultSettings.allowSpellBrowser = settings.allowSpellBrowser; - defaultSettings.allowNpcBrowser = settings.allowNpcBrowser; + defaultSettings.allowSpellBrowser = settings.allowSpellBrowser ? true : false; + defaultSettings.allowFeatBrowser = settings.allowFeatBrowser ? true : false; + defaultSettings.allowItemBrowser = settings.allowItemBrowser ? true : false; + defaultSettings.allowNpcBrowser = settings.allowNpcBrowser ? true : false; + if (game.user.isGM) { game.settings.set('compendiumBrowser', 'settings', defaultSettings); + console.log("New default settings set"); + console.log(defaultSettings); } this.settings = defaultSettings; } @@ -701,6 +952,9 @@ class SpellBrowser extends Application { } + _lazyLoadImg(entries, observer) { + } + /** * Used to add custom filters to the Spell-Browser * @param {String} category - Title of the category @@ -738,6 +992,14 @@ class SpellBrowser extends Application { addNpcFilter(category, label, path, type, possibleValues = null, valIsArray = false) { this.addFilter('npc', category, label, path, type, possibleValues, valIsArray); } + + addFeatFilter(category, label, path, type, possibleValues = null, valIsArray = false) { + this.addFilter('feat', category, label, path, type, possibleValues, valIsArray); + } + + addItemFilter(category, label, path, type, possibleValues = null, valIsArray = false) { + this.addFilter('item', category, label, path, type, possibleValues, valIsArray); + } } Hooks.on('ready', async function() { @@ -747,6 +1009,8 @@ Hooks.on('ready', async function() { await game.compendiumBrowser.initializeContent(); } + // Spellfilters + game.compendiumBrowser.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'data.source', 'text'); game.compendiumBrowser.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.lvl"), 'data.level', 'multiSelect', [game.i18n.localize("CMPBrowser.cantip"), 1, 2, 3, 4, 5, 6, 7, 8, 9]); game.compendiumBrowser.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.school"), 'data.school', 'select', CONFIG.DND5E.spellSchools); @@ -780,6 +1044,72 @@ Hooks.on('ready', async function() { game.compendiumBrowser.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.somatic"), 'data.components.somatic', 'bool'); game.compendiumBrowser.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.material"), 'data.components.material', 'bool'); + // Feature Filters + + game.compendiumBrowser.addFeatFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'data.source', 'text'); + game.compendiumBrowser.addFeatFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.class"), 'classRequirement', 'select', + { + artificer: game.i18n.localize("CMPBrowser.artificer"), + barbarian: "Barbarian", + bard: game.i18n.localize("CMPBrowser.bard"), + cleric: game.i18n.localize("CMPBrowser.cleric"), + druid: game.i18n.localize("CMPBrowser.druid"), + fighter: "Fighter", + monk: "Monk", + paladin: game.i18n.localize("CMPBrowser.paladin"), + ranger: game.i18n.localize("CMPBrowser.ranger"), + rogue: "Rogue", + sorcerer: game.i18n.localize("CMPBrowser.sorcerer"), + warlock: game.i18n.localize("CMPBrowser.warlock"), + wizard: game.i18n.localize("CMPBrowser.wizard") + }, true); + + game.compendiumBrowser.addFeatFilter("Game Mechanics", game.i18n.localize("DND5E.ItemActivationCost"), 'data.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes); + game.compendiumBrowser.addFeatFilter("Game Mechanics", game.i18n.localize("CMPBrowser.damageType"), 'damageTypes', 'select', CONFIG.DND5E.damageTypes); + game.compendiumBrowser.addFeatFilter("Game Mechanics", "Uses Resources", 'usesRessources', 'bool'); + + + // Item Filters + + game.compendiumBrowser.addItemFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'data.source', 'text'); + game.compendiumBrowser.addItemFilter(game.i18n.localize("CMPBrowser.general"), "Item Type", 'type', 'select', { + consumable: game.i18n.localize("DND5E.ItemTypeConsumable"), + backpack: game.i18n.localize("DND5E.ItemTypeContainer"), + equipment: game.i18n.localize("DND5E.ItemTypeEquipment"), + loot: game.i18n.localize("DND5E.ItemTypeLoot"), + tool: game.i18n.localize("DND5E.ItemTypeTool"), + weapon: game.i18n.localize("DND5E.ItemTypeWeapon") + }); + game.compendiumBrowser.addItemFilter(game.i18n.localize("CMPBrowser.general"), "Packs", 'matchedPacks', 'select', + { + burglar: "Burglar's Pack", + diplomat: "Diplomat's Pack", + dungeoneer: "Dungeoneer's Pack", + entertainer: "Entertainer's Pack", + explorer: "Explorer's Pack", + monsterhunter: "Monster Hunter's Pack", + priest: "Priest's Pack", + scholar: "Scholar's Pack", + }, true); + + game.compendiumBrowser.addItemFilter("Game Mechanics", game.i18n.localize("DND5E.ItemActivationCost"), 'data.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes); + game.compendiumBrowser.addItemFilter("Game Mechanics", game.i18n.localize("CMPBrowser.damageType"), 'damageTypes', 'select', CONFIG.DND5E.damageTypes); + game.compendiumBrowser.addItemFilter("Game Mechanics", "Uses Resources", 'usesRessources', 'bool'); + + game.compendiumBrowser.addItemFilter("Item Subtype", "Weapon", 'data.weaponType', 'text', CONFIG.DND5E.weaponTypes); + game.compendiumBrowser.addItemFilter("Item Subtype", "Equipment", 'data.armor.type', 'text', CONFIG.DND5E.equipmentTypes); + game.compendiumBrowser.addItemFilter("Item Subtype", "Consumable", 'data.consumableType', 'text', CONFIG.DND5E.consumableTypes); + + game.compendiumBrowser.addItemFilter("Magic Items", "Rarity", 'data.rarity', 'select', { + Common: "Common", + Uncommon: "Uncommon", + Rare: "Rare", + "Very rare": "Very Rare", + Legendary: "Legendary" + }); + + // NPC Filters + game.compendiumBrowser.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'data.details.source', 'text'); game.compendiumBrowser.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.size"), 'data.traits.size', 'select', CONFIG.DND5E.actorSizes); game.compendiumBrowser.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.hasSpells"), 'hasSpells', 'bool'); diff --git a/compendium-browser.less b/compendium-browser.less index 3ac99a7..928ae09 100644 --- a/compendium-browser.less +++ b/compendium-browser.less @@ -1,21 +1,3 @@ -/* core foundry changes -#compendium.flexcolumn.active { - display: flex; - flex-direction: column; -} -#compendium.flexcolumn > .directory-list { - width: 100%; - height: auto; - flex-basis: 0; - flex-grow: 1; -} -#compendium.flexcolumn > .directory-footer { - height: auto; -} -#compendium.flexcolumn > .directory-footer > * { - margin-top: 5px; -} -*/ #compendium .directory-footer .compendium-browser-btn { margin-top:5px; } @@ -24,12 +6,36 @@ display:block; } -/* spellbrowser */ -/* resizing */ .compendium-browser { + overflow-y: hidden!important; max-width:1100px; max-height:90vh; + .window-content { + overflow-y: hidden!important; + height: 100%; + .parent { + overflow-y: hidden!important; + height: 100%; + .content { + overflow-y: hidden!important; + height: calc(100% - 2em); + .tab { + overflow-y: hidden!important; + height: 100%; + .browser { + overflow-y: hidden!important; + height: 100%; + ul { + overflow-y:auto; + height:100%; + } + } + } + } + } + } + .tabs { max-height:2em; border-bottom: solid #782e22; @@ -123,6 +129,8 @@ } .browser { + height: 100%; + overflow-y: hidden!important; .window-content { overflow-y: hidden!important; @@ -161,21 +169,35 @@ } } - .spell-browser { - .spell { + .item-browser, .feat-browser, .spell-browser { + li { cursor:default; vertical-align: middle; line-height:32px; margin:2px 0; - .spell-image { + .item-image { max-width:32px; height:32px; } - .spell-name { + .item-name { height:32px; padding-left:5px; } + + .feat-tags, .item-tags { + text-align:right; + margin-right:3px; + margin-left: 3px; + text-transform:capitalize; + height:32px; + } + } + } + + .spell-browser { + .spell { + .spell-level { text-align:center; font-weight:900; diff --git a/item-packs.json b/item-packs.json new file mode 100644 index 0000000..6ef94ac --- /dev/null +++ b/item-packs.json @@ -0,0 +1,10 @@ +{ + "burglar": ["Burglar's Pack", "Backpack","Ball Bearings", "String", "Bell", "Candle", "Crowbar", "Hammer", "Piton", "Hooded Lantern", "Oil Flask", "Rations", "Tinderbox","Waterskin","Hempen Rope (50 ft.)"], + "diplomat": ["Diplomat's Pack", "Chest", "Map or Scroll Case", "Fine Clothes", "Ink Bottle", "Ink Pen", "Lamp", "Oil Flask", "Paper", "Perfume", "Sealing Wax", "Soap"], + "dungeoneer": ["Dungeoneer's Pack", "Backpack", "Crowbar", "Hammer", "Piton", "Torch", "Tinderbox", "Rations", "Waterskin", "Hempen Rope (50 ft.)"], + "entertainer": ["Entertainer's Pack", "Backpack", "Bedroll", "Costume Clothes", "Candle", "Rations", "Waterskin", "Disguise Kit"], + "explorer": ["Explorer's Pack", "Backpack", "Bedroll", "Mess Kit", "Tinderbox", "Torch", "Rations", "Waterskin", "Hempen Rope (50 ft.)"], + "monsterhunter": ["Monster Hunter's Pack", "Chest", "Crowbar", "Hammer", "Wooden Stake", "Holy Symbol", "Flask of Holy Water", "Manacles", "Steel Mirror", "Oil Flask", "Tinderbox", "Torch"], + "priest": ["Priest's Pack", "Backpack", "Blanket", "Candle", "Tinderbox", "Alms Box", "Block of Incense", "Censor", "Vestments", "Rations", "Waterskin"], + "scholar": ["Scholar's Pack", "Backpack", "Book of Lore", "Ink Bottle", "Ink Pen", "Parchment", "Bag of Sand", "Small Knife"] +} \ No newline at end of file diff --git a/lang/en.json b/lang/en.json index a89f4d6..5f4b998 100644 --- a/lang/en.json +++ b/lang/en.json @@ -5,7 +5,7 @@ "CMPBrowser.generalSettings":"General Settings", "CMPBrowser.allowSpellAcc":"Allow Players Access to the spell browser", "CMPBrowser.allowNpcAcc":"Allow Players Access to the npc browser", - "CMPBrowser.compSettingsSpell":"Spell Compendium Settings", + "CMPBrowser.compSettingsSpell":"Item Compendium Settings", "CMPBrowser.compSettingsNpc":"NPC Compendium Settings", "CMPBrowser.load":"Load", "CMPBrowser.lvl":"Level", diff --git a/module.json b/module.json index cb2b1c8..d1bf696 100644 --- a/module.json +++ b/module.json @@ -2,7 +2,7 @@ "name": "compendium-browser", "title": "Compendium Browser", "description": "A module to easily browse and filter spells as well as npcs loaded from compendie.", - "version": "0.2.1", + "version": "0.3.0", "author": "Felix#6196", "systems": ["dnd5e"], "scripts": ["./compendium-browser.js"], @@ -28,6 +28,6 @@ "url": "https://github.com/syl3r86/compendium-browser", "manifest": "https://raw.githubusercontent.com/syl3r86/compendium-browser/master/module.json", "download": "https://github.com/syl3r86/compendium-browser/archive/master.zip", - "minimumCoreVersion": "0.5.5", - "compatibleCoreVersion": "0.5.5" + "minimumCoreVersion": "0.6.2", + "compatibleCoreVersion": "0.6.2" } diff --git a/sub-classes.json b/sub-classes.json new file mode 100644 index 0000000..072d52c --- /dev/null +++ b/sub-classes.json @@ -0,0 +1,15 @@ +{ + "artificer":["Alchemist","Gunsmith"], + "barbarian":["Ancesstrial Guardian", "Battlerager", "Berserker", "Storm Herald", "Totem Warriro", "Zealot"], + "bard":["Eloquence", "Glamour", "Lore", "Swords", "Valor", "Whispers"], + "cleric":["Arcana", "Death", "Forge", "Grave", "Knowledge", "Life", "Light", "Nature", "Order", "Tempest", "Trickery", "War Domain"], + "druid":["Dreams", "Land", "Moon", "Sheapherd", "Spores"], + "fighter":["Arcane Archer", "Battle Master", "Cavalier", "Champion", "Echo Knight", "Eldritch Knight", "Samurai"], + "monk":["Drunken Master", "Four Elements", "Kensei", "Long Death", "Open Hand", "Shadow", "Sun Soul"], + "paladin":["Ancients", "Conquest", "Crown", "Devotion", "Glory", "Oathbreaker", "Redemption", "Vengeance"], + "ranger":["Beast Master", "Gloom Stalker", "Horizon Walker", "Hunter", "Monster Slayer"], + "rogue":["Arcane Trickster", "Assassin", "Inquisitive", "Mastermind", "Scout", "Swashbuckler", "Thief"], + "sorcerer":["Devine Soul", "Draconic", "Shadow", "Storm", "Wild"], + "warlock":["Archfey", "Celestial", "Fiend","Great Old One", "Hexblade", "Undying"], + "wizard":["Abjuration", "Bladesinging", "Chronurgy", "Conjuration", "Divination", "Énchantment", "Evocation", "Graviturgy", "Illusion", "Necromancy", "Transmutation", "War Magic"] +} \ No newline at end of file diff --git a/template/feat-browser.html b/template/feat-browser.html new file mode 100644 index 0000000..34d8b94 --- /dev/null +++ b/template/feat-browser.html @@ -0,0 +1,38 @@ +
+
+
+
+ +
+
+
{{localize "CMPBrowser.sortBy"}}:
+
+
+ +
+ {{> "modules/compendium-browser/template/filter-container.html" filters=featFilters}} +
+ + +
\ No newline at end of file diff --git a/template/item-browser.html b/template/item-browser.html new file mode 100644 index 0000000..603fb56 --- /dev/null +++ b/template/item-browser.html @@ -0,0 +1,37 @@ +
+
+
+
+ +
+
+
{{localize "CMPBrowser.sortBy"}}:
+
+
+ +
+ {{> "modules/compendium-browser/template/filter-container.html" filters=itemFilters}} +
+ + +
\ No newline at end of file diff --git a/template/npc-browser.html b/template/npc-browser.html index 4472b02..dc0af5f 100644 --- a/template/npc-browser.html +++ b/template/npc-browser.html @@ -20,7 +20,7 @@ {{#each npcs as |npc id|}}
  • - +
    diff --git a/template/settings.html b/template/settings.html index 823ac4a..9a442be 100644 --- a/template/settings.html +++ b/template/settings.html @@ -5,6 +5,14 @@

    {{localize "CMPBrowser.allowSpellAcc"}}

    + +