Moved creature variables to their own collection
Another big change to the engine, expect bugs
This commit is contained in:
21
app/imports/api/creature/creatures/CreatureVariables.js
Normal file
21
app/imports/api/creature/creatures/CreatureVariables.js
Normal 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;
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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 => {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 }});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user