Moved creature variables to their own collection

Another big change to the engine, expect bugs
This commit is contained in:
Stefan Zermatten
2022-06-29 14:54:25 +02:00
parent 9dd84a83d2
commit f07f05ca2c
14 changed files with 174 additions and 70 deletions

View File

@@ -0,0 +1,21 @@
//set up the collection for creature variables
let CreatureVariables = new Mongo.Collection('creatureVariables');
// Unique index on _creatureId
if (Meteor.isServer) {
CreatureVariables._ensureIndex({ _creatureId: 1 }, { unique: true })
}
/** No schema because the structure isn't known until compute time
* Expect documents to looke like:
* {
* _id: "nE8Ngd6K4L4jSxLY2",
* _creatureId: "nE8Ngd6K4L4jSxLY2", // indexed reference to the creature
* explicitlyDefinedVariableName: {...some creatureProperty}
* implicitVariableName: {value: 10},
* undefinedVariableName: {},
* }
* Where top level fields that don't start with `_` are variables on the sheet
**/
export default CreatureVariables;

View File

@@ -1,5 +1,6 @@
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
import Creatures from '/imports/api/creature/creatures/Creatures.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js';
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js';
import LogContentSchema from '/imports/api/creature/log/LogContentSchema.js'; import LogContentSchema from '/imports/api/creature/log/LogContentSchema.js';
import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
@@ -154,7 +155,6 @@ const logRoll = new ValidatedMethod({
}).validator(), }).validator(),
run({roll, creatureId}){ run({roll, creatureId}){
const creature = Creatures.findOne(creatureId, {fields: { const creature = Creatures.findOne(creatureId, {fields: {
variables: 1,
readers: 1, readers: 1,
writers: 1, writers: 1,
owner: 1, owner: 1,
@@ -163,6 +163,7 @@ const logRoll = new ValidatedMethod({
avatarPicture: 1, avatarPicture: 1,
}}); }});
assertEditPermission(creature, this.userId); assertEditPermission(creature, this.userId);
const variables = CreatureVariables.findOne({ _creatureId: creatureId });
let logContent = [] let logContent = []
let parsedResult = undefined; let parsedResult = undefined;
try { try {
@@ -175,7 +176,7 @@ const logRoll = new ValidatedMethod({
let { let {
result: compiled, result: compiled,
context context
} = resolve('compile', parsedResult, creature.variables); } = resolve('compile', parsedResult, variables);
const compiledString = toString(compiled); const compiledString = toString(compiled);
if (!equalIgnoringWhitespace(compiledString, roll)) logContent.push({ if (!equalIgnoringWhitespace(compiledString, roll)) logContent.push({
value: roll value: roll
@@ -183,12 +184,12 @@ const logRoll = new ValidatedMethod({
logContent.push({ logContent.push({
value: compiledString value: compiledString
}); });
let {result: rolled} = resolve('roll', compiled, creature.variables, context); let {result: rolled} = resolve('roll', compiled, variables, context);
let rolledString = toString(rolled); let rolledString = toString(rolled);
if (rolledString !== compiledString) logContent.push({ if (rolledString !== compiledString) logContent.push({
value: rolledString value: rolledString
}); });
let {result} = resolve('reduce', rolled, creature.variables, context); let {result} = resolve('reduce', rolled, variables, context);
let resultString = toString(result); let resultString = toString(result);
if (resultString !== rolledString) logContent.push({ if (resultString !== rolledString) logContent.push({
value: resultString value: resultString

View File

@@ -3,6 +3,7 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js'; import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
import Creatures from '/imports/api/creature/creatures/Creatures.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js';
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import { CreatureLogSchema, insertCreatureLogWork } from '/imports/api/creature/log/CreatureLogs.js'; import { CreatureLogSchema, insertCreatureLogWork } from '/imports/api/creature/log/CreatureLogs.js';
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js'; import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
@@ -38,6 +39,12 @@ const doAction = new ValidatedMethod({
let action = CreatureProperties.findOne(actionId); let action = CreatureProperties.findOne(actionId);
// Check permissions // Check permissions
let creature = getRootCreatureAncestor(action); let creature = getRootCreatureAncestor(action);
const variables = CreatureVariables.findOne({
_creatureId: creature._id
}, {
fields: {_id: 0, _creatureId: 0},
});
creature.variables = variables;
assertEditPermission(creature, this.userId); assertEditPermission(creature, this.userId);
@@ -46,6 +53,12 @@ const doAction = new ValidatedMethod({
targetIds.forEach(targetId => { targetIds.forEach(targetId => {
let target = Creatures.findOne(targetId); let target = Creatures.findOne(targetId);
assertEditPermission(target, this.userId); assertEditPermission(target, this.userId);
const variables = CreatureVariables.findOne({
_creatureId: targetId
}, {
fields: {_id: 0, _creatureId: 0},
});
target.variables = variables;
targets.push(target); targets.push(target);
}); });

View File

@@ -2,7 +2,7 @@ import { EJSON } from 'meteor/ejson';
import createGraph from 'ngraph.graph'; import createGraph from 'ngraph.graph';
export default class CreatureComputation { export default class CreatureComputation {
constructor(properties, creature){ constructor(properties, creature, variables){
// Set up fields // Set up fields
this.originalPropsById = {}; this.originalPropsById = {};
this.propsById = {}; this.propsById = {};
@@ -12,6 +12,7 @@ export default class CreatureComputation {
this.dependencyGraph = createGraph(); this.dependencyGraph = createGraph();
this.errors = []; this.errors = [];
this.creature = creature; this.creature = creature;
this.variables = variables;
// Store properties for easy access later // Store properties for easy access later
properties.forEach(prop => { properties.forEach(prop => {

View File

@@ -4,6 +4,7 @@ import CreatureProperties,
from '/imports/api/creature/creatureProperties/CreatureProperties.js'; from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import { loadedCreatures } from '../loadCreatures.js'; import { loadedCreatures } from '../loadCreatures.js';
import Creatures from '/imports/api/creature/creatures/Creatures.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js';
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js';
import computedOnlySchemas from '/imports/api/properties/computedOnlyPropertySchemasIndex.js'; import computedOnlySchemas from '/imports/api/properties/computedOnlyPropertySchemasIndex.js';
import computedSchemas from '/imports/api/properties/computedPropertySchemasIndex.js'; import computedSchemas from '/imports/api/properties/computedPropertySchemasIndex.js';
import linkInventory from './buildComputation/linkInventory.js'; import linkInventory from './buildComputation/linkInventory.js';
@@ -33,8 +34,9 @@ import removeSchemaFields from './buildComputation/removeSchemaFields.js';
export default function buildCreatureComputation(creatureId){ export default function buildCreatureComputation(creatureId){
const creature = getCreature(creatureId); const creature = getCreature(creatureId);
const variables = getVariables(creatureId);
const properties = getProperties(creatureId); const properties = getProperties(creatureId);
const computation = buildComputationFromProps(properties, creature); const computation = buildComputationFromProps(properties, creature, variables);
return computation; return computation;
} }
@@ -45,7 +47,7 @@ function getProperties(creatureId) {
const cloneProps = EJSON.clone(props); const cloneProps = EJSON.clone(props);
return cloneProps return cloneProps
} }
console.time(`Cache miss fetching from db: ${creatureId}`) // console.time(`Cache miss on creature properties: ${creatureId}`)
const props = CreatureProperties.find({ const props = CreatureProperties.find({
'ancestors.id': creatureId, 'ancestors.id': creatureId,
'removed': {$ne: true}, 'removed': {$ne: true},
@@ -53,29 +55,41 @@ function getProperties(creatureId) {
sort: { order: 1 }, sort: { order: 1 },
fields: { icon: 0 }, fields: { icon: 0 },
}).fetch(); }).fetch();
console.timeEnd(`Cache miss fetching from db: ${creatureId}`); // console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
return props; return props;
} }
function getCreature(creatureId) { function getCreature(creatureId) {
if (loadedCreatures.has(creatureId)) { if (loadedCreatures.has(creatureId)) {
const loadedCreature = loadedCreatures.get(creatureId); const loadedCreature = loadedCreatures.get(creatureId);
const creature = loadedCreature.creatures.get(creatureId); const creature = loadedCreature.creature;
if (creature) return creature; if (creature) return creature;
} }
console.time(`Cache miss on Creature: ${creatureId}`); // console.time(`Cache miss on Creature: ${creatureId}`);
const creature = Creatures.findOne(creatureId, { const creature = Creatures.findOne(creatureId, {
denormalizedStats: 1, denormalizedStats: 1,
variables: 1, variables: 1,
dirty: 1, dirty: 1,
}); });
console.timeEnd(`Cache miss on Creature: ${creatureId}`); // console.timeEnd(`Cache miss on Creature: ${creatureId}`);
return creature; return creature;
} }
export function buildComputationFromProps(properties, creature){ function getVariables(creatureId) {
if (loadedCreatures.has(creatureId)) {
const loadedCreature = loadedCreatures.get(creatureId);
const variables = loadedCreature.variables;
if (variables) return variables;
}
// console.time(`Cache miss on variables: ${creatureId}`);
const variables = CreatureVariables.findOne({_creatureId: creatureId});
// console.timeEnd(`Cache miss on variables: ${creatureId}`);
return variables;
}
const computation = new CreatureComputation(properties, creature); export function buildComputationFromProps(properties, creature, variables){
const computation = new CreatureComputation(properties, creature, variables);
// Dependency graph where edge(a, b) means a depends on b // Dependency graph where edge(a, b) means a depends on b
// The graph includes all dependencies even of inactive properties // The graph includes all dependencies even of inactive properties
// such that any properties changing without changing their dependencies // such that any properties changing without changing their dependencies

View File

@@ -1,15 +1,14 @@
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js';
import Creatures from '/imports/api/creature/creatures/Creatures.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js';
import { EJSON } from 'meteor/ejson'; import { EJSON } from 'meteor/ejson';
import { omitBy } from 'lodash'; import { omitBy } from 'lodash';
export default function writeScope(creatureId, computation) { export default function writeScope(creatureId, computation) {
const scope = computation.scope; const scope = computation.scope;
const variables = computation.creature?.variables || {}; const variables = computation.variables || {};
let $set, $unset; delete variables._id;
if (computation.creature.dirty) { let $set, $unset;
$unset = { dirty: 1 };
}
for (const key in scope){ for (const key in scope){
// Remove large properties that aren't likely to be accessed // Remove large properties that aren't likely to be accessed
@@ -26,12 +25,14 @@ export default function writeScope(creatureId, computation) {
// Only update changed fields // Only update changed fields
if (!EJSON.equals(variables[key], scope[key])) { if (!EJSON.equals(variables[key], scope[key])) {
if (!$set) $set = {}; if (!$set) $set = {};
// Set the changed key in the creature variables /* Log detailed diffs
const diff = omitBy(variables[key], (v, k) => EJSON.equals(scope[key][k], v)); const diff = omitBy(variables[key], (v, k) => EJSON.equals(scope[key][k], v));
for (let subkey in diff) { for (let subkey in diff) {
console.log(`${key}.${subkey}: ${variables[key][subkey]} => ${scope[key][subkey]}`) console.log(`${key}.${subkey}: ${variables[key][subkey]} => ${scope[key][subkey]}`)
} }
$set[`variables.${key}`] = scope[key]; */
// Set the changed key in the creature variables
$set[key] = scope[key];
} }
} }
@@ -39,12 +40,17 @@ export default function writeScope(creatureId, computation) {
for (const key in variables) { for (const key in variables) {
if (!scope[key]) { if (!scope[key]) {
if (!$unset) $unset = {}; if (!$unset) $unset = {};
$unset[`variables.${key}`] = 1; $unset[key] = 1;
} }
} }
if ($set || $unset) { if ($set || $unset) {
const updates = Creatures.update(creatureId, { $set, $unset }); const update = {};
console.log('wrote scope: ', updates); if ($set) update.$set = $set;
if ($unset) update.$unset = $unset;
CreatureVariables.upsert({_creatureId: creatureId}, update);
}
if (computation.creature.dirty) {
Creatures.update({_creatureId: creatureId}, {$unset: { dirty: 1 }});
} }
} }

View File

@@ -30,6 +30,7 @@ function computeComputation(computation, creatureId) {
logError.location = e.stack.split('\n')[1]; logError.location = e.stack.split('\n')[1];
} }
console.error(logError); console.error(logError);
throw e;
} finally { } finally {
writeErrors(creatureId, computation.errors); writeErrors(creatureId, computation.errors);
} }

View File

@@ -1,6 +1,7 @@
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import Creatures from '/imports/api/creature/creatures/Creatures.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js';
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import computeCreature from './computeCreature'; import computeCreature from './computeCreature';
const COMPUTE_DEBOUNCE_TIME = 100; // ms const COMPUTE_DEBOUNCE_TIME = 100; // ms
@@ -68,7 +69,6 @@ class LoadedCreature {
}, },
}); });
self.creatures = new Map();
// Observe the creature itself // Observe the creature itself
self.creatureObserver = Creatures.find({ self.creatureObserver = Creatures.find({
_id: creatureId, _id: creatureId,
@@ -87,26 +87,62 @@ class LoadedCreature {
}, },
}); });
// Observe the creature's variables
self.variablesObserver = CreatureVariables.find({
_creatureId: creatureId,
}, {
fields: { _creatureId: 0},
}).observeChanges({
added(id, fields) {
fields._id = id;
self.addVariables(fields)
},
changed(id, fields) {
self.changeVariables(id, fields);
},
removed(id) {
self.removeVariables(id);
},
});
}); });
} }
stop() { stop() {
this.creatureObserver.stop();
this.propertyObserver.stop(); this.propertyObserver.stop();
this.creatureObserver.stop();
this.variablesObserver.stop();
} }
addProperty(prop) { addProperty(prop) {
this.properties.set(prop._id, prop); this.properties.set(prop._id, prop);
} }
addCreature(creature) {
this.creatures.set(creature._id, creature);
}
changeProperty(id, fields) { changeProperty(id, fields) {
this.changeMap(id, fields, this.properties); LoadedCreature.changeMap(id, fields, this.properties);
}
removeProperty(id) {
this.properties.delete(id)
}
addCreature(creature) {
this.creature = creature;
} }
changeCreature(id, fields) { changeCreature(id, fields) {
this.changeMap(id, fields, this.creatures); LoadedCreature.changeDoc(this.creature, fields);
} }
changeMap(id, fields, map) { removeCreature() {
delete this.creature;
}
addVariables(variables) {
this.variables = variables;
}
changeVariables(id, fields) {
LoadedCreature.changeDoc(this.variables, fields);
}
removeVariables() {
delete this.variables;
}
static changeMap(id, fields, map) {
const doc = map.get(id); const doc = map.get(id);
LoadedCreature.changeDoc(doc, fields);
}
static changeDoc(doc, fields) {
if (!doc) return; if (!doc) return;
for (let key in fields) { for (let key in fields) {
if (key === undefined) { if (key === undefined) {
@@ -116,10 +152,4 @@ class LoadedCreature {
} }
} }
} }
removeProperty(id) {
this.properties.delete(id)
}
removeCreature(id) {
this.creatures.delete(id)
}
} }

View File

@@ -1,5 +1,6 @@
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
import Creatures from '/imports/api/creature/creatures/Creatures.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js';
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import CreatureLogs from '/imports/api/creature/log/CreatureLogs.js'; import CreatureLogs from '/imports/api/creature/log/CreatureLogs.js';
import { assertViewPermission } from '/imports/api/creature/creatures/creaturePermissions.js'; import { assertViewPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
@@ -41,6 +42,9 @@ Meteor.publish('singleCharacter', function (creatureId) {
Creatures.find({ Creatures.find({
_id: creatureId, _id: creatureId,
}), }),
CreatureVariables.find({
_creatureId: creatureId,
}),
CreatureProperties.find({ CreatureProperties.find({
'ancestors.id': creatureId, 'ancestors.id': creatureId,
}), }),

View File

@@ -27,33 +27,33 @@
> >
<v-card class="class-details mb-2"> <v-card class="class-details mb-2">
<v-card-title <v-card-title
v-if="creature.variables.level" v-if="variables.level"
class="text-h6" class="text-h6"
> >
Level {{ creature.variables.level.value }} Level {{ variables.level.value }}
</v-card-title> </v-card-title>
<v-list two-line> <v-list two-line>
<v-list-item> <v-list-item>
<v-list-item-content> <v-list-item-content>
<v-list-item-title <v-list-item-title
v-if=" v-if="
creature.variables.milestoneLevels && variables.milestoneLevels &&
creature.variables.milestoneLevels.value variables.milestoneLevels.value
" "
> >
{{ creature.variables.milestoneLevels.value }} Milestone levels {{ variables.milestoneLevels.value }} Milestone levels
</v-list-item-title> </v-list-item-title>
<v-list-item-title <v-list-item-title
v-if=" v-if="
!(creature.variables.milestoneLevels && !(variables.milestoneLevels &&
creature.variables.milestoneLevels.value) || variables.milestoneLevels.value) ||
(creature.variables.xp && (variables.xp &&
creature.variables.xp.value) variables.xp.value)
" "
> >
{{ {{
creature.variables.xp && variables.xp &&
creature.variables.xp.value || variables.xp.value ||
0 0
}} XP }} XP
</v-list-item-title> </v-list-item-title>
@@ -103,6 +103,7 @@ import CreatureProperties from '/imports/api/creature/creatureProperties/Creatur
import { nodeArrayToTree } from '/imports/api/parenting/nodesToTree.js'; import { nodeArrayToTree } from '/imports/api/parenting/nodesToTree.js';
import BuildTreeNodeList from '/imports/ui/creature/buildTree/BuildTreeNodeList.vue'; import BuildTreeNodeList from '/imports/ui/creature/buildTree/BuildTreeNodeList.vue';
import SlotCardsToFill from '/imports/ui/creature/slots/SlotCardsToFill.vue'; import SlotCardsToFill from '/imports/ui/creature/slots/SlotCardsToFill.vue';
import CreatureVariables from '../../../../api/creature/creatures/CreatureVariables';
function traverse(tree, callback, parents = []){ function traverse(tree, callback, parents = []){
tree.forEach(node => { tree.forEach(node => {
@@ -152,6 +153,9 @@ export default {
creature(){ creature(){
return Creatures.findOne(this.creatureId); return Creatures.findOne(this.creatureId);
}, },
variables() {
return CreatureVariables.findOne({ _creatureId: this.creatureId }) || {};
},
classLevels(){ classLevels(){
return CreatureProperties.find({ return CreatureProperties.find({
'ancestors.id': this.creatureId, 'ancestors.id': this.creatureId,
@@ -217,8 +221,8 @@ export default {
elementId: 'experience-add-button', elementId: 'experience-add-button',
data: { data: {
creatureIds: [this.creatureId], creatureIds: [this.creatureId],
startAsMilestone: this.creature.variables.milestoneLevels && startAsMilestone: this.variables.milestoneLevels &&
!!this.creature.variables.milestoneLevels.value, !!this.variables.milestoneLevels.value,
}, },
}); });
}, },
@@ -228,8 +232,8 @@ export default {
elementId: 'experience-info-button', elementId: 'experience-info-button',
data: { data: {
creatureId: this.creatureId, creatureId: this.creatureId,
startAsMilestone: this.creature.variables.milestoneLevels && startAsMilestone: this.variables.milestoneLevels &&
!!this.creature.variables.milestoneLevels.value, !!this.variables.milestoneLevels.value,
}, },
}); });
}, },

View File

@@ -31,12 +31,12 @@
<v-list-item-action> <v-list-item-action>
<v-list-item-title> <v-list-item-title>
<coin-value <coin-value
:value="creature.variables && creature.variables.valueTotal && creature.variables.valueTotal.value|| 0" :value="variables && variables.valueTotal && variables.valueTotal.value|| 0"
/> />
</v-list-item-title> </v-list-item-title>
</v-list-item-action> </v-list-item-action>
</v-list-item> </v-list-item>
<v-list-item v-if="creature.variables && creature.variables.itemsAttuned && creature.variables.itemsAttuned.value"> <v-list-item v-if="variables && variables.itemsAttuned && variables.itemsAttuned.value">
<v-list-item-avatar> <v-list-item-avatar>
<v-icon>$vuetify.icons.spell</v-icon> <v-icon>$vuetify.icons.spell</v-icon>
</v-list-item-avatar> </v-list-item-avatar>
@@ -47,7 +47,7 @@
</v-list-item-content> </v-list-item-content>
<v-list-item-action> <v-list-item-action>
<v-list-item-title> <v-list-item-title>
{{ creature.variables.itemsAttuned.value }} {{ variables.itemsAttuned.value }}
</v-list-item-title> </v-list-item-title>
</v-list-item-action> </v-list-item-action>
</v-list-item> </v-list-item>
@@ -104,6 +104,7 @@ import getParentRefByTag from '/imports/api/creature/creatureProperties/methods/
import BUILT_IN_TAGS from '/imports/constants/BUILT_IN_TAGS.js'; import BUILT_IN_TAGS from '/imports/constants/BUILT_IN_TAGS.js';
import CoinValue from '/imports/ui/components/CoinValue.vue'; import CoinValue from '/imports/ui/components/CoinValue.vue';
import stripFloatingPointOddities from '/imports/api/engine/computation/utility/stripFloatingPointOddities.js'; import stripFloatingPointOddities from '/imports/api/engine/computation/utility/stripFloatingPointOddities.js';
import CreatureVariables from '../../../../api/creature/creatures/CreatureVariables';
export default { export default {
components: { components: {
@@ -138,6 +139,9 @@ export default {
color: 1, color: 1,
variables: 1, variables: 1,
}}); }});
},
variables() {
return CreatureVariables.findOne({ _creatureId: this.creatureId }) || {};
}, },
containersWithoutAncestorContainers(){ containersWithoutAncestorContainers(){
return CreatureProperties.find({ return CreatureProperties.find({
@@ -206,9 +210,9 @@ export default {
}, },
weightCarried(){ weightCarried(){
return stripFloatingPointOddities( return stripFloatingPointOddities(
this.creature.variables && this.variables &&
this.creature.variables.weightCarried && this.variables.weightCarried &&
this.creature.variables.weightCarried.value || 0 this.variables.weightCarried.value || 0
); );
}, },
}, },

View File

@@ -180,7 +180,7 @@
</template> </template>
<script lang="js"> <script lang="js">
import Creatures from '/imports/api/creature/creatures/Creatures.js'; import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import LibraryNodes from '/imports/api/library/LibraryNodes.js'; import LibraryNodes from '/imports/api/library/LibraryNodes.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue'; import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
@@ -297,9 +297,9 @@ export default {
return model; return model;
} }
}, },
creature(){ variables() {
if (!this.creatureId) return {variables: {}}; if (!this.creatureId) return {};
return Creatures.findOne(this.creatureId); return CreatureVariables.findOne({ _creatureId: this.creatureId }) || {};
}, },
currentLimit(){ currentLimit(){
return this._subs['slotFillers'].data('limit') || 50; return this._subs['slotFillers'].data('limit') || 50;
@@ -363,7 +363,7 @@ export default {
if (node.slotFillerCondition){ if (node.slotFillerCondition){
try { try {
let parseNode = parse(node.slotFillerCondition); let parseNode = parse(node.slotFillerCondition);
const {result: resultNode} = resolve('reduce', parseNode, this.creature.variables); const {result: resultNode} = resolve('reduce', parseNode, this.variables);
if (resultNode?.parseType === 'constant'){ if (resultNode?.parseType === 'constant'){
if (!resultNode.value){ if (!resultNode.value){
node._disabledBySlotFillerCondition = true; node._disabledBySlotFillerCondition = true;

View File

@@ -35,6 +35,7 @@
<script lang="js"> <script lang="js">
import CreatureLogs, { logRoll } from '/imports/api/creature/log/CreatureLogs.js'; import CreatureLogs, { logRoll } from '/imports/api/creature/log/CreatureLogs.js';
import Creatures from '/imports/api/creature/creatures/Creatures.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js';
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js'; import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
import { parse, prettifyParseError } from '/imports/parser/parser.js'; import { parse, prettifyParseError } from '/imports/parser/parser.js';
import resolve, { toString } from '/imports/parser/resolve.js'; import resolve, { toString } from '/imports/parser/resolve.js';
@@ -73,7 +74,7 @@ export default {
return; return;
} }
try { try {
let {result: compiled} = resolve('compile', result, this.creature.variables); let {result: compiled} = resolve('compile', result, this.variables);
this.inputHint = toString(compiled); this.inputHint = toString(compiled);
return; return;
} catch (e){ } catch (e){
@@ -107,6 +108,9 @@ export default {
creature(){ creature(){
return Creatures.findOne(this.creatureId) || {}; return Creatures.findOne(this.creatureId) || {};
}, },
variables(){
return CreatureVariables.findOne({_creatureId: this.creatureId}) || {};
},
editPermission(){ editPermission(){
try { try {
assertEditPermission(this.creature, Meteor.userId()); assertEditPermission(this.creature, Meteor.userId());

View File

@@ -126,7 +126,7 @@ import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import AttributeEffect from '/imports/ui/properties/components/attributes/AttributeEffect.vue'; import AttributeEffect from '/imports/ui/properties/components/attributes/AttributeEffect.vue';
import SkillProficiency from '/imports/ui/properties/components/skills/SkillProficiency.vue'; import SkillProficiency from '/imports/ui/properties/components/skills/SkillProficiency.vue';
import Creatures from '/imports/api/creature/creatures/Creatures.js'; import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js';
import getProficiencyIcon from '/imports/ui/utility/getProficiencyIcon.js'; import getProficiencyIcon from '/imports/ui/utility/getProficiencyIcon.js';
export default { export default {
@@ -185,6 +185,9 @@ export default {
}, },
}, },
meteor: { meteor: {
variables(){
return CreatureVariables.findOne({_creatureId: this.context.creatureId}) || {};
},
baseEffects(){ baseEffects(){
if (this.context.creatureId){ if (this.context.creatureId){
let creatureId = this.context.creatureId; let creatureId = this.context.creatureId;
@@ -280,10 +283,8 @@ export default {
proficiencyBonus(){ proficiencyBonus(){
let creatureId = this.context.creatureId; let creatureId = this.context.creatureId;
if (!creatureId) return; if (!creatureId) return;
let creature = Creatures.findOne(creatureId) return this.variables.proficiencyBonus &&
return creature && this.variables.proficiencyBonus.value;
creature.variables.proficiencyBonus &&
creature.variables.proficiencyBonus.value;
}, },
}, },
} }