Merge feature-nested-sets into develop
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { CreatureLogSchema, insertCreatureLogWork } from '/imports/api/creature/log/CreatureLogs.js';
|
||||
import { CreatureLogSchema, insertCreatureLogWork } from '/imports/api/creature/log/CreatureLogs';
|
||||
import {
|
||||
getCreature, getVariables, getPropertiesOfType, replaceLinkedVariablesWithProps
|
||||
} from '/imports/api/engine/loadCreatures.js';
|
||||
} from '/imports/api/engine/loadCreatures';
|
||||
import { groupBy, remove } from 'lodash';
|
||||
|
||||
export default class ActionContext {
|
||||
@@ -56,10 +56,10 @@ export default class ActionContext {
|
||||
// Group the triggers into triggers.<event>.<timing> or
|
||||
// triggers.doActionProperty.<propertyType>.<timing>
|
||||
this.triggers = groupBy(this.triggers, 'event');
|
||||
for (let event in this.triggers) {
|
||||
for (const event in this.triggers) {
|
||||
if (event === 'doActionProperty') {
|
||||
this.triggers[event] = groupBy(this.triggers[event], 'actionPropertyType');
|
||||
for (let propertyType in this.triggers[event]) {
|
||||
for (const propertyType in this.triggers[event]) {
|
||||
this.triggers[event][propertyType] = groupBy(this.triggers[event][propertyType], 'timing');
|
||||
}
|
||||
} else {
|
||||
@@ -1,37 +0,0 @@
|
||||
import action from './applyPropertyByType/applyAction.js';
|
||||
import ammo from './applyPropertyByType/applyItemAsAmmo.js'
|
||||
import adjustment from './applyPropertyByType/applyAdjustment.js';
|
||||
import branch from './applyPropertyByType/applyBranch.js';
|
||||
import buff from './applyPropertyByType/applyBuff.js';
|
||||
import buffRemover from './applyPropertyByType/applyBuffRemover.js';
|
||||
import damage from './applyPropertyByType/applyDamage.js';
|
||||
import folder from './applyPropertyByType/applyFolder.js';
|
||||
import note from './applyPropertyByType/applyNote.js';
|
||||
import roll from './applyPropertyByType/applyRoll.js';
|
||||
import savingThrow from './applyPropertyByType/applySavingThrow.js';
|
||||
import toggle from './applyPropertyByType/applyToggle.js';
|
||||
|
||||
const applyPropertyByType = {
|
||||
action,
|
||||
ammo,
|
||||
adjustment,
|
||||
branch,
|
||||
buff,
|
||||
buffRemover,
|
||||
damage,
|
||||
folder,
|
||||
note,
|
||||
propertySlot: folder,
|
||||
roll,
|
||||
savingThrow,
|
||||
spell: action,
|
||||
toggle,
|
||||
};
|
||||
|
||||
export default async function applyProperty(node, actionContext, ...rest) {
|
||||
if (node.node.deactivatedByToggle) return;
|
||||
actionContext.scope[`#${node.node.type}`] = node.node;
|
||||
console.log('start apply props by type', node.node.type)
|
||||
await applyPropertyByType[node.node.type]?.(node, actionContext, ...rest);
|
||||
console.log('end apply prop by type', node.node.type)
|
||||
}
|
||||
38
app/imports/api/engine/actions/applyProperty.ts
Normal file
38
app/imports/api/engine/actions/applyProperty.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import action from './applyPropertyByType/applyAction';
|
||||
import ammo from './applyPropertyByType/applyItemAsAmmo'
|
||||
import adjustment from './applyPropertyByType/applyAdjustment';
|
||||
import branch from './applyPropertyByType/applyBranch';
|
||||
import buff from './applyPropertyByType/applyBuff';
|
||||
import buffRemover from './applyPropertyByType/applyBuffRemover';
|
||||
import damage from './applyPropertyByType/applyDamage';
|
||||
import folder from './applyPropertyByType/applyFolder';
|
||||
import note from './applyPropertyByType/applyNote';
|
||||
import roll from './applyPropertyByType/applyRoll';
|
||||
import savingThrow from './applyPropertyByType/applySavingThrow';
|
||||
import toggle from './applyPropertyByType/applyToggle';
|
||||
import ActionContext from '/imports/api/engine/actions/ActionContext';
|
||||
import { TreeNode } from '/imports/api/parenting/parentingFunctions';
|
||||
import { CreatureProperty } from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
|
||||
const applyPropertyByType = {
|
||||
action,
|
||||
ammo,
|
||||
adjustment,
|
||||
branch,
|
||||
buff,
|
||||
buffRemover,
|
||||
damage,
|
||||
folder,
|
||||
note,
|
||||
propertySlot: folder,
|
||||
roll,
|
||||
savingThrow,
|
||||
spell: action,
|
||||
toggle,
|
||||
};
|
||||
|
||||
export default function applyProperty(node: TreeNode<CreatureProperty>, actionContext: ActionContext, ...rest) {
|
||||
if (node.doc.deactivatedByToggle) return;
|
||||
actionContext.scope[`#${node.doc.type}`] = node.doc;
|
||||
applyPropertyByType[node.doc.type]?.(node, actionContext, ...rest);
|
||||
}
|
||||
@@ -1,22 +1,31 @@
|
||||
import recalculateInlineCalculations from './shared/recalculateInlineCalculations.js';
|
||||
import recalculateCalculation from './shared/recalculateCalculation.js';
|
||||
import rollDice from '/imports/parser/rollDice.js';
|
||||
import applyProperty from '../applyProperty.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import { damagePropertyWork } from '/imports/api/creature/creatureProperties/methods/damageProperty.js';
|
||||
import numberToSignedString from '/imports/api/utility/numberToSignedString.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import { resetProperties } from '/imports/api/creature/creatures/methods/restCreature.js';
|
||||
import recalculateInlineCalculations from './shared/recalculateInlineCalculations';
|
||||
import recalculateCalculation from './shared/recalculateCalculation';
|
||||
import rollDice from '/imports/parser/rollDice';
|
||||
import applyProperty from '../applyProperty';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
import { damagePropertyWork } from '/imports/api/creature/creatureProperties/methods/damageProperty';
|
||||
import numberToSignedString from '/imports/api/utility/numberToSignedString';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
import { resetProperties } from '/imports/api/creature/creatures/methods/restCreature';
|
||||
import { TreeNode, hasAncestorRelationship } from '/imports/api/parenting/parentingFunctions';
|
||||
import { Action } from '/imports/api/properties/Actions';
|
||||
import { LogContent } from '/imports/api/creature/log/LogContentSchema';
|
||||
import { Item } from '/imports/api/properties/Items';
|
||||
|
||||
export default async function applyAction(node, actionContext) {
|
||||
await applyNodeTriggers(node, 'before', actionContext);
|
||||
const prop = node.node;
|
||||
interface Ammo extends Item {
|
||||
type: 'ammo'
|
||||
adjustment: number
|
||||
}
|
||||
|
||||
export default function applyAction(node: TreeNode<Action>, actionContext) {
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
const prop = node.doc;
|
||||
if (prop.target === 'self') actionContext.targets = [actionContext.creature];
|
||||
const targets = actionContext.targets;
|
||||
|
||||
// Log the name and summary
|
||||
let content = { name: prop.name };
|
||||
const content: LogContent = { name: prop.name, };
|
||||
if (prop.summary?.text) {
|
||||
recalculateInlineCalculations(prop.summary, actionContext);
|
||||
content.value = prop.summary.value;
|
||||
@@ -27,7 +36,7 @@ export default async function applyAction(node, actionContext) {
|
||||
const failed = await spendResources(prop, actionContext);
|
||||
if (failed) return;
|
||||
|
||||
const attack = prop.attackRoll || prop.attackRollBonus;
|
||||
const attack = prop.attackRoll;
|
||||
|
||||
// Attack if there is an attack roll
|
||||
if (attack && attack.calculation) {
|
||||
@@ -59,7 +68,7 @@ function applyAttackWithoutTarget({ attack, actionContext }) {
|
||||
|
||||
recalculateCalculation(attack, actionContext);
|
||||
const scope = actionContext.scope;
|
||||
let {
|
||||
const {
|
||||
resultPrefix,
|
||||
result,
|
||||
criticalHit,
|
||||
@@ -96,7 +105,7 @@ function applyAttackToTarget({ attack, target, actionContext }) {
|
||||
|
||||
recalculateCalculation(attack, actionContext);
|
||||
|
||||
let {
|
||||
const {
|
||||
resultPrefix,
|
||||
result,
|
||||
criticalHit,
|
||||
@@ -176,7 +185,7 @@ function applyCrits(value, scope) {
|
||||
scopeCrit = scopeCrit.value;
|
||||
}
|
||||
const criticalHitTarget = scopeCrit || 20;
|
||||
let criticalHit = value >= criticalHitTarget;
|
||||
const criticalHit = value >= criticalHitTarget;
|
||||
let criticalMiss;
|
||||
if (criticalHit) {
|
||||
scope['~criticalHit'] = { value: true };
|
||||
@@ -189,9 +198,9 @@ function applyCrits(value, scope) {
|
||||
return { criticalHit, criticalMiss };
|
||||
}
|
||||
|
||||
async function spendResources(prop, actionContext) {
|
||||
function spendResources(prop: Action, actionContext) {
|
||||
// Check Uses
|
||||
if (prop.usesLeft <= 0) {
|
||||
if (!prop.usesLeft || prop.usesLeft <= 0) {
|
||||
if (!prop.silent) actionContext.addLog({
|
||||
name: 'Error',
|
||||
value: `${prop.name || 'action'} does not have enough uses left`,
|
||||
@@ -207,42 +216,45 @@ async function spendResources(prop, actionContext) {
|
||||
return true;
|
||||
}
|
||||
// Items
|
||||
let spendLog = [];
|
||||
let gainLog = [];
|
||||
const ammoToApply = [];
|
||||
const spendLog: string[] = [];
|
||||
const gainLog: string[] = [];
|
||||
const ammoToApply: TreeNode<Ammo>[] = [];
|
||||
try {
|
||||
prop.resources.itemsConsumed.forEach(itemConsumed => {
|
||||
recalculateCalculation(itemConsumed.quantity, actionContext);
|
||||
if (!itemConsumed.itemId) {
|
||||
throw 'No ammo was selected for this prop';
|
||||
}
|
||||
let item = CreatureProperties.findOne(itemConsumed.itemId);
|
||||
if (!item || item.ancestors[0].id !== prop.ancestors[0].id) {
|
||||
const item = CreatureProperties.findOne(itemConsumed.itemId) as Item;
|
||||
if (!item || item.root.id !== prop.root.id) {
|
||||
throw 'The prop\'s ammo was not found on the creature';
|
||||
}
|
||||
|
||||
if (
|
||||
!itemConsumed?.quantity?.value ||
|
||||
!isFinite(itemConsumed.quantity.value)
|
||||
!isFinite(+itemConsumed.quantity.value)
|
||||
) return;
|
||||
const quantityConsumed = +itemConsumed.quantity.value;
|
||||
|
||||
let logName = item.name;
|
||||
if (itemConsumed.quantity.value > 1 || itemConsumed.quantity.value < -1) {
|
||||
if (quantityConsumed > 1 || quantityConsumed < -1) {
|
||||
logName = item.plural || logName;
|
||||
}
|
||||
if (itemConsumed.quantity.value > 0) {
|
||||
spendLog.push(logName + ': ' + itemConsumed.quantity.value);
|
||||
} else if (itemConsumed.quantity.value < 0) {
|
||||
gainLog.push(logName + ': ' + -itemConsumed.quantity.value);
|
||||
if (quantityConsumed > 0) {
|
||||
spendLog.push(logName + ': ' + quantityConsumed);
|
||||
} else if (quantityConsumed < 0) {
|
||||
gainLog.push(logName + ': ' + -quantityConsumed);
|
||||
}
|
||||
// So long as the item isn't an ancestor of the current prop apply it
|
||||
// If it was an ancestor this would be an infinite loop
|
||||
if (!hasAncestorRelationship(item, prop)) {
|
||||
ammoToApply.push({
|
||||
node: {
|
||||
doc: {
|
||||
...item,
|
||||
// Use ammo pseudo-type
|
||||
type: 'ammo',
|
||||
// Store the adjustment to be applied
|
||||
adjustment: itemConsumed.quantity.value,
|
||||
adjustment: quantityConsumed,
|
||||
},
|
||||
children: []
|
||||
});
|
||||
@@ -263,6 +275,7 @@ async function spendResources(prop, actionContext) {
|
||||
CreatureProperties.update(prop._id, {
|
||||
$inc: { usesUsed: 1 }
|
||||
}, {
|
||||
//@ts-expect-error no typings for collection 2 selector
|
||||
selector: prop
|
||||
});
|
||||
if (!prop.silent) actionContext.addLog({
|
||||
@@ -277,8 +290,9 @@ async function spendResources(prop, actionContext) {
|
||||
recalculateCalculation(attConsumed.quantity, actionContext);
|
||||
|
||||
if (!attConsumed.quantity?.value) return;
|
||||
const quantityConsumed = +attConsumed.quantity.value;
|
||||
if (!attConsumed.variableName) return;
|
||||
let stat = actionContext.scope[attConsumed.variableName];
|
||||
const stat = actionContext.scope[attConsumed.variableName];
|
||||
if (!stat) {
|
||||
spendLog.push(attConsumed.variableName + ': ' + ' not found');
|
||||
return;
|
||||
@@ -289,10 +303,10 @@ async function spendResources(prop, actionContext) {
|
||||
value: attConsumed.quantity.value,
|
||||
actionContext,
|
||||
});
|
||||
if (attConsumed.quantity.value > 0) {
|
||||
spendLog.push(stat.name + ': ' + attConsumed.quantity.value);
|
||||
} else if (attConsumed.quantity.value < 0) {
|
||||
gainLog.push(stat.name + ': ' + -attConsumed.quantity.value);
|
||||
if (quantityConsumed > 0) {
|
||||
spendLog.push(stat.name + ': ' + quantityConsumed);
|
||||
} else if (quantityConsumed < 0) {
|
||||
gainLog.push(stat.name + ': ' + -quantityConsumed);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -313,20 +327,3 @@ async function spendResources(prop, actionContext) {
|
||||
inline: true,
|
||||
});
|
||||
}
|
||||
|
||||
function hasAncestorRelationship(a, b) {
|
||||
let top, bottom;
|
||||
if (a.ancestors.length === b.ancestors.length) {
|
||||
// Can't be ancestors of one another if they have the same number of ancestors
|
||||
return false;
|
||||
} else if (a.ancestors.length > b.ancestors.length) {
|
||||
// longer ancestor list goes on the bottom
|
||||
top = b;
|
||||
bottom = a;
|
||||
} else {
|
||||
top = a;
|
||||
bottom = b;
|
||||
}
|
||||
const expectedAncestorPosition = top.ancestors.length;
|
||||
return bottom.ancestors[expectedAncestorPosition]?.id === top._id;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import recalculateCalculation from './shared/recalculateCalculation.js';
|
||||
import { damagePropertyWork } from '/imports/api/creature/creatureProperties/methods/damageProperty.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
import recalculateCalculation from './shared/recalculateCalculation';
|
||||
import { damagePropertyWork } from '/imports/api/creature/creatureProperties/methods/damageProperty';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
|
||||
export default function applyAdjustment(node, actionContext) {
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
const damageTargets = prop.target === 'self' ? [actionContext.creature] : actionContext.targets;
|
||||
|
||||
if (!prop.amount) {
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import applyProperty from '../applyProperty.js';
|
||||
import recalculateCalculation from './shared/recalculateCalculation.js';
|
||||
import rollDice from '/imports/parser/rollDice.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import getUserInput from '/imports/api/engine/actions/getUserInput';
|
||||
import applyProperty from '../applyProperty';
|
||||
import recalculateCalculation from './shared/recalculateCalculation';
|
||||
import rollDice from '/imports/parser/rollDice';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
|
||||
export default async function applyBranch(node, actionContext) {
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
const scope = actionContext.scope;
|
||||
const targets = actionContext.targets;
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
switch (prop.branchType) {
|
||||
case 'if':
|
||||
recalculateCalculation(prop.condition, actionContext);
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
import {
|
||||
setLineageOfDocs,
|
||||
renewDocIds
|
||||
} from '/imports/api/parenting/parenting.js';
|
||||
import { setDocToLastOrder } from '/imports/api/parenting/order.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import computedSchemas from '/imports/api/properties/computedPropertySchemasIndex.js';
|
||||
import applyFnToKey from '/imports/api/engine/computation/utility/applyFnToKey.js';
|
||||
renewDocIds,
|
||||
} from '/imports/api/parenting/parentingFunctions';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import computedSchemas from '/imports/api/properties/computedPropertySchemasIndex';
|
||||
import applyFnToKey from '/imports/api/engine/computation/utility/applyFnToKey';
|
||||
import { get } from 'lodash';
|
||||
import resolve, { map, toString } from '/imports/parser/resolve.js';
|
||||
import accessor from '/imports/parser/parseTree/accessor.js';
|
||||
import logErrors from './shared/logErrors.js';
|
||||
import { insertCreatureLog } from '/imports/api/creature/log/CreatureLogs.js';
|
||||
import cyrb53 from '/imports/api/engine/computation/utility/cyrb53.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX.js';
|
||||
import recalculateInlineCalculations from './shared/recalculateInlineCalculations.js';
|
||||
import resolve, { map, toString } from '/imports/parser/resolve';
|
||||
import accessor from '/imports/parser/parseTree/accessor';
|
||||
import logErrors from './shared/logErrors';
|
||||
import { insertCreatureLog } from '/imports/api/creature/log/CreatureLogs';
|
||||
import cyrb53 from '/imports/api/engine/computation/utility/cyrb53';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX';
|
||||
import recalculateInlineCalculations from './shared/recalculateInlineCalculations';
|
||||
|
||||
export default function applyBuff(node, actionContext) {
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
let buffTargets = prop.target === 'self' ? [actionContext.creature] : actionContext.targets;
|
||||
|
||||
// Mark the buff as dirty for recalculation
|
||||
@@ -26,7 +24,7 @@ export default function applyBuff(node, actionContext) {
|
||||
|
||||
// Then copy the descendants of the buff to the targets
|
||||
let propList = [prop];
|
||||
function addChildrenToPropList(children, { skipCrystalize } = {}) {
|
||||
function addChildrenToPropList(children, { skipCrystalize } = { skipCrystalize: false }) {
|
||||
children.forEach(child => {
|
||||
if (skipCrystalize) child.node._skipCrystalize = true;
|
||||
propList.push(child.node);
|
||||
@@ -41,13 +39,20 @@ export default function applyBuff(node, actionContext) {
|
||||
crystalizeVariables({ propList, actionContext });
|
||||
}
|
||||
|
||||
let oldParent = {
|
||||
id: prop.parent.id,
|
||||
collection: prop.parent.collection,
|
||||
};
|
||||
buffTargets.forEach(target => {
|
||||
const targetPropList = EJSON.clone(propList);
|
||||
// Move the properties to the target by replacing the old subtree parent and root with the '
|
||||
// target id
|
||||
renewDocIds({
|
||||
docArray: targetPropList,
|
||||
idMap: {
|
||||
[prop.parentId]: target._id,
|
||||
[prop.root.id]: target._id,
|
||||
},
|
||||
collectionMap: { [prop.root.collection]: 'creatures' }
|
||||
});
|
||||
// Apply the buff
|
||||
copyNodeListToTarget(propList, target, oldParent);
|
||||
CreatureProperties.batchInsert(targetPropList);
|
||||
|
||||
//Log the buff
|
||||
let logValue = prop.description?.value
|
||||
@@ -82,23 +87,6 @@ export default function applyBuff(node, actionContext) {
|
||||
// Don't apply the children of the buff, they get copied to the target instead
|
||||
}
|
||||
|
||||
function copyNodeListToTarget(propList, target, oldParent) {
|
||||
let ancestry = [{ collection: 'creatures', id: target._id }];
|
||||
setLineageOfDocs({
|
||||
docArray: propList,
|
||||
newAncestry: ancestry,
|
||||
oldParent,
|
||||
});
|
||||
renewDocIds({
|
||||
docArray: propList,
|
||||
});
|
||||
setDocToLastOrder({
|
||||
collection: CreatureProperties,
|
||||
doc: propList[0],
|
||||
});
|
||||
CreatureProperties.batchInsert(propList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all variables with their resolved values
|
||||
* except variables of the form `~target.thing.total` become `thing.total`
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { findLast, difference, intersection, filter } from 'lodash';
|
||||
import applyProperty from '../applyProperty.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import { getProperyAncestors, getPropertiesOfType } from '/imports/api/engine/loadCreatures.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import { softRemove } from '/imports/api/parenting/softRemove.js';
|
||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import applyProperty from '../applyProperty';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
import { getPropertyAncestors, getPropertiesOfType } from '/imports/api/engine/loadCreatures';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import { softRemove } from '/imports/api/parenting/softRemove';
|
||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
|
||||
export default function applyBuffRemover(node, actionContext) {
|
||||
// Apply triggers
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
|
||||
// Log Name
|
||||
if (prop.name && !prop.silent) {
|
||||
@@ -21,7 +21,7 @@ export default function applyBuffRemover(node, actionContext) {
|
||||
// Remove buffs
|
||||
if (prop.targetParentBuff) {
|
||||
// Remove nearest ancestor buff
|
||||
const ancestors = getProperyAncestors(actionContext.creature._id, prop._id);
|
||||
const ancestors = getPropertyAncestors(actionContext.creature._id, prop._id);
|
||||
const nearestBuff = findLast(ancestors, ancestor => ancestor.type === 'buff');
|
||||
if (!nearestBuff) {
|
||||
actionContext.addLog({
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { some, intersection, difference, remove, includes } from 'lodash';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import { insertCreatureLog } from '/imports/api/creature/log/CreatureLogs.js';
|
||||
import resolve, { Context, toString } from '/imports/parser/resolve.js';
|
||||
import logErrors from './shared/logErrors.js';
|
||||
import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation.js'
|
||||
import { damagePropertyWork } from '/imports/api/creature/creatureProperties/methods/damageProperty.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
import { insertCreatureLog } from '/imports/api/creature/log/CreatureLogs';
|
||||
import resolve, { Context, toString } from '/imports/parser/resolve';
|
||||
import logErrors from './shared/logErrors';
|
||||
import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation'
|
||||
import { damagePropertyWork } from '/imports/api/creature/creatureProperties/methods/damageProperty';
|
||||
import {
|
||||
getPropertiesOfType
|
||||
} from '/imports/api/engine/loadCreatures.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags.js';
|
||||
import applySavingThrow from '/imports/api/engine/actions/applyPropertyByType/applySavingThrow.js';
|
||||
} from '/imports/api/engine/loadCreatures';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags';
|
||||
import applySavingThrow from '/imports/api/engine/actions/applyPropertyByType/applySavingThrow';
|
||||
|
||||
export default function applyDamage(node, actionContext) {
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
const scope = actionContext.scope;
|
||||
|
||||
// Skip if there is no parse node to work with
|
||||
@@ -167,7 +167,7 @@ export default function applyDamage(node, actionContext) {
|
||||
creatureId: target._id,
|
||||
content: [{
|
||||
name,
|
||||
value: `Recieved **${damageDealt}** ${suffix}`,
|
||||
value: `Received **${damageDealt}** ${suffix}`,
|
||||
}],
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
|
||||
export default function applyFolder(node, actionContext) {
|
||||
// Apply triggers
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { getPropertyDecendants } from '/imports/api/engine/loadCreatures.js';
|
||||
import applyProperty from '../applyProperty.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import { nodeArrayToTree } from '/imports/api/parenting/nodesToTree.js';
|
||||
import { adjustQuantityWork } from '/imports/api/creature/creatureProperties/methods/adjustQuantity.js';
|
||||
import { getPropertyDescendants } from '/imports/api/engine/loadCreatures';
|
||||
import applyProperty from '../applyProperty';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
import { docsToForest as nodeArrayToTree } from '/imports/api/parenting/parentingFunctions';
|
||||
import { adjustQuantityWork } from '/imports/api/creature/creatureProperties/methods/adjustQuantity';
|
||||
|
||||
export default function applyItemAsAmmo(node, actionContext) {
|
||||
// The item node should come without children, since it is not part of the original action tree
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
// Get all the item's descendant properties
|
||||
const properties = getPropertyDecendants(actionContext.creature._id, prop._id);
|
||||
const properties = getPropertyDescendants(actionContext.creature._id, prop._id);
|
||||
properties.sort((a, b) => a.order - b.order);
|
||||
const propertyForest = nodeArrayToTree(properties);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import recalculateInlineCalculations from './shared/recalculateInlineCalculations.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import recalculateInlineCalculations from './shared/recalculateInlineCalculations';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
|
||||
export default async function applyNote(node, actionContext) {
|
||||
await applyNodeTriggers(node, 'before', actionContext);
|
||||
const prop = node.node;
|
||||
export default function applyNote(node, actionContext) {
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
const prop = node.doc
|
||||
|
||||
// Log Name, summary
|
||||
let content = { name: prop.name };
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import logErrors from './shared/logErrors.js';
|
||||
import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation.js';
|
||||
import resolve, { toString } from '/imports/parser/resolve.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
import logErrors from './shared/logErrors';
|
||||
import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation';
|
||||
import resolve, { toString } from '/imports/parser/resolve';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
|
||||
export default function applyRoll(node, actionContext) {
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
|
||||
if (prop.roll?.calculation) {
|
||||
const logValue = [];
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import rollDice from '/imports/parser/rollDice.js';
|
||||
import recalculateCalculation from './shared/recalculateCalculation.js';
|
||||
import applyProperty from '../applyProperty.js';
|
||||
import numberToSignedString from '/imports/api/utility/numberToSignedString.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import { applyUnresolvedEffects } from '/imports/api/engine/actions/doCheck.js';
|
||||
import rollDice from '/imports/parser/rollDice';
|
||||
import recalculateCalculation from './shared/recalculateCalculation';
|
||||
import applyProperty from '../applyProperty';
|
||||
import numberToSignedString from '/imports/api/utility/numberToSignedString';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
import { applyUnresolvedEffects } from '/imports/api/engine/actions/doCheck';
|
||||
|
||||
export default function applySavingThrow(node, actionContext) {
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
const originalTargets = actionContext.targets;
|
||||
|
||||
let saveTargets = prop.target === 'self' ? [actionContext.creature] : actionContext.targets;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import recalculateCalculation from './shared/recalculateCalculation.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren.js';
|
||||
import recalculateCalculation from './shared/recalculateCalculation';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
import applyChildren from '/imports/api/engine/actions/applyPropertyByType/shared/applyChildren';
|
||||
|
||||
export default function applyToggle(node, actionContext) {
|
||||
applyNodeTriggers(node, 'before', actionContext);
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
recalculateCalculation(prop.condition, actionContext);
|
||||
if (prop.condition?.value) {
|
||||
return applyChildren(node, actionContext);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import applyProperty from '/imports/api/engine/actions/applyProperty.js';
|
||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
import applyProperty from '/imports/api/engine/actions/applyProperty';
|
||||
|
||||
export default async function applyChildren(node, actionContext) {
|
||||
applyNodeTriggers(node, 'after', actionContext);
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import logErrors from './logErrors.js';
|
||||
import { Context, toPrimitiveOrString } from '/imports/parser/resolve.js';
|
||||
import logErrors from './logErrors';
|
||||
import { toPrimitiveOrString } from '/imports/parser/resolve';
|
||||
import {
|
||||
aggregateCalculationEffects,
|
||||
aggregateCalculationProficiencies,
|
||||
resolveCalculationNode,
|
||||
} from '/imports/api/engine/computation/computeComputation/computeByType/computeCalculation.js';
|
||||
} from '/imports/api/engine/computation/computeComputation/computeByType/computeCalculation';
|
||||
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
|
||||
import resolve from '/imports/parser/resolve.js';
|
||||
import { getEffectiveActionScope } from '/imports/api/engine/actions/Actions';
|
||||
import resolve from '/imports/parser/resolve';
|
||||
|
||||
// TODO move this whole file to Actions.ts
|
||||
// Redo the work of imports/api/engine/computation/computeComputation/computeByType/computeCalculation.js
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import embedInlineCalculations from '/imports/api/engine/computation/utility/embedInlineCalculations.js';
|
||||
import recalculateCalculation from './recalculateCalculation.js'
|
||||
import embedInlineCalculations from '/imports/api/engine/computation/utility/embedInlineCalculations';
|
||||
import recalculateCalculation from './recalculateCalculation'
|
||||
|
||||
export default function recalculateInlineCalculations(inlineCalcObj, action) {
|
||||
export default function recalculateInlineCalculations(inlineCalcObj, actionContext) {
|
||||
// Skip if there are no calculations
|
||||
if (!inlineCalcObj?.inlineCalculations?.length) return;
|
||||
// Recalculate each calculation with the current scope
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { triggerMatchTags } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import clean from '/imports/api/engine/computation/utility/cleanProp.testFn.js';
|
||||
import { triggerMatchTags } from '/imports/api/engine/actions/applyTriggers';
|
||||
import clean from '/imports/api/engine/computation/utility/cleanProp.testFn';
|
||||
import { assert } from 'chai';
|
||||
|
||||
export default function () {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation.js';
|
||||
import recalculateInlineCalculations from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateInlineCalculations.js';
|
||||
import { getPropertyDecendants } from '/imports/api/engine/loadCreatures.js';
|
||||
import { nodeArrayToTree } from '/imports/api/parenting/nodesToTree.js';
|
||||
import applyProperty from '/imports/api/engine/actions/applyProperty.js';
|
||||
import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation';
|
||||
import recalculateInlineCalculations from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateInlineCalculations';
|
||||
import { getPropertyDescendants } from '/imports/api/engine/loadCreatures';
|
||||
import { TreeNode, docsToForest as nodeArrayToTree } from '/imports/api/parenting/parentingFunctions';
|
||||
import applyProperty from '/imports/api/engine/actions/applyProperty';
|
||||
import { difference, intersection } from 'lodash';
|
||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags.js';
|
||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags';
|
||||
|
||||
export async function applyNodeTriggers(node, timing, actionContext) {
|
||||
const prop = node.node;
|
||||
export function applyNodeTriggers(node: TreeNode<any>, timing, actionContext) {
|
||||
const prop = node.doc;
|
||||
const type = prop.type;
|
||||
const triggers = actionContext.triggers?.doActionProperty?.[type]?.[timing];
|
||||
if (triggers) {
|
||||
@@ -68,7 +68,7 @@ export async function applyTrigger(trigger, prop, actionContext) {
|
||||
if (!trigger.silent) actionContext.addLog(content);
|
||||
|
||||
// Get all the trigger's properties and apply them
|
||||
const properties = getPropertyDecendants(actionContext.creature._id, trigger._id);
|
||||
const properties = getPropertyDescendants(actionContext.creature._id, trigger._id);
|
||||
properties.sort((a, b) => a.order - b.order);
|
||||
const propertyForest = nodeArrayToTree(properties);
|
||||
for (const node of propertyForest) {
|
||||
@@ -1,15 +1,15 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
||||
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
|
||||
import { nodeArrayToTree } from '/imports/api/parenting/nodesToTree.js';
|
||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions';
|
||||
import { docsToForest } from '/imports/api/parenting/parentingFunctions';
|
||||
import {
|
||||
getProperyAncestors, getPropertyDecendants
|
||||
} from '/imports/api/engine/loadCreatures.js';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import applyProperty from './applyProperty.js';
|
||||
import ActionContext from '/imports/api/engine/actions/ActionContext.js';
|
||||
getPropertyAncestors, getPropertyDescendants
|
||||
} from '/imports/api/engine/loadCreatures';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import applyProperty from './applyProperty';
|
||||
import ActionContext from '/imports/api/engine/actions/ActionContext';
|
||||
|
||||
const doAction = new ValidatedMethod({
|
||||
name: 'creatureProperties.doAction',
|
||||
@@ -47,10 +47,10 @@ const doAction = new ValidatedMethod({
|
||||
async run({ actionId, targetIds = [], scope, invocationId }) {
|
||||
console.log('do Action running');
|
||||
// Get action context
|
||||
let action = CreatureProperties.findOne(actionId);
|
||||
const creatureId = action.ancestors[0].id;
|
||||
|
||||
const actionContext = new ActionContext(creatureId, targetIds, this, invocationId);
|
||||
const action = CreatureProperties.findOne(actionId);
|
||||
if (!action) throw new Meteor.Error('not-found', 'The action was not found');
|
||||
const creatureId = action.root.id;
|
||||
const actionContext = new ActionContext(creatureId, targetIds, this);
|
||||
|
||||
// Check permissions
|
||||
assertEditPermission(actionContext.creature, this.userId);
|
||||
@@ -58,10 +58,10 @@ const doAction = new ValidatedMethod({
|
||||
assertEditPermission(target, this.userId);
|
||||
});
|
||||
|
||||
const ancestors = getProperyAncestors(creatureId, action._id);
|
||||
const ancestors = getPropertyAncestors(creatureId, action._id);
|
||||
ancestors.sort((a, b) => a.order - b.order);
|
||||
|
||||
const properties = getPropertyDecendants(creatureId, action._id);
|
||||
const properties = getPropertyDescendants(creatureId, action._id);
|
||||
properties.push(action);
|
||||
properties.sort((a, b) => a.order - b.order);
|
||||
|
||||
@@ -86,7 +86,7 @@ export async function doActionWork({
|
||||
}) {
|
||||
// get the docs
|
||||
const ancestorScope = getAncestorScope(ancestors);
|
||||
const propertyForest = nodeArrayToTree(properties);
|
||||
const propertyForest = docsToForest(properties);
|
||||
if (propertyForest.length !== 1) {
|
||||
throw new Meteor.Error(`The action has ${propertyForest.length} top level properties, expected 1`);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ export async function doActionWork({
|
||||
|
||||
// Assumes ancestors are in tree order already
|
||||
function getAncestorScope(ancestors) {
|
||||
let scope = {};
|
||||
const scope = {};
|
||||
ancestors.forEach(prop => {
|
||||
scope[`#${prop.type}`] = prop;
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import '/imports/api/simpleSchemaConfig.js';
|
||||
//import testTypes from './testTypes/index.js';
|
||||
import applyTriggers from '/imports/api/engine/actions/applyTriggers.testFn.js';
|
||||
import { doActionWork } from './doAction.js';
|
||||
import { CreatureLogSchema } from '/imports/api/creature/log/CreatureLogs.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import '/imports/api/simpleSchemaConfig';
|
||||
//import testTypes from './testTypes/index';
|
||||
import applyTriggers from '/imports/api/engine/actions/applyTriggers.testFn';
|
||||
import { doActionWork } from './doAction';
|
||||
import { CreatureLogSchema } from '/imports/api/creature/log/CreatureLogs';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||
|
||||
function cleanProp(prop) {
|
||||
let schema = CreatureProperties.simpleSchema(prop);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
||||
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||
import {
|
||||
getProperyAncestors, getPropertyDecendants
|
||||
} from '/imports/api/engine/loadCreatures.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
|
||||
import { damagePropertyWork } from '/imports/api/creature/creatureProperties/methods/damageProperty.js';
|
||||
import { doActionWork } from '/imports/api/engine/actions/doAction.js';
|
||||
import ActionContext from '/imports/api/engine/actions/ActionContext.js';
|
||||
getPropertyAncestors, getPropertyDescendants
|
||||
} from '/imports/api/engine/loadCreatures';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions';
|
||||
import { damagePropertyWork } from '/imports/api/creature/creatureProperties/methods/damageProperty';
|
||||
import { doActionWork } from '/imports/api/engine/actions/doAction';
|
||||
import ActionContext from '/imports/api/engine/actions/ActionContext';
|
||||
|
||||
const doAction = new ValidatedMethod({
|
||||
name: 'creatureProperties.doCastSpell',
|
||||
@@ -48,7 +48,7 @@ const doAction = new ValidatedMethod({
|
||||
run({ spellId, slotId, ritual, targetIds = [], scope = {} }) {
|
||||
// Get action context
|
||||
let spell = CreatureProperties.findOne(spellId);
|
||||
const creatureId = spell.ancestors[0].id;
|
||||
const creatureId = spell.root.id;
|
||||
const actionContext = new ActionContext(creatureId, targetIds, this);
|
||||
|
||||
// Check permissions
|
||||
@@ -57,10 +57,10 @@ const doAction = new ValidatedMethod({
|
||||
assertEditPermission(target, this.userId);
|
||||
});
|
||||
|
||||
const ancestors = getProperyAncestors(creatureId, spell._id);
|
||||
const ancestors = getPropertyAncestors(creatureId, spell._id);
|
||||
ancestors.sort((a, b) => a.order - b.order);
|
||||
|
||||
const properties = getPropertyDecendants(creatureId, spell._id);
|
||||
const properties = getPropertyDescendants(creatureId, spell._id);
|
||||
properties.push(spell);
|
||||
properties.sort((a, b) => a.order - b.order);
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
||||
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
|
||||
import rollDice from '/imports/parser/rollDice.js';
|
||||
import numberToSignedString from '/imports/api/utility/numberToSignedString.js';
|
||||
import { applyTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||
import ActionContext from '/imports/api/engine/actions/ActionContext.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions';
|
||||
import rollDice from '/imports/parser/rollDice';
|
||||
import numberToSignedString from '/imports/api/utility/numberToSignedString';
|
||||
import { applyTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||
import ActionContext from '/imports/api/engine/actions/ActionContext';
|
||||
import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation';
|
||||
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
|
||||
|
||||
@@ -26,7 +26,8 @@ const doCheck = new ValidatedMethod({
|
||||
},
|
||||
run({ propId, scope }) {
|
||||
const prop = CreatureProperties.findOne(propId);
|
||||
const creatureId = prop.ancestors[0].id;
|
||||
if (!prop) throw new Meteor.Error('not-found', 'The property was not found');
|
||||
const creatureId = prop.root.id;
|
||||
const actionContext = new ActionContext(creatureId, [creatureId], this);
|
||||
Object.assign(actionContext.scope, scope);
|
||||
actionContext.scope[`#${prop.type}`] = prop;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
import './doCastSpell.js';
|
||||
import './doCheck.js';
|
||||
import './doCastSpell';
|
||||
import './doCheck';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EJSON } from 'meteor/ejson';
|
||||
import createGraph, { Graph } from 'ngraph.graph';
|
||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags.js';
|
||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags';
|
||||
|
||||
interface CreatureProperty {
|
||||
_id: string;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import walkDown from '/imports/api/engine/computation/utility/walkdown.js';
|
||||
import { CreatureProperty } from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import walkDown from '/imports/api/engine/computation/utility/walkdown';
|
||||
import { TreeNode } from '/imports/api/parenting/parentingFunctions';
|
||||
import { isSpell } from '/imports/api/properties/Spells';
|
||||
|
||||
export default function computeInactiveStatus(node) {
|
||||
const prop = node.node;
|
||||
export default function computeInactiveStatus(node: TreeNode<CreatureProperty>): void {
|
||||
const prop = node.doc;
|
||||
if (!isActive(prop)) {
|
||||
// Mark prop inactive due to self
|
||||
prop.inactive = true;
|
||||
@@ -10,22 +13,21 @@ export default function computeInactiveStatus(node) {
|
||||
if (!childrenActive(prop)) {
|
||||
// Mark children as inactive due to ancestor
|
||||
walkDown(node.children, child => {
|
||||
child.node.inactive = true;
|
||||
child.node.deactivatedByAncestor = true;
|
||||
child.doc.inactive = true;
|
||||
child.doc.deactivatedByAncestor = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function isActive(prop) {
|
||||
function isActive(prop: CreatureProperty): boolean {
|
||||
if (prop.disabled) return false;
|
||||
switch (prop.type) {
|
||||
// Unprepared spells are inactive
|
||||
case 'spell': return !!prop.prepared || !!prop.alwaysPrepared;
|
||||
default: return true;
|
||||
if (isSpell(prop)) {
|
||||
return !!prop.prepared || !!prop.alwaysPrepared;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function childrenActive(prop) {
|
||||
function childrenActive(prop): boolean {
|
||||
// Children of disabled properties are always inactive
|
||||
if (prop.disabled) return false;
|
||||
switch (prop.type) {
|
||||
@@ -3,11 +3,11 @@
|
||||
* before `spacesLeft` can be computed
|
||||
*/
|
||||
export default function computeSlotQuantityFilled(node, dependencyGraph) {
|
||||
let slot = node.node;
|
||||
let slot = node.doc;
|
||||
if (slot.type !== 'propertySlot') return;
|
||||
slot.totalFilled = 0;
|
||||
node.children.forEach(child => {
|
||||
let childProp = child.node;
|
||||
let childProp = child.doc;
|
||||
dependencyGraph.addLink(slot._id, childProp._id, 'slotFill');
|
||||
if (
|
||||
Number.isFinite(childProp.slotQuantityFilled)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import walkDown from '/imports/api/engine/computation/utility/walkdown.js';
|
||||
import { getEffectTagTargets } from '/imports/api/engine/computation/buildComputation/linkTypeDependencies.js';
|
||||
import walkDown from '/imports/api/engine/computation/utility/walkdown';
|
||||
import { getEffectTagTargets } from '/imports/api/engine/computation/buildComputation/linkTypeDependencies';
|
||||
|
||||
export default function computeToggleDependencies(node, dependencyGraph, computation, forest) {
|
||||
const prop = node.node;
|
||||
const prop = node.doc
|
||||
// Only for toggles
|
||||
if (prop.type !== 'toggle') return;
|
||||
|
||||
@@ -11,12 +11,12 @@ export default function computeToggleDependencies(node, dependencyGraph, computa
|
||||
getEffectTagTargets(prop, computation).forEach(targetId => {
|
||||
const target = forest.nodeIndex[targetId];
|
||||
if (!target) return;
|
||||
target.node._computationDetails.toggleAncestors.push(prop);
|
||||
dependencyGraph.addLink(target.node._id, prop._id, 'toggle');
|
||||
target.doc._computationDetails.toggleAncestors.push(prop);
|
||||
dependencyGraph.addLink(target.doc._id, prop._id, 'toggle');
|
||||
walkDown(target.children, child => {
|
||||
// The child nodes depend on the toggle
|
||||
child.node._computationDetails.toggleAncestors.push(prop);
|
||||
dependencyGraph.addLink(child.node._id, prop._id, 'toggle');
|
||||
child.doc._computationDetails.toggleAncestors.push(prop);
|
||||
dependencyGraph.addLink(child.doc._id, prop._id, 'toggle');
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export default function computeToggleDependencies(node, dependencyGraph, computa
|
||||
|
||||
walkDown(node.children, child => {
|
||||
// The child nodes depend on the toggle
|
||||
child.node._computationDetails.toggleAncestors.push(prop);
|
||||
dependencyGraph.addLink(child.node._id, prop._id, 'toggle');
|
||||
child.doc._computationDetails.toggleAncestors.push(prop);
|
||||
dependencyGraph.addLink(child.doc._id, prop._id, 'toggle');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import findAncestorByType from '/imports/api/engine/computation/utility/findAncestorByType.js';
|
||||
import { traverse } from '/imports/parser/resolve.js';
|
||||
import { traverse } from '/imports/parser/resolve';
|
||||
|
||||
export default function linkCalculationDependencies(dependencyGraph, prop, { propsById }) {
|
||||
prop._computationDetails.calculations.forEach(calcObj => {
|
||||
@@ -57,3 +56,14 @@ function getAncestorProp(type, memo, prop, propsById) {
|
||||
return ancestorProp;
|
||||
}
|
||||
}
|
||||
|
||||
function findAncestorByType(prop, type, propsById) {
|
||||
if (!prop || !prop.parentId) return;
|
||||
let parentProp = prop;
|
||||
while (parentProp) {
|
||||
parentProp = propsById[parentProp.parentId];
|
||||
if (parentProp?.type === type) {
|
||||
return parentProp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export default function linkInventory(forest, dependencyGraph) {
|
||||
|
||||
while (stack.length) {
|
||||
const top = stack[stack.length - 1];
|
||||
const prop = top.node;
|
||||
const prop = top.doc;
|
||||
if (prop._computationDetails.inventoryChildrenVisited) {
|
||||
if (prop.type === 'container') containerStack.pop();
|
||||
stack.pop();
|
||||
@@ -18,7 +18,7 @@ export default function linkInventory(forest, dependencyGraph) {
|
||||
} else {
|
||||
// Add all containers to the stack when we first visit them
|
||||
if (prop.type === 'container') {
|
||||
containerStack.push(top.node);
|
||||
containerStack.push(top.doc);
|
||||
}
|
||||
// Push children onto the stack and mark this as children are visited
|
||||
stack.push(...top.children);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX.js';
|
||||
import { prettifyParseError, parse } from '/imports/parser/parser.js';
|
||||
import applyFnToKey from '/imports/api/engine/computation/utility/applyFnToKey.js';
|
||||
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX';
|
||||
import { prettifyParseError, parse } from '/imports/parser/parser';
|
||||
import applyFnToKey from '/imports/api/engine/computation/utility/applyFnToKey';
|
||||
import { get, set, unset } from 'lodash';
|
||||
import errorNode from '/imports/parser/parseTree/error.js';
|
||||
import cyrb53 from '/imports/api/engine/computation/utility/cyrb53.js';
|
||||
import errorNode from '/imports/parser/parseTree/error';
|
||||
import cyrb53 from '/imports/api/engine/computation/utility/cyrb53';
|
||||
|
||||
export default function parseCalculationFields(prop, schemas) {
|
||||
discoverInlineCalculationFields(prop, schemas);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import applyFnToKey from '../utility/applyFnToKey.js';
|
||||
import applyFnToKey from '../utility/applyFnToKey';
|
||||
import { unset } from 'lodash';
|
||||
|
||||
export default function removeSchemaFields(schemas, prop) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
import { applyNestedSetProperties } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
export default function () {
|
||||
let computation = buildComputationFromProps(testProperties);
|
||||
|
||||
const bySelf = (propId, note) => assertDeactivatedBySelf(computation, propId, note);
|
||||
const byAncestor = (propId, note) => assertDeactivatedByAncestor(computation, propId, note);
|
||||
const active = (propId, note) => assertActive(computation, propId, note);
|
||||
@@ -51,66 +53,68 @@ var testProperties = [
|
||||
clean({
|
||||
_id: 'itemUnequippedId',
|
||||
type: 'item',
|
||||
ancestors: [{ id: 'charId' }],
|
||||
parentId: 'charId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'itemUnequippedChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{ id: 'charId' }, { id: 'itemUnequippedId' }],
|
||||
parentId: 'itemUnequippedId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'itemEquippedId',
|
||||
type: 'item',
|
||||
equipped: true,
|
||||
ancestors: [{ id: 'charId' }],
|
||||
parentId: 'charId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'itemEquippedChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{ id: 'charId' }, { id: 'itemEquippedId' }],
|
||||
parentId: 'itemEquippedId',
|
||||
}),
|
||||
// Spells
|
||||
clean({
|
||||
_id: 'spellPreparedId',
|
||||
type: 'spell',
|
||||
ancestors: [{ id: 'charId' }],
|
||||
parentId: 'charId',
|
||||
prepared: true,
|
||||
}),
|
||||
clean({
|
||||
_id: 'spellPreparedChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{ id: 'charId' }, { id: 'spellPreparedId' }],
|
||||
parentId: 'spellPreparedId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'spellAlwaysPreparedId',
|
||||
type: 'spell',
|
||||
ancestors: [{ id: 'charId' }],
|
||||
parentId: 'charId',
|
||||
alwaysPrepared: true,
|
||||
}),
|
||||
clean({
|
||||
_id: 'spellAlwaysPreparedChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{ id: 'charId' }, { id: 'spellAlwaysPreparedId' }],
|
||||
parentId: 'spellAlwaysPreparedId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'spellUnpreparedId',
|
||||
type: 'spell',
|
||||
ancestors: [{ id: 'charId' }],
|
||||
parentId: 'charId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'spellUnpreparedChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{ id: 'charId' }, { id: 'spellUnpreparedId' }],
|
||||
parentId: 'spellUnpreparedId',
|
||||
}),
|
||||
// Notes
|
||||
clean({
|
||||
_id: 'NoteId',
|
||||
type: 'note',
|
||||
ancestors: [{ id: 'charId' }],
|
||||
parentId: 'charId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'NoteChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{ id: 'charId' }, { id: 'NoteId' }],
|
||||
parentId: 'NoteId',
|
||||
}),
|
||||
];
|
||||
|
||||
applyNestedSetProperties(testProperties);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
import { applyNestedSetProperties } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
@@ -13,7 +14,6 @@ var testProperties = [
|
||||
clean({
|
||||
_id: 'slotId',
|
||||
type: 'propertySlot',
|
||||
ancestors: [{ id: 'charId' }],
|
||||
}),
|
||||
// Children
|
||||
clean({
|
||||
@@ -21,16 +21,18 @@ var testProperties = [
|
||||
type: 'folder',
|
||||
slotQuantityFilled: 3,
|
||||
slotFillerType: 'item',
|
||||
ancestors: [{ id: 'charId' }, { id: 'slotId' }],
|
||||
parentId: 'slotId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'slotChildId',
|
||||
type: 'item',
|
||||
ancestors: [{ id: 'charId' }, { id: 'slotId' }],
|
||||
parentId: 'slotId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'slotGrandchildId',
|
||||
type: 'effect',
|
||||
ancestors: [{ id: 'charId' }, { id: 'slotId' }, { id: 'slotChildId' }],
|
||||
parentId: 'slotChildId',
|
||||
}),
|
||||
];
|
||||
|
||||
applyNestedSetProperties(testProperties);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
import { applyNestedSetProperties } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
const hasLink = computation.dependencyGraph.hasLink;
|
||||
assert.include(
|
||||
@@ -37,38 +38,37 @@ var testProperties = [
|
||||
_id: 'enabledToggleId',
|
||||
type: 'toggle',
|
||||
enabled: true,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'disabledToggleId',
|
||||
type: 'toggle',
|
||||
disabled: true,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'conditionToggleId',
|
||||
type: 'toggle',
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
// Children
|
||||
clean({
|
||||
_id: 'enabledToggleChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{id: 'charId'}, {id: 'enabledToggleId'}],
|
||||
parentId: 'enabledToggleId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'disabledToggleChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{id: 'charId'}, {id: 'disabledToggleId'}],
|
||||
parentId: 'disabledToggleId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'conditionToggleChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{id: 'charId'}, {id: 'conditionToggleId'}],
|
||||
parentId: 'conditionToggleId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'conditionToggleGrandChildId',
|
||||
type: 'folder',
|
||||
ancestors: [{id: 'charId'}, {id: 'conditionToggleId'}, {id: 'conditionToggleChildId'}],
|
||||
parentId: 'conditionToggleChildId',
|
||||
}),
|
||||
];
|
||||
|
||||
applyNestedSetProperties(testProperties);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
import { applyNestedSetProperties } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
const hasLink = computation.dependencyGraph.hasLink;
|
||||
const prop = (id) => computation.propsById[id];
|
||||
@@ -32,7 +33,6 @@ var testProperties = [
|
||||
clean({
|
||||
_id: 'spellListId',
|
||||
type: 'spellList',
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'childId',
|
||||
@@ -40,7 +40,7 @@ var testProperties = [
|
||||
description: {
|
||||
text: 'DC {#spellList.dc} save or suck'
|
||||
},
|
||||
ancestors: [{id: 'charId'}, {id: 'spellListId'}],
|
||||
parentId: 'spellListId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'grandchildId',
|
||||
@@ -48,7 +48,7 @@ var testProperties = [
|
||||
dc: {
|
||||
calculation: '#spellList.dc + strength + wisdom.modifier'
|
||||
},
|
||||
ancestors: [{id: 'charId'}, {id: 'spellListId'}, {id: 'childId'}],
|
||||
parentId: 'childId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'strengthId',
|
||||
@@ -57,6 +57,7 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '15 + ',
|
||||
},
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
];
|
||||
|
||||
applyNestedSetProperties(testProperties);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
import { applyNestedSetProperties } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
const hasLink = computation.dependencyGraph.hasLink;
|
||||
|
||||
@@ -62,28 +63,28 @@ var testProperties = [
|
||||
type: 'item',
|
||||
equipped: true,
|
||||
attuned: true,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'containerId',
|
||||
type: 'container',
|
||||
carried: true,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'childContainerId',
|
||||
type: 'container',
|
||||
carried: true,
|
||||
ancestors: [{id: 'charId'}, {id: 'containerId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'childItemId',
|
||||
type: 'item',
|
||||
ancestors: [{id: 'charId'}, {id: 'containerId'}],
|
||||
parentId: 'containerId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'grandchildItemId',
|
||||
type: 'item',
|
||||
ancestors: [{id: 'charId'}, {id: 'containerId'}, {id: 'childContainerId'}],
|
||||
parentId: 'childContainerId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'childItemId',
|
||||
type: 'item',
|
||||
parentId: 'containerId',
|
||||
}),
|
||||
];
|
||||
|
||||
applyNestedSetProperties(testProperties);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
const getLink = computation.dependencyGraph.hasLink;
|
||||
const getNode = computation.dependencyGraph.getNode;
|
||||
@@ -22,6 +22,5 @@ var testProperties = [
|
||||
_id: 'strengthId',
|
||||
type: 'attribute',
|
||||
variableName: 'strength',
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { nodeArrayToTree } from '/imports/api/parenting/nodesToTree.js';
|
||||
import { docsToForest } from '/imports/api/parenting/parentingFunctions';
|
||||
import { DenormalisedOnlyCreaturePropertySchema as denormSchema }
|
||||
from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import { getProperties, getCreature, getVariables } from '/imports/api/engine/loadCreatures.js';
|
||||
import computedOnlySchemas from '/imports/api/properties/computedOnlyPropertySchemasIndex.js';
|
||||
import computedSchemas from '/imports/api/properties/computedPropertySchemasIndex.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 './CreatureComputation.ts';
|
||||
import removeSchemaFields from './buildComputation/removeSchemaFields.js';
|
||||
from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import { getProperties, getCreature, getVariables } from '/imports/api/engine/loadCreatures';
|
||||
import computedOnlySchemas from '/imports/api/properties/computedOnlyPropertySchemasIndex';
|
||||
import computedSchemas from '/imports/api/properties/computedPropertySchemasIndex';
|
||||
import linkInventory from './buildComputation/linkInventory';
|
||||
import walkDown from './utility/walkdown';
|
||||
import parseCalculationFields from './buildComputation/parseCalculationFields';
|
||||
import computeInactiveStatus from './buildComputation/computeInactiveStatus';
|
||||
import computeToggleDependencies from './buildComputation/computeToggleDependencies';
|
||||
import linkCalculationDependencies from './buildComputation/linkCalculationDependencies';
|
||||
import linkTypeDependencies from './buildComputation/linkTypeDependencies';
|
||||
import computeSlotQuantityFilled from './buildComputation/computeSlotQuantityFilled';
|
||||
import CreatureComputation from './CreatureComputation';
|
||||
import removeSchemaFields from './buildComputation/removeSchemaFields';
|
||||
|
||||
/**
|
||||
* Store index of properties
|
||||
@@ -86,7 +86,7 @@ export function buildComputationFromProps(properties, creature, variables) {
|
||||
});
|
||||
|
||||
// Get all the properties as trees based on their ancestors
|
||||
let forest = nodeArrayToTree(properties);
|
||||
let forest = docsToForest(properties);
|
||||
// Walk the property trees computing things that need to be inherited
|
||||
walkDown(forest, node => {
|
||||
computeInactiveStatus(node);
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import '/imports/api/simpleSchemaConfig.js';
|
||||
import { buildComputationFromProps } from './buildCreatureComputation.js';
|
||||
import '/imports/api/simpleSchemaConfig';
|
||||
import { buildComputationFromProps } from './buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import computeInactiveStatus from './buildComputation/tests/computeInactiveStatus.testFn.js';
|
||||
import computeSlotQuantityFilled from './buildComputation/tests/computeSlotQuantityFilled.testFn.js';
|
||||
import computeToggleDependencies from './buildComputation/tests/computeToggleDependencies.testFn.js';
|
||||
import linkCalculationDependencies from './buildComputation/tests/linkCalculationDependencies.testFn.js';
|
||||
import linkInventory from './buildComputation/tests/linkInventory.testFn.js';
|
||||
import linkTypeDependencies from './buildComputation/tests/linkTypeDependencies.testFn.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import computeInactiveStatus from './buildComputation/tests/computeInactiveStatus.testFn';
|
||||
import computeSlotQuantityFilled from './buildComputation/tests/computeSlotQuantityFilled.testFn';
|
||||
import computeToggleDependencies from './buildComputation/tests/computeToggleDependencies.testFn';
|
||||
import linkCalculationDependencies from './buildComputation/tests/linkCalculationDependencies.testFn';
|
||||
import linkInventory from './buildComputation/tests/linkInventory.testFn';
|
||||
import linkTypeDependencies from './buildComputation/tests/linkTypeDependencies.testFn';
|
||||
|
||||
describe('buildComputation', function(){
|
||||
it('Builds something at all', function(){
|
||||
describe('buildComputation', function () {
|
||||
it('Builds something at all', function () {
|
||||
let computation = buildComputationFromProps(testProperties);
|
||||
assert.exists(computation);
|
||||
});
|
||||
@@ -37,7 +37,7 @@ var testProperties = [
|
||||
}),
|
||||
];
|
||||
|
||||
function clean(prop){
|
||||
function clean(prop) {
|
||||
let schema = CreatureProperties.simpleSchema(prop);
|
||||
return schema.clean(prop);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import _variable from './computeByType/computeVariable.js';
|
||||
import action from './computeByType/computeAction.js';
|
||||
import attribute from './computeByType/computeAttribute.js';
|
||||
import skill from './computeByType/computeSkill.js';
|
||||
import pointBuy from './computeByType/computePointBuy.js';
|
||||
import propertySlot from './computeByType/computeSlot.js';
|
||||
import container from './computeByType/computeContainer.js';
|
||||
import spellList from './computeByType/computeSpellList.js';
|
||||
import toggle from './computeByType/computeToggle.js';
|
||||
import trigger from './computeByType/computeTrigger.js'
|
||||
import _calculation from './computeByType/computeCalculation.js';
|
||||
import _variable from './computeByType/computeVariable';
|
||||
import action from './computeByType/computeAction';
|
||||
import attribute from './computeByType/computeAttribute';
|
||||
import skill from './computeByType/computeSkill';
|
||||
import pointBuy from './computeByType/computePointBuy';
|
||||
import propertySlot from './computeByType/computeSlot';
|
||||
import container from './computeByType/computeContainer';
|
||||
import spellList from './computeByType/computeSpellList';
|
||||
import toggle from './computeByType/computeToggle';
|
||||
import _calculation from './computeByType/computeCalculation';
|
||||
|
||||
export default Object.freeze({
|
||||
_variable,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import call from '/imports/parser/parseTree/call.js';
|
||||
import constant from '/imports/parser/parseTree/constant.js';
|
||||
import operator from '/imports/parser/parseTree/operator.js';
|
||||
import parenthesis from '/imports/parser/parseTree/parenthesis.js';
|
||||
import resolve, { toPrimitiveOrString } from '/imports/parser/resolve.js';
|
||||
import call from '/imports/parser/parseTree/call';
|
||||
import constant from '/imports/parser/parseTree/constant';
|
||||
import operator from '/imports/parser/parseTree/operator';
|
||||
import parenthesis from '/imports/parser/parseTree/parenthesis';
|
||||
import resolve, { toPrimitiveOrString } from '/imports/parser/resolve';
|
||||
|
||||
export default function computeCalculation(computation, node) {
|
||||
const calcObj = node.data;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import aggregate from './computeVariable/aggregate/index.js';
|
||||
import { safeStrip } from '/imports/api/engine/computation/utility/stripFloatingPointOddities.js';
|
||||
import aggregate from './computeVariable/aggregate/index';
|
||||
import { safeStrip } from '/imports/api/engine/computation/utility/stripFloatingPointOddities';
|
||||
|
||||
export default function computeContainer(computation, node) {
|
||||
if (!node.data) node.data = {};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { has } from 'lodash';
|
||||
import resolveCalculationNode from '/imports/api/engine/computation/computeComputation/computeByType/computeCalculation.js';
|
||||
import { resolveCalculationNode } from '/imports/api/engine/computation/computeComputation/computeByType/computeCalculation';
|
||||
|
||||
export default function computePointBuy(computation, node) {
|
||||
const prop = node.data;
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
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 computeVariableAsToggle from './computeVariable/computeVariableAsToggle.js';
|
||||
import computeImplicitVariable from './computeVariable/computeImplicitVariable.js';
|
||||
import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js';
|
||||
import { computedInlineCalculationField } from '/imports/api/properties/subSchemas/inlineCalculationField';
|
||||
import aggregate from './computeVariable/aggregate/index';
|
||||
import computeVariableAsAttribute from './computeVariable/computeVariableAsAttribute';
|
||||
import computeVariableAsSkill from './computeVariable/computeVariableAsSkill';
|
||||
import computeVariableAsConstant from './computeVariable/computeVariableAsConstant';
|
||||
import computeVariableAsClass from './computeVariable/computeVariableAsClass';
|
||||
import computeVariableAsToggle from './computeVariable/computeVariableAsToggle';
|
||||
import computeImplicitVariable from './computeVariable/computeImplicitVariable';
|
||||
import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX';
|
||||
|
||||
export default function computeVariable(computation, node) {
|
||||
const scope = computation.scope;
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function aggregateDefinition({ node, linkedNode, link }) {
|
||||
!definingProp ||
|
||||
prop.type !== 'pointBuyRow' && (
|
||||
definingProp.type === 'pointBuyRow' ||
|
||||
prop.order > definingProp.order
|
||||
prop.left > definingProp.left
|
||||
)
|
||||
) {
|
||||
// override the current defining prop
|
||||
|
||||
@@ -10,7 +10,7 @@ export default function aggregateEventDefinition({ node, linkedNode, link }) {
|
||||
// Find the last defining event
|
||||
if (
|
||||
!definingEvent ||
|
||||
prop.order > definingEvent.order
|
||||
prop.left > definingEvent.left
|
||||
) {
|
||||
// override the current defining prop
|
||||
if (definingEvent) definingEvent.overridden = true;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import definition from './aggregateDefinition.js';
|
||||
import damageMultiplier from './aggregateDamageMultiplier.js';
|
||||
import effect from './aggregateEffect.js';
|
||||
import eventDefinition from './aggregateEventDefinition.js';
|
||||
import proficiency from './aggregateProficiency.js';
|
||||
import classLevel from './aggregateClassLevel.js';
|
||||
import inventory from './aggregateInventory.js';
|
||||
import definition from './aggregateDefinition';
|
||||
import damageMultiplier from './aggregateDamageMultiplier';
|
||||
import effect from './aggregateEffect';
|
||||
import eventDefinition from './aggregateEventDefinition';
|
||||
import proficiency from './aggregateProficiency';
|
||||
import classLevel from './aggregateClassLevel';
|
||||
import inventory from './aggregateInventory';
|
||||
|
||||
export default Object.freeze({
|
||||
classLevel,
|
||||
|
||||
@@ -1,61 +1,61 @@
|
||||
import getAggregatorResult from './getAggregatorResult.js';
|
||||
import getAggregatorResult from './getAggregatorResult';
|
||||
|
||||
/*
|
||||
* Variables with effects, proficiencies, or damage multipliers but no defining
|
||||
* properties are added to the scope as implicit variables
|
||||
*/
|
||||
export default function computeImplicitVariable(node){
|
||||
const prop = {};
|
||||
export default function computeImplicitVariable(node) {
|
||||
const prop = {};
|
||||
|
||||
// Combine damage multipliers
|
||||
if (node.data.immunity){
|
||||
if (node.data.immunity) {
|
||||
prop.immunity = node.data.immunity;
|
||||
prop.immunities = node.data.immunities;
|
||||
}
|
||||
if (node.data.resistance){
|
||||
if (node.data.resistance) {
|
||||
prop.resistance = node.data.resistance;
|
||||
prop.resistances = node.data.resistances;
|
||||
}
|
||||
if (node.data.vulnerability){
|
||||
if (node.data.vulnerability) {
|
||||
prop.vulnerability = node.data.vulnerability;
|
||||
prop.vulnerabilities = node.data.vulnerabilities;
|
||||
}
|
||||
|
||||
const result = getAggregatorResult(node);
|
||||
if (result !== undefined){
|
||||
prop.value = result;
|
||||
}
|
||||
if (node.data.proficiency !== undefined){
|
||||
prop.proficiency = node.data.proficiency;
|
||||
}
|
||||
const result = getAggregatorResult(node);
|
||||
if (result !== undefined) {
|
||||
prop.value = result;
|
||||
}
|
||||
if (node.data.proficiency !== undefined) {
|
||||
prop.proficiency = node.data.proficiency;
|
||||
}
|
||||
|
||||
// denormalise class level aggregator
|
||||
let classLevelAgg = node.data.classLevelAggregator;
|
||||
if (classLevelAgg){
|
||||
prop.level = classLevelAgg.level;
|
||||
}
|
||||
// denormalise class level aggregator
|
||||
let classLevelAgg = node.data.classLevelAggregator;
|
||||
if (classLevelAgg) {
|
||||
prop.level = classLevelAgg.level;
|
||||
}
|
||||
|
||||
// denormalise the effect aggregator fields
|
||||
const aggregator = node.data.effectAggregator;
|
||||
if (aggregator){
|
||||
if (aggregator.advantage && !aggregator.disadvantage){
|
||||
prop.advantage = 1;
|
||||
} else if (aggregator.disadvantage && !aggregator.advantage){
|
||||
prop.advantage = -1;
|
||||
} else {
|
||||
prop.advantage = 0;
|
||||
}
|
||||
// Passive bonus
|
||||
prop.passiveBonus = aggregator.passiveAdd;
|
||||
// conditional benefits
|
||||
prop.conditionalBenefits = aggregator.conditional;
|
||||
// Roll bonuses
|
||||
prop.rollBonus = aggregator.rollBonus;
|
||||
// Forced to fail
|
||||
prop.fail = aggregator.fail;
|
||||
// Rollbonus
|
||||
prop.rollBonuses = aggregator.rollBonus;
|
||||
}
|
||||
// denormalise the effect aggregator fields
|
||||
const aggregator = node.data.effectAggregator;
|
||||
if (aggregator) {
|
||||
if (aggregator.advantage && !aggregator.disadvantage) {
|
||||
prop.advantage = 1;
|
||||
} else if (aggregator.disadvantage && !aggregator.advantage) {
|
||||
prop.advantage = -1;
|
||||
} else {
|
||||
prop.advantage = 0;
|
||||
}
|
||||
// Passive bonus
|
||||
prop.passiveBonus = aggregator.passiveAdd;
|
||||
// conditional benefits
|
||||
prop.conditionalBenefits = aggregator.conditional;
|
||||
// Roll bonuses
|
||||
prop.rollBonus = aggregator.rollBonus;
|
||||
// Forced to fail
|
||||
prop.fail = aggregator.fail;
|
||||
// Rollbonus
|
||||
prop.rollBonuses = aggregator.rollBonus;
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import getAggregatorResult from './getAggregatorResult.js';
|
||||
import getAggregatorResult from './getAggregatorResult';
|
||||
|
||||
export default function computeVariableAsAttribute(computation, node, prop) {
|
||||
let result = getAggregatorResult(node) || 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { parse } from '/imports/parser/parser.js';
|
||||
import { parse } from '/imports/parser/parser';
|
||||
|
||||
export default function computeVariableAsConstant(computation, node, prop){
|
||||
export default function computeVariableAsConstant(computation, node, prop) {
|
||||
let string = prop.calculation;
|
||||
if (!string) return;
|
||||
let parseNode;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import aggregate from './aggregate/index.js';
|
||||
import aggregate from './aggregate/index';
|
||||
|
||||
export default function computeVariableAsSkill(computation, node, prop) {
|
||||
// Skills are based on some ability Modifier
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import getAggregatorResult from './getAggregatorResult.js';
|
||||
import getAggregatorResult from './getAggregatorResult';
|
||||
|
||||
export default function computeVariableAsToggle(computation, node, prop){
|
||||
export default function computeVariableAsToggle(computation, node, prop) {
|
||||
let result = getAggregatorResult(node, prop) || 0;
|
||||
|
||||
prop.value = !!result || !!prop.enabled || !!prop.condition?.value;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import stripFloatingPointOddities from '/imports/api/engine/computation/utility/stripFloatingPointOddities.js';
|
||||
import stripFloatingPointOddities from '/imports/api/engine/computation/utility/stripFloatingPointOddities';
|
||||
|
||||
export default function getAggregatorResult(node) {
|
||||
// Work out the base value as the greater of the deining stat value
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation.js';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
computeCreatureComputation(computation);
|
||||
|
||||
@@ -33,7 +33,6 @@ var testProperties = [
|
||||
clean({
|
||||
_id: 'actionId',
|
||||
type: 'action',
|
||||
ancestors: [{id: 'charId'}],
|
||||
summary: {
|
||||
text: 'test summary {1 + 2} without referencing anything {3 + 4}',
|
||||
},
|
||||
@@ -61,14 +60,17 @@ var testProperties = [
|
||||
calculation: 'nonExistantProperty + 7',
|
||||
},
|
||||
usesUsed: 5,
|
||||
left: 1,
|
||||
right: 2,
|
||||
}),
|
||||
clean({
|
||||
_id: 'rolledDescriptionId',
|
||||
type: 'action',
|
||||
ancestors: [{id: 'charId'}],
|
||||
summary: {
|
||||
text: 'test roll gets compiled {4 + (2 + 2)} properly',
|
||||
},
|
||||
left: 3,
|
||||
right: 4,
|
||||
}),
|
||||
clean({
|
||||
_id: 'numItemsConumedId',
|
||||
@@ -77,6 +79,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '3',
|
||||
},
|
||||
left: 5,
|
||||
right: 6,
|
||||
}),
|
||||
clean({
|
||||
_id: 'numResourceConumedId',
|
||||
@@ -85,6 +89,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '4',
|
||||
},
|
||||
left: 7,
|
||||
right: 8,
|
||||
}),
|
||||
clean({
|
||||
_id: 'resourceVarId',
|
||||
@@ -94,6 +100,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '9',
|
||||
},
|
||||
left: 9,
|
||||
right: 10,
|
||||
}),
|
||||
clean({
|
||||
_id: 'inlineRefResourceId',
|
||||
@@ -102,6 +110,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '1 + 5',
|
||||
},
|
||||
left: 11,
|
||||
right: 12,
|
||||
}),
|
||||
clean({
|
||||
_id: 'arrowId',
|
||||
@@ -110,5 +120,7 @@ var testProperties = [
|
||||
quantity: 27,
|
||||
icon: 'itemIcon',
|
||||
color: 'itemColor',
|
||||
left: 13,
|
||||
right: 14,
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation.js';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
@@ -27,6 +27,8 @@ var testProperties = [
|
||||
_id: 'emptyId',
|
||||
type: 'attribute',
|
||||
attributeType: 'ability',
|
||||
left: 1,
|
||||
right: 2,
|
||||
}),
|
||||
clean({
|
||||
_id: 'noVariableNameId',
|
||||
@@ -35,6 +37,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '8'
|
||||
},
|
||||
left: 3,
|
||||
right: 4,
|
||||
}),
|
||||
clean({
|
||||
_id: 'strengthId',
|
||||
@@ -44,6 +48,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '12'
|
||||
},
|
||||
left: 5,
|
||||
right: 6,
|
||||
}),
|
||||
clean({
|
||||
_id: 'overriddenDexId',
|
||||
@@ -54,6 +60,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '15'
|
||||
},
|
||||
left: 7,
|
||||
right: 8,
|
||||
}),
|
||||
clean({
|
||||
_id: 'dexterityId',
|
||||
@@ -64,6 +72,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '15'
|
||||
},
|
||||
left: 9,
|
||||
right: 10,
|
||||
}),
|
||||
clean({
|
||||
_id: 'constitutionId',
|
||||
@@ -73,6 +83,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '21'
|
||||
},
|
||||
left: 11,
|
||||
right: 12,
|
||||
}),
|
||||
clean({
|
||||
_id: 'referencesDexId',
|
||||
@@ -81,6 +93,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: 'dexterity.modifier + 2'
|
||||
},
|
||||
left: 13,
|
||||
right: 14,
|
||||
}),
|
||||
clean({
|
||||
_id: 'hitDiceId',
|
||||
@@ -91,6 +105,8 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '4'
|
||||
},
|
||||
left: 15,
|
||||
right: 16,
|
||||
}),
|
||||
clean({
|
||||
_id: 'parseErrorId',
|
||||
@@ -100,5 +116,7 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: '12 +'
|
||||
},
|
||||
left: 17,
|
||||
right: 18,
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation.js';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
import { applyNestedSetProperties } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
computeCreatureComputation(computation);
|
||||
const scope = id => computation.scope[id];
|
||||
@@ -20,41 +21,37 @@ var testProperties = [
|
||||
type: 'class',
|
||||
variableName: 'wizard',
|
||||
classType: 'startingClass',
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'rangerId',
|
||||
type: 'class',
|
||||
variableName: 'ranger',
|
||||
classType: 'multiClass',
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'wiz1Id',
|
||||
type: 'classLevel',
|
||||
variableName: 'wizard',
|
||||
level: 1,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'wiz2Id',
|
||||
type: 'classLevel',
|
||||
variableName: 'wizard',
|
||||
level: 2,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'wiz4Id',
|
||||
type: 'classLevel',
|
||||
variableName: 'wizard',
|
||||
level: 4,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'rang1Id',
|
||||
type: 'classLevel',
|
||||
variableName: 'ranger',
|
||||
level: 1,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
];
|
||||
|
||||
applyNestedSetProperties(testProperties);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation.js';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
import { applyNestedSetProperties } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
computeCreatureComputation(computation);
|
||||
const prop = id => computation.propsById[id];
|
||||
@@ -23,6 +24,7 @@ var testProperties = [
|
||||
baseValue: {
|
||||
calculation: 'arrayConstant[3]',
|
||||
},
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
];
|
||||
|
||||
applyNestedSetProperties(testProperties);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation.js';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
computeCreatureComputation(computation);
|
||||
const scope = id => computation.scope[id];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation.js';
|
||||
import { propsFromForest } from '/imports/api/properties/tests/propTestBuilder.testFn.js';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation.js';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
import { applyNestedSetProperties, compareOrder } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
computeCreatureComputation(computation);
|
||||
const prop = id => computation.propsById[id];
|
||||
@@ -13,9 +14,8 @@ export default function(){
|
||||
assert.equal(scope('valueEquipment'), 3);
|
||||
|
||||
assert.equal(scope('itemsAttuned'), 1);
|
||||
|
||||
assert.equal(prop('childContainerId').carriedWeight, 69);
|
||||
assert.equal(prop('childContainerId').contentsWeight, 69);
|
||||
assert.equal(prop('childContainerId').carriedWeight, 69, 'Calculates container carried weight correctly');
|
||||
assert.equal(prop('childContainerId').contentsWeight, 69, 'Calculates container contents weight correctly');
|
||||
|
||||
assert.equal(scope('weightCarried'), 104);
|
||||
assert.equal(scope('valueCarried'), 129);
|
||||
@@ -32,7 +32,6 @@ var testProperties = [
|
||||
attuned: true,
|
||||
weight: 2,
|
||||
value: 3,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'containerId',
|
||||
@@ -40,22 +39,13 @@ var testProperties = [
|
||||
carried: true,
|
||||
weight: 5,
|
||||
value: 7,
|
||||
ancestors: [{id: 'charId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'childContainerId',
|
||||
type: 'container',
|
||||
carried: true,
|
||||
weight: 11,
|
||||
value: 13,
|
||||
ancestors: [{id: 'charId'}, {id: 'containerId'}],
|
||||
}),
|
||||
clean({
|
||||
_id: 'childItemId',
|
||||
type: 'item',
|
||||
weight: 17,
|
||||
value: 19,
|
||||
ancestors: [{id: 'charId'}, {id: 'containerId'}],
|
||||
parentId: 'containerId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'grandchildItemId',
|
||||
@@ -63,6 +53,16 @@ var testProperties = [
|
||||
weight: 23, // 69 total
|
||||
value: 29, // 87 total
|
||||
quantity: 3,
|
||||
ancestors: [{id: 'charId'}, {id: 'containerId'}, {id: 'childContainerId'}],
|
||||
parentId: 'childContainerId',
|
||||
}),
|
||||
clean({
|
||||
_id: 'childContainerId',
|
||||
type: 'container',
|
||||
carried: true,
|
||||
weight: 11,
|
||||
value: 13,
|
||||
parentId: 'containerId',
|
||||
}),
|
||||
];
|
||||
applyNestedSetProperties(testProperties);
|
||||
testProperties.sort(compareOrder);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation.js';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
import { applyNestedSetProperties, compareOrder } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
const hasLink = computation.dependencyGraph.hasLink;
|
||||
computeCreatureComputation(computation);
|
||||
const prop = id => computation.propsById[id];
|
||||
assert.equal(
|
||||
@@ -38,7 +40,6 @@ var testProperties = [
|
||||
clean({
|
||||
_id: 'actionId',
|
||||
type: 'action',
|
||||
ancestors: [{ id: 'charId' }],
|
||||
attackRoll: {
|
||||
calculation: 'strength.modifier',
|
||||
},
|
||||
@@ -48,7 +49,6 @@ var testProperties = [
|
||||
_id: 'profBonusId',
|
||||
type: 'attribute',
|
||||
variableName: 'proficiencyBonus',
|
||||
ancestors: [{ id: 'charId' }],
|
||||
baseValue: {
|
||||
calculation: '13'
|
||||
},
|
||||
@@ -62,3 +62,5 @@ var testProperties = [
|
||||
targetTags: ['martial weapon']
|
||||
}),
|
||||
];
|
||||
applyNestedSetProperties(testProperties);
|
||||
testProperties.sort(compareOrder);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation.js';
|
||||
import { buildComputationFromProps } from '/imports/api/engine/computation/buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation.js';
|
||||
import clean from '../../utility/cleanProp.testFn.js';
|
||||
import computeCreatureComputation from '../../computeCreatureComputation';
|
||||
import clean from '../../utility/cleanProp.testFn';
|
||||
|
||||
export default function(){
|
||||
export default function () {
|
||||
const computation = buildComputationFromProps(testProperties);
|
||||
computeCreatureComputation(computation);
|
||||
const prop = id => computation.propsById[id];
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import computeAction from './computeAction.testFn.js';
|
||||
import computeAttribute from './computeAttribute.testFn.js';
|
||||
import computeCalculations from './computeCalculations.testFn.js';
|
||||
import computeClasses from './computeClasses.testFn.js';
|
||||
import computeConstants from './computeConstants.testFn.js';
|
||||
import computeInventory from './computeInventory.testFn.js';
|
||||
import computeDamageMultipliers from './computeDamageMultipliers.testFn.js';
|
||||
import computeEffects from './computeEffects.testFn.js';
|
||||
import computeSkills from './computeSkills.testFn.js';
|
||||
import computePointBuys from './computePointBuys.testFn.js';
|
||||
import computeProficiencies from './computeProficiencies.testFn.js';
|
||||
import computeAction from './computeAction.testFn';
|
||||
import computeAttribute from './computeAttribute.testFn';
|
||||
import computeClasses from './computeClasses.testFn';
|
||||
import computeConstants from './computeConstants.testFn';
|
||||
import computeInventory from './computeInventory.testFn';
|
||||
import computeDamageMultipliers from './computeDamageMultipliers.testFn';
|
||||
import computeEffects from './computeEffects.testFn';
|
||||
import computeSkills from './computeSkills.testFn';
|
||||
import computeProficiencies from './computeProficiencies.testFn';
|
||||
|
||||
export default [{
|
||||
text: 'Computes actions',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import computeToggles from '/imports/api/engine/computation/computeComputation/computeToggles.js';
|
||||
import computeByType from '/imports/api/engine/computation/computeComputation/computeByType.js';
|
||||
import embedInlineCalculations from './utility/embedInlineCalculations.js';
|
||||
import { removeEmptyCalculations } from './buildComputation/parseCalculationFields.js';
|
||||
import computeToggles from '/imports/api/engine/computation/computeComputation/computeToggles';
|
||||
import computeByType from '/imports/api/engine/computation/computeComputation/computeByType';
|
||||
import embedInlineCalculations from './utility/embedInlineCalculations';
|
||||
import { removeEmptyCalculations } from './buildComputation/parseCalculationFields';
|
||||
import path from 'ngraph.path';
|
||||
|
||||
export default function computeCreatureComputation(computation) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import computeCreatureComputation from './computeCreatureComputation.js';
|
||||
import { buildComputationFromProps } from './buildCreatureComputation.js';
|
||||
import computeCreatureComputation from './computeCreatureComputation';
|
||||
import { buildComputationFromProps } from './buildCreatureComputation';
|
||||
import { assert } from 'chai';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import computeTests from './computeComputation/tests/index.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import computeTests from './computeComputation/tests/index';
|
||||
|
||||
describe('Compute compuation', function(){
|
||||
it('Computes something at all', function(){
|
||||
describe('Compute compuation', function () {
|
||||
it('Computes something at all', function () {
|
||||
let computation = buildComputationFromProps(testProperties);
|
||||
computeCreatureComputation(computation);
|
||||
assert.exists(computation);
|
||||
@@ -28,7 +28,7 @@ var testProperties = [
|
||||
}),
|
||||
];
|
||||
|
||||
function clean(prop){
|
||||
function clean(prop) {
|
||||
let schema = CreatureProperties.simpleSchema(prop);
|
||||
return schema.clean(prop);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import applyFnToKey from './applyFnToKey.js';
|
||||
import applyFnToKey from './applyFnToKey';
|
||||
import { assert } from 'chai';
|
||||
import { get } from 'lodash';
|
||||
|
||||
describe('apply function to key', function(){
|
||||
it('uses a basic key correctly', function(){
|
||||
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);
|
||||
@@ -11,7 +11,7 @@ describe('apply function to key', function(){
|
||||
assert.equal(get(doc, key), 'foxy');
|
||||
});
|
||||
});
|
||||
it('uses a single nested key correctly', function(){
|
||||
it('uses a single nested key correctly', function () {
|
||||
let obj = getStartingObject();
|
||||
let foxSounds = [];
|
||||
applyFnToKey(obj, 'fox.sound.$', (doc, key) => {
|
||||
@@ -21,7 +21,7 @@ describe('apply function to key', function(){
|
||||
assert.include(foxSounds, 'tjoef');
|
||||
assert.include(foxSounds, 'kek');
|
||||
});
|
||||
it('uses a double nested key correctly', function(){
|
||||
it('uses a double nested key correctly', function () {
|
||||
let obj = getStartingObject();
|
||||
let birdSounds = [];
|
||||
applyFnToKey(obj, 'birds.$.sound.$', (doc, key) => {
|
||||
@@ -33,7 +33,7 @@ describe('apply function to key', function(){
|
||||
});
|
||||
});
|
||||
|
||||
function getStartingObject(){
|
||||
function getStartingObject() {
|
||||
return {
|
||||
fox: {
|
||||
name: 'foxy',
|
||||
@@ -48,7 +48,7 @@ function getStartingObject(){
|
||||
sound: [
|
||||
'koer',
|
||||
]
|
||||
},{
|
||||
}, {
|
||||
name: 'parrot',
|
||||
sound: [
|
||||
'hello',
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
|
||||
export default function cleanProp(prop){
|
||||
export default function cleanProp(prop) {
|
||||
if (!prop.root) {
|
||||
prop.root = { collection: 'creatures', id: 'testCreature' }
|
||||
}
|
||||
let schema = CreatureProperties.simpleSchema(prop);
|
||||
return schema.clean(prop);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX.js';
|
||||
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX';
|
||||
|
||||
export default function embedInlineCalculations(inlineCalcObj){
|
||||
export default function embedInlineCalculations(inlineCalcObj) {
|
||||
const string = inlineCalcObj.text;
|
||||
const calculations = inlineCalcObj.inlineCalculations;
|
||||
if (!string || !calculations) return;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
export default function findAncestorByType(prop, type, propsById){
|
||||
if (!prop || !prop.ancestors) return;
|
||||
let ancestor;
|
||||
for (let i = prop.ancestors.length - 1; i >= 0; i--){
|
||||
ancestor = propsById[prop.ancestors[i].id];
|
||||
if (ancestor && ancestor.type === type){
|
||||
return ancestor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Meteor } from 'meteor/meteor'
|
||||
import { EJSON } from 'meteor/ejson';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import propertySchemasIndex from '/imports/api/properties/computedOnlyPropertySchemasIndex.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import propertySchemasIndex from '/imports/api/properties/computedOnlyPropertySchemasIndex';
|
||||
|
||||
export default function writeAlteredProperties(computation) {
|
||||
let bulkWriteOperations = [];
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||
|
||||
export default function(creatureId, errors = []){
|
||||
if (errors.length){
|
||||
Creatures.update(creatureId, {$set: {computeErrors: errors}});
|
||||
export default function (creatureId, errors = []) {
|
||||
if (errors.length) {
|
||||
Creatures.update(creatureId, { $set: { computeErrors: errors } });
|
||||
} else {
|
||||
Creatures.update(creatureId, {$unset: {computeErrors: 1}});
|
||||
Creatures.update(creatureId, { $unset: { computeErrors: 1 } });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||
import { EJSON } from 'meteor/ejson';
|
||||
|
||||
export default function writeScope(creatureId, computation) {
|
||||
@@ -27,7 +27,6 @@ export default function writeScope(creatureId, computation) {
|
||||
|
||||
// Remove large properties that aren't likely to be accessed
|
||||
delete scope[key].parent;
|
||||
delete scope[key].ancestors;
|
||||
|
||||
// Remove empty keys
|
||||
for (const subKey in scope[key]) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import buildCreatureComputation from './computation/buildCreatureComputation.js';
|
||||
import computeCreatureComputation from './computation/computeCreatureComputation.js';
|
||||
import writeAlteredProperties from './computation/writeComputation/writeAlteredProperties.js';
|
||||
import writeScope from './computation/writeComputation/writeScope.js';
|
||||
import writeErrors from './computation/writeComputation/writeErrors.js';
|
||||
import buildCreatureComputation from './computation/buildCreatureComputation';
|
||||
import computeCreatureComputation from './computation/computeCreatureComputation';
|
||||
import writeAlteredProperties from './computation/writeComputation/writeAlteredProperties';
|
||||
import writeScope from './computation/writeComputation/writeScope';
|
||||
import writeErrors from './computation/writeComputation/writeErrors';
|
||||
|
||||
export default function computeCreature(creatureId) {
|
||||
if (Meteor.isClient) return;
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import { debounce } from 'lodash';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import CreatureProperties, { CreatureProperty } from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import computeCreature from './computeCreature';
|
||||
import { getFilter } from '/imports/api/parenting/parentingFunctions';
|
||||
|
||||
const COMPUTE_DEBOUNCE_TIME = 100; // ms
|
||||
export const loadedCreatures = new Map(); // creatureId => {creature, properties, etc.}
|
||||
export const loadedCreatures: Map<string, LoadedCreature> = new Map(); // creatureId => {creature, properties, etc.}
|
||||
// TODO: migrate to nested sets
|
||||
|
||||
export function loadCreature(creatureId, subscription) {
|
||||
export function loadCreature(creatureId: string, subscription: Tracker.Computation) {
|
||||
if (!creatureId) throw 'creatureId is required';
|
||||
let creature = loadedCreatures.get(creatureId);
|
||||
if (loadedCreatures.has(creatureId)) {
|
||||
if (creature) {
|
||||
creature.subs.add(subscription);
|
||||
} else {
|
||||
creature = new LoadedCreature(subscription, creatureId);
|
||||
@@ -32,75 +34,67 @@ function unloadCreature(creatureId, subscription) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getSingleProperty(creatureId, propertyId) {
|
||||
if (loadedCreatures.has(creatureId)) {
|
||||
const creature = loadedCreatures.get(creatureId);
|
||||
const property = creature.properties.get(propertyId);
|
||||
const cloneProp = EJSON.clone(property);
|
||||
return cloneProp;
|
||||
export function getSingleProperty(creatureId: string, propertyId: string) {
|
||||
const creature = loadedCreatures.get(creatureId)
|
||||
const property = creature?.properties.get(propertyId);
|
||||
if (property) {
|
||||
return EJSON.clone(property);
|
||||
}
|
||||
// console.time(`Cache miss on creature properties: ${creatureId}`)
|
||||
const prop = CreatureProperties.findOne({
|
||||
_id: propertyId,
|
||||
'ancestors.id': creatureId,
|
||||
'root.id': creatureId,
|
||||
'removed': { $ne: true },
|
||||
}, {
|
||||
sort: { order: 1 },
|
||||
});
|
||||
// console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
|
||||
return prop;
|
||||
}
|
||||
|
||||
export function getProperties(creatureId) {
|
||||
if (loadedCreatures.has(creatureId)) {
|
||||
const creature = loadedCreatures.get(creatureId);
|
||||
const creature = loadedCreatures.get(creatureId);
|
||||
if (creature) {
|
||||
const props = Array.from(creature.properties.values());
|
||||
const cloneProps = EJSON.clone(props);
|
||||
return cloneProps
|
||||
return EJSON.clone(props);
|
||||
}
|
||||
// console.time(`Cache miss on creature properties: ${creatureId}`)
|
||||
const props = CreatureProperties.find({
|
||||
'ancestors.id': creatureId,
|
||||
'root.id': creatureId,
|
||||
'removed': { $ne: true },
|
||||
}, {
|
||||
sort: { order: 1 },
|
||||
sort: { left: 1 },
|
||||
}).fetch();
|
||||
// console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
|
||||
return props;
|
||||
}
|
||||
|
||||
export function getPropertiesOfType(creatureId, propType) {
|
||||
if (loadedCreatures.has(creatureId)) {
|
||||
const creature = loadedCreatures.get(creatureId);
|
||||
const props = []
|
||||
const creature = loadedCreatures.get(creatureId);
|
||||
if (creature) {
|
||||
const props: CreatureProperty[] = []
|
||||
for (const prop of creature.properties.values()) {
|
||||
if (prop.type === propType) {
|
||||
props.push(prop);
|
||||
}
|
||||
}
|
||||
const cloneProps = EJSON.clone(props);
|
||||
return cloneProps
|
||||
return EJSON.clone(props);
|
||||
}
|
||||
// console.time(`Cache miss on creature properties: ${creatureId}`)
|
||||
const props = CreatureProperties.find({
|
||||
'ancestors.id': creatureId,
|
||||
'root.id': creatureId,
|
||||
'removed': { $ne: true },
|
||||
'type': propType,
|
||||
}, {
|
||||
sort: { order: 1 },
|
||||
sort: { left: 1 },
|
||||
}).fetch();
|
||||
// console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
|
||||
return props;
|
||||
}
|
||||
|
||||
export function getCreature(creatureId) {
|
||||
if (loadedCreatures.has(creatureId)) {
|
||||
const loadedCreature = loadedCreatures.get(creatureId);
|
||||
const creature = loadedCreature.creature;
|
||||
if (creature) {
|
||||
const cloneCreature = EJSON.clone(creature);
|
||||
return cloneCreature;
|
||||
}
|
||||
const loadedCreature = loadedCreatures.get(creatureId);
|
||||
const loadedCreatureDoc = loadedCreature?.creature;
|
||||
if (loadedCreatureDoc) {
|
||||
return EJSON.clone(loadedCreatureDoc);
|
||||
}
|
||||
// console.time(`Cache miss on Creature: ${creatureId}`);
|
||||
const creature = Creatures.findOne(creatureId);
|
||||
@@ -109,13 +103,10 @@ export function getCreature(creatureId) {
|
||||
}
|
||||
|
||||
export function getVariables(creatureId) {
|
||||
if (loadedCreatures.has(creatureId)) {
|
||||
const loadedCreature = loadedCreatures.get(creatureId);
|
||||
const variables = loadedCreature.variables;
|
||||
if (variables) {
|
||||
const cloneVariables = EJSON.clone(variables);
|
||||
return cloneVariables;
|
||||
}
|
||||
const loadedCreature = loadedCreatures.get(creatureId);
|
||||
const loadedVariables = loadedCreature?.variables;
|
||||
if (loadedVariables) {
|
||||
return EJSON.clone(loadedVariables);
|
||||
}
|
||||
// console.time(`Cache miss on variables: ${creatureId}`);
|
||||
const variables = CreatureVariables.findOne({ _creatureId: creatureId });
|
||||
@@ -131,49 +122,44 @@ export function replaceLinkedVariablesWithProps(variables) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getProperyAncestors(creatureId, propertyId) {
|
||||
export function getPropertyAncestors(creatureId: string, propertyId: string) {
|
||||
const prop = getSingleProperty(creatureId, propertyId);
|
||||
if (!prop) return [];
|
||||
const ancestorIds = [];
|
||||
prop.ancestors.forEach(ref => {
|
||||
if (ref.collection === 'creatureProperties') {
|
||||
ancestorIds.push(ref.id);
|
||||
}
|
||||
});
|
||||
if (loadedCreatures.has(creatureId)) {
|
||||
const loadedCreature = loadedCreatures.get(creatureId);
|
||||
if (loadedCreature) {
|
||||
// Get the ancestor properties from the cache
|
||||
const creature = loadedCreatures.get(creatureId);
|
||||
const props = [];
|
||||
ancestorIds.forEach(id => {
|
||||
const prop = creature.properties.get(id);
|
||||
if (prop) {
|
||||
props.push(prop);
|
||||
}
|
||||
});
|
||||
const cloneProps = EJSON.clone(props);
|
||||
return cloneProps
|
||||
const props: CreatureProperty[] = [];
|
||||
let currentProp: CreatureProperty | undefined = prop;
|
||||
// Iterate through parent chain to get all linked ancestors
|
||||
while (currentProp?.parentId) {
|
||||
currentProp = getSingleProperty(creatureId, currentProp.parentId);
|
||||
if (currentProp) props.push(currentProp);
|
||||
}
|
||||
return EJSON.clone(props);
|
||||
} else {
|
||||
// Fetch from database
|
||||
return CreatureProperties.find({
|
||||
_id: { $in: ancestorIds },
|
||||
...getFilter.ancestors(prop),
|
||||
removed: { $ne: true },
|
||||
}, {
|
||||
sort: { order: 1 },
|
||||
sort: { left: 1 }
|
||||
}).fetch();
|
||||
}
|
||||
}
|
||||
|
||||
export function getPropertyDecendants(creatureId, propertyId) {
|
||||
export function getPropertyDescendants(creatureId, propertyId) {
|
||||
const property = getSingleProperty(creatureId, propertyId);
|
||||
if (!property) return [];
|
||||
// This prop will always appear at the same position in the ancestor array
|
||||
// of its decendants, so only check there
|
||||
const expectedAncestorPostition = property.ancestors.length;
|
||||
if (loadedCreatures.has(creatureId)) {
|
||||
const creature = loadedCreatures.get(creatureId);
|
||||
const props = [];
|
||||
if (!creature) return [];
|
||||
const props: CreatureProperty[] = [];
|
||||
// Loop through all properties and find ones that match the nested set condition
|
||||
for (const prop of creature.properties.values()) {
|
||||
if (prop.ancestors[expectedAncestorPostition]?.id === propertyId) {
|
||||
if (
|
||||
prop.left > property.left
|
||||
&& prop.right < property.right
|
||||
) {
|
||||
props.push(prop);
|
||||
}
|
||||
}
|
||||
@@ -181,10 +167,10 @@ export function getPropertyDecendants(creatureId, propertyId) {
|
||||
return cloneProps
|
||||
} else {
|
||||
return CreatureProperties.find({
|
||||
'ancestors.id': propertyId,
|
||||
...getFilter.descendants(property),
|
||||
removed: { $ne: true },
|
||||
}, {
|
||||
sort: { order: 1 },
|
||||
sort: { left: 1 },
|
||||
}).fetch();
|
||||
}
|
||||
}
|
||||
@@ -221,14 +207,21 @@ export function getPropertyChildren(creatureId, property) {
|
||||
}
|
||||
|
||||
class LoadedCreature {
|
||||
subs: Set<Tracker.Computation>;
|
||||
propertyObserver: Meteor.LiveQueryHandle;
|
||||
creatureObserver: Meteor.LiveQueryHandle;
|
||||
variablesObserver: Meteor.LiveQueryHandle;
|
||||
properties: Map<string, CreatureProperty>;
|
||||
creature: any;
|
||||
variables: any;
|
||||
|
||||
constructor(sub, creatureId) {
|
||||
const self = this;
|
||||
// This may be called from a subscription, but we don't want the observers
|
||||
// to be destroyed with it, so use a non-reactive context to observe
|
||||
// the required documents
|
||||
const self = this;
|
||||
Tracker.nonreactive(() => {
|
||||
self.subs = new Set([sub]);
|
||||
|
||||
const compute = debounce(Meteor.bindEnvironment(() => {
|
||||
computeCreature(creatureId);
|
||||
}), COMPUTE_DEBOUNCE_TIME);
|
||||
@@ -269,8 +262,8 @@ class LoadedCreature {
|
||||
self.changeCreature(id, fields);
|
||||
if (fields.dirty) compute();
|
||||
},
|
||||
removed(id) {
|
||||
self.removeCreature(id);
|
||||
removed() {
|
||||
self.removeCreature();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -287,8 +280,8 @@ class LoadedCreature {
|
||||
changed(id, fields) {
|
||||
self.changeVariables(id, fields);
|
||||
},
|
||||
removed(id) {
|
||||
self.removeVariables(id);
|
||||
removed() {
|
||||
self.removeVariables();
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -331,7 +324,7 @@ class LoadedCreature {
|
||||
}
|
||||
static changeDoc(doc, fields) {
|
||||
if (!doc) return;
|
||||
for (let key in fields) {
|
||||
for (const key in fields) {
|
||||
if (key === undefined) {
|
||||
delete doc[key];
|
||||
} else {
|
||||
Reference in New Issue
Block a user