diff --git a/.DS_Store b/.DS_Store index 6af03ce3..502b5020 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/app/imports/api/engine/action/applyProperties/applyActionProperty.ts b/app/imports/api/engine/action/applyProperties/applyActionProperty.ts index 7a56ca34..d38dbddb 100644 --- a/app/imports/api/engine/action/applyProperties/applyActionProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyActionProperty.ts @@ -27,7 +27,7 @@ export default async function applyActionProperty( result.appendLog({ name: getPropertyTitle(prop), ...prop.summary && { value: prop.summary.value }, - ...prop.silent && { silenced: true }, + silenced: prop.silent, }, targetIds); // Check Uses @@ -35,7 +35,7 @@ export default async function applyActionProperty( result.appendLog({ name: 'Error', value: `${getPropertyTitle(prop)} does not have enough uses left`, - ...prop.silent && { silenced: true }, + silenced: prop.silent, }, targetIds); return; } @@ -45,7 +45,7 @@ export default async function applyActionProperty( result.appendLog({ name: 'Error', value: 'This creature doesn\'t have sufficient resources to perform this action', - ...prop.silent && { silenced: true }, + silenced: prop.silent, }, targetIds); return; } diff --git a/app/imports/api/engine/action/applyProperties/applyBranchProperty.ts b/app/imports/api/engine/action/applyProperties/applyBranchProperty.ts index 59a0bbea..86e7ba68 100644 --- a/app/imports/api/engine/action/applyProperties/applyBranchProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyBranchProperty.ts @@ -32,7 +32,8 @@ export default async function applyBranchProperty( if (!isFinite(prop.condition?.value)) { result.appendLog({ name: 'Branch Error', - value: `Index did not resolve into a valid number, got \`${prop.condition?.value}\` instead` + value: `Index did not resolve into a valid number, got \`${prop.condition?.value}\` instead`, + silenced: prop.silent, }, targets); return applyAfterTasksSkipChildren(action, prop, targets, userInput); } @@ -47,7 +48,8 @@ export default async function applyBranchProperty( if (scope['~attackHit']?.value) { if (!targets.length && !prop.silent) { result.appendLog({ - value: '**On hit**' + value: '**On hit**', + silenced: prop.silent, }, targets); } return applyDefaultAfterPropTasks(action, prop, targets, userInput); @@ -60,7 +62,8 @@ export default async function applyBranchProperty( if (scope['~attackMiss']?.value) { if (!targets.length && !prop.silent) { result.appendLog({ - value: '**On miss**' + value: '**On miss**', + silenced: prop.silent, }, targets); } return applyDefaultAfterPropTasks(action, prop, targets, userInput); @@ -73,7 +76,8 @@ export default async function applyBranchProperty( if (scope['~saveFailed']?.value) { if (!targets.length && !prop.silent) { result.appendLog({ - value: '**On failed save**' + value: '**On failed save**', + silenced: prop.silent, }, targets); } return applyDefaultAfterPropTasks(action, prop, targets, userInput); @@ -86,7 +90,8 @@ export default async function applyBranchProperty( if (scope['~saveSucceeded']?.value) { if (!targets.length && !prop.silent) { result.appendLog({ - value: '**On save**' + value: '**On save**', + silenced: prop.silent, }, targets); } return applyDefaultAfterPropTasks(action, prop, targets, userInput); @@ -123,4 +128,4 @@ export default async function applyBranchProperty( return applyAfterPropTasksForSomeChildren(action, prop, chosenChildren, targets, userInput); } } -} \ No newline at end of file +} diff --git a/app/imports/api/engine/action/applyProperties/applyBuffProperty.ts b/app/imports/api/engine/action/applyProperties/applyBuffProperty.ts index a0006d2d..241912f6 100644 --- a/app/imports/api/engine/action/applyProperties/applyBuffProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyBuffProperty.ts @@ -62,7 +62,8 @@ export default async function applyBuffProperty( } result.appendLog({ name: getPropertyTitle(prop), - value: logValue + value: logValue, + silenced: prop.silent, }, [target]); // remove all the computed fields @@ -114,6 +115,7 @@ async function crystalizeVariables( result.appendLog({ name: 'Error', value: 'Variable `~target` should not be used without a property: ~target.property', + silenced: prop.silent, }, task.targetIds); } return node; diff --git a/app/imports/api/engine/action/applyProperties/applyBuffRemoverProperty.ts b/app/imports/api/engine/action/applyProperties/applyBuffRemoverProperty.ts index c18e13e3..791f0b7a 100644 --- a/app/imports/api/engine/action/applyProperties/applyBuffRemoverProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyBuffRemoverProperty.ts @@ -19,7 +19,7 @@ export default async function applyBuffRemoverProperty( // Log Name result.appendLog({ name: getPropertyTitle(prop), - ...prop.silent && { silenced: true }, + silenced: prop.silent, }, task.targetIds) } @@ -41,6 +41,7 @@ export default async function applyBuffRemoverProperty( result.appendLog({ name: 'Error', value: 'Buff remover does not have a parent buff to remove', + silenced: prop.silent, }, [targetId]); return; } diff --git a/app/imports/api/engine/action/applyProperties/applyCreatureTemplateProperty.ts b/app/imports/api/engine/action/applyProperties/applyCreatureTemplateProperty.ts index baea93cf..ed4dbe33 100644 --- a/app/imports/api/engine/action/applyProperties/applyCreatureTemplateProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyCreatureTemplateProperty.ts @@ -17,12 +17,14 @@ export default async function applyCreatureTemplateProperty( // Creatures are always summoned as children of the action's creature result.appendLog({ name: getPropertyTitle(prop), - value: logValue + value: logValue, + silenced: prop.silent, }, []); result.appendLog({ name: 'Warning', - value: 'Creature summoning is not yet implemented...' + value: 'Creature summoning is not yet implemented...', + silenced: prop.silent, }, []); return; diff --git a/app/imports/api/engine/action/applyProperties/applyDamageProperty.ts b/app/imports/api/engine/action/applyProperties/applyDamageProperty.ts index 2bbe6999..c38c53e5 100644 --- a/app/imports/api/engine/action/applyProperties/applyDamageProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyDamageProperty.ts @@ -188,6 +188,7 @@ export default async function applyDamageProperty( name: logName, value: logValue.join('\n'), inline: true, + silenced: prop.silent, }, damageTargets); return applyDefaultAfterPropTasks(action, prop, damageTargets, inputProvider); } diff --git a/app/imports/api/engine/action/applyProperties/applyNoteProperty.ts b/app/imports/api/engine/action/applyProperties/applyNoteProperty.ts index 655b6654..41baa4dd 100644 --- a/app/imports/api/engine/action/applyProperties/applyNoteProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyNoteProperty.ts @@ -9,8 +9,9 @@ export default async function applyNoteProperty( task: PropTask, action: EngineAction, result: TaskResult, inputProvider: InputProvider ): Promise { const prop = task.prop; - let contents: LogContent[] | undefined = undefined; - const logContent: LogContent = {}; + const logContent: LogContent & { silenced: boolean } = { + silenced: prop.silent, + }; if (prop.name) logContent.name = prop.name; if (prop.summary?.text) { await recalculateInlineCalculations(prop.summary, action, 'reduce', inputProvider); @@ -18,19 +19,15 @@ export default async function applyNoteProperty( } if (logContent.name || logContent.value) { - contents = [logContent]; + result.appendLog(logContent, task.targetIds); } // Log description if (prop.description?.text) { await recalculateInlineCalculations(prop.description, action, 'reduce', inputProvider); - if (!contents) contents = []; - contents.push({ value: prop.description.value }); - } - if (contents) { - result.mutations.push({ - contents, - targetIds: task.targetIds, - }); + result.appendLog({ + value: prop.description.value, + silenced: prop.silent, + }, task.targetIds); } return applyDefaultAfterPropTasks(action, prop, task.targetIds, inputProvider); -} \ No newline at end of file +} diff --git a/app/imports/api/engine/action/applyProperties/applyRollProperty.ts b/app/imports/api/engine/action/applyProperties/applyRollProperty.ts index bc7694d6..a27f2149 100644 --- a/app/imports/api/engine/action/applyProperties/applyRollProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyRollProperty.ts @@ -27,7 +27,11 @@ export default async function applyRollProperty( logValue.push(toString(rolled)); } errors?.forEach(error => { - result.appendLog({ name: 'Error', value: error.message }, task.targetIds); + result.appendLog({ + name: 'Error', + value: error.message, + silenced: prop.silent, + }, task.targetIds); }); // Store the result @@ -52,7 +56,7 @@ export default async function applyRollProperty( name: prop.name, value: logValue.join('\n'), inline: true, - ...prop.silent && { silenced: true }, + silenced: prop.silent, }, task.targetIds); // Apply children diff --git a/app/imports/api/engine/action/applyProperties/applySavingThrowProperty.ts b/app/imports/api/engine/action/applyProperties/applySavingThrowProperty.ts index f989851e..95688331 100644 --- a/app/imports/api/engine/action/applyProperties/applySavingThrowProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applySavingThrowProperty.ts @@ -28,6 +28,7 @@ export default async function applySavingThrowProperty( result.appendLog({ name: 'Error', value: 'Saving throw requires a DC', + silenced: prop.silent, }, saveTargetIds); return applyDefaultAfterPropTasks(action, prop, saveTargetIds, inputProvider); } @@ -37,7 +38,7 @@ export default async function applySavingThrowProperty( name: getPropertyTitle(prop), value: `DC **${dc}**`, inline: true, - ...prop.silent && { silenced: prop.silent } + silenced: prop.silent, }, saveTargetIds); const targetId = saveTargetIds[0]; @@ -60,6 +61,7 @@ export default async function applySavingThrowProperty( result.appendLog({ name: 'Saving throw error', value: 'No saving throw found: ' + prop.stat, + silenced: prop.silent, }, [targetId]); return applyDefaultAfterPropTasks(action, prop, [targetId], inputProvider); } @@ -103,10 +105,11 @@ export default async function applySavingThrowProperty( result.pushScope['~saveFailed'] = { value: true }; result.pushScope['~saveSucceeded'] = { value: false }; } - if (!prop.silent) result.appendLog({ + result.appendLog({ name: saveSuccess ? 'Successful save' : 'Failed save', value: resultPrefix + '\n**' + resultValue + '**', inline: true, + silenced: prop.silent, }, [targetId]); return applyDefaultAfterPropTasks(action, prop, [targetId], inputProvider); } diff --git a/app/imports/api/engine/action/applyProperties/applyTriggerProperty.ts b/app/imports/api/engine/action/applyProperties/applyTriggerProperty.ts index 3064c444..a7c86268 100644 --- a/app/imports/api/engine/action/applyProperties/applyTriggerProperty.ts +++ b/app/imports/api/engine/action/applyProperties/applyTriggerProperty.ts @@ -1,3 +1,4 @@ +import TaskResult, { LogContent } from '../tasks/TaskResult'; import { EngineAction } from '/imports/api/engine/action/EngineActions'; import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups'; import recalculateInlineCalculations from '/imports/api/engine/action/functions/recalculateInlineCalculations'; @@ -5,12 +6,12 @@ import { PropTask } from '/imports/api/engine/action/tasks/Task'; import getPropertyTitle from '/imports/api/utility/getPropertyTitle'; export default async function applyTriggerProperty( - task: PropTask, action: EngineAction, result, userInput + task: PropTask, action: EngineAction, result: TaskResult, userInput ): Promise { const prop = task.prop; - const logContent = { + const logContent: LogContent & { silenced: boolean } = { name: getPropertyTitle(prop), - ...prop.silent && { silenced: true }, + silenced: prop.silent, } // Add the trigger description to the log @@ -21,6 +22,6 @@ export default async function applyTriggerProperty( } } - result.appendLog(logContent); + result.appendLog(logContent, task.targetIds); return applyDefaultAfterPropTasks(action, prop, task.targetIds, userInput); } diff --git a/app/imports/api/engine/action/applySilencedProps.test.ts b/app/imports/api/engine/action/applySilencedProps.test.ts new file mode 100644 index 00000000..05254012 --- /dev/null +++ b/app/imports/api/engine/action/applySilencedProps.test.ts @@ -0,0 +1,50 @@ +import { assert } from 'chai'; +import { + allMutations, + createTestCreature, + getRandomIds, + removeAllCreaturesAndProps, + runActionById +} from '/imports/api/engine/action/functions/actionEngineTest.testFn'; + +const [ + creatureId, silencedNoteId +] = getRandomIds(2); + +const actionTestCreature = { + _id: creatureId, + props: [ + { + _id: silencedNoteId, + type: 'note', + name: 'Note Name', + summary: { text: 'Note summary {1 + 2}' }, + silent: true, + }, + ], +} + +describe('Apply silenced properties', function () { + // Increase timeout + this.timeout(8000); + + before(async function () { + await removeAllCreaturesAndProps(); + await createTestCreature(actionTestCreature); + }); + + it('Hides the note text', async function () { + const action = await runActionById(silencedNoteId); + assert.exists(action); + assert.deepEqual(allMutations(action), [{ + contents: [ + { + name: 'Note Name', + value: 'Note summary 3', + silenced: true, + }, + ], + targetIds: [], + }]); + }); +}); diff --git a/app/imports/api/engine/action/tasks/TaskResult.ts b/app/imports/api/engine/action/tasks/TaskResult.ts index 10ca4232..a9426fbe 100644 --- a/app/imports/api/engine/action/tasks/TaskResult.ts +++ b/app/imports/api/engine/action/tasks/TaskResult.ts @@ -26,7 +26,13 @@ export default class TaskResult { this.scope = {}; } // Appends the log content to the latest mutation - appendLog(content: LogContent, targetIds: string[]) { + appendLog(content: LogContent & { silenced: boolean }, targetIds: string[]) { + // Create a shallow copy of the content + const logContent: LogContent = { ...content }; + // remove false silenced properties + if (!logContent.silenced) { + delete logContent.silenced; + } if (!this.mutations.length) { this.mutations.push({ targetIds, contents: [] }); } @@ -34,7 +40,7 @@ export default class TaskResult { if (!latestMutation.contents) { latestMutation.contents = []; } - latestMutation.contents.push(content); + latestMutation.contents.push(logContent); } appendParserContextErrors(context: Context, targetIds) { if (!context.errors?.length) return; diff --git a/app/imports/api/engine/action/tasks/applyCastSpellTask.ts b/app/imports/api/engine/action/tasks/applyCastSpellTask.ts index 8f900a97..0907cd12 100644 --- a/app/imports/api/engine/action/tasks/applyCastSpellTask.ts +++ b/app/imports/api/engine/action/tasks/applyCastSpellTask.ts @@ -22,6 +22,7 @@ export default async function applySpellProperty( result.appendLog({ name: 'Error casting spell', value: 'No spell was selected', + silenced: false, }, [action.creatureId]); return; } @@ -32,6 +33,7 @@ export default async function applySpellProperty( result.appendLog({ name: 'Error casting spell', value: 'The chosen spell was not found', + silenced: false, }, [action.creatureId]); return; } @@ -80,7 +82,8 @@ function logCastingMessage(slotLevel: number, castOptions, result: TaskResult, p // Post the message if (message) { result.appendLog({ - name: `Casting at level ${slotLevel}` + name: `Casting at level ${slotLevel}`, + silenced: prop.silent, }, targetIds); } } diff --git a/app/imports/api/engine/action/tasks/applyCheckTask.ts b/app/imports/api/engine/action/tasks/applyCheckTask.ts index fe350d8b..7d3a1595 100644 --- a/app/imports/api/engine/action/tasks/applyCheckTask.ts +++ b/app/imports/api/engine/action/tasks/applyCheckTask.ts @@ -74,7 +74,7 @@ export default async function applyCheckTask( name: checkName, inline: true, ...dc !== null && { value: `DC **${dc}**` }, - ...task?.silent && { silenced: task.silent } + silenced: task.silent ?? false, }, [targetId]); // Roll the dice @@ -108,7 +108,7 @@ export default async function applyCheckTask( name: rollName, value: `${resultPrefix}\n**${totalValue}**`, inline: true, - ...task?.silent && { silenced: task.silent } + silenced: task.silent ?? false, }, [targetId]); // After check triggers diff --git a/app/imports/api/engine/action/tasks/applyDamagePropTask.ts b/app/imports/api/engine/action/tasks/applyDamagePropTask.ts index 43d7afee..6d3fa735 100644 --- a/app/imports/api/engine/action/tasks/applyDamagePropTask.ts +++ b/app/imports/api/engine/action/tasks/applyDamagePropTask.ts @@ -73,7 +73,7 @@ export default async function applyDamagePropTask( value: `${statName}${operation === 'set' ? ' set to' : ''}` + ` ${value}`, inline: true, - ...task.silent && { silenced: true }, + silenced: task.silent ?? false, }, task.targetIds); } diff --git a/app/imports/api/engine/action/tasks/applyResetTask.ts b/app/imports/api/engine/action/tasks/applyResetTask.ts index 26dd24f0..e6ddf0a5 100644 --- a/app/imports/api/engine/action/tasks/applyResetTask.ts +++ b/app/imports/api/engine/action/tasks/applyResetTask.ts @@ -20,10 +20,16 @@ export default async function applyResetTask( // Print a title for rest events switch (task.eventName) { case 'shortRest': - result.appendLog({ name: 'Short Rest' }, task.targetIds); + result.appendLog({ + name: 'Short Rest', + silenced: task.silent ?? false, + }, task.targetIds); break; case 'longRest': - result.appendLog({ name: 'Long Rest' }, task.targetIds); + result.appendLog({ + name: 'Long Rest', + silenced: task.silent ?? false, + }, task.targetIds); break; } diff --git a/app/imports/api/properties/Notes.js b/app/imports/api/properties/Notes.js index 4aa66a6e..699f981d 100644 --- a/app/imports/api/properties/Notes.js +++ b/app/imports/api/properties/Notes.js @@ -16,6 +16,11 @@ let NoteSchema = createPropertySchema({ type: 'inlineCalculationFieldToCompute', optional: true, }, + // Prevent the property from showing up in the log + silent: { + type: Boolean, + optional: true, + }, }); let ComputedOnlyNoteSchema = createPropertySchema({ diff --git a/app/imports/api/properties/Toggles.js b/app/imports/api/properties/Toggles.js index c0802588..398cf2f6 100644 --- a/app/imports/api/properties/Toggles.js +++ b/app/imports/api/properties/Toggles.js @@ -32,6 +32,11 @@ const ToggleSchema = createPropertySchema({ type: 'fieldToCompute', optional: true, }, + // Prevent the property from showing up in the log + silent: { + type: Boolean, + optional: true, + }, }).extend(TagTargetingSchema); const ComputedOnlyToggleSchema = createPropertySchema({ diff --git a/app/imports/client/ui/log/LogContent.vue b/app/imports/client/ui/log/LogContent.vue index 8de93e87..3545b7c8 100644 --- a/app/imports/client/ui/log/LogContent.vue +++ b/app/imports/client/ui/log/LogContent.vue @@ -1,7 +1,7 @@ @@ -39,6 +42,9 @@ import TabletopLogContent from '/imports/client/ui/log/TabletopLogContent.vue'; import Creatures from '/imports/api/creature/creatures/Creatures'; +// TODO move content filtering to this component so we can determine if any content was hidden +// then show a button to reveal silenced content at a lower opacity + export default { components: { TabletopLogContent, @@ -50,6 +56,11 @@ export default { }, showName: Boolean, }, + data() { + return { + showSilenced: false, + }; + }, meteor: { creature() { return Creatures.findOne(this.model.creatureId); diff --git a/app/package.json b/app/package.json index 5c01d617..65a82bac 100644 --- a/app/package.json +++ b/app/package.json @@ -9,7 +9,7 @@ }, "author": "Thaum Rystra", "scripts": { - "serve": "meteor run --raw-logs", + "serve": "meteor run --raw-logs --settings settings.json", "debug": "meteor --inspect", "bundle-viz": "meteor --extra-packages bundle-visualizer --production", "lint": "eslint .",