diff --git a/app/imports/api/creature/actions/applyAction.js b/app/imports/api/creature/actions/applyAction.js
index 82ea824b..1ffb7990 100644
--- a/app/imports/api/creature/actions/applyAction.js
+++ b/app/imports/api/creature/actions/applyAction.js
@@ -4,7 +4,7 @@ import embedInlineCalculations from '/imports/api/creature/computation/afterComp
export default function applyAction({prop, log}){
let content = { name: prop.name };
if (prop.summary){
- content.description = embedInlineCalculations(
+ content.value = embedInlineCalculations(
prop.summary, prop.summaryCalculations
);
}
diff --git a/app/imports/api/creature/actions/applyAdjustment.js b/app/imports/api/creature/actions/applyAdjustment.js
index 88740430..5c106a73 100644
--- a/app/imports/api/creature/actions/applyAdjustment.js
+++ b/app/imports/api/creature/actions/applyAdjustment.js
@@ -21,7 +21,7 @@ export default function applyAdjustment({
context.errors.forEach(e => {
log.content.push({
name: 'Attribute damage error',
- error: e.message || e.toString(),
+ value: e.message || e.toString(),
});
});
if (damageTargets) {
@@ -41,15 +41,15 @@ export default function applyAdjustment({
});
log.content.push({
name: 'Attribute damage',
- resultPrefix: `${prop.stat} ${prop.operation === 'set' ? 'set to' : ''}`,
- result: `${result.isNumber ? -result.value : result.toString()}`,
+ value: `${prop.stat}${prop.operation === 'set' ? ' set to' : ''}` +
+ ` ${result.isNumber ? -result.value : result.toString()}`,
});
});
} else {
log.content.push({
name: 'Attribute damage',
- resultPrefix: `${prop.stat} ${prop.operation === 'set' ? 'set to' : ''}`,
- result: `${result.isNumber ? -result.value : result.toString()}`,
+ value: `${prop.stat}${prop.operation === 'set' ? ' set to' : ''}` +
+ ` ${result.isNumber ? -result.value : result.toString()}`,
});
}
}
diff --git a/app/imports/api/creature/actions/applyAttack.js b/app/imports/api/creature/actions/applyAttack.js
index 18f4933e..e3774041 100644
--- a/app/imports/api/creature/actions/applyAttack.js
+++ b/app/imports/api/creature/actions/applyAttack.js
@@ -17,7 +17,6 @@ export default function applyAttack({
log.content.push({
name: criticalHit ? 'Critical Hit!' : 'To Hit',
- resultPrefix: `1d20 [${value}] + ${prop.rollBonusResult} = `,
- result,
+ value: `1d20 [${value}] + ${prop.rollBonusResult} = ` + result,
});
}
diff --git a/app/imports/api/creature/actions/applyDamage.js b/app/imports/api/creature/actions/applyDamage.js
index 9704aa6c..04ca05d2 100644
--- a/app/imports/api/creature/actions/applyDamage.js
+++ b/app/imports/api/creature/actions/applyDamage.js
@@ -42,15 +42,15 @@ export default function applyDamage({
if (result.constructor.name === 'ErrorNode'){
log.content.push({
name: 'Damage error',
- error: result.toString(),
+ value: result.toString(),
});
return;
}
// Memoise the damage suffix for the log
- let suffix = (criticalHit ? ' critical ' : '') +
+ let suffix = (criticalHit ? ' critical ' : ' ') +
prop.damageType +
- (prop.damageType !== 'healing' ? ' damage': '');
+ (prop.damageType !== ' healing ' ? ' damage ': '');
if (damageTargets && damageTargets.length) {
// Iterate through all the targets
@@ -69,7 +69,7 @@ export default function applyDamage({
if (result.constructor.name === 'ErrorNode' || !result.isNumber){
log.content.push({
name: 'Damage error',
- error: result.toString(),
+ value: result.toString(),
});
return;
}
@@ -86,26 +86,21 @@ export default function applyDamage({
// Target is same as self, log damage as such
log.content.push({
name,
- result: damageDealt,
- details: suffix + ' to self',
+ value: damageDealt + suffix + ' to self',
});
} else {
log.content.push({
name,
- resultPrefix: 'Dealt ',
- result: damageDealt,
- details: suffix + `${target.name && ' to '}${target.name}`,
+ value: 'Dealt ' + damageDealt + suffix + ` ${target.name && ' to '}${target.name}`,
});
// Log the damage received on that creature's log as well
insertCreatureLog.call({
log: {
+ creatureId: target._id,
content: [{
name,
- resultPrefix: 'Recieved ',
- result: damageDealt,
- details: suffix,
+ value: 'Recieved ' + damageDealt + suffix,
}],
- creatureId: target._id,
}
});
}
@@ -114,8 +109,7 @@ export default function applyDamage({
// There are no targets, just log the result
log.content.push({
name: prop.damageType === 'healing' ? 'Healing' : 'Damage',
- result: result.toString(),
- details: suffix,
+ value: result.toString() + suffix,
});
}
}
diff --git a/app/imports/api/creature/actions/applyRoll.js b/app/imports/api/creature/actions/applyRoll.js
index 208cbeb1..8653ba7a 100644
--- a/app/imports/api/creature/actions/applyRoll.js
+++ b/app/imports/api/creature/actions/applyRoll.js
@@ -20,7 +20,6 @@ export default function applyRoll({
}
log.content.push({
name: prop.name,
- resultPrefix: prop.variableName + ' = ' + prop.roll + ' = ',
- result: result.toString(),
+ value: prop.variableName + ' = ' + prop.roll + ' = ' + result.toString(),
});
}
diff --git a/app/imports/api/creature/actions/applySave.js b/app/imports/api/creature/actions/applySave.js
index de01a5c5..bb6ce0d3 100644
--- a/app/imports/api/creature/actions/applySave.js
+++ b/app/imports/api/creature/actions/applySave.js
@@ -22,8 +22,7 @@ export default function applySave({
let dc = result.value;
log.content.push({
name: prop.name,
- resultPrefix: ' DC ',
- result: result.toString(),
+ value: ' DC ' + result.toString(),
});
if (prop.target === 'self'){
let save = CreaturesProperties.findOne({
@@ -36,7 +35,8 @@ export default function applySave({
});
if (!save){
log.content.push({
- error: 'No saving throw found: ' + prop.stat,
+ name: 'Saving throw error',
+ value: 'No saving throw found: ' + prop.stat,
});
return;
}
@@ -60,9 +60,7 @@ export default function applySave({
let saveSuccess = result >= dc;
log.content.push({
name: 'Save',
- resultPrefix,
- result,
- details: saveSuccess ? 'Passed' : 'Failed'
+ value: resultPrefix + result + (saveSuccess ? 'Passed' : 'Failed')
});
return !saveSuccess;
} else {
@@ -71,7 +69,8 @@ export default function applySave({
}
} catch (e){
log.content.push({
- error: e.toString(),
+ name: 'Save error',
+ value: e.toString(),
});
}
}
diff --git a/app/imports/api/creature/actions/applyToggle.js b/app/imports/api/creature/actions/applyToggle.js
index 1922978f..79d222ed 100644
--- a/app/imports/api/creature/actions/applyToggle.js
+++ b/app/imports/api/creature/actions/applyToggle.js
@@ -21,14 +21,13 @@ export default function applyToggle({
if (result.constructor.name === 'ErrorNode') {
log.content.push({
name: 'Toggle error',
- error: result.toString(),
+ value: result.toString(),
});
return false;
}
log.content.push({
name: prop.name || 'Toggle',
- resultPrefix: prop.condition + ' = ',
- result: result.toString(),
+ value: prop.condition + ' = ' + result.toString(),
});
return !!result.value;
}
diff --git a/app/imports/api/creature/actions/spendResources.js b/app/imports/api/creature/actions/spendResources.js
index da8dc653..ef71c04a 100644
--- a/app/imports/api/creature/actions/spendResources.js
+++ b/app/imports/api/creature/actions/spendResources.js
@@ -61,7 +61,7 @@ export default function spendResources({prop, log}){
});
log.content.push({
name: 'Uses left',
- result: prop.usesResult - (prop.usesUsed || 0) - 1,
+ value: prop.usesResult - (prop.usesUsed || 0) - 1,
});
}
@@ -84,10 +84,10 @@ export default function spendResources({prop, log}){
// Log all the spending
if (gainLog.length) log.content.push({
name: 'Gained',
- description: gainLog.join('\n'),
+ value: gainLog.join('\n'),
});
if (spendLog.length) log.content.push({
name: 'Spent',
- description: spendLog.join('\n'),
+ value: spendLog.join('\n'),
});
}
diff --git a/app/imports/api/creature/log/CreatureLogs.js b/app/imports/api/creature/log/CreatureLogs.js
index bd20a1b7..aec3a4c8 100644
--- a/app/imports/api/creature/log/CreatureLogs.js
+++ b/app/imports/api/creature/log/CreatureLogs.js
@@ -58,6 +58,7 @@ function removeOldLogs(creatureId){
sort: {date: -1},
skip: PER_CREATURE_LOG_LIMIT,
});
+ if (!firstExpiredLog) return;
// Remove all logs older than the one over the limit
CreatureLogs.remove({
creatureId,
@@ -69,32 +70,10 @@ function logToMessageData(log){
let embed = {
fields: [],
};
- log.content.forEach(c => {
- let field = {};
- let descriptionField = {};
- if (c.name) field.name = c.name;
- let valueArray = [];
- if (c.error) valueArray.push(`*${c.error}*`);
- if (c.resultPrefix) valueArray.push(`${c.resultPrefix}`);
- if (c.result) valueArray.push(`\`${c.result}\``);
- if (c.details) valueArray.push(c.details);
- if (valueArray.length) field.value = valueArray.join(' ');
- if (c.description){
- if (!field.value){
- field.value = c.description;
- } else {
- descriptionField.value = c.description;
- }
- }
- if (field.name || field.value){
- if (!field.name) field.name = '\u200b';
- if (!field.value) field.value = '\u200b';
- embed.fields.push(field);
- }
- if (descriptionField.value){
- descriptionField.name = '\u200b';
- embed.fields.push(descriptionField);
- }
+ log.content.forEach(field => {
+ if (!field.name) field.name = '\u200b';
+ if (!field.value) field.value = '\u200b';
+ embed.fields.push(field);
});
return { embeds: [embed] };
}
@@ -109,7 +88,7 @@ function logWebhook({log, creature}){
}
const insertCreatureLog = new ValidatedMethod({
- name: 'creatureLogs.methods.insertCreatureLog',
+ name: 'creatureLogs.methods.insert',
mixins: [RateLimiterMixin],
rateLimit: {
numRequests: 5,
@@ -138,7 +117,7 @@ const insertCreatureLog = new ValidatedMethod({
export function insertCreatureLogWork({log, creature, method}){
// Build the new log
if (typeof log === 'string'){
- log = {text: log};
+ log = {content: [{value: log}]};
}
log.date = new Date();
// Insert it
@@ -190,30 +169,30 @@ const logRoll = new ValidatedMethod({
parsedResult = parse(roll);
} catch (e){
let error = prettifyParseError(e);
- logContent.push({error});
+ logContent.push({name: 'Parse Error', value: error});
}
if (parsedResult) try {
let rollContext = new CompilationContext();
let compiled = parsedResult.compile(creature.variables, rollContext);
let compiledString = compiled.toString();
if (!equalIgnoringWhitespace(compiledString, roll)) logContent.push({
- details: roll
+ value: roll
});
logContent.push({
- details: compiledString
+ value: compiledString
});
let rolled = compiled.roll(creature.variables, rollContext);
let rolledString = rolled.toString();
if (rolledString !== compiledString) logContent.push({
- result: rolled.toString()
+ value: rolled.toString()
});
let result = rolled.reduce(creature.variables, rollContext);
let resultString = result.toString();
if (resultString !== rolledString) logContent.push({
- result: resultString
+ value: resultString
});
} catch (e){
- logContent = [{error: 'Calculation error'}];
+ logContent = [{name: 'Calculation error'}];
}
const log = {
content: logContent,
diff --git a/app/imports/api/creature/log/LogContentSchema.js b/app/imports/api/creature/log/LogContentSchema.js
index 80c9994b..b20c7464 100644
--- a/app/imports/api/creature/log/LogContentSchema.js
+++ b/app/imports/api/creature/log/LogContentSchema.js
@@ -3,31 +3,14 @@ import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js';
import RollDetailsSchema from '/imports/api/properties/subSchemas/RollDetailsSchema.js';
let LogContentSchema = new SimpleSchema({
+ // The name of the field, included in discord webhook message
name: {
type: String,
optional: true,
},
- error: {
- type: String,
- optional: true,
- },
- resultPrefix: {
- type: String,
- optional: true,
- },
- result: {
- type: String,
- optional: true,
- },
- expandedResult: {
- type: String,
- optional: true,
- },
- details: {
- type: String,
- optional: true,
- },
- description: {
+ // The details of the field, included in discord webhook message
+ // Markdown support
+ value: {
type: String,
optional: true,
},
diff --git a/app/imports/parser/parseTree/OperatorNode.js b/app/imports/parser/parseTree/OperatorNode.js
index 7bd546de..56633993 100644
--- a/app/imports/parser/parseTree/OperatorNode.js
+++ b/app/imports/parser/parseTree/OperatorNode.js
@@ -53,6 +53,10 @@ export default class OperatorNode extends ParseNode {
}
toString(){
let {left, right, operator} = this;
+ // special case of adding a negative number
+ if (operator === '+' && right.isNumber && right.value < 0){
+ return `${left.toString()} - ${-right.value}`
+ }
return `${left.toString()} ${operator} ${right.toString()}`;
}
traverse(fn){
diff --git a/app/imports/server/config/SyncedCronConfig.js b/app/imports/server/config/SyncedCronConfig.js
new file mode 100644
index 00000000..8ef48fec
--- /dev/null
+++ b/app/imports/server/config/SyncedCronConfig.js
@@ -0,0 +1,6 @@
+import { SyncedCron } from 'meteor/percolate:synced-cron';
+
+SyncedCron.config({
+ // Log job run details to console
+ log: false,
+});
diff --git a/app/imports/ui/components/snackbars/SnackbarQueue.js b/app/imports/ui/components/snackbars/SnackbarQueue.js
new file mode 100644
index 00000000..887a219f
--- /dev/null
+++ b/app/imports/ui/components/snackbars/SnackbarQueue.js
@@ -0,0 +1,16 @@
+// Modified from https://gitlab.com/tozd/vue/snackbar-que
+import Vue from 'vue';
+
+const globalState = Vue.observable({queue: []});
+let lastSnackbarId = 0;
+
+function snackbar(data) {
+ globalState.queue.push({
+ data,
+ id: ++lastSnackbarId,
+ enqueuedAt: new Date(),
+ shown: false,
+ });
+}
+
+export {snackbar, globalState}
diff --git a/app/imports/ui/components/snackbars/SnackbarQueue.vue b/app/imports/ui/components/snackbars/SnackbarQueue.vue
new file mode 100644
index 00000000..0cd0ecd6
--- /dev/null
+++ b/app/imports/ui/components/snackbars/SnackbarQueue.vue
@@ -0,0 +1,128 @@
+
+
+ {{ content.name }}
+
+