From e3e7b76f02372024fd04361302c6dbb40340725c Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 4 Feb 2019 14:29:03 +0200 Subject: [PATCH] Results of effects are now stored on the effect, fixed defaults to suit --- .../api/creature/DEFAULT_CHARACTER_DOCS.js | 1 + .../api/creature/creatureComputation.js | 67 ++++++++++++------- .../api/creature/getDefaultCharacterDocs.js | 17 ++++- 3 files changed, 61 insertions(+), 24 deletions(-) diff --git a/app/imports/api/creature/DEFAULT_CHARACTER_DOCS.js b/app/imports/api/creature/DEFAULT_CHARACTER_DOCS.js index 846c9b6b..b637b9e5 100644 --- a/app/imports/api/creature/DEFAULT_CHARACTER_DOCS.js +++ b/app/imports/api/creature/DEFAULT_CHARACTER_DOCS.js @@ -95,6 +95,7 @@ export default () => ({ "stat": "proficiencyBonus", "operation": "add", "calculation": "floor(level / 4 + 1.75)", + "enabled": true, }, ], diff --git a/app/imports/api/creature/creatureComputation.js b/app/imports/api/creature/creatureComputation.js index e1bfc688..ef39c7a1 100644 --- a/app/imports/api/creature/creatureComputation.js +++ b/app/imports/api/creature/creatureComputation.js @@ -89,10 +89,13 @@ export function recomputeCreatureById(charId){ * @returns {undefined} */ function writeCreature(char) { + if (Meteor.isClient){ + console.log(char); + } writeAttributes(char); writeSkills(char); writeDamageMultipliers(char); - // TODO write effect results to effect.result + writeEffects(char); Creatures.update(char.id, {$set: {level: char.level}}); }; @@ -132,7 +135,25 @@ function writeAttributes(char) { } }; - +function writeEffects(char){ + let bulkWriteOps = _.map(char.computedEffects, effect => ({ + updateOne: { + filter: {_id: effect._id}, + update: {$set: { + result: effect.result, + }}, + }, + })); + if (Meteor.isServer){ + Effects.rawCollection().bulkWrite(bulkWriteOps, {ordered : false}, function(e, r){ + if (e) console.warn(JSON.stringify(e, null, 2)) + }); + } else { + _.each(bulkWriteOps, op => { + Effects.update(op.updateOne.filter, op.updateOne.update); + }); + } +} /** * Write all the skills from the in-memory char object to the Skills docs @@ -212,6 +233,8 @@ function buildCreature(charId){ skills: {}, dms: {}, classes: {}, + otherEffects: [], + computedEffects: [], level: 0, }; // Fetch the attributes of the creature and add them to an object for quick lookup @@ -280,8 +303,9 @@ function buildCreature(charId){ // Fetch the class levels and store them // don't use the word "class" it's reserved Classes.find({charId}).forEach(cls => { - if (!char.classes[cls.name]){ - char.classes[cls.name] = {level: cls.level}; + const strippedCls = cls.name.replace(/\s+/g, ''); + if (!char.classes[strippedCls]){ + char.classes[strippedCls] = {level: cls.level}; char.level += cls.level; } }); @@ -292,10 +316,10 @@ function buildCreature(charId){ enabled: true, }).forEach(effect => { let storedEffect = { + _id: effect._id, computed: false, result: 0, operation: effect.operation, - value: effect.value, calculation: effect.calculation, } if (char.atts[effect.stat]) { @@ -305,7 +329,7 @@ function buildCreature(charId){ } else if (char.dms[effect.stat]) { char.dms[effect.stat].effects.push(storedEffect); } else { - // ignore effects that don't apply to an actual stat + char.otherEffects.push(storedEffects); } }); @@ -330,6 +354,7 @@ function buildCreature(charId){ */ export function computeCreature(char){ // Iterate over each stat in order and compute it + let statName; for (statName in char.atts){ let stat = char.atts[statName] computeStat (stat, char); @@ -342,6 +367,9 @@ export function computeCreature(char){ let stat = char.dms[statName] computeStat (stat, char); } + for (let effect of char.otherEffects){ + computeEffect(effect, char); + } return char; }; @@ -391,16 +419,18 @@ function computeStat(stat, char){ */ function computeEffect(effect, char){ if (effect.computed) return; - if (_.isFinite(effect.value)){ - effect.result = effect.value; + if (_.isFinite(effect.calculation)){ + effect.result = +effect.calculation; } else if(effect.operation === "conditional"){ effect.result = effect.calculation; } else if(_.contains(["advantage", "disadvantage", "fail"], effect.operation)){ effect.result = 1; } else if (_.isString(effect.calculation)){ effect.result = evaluateCalculation(effect.calculation, char); + console.log(`evaluated ${effect.calculation} to ${effect.result}`); } effect.computed = true; + char.computedEffects.push(effect); }; @@ -424,14 +454,7 @@ function applyEffect(effect, stat){ } else if (effect.operation === "mul"){ if (!_.has(stat, "mul")) return; - if (stat.type === "damageMultiplier"){ - if (value === 0) stat.immunityCount++; - else if (value === 0.5) stat.ressistanceCount++; - else if (value === 2) stat.vulnerabilityCount++; - } else { - // Multiply all muls together - stat.mul *= effect.result; - } + stat.mul *= effect.result; } // Take the largest min value if (effect.operation === "min"){ @@ -573,11 +596,8 @@ function combineDamageMultiplier(stat, char){ */ function evaluateCalculation(string, char){ if (!string) return string; - // Replace all the string variables with numbers if possible - string = string.replace(/\b[a-z,1-9]+\b/gi, function(sub){ - // Make case insensitive - sub = sub.toLowerCase() + string = string.replace(/\w*[a-z]\w*/gi, function(sub){ // Attributes if (char.atts[sub]){ if (!char.atts[sub].computed){ @@ -586,7 +606,7 @@ function evaluateCalculation(string, char){ return char.atts[sub].result; } // Modifiers - if (/^\w+mod$/.test(sub)){ + if (/^\w+mod$/i.test(sub)){ var slice = sub.slice(0, -3); if (char.atts[slice]){ if (!char.atts[slice].computed){ @@ -610,9 +630,9 @@ function evaluateCalculation(string, char){ return char.dms[sub].result; } // Class levels - if (/^\w+levels?$/.test(sub)){ + if (/^\w+levels?$/i.test(sub)){ //strip out "level(s)" - var className = sub.replace(/levels?$/, ""); + var className = sub.replace(/levels?$/i, ""); return char.classes[className] && char.classes[className].level || sub; } // Creature level @@ -620,6 +640,7 @@ function evaluateCalculation(string, char){ return char.level; } // Give up + console.log(`Could not match ${sub}`); return sub; }); diff --git a/app/imports/api/creature/getDefaultCharacterDocs.js b/app/imports/api/creature/getDefaultCharacterDocs.js index 3dbb1080..658e3128 100644 --- a/app/imports/api/creature/getDefaultCharacterDocs.js +++ b/app/imports/api/creature/getDefaultCharacterDocs.js @@ -18,7 +18,8 @@ const getRacialBonusEffect = function(charId, attribute, bonus){ name: "Race Bonus", stat: attribute, operation: "add", - value: bonus, + calculation: bonus, + enabled: true, parent: { collection: "Creatures", id: charId, @@ -112,6 +113,7 @@ const getDefaultCharacterDocs = function(charId, { stat: `${hitDice}HitDice`, operation: "add", calculation: `${strippedCls}Level`, + enabled: true, parent: { collection: "Classes", id: classId, @@ -134,7 +136,20 @@ const getDefaultCharacterDocs = function(charId, { name: cls, stat: `${hitDice}HitDice`, operation: "add", + calculation: `${strippedCls}Level`, + enabled: true, + parent: { + collection: "Classes", + id: classId, + }, + charId: charId, + }); + docs.effects.push({ + name: cls, + stat: `hitPoints`, + operation: "add", calculation: `${healthPerLevel - 2} + ${healthPerLevel} * ${strippedCls}Level`, + enabled: true, parent: { collection: "Classes", id: classId,