Add files via upload

v0.3.0
Felix 2020-06-12 17:29:59 +02:00 committed by GitHub
parent 8c076e313d
commit ef2e6349b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 581 additions and 90 deletions

View File

@ -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 { #compendium .directory-footer .compendium-browser-btn {
margin-top: 5px; margin-top: 5px;
} }
#compendium .directory-footer { #compendium .directory-footer {
display: block; display: block;
} }
/* spellbrowser */
/* resizing */
.compendium-browser { .compendium-browser {
overflow-y: hidden!important;
max-width: 1100px; max-width: 1100px;
max-height: 90vh; 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 { .compendium-browser .tabs {
max-height: 2em; max-height: 2em;
border-bottom: solid #782e22; border-bottom: solid #782e22;
@ -109,6 +114,10 @@
.compendium-browser .control-area .filtercontainer .small-select { .compendium-browser .control-area .filtercontainer .small-select {
width: 40px; width: 40px;
} }
.compendium-browser .browser {
height: 100%;
overflow-y: hidden!important;
}
.compendium-browser .browser .window-content { .compendium-browser .browser .window-content {
overflow-y: hidden!important; overflow-y: hidden!important;
} }
@ -137,20 +146,38 @@
display: inline-block; display: inline-block;
min-width: 15px; 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; cursor: default;
vertical-align: middle; vertical-align: middle;
line-height: 32px; line-height: 32px;
margin: 2px 0; 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; max-width: 32px;
height: 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; height: 32px;
padding-left: 5px; 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 { .compendium-browser .spell-browser .spell .spell-level {
text-align: center; text-align: center;
font-weight: 900; font-weight: 900;

View File

@ -10,7 +10,7 @@ class SpellBrowser extends Application {
if (this.settings === undefined) { if (this.settings === undefined) {
this.initSettings(); this.initSettings();
} }
this.loadSpells().then(obj => { this.loadItems().then(obj => {
this.spells = obj; this.spells = obj;
}); });
this.loadNpcs().then(obj => { this.loadNpcs().then(obj => {
@ -19,6 +19,8 @@ class SpellBrowser extends Application {
await loadTemplates([ await loadTemplates([
"modules/compendium-browser/template/spell-browser.html", "modules/compendium-browser/template/spell-browser.html",
"modules/compendium-browser/template/npc-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/filter-container.html",
"modules/compendium-browser/template/settings.html" "modules/compendium-browser/template/settings.html"
]); ]);
@ -33,6 +35,14 @@ class SpellBrowser extends Application {
registeredFilterCategorys: {}, registeredFilterCategorys: {},
activeFilters: {} activeFilters: {}
}; };
this.featFilters = {
registeredFilterCategorys: {},
activeFilters: {}
};
this.itemFilters = {
registeredFilterCategorys: {},
activeFilters: {}
};
} }
static get defaultOptions() { static get defaultOptions() {
@ -77,14 +87,20 @@ class SpellBrowser extends Application {
async getData() { async getData() {
if (!this.spellsLoaded) { if (!this.spellsLoaded) {
// spells will be stored locally to not require full loading each time the browser is opened // 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; this.spellsLoaded = true;
} }
let data = {}; let data = {};
data.spells = this.spells; data.spells = this.items.spells;
data.spellFilters = this.spellFilters; data.spellFilters = this.spellFilters;
data.showSpellBrowser = (game.user.isGM || this.settings.allowSpellBrowser); 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.npcs = this.npcs;
data.npcFilters = this.npcFilters; data.npcFilters = this.npcFilters;
data.showNpcBrowser = (game.user.isGM || this.settings.allowNpcBrowser); data.showNpcBrowser = (game.user.isGM || this.settings.allowNpcBrowser);
@ -93,8 +109,8 @@ class SpellBrowser extends Application {
return data; return data;
} }
async loadSpells() { async loadItems() {
console.log('Spell Browser | Started loading spells'); console.log('Spell Browser | Started loading items');
if (this.classList === undefined) { if (this.classList === undefined) {
this.classList = await fetch('modules/compendium-browser/spell-classes.json').then(result => { this.classList = await fetch('modules/compendium-browser/spell-classes.json').then(result => {
@ -104,44 +120,134 @@ 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.spellsLoaded = false;
this.spellsLoading = true; this.spellsLoading = true;
let unfoundSpells = ''; let unfoundSpells = '';
let spells = {}; let items = {
spells: {},
feats: {},
items: {}
};
for (let pack of game.packs) { for (let pack of game.packs) {
if (pack['metadata']['entity'] == "Item" && this.settings.loadedSpellCompendium[pack.collection].load) { if (pack['metadata']['entity'] == "Item" && this.settings.loadedSpellCompendium[pack.collection].load) {
await pack.getContent().then(content => { await pack.getContent().then(content => {
for (let spell of content) { for (let item5e of content) {
spell = spell.data; let item = item5e.data;
if (spell.type == 'spell') { if (item.type == 'spell') {
spell.compendium = pack.collection; item.compendium = pack.collection;
// determining classes that can use the spell // determining classes that can use the spell
let cleanSpellName = spell.name.toLowerCase().replace(/[^一-龠ぁ-ゔァ-ヴーa-zA-Z0-9---9々〆〤]/g, '').replace("'", '').replace(/ /g, ''); let cleanSpellName = item.name.toLowerCase().replace(/[^一-龠ぁ-ゔァ-ヴーa-zA-Z0-9---9々〆〤]/g, '').replace("'", '').replace(/ /g, '');
//let cleanSpellName = spell.name.toLowerCase().replace(/[^a-zA-Z0-9\s:]/g, '').replace("'", '').replace(/ /g, ''); //let cleanSpellName = spell.name.toLowerCase().replace(/[^a-zA-Z0-9\s:]/g, '').replace("'", '').replace(/ /g, '');
if (this.classList[cleanSpellName] !== undefined) { if (this.classList[cleanSpellName] !== undefined) {
let classes = this.classList[cleanSpellName]; let classes = this.classList[cleanSpellName];
spell.data.classes = classes.split(','); item.data.classes = classes.split(',');
} else { } else {
unfoundSpells += cleanSpellName + ','; unfoundSpells += cleanSpellName + ',';
} }
// getting damage types // getting damage types
spell.damageTypes = []; item.damageTypes = [];
if (spell.data.damage && spell.data.damage.parts.length > 0) { if (item.data.damage && item.data.damage.parts.length > 0) {
for (let part of spell.data.damage.parts) { for (let part of item.data.damage.parts) {
let type = part[1]; let type = part[1];
if (spell.damageTypes.indexOf(type) === -1) { if (item.damageTypes.indexOf(type) === -1) {
spell.damageTypes.push(type); 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(`Spell Browser | List of Spells that don't have a class assosiated to them:`);
console.log(unfoundSpells); console.log(unfoundSpells);
} }
console.log('Spell Browser | Finished loading spells'); console.log('Spell Browser | Finished loading items');
return spells; return items;
} }
async loadNpcs() { async loadNpcs() {
console.log('NPC Browser | Started loading spells'); console.log('NPC Browser | Started loading NPCs');
let npcs = {}; let npcs = {};
for (let pack of game.packs) { for (let pack of game.packs) {
if (pack['metadata']['entity'] == "Actor" && this.settings.loadedNpcCompendium[pack.collection].load) { if (pack['metadata']['entity'] == "Actor" && this.settings.loadedNpcCompendium[pack.collection].load) {
await pack.getContent().then(async content => { await pack.getContent().then(async content => {
for (let npc of content) { for (let npc of content) {
//console.log('%c '+npc.name, 'background: white; color: red')
npc = npc.data; npc = npc.data;
// add needed data // add needed data
npc.compendium = pack.collection; npc.compendium = pack.collection;
@ -267,6 +375,32 @@ class SpellBrowser extends Application {
}); });
html.find('.spell-browser select[name=sortorder]').trigger('change'); 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 // sort npc list
html.find('.npc-browser select[name=sortorder]').on('change', ev => { html.find('.npc-browser select[name=sortorder]').on('change', ev => {
let npcList = html.find('.npc-browser li'); let npcList = html.find('.npc-browser li');
@ -286,6 +420,16 @@ class SpellBrowser extends Application {
this.render(); 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 => { html.find('#reset-npc-filter').click(ev => {
this.npcFilters.activeFilters = {}; this.npcFilters.activeFilters = {};
this.render(); this.render();
@ -298,7 +442,7 @@ class SpellBrowser extends Application {
if (setting === 'spell-compendium-setting') { if (setting === 'spell-compendium-setting') {
let key = ev.target.dataset.key; let key = ev.target.dataset.key;
this.settings.loadedSpellCompendium[key].load = value; this.settings.loadedSpellCompendium[key].load = value;
this.loadSpells().then((spells) => { this.loadItems().then((spells) => {
this.spells = spells; this.spells = spells;
this.render(); this.render();
}); });
@ -315,6 +459,12 @@ class SpellBrowser extends Application {
if (setting === 'allow-spell-browser') { if (setting === 'allow-spell-browser') {
this.settings.allowSpellBrowser = value; 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') { if (setting === 'allow-npc-browser') {
this.settings.allowNpcBrowser = value; this.settings.allowNpcBrowser = value;
} }
@ -349,10 +499,16 @@ class SpellBrowser extends Application {
let subjects = null; let subjects = null;
if (itemType === 'spell') { if (itemType === 'spell') {
list = html.find('.spell-browser li'); list = html.find('.spell-browser li');
subjects = this.spells; subjects = this.items.spells;
} else if (itemType === 'npc') { } else if (itemType === 'npc') {
list = html.find('.npc-browser li'); list = html.find('.npc-browser li');
subjects = this.npcs; 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); this.filterElements(list, subjects, this[filterTarget].activeFilters);
}); });
@ -386,10 +542,16 @@ class SpellBrowser extends Application {
let subjects = null; let subjects = null;
if (itemType === 'spell') { if (itemType === 'spell') {
list = html.find('.spell-browser li'); list = html.find('.spell-browser li');
subjects = this.spells; subjects = this.items.spells;
} else if (itemType === 'npc') { } else if (itemType === 'npc') {
list = html.find('.npc-browser li'); list = html.find('.npc-browser li');
subjects = this.npcs; 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); this.filterElements(list, subjects, this[filterTarget].activeFilters);
}); });
@ -429,10 +591,16 @@ class SpellBrowser extends Application {
let subjects = null; let subjects = null;
if (itemType === 'spell') { if (itemType === 'spell') {
list = html.find('.spell-browser li'); list = html.find('.spell-browser li');
subjects = this.spells; subjects = this.items.spells;
} else if (itemType === 'npc') { } else if (itemType === 'npc') {
list = html.find('.npc-browser li'); list = html.find('.npc-browser li');
subjects = this.npcs; 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); this.filterElements(list, subjects, this[filterTarget].activeFilters);
}); });
@ -466,21 +634,45 @@ class SpellBrowser extends Application {
let subjects = null; let subjects = null;
if (itemType === 'spell') { if (itemType === 'spell') {
list = html.find('.spell-browser li'); list = html.find('.spell-browser li');
subjects = this.spells; subjects = this.items.spells;
} else if (itemType === 'npc') { } else if (itemType === 'npc') {
list = html.find('.npc-browser li'); list = html.find('.npc-browser li');
subjects = this.npcs; 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); 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) { sortSpells(list, byName) {
if(byName) { if(byName) {
list.sort((a, b) => { list.sort((a, b) => {
let aName = $(a).find('.spell-name a')[0].innerHTML; let aName = $(a).find('.item-name a')[0].innerHTML;
let bName = $(b).find('.spell-name a')[0].innerHTML; let bName = $(b).find('.item-name a')[0].innerHTML;
if (aName < bName) return -1; if (aName < bName) return -1;
if (aName > bName) return 1; if (aName > bName) return 1;
return 0; return 0;
@ -492,8 +684,62 @@ class SpellBrowser extends Application {
if (aVal < bVal) return -1; if (aVal < bVal) return -1;
if (aVal > bVal) return 1; if (aVal > bVal) return 1;
if (aVal == bVal) { if (aVal == bVal) {
let aName = $(a).find('.spell-name a')[0].innerHTML; let aName = $(a).find('.item-name a')[0].innerHTML;
let bName = $(b).find('.spell-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;
if (aName > bName) return 1; if (aName > bName) return 1;
return 0; return 0;
@ -572,6 +818,7 @@ class SpellBrowser extends Application {
} }
if (filter.valIsArray === false) { if (filter.valIsArray === false) {
if (filter.type === 'text') { if (filter.type === 'text') {
if (prop === undefined) return false;
if (prop.toLowerCase().indexOf(filter.value.toLowerCase()) === -1) { if (prop.toLowerCase().indexOf(filter.value.toLowerCase()) === -1) {
return false; return false;
} }
@ -599,7 +846,6 @@ class SpellBrowser extends Application {
} }
} }
} else { } else {
console.log(prop);
for (let val of filter.values) { for (let val of filter.values) {
if (prop === val) { if (prop === val) {
continue; continue;
@ -666,10 +912,15 @@ class SpellBrowser extends Application {
defaultSettings.loadedNpcCompendium[compKey].load = settings.loadedNpcCompendium[compKey].load; defaultSettings.loadedNpcCompendium[compKey].load = settings.loadedNpcCompendium[compKey].load;
} }
} }
defaultSettings.allowSpellBrowser = settings.allowSpellBrowser; defaultSettings.allowSpellBrowser = settings.allowSpellBrowser ? true : false;
defaultSettings.allowNpcBrowser = settings.allowNpcBrowser; defaultSettings.allowFeatBrowser = settings.allowFeatBrowser ? true : false;
defaultSettings.allowItemBrowser = settings.allowItemBrowser ? true : false;
defaultSettings.allowNpcBrowser = settings.allowNpcBrowser ? true : false;
if (game.user.isGM) { if (game.user.isGM) {
game.settings.set('compendiumBrowser', 'settings', defaultSettings); game.settings.set('compendiumBrowser', 'settings', defaultSettings);
console.log("New default settings set");
console.log(defaultSettings);
} }
this.settings = defaultSettings; this.settings = defaultSettings;
} }
@ -701,6 +952,9 @@ class SpellBrowser extends Application {
} }
_lazyLoadImg(entries, observer) {
}
/** /**
* Used to add custom filters to the Spell-Browser * Used to add custom filters to the Spell-Browser
* @param {String} category - Title of the category * @param {String} category - Title of the category
@ -738,6 +992,14 @@ class SpellBrowser extends Application {
addNpcFilter(category, label, path, type, possibleValues = null, valIsArray = false) { addNpcFilter(category, label, path, type, possibleValues = null, valIsArray = false) {
this.addFilter('npc', category, label, path, type, possibleValues, valIsArray); 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() { Hooks.on('ready', async function() {
@ -747,6 +1009,8 @@ Hooks.on('ready', async function() {
await game.compendiumBrowser.initializeContent(); 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("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.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); 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.somatic"), 'data.components.somatic', 'bool');
game.compendiumBrowser.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.material"), 'data.components.material', '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("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.size"), 'data.traits.size', 'select', CONFIG.DND5E.actorSizes);
game.compendiumBrowser.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.hasSpells"), 'hasSpells', 'bool'); game.compendiumBrowser.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.hasSpells"), 'hasSpells', 'bool');

View File

@ -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 { #compendium .directory-footer .compendium-browser-btn {
margin-top:5px; margin-top:5px;
} }
@ -24,12 +6,36 @@
display:block; display:block;
} }
/* spellbrowser */
/* resizing */
.compendium-browser { .compendium-browser {
overflow-y: hidden!important;
max-width:1100px; max-width:1100px;
max-height:90vh; 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 { .tabs {
max-height:2em; max-height:2em;
border-bottom: solid #782e22; border-bottom: solid #782e22;
@ -123,6 +129,8 @@
} }
.browser { .browser {
height: 100%;
overflow-y: hidden!important;
.window-content { .window-content {
overflow-y: hidden!important; overflow-y: hidden!important;
@ -161,21 +169,35 @@
} }
} }
.spell-browser { .item-browser, .feat-browser, .spell-browser {
.spell { li {
cursor:default; cursor:default;
vertical-align: middle; vertical-align: middle;
line-height:32px; line-height:32px;
margin:2px 0; margin:2px 0;
.spell-image { .item-image {
max-width:32px; max-width:32px;
height:32px; height:32px;
} }
.spell-name { .item-name {
height:32px; height:32px;
padding-left:5px; 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 { .spell-level {
text-align:center; text-align:center;
font-weight:900; font-weight:900;

10
item-packs.json 100644
View File

@ -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"]
}

View File

@ -5,7 +5,7 @@
"CMPBrowser.generalSettings":"General Settings", "CMPBrowser.generalSettings":"General Settings",
"CMPBrowser.allowSpellAcc":"Allow Players Access to the spell browser", "CMPBrowser.allowSpellAcc":"Allow Players Access to the spell browser",
"CMPBrowser.allowNpcAcc":"Allow Players Access to the npc 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.compSettingsNpc":"NPC Compendium Settings",
"CMPBrowser.load":"Load", "CMPBrowser.load":"Load",
"CMPBrowser.lvl":"Level", "CMPBrowser.lvl":"Level",

View File

@ -2,7 +2,7 @@
"name": "compendium-browser", "name": "compendium-browser",
"title": "Compendium Browser", "title": "Compendium Browser",
"description": "A module to easily browse and filter spells as well as npcs loaded from compendie.", "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", "author": "Felix#6196",
"systems": ["dnd5e"], "systems": ["dnd5e"],
"scripts": ["./compendium-browser.js"], "scripts": ["./compendium-browser.js"],
@ -28,6 +28,6 @@
"url": "https://github.com/syl3r86/compendium-browser", "url": "https://github.com/syl3r86/compendium-browser",
"manifest": "https://raw.githubusercontent.com/syl3r86/compendium-browser/master/module.json", "manifest": "https://raw.githubusercontent.com/syl3r86/compendium-browser/master/module.json",
"download": "https://github.com/syl3r86/compendium-browser/archive/master.zip", "download": "https://github.com/syl3r86/compendium-browser/archive/master.zip",
"minimumCoreVersion": "0.5.5", "minimumCoreVersion": "0.6.2",
"compatibleCoreVersion": "0.5.5" "compatibleCoreVersion": "0.6.2"
} }

15
sub-classes.json 100644
View File

@ -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"]
}

View File

@ -0,0 +1,38 @@
<div class="feat-browser browser flexrow">
<div class="control-area">
<div class="filtercontainer" id="tagfilter">
<div class="filter" data-type="text" data-path="name">
<input class="" name="textFilter" type="text" value="" data-dtype="String" placeholder="{{localize "Name"}}"/>
</div>
<dl id="sorter">
<dt>{{localize "CMPBrowser.sortBy"}}:</dt>
<dd><select class="null" name="sortorder">
<option value="true" selected>{{localize "Name"}}</option>
<option value="false">Class</option>
</select></dd>
</dl>
<button id="reset-feat-filter">Reset Filters</button>
</div>
{{> "modules/compendium-browser/template/filter-container.html" filters=featFilters}}
</div>
<ul>
{{#each feats as |feat id|}}
<li class="feat flexrow draggable" data-entry-compendium="{{feat.compendium}}" data-entry-id="{{feat._id}}">
<div class="item-image">
<img class="" data-src="{{feat.img}}" title="{{feat.name}}" width="32" height="32"/>
</div>
<div class="item-name">
<span class="item-edit" ><a>{{feat.name}}</a></span>
</div>
<div class="feat-tags">
<span title="Class Requirement">{{feat.classRequirementString}}</span>
</div>
<div class="filter-tags">
<input type="hidden" name="class" value="{{feat.classRequirementString}}">
</div>
</li>
{{/each}}
</ul>
</div>

View File

@ -0,0 +1,37 @@
<div class="item-browser browser flexrow">
<div class="control-area">
<div class="filtercontainer" id="tagfilter">
<div class="filter" data-type="text" data-path="name">
<input class="" name="textFilter" type="text" value="" data-dtype="String" placeholder="{{localize "Name"}}"/>
</div>
<dl id="sorter">
<dt>{{localize "CMPBrowser.sortBy"}}:</dt>
<dd><select class="null" name="sortorder">
<option value="true" selected>{{localize "Name"}}</option>
<option value="false">Item Type</option>
</select></dd>
</dl>
<button id="reset-item-filter">Reset Filters</button>
</div>
{{> "modules/compendium-browser/template/filter-container.html" filters=itemFilters}}
</div>
<ul>
{{#each items as |item id|}}
<li class="item flexrow draggable" data-entry-compendium="{{item.compendium}}" data-entry-id="{{item._id}}">
<div class="item-image">
<img class="" data-src="{{item.img}}" title="{{item.name}}" width="32" height="32"/>
</div>
<div class="item-name">
<span class="item-edit" ><a>{{item.name}}</a></span>
</div>
<div class="item-tags">
<span title="Item Type">{{item.type}}</span>
</div>
<div class="filter-tags">
<input type="hidden" name="type" value="{{item.type}}">
</div>
</li>
{{/each}}
</ul>
</div>

View File

@ -20,7 +20,7 @@
{{#each npcs as |npc id|}} {{#each npcs as |npc id|}}
<li class="npc flexrow draggable" data-entry-compendium="{{npc.compendium}}" data-entry-id="{{npc._id}}"> <li class="npc flexrow draggable" data-entry-compendium="{{npc.compendium}}" data-entry-id="{{npc._id}}">
<div class="npc-image"> <div class="npc-image">
<img class="" src="{{npc.img}}" title="{{npc.name}}" width="32" height="32" /> <img class="" data-src="{{npc.img}}" title="{{npc.name}}" width="32" height="32" />
</div> </div>
<div class="npc-line"> <div class="npc-line">
<div class="npc-name"> <div class="npc-name">

View File

@ -5,6 +5,14 @@
<input data-setting="allow-spell-browser" type="checkbox" {{#if settings.allowSpellBrowser}}checked{{/if}}> <input data-setting="allow-spell-browser" type="checkbox" {{#if settings.allowSpellBrowser}}checked{{/if}}>
<h4>{{localize "CMPBrowser.allowSpellAcc"}}</h4> <h4>{{localize "CMPBrowser.allowSpellAcc"}}</h4>
</label> </label>
<label>
<input data-setting="allow-feat-browser" type="checkbox" {{#if settings.allowFeatBrowser}}checked{{/if}}>
<h4>Allow Players Access to the feat browser</h4>
</label>
<label>
<input data-setting="allow-item-browser" type="checkbox" {{#if settings.allowItemBrowser}}checked{{/if}}>
<h4>Allow Players Access to the item browser</h4>
</label>
<label> <label>
<input data-setting="allow-npc-browser" type="checkbox" {{#if settings.allowNpcBrowser}}checked{{/if}}> <input data-setting="allow-npc-browser" type="checkbox" {{#if settings.allowNpcBrowser}}checked{{/if}}>
<h4>{{localize "CMPBrowser.allowNpcAcc"}}</h4> <h4>{{localize "CMPBrowser.allowNpcAcc"}}</h4>

View File

@ -18,10 +18,10 @@
<ul> <ul>
{{#each spells as |spell id|}} {{#each spells as |spell id|}}
<li class="spell flexrow draggable" data-entry-compendium="{{spell.compendium}}" data-entry-id="{{spell._id}}"> <li class="spell flexrow draggable" data-entry-compendium="{{spell.compendium}}" data-entry-id="{{spell._id}}">
<div class="spell-image"> <div class="item-image">
<img class="" src="{{spell.img}}" title="{{spell.name}}" width="32" height="32"/> <img class="" data-src="{{spell.img}}" title="{{spell.name}}" width="32" height="32"/>
</div> </div>
<div class="spell-name"> <div class="item-name">
<span class="item-edit" ><a>{{spell.name}}</a></span> <span class="item-edit" ><a>{{spell.name}}</a></span>
</div> </div>
<div class="spell-tags"> <div class="spell-tags">

View File

@ -1,12 +1,16 @@
<div> <div class="parent">
<div class="tabs"> <div class="tabs">
{{#if showSpellBrowser}}<a class="item" data-tab="spell">{{localize "CMPBrowser.spellBrowser"}}</a>{{/if}} {{#if showSpellBrowser}}<a class="item" data-tab="spell">{{localize "CMPBrowser.spellBrowser"}}</a>{{/if}}
{{#if showFeatBrowser}}<a class="item" data-tab="feat">Feat Browser</a>{{/if}}
{{#if showItemBrowser}}<a class="item" data-tab="item">Item Browser</a>{{/if}}
{{#if showNpcBrowser}}<a class="item" data-tab="npc">{{localize "CMPBrowser.npcBrowser"}}</a>{{/if}} {{#if showNpcBrowser}}<a class="item" data-tab="npc">{{localize "CMPBrowser.npcBrowser"}}</a>{{/if}}
{{#if isGM}}<a class="item" data-tab="setting">{{localize "CMPBrowser.settings"}}</a>{{/if}} {{#if isGM}}<a class="item" data-tab="setting">{{localize "CMPBrowser.settings"}}</a>{{/if}}
</div> </div>
<div class="content"> <div class="content">
<div class="tab" data-tab="spell">{{#if showSpellBrowser}}{{> "modules/compendium-browser/template/spell-browser.html"}}{{/if}}</div> <div class="tab" data-tab="spell">{{#if showSpellBrowser}}{{> "modules/compendium-browser/template/spell-browser.html"}}{{/if}}</div>
<div class="tab" data-tab="feat">{{#if showSpellBrowser}}{{> "modules/compendium-browser/template/feat-browser.html"}}{{/if}}</div>
<div class="tab" data-tab="item">{{#if showSpellBrowser}}{{> "modules/compendium-browser/template/item-browser.html"}}{{/if}}</div>
<div class="tab" data-tab="npc">{{#if showNpcBrowser}} {{> "modules/compendium-browser/template/npc-browser.html"}}{{/if}}</div> <div class="tab" data-tab="npc">{{#if showNpcBrowser}} {{> "modules/compendium-browser/template/npc-browser.html"}}{{/if}}</div>
<div class="tab" data-tab="setting">{{#if isGM}} {{> "modules/compendium-browser/template/settings.html"}}{{/if}}</div> <div class="tab" data-tab="setting">{{#if isGM}} {{> "modules/compendium-browser/template/settings.html"}}{{/if}}</div>
</div> </div>