Improved dependencies-only recalculations and fixed many calculation bugs
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
||||||
|
import { union } from 'lodash';
|
||||||
|
|
||||||
export default class EffectAggregator{
|
export default class EffectAggregator{
|
||||||
constructor(stat, memo){
|
constructor(stat, memo){
|
||||||
@@ -14,7 +15,10 @@ export default class EffectAggregator{
|
|||||||
memo
|
memo
|
||||||
});
|
});
|
||||||
this.statBaseValue = result.value;
|
this.statBaseValue = result.value;
|
||||||
stat.dependencies.push(...dependencies);
|
stat.dependencies = union(
|
||||||
|
stat.dependencies,
|
||||||
|
dependencies,
|
||||||
|
);
|
||||||
if (context.errors.length){
|
if (context.errors.length){
|
||||||
this.baseValueErrors = context.errors;
|
this.baseValueErrors = context.errors;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
import computeToggle from '/imports/api/creature/computation/engine/computeToggle.js';
|
import computeToggle from '/imports/api/creature/computation/engine/computeToggle.js';
|
||||||
|
import { union } from 'lodash';
|
||||||
|
|
||||||
export default function applyToggles(prop, memo){
|
export default function applyToggles(prop, memo){
|
||||||
prop.computationDetails.toggleAncestors.forEach(toggleId => {
|
prop.computationDetails.toggleAncestors.forEach(toggleId => {
|
||||||
let toggle = memo.togglesById[toggleId];
|
let toggle = memo.togglesById[toggleId];
|
||||||
computeToggle(toggle, memo);
|
computeToggle(toggle, memo);
|
||||||
prop.dependencies.push(toggle._id, ...toggle.dependencies);
|
prop.dependencies = union(
|
||||||
|
prop.dependencies,
|
||||||
|
[toggle._id],
|
||||||
|
toggle.dependencies,
|
||||||
|
);
|
||||||
if (!toggle.toggleResult){
|
if (!toggle.toggleResult){
|
||||||
prop.computationDetails.disabledByToggle = true;
|
prop.computationDetails.disabledByToggle = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import computeStat from '/imports/api/creature/computation/engine/computeStat.js';
|
import computeStat from '/imports/api/creature/computation/engine/computeStat.js';
|
||||||
import applyToggles from '/imports/api/creature/computation/engine/applyToggles.js';
|
import applyToggles from '/imports/api/creature/computation/engine/applyToggles.js';
|
||||||
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
||||||
|
import { union } from 'lodash';
|
||||||
|
|
||||||
export default function combineStat(stat, aggregator, memo){
|
export default function combineStat(stat, aggregator, memo){
|
||||||
if (stat.type === 'attribute'){
|
if (stat.type === 'attribute'){
|
||||||
@@ -45,7 +46,7 @@ function combineAttribute(stat, aggregator, memo){
|
|||||||
});
|
});
|
||||||
stat.spellSlotLevelValue = result.value;
|
stat.spellSlotLevelValue = result.value;
|
||||||
stat.spellSlotLevelErrors = context.errors;
|
stat.spellSlotLevelErrors = context.errors;
|
||||||
stat.dependencies.push(...dependencies);
|
stat.dependencies = union(stat.dependencies, dependencies);
|
||||||
}
|
}
|
||||||
stat.currentValue = stat.value - (stat.damage || 0);
|
stat.currentValue = stat.value - (stat.damage || 0);
|
||||||
// Ability scores get modifiers
|
// Ability scores get modifiers
|
||||||
@@ -60,7 +61,11 @@ function combineAttribute(stat, aggregator, memo){
|
|||||||
let conStat = memo.statsByVariableName['constitution'];
|
let conStat = memo.statsByVariableName['constitution'];
|
||||||
if (conStat && 'modifier' in conStat){
|
if (conStat && 'modifier' in conStat){
|
||||||
stat.constitutionMod = conStat.modifier;
|
stat.constitutionMod = conStat.modifier;
|
||||||
stat.dependencies.push(conStat._id, ...conStat.dependencies);
|
stat.dependencies = union(
|
||||||
|
stat.dependencies,
|
||||||
|
[conStat._id],
|
||||||
|
conStat.dependencies,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Stats that have no effects can be hidden based on a sheet setting
|
// Stats that have no effects can be hidden based on a sheet setting
|
||||||
@@ -77,7 +82,11 @@ function combineSkill(stat, aggregator, memo){
|
|||||||
computeStat(ability, memo);
|
computeStat(ability, memo);
|
||||||
}
|
}
|
||||||
stat.abilityMod = ability.modifier;
|
stat.abilityMod = ability.modifier;
|
||||||
stat.dependencies.push(ability._id, ...ability.dependencies);
|
stat.dependencies = union(
|
||||||
|
stat.dependencies,
|
||||||
|
[ability._id],
|
||||||
|
ability.dependencies,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Combine all the child proficiencies
|
// Combine all the child proficiencies
|
||||||
stat.proficiency = stat.baseProficiency || 0;
|
stat.proficiency = stat.baseProficiency || 0;
|
||||||
@@ -89,7 +98,11 @@ function combineSkill(stat, aggregator, memo){
|
|||||||
prof.value > stat.proficiency
|
prof.value > stat.proficiency
|
||||||
){
|
){
|
||||||
stat.proficiency = prof.value;
|
stat.proficiency = prof.value;
|
||||||
stat.dependencies.push(prof._id, ...prof.dependencies);
|
stat.dependencies = union(
|
||||||
|
stat.dependencies,
|
||||||
|
[prof._id],
|
||||||
|
prof.dependencies,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get the character's proficiency bonus to apply
|
// Get the character's proficiency bonus to apply
|
||||||
@@ -99,10 +112,18 @@ function combineSkill(stat, aggregator, memo){
|
|||||||
if (typeof profBonus !== 'number' && memo.statsByVariableName['level']){
|
if (typeof profBonus !== 'number' && memo.statsByVariableName['level']){
|
||||||
let level = memo.statsByVariableName['level'].value;
|
let level = memo.statsByVariableName['level'].value;
|
||||||
profBonus = Math.ceil(level / 4) + 1;
|
profBonus = Math.ceil(level / 4) + 1;
|
||||||
if (level._id) stat.dependencies.push(level._id);
|
if (level._id){
|
||||||
if (level.dependencies) stat.dependencies.push(...level.dependencies);
|
stat.dependencies = union(stat.dependencies, [level._id]);
|
||||||
|
}
|
||||||
|
if (level.dependencies){
|
||||||
|
stat.dependencies = union(stat.dependencies, level.dependencies);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
stat.dependencies.push(profBonusStat._id, ...profBonusStat.dependencies);
|
stat.dependencies = union(
|
||||||
|
stat.dependencies,
|
||||||
|
[profBonusStat._id],
|
||||||
|
profBonusStat.dependencies,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Multiply the proficiency bonus by the actual proficiency
|
// Multiply the proficiency bonus by the actual proficiency
|
||||||
profBonus *= stat.proficiency;
|
profBonus *= stat.proficiency;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
||||||
import applyToggles from '/imports/api/creature/computation/engine/applyToggles.js';
|
import applyToggles from '/imports/api/creature/computation/engine/applyToggles.js';
|
||||||
|
import { union } from 'lodash';
|
||||||
|
|
||||||
export default function computeEffect(effect, memo){
|
export default function computeEffect(effect, memo){
|
||||||
if (effect.computationDetails.computed) return;
|
if (effect.computationDetails.computed) return;
|
||||||
@@ -44,7 +45,7 @@ export default function computeEffect(effect, memo){
|
|||||||
memo
|
memo
|
||||||
});
|
});
|
||||||
effect.result = result.value;
|
effect.result = result.value;
|
||||||
effect.dependencies.push(...dependencies);
|
effect.dependencies = union(effect.dependencies, dependencies);
|
||||||
if (context.errors.length){
|
if (context.errors.length){
|
||||||
effect.errors = context.errors;
|
effect.errors = context.errors;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
||||||
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
||||||
|
import { union } from 'lodash';
|
||||||
|
|
||||||
export default function computeEndStepProperty(prop, memo){
|
export default function computeEndStepProperty(prop, memo){
|
||||||
switch (prop.type){
|
switch (prop.type){
|
||||||
@@ -35,7 +36,7 @@ function computeAction(prop, memo){
|
|||||||
dependencies,
|
dependencies,
|
||||||
} = evaluateCalculation({ string: prop.uses, prop, memo});
|
} = evaluateCalculation({ string: prop.uses, prop, memo});
|
||||||
prop.usesResult = result.value;
|
prop.usesResult = result.value;
|
||||||
prop.dependencies.push(...dependencies);
|
prop.dependencies = union(prop.dependencies, dependencies);
|
||||||
if (context.errors.length){
|
if (context.errors.length){
|
||||||
prop.usesErrors = context.errors;
|
prop.usesErrors = context.errors;
|
||||||
} else {
|
} else {
|
||||||
@@ -57,7 +58,13 @@ function computeAction(prop, memo){
|
|||||||
if (available < attConsumed.quantity){
|
if (available < attConsumed.quantity){
|
||||||
prop.insufficientResources = true;
|
prop.insufficientResources = true;
|
||||||
}
|
}
|
||||||
if (stat) prop.dependencies.push(stat._id, ...stat.dependencies);
|
if (stat){
|
||||||
|
prop.dependencies = union(
|
||||||
|
prop.dependencies,
|
||||||
|
[stat._id],
|
||||||
|
stat.dependencies
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Items consumed
|
// Items consumed
|
||||||
@@ -76,7 +83,13 @@ function computeAction(prop, memo){
|
|||||||
if (!item || available < itemConsumed.quantity){
|
if (!item || available < itemConsumed.quantity){
|
||||||
prop.insufficientResources = true;
|
prop.insufficientResources = true;
|
||||||
}
|
}
|
||||||
if (item) prop.dependencies.push(item._id, ...item.dependencies);
|
if (item){
|
||||||
|
prop.dependencies = union(
|
||||||
|
prop.dependencies,
|
||||||
|
[item._id],
|
||||||
|
item.dependencies
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +104,7 @@ function computePropertyField(prop, memo, fieldName, fn){
|
|||||||
} else {
|
} else {
|
||||||
prop[`${fieldName}Result`] = result.toString();
|
prop[`${fieldName}Result`] = result.toString();
|
||||||
}
|
}
|
||||||
prop.dependencies.push(...dependencies);
|
prop.dependencies = union(prop.dependencies, dependencies);
|
||||||
if (context.errors.length){
|
if (context.errors.length){
|
||||||
prop[`${fieldName}Errors`] = context.errors;
|
prop[`${fieldName}Errors`] = context.errors;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
||||||
|
import { union } from 'lodash';
|
||||||
|
|
||||||
export default function computeInlineCalculations(prop, memo){
|
export default function computeInlineCalculations(prop, memo){
|
||||||
if (prop.summary){
|
if (prop.summary){
|
||||||
@@ -28,7 +29,7 @@ function computeInlineCalcsForField(prop, memo, field){
|
|||||||
computation.errors = context.errors;
|
computation.errors = context.errors;
|
||||||
}
|
}
|
||||||
inlineComputations.push(computation);
|
inlineComputations.push(computation);
|
||||||
prop.dependencies.push(...dependencies);
|
prop.dependencies = union(prop.dependencies, dependencies);
|
||||||
}
|
}
|
||||||
prop[`${field}Calculations`] = inlineComputations;
|
prop[`${field}Calculations`] = inlineComputations;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { forOwn, has } from 'lodash';
|
import { forOwn, has, union } from 'lodash';
|
||||||
|
|
||||||
export default function computeLevels(memo){
|
export default function computeLevels(memo){
|
||||||
computeClassLevels(memo);
|
computeClassLevels(memo);
|
||||||
@@ -8,7 +8,10 @@ export default function computeLevels(memo){
|
|||||||
function computeClassLevels(memo){
|
function computeClassLevels(memo){
|
||||||
forOwn(memo.classLevelsById, classLevel => {
|
forOwn(memo.classLevelsById, classLevel => {
|
||||||
// class levels are mutually dependent
|
// class levels are mutually dependent
|
||||||
classLevel.dependencies.push(Object.keys(memo.classLevelsById));
|
classLevel.dependencies = union(
|
||||||
|
classLevel.dependencies,
|
||||||
|
Object.keys(memo.classLevelsById)
|
||||||
|
);
|
||||||
let name = classLevel.variableName;
|
let name = classLevel.variableName;
|
||||||
let stat = memo.statsByVariableName[name];
|
let stat = memo.statsByVariableName[name];
|
||||||
if (!stat){
|
if (!stat){
|
||||||
@@ -43,8 +46,18 @@ function computeTotalLevel(memo){
|
|||||||
for (let name in memo.classes){
|
for (let name in memo.classes){
|
||||||
let cls = memo.classes[name];
|
let cls = memo.classes[name];
|
||||||
level += cls.level || 0;
|
level += cls.level || 0;
|
||||||
if (cls._id) currentLevel.dependencies.push(cls._id);
|
if (cls._id){
|
||||||
if (cls.dependencies) currentLevel.dependencies.push(...cls.dependencies);
|
currentLevel.dependencies = union(
|
||||||
|
currentLevel.dependencies,
|
||||||
|
[cls._id]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (cls.dependencies){
|
||||||
|
currentLevel.dependencies = union(
|
||||||
|
currentLevel.dependencies,
|
||||||
|
cls.dependencies,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
currentLevel.value = level;
|
currentLevel.value = level;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import combineStat from '/imports/api/creature/computation/engine/combineStat.js
|
|||||||
import computeEffect from '/imports/api/creature/computation/engine/computeEffect.js';
|
import computeEffect from '/imports/api/creature/computation/engine/computeEffect.js';
|
||||||
import EffectAggregator from '/imports/api/creature/computation/engine/EffectAggregator.js';
|
import EffectAggregator from '/imports/api/creature/computation/engine/EffectAggregator.js';
|
||||||
import applyToggles from '/imports/api/creature/computation/engine/applyToggles.js';
|
import applyToggles from '/imports/api/creature/computation/engine/applyToggles.js';
|
||||||
import { each } from 'lodash';
|
import { each, union } from 'lodash';
|
||||||
|
|
||||||
export default function computeStat(stat, memo){
|
export default function computeStat(stat, memo){
|
||||||
// If the stat is already computed, skip it
|
// If the stat is already computed, skip it
|
||||||
@@ -27,8 +27,16 @@ export default function computeStat(stat, memo){
|
|||||||
let aggregator = new EffectAggregator(stat, memo)
|
let aggregator = new EffectAggregator(stat, memo)
|
||||||
each(stat.computationDetails.effects, (effect) => {
|
each(stat.computationDetails.effects, (effect) => {
|
||||||
computeEffect(effect, memo);
|
computeEffect(effect, memo);
|
||||||
if (effect._id) stat.dependencies.push(effect._id);
|
if (effect._id){
|
||||||
stat.dependencies.push(...effect.dependencies);
|
stat.dependencies = union(
|
||||||
|
stat.dependencies,
|
||||||
|
[effect._id]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
stat.dependencies = union(
|
||||||
|
stat.dependencies,
|
||||||
|
effect.dependencies
|
||||||
|
)
|
||||||
if (!effect.computationDetails.disabledByToggle){
|
if (!effect.computationDetails.disabledByToggle){
|
||||||
aggregator.addEffect(effect);
|
aggregator.addEffect(effect);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
import evaluateCalculation from '/imports/api/creature/computation/engine/evaluateCalculation.js';
|
||||||
|
import { union } from 'lodash';
|
||||||
|
|
||||||
export default function computeToggle(toggle, memo){
|
export default function computeToggle(toggle, memo){
|
||||||
if (toggle.computationDetails.computed) return;
|
if (toggle.computationDetails.computed) return;
|
||||||
@@ -32,7 +33,10 @@ export default function computeToggle(toggle, memo){
|
|||||||
dependencies,
|
dependencies,
|
||||||
} = evaluateCalculation({string: toggle.condition, prop: toggle, memo});
|
} = evaluateCalculation({string: toggle.condition, prop: toggle, memo});
|
||||||
toggle.toggleResult = !!result.value;
|
toggle.toggleResult = !!result.value;
|
||||||
toggle.dependencies.push(...dependencies);
|
toggle.dependencies = union(
|
||||||
|
toggle.dependencies,
|
||||||
|
dependencies,
|
||||||
|
);
|
||||||
if (context.errors.length){
|
if (context.errors.length){
|
||||||
toggle.errors = context.errors;
|
toggle.errors = context.errors;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import SymbolNode from '/imports/parser/parseTree/SymbolNode.js';
|
|||||||
import AccessorNode from '/imports/parser/parseTree/AccessorNode.js';
|
import AccessorNode from '/imports/parser/parseTree/AccessorNode.js';
|
||||||
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
||||||
import findAncestorByType from '/imports/api/creature/computation/engine/findAncestorByType.js';
|
import findAncestorByType from '/imports/api/creature/computation/engine/findAncestorByType.js';
|
||||||
|
import { union } from 'lodash';
|
||||||
|
|
||||||
/* Convert a calculation into a constant output and errors*/
|
/* Convert a calculation into a constant output and errors*/
|
||||||
export default function evaluateCalculation({
|
export default function evaluateCalculation({
|
||||||
@@ -55,7 +56,12 @@ export default function evaluateCalculation({
|
|||||||
if (stat && stat.computationDetails && !stat.computationDetails.computed){
|
if (stat && stat.computationDetails && !stat.computationDetails.computed){
|
||||||
computeStat(stat, memo);
|
computeStat(stat, memo);
|
||||||
}
|
}
|
||||||
if (stat) dependencies.push(stat._id || node.name, ...stat.dependencies);
|
if (stat){
|
||||||
|
dependencies = union(dependencies, [
|
||||||
|
stat._id || node.name,
|
||||||
|
...stat.dependencies
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Evaluate
|
// Evaluate
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||||
|
import { union } from 'lodash';
|
||||||
|
|
||||||
export default function getDependentProperties({creatureId, dependencies}){
|
export default function getDependentProperties({
|
||||||
|
creatureId,
|
||||||
|
propertyIds,
|
||||||
|
propertiesDependedAponIds,
|
||||||
|
}){
|
||||||
// find ids of all dependant toggles that have conditions, even if inactive
|
// find ids of all dependant toggles that have conditions, even if inactive
|
||||||
let toggleIds = CreatureProperties.find({
|
let toggleIds = CreatureProperties.find({
|
||||||
'ancestors.id': creatureId,
|
'ancestors.id': creatureId,
|
||||||
type: 'toggle',
|
type: 'toggle',
|
||||||
removed: {$ne: true},
|
removed: {$ne: true},
|
||||||
condition: { $exists: true },
|
condition: { $exists: true },
|
||||||
dependencies: {$in: dependencies},
|
dependencies: {$in: propertyIds},
|
||||||
}, {
|
}, {
|
||||||
fields: {_id: 1},
|
fields: {_id: 1},
|
||||||
}).map(t => t._id);
|
}).map(t => t._id);
|
||||||
@@ -15,7 +20,7 @@ export default function getDependentProperties({creatureId, dependencies}){
|
|||||||
let props = CreatureProperties.find({
|
let props = CreatureProperties.find({
|
||||||
'ancestors.id': creatureId,
|
'ancestors.id': creatureId,
|
||||||
removed: {$ne: true},
|
removed: {$ne: true},
|
||||||
dependencies: {$in: dependencies},
|
dependencies: {$in: propertyIds},
|
||||||
$or: [
|
$or: [
|
||||||
// All active properties
|
// All active properties
|
||||||
{inactive: {$ne: true}},
|
{inactive: {$ne: true}},
|
||||||
@@ -25,18 +30,22 @@ export default function getDependentProperties({creatureId, dependencies}){
|
|||||||
// All decendents of the above toggles
|
// All decendents of the above toggles
|
||||||
{'ancestors.id': {$in: toggleIds}},
|
{'ancestors.id': {$in: toggleIds}},
|
||||||
]
|
]
|
||||||
}, {
|
}, { fields: {_id: 1, dependencies: 1} }).fetch();
|
||||||
// Filter out fields never used by calculations
|
// Add all the properties that changing props depend on, but haven't yet been
|
||||||
fields: {
|
// included to make an array of every property we need
|
||||||
icon: 0,
|
let allConnectedPropIds = [...propertyIds, ...propertiesDependedAponIds];
|
||||||
},
|
props.forEach(prop => {
|
||||||
sort: {
|
allConnectedPropIds = union(
|
||||||
order: 1,
|
allConnectedPropIds,
|
||||||
}
|
prop.dependencies,
|
||||||
}).fetch();
|
[prop._id]);
|
||||||
// Add on all the properties th
|
|
||||||
CreatureProperties.find({_id: {$in: dependencies}}).forEach(prop => {
|
|
||||||
props.push(prop)
|
|
||||||
});
|
});
|
||||||
return props;
|
// Add on all the properties and the objects they depend apon
|
||||||
|
return CreatureProperties.find({
|
||||||
|
_id: {$in: allConnectedPropIds}
|
||||||
|
}, {
|
||||||
|
// Ignore fields not used in computations
|
||||||
|
fields: {icon: 0},
|
||||||
|
sort: {order: 1},
|
||||||
|
}).fetch();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default function writeAlteredProperties(memo){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
bulkWriteProperties(bulkWriteOperations);
|
writePropertiesSequentially(bulkWriteOperations);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addChangedKeysToOp(op, keys, original, changed) {
|
function addChangedKeysToOp(op, keys, original, changed) {
|
||||||
@@ -77,11 +77,28 @@ function addUnsetOp(op, key){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We use this instead of bulkWriteProperties because it functions with latency
|
||||||
|
// compensation without needing to roll back changes, which causes multiple
|
||||||
|
// expensive redraws of the character sheet
|
||||||
|
function writePropertiesSequentially(bulkWriteOps){
|
||||||
|
bulkWriteOps.forEach(op => {
|
||||||
|
let updateOneOrMany = op.updateOne || op.updateMany;
|
||||||
|
CreatureProperties.update(updateOneOrMany.filter, updateOneOrMany.update, {
|
||||||
|
// The bulk code is bypassing validation, so do the same here
|
||||||
|
// selector: {type: op.type} // include this if bypass is off
|
||||||
|
bypassCollection2: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is more efficient on the database, but significantly less efficient
|
||||||
|
// in the UI because of incompatibility with latency compensation. If the
|
||||||
|
// duplicate redraws can be fixed, this is a strictly better way of processing
|
||||||
|
// writes
|
||||||
function bulkWriteProperties(bulkWriteOps){
|
function bulkWriteProperties(bulkWriteOps){
|
||||||
if (!bulkWriteOps.length) return;
|
if (!bulkWriteOps.length) return;
|
||||||
// Only use bulk writing if there are many writes to do
|
// bulkWrite is only available on the server
|
||||||
// it makes latency compensation janky, so we avoid it for smaller writes
|
if (Meteor.isServer){
|
||||||
if (Meteor.isServer && bulkWriteOps.length > 16){
|
|
||||||
CreatureProperties.rawCollection().bulkWrite(
|
CreatureProperties.rawCollection().bulkWrite(
|
||||||
bulkWriteOps,
|
bulkWriteOps,
|
||||||
{ordered : false},
|
{ordered : false},
|
||||||
@@ -93,13 +110,6 @@ function bulkWriteProperties(bulkWriteOps){
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
bulkWriteOps.forEach(op => {
|
writePropertiesSequentially(bulkWriteOps);
|
||||||
let updateOneOrMany = op.updateOne || op.updateMany;
|
|
||||||
CreatureProperties.update(updateOneOrMany.filter, updateOneOrMany.update, {
|
|
||||||
// The bulk code is bypassing validation, so do the same here
|
|
||||||
// selector: {type: op.type} // include this if bypass is off
|
|
||||||
bypassCollection2: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import recomputeSlotFullness from '/imports/api/creature/denormalise/recomputeSl
|
|||||||
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
|
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
|
||||||
import getDependentProperties from '/imports/api/creature/computation/engine/getDependentProperties.js';
|
import getDependentProperties from '/imports/api/creature/computation/engine/getDependentProperties.js';
|
||||||
import Creatures from '/imports/api/creature/Creatures.js';
|
import Creatures from '/imports/api/creature/Creatures.js';
|
||||||
|
import recomputeInactiveProperties from '/imports/api/creature/denormalise/recomputeInactiveProperties.js';
|
||||||
|
|
||||||
export const recomputeCreature = new ValidatedMethod({
|
export const recomputeCreature = new ValidatedMethod({
|
||||||
|
|
||||||
@@ -88,6 +89,7 @@ export function recomputeCreatureByDoc(creature){
|
|||||||
writeCreatureVariables(computationMemo, creatureId);
|
writeCreatureVariables(computationMemo, creatureId);
|
||||||
recomputeDamageMultipliersById(creatureId);
|
recomputeDamageMultipliersById(creatureId);
|
||||||
recomputeSlotFullness(creatureId);
|
recomputeSlotFullness(creatureId);
|
||||||
|
recomputeInactiveProperties(creatureId);
|
||||||
return computationMemo;
|
return computationMemo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,17 +97,24 @@ export function recomputePropertyDependencies(property){
|
|||||||
let creature = getRootCreatureAncestor(property);
|
let creature = getRootCreatureAncestor(property);
|
||||||
recomputeCreatureByDependencies({
|
recomputeCreatureByDependencies({
|
||||||
creature,
|
creature,
|
||||||
dependencies: [property._id],
|
propertyIds: [property._id],
|
||||||
|
propertiesDependedAponIds: property.dependencies,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function recomputeCreatureByDependencies({creature, dependencies}){
|
export function recomputeCreatureByDependencies({
|
||||||
|
creature,
|
||||||
|
propertyIds,
|
||||||
|
propertiesDependedAponIds
|
||||||
|
}){
|
||||||
let props = getDependentProperties({
|
let props = getDependentProperties({
|
||||||
creatureId: creature._id,
|
creatureId: creature._id,
|
||||||
dependencies,
|
propertyIds,
|
||||||
|
propertiesDependedAponIds,
|
||||||
});
|
});
|
||||||
let computationMemo = new ComputationMemo(props, creature);
|
let computationMemo = new ComputationMemo(props, creature);
|
||||||
computeMemo(computationMemo);
|
computeMemo(computationMemo);
|
||||||
writeAlteredProperties(computationMemo);
|
writeAlteredProperties(computationMemo);
|
||||||
|
recomputeInactiveProperties(creature._id);
|
||||||
return computationMemo;
|
return computationMemo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import SimpleSchema from 'simpl-schema';
|
|||||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||||
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
|
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
|
||||||
import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js';
|
import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js';
|
||||||
import { recomputePropertyDependencies, recomputeCreatureByDoc, recomputeCreature } from '/imports/api/creature/computation/methods/recomputeCreature.js';
|
import { recomputePropertyDependencies } from '/imports/api/creature/computation/methods/recomputeCreature.js';
|
||||||
|
|
||||||
const damageProperty = new ValidatedMethod({
|
const damageProperty = new ValidatedMethod({
|
||||||
name: 'creatureProperties.damage',
|
name: 'creatureProperties.damage',
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ const dealDamage = new ValidatedMethod({
|
|||||||
let totalDamage = Math.floor(amount * multiplier);
|
let totalDamage = Math.floor(amount * multiplier);
|
||||||
let damageLeft = totalDamage;
|
let damageLeft = totalDamage;
|
||||||
if (damageType === 'healing') damageLeft = -totalDamage;
|
if (damageType === 'healing') damageLeft = -totalDamage;
|
||||||
let dependencies = [];
|
let propertyIds = [];
|
||||||
|
let propertiesDependedAponIds = [];
|
||||||
healthBars.forEach(healthBar => {
|
healthBars.forEach(healthBar => {
|
||||||
if (damageLeft === 0) return;
|
if (damageLeft === 0) return;
|
||||||
let damageAdded = damagePropertyWork({
|
let damageAdded = damagePropertyWork({
|
||||||
@@ -57,10 +58,14 @@ const dealDamage = new ValidatedMethod({
|
|||||||
value: damageLeft,
|
value: damageLeft,
|
||||||
});
|
});
|
||||||
damageLeft -= damageAdded;
|
damageLeft -= damageAdded;
|
||||||
dependencies.push(healthBar.variableName);
|
propertyIds.push(healthBar._id);
|
||||||
dependencies.push(...healthBar.dependencies);
|
propertiesDependedAponIds.push(...healthBar.dependencies);
|
||||||
|
});
|
||||||
|
recomputeCreatureByDependencies({
|
||||||
|
creature,
|
||||||
|
propertyIds,
|
||||||
|
propertiesDependedAponIds,
|
||||||
});
|
});
|
||||||
recomputeCreatureByDependencies({creature, dependencies});
|
|
||||||
return totalDamage;
|
return totalDamage;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -59,13 +59,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CreatureProperties, {
|
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||||
damageProperty,
|
import damageProperty from '/imports/api/creature/creatureProperties/methods/damageProperty.js';
|
||||||
pushToProperty,
|
import pushToProperty from '/imports/api/creature/creatureProperties/methods/pushToProperty.js';
|
||||||
pullFromProperty,
|
import pullFromProperty from '/imports/api/creature/creatureProperties/methods/pullFromProperty.js';
|
||||||
softRemoveProperty,
|
import softRemoveProperty from '/imports/api/creature/creatureProperties/methods/softRemoveProperty.js';
|
||||||
restoreProperty,
|
import restoreProperty from '/imports/api/creature/creatureProperties/methods/restoreProperty.js';
|
||||||
} from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
|
||||||
import updateCreatureProperty from '/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js';
|
import updateCreatureProperty from '/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js';
|
||||||
import duplicateProperty from '/imports/api/creature/creatureProperties/methods/duplicateProperty.js';
|
import duplicateProperty from '/imports/api/creature/creatureProperties/methods/duplicateProperty.js';
|
||||||
import Creatures from '/imports/api/creature/Creatures.js';
|
import Creatures from '/imports/api/creature/Creatures.js';
|
||||||
|
|||||||
Reference in New Issue
Block a user