Got tests running on single property character

This commit is contained in:
Stefan Zermatten
2021-09-15 15:15:18 +02:00
parent 856fc41429
commit dfd7ad4af5
24 changed files with 277 additions and 119 deletions

View File

@@ -1,7 +1,7 @@
import computeStat from '/imports/api/creature/computation/engine/computeStat.js';
import computeProficiency from '/imports/api/creature/computation/engine/computeProficiency.js';
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
import stripFloatingPointOddities from '/imports/ui/utility/stripFloatingPointOddities.js';
import stripFloatingPointOddities from '/imports/api/creature/computation/newEngine/utility/stripFloatingPointOddities.js';
import { union } from 'lodash';
export default function combineStat(stat, aggregator, memo){

View File

@@ -0,0 +1,36 @@
import { cloneDeep } from 'lodash';
import createGraph from 'ngraph.graph';
export default class CreatureComputation {
constructor(properties){
// Set up fields
this.originalPropsById = {};
this.propsById = {};
this.propsByType = {};
this.propsByVariableName = {};
this.props = properties;
this.dependencyGraph = createGraph();
// Store properties for easy access later
properties.forEach(prop => {
// Store a copy of the unmodified prop
this.originalPropsById[prop._id] = cloneDeep(prop);
// Store by id
this.propsById[prop._id] = prop;
// Store by type
this.propsByType[prop.type] ?
this.propsByType[prop.type].push(prop) :
this.propsByType[prop.type] = [prop];
// Store by variableName
this.propsByVariableName[prop.variableName] ?
this.propsByVariableName[prop.variableName].push(prop) :
this.propsByVariableName[prop.variableName]= [prop];
// Store the prop in the dependency graph
this.dependencyGraph.addNode(prop._id, prop);
});
}
}

View File

@@ -9,7 +9,7 @@ export default function linkCalculationDependencies(dependencyGraph, prop, {prop
// ancestors: {} //this gets added if there are resolved ancestors
};
// Traverse the parsed calculation looking for variable names
calcObj._parsedCalculation.travese(node => {
calcObj._parsedCalculation.traverse(node => {
// Skip nodes that aren't symbols or accessors
if (!(node instanceof SymbolNode || node instanceof AccessorNode)) return;
// Link ancestor references as direct property dependencies

View File

@@ -27,6 +27,8 @@ export default function linkInventory(forest, dependencyGraph){
}
function handleProp(prop, containerStack, dependencyGraph){
// Skip props that aren't part of the inventory
if (prop.type !== 'inventory' && prop.type !== 'container') return;
// Determine if this property is carried, items are carried by default
let carried = prop.type === 'container' ? prop.carried : true;

View File

@@ -13,7 +13,7 @@ const linkDependenciesByType = {
}
export default function linkTypeDependencies(dependencyGraph, prop){
linkDependenciesByType[prop.type]?.(prop);
linkDependenciesByType[prop.type]?.(dependencyGraph, prop);
}
function linkClassLevel(dependencyGraph, prop){

View File

@@ -1,20 +1,54 @@
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX.js';
import { prettifyParseError, parse } from '/imports/parser/parser.js';
import ErrorNode from '/imports/parser/parseTree/ErrorNode.js';
import applyFnToKey from '/imports/api/creature/computation/newEngine/utility/applyFnToKey.js';
import { get } from 'lodash';
export default function parseCalculationFields(prop, schemas){
parseInlineCalculationFields(prop, schemas);
parseDirectCalculationFields(prop, schemas);
}
function parseInlineCalculationFields(prop, schemas){
// For each key in the schema
schemas[prop.type]._schemaKeys.forEach( key => {
// That ends in .inlineCalculations
if (key.slice(-19) === '.inlineCalculations'){
const inlineCalcKey = key.slice(0, -19);
applyFnToKey(prop, inlineCalcKey, (prop, key) => {
const inlineCalcObj = get(prop, key);
if (!inlineCalcObj) return;
// Store a reference to all the inline calculations
prop._computationDetails.inlineCalculations.push(inlineCalcObj);
// Extract the calculations and store them on the property
let string = inlineCalcObj.text;
inlineCalcObj.inlineCalculations = [];
let matches = string.matchAll(INLINE_CALCULATION_REGEX);
for (let match of matches){
let calculation = match[1];
inlineCalcObj.inlineCalculations.push({
calculation,
});
}
});
}
});
}
function parseDirectCalculationFields(prop, schemas){
// For each key in the schema
schemas[prop.type]._schemaKeys.forEach( key => {
// that ends in '.calculation'
if (key.slice(-12) === '.calculation'){
const calcKey = key.sclice(0, -12);
const calcKey = key.slice(0, -12);
// Determine the level the calculation should compute down to
let parseLevel = schemas[prop.type].getDefinition(calcKey).parseLevel;
let parseLevel = schemas[prop.type].getDefinition(calcKey).parseLevel || 'reduce';
// For all fields matching they keys
// supports `keys.$.with.$.arrays`
applyFnToKey(prop, calcKey, calcObj => {
applyFnToKey(prop, calcKey, (prop, key) => {
const calcObj = get(prop, key);
if (!calcObj) return;
// Store a reference to all the calculations
prop._computationDetails.calculations.push(calcObj);
// Store the level to compute down to later
@@ -23,14 +57,7 @@ export default function parseCalculationFields(prop, schemas){
parseCalculation(calcObj);
});
// Or that ends in .inlineCalculations
} else if (key.slice(-19) === '.inlineCalculations'){
const inlineCalcKey = key.sclice(0, -19);
applyFnToKey(prop, inlineCalcKey, inlineCalcObj => {
// Store a reference to all the inline calculations
prop._computationDetails.inlineCalculations.push(inlineCalcObj);
});
}
});
}

View File

@@ -0,0 +1,13 @@
import applyFnToKey from '../utility/applyFnToKey.js';
import { unset } from 'lodash';
export default function removeSchemaFields(schemas, prop){
schemas.forEach(schema => {
schema._schemaKeys.forEach(key => {
// Skip object keys
if (schema.getQuickTypeForKey(key) === 'object') return;
// Unset other computed only keys
applyFnToKey(prop, key, unset)
});
});
}

View File

@@ -4,17 +4,16 @@ import CreatureProperties,
from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import computedOnlySchemas from '/imports/api/properties/computedOnlyPropertySchemasIndex.js';
import computedSchemas from '/imports/api/properties/computedPropertySchemasIndex.js';
import applyFnToKey from '/imports/api/creature/computation/newEngine/utility/applyFnToKey.js';
import { cloneDeep, unset } from 'lodash';
import createGraph from 'ngraph.graph';
import linkInventory from '/imports/api/creature/computation/newEngine/buildComputation/linkInventory.js';
import walkDown from '/imports/api/creature/computation/newEngine/utility/walkdown.js';
import parseCalculationFields from '/imports/api/creature/computation/newEngine/buildComputation/parseCalculationFields.js';
import computeInactiveStatus from '/imports/api/creature/computation/newEngine/buildComputation/computeInactiveStatus.js';
import computeToggleDependencies from '/imports/api/creature/computation/newEngine/buildComputation/computeToggleDependencies.js';
import linkCalculationDependencies from '/imports/api/creature/computation/newEngine/buildComputation/linkCalculationDependencies.js';
import linkTypeDependencies from '/imports/api/creature/computation/newEngine/buildComputation/linkTypeDependencies.js';
import computeSlotQuantityFilled from '/imports/api/creature/computation/newEngine/buildComputation/computeSlotQuantityFilled.js';
import linkInventory from './buildComputation/linkInventory.js';
import walkDown from './utility/walkdown.js';
import parseCalculationFields from './buildComputation/parseCalculationFields.js';
import computeInactiveStatus from './buildComputation/computeInactiveStatus.js';
import computeToggleDependencies from './buildComputation/computeToggleDependencies.js';
import linkCalculationDependencies from './buildComputation/linkCalculationDependencies.js';
import linkTypeDependencies from './buildComputation/linkTypeDependencies.js';
import computeSlotQuantityFilled from './buildComputation/computeSlotQuantityFilled.js';
import CreatureComputation from './buildComputation/CreatureComputation.js';
import removeSchemaFields from './buildComputation/removeSchemaFields.js';
/**
* Store index of properties
@@ -50,50 +49,32 @@ function getProperties(creatureId){
}
export function buildComputationFromProps(properties){
const computation = new CreatureComputation(properties);
// Dependency graph where edge(a, b) means a depends on b
// The graph includes all dependencies even of inactive properties
// such that any properties changing without changing their dependencies
// can limit the recompute to connected parts of the graph
// Each node's data represents a prop or a virtual prop like a variable
// Each link's data is a string representing the link type
const dependencyGraph = createGraph();
const computation = {
originalPropsById: {},
propsById: {},
propsByType: {},
propsByVariableName: {},
props: properties,
dependencyGraph,
};
const dependencyGraph = computation.dependencyGraph;
// Process the properties one by one
properties.forEach(prop => {
// Store the prop in the memo by type, variableName and id
storePropInMemo(prop, computation)
// Store the prop in the dependency graph
dependencyGraph.addNode(prop._id, prop);
// Remove old computed only fields
computedOnlySchemas[prop.type]._schemaKeys.forEach(key =>
applyFnToKey(prop, key, unset)
);
// Remove old denormalised fields
denormSchema._schemaKeys.forEach(key =>
applyFnToKey(prop, key, unset)
);
let computedSchema = computedOnlySchemas[prop.type];
removeSchemaFields([computedSchema, denormSchema], prop);
// Add a place to store all the computation details
prop._computationDetails = {
calculations: [],
inlineCalculations: [],
toggleAncestors: [],
};
// Parse all the calculations
parseCalculationFields(prop, computedSchemas);
});
// Get all the properties as trees based on their ancestors
@@ -108,7 +89,7 @@ export function buildComputationFromProps(properties){
// Link the inventory dependencies
linkInventory(forest, dependencyGraph);
// Graph functions that rely on the props being stored first
// Link functions that require the above to be complete
properties.forEach(prop => {
linkTypeDependencies(dependencyGraph, prop, computation);
linkCalculationDependencies(dependencyGraph, prop, computation);
@@ -116,19 +97,3 @@ export function buildComputationFromProps(properties){
return computation;
}
function storePropInMemo(prop, memo){
// Store dicts for easy access later
// Store a copy of the unmodified prop
memo.originalPropsById[prop._id] = cloneDeep(prop);
// Store by id
memo.propsById[prop._id] = prop;
// Store by type
memo.propsByType[prop.type] ?
memo.propsByType[prop.type].push(prop) :
memo.propsByType[prop.type] = [prop];
// Store by variableName
memo.propsByVariableName[prop.variableName] ?
memo.propsByVariableName[prop.variableName].push(prop) :
memo.propsByVariableName[prop.variableName]= [prop];
}

View File

@@ -3,9 +3,9 @@ import { assert } from 'chai';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
describe('buildComputation', function(){
it('Builds something', function(){
it('Builds something at all', function(){
let computation = buildComputationFromProps(testProperties);
console.log(computation);
assert.exists(computation);
});
});
@@ -13,6 +13,14 @@ var testProperties = [
clean({
_id: 'attributeId123',
type: 'attribute',
variableName: 'strength',
attributeType: 'ability',
baseValue: {
calculation: '1 + 2 + 3',
},
description: {
text: 'strength is {strength}'
}
}),
];

View File

@@ -1,9 +1,9 @@
import aggregate from '/imports/api/creature/computation/newEngine/computeComputation/computeVariable/aggregate/index.js';
import computeVariableAsAttribute from '/imports/api/creature/computation/newEngine/computeComputation/computeVariableAsType/computeVariableAsAttribute.js';
import computeVariableAsSkill from '/imports/api/creature/computation/newEngine/computeComputation/computeVariableAsType/computeVariableAsSkill.js';
import computeVariableAsConstant from '/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/computeVariableAsConstant.js';
import computeVariableAsClass from '/imports/api/creature/computation/newEngine/computeComputation/computeVariable/computeVariableAsClass.js';
import computeImplicitVariable from '/imports/api/creature/computation/newEngine/computeComputation/computeVariable/computeImplicitVariable.js';
import aggregate from './computeVariable/aggregate/index.js';
import computeVariableAsAttribute from './computeVariable/computeVariableAsAttribute.js';
import computeVariableAsSkill from './computeVariable/computeVariableAsSkill.js';
import computeVariableAsConstant from './computeVariable/computeVariableAsConstant.js';
import computeVariableAsClass from './computeVariable/computeVariableAsClass.js';
import computeImplicitVariable from './computeVariable/computeImplicitVariable.js';
export default function computeVariable(graph, node, scope){
if (!node.data) node.data = {};
@@ -16,6 +16,7 @@ export default function computeVariable(graph, node, scope){
// Otherwise add an implicit variable to the scope
scope[node.id] = computeImplicitVariable(node, scope);
}
console.log('computed variable ', node);
}
function aggregateLinks(graph, node){
@@ -40,13 +41,14 @@ function aggregateLinks(graph, node){
function combineAggregations(node, scope){
combineMultiplierAggregator(node);
node.overridenProps.forEach(prop => {
node.data.overridenProps?.forEach(prop => {
computeVariableProp(node, prop, scope);
});
computeVariableProp(node, node.definingProp, scope);
computeVariableProp(node, node.data.definingProp, scope);
}
function computeVariableProp(node, prop, scope){
if (!prop) return;
if (prop.type === 'attribute'){
computeVariableAsAttribute(node, prop, scope)
} else if (prop.type === 'skill'){
@@ -61,6 +63,7 @@ function computeVariableProp(node, prop, scope){
function combineMultiplierAggregator(node){
// get a reference to the aggregator
const aggregator = node.data.multiplierAggregator;
if (!aggregator) return;
// Combine
let value;

View File

@@ -1,4 +1,4 @@
import getAggregatorResult from '/imports/api/creature/computation/newEngine/computeComputation/computeVariable/getAggregatorResult.js';
import getAggregatorResult from './getAggregatorResult.js';
/*
* Variables with effects, proficiencies, or damage multipliers but no defining

View File

@@ -1,7 +1,8 @@
import getAggregatorResult from '/imports/api/creature/computation/newEngine/computeComputation/computeVariable/getAggregatorResult.js';
import getAggregatorResult from './getAggregatorResult.js';
export default function computeVariableAsAttribute(node, prop, scope){
let result = getAggregatorResult(node);
console.log('computing variable as attribure ', node);
prop.total = result;
prop.value = prop.total - (prop.damage || 0);

View File

@@ -2,6 +2,7 @@ import { CompilationContext } from '/imports/parser/parser.js';
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX.js';
export default function computeCalculations(node, scope){
if (!node.data) return;
// evaluate all the calculations
node.data._computationDetails?.calculations?.forEach(calcObj => {
evaluateCalculation(calcObj, scope)
@@ -14,7 +15,7 @@ export default function computeCalculations(node, scope){
function evaluateCalculation(calculation, scope){
const context = new CompilationContext();
const parseNode = calculation._parsedCalculation;
const fn = calculation._parseLevel || 'reduce';
const fn = calculation._parseLevel;
const calculationScope = {...calculation._localScope, ...scope};
calculation.value = parseNode[fn](calculationScope, context);
calculation.errors = context.errors;

View File

@@ -1,5 +1,6 @@
export default function evaluateToggles(node){
let prop = node.data;
if (!prop) return;
let toggles = prop._computationDetails?.toggleAncestors;
if (!toggles) return;
toggles.forEach(toggle => {

View File

@@ -8,27 +8,23 @@ export default function computeCreatureComputation(computation){
const scope = {};
const graph = computation.dependencyGraph;
// Add all nodes to the stack
graph.forEachNode(node => stack.push({
node,
visited: false,
visitedChildren: false,
}));
graph.forEachNode(node => stack.push(node));
// Depth first traversal of nodes
while (stack.length){
let top = stack[stack.length - 1];
if (top.visited){
if (top._visited){
// The object has already been computed, skip
stack.pop();
} else if (top.visitedChildren){
// Compute the top object of the stack
compute(graph, top.node, scope);
} else if (top._visitedChildren){
// Mark the object as visited and remove from stack
top.visited = true;
top._visited = true;
stack.pop();
// Compute the top object of the stack
compute(graph, top, scope);
} else {
top._visitedChildren = true;
// Push dependencies to graph to be computed first
pushDependenciesToStack(top.node.id, graph, stack);
top.visitedChildren = true;
pushDependenciesToStack(top.id, graph, stack);
}
}
}
@@ -42,15 +38,5 @@ function compute(graph, node, scope){
}
function pushDependenciesToStack(nodeId, graph, stack){
graph.forEachLinkedNode(
nodeId,
(linkedNode) => {
stack.push({
node: linkedNode,
visited: false,
visitedChildren: false,
});
},
true // enumerate only outbound links
);
graph.forEachLinkedNode(nodeId, linkedNode => stack.push(linkedNode), true);
}

View File

@@ -0,0 +1,34 @@
import computeCreatureComputation from './computeCreatureComputation.js';
import { buildComputationFromProps } from './buildCreatureComputation.js';
import { assert } from 'chai';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
describe('Compute compuation', function(){
it('Computes something at all', function(){
console.time('compute');
let computation = buildComputationFromProps(testProperties);
computeCreatureComputation(computation);
console.timeEnd('compute');
assert.exists(computation);
});
});
var testProperties = [
clean({
_id: 'attributeId123',
type: 'attribute',
variableName: 'strength',
attributeType: 'ability',
baseValue: {
calculation: '1 + 2 + 3',
},
description: {
text: 'strength is {strength}'
}
}),
];
function clean(prop){
let schema = CreatureProperties.simpleSchema(prop);
return schema.clean(prop);
}

View File

@@ -1,7 +1,7 @@
import { get } from 'lodash';
export function applyFnToKey(doc, key, fn){
if (key.includes('$.')){
export default function applyFnToKey(doc, key, fn){
if (key.includes('.$')){
applyToArrayKey(doc, key, fn);
} else {
applyToSingleKey(doc, key, fn);
@@ -16,26 +16,31 @@ function applyToSingleKey(doc, key, fn){
/**
* Applies the given function to all instances in a document key
* key.$.with.$.subdocs will apply to all key[i...n].with[j...m].subdocs
* Warning: Order might be confusing, it will traverse the deepest array in order
* but the shallower arrays in reverse order
*/
function applyToArrayKey(doc, key, fn){
const keySplit = key.split('.$');
// Stack based depth first traversal of arrays
const array = get(doc, keySplit[0]);
if (!array) return;
const stack = [{
array: get(doc, keySplit[0]),
array,
paths: keySplit.slice(1),
currentPath: keySplit[0],
indices: [],
}];
while(stack.length){
const state = stack.pop();
for (let index in state.array.length){
for (let index in state.array){
const currentPath = `${state.currentPath}[${index}]${state.paths[0]}`
if (state.paths.length == 1){
applyToSingleKey(doc, currentPath, fn);
} else {
const array = get(doc, currentPath);
if (!array) return;
stack.push({
array: get(doc, currentPath),
array,
paths: state.paths.slice(1),
currentPath,
indices: [...state.indices, index],

View File

@@ -0,0 +1,60 @@
import applyFnToKey from './applyFnToKey.js';
import { assert } from 'chai';
import { get } from 'lodash';
describe('apply function to key', function(){
it('uses a basic key correctly', function(){
let obj = getStartingObject();
applyFnToKey(obj, 'fox.name', (doc, key) => {
assert.equal(obj, doc);
assert.equal(key, 'fox.name');
assert.equal(get(doc, key), 'foxy');
});
});
it('uses a single nested key correctly', function(){
let obj = getStartingObject();
let foxSounds = [];
applyFnToKey(obj, 'fox.sound.$', (doc, key) => {
foxSounds.push(get(doc, key));
});
assert.include(foxSounds, 'wah');
assert.include(foxSounds, 'tjoef');
assert.include(foxSounds, 'kek');
});
it('uses a double nested key correctly', function(){
let obj = getStartingObject();
let birdSounds = [];
applyFnToKey(obj, 'birds.$.sound.$', (doc, key) => {
birdSounds.push(get(doc, key));
});
assert.include(birdSounds, 'koer');
assert.include(birdSounds, 'hello');
assert.include(birdSounds, 'squawk');
});
});
function getStartingObject(){
return {
fox: {
name: 'foxy',
sound: [
'tjoef',
'kek',
'wah'
]
},
birds: [{
name: 'pigeon',
sound: [
'koer',
]
},{
name: 'parrot',
sound: [
'hello',
'cracker?',
'squawk',
]
}]
}
}

View File

@@ -6,6 +6,7 @@ import {
} from '/imports/api/properties/subSchemas/ResourcesSchema.js';
import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js';
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
SimpleSchema.extendOptions(['parseLevel']);
/*
* Actions are things a character can do

View File

@@ -1,5 +1,5 @@
import SimpleSchema from 'simpl-schema';
import InlineComputationSchema from '/imports/api/properties/subSchemas/InlineComputationSchema.js';
import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js';
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
// Get schemas that apply fields directly so they can be gracefully extended
@@ -26,18 +26,36 @@ function computedOnlyInlineCalculationField(field){
type: Object,
optional: true,
},
[`${field}.value`]: {
type: String,
optional: true,
max: STORAGE_LIMITS.inlineCalculationField,
},
[`${field}.inlineCalculations`]: {
type: Array,
defaultValue: [],
maxCount: STORAGE_LIMITS.inlineCalculationCount,
},
[`${field}.inlineCalculations.$`]: {
type: InlineComputationSchema,
type: Object,
},
[`${field}.value`]: {
// The part between bracers {}
[`${field}.inlineCalculations.$.calculation`]: {
type: String,
max: STORAGE_LIMITS.calculation,
},
[`${field}.inlineCalculations.$.value`]: {
type: SimpleSchema.oneOf(String, Number),
optional: true,
max: STORAGE_LIMITS.inlineCalculationField,
max: STORAGE_LIMITS.calculation,
},
[`${field}.inlineCalculations.$.errors`]: {
type: Array,
optional: true,
maxCount: STORAGE_LIMITS.errorCount,
},
[`${field}.inlineCalculations.$.errors.$`]: {
type: ErrorSchema,
},
});
}

View File

@@ -38,9 +38,6 @@ const exampleAction = {
'usesUsed':0,
'description':'Starting at 1st level, you gain the ability to place a baleful curse on someone. As a bonus action, choose one creature you can see within 30 feet of you. The target is cursed for 1 minute. The curse ends early if the target dies, you die, or you are incapacitated. Until the curse ends, you gain the following benefits:\n\n- You gain a bonus to damage rolls against the cursed target. The bonus equals your proficiency bonus.\n- Any attack roll you make against the cursed target is a critical hit on a roll of 19 or 20 on the d20.\n- If the cursed target dies, you regain hit points equal to your warlock level + your Charisma modifier (minimum of 1 hit point). \n{warlock.level <10 ? "" :"- If you are hit with an attack by your cursed target, use your reaction to roll a d6. On a 4 or higher, the attack instead misses."} \nYou can\\\'t use this feature again until you finish a short or long rest.',
'color':'#8e24aa',
'dependencies':[
'4eM4YkgAaoCJfCfQ8',
],
'descriptionCalculations':[
{
'calculation':'warlock.level <10 ? "" :"- If you are hit with an attack by your cursed target, use your reaction to roll a d6. On a 4 or higher, the attack instead misses."',

View File

@@ -107,7 +107,7 @@ import ItemList from '/imports/ui/properties/components/inventory/ItemList.vue';
import getParentRefByTag from '/imports/api/creature/creatureProperties/methods/getParentRefByTag.js';
import BUILT_IN_TAGS from '/imports/constants/BUILT_IN_TAGS.js';
import CoinValue from '/imports/ui/components/CoinValue.vue';
import stripFloatingPointOddities from '/imports/ui/utility/stripFloatingPointOddities.js';
import stripFloatingPointOddities from '/imports/api/creature/computation/newEngine/utility/stripFloatingPointOddities.js';
export default {
components: {

View File

@@ -49,7 +49,7 @@ import ToolbarCard from '/imports/ui/components/ToolbarCard.vue';
import ItemList from '/imports/ui/properties/components/inventory/ItemList.vue';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import CoinValue from '/imports/ui/components/CoinValue.vue';
import stripFloatingPointOddities from '/imports/ui/utility/stripFloatingPointOddities.js';
import stripFloatingPointOddities from '/imports/api/creature/computation/newEngine/utility/stripFloatingPointOddities.js';
export default {
components: {

View File

@@ -134,7 +134,7 @@ import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyV
import CoinValue from '/imports/ui/components/CoinValue.vue';
import IncrementButton from '/imports/ui/components/IncrementButton.vue';
import adjustQuantity from '/imports/api/creature/creatureProperties/methods/adjustQuantity.js';
import stripFloatingPointOddities from '/imports/ui/utility/stripFloatingPointOddities.js';
import stripFloatingPointOddities from '/imports/api/creature/computation/newEngine/utility/stripFloatingPointOddities.js';
export default {
components:{