From 936ca862db181056bc7466b389cdcc6ced9f47d5 Mon Sep 17 00:00:00 2001 From: Thaum Rystra <9525416+ThaumRystra@users.noreply.github.com> Date: Tue, 21 Nov 2023 11:35:07 +0200 Subject: [PATCH] Added Rolls to action system rewrite --- app/imports/api/engine/actions/Actions.ts | 63 ++++++++++++++++++- .../api/engine/actions/actions.test.ts | 17 ++++- .../shared/recalculateCalculation.js | 29 +++++---- app/packages/redis-oplog | 1 + 4 files changed, 93 insertions(+), 17 deletions(-) create mode 160000 app/packages/redis-oplog diff --git a/app/imports/api/engine/actions/Actions.ts b/app/imports/api/engine/actions/Actions.ts index 91bfbc4e..2e513d96 100644 --- a/app/imports/api/engine/actions/Actions.ts +++ b/app/imports/api/engine/actions/Actions.ts @@ -3,8 +3,9 @@ import { forEach, get, isEmpty, pick } from 'lodash'; import LogContentSchema from '/imports/api/creature/log/LogContentSchema'; import { getPropertyChildren, getSingleProperty, getVariables } from '/imports/api/engine/loadCreatures'; import recalculateInlineCalculations from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateInlineCalculations'; -import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation'; +import recalculateCalculation, { rollAndReduceCalculation } from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation'; import rollDice from '/imports/parser/rollDice'; +import { toString } from '/imports/parser/resolve'; /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -828,6 +829,12 @@ const applyPropertyByType = { return result; }, + async folder(prop, task: Task, action: Action): Promise { + const result = createResult(); + doNext(action, await childAndTriggerTasks(action, prop, task.targetIds)); + return result; + }, + async note(prop, task: Task, action: Action): Promise { const result = createResult(); @@ -858,6 +865,60 @@ const applyPropertyByType = { return result; }, + async roll(prop, task: Task, action: Action): Promise { + const result = createResult(); + + // If there isn't a calculation, just apply the children instead + if (!prop.roll?.calculation) { + doNext(action, await childAndTriggerTasks(action, prop, task.targetIds)); + return result; + } + + const logValue: string[] = []; + + // roll the dice only and store that string + const { + rolled, reduced, errors + } = rollAndReduceCalculation(prop.roll, action); + + if (rolled.parseType !== 'constant') { + logValue.push(toString(rolled)); + } + errors?.forEach(error => { + result.appendLog({ name: 'Error', value: error.message }, task.targetIds); + }); + + // Store the result + if (reduced.parseType === 'constant') { + prop.roll.value = reduced.value; + } else if (reduced.parseType === 'error') { + prop.roll.value = null; + } else { + prop.roll.value = toString(reduced); + } + + // If we didn't end up with a constant or a number of finite value, give up + if (reduced?.parseType !== 'constant' || (reduced.valueType === 'number' && !isFinite(reduced.value))) { + doNext(action, await childAndTriggerTasks(action, prop, task.targetIds)); + return result; + } + const value = reduced.value; + + result.scope[prop.variableName] = { value }; + logValue.push(`**${value}**`); + + result.appendLog({ + name: prop.name, + value: logValue.join('\n'), + inline: true, + silenced: prop.silent, + }, task.targetIds); + + // Apply children + doNext(action, await childAndTriggerTasks(action, prop, task.targetIds)); + return result; + }, + } type DamageProp = { diff --git a/app/imports/api/engine/actions/actions.test.ts b/app/imports/api/engine/actions/actions.test.ts index 74a1f092..febb1358 100644 --- a/app/imports/api/engine/actions/actions.test.ts +++ b/app/imports/api/engine/actions/actions.test.ts @@ -78,6 +78,10 @@ describe('Interrupt action system', function () { 'Applying increment adjustments should return the correct updates' ); }); + it('Applies rolls', async function () { + const action = await runActionById(rollId); + console.log(allLogContent(action)); + }); }); function createAction(prop, targetIds?) { @@ -123,7 +127,8 @@ function allLogContent(action: Action) { return contents; } -let note1Id, ifTruthyBranchId, ifFalsyBranchId, indexBranchId, choiceBranchId, adjustedStatId, adjustmentIncrementId, adjustmentSetId; +let note1Id, ifTruthyBranchId, ifFalsyBranchId, indexBranchId, choiceBranchId, adjustedStatId, + adjustmentIncrementId, adjustmentSetId, rollId; const propForest = [ // Apply a simple note @@ -201,6 +206,16 @@ const propForest = [ { type: 'note', summary: { text: 'adjustment increment applied' } }, ], }, + // Apply rolls + { + _id: rollId = Random.id(), + type: 'roll', + roll: { calculation: '1 + 3 + 1d20 + 5' }, + variableName: 'rollVar', + children: [ + { type: 'note', summary: { text: 'rollVar: {rollVar}' } } + ] + } ]; function insertActionTestProps() { diff --git a/app/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation.js b/app/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation.js index 4f08c8e9..ba9f330f 100644 --- a/app/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation.js +++ b/app/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation.js @@ -1,5 +1,5 @@ import logErrors from './logErrors.js'; -import { toPrimitiveOrString } from '/imports/parser/resolve.js'; +import { Context, toPrimitiveOrString } from '/imports/parser/resolve.js'; import { aggregateCalculationEffects, aggregateCalculationProficiencies, @@ -9,12 +9,15 @@ import { getSingleProperty } from '/imports/api/engine/loadCreatures'; import resolve from '/imports/parser/resolve.js'; import { getEffectiveActionScope } from '/imports/api/engine/actions/Actions'; +// TODO move this whole file to Actions.ts // Redo the work of imports/api/engine/computation/computeComputation/computeByType/computeCalculation.js // But in the action scope -export default function recalculateCalculation(calcObj, action, parseLevel = 'reduce', context) { +export default function recalculateCalculation(calcObj, action, parseLevel = 'reduce', context, scope) { if (!calcObj?.parseNode) return; calcObj._parseLevel = parseLevel; - const scope = getEffectiveActionScope(action); + if (!scope) { + scope = getEffectiveActionScope(action); + } // Re-resolve the parse node resolveCalculationNode(calcObj, calcObj.parseNode, scope, context); // store the unaffected value @@ -36,26 +39,22 @@ export default function recalculateCalculation(calcObj, action, parseLevel = 're // Store the primitive value calcObj.value = toPrimitiveOrString(calcObj.valueNode); - - logErrors(calcObj.errors, action); + // TODO log errors } -export function rollAndReduceCalculation(calcObj, actionContext, context) { +export function rollAndReduceCalculation(calcObj, action) { + const context = new Context(); + const scope = getEffectiveActionScope(action); // Compile - recalculateCalculation(calcObj, actionContext, 'compile', context); + recalculateCalculation(calcObj, action, 'compile', context, scope); const compiled = calcObj.valueNode; - const compileErrors = context.errors; // Roll - context.errors = []; - const { result: rolled } = resolve('roll', calcObj.valueNode, actionContext.scope, context); - const rollErrors = context.errors; + const { result: rolled } = resolve('roll', calcObj.valueNode, scope, context); // Reduce - context.errors = []; - const { result: reduced } = resolve('reduce', rolled, actionContext.scope, context); - const reduceErrors = context.errors; + const { result: reduced } = resolve('reduce', rolled, scope, context); // Return - return { compiled, compileErrors, rolled, rollErrors, reduced, reduceErrors }; + return { compiled, rolled, reduced, errors: context.errors }; } diff --git a/app/packages/redis-oplog b/app/packages/redis-oplog new file mode 160000 index 00000000..83e302c1 --- /dev/null +++ b/app/packages/redis-oplog @@ -0,0 +1 @@ +Subproject commit 83e302c15456d6744047c50fc8d1add9e739b001