diff --git a/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js b/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js index 9558ff55..f3d82f75 100644 --- a/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js +++ b/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js @@ -18,23 +18,31 @@ export default function getSlotFillFilter({ slot, libraryIds }) { }] }); } else if (slot.type === 'class') { - filter.$and.push({ - $or: [{ - type: 'classLevel', - }, { - slotFillerType: 'classLevel', - }] - }); + const classLevelFilter = { + type: 'classLevel', + }; + const slotFillerFilter = { + slotFillerType: 'classLevel', + }; + + // Match variable name or tags if (slot.variableName) { - filter.variableName = slot.variableName; + classLevelFilter.variableName = slot.variableName; + slotFillerFilter.libraryTags = slot.variableName; } // Only search for levels the class needs if (slot.missingLevels && slot.missingLevels.length) { - filter.level = { $in: slot.missingLevels }; + classLevelFilter.level = { $in: slot.missingLevels }; + slotFillerFilter['cache.node.level'] = { $in: slot.missingLevels }; } else { - filter.level = { $gt: slot.level || 0 }; + classLevelFilter.level = { $gt: slot.level || 0 }; + slotFillerFilter['cache.node.level'] = { $gt: slot.level || 0 }; } + + filter.$and.push({ + $or: [classLevelFilter, slotFillerFilter] + }); } let tagsOr = []; let tagsNin = []; diff --git a/app/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js b/app/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js index deb55bc7..469cd0fc 100644 --- a/app/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js +++ b/app/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js @@ -105,6 +105,8 @@ function insertPropertyFromNode(nodeId, ancestors, order) { // Convert all references into actual nodes nodes = reifyNodeReferences(nodes); + // Refetch the root node, it might have been reified + node = nodes[0] || node; // set libraryNodeIds storeLibraryNodeReferences(nodes); diff --git a/app/imports/client/ui/creature/slots/LevelUpDialog.vue b/app/imports/client/ui/creature/slots/LevelUpDialog.vue index dcf4ce08..7b49f6f7 100644 --- a/app/imports/client/ui/creature/slots/LevelUpDialog.vue +++ b/app/imports/client/ui/creature/slots/LevelUpDialog.vue @@ -49,7 +49,7 @@ :key="libraryNode._id" :model="libraryNode" :data-id="libraryNode._id" - :class="{disabled: isDisabled(libraryNode)}" + :class="{disabled: isDisabled(libraryNode) || libraryNode._disabledBySlotFillerCondition}" > - + @@ -120,11 +121,12 @@ column align-center justify-center - class="ma-3" + class="ma-3 mt-8" > Load More @@ -247,6 +249,13 @@ export default { }); return { or, not }; }, + filledLevels() { + return LibraryNodes.find({ + _id: { $in: this.selectedNodeIds } + }).map( + node => node.level || node.cache?.node?.level || 0 + ).sort((a, b) => a - b); + } }, watch: { selectedNodeIds(selectedIds, oldSelectedIds) { @@ -257,14 +266,19 @@ export default { if (!addedId) return; const addedNode = LibraryNodes.findOne(addedId); if (!addedNode) return; - // Tick any unchecked nodes of a lower level, but only one per level + // Check which levels are already backfilled const backFilledLevels = new Set(); + const sortedIds = LibraryNodes.find({ + _id: { $in: selectedIds } + }).map(node => backFilledLevels.add(node.level || node.cache?.node?.level || 0)); + // Tick any unchecked nodes of a lower level, but only one per level this.libraryNodes.forEach(node => { if ( !selectedIds.includes(node._id) - && node.level < addedNode.level + && (node.level < addedNode.level) && !backFilledLevels.has(node.level) && !this.isDisabled(node) + && !node._disabledBySlotFillerCondition ) { selectedIds.push(node._id); backFilledLevels.add(node.level) @@ -278,12 +292,26 @@ export default { _id: { $in: selectedIds } }, { sort: { level: 1, name: 1, order: 1 } - }).map(node => node._id); + }) + .fetch() + .sort((a, b) => (a.level || a.cache?.node?.level || 0) - (b.level || b.cache?.node?.level || 0)) + .map(node => node._id); // Only update if the order changed if (!isEqual(this.selectedNodeIds, sortedIds)) { this.selectedNodeIds = sortedIds; } - } + }, + activeCount(val) { + // Still loading fillers + if (!this._subs['classFillers'].ready()) return; + // Can load more, and not showing enough active choices, so load more + if ( + this.currentLimit < this.countAll + && val < 20 + ) { + this.loadMore(); + } + }, }, methods: { loadMore() { @@ -300,12 +328,10 @@ export default { }); }, isDisabled(node) { - return node._disabledBySlotFillerCondition || - node._disabledByAlreadyAdded || - ( - node._disabledByQuantityFilled && - !this.selectedNodeIds.includes(node._id) - ) + const selected = this.selectedNodeIds.includes(node._id); + return node._disabledByAlreadyAdded + || ( node._disabledByQuantityFilled && !selected ) + || ( this.filledLevels.includes(node.level || node.cache?.node?.level || 0) && !selected ) }, }, meteor: { @@ -338,6 +364,10 @@ export default { countAll() { return this._subs['classFillers'].data('countAll'); }, + activeCount() { + if (!this.libraryNodes) return; + return this.libraryNodes.length - (this.disabledNodeCount || 0); + }, alreadyAdded() { let added = new Set(); if (!this.model.unique) return added; @@ -397,6 +427,9 @@ export default { // Mark classFillers whose condition isn't met or are too big to fit // the quantity to fill nodes.forEach(node => { + if (node.cache?.node) { + node.level = node.cache.node.level; + } if (node.slotFillerCondition) { try { let parseNode = parse(node.slotFillerCondition); @@ -430,6 +463,7 @@ export default { node._disabledByAlreadyAdded = true; } }); + nodes.sort((a, b) => a.level - b.level); this.disabledNodeCount = disabledNodeCount; return nodes; }, diff --git a/app/imports/client/ui/creature/slots/SlotFillDialog.vue b/app/imports/client/ui/creature/slots/SlotFillDialog.vue index 75af7420..197aedd0 100644 --- a/app/imports/client/ui/creature/slots/SlotFillDialog.vue +++ b/app/imports/client/ui/creature/slots/SlotFillDialog.vue @@ -64,7 +64,7 @@ :key="libraryNode._id" :model="libraryNode" :data-id="libraryNode._id" - :class="{disabled: isDisabled(libraryNode)}" + :class="{disabled: isDisabled(libraryNode) || libraryNode._disabledBySlotFillerCondition}" > - + @@ -136,16 +137,38 @@ column align-center justify-center - class="ma-3" + class="ma-3 mt-8" > Load More + - +