Compare commits

...

7 Commits

Author SHA1 Message Date
Stefan Zermatten
5ad0de9eb7 Bumped version 2022-11-25 16:36:44 +02:00
Stefan Zermatten
0b377fcb71 Attributes show their children in stats cards 2022-11-25 16:27:18 +02:00
Stefan Zermatten
1f26fbf00e Iterated on stat grouping cards
adde slots, spell lists, children of slot fillers
hid properties in most places
spell slots in correct order
2022-11-25 13:25:38 +02:00
Stefan Zermatten
bb1e9624ad Fixed hit dice missing on stats tab 2022-11-25 12:14:47 +02:00
Stefan Zermatten
bda446858e Fixed spell tab btn not hiding correctly on mobile 2022-11-24 15:04:35 +02:00
Stefan Zermatten
e19e91f7e0 Fixed broken $attackRoll always returning 0 2022-11-24 14:51:05 +02:00
Stefan Zermatten
bac9fc98dd Fixed order of stats tab, unhid sneaky folders 2022-11-24 14:48:58 +02:00
19 changed files with 384 additions and 105 deletions

View File

@@ -165,7 +165,7 @@ function rollAttack(attack, scope) {
} }
scope['$attackDiceRoll'] = { value }; scope['$attackDiceRoll'] = { value };
const result = value + attack.value; const result = value + attack.value;
scope['$attackRoll'] = { result }; scope['$attackRoll'] = { value: result };
const { criticalHit, criticalMiss } = applyCrits(value, scope); const { criticalHit, criticalMiss } = applyCrits(value, scope);
return { resultPrefix, result, value, criticalHit, criticalMiss }; return { resultPrefix, result, value, criticalHit, criticalMiss };
} }

View File

@@ -4,7 +4,7 @@
:class="{ :class="{
'empty': !hasChildren, 'empty': !hasChildren,
}" }"
:data-id="`build-tree-node-${node._id}`" :data-id="`tree-node-${node._id}`"
> >
<div <div
class="layout align-center justify-start tree-node-title" class="layout align-center justify-start tree-node-title"

View File

@@ -104,8 +104,8 @@
<span>Actions</span> <span>Actions</span>
<v-icon>mdi-lightning-bolt</v-icon> <v-icon>mdi-lightning-bolt</v-icon>
</v-btn> </v-btn>
<v-btn> <v-btn v-if="!creature.settings.hideSpellsTab">
<span v-if="!creature.settings.hideSpellsTab">Spells</span> <span>Spells</span>
<v-icon>mdi-fire</v-icon> <v-icon>mdi-fire</v-icon>
</v-btn> </v-btn>
<v-btn> <v-btn>

View File

@@ -58,8 +58,19 @@ export default {
}}, }},
meteor: { meteor: {
actions() { actions() {
return CreatureProperties.find({ const folderIds = CreatureProperties.find({
'ancestors.id': this.creatureId, 'ancestors.id': this.creatureId,
type: 'folder',
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: folderIds,
},
type: 'action', type: 'action',
actionType: { $ne: 'event' }, actionType: { $ne: 'event' },
removed: { $ne: true }, removed: { $ne: true },

View File

@@ -86,7 +86,7 @@
<build-tree-node-list <build-tree-node-list
:children="slotBuildTree" :children="slotBuildTree"
class="mx-2" class="mx-2"
@selected="_id => propertyClicked({_id, prefix: 'build-tree-node-'})" @selected="_id => propertyClicked({_id, prefix: 'tree-node-'})"
/> />
</v-card> </v-card>
</v-col> </v-col>

View File

@@ -56,8 +56,19 @@ export default {
}, },
meteor: { meteor: {
features() { features() {
return CreatureProperties.find({ const folderIds = CreatureProperties.find({
'ancestors.id': this.creatureId, 'ancestors.id': this.creatureId,
type: 'folder',
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: folderIds,
},
type: 'feature', type: 'feature',
removed: { $ne: true }, removed: { $ne: true },
inactive: { $ne: true }, inactive: { $ne: true },

View File

@@ -141,9 +141,21 @@ export default {
}; };
}, },
meteor: { meteor: {
containers() { folderIds() {
return CreatureProperties.find({ return CreatureProperties.find({
'ancestors.id': this.creatureId, 'ancestors.id': this.creatureId,
type: 'folder',
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
},
containers() {
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: this.folderIds,
},
type: 'container', type: 'container',
removed: { $ne: true }, removed: { $ne: true },
inactive: { $ne: true }, inactive: { $ne: true },
@@ -166,7 +178,7 @@ export default {
return CreatureProperties.find({ return CreatureProperties.find({
'ancestors.id': { 'ancestors.id': {
$eq: this.creatureId, $eq: this.creatureId,
$nin: this.containerIds $nin: [...this.containerIds, ...this.folderIds],
}, },
type: 'container', type: 'container',
removed: { $ne: true }, removed: { $ne: true },
@@ -179,7 +191,7 @@ export default {
return CreatureProperties.find({ return CreatureProperties.find({
'ancestors.id': { 'ancestors.id': {
$eq: this.creatureId, $eq: this.creatureId,
$nin: this.containerIds $nin: [...this.containerIds, ...this.folderIds],
}, },
type: 'item', type: 'item',
equipped: { $ne: true }, equipped: { $ne: true },

View File

@@ -60,8 +60,19 @@ export default {
}, },
meteor: { meteor: {
notes(){ notes(){
return CreatureProperties.find({ const folderIds = CreatureProperties.find({
'ancestors.id': this.creatureId, 'ancestors.id': this.creatureId,
type: 'folder',
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: folderIds,
},
type: 'note', type: 'note',
removed: {$ne: true}, removed: {$ne: true},
inactive: {$ne: true}, inactive: {$ne: true},

View File

@@ -10,7 +10,7 @@
@remove="softRemove" @remove="softRemove"
/> />
<div <div
v-if="spellSlots && spellSlots.length || hasSpells" v-if="hasSpellSlots || hasSpells"
class="spell-slots" class="spell-slots"
> >
<spell-slot-card <spell-slot-card
@@ -77,9 +77,32 @@ export default {
} }
}, },
meteor: { meteor: {
spellSlots() { folderIds() {
return CreatureProperties.find({ return CreatureProperties.find({
'ancestors.id': this.creatureId, 'ancestors.id': this.creatureId,
type: 'folder',
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
},
hasSpellSlots() {
return !!CreatureProperties.findOne({
'ancestors.id': this.creatureId,
inactive: { $ne: true },
removed: { $ne: true },
overridden: { $ne: true },
level: { $ne: 0 },
type: 'attribute',
attributeType: 'spellSlot',
});
},
spellSlots() {
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: this.folderIds,
},
inactive: { $ne: true }, inactive: { $ne: true },
removed: { $ne: true }, removed: { $ne: true },
overridden: { $ne: true }, overridden: { $ne: true },
@@ -89,11 +112,16 @@ export default {
{ hideWhenTotalZero: true, total: 0 }, { hideWhenTotalZero: true, total: 0 },
{ hideWhenValueZero: true, value: 0 }, { hideWhenValueZero: true, value: 0 },
], ],
}, {
sort: { order: 1 }
}); });
}, },
spellLists() { spellLists() {
return CreatureProperties.find({ return CreatureProperties.find({
'ancestors.id': this.creatureId, 'ancestors.id': {
$eq: this.creatureId,
$nin: this.folderIds,
},
type: 'spellList', type: 'spellList',
removed: { $ne: true }, removed: { $ne: true },
inactive: { $ne: true }, inactive: { $ne: true },
@@ -113,7 +141,7 @@ export default {
return CreatureProperties.find({ return CreatureProperties.find({
'ancestors.id': { 'ancestors.id': {
$eq: this.creatureId, $eq: this.creatureId,
$nin: this.spellListIds, $nin: [...this.spellListIds, ...this.folderIds],
}, },
type: 'spell', type: 'spell',
removed: { $ne: true }, removed: { $ne: true },
@@ -130,7 +158,7 @@ export default {
return CreatureProperties.find({ return CreatureProperties.find({
'ancestors.id': { 'ancestors.id': {
$eq: this.creatureId, $eq: this.creatureId,
$nin: this.spellListIds, $nin: [...this.spellListIds, ...this.folderIds],
}, },
type: 'spellList', type: 'spellList',
removed: { $ne: true }, removed: { $ne: true },

View File

@@ -161,13 +161,13 @@
</div> </div>
<div <div
v-if="properties.hitDice && properties.hitDice.length" v-if="properties.attribute.hitDice && properties.attribute.hitDice.length"
class="hit-dice" class="hit-dice"
> >
<v-card> <v-card>
<v-list> <v-list>
<v-subheader>Hit Dice</v-subheader> <v-subheader>Hit Dice</v-subheader>
<template v-for="(hitDie, index) in hitDice"> <template v-for="(hitDie, index) in properties.attribute.hitDice">
<v-divider <v-divider
v-if="index !== 0" v-if="index !== 0"
:key="hitDie._id + 'divider'" :key="hitDie._id + 'divider'"
@@ -428,7 +428,7 @@ const propertyHandlers = {
let skipChildren; let skipChildren;
let propPath = null; let propPath = null;
if (prop.hideStatsGroup) { if (prop.hideStatsGroup) {
return { skipChildren: true} skipChildren = true;
} }
if (prop.tab === 'stats') { if (prop.tab === 'stats') {
propPath = ['folder', prop.location] propPath = ['folder', prop.location]
@@ -546,7 +546,7 @@ export default {
if (creature.settings.hideUnusedStats) { if (creature.settings.hideUnusedStats) {
filter.hide = { $ne: true }; filter.hide = { $ne: true };
} }
const allProps = CreatureProperties.find(filter, { sort: { order: 1 } }); const allProps = CreatureProperties.find(filter, { sort: { order: -1 } });
const forest = nodeArrayToTree(allProps); const forest = nodeArrayToTree(allProps);
const properties = { folder: {}, attribute: {}, skill: {} }; const properties = { folder: {}, attribute: {}, skill: {} };
walkDown(forest, node => { walkDown(forest, node => {

View File

@@ -8,7 +8,7 @@
class="slot-card d-flex flex-column" class="slot-card d-flex flex-column"
@mouseover="hover = true" @mouseover="hover = true"
@mouseleave="hover = false" @mouseleave="hover = false"
@click="$emit('click')" @click="fillSlot"
> >
<card-highlight <card-highlight
:active="hover" :active="hover"
@@ -28,7 +28,7 @@
<v-btn <v-btn
icon icon
color="accent" color="accent"
@click.stop="$emit('ignore')" @click.stop="ignoreProp"
> >
<v-icon>mdi-close</v-icon> <v-icon>mdi-close</v-icon>
</v-btn> </v-btn>
@@ -39,6 +39,9 @@
<script lang="js"> <script lang="js">
import CardHighlight from '/imports/client/ui/components/CardHighlight.vue'; import CardHighlight from '/imports/client/ui/components/CardHighlight.vue';
import PropertyDescription from '/imports/client/ui/properties/viewers/shared/PropertyDescription.vue'; import PropertyDescription from '/imports/client/ui/properties/viewers/shared/PropertyDescription.vue';
import insertPropertyFromLibraryNode from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js';
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue.js';
import updateCreatureProperty from '/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js';
export default { export default {
components: { components: {
@@ -51,6 +54,9 @@ export default {
isDark: false, isDark: false,
}, },
}, },
context: {
default: {},
},
}, },
props: { props: {
model: { model: {
@@ -72,5 +78,45 @@ export default {
} }
} }
}, },
methods: {
fillSlot() {
const slotId = this.model._id;
this.$store.commit('pushDialogStack', {
component: 'slot-fill-dialog',
elementId: `slot-card-${slotId}`,
data: {
slotId,
creatureId: this.context.creatureId,
},
callback(nodeIds){
if (!nodeIds || !nodeIds.length) return;
insertPropertyFromLibraryNode.call({
nodeIds,
parentRef: {
'id': slotId,
'collection': 'creatureProperties',
},
}, error => {
if (error){
console.error(error);
snackbar({text: error.reason || error.message || error.toString()});
}
});
}
});
},
ignoreProp(){
updateCreatureProperty.call({
_id: this.model._id,
path: ['ignored'],
value: true
}, error => {
if (error){
console.error(error);
snackbar({text: error.reason || error.message || error.toString()});
}
});
},
}
} }
</script> </script>

View File

@@ -1,5 +1,8 @@
<template> <template>
<column-layout wide-columns class="slots-to-fill"> <column-layout
wide-columns
class="slots-to-fill"
>
<v-fade-transition <v-fade-transition
group group
leave-absolute leave-absolute
@@ -39,7 +42,6 @@ import SlotCard from '/imports/client/ui/creature/slots/SlotCard.vue';
import PointBuyCard from '/imports/client/ui/properties/components/pointBuy/PointBuyCard.vue'; import PointBuyCard from '/imports/client/ui/properties/components/pointBuy/PointBuyCard.vue';
import ColumnLayout from '/imports/client/ui/components/ColumnLayout.vue'; import ColumnLayout from '/imports/client/ui/components/ColumnLayout.vue';
import updateCreatureProperty from '/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js'; import updateCreatureProperty from '/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js';
import insertPropertyFromLibraryNode from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js';
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue.js'; import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue.js';
export default { export default {
@@ -64,31 +66,6 @@ export default {
} }
}); });
}, },
fillSlot(slotId){
this.$store.commit('pushDialogStack', {
component: 'slot-fill-dialog',
elementId: `slot-card-${slotId}`,
data: {
slotId,
creatureId: this.context.creatureId,
},
callback(nodeIds){
if (!nodeIds || !nodeIds.length) return;
insertPropertyFromLibraryNode.call({
nodeIds,
parentRef: {
'id': slotId,
'collection': 'creatureProperties',
},
}, error => {
if (error){
console.error(error);
snackbar({text: error.reason || error.message || error.toString()});
}
});
}
});
},
editPointBuy(_id){ editPointBuy(_id){
this.$store.commit('pushDialogStack', { this.$store.commit('pushDialogStack', {
component: 'creature-property-dialog', component: 'creature-property-dialog',
@@ -101,10 +78,21 @@ export default {
}, },
}, },
meteor: { meteor: {
slots(){ slots() {
return CreatureProperties.find({ const folderIds = CreatureProperties.find({
type: 'propertySlot',
'ancestors.id': this.context.creatureId, 'ancestors.id': this.context.creatureId,
type: 'folder',
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
return CreatureProperties.find({
'ancestors.id': {
$eq: this.context.creatureId,
$nin: folderIds,
},
type: 'propertySlot',
ignored: { $ne: true }, ignored: { $ne: true },
$and: [ $and: [
{ {

View File

@@ -15,7 +15,8 @@
:model="prop" :model="prop"
:data-id="prop._id" :data-id="prop._id"
@click="$emit('click-property', {_id: prop._id})" @click="$emit('click-property', {_id: prop._id})"
@sub-click="_id => $emit('sub-click', _id)" @click-property="e => $emit('click-property', e)"
@sub-click="e => $emit('sub-click', e)"
@remove="$emit('remove', prop._id)" @remove="$emit('remove', prop._id)"
/> />
</v-card> </v-card>
@@ -27,15 +28,15 @@ import CreatureProperties from '/imports/api/creature/creatureProperties/Creatur
import propComponents from '/imports/client/ui/properties/components/folders/propertyComponentIndex.js'; import propComponents from '/imports/client/ui/properties/components/folders/propertyComponentIndex.js';
export default { export default {
components: {
...propComponents,
},
props: { props: {
model: { model: {
type: Object, type: Object,
required: true, required: true,
} }
}, },
beforeCreate() {
Object.assign(this.$options.components, propComponents);
},
meteor: { meteor: {
properties() { properties() {
const props = []; const props = [];
@@ -50,6 +51,7 @@ export default {
deactivatedByAncestor: { $ne: true }, deactivatedByAncestor: { $ne: true },
}, },
{ {
type: { $ne: 'toggle' },
inactive: { $ne: true } inactive: { $ne: true }
}, },
], ],
@@ -60,7 +62,7 @@ export default {
}, { }, {
sort: { order: 1 }, sort: { order: 1 },
}).forEach(prop => { }).forEach(prop => {
if (this.$options.components[prop.type]) { if (propComponents[prop.type]) {
props.push(prop); props.push(prop);
} }
}); });

View File

@@ -1,44 +1,55 @@
<template> <template>
<div class="attribute"> <div>
<ability-list-tile <div
v-if="model.attributeType === 'ability'" class="attribute"
:data-id="dataId"
>
<ability-list-tile
v-if="model.attributeType === 'ability'"
:model="model"
@click="$emit('click')"
/>
<hit-dice-list-tile
v-else-if="model.attributeType === 'hitDice'"
:model="model"
@click="$emit('click')"
@change="({ type, value }) => damageProperty({type, value: -value})"
/>
<health-bar
v-else-if="model.attributeType === 'healthBar'"
:model="model"
@change="damageProperty"
@click="$emit('click')"
/>
<spell-slot-list-tile
v-else-if="model.attributeType === 'spellSlot'"
:model="model"
@click="$emit('click')"
/>
<resource-card-content
v-else-if="model.attributeType === 'resource'"
:model="model"
@click="$emit('click')"
@change="({ type, value }) => damageProperty({type, value: -value})"
@mouseover="hover = true"
@mouseleave="hover = false"
/>
<attribute-card-content
v-else-if="model.attributeType !== 'utility'"
class="pointer"
:model="model"
@click="$emit('click')"
@mouseover="hover = true"
@mouseleave="hover = false"
/>
<card-highlight :active="hover" />
</div>
<folder-group-children
:model="model" :model="model"
@click="$emit('click')" @click-property="e => $emit('click-property', e)"
@sub-click="e => $emit('sub-click', e)"
@remove="e => $emit('remove', e)"
/> />
<hit-dice-list-tile
v-else-if="model.attributeType === 'hitDice'"
:model="model"
@click="$emit('click')"
@change="({ type, value }) => damageProperty({type, value: -value})"
/>
<health-bar
v-else-if="model.attributeType === 'healthBar'"
:model="model"
@change="damageProperty"
@click="$emit('click')"
/>
<spell-slot-list-tile
v-else-if="model.attributeType === 'spellSlot'"
:model="model"
@click="$emit('click')"
/>
<resource-card-content
v-else-if="model.attributeType === 'resource'"
:model="model"
@click="$emit('click')"
@change="({ type, value }) => damageProperty({type, value: -value})"
@mouseover="hover = true"
@mouseleave="hover = false"
/>
<attribute-card-content
v-else-if="model.attributeType !== 'utility'"
class="pointer"
:model="model"
@click="$emit('click')"
@mouseover="hover = true"
@mouseleave="hover = false"
/>
<card-highlight :active="hover" />
</div> </div>
</template> </template>
@@ -50,6 +61,7 @@ import SpellSlotListTile from '/imports/client/ui/properties/components/attribut
import ResourceCardContent from '/imports/client/ui/properties/components/attributes/ResourceCardContent.vue'; import ResourceCardContent from '/imports/client/ui/properties/components/attributes/ResourceCardContent.vue';
import AttributeCardContent from '/imports/client/ui/properties/components/attributes/AttributeCardContent.vue'; import AttributeCardContent from '/imports/client/ui/properties/components/attributes/AttributeCardContent.vue';
import CardHighlight from '/imports/client/ui/components/CardHighlight.vue'; import CardHighlight from '/imports/client/ui/components/CardHighlight.vue';
import FolderGroupChildren from '/imports/client/ui/properties/components/folders/folderGroupComponents/FolderGroupChildren.vue';
import damageProperty from '/imports/api/creature/creatureProperties/methods/damageProperty.js'; import damageProperty from '/imports/api/creature/creatureProperties/methods/damageProperty.js';
@@ -62,12 +74,17 @@ export default {
ResourceCardContent, ResourceCardContent,
AttributeCardContent, AttributeCardContent,
CardHighlight, CardHighlight,
FolderGroupChildren,
}, },
props: { props: {
model: { model: {
type: Object, type: Object,
required: true, required: true,
}, },
dataId: {
type: String,
required: true,
},
}, },
data() { data() {
return { return {
@@ -81,6 +98,10 @@ export default {
value: change.value value: change.value
}); });
}, },
log({_id}) {
console.log(...arguments)
this.$emit('click-property', { _id });
}
} }
} }
</script> </script>

View File

@@ -0,0 +1,66 @@
<template>
<div
v-if="properties && properties.length"
>
<component
:is="prop.type"
v-for="prop in properties"
:key="prop._id"
:model="prop"
:data-id="prop._id"
@click="$emit('click-property', {_id: prop._id})"
@click-property="(e) => $emit('click-property', e)"
@sub-click="(e) => $emit('sub-click', e)"
@remove="$emit('remove', prop._id)"
/>
</div>
</template>
<script lang="js">
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import propComponents from '/imports/client/ui/properties/components/folders/propertyComponentIndex.js';
export default {
props: {
model: {
type: Object,
required: true,
}
},
beforeCreate() {
Object.assign(this.$options.components, propComponents);
},
meteor: {
properties() {
const props = [];
CreatureProperties.find({
'parent.id': this.model._id,
removed: { $ne: true },
overridden: { $ne: true },
$or: [
{
type: 'toggle',
showUI: true,
deactivatedByAncestor: { $ne: true },
},
{
type: { $ne: 'toggle' },
inactive: { $ne: true },
},
],
$nor: [
{ hideWhenTotalZero: true, total: 0 },
{ hideWhenValueZero: true, value: 0 },
],
}, {
sort: { order: 1 },
}).forEach(prop => {
if (propComponents[prop.type]) {
props.push(prop);
}
});
return props;
},
},
}
</script>

View File

@@ -0,0 +1,82 @@
<template>
<build-tree-node-list
:children="slotBuildTree"
class="mx-2"
@selected="_id => $emit('sub-click', _id)"
/>
</template>
<script lang="js">
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import { nodeArrayToTree } from '/imports/api/parenting/nodesToTree.js';
import BuildTreeNodeList from '/imports/client/ui/creature/buildTree/BuildTreeNodeList.vue';
function traverse(tree, callback, parents = []){
tree.forEach(node => {
callback(node, parents);
traverse(node.children, callback, [...parents, node]);
});
}
export default {
components: {
BuildTreeNodeList,
},
props: {
model: {
type: Object,
required: true,
},
},
meteor: {
slotBuildTree() {
const slots = CreatureProperties.find({
$and: [ {
$or: [
{ 'ancestors.id': this.model._id, },
{ '_id': this.model._id, },
],
}, {
$or:
[
{ 'slotCondition.value': { $nin: [false, 0, ''] } },
{ 'slotCondition.value': { $exists: false } },
{ 'slotCondition': { $exists: false } },
],
} ],
type: { $in: ['propertySlot', 'pointBuy'] },
removed: { $ne: true },
inactive: { $ne: true },
}, {
sort: { order: 1 }
});
const slotIds = slots.map(s => s._id);
const slotChildren = CreatureProperties.find({
'parent.id': { $in: slotIds },
removed: { $ne: true },
}, {
sort: { order: 1 },
});
const tree = nodeArrayToTree([
...slots.fetch(),
...slotChildren.fetch()
]);
traverse(tree, (child, parents) => {
const model = child.node;
const isSlotWithSpace = model.type === 'propertySlot' && (
model.spaceLeft > 0 ||
!model.quantityExpected ||
model.quantityExpected.value === 0
);
if (isSlotWithSpace) {
model._canFill = true;
parents.forEach(node => {
node.node._descendantCanFill = true;
});
}
});
return tree;
},
}
}
</script>

View File

@@ -17,16 +17,17 @@ import item from '/imports/client/ui/properties/components/inventory/ItemListTil
import note from '/imports/client/ui/properties/components/persona/NoteCard.vue'; import note from '/imports/client/ui/properties/components/persona/NoteCard.vue';
//import pointBuy from ''; //import pointBuy from '';
//import proficiency from ''; //import proficiency from '';
//import propertySlot from ''; import propertySlot from '/imports/client/ui/properties/components/folders/folderGroupComponents/SlotBuildTree.vue';
//import reference from ''; //import reference from '';
//import roll from ''; //import roll from '';
//import savingThrow from ''; //import savingThrow from '';
import skill from '/imports/client/ui/properties/components/skills/SkillListTile.vue'; import skill from '/imports/client/ui/properties/components/skills/SkillListTile.vue';
//import slotFiller from ''; //import slotFiller from '';
//import spellList from ''; import spellList from '/imports/client/ui/properties/components/spells/SpellListCard.vue';
//import spell from ''; import spell from '/imports/client/ui/properties/components/spells/SpellListTile.vue';
import toggle from '/imports/client/ui/properties/components/toggles/ToggleCard.vue'; import toggle from '/imports/client/ui/properties/components/toggles/ToggleCard.vue';
//import trigger from ''; //import trigger from '';
import FolderGroupChildren from '/imports/client/ui/properties/components/folders/folderGroupComponents/FolderGroupChildren.vue';
export default { export default {
action, action,
@@ -43,19 +44,19 @@ export default {
//damageMultiplier, //damageMultiplier,
//effect, //effect,
feature, feature,
//folder, // folder // Like actions, we don't show sub-folders
item, item,
note, note,
//pointBuy, //pointBuy,
//proficiency, //proficiency,
//propertySlot, propertySlot,
//reference, //reference,
//roll, //roll,
//savingThrow, //savingThrow,
skill, skill,
//slotFiller, slotFiller: FolderGroupChildren,
//spellList, spellList,
//spell, spell,
toggle, toggle,
//trigger, //trigger,
}; };

View File

@@ -35,7 +35,7 @@
<v-expand-transition> <v-expand-transition>
<div v-if="model.groupStats"> <div v-if="model.groupStats">
<smart-switch <smart-switch
label="Hide children from stats tab" label="Hide children from their default locations"
:value="model.hideStatsGroup" :value="model.hideStatsGroup"
:error-messages="errors.hideStatsGroup" :error-messages="errors.hideStatsGroup"
@change="change('hideStatsGroup', ...arguments)" @change="change('hideStatsGroup', ...arguments)"

View File

@@ -1,6 +1,6 @@
{ {
"name": "dicecloud", "name": "dicecloud",
"version": "2.0.45", "version": "2.0.46",
"description": "Unofficial Online Realtime D&D 5e App", "description": "Unofficial Online Realtime D&D 5e App",
"license": "GPL-3.0", "license": "GPL-3.0",
"repository": { "repository": {