diff --git a/app/imports/api/engine/action/applyProperties/applyBuffProperty.ts b/app/imports/api/engine/action/applyProperties/applyBuffProperty.ts index fca54e4f..91b27fde 100644 --- a/app/imports/api/engine/action/applyProperties/applyBuffProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyBuffProperty.ts @@ -80,7 +80,7 @@ async function logBuff(prop, targetIds, action, userInput, result) { //Log the buff let logValue = prop.description?.value if (prop.description?.text) { - recalculateInlineCalculations(prop.description, action, 'reduce', userInput); + await recalculateInlineCalculations(prop.description, action, 'reduce', userInput); logValue = prop.description?.value; } result.appendLog({ diff --git a/app/imports/api/engine/action/applyProperties/applyCreatureTemplateProperty.ts b/app/imports/api/engine/action/applyProperties/applyCreatureTemplateProperty.ts index ed4dbe33..0c25dd85 100644 --- a/app/imports/api/engine/action/applyProperties/applyCreatureTemplateProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyCreatureTemplateProperty.ts @@ -10,7 +10,7 @@ export default async function applyCreatureTemplateProperty( //Log the Creature that is about to be summoned let logValue = prop.description?.value if (prop.description?.text) { - recalculateInlineCalculations(prop.description, action, 'reduce', userInput); + await recalculateInlineCalculations(prop.description, action, 'reduce', userInput); logValue = prop.description?.value; } // There are no targets for creature templates diff --git a/app/imports/api/engine/action/functions/recalculateCalculation.ts b/app/imports/api/engine/action/functions/recalculateCalculation.ts index 1258cfd2..88240692 100644 --- a/app/imports/api/engine/action/functions/recalculateCalculation.ts +++ b/app/imports/api/engine/action/functions/recalculateCalculation.ts @@ -8,13 +8,10 @@ import { getSingleProperty } from '/imports/api/engine/loadCreatures'; import resolve from '/imports/parser/resolve'; import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope'; import { CalculatedField } from '/imports/api/properties/subSchemas/computedField'; -import { ResolveLevel } from '/imports/parser/parseTree/NodeFactory'; import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider'; import { EngineAction } from '/imports/api/engine/action/EngineActions'; +import ResolveLevel from '/imports/parser/types/ResolveLevel'; -// TODO Redo the work of -// imports/api/engine/computation/computeComputation/computeByType/computeCalculation.js -// But in the action scope export default async function recalculateCalculation( calcObj: CalculatedField, action, @@ -27,7 +24,7 @@ export default async function recalculateCalculation( const { result: unaffectedResult, context - } = await resolve(parseLevel, calcObj.parseNode, scope); + } = await resolve(parseLevel, calcObj.parseNode, scope, undefined, userInput); calcObj.valueNode = unaffectedResult; // store the unaffected value @@ -48,7 +45,7 @@ export default async function recalculateCalculation( // Resolve the modified valueNode, use the same context const { result: finalResult - } = await resolve(parseLevel, calcObj.valueNode, scope, context); + } = await resolve(parseLevel, calcObj.valueNode, scope, context, userInput); // Store the errors calcObj.errors = context.errors; diff --git a/app/imports/api/engine/action/functions/recalculateInlineCalculations.ts b/app/imports/api/engine/action/functions/recalculateInlineCalculations.ts index 02d7e5e1..d1589027 100644 --- a/app/imports/api/engine/action/functions/recalculateInlineCalculations.ts +++ b/app/imports/api/engine/action/functions/recalculateInlineCalculations.ts @@ -13,7 +13,7 @@ export default async function recalculateInlineCalculations( if (!inlineCalcObj?.inlineCalculations?.length) return; // Recalculate each calculation with the current scope for (const calc of inlineCalcObj.inlineCalculations) { - await recalculateCalculation(calc, action, undefined, userInput); + await recalculateCalculation(calc, action, parseLevel, userInput); } // Embed the new calculated values embedInlineCalculations(inlineCalcObj); diff --git a/app/imports/api/engine/action/test/diceRollFunctions.test.ts b/app/imports/api/engine/action/test/diceRollFunctions.test.ts new file mode 100644 index 00000000..6aa7c060 --- /dev/null +++ b/app/imports/api/engine/action/test/diceRollFunctions.test.ts @@ -0,0 +1,53 @@ +import { assert } from 'chai'; +import { + allLogContent, + createTestCreature, + getRandomIds, + removeAllCreaturesAndProps, + runActionById +} from '/imports/api/engine/action/functions/actionEngineTest.testFn'; + +const [ + creatureId, dropLowestId +] = getRandomIds(2); + +const actionTestCreature = { + _id: creatureId, + props: [ + { + _id: dropLowestId, + type: 'note', + summary: { text: 'Note summary {dropLowest(10d6,3)}' }, + children: [ + { + type: 'roll', + name: 'Roll', + variableName: 'dropLowestVar', + roll: { calculation: 'dropLowest(10d6,3)' } + } + ] + }, + ], +} + +describe.only('Built in dice functions', function () { + // Increase timeout + this.timeout(8000); + + before(async function () { + await removeAllCreaturesAndProps(); + await createTestCreature(actionTestCreature); + }); + + it('Rolls 10d6 and drops the lowest 3 values', async function () { + const action = await runActionById(dropLowestId); + assert.exists(action); + assert.deepEqual(allLogContent(action), [{ + value: 'Note summary 33', + }, { + inline: true, + name: 'Roll', + value: '10d6 [~~3~~, 4, 5, 6, ~~1~~, ~~2~~, 3, 4, 5, 6]\n**33**', + }]); + }); +}); diff --git a/app/imports/parser/parseTree/call.ts b/app/imports/parser/parseTree/call.ts index 3f90d9b5..b28e94fc 100644 --- a/app/imports/parser/parseTree/call.ts +++ b/app/imports/parser/parseTree/call.ts @@ -172,16 +172,17 @@ const call: CallFactory = { expectedType = argumentsExpected[index]; } if (expectedType === 'parseNode') return; - failed = !( + const argFailed = !( node.parseType === expectedType || (node.parseType === 'constant' && node.valueType === expectedType) ); - if (failed && fn === 'reduce') { + if (argFailed && fn === 'reduce') { const typeName = typeof expectedType === 'string' ? expectedType : expectedType.constructor.name; const nodeName = node.parseType === 'constant' ? node.valueType : node.parseType; context.error(`Incorrect arguments to ${callNode.functionName} function` + `expected ${typeName} got ${nodeName}`); } + failed = failed || argFailed; }); return failed; }