diff --git a/rpg-docs/Model/Character/Characters.js b/rpg-docs/Model/Character/Characters.js index eeaebb40..4fd1173c 100644 --- a/rpg-docs/Model/Character/Characters.js +++ b/rpg-docs/Model/Character/Characters.js @@ -3,17 +3,17 @@ Characters = new Meteor.Collection("characters"); Schemas.Character = new SimpleSchema({ //strings - name: { type: String, defaultValue: "", optional: true }, - alignment: { type: String, defaultValue: "", optional: true }, - gender: { type: String, defaultValue: "", optional: true }, - race: { type: String, defaultValue: "", optional: true }, - description:{ type: String, defaultValue: "", optional: true }, - personality:{ type: String, defaultValue: "", optional: true }, - ideals: { type: String, defaultValue: "", optional: true }, - bonds: { type: String, defaultValue: "", optional: true }, - flaws: { type: String, defaultValue: "", optional: true }, - backstory: { type: String, defaultValue: "", optional: true }, - notes: { type: String, defaultValue: "", optional: true }, + name: { type: String, defaultValue: "", trim: false}, + alignment: { type: String, defaultValue: "", trim: false}, + gender: { type: String, defaultValue: "", trim: false}, + race: { type: String, defaultValue: "", trim: false}, + description:{ type: String, defaultValue: "", trim: false}, + personality:{ type: String, defaultValue: "", trim: false}, + ideals: { type: String, defaultValue: "", trim: false}, + bonds: { type: String, defaultValue: "", trim: false}, + flaws: { type: String, defaultValue: "", trim: false}, + backstory: { type: String, defaultValue: "", trim: false}, + notes: { type: String, defaultValue: "", trim: false}, //attributes //ability scores @@ -269,7 +269,7 @@ Characters.helpers({ var char = Characters.findOne(this._id, {fields: fieldSelector}); var field = char[fieldName]; if(field === undefined){ - throw "no such field "+fieldName+" exists"; + console.log("no field ", fieldName, " exists for character ", char) } return field; }, @@ -279,52 +279,123 @@ Characters.helpers({ console.log("Character's schema does not contain a field called: " + fieldName); return; } - var field = this.getField(fieldName); //duck typing to get the right value function //.proficiency implies skill if (Schemas.Character.schema(fieldName + ".proficiency")){ - return this.skillMod(field); + return this.skillMod(fieldName); } //base without proficiency implies attribute if (Schemas.Character.schema(fieldName + ".base")){ - return this.attributeValue(field); + return this.attributeValue(fieldName); } //fall back to just returning the field itself - return field; + return this.getField(fieldName); }, - attributeValue: function(attribute){ - if (attribute === undefined) return; - var charId = this._id; - if (_.isString(attribute)){ - attribute = this.getField(attribute); + attributeValue: (function(){ + //store a private array of attributes we've visited without returning + //if we try to visit the same attribute twice before resolving its value + //we are in a dependency loop and need to GTFO + var visitedAttributes = []; + return function(attributeName){ + check(attributeName, String); + //we're still evaluating this attribute, must be in a loop + if(_.contains(visitedAttributes, attributeName)) { + console.log("dependency loop detected"); + return NaN; + } + //push this attribute to the list of visited attributes + //we can't visit it again unless it returns first + visitedAttributes.push(attributeName); + + var charId = this._id; + var attribute = this.getField(attributeName); + //base value + var value = attribute.base; + //add all values in add array + _.each(attribute.add, function(effect){ + value += evaluateEffect(charId, effect); + }); + + //multiply all values in mul array + _.each(attribute.mul, function(effect){ + value *= evaluateEffect(charId, effect); + }); + + //largest min + _.each(attribute.min, function(effect){ + var min = evaluateEffect(charId, effect); + value = value > min? value : min; + }); + + //smallest max + _.each(attribute.max, function(effect){ + var max = evaluateEffect(charId, effect); + value = value < max? value : max; + }); + //done traversing the tree, this attribute returns, pull it from the array + visitedAttributes = _.without(visitedAttributes, attributeName); + return value; } - //base value - var value = attribute.base; - //add all values in add array - _.each(attribute.add, function(effect){ - value += evaluateEffect(charId, effect); - }); + })(), - //multiply all values in mul array - _.each(attribute.mul, function(effect){ - value *= evaluateEffect(charId, effect); - }); + skillMod: (function(){ + //store a private array of skills we've visited without returning + //if we try to visit the same skill twice before resolving its value + //we are in a dependency loop and need to GTFO + var visitedSkills = []; + return function(skillName){ + check(skillName, String); + //we're still evaluating this attribute, must be in a loop + if(_.contains(visitedSkills, skillName)) { + console.log("dependency loop detected"); + return NaN; + } + //push this skill to the list of visited skills + //we can't visit it again unless it returns first + visitedSkills.push(skillName); - //largest min - _.each(attribute.min, function(effect){ - var min = evaluateEffect(charId, effect); - value = value > min? value : min; - }); + var charId = this._id; + skill = this.getField(skillName); + //get the final value of the ability score + var ability = this.attributeValue(skill.ability); - //smallest max - _.each(attribute.max, function(effect){ - var max = evaluateEffect(charId, effect); - value = value < max? value : max; - }); + //base modifier + var mod = +getMod(ability) - return value; - }, + //multiply proficiency bonus by largest value in proficiency array + var prof = this.proficiency(skill); + + //add multiplied proficiency bonus to modifier + mod += prof * this.attributeValue("proficiencyBonus"); + + //add all values in add array + _.each(skill.add, function(effect){ + mod += evaluateEffect(charId, effect); + }); + + //multiply all values in mul array + _.each(skill.mul, function(effect){ + mod *= evaluateEffect(charId, effect); + }); + + //largest min + _.each(skill.min, function(effect){ + var min = evaluateEffect(charId, effect); + mod = mod > min? mod : min; + }); + + //smallest max + _.each(skill.max, function(effect){ + var max = evaluateEffect(charId, effect); + mod = mod < max? mod : max; + }); + + //done traversing the tree, this skill returns, pull it from the array + visitedSkills = _.without(visitedSkills, skillName); + return signedString(mod); + } + })(), proficiency: function(skill){ if (_.isString(skill)){ @@ -342,52 +413,6 @@ Characters.helpers({ return prof; }, - skillMod: function(skill){ - if(skill === undefined){ - console.log("Cannot get skillMod of undefined"); - return; - } - var charId = this._id; - if (_.isString(skill)){ - skill = this.getField(skill); - } - //get the final value of the ability score - var ability = this.attributeValue(skill.ability); - - //base modifier - var mod = +getMod(ability) - - //multiply proficiency bonus by largest value in proficiency array - var prof = this.proficiency(skill); - - //add multiplied proficiency bonus to modifier - mod += prof * this.attributeValue("proficiencyBonus"); - - //add all values in add array - _.each(skill.add, function(effect){ - mod += evaluateEffect(charId, effect); - }); - - //multiply all values in mul array - _.each(skill.mul, function(effect){ - mod *= evaluateEffect(charId, effect); - }); - - //largest min - _.each(skill.min, function(effect){ - var min = evaluateEffect(charId, effect); - mod = mod > min? mod : min; - }); - - //smallest max - _.each(skill.max, function(effect){ - var max = evaluateEffect(charId, effect); - mod = mod < max? mod : max; - }); - - return signedString(mod); - }, - passiveSkill: function(skill){ if (_.isString(skill)){ skill = this.getField(skill); diff --git a/rpg-docs/client/globalHelpers/effectList.js b/rpg-docs/client/globalHelpers/effectList.js index 3bc9df75..9ba6c4d2 100644 --- a/rpg-docs/client/globalHelpers/effectList.js +++ b/rpg-docs/client/globalHelpers/effectList.js @@ -1,10 +1,11 @@ -Template.registerHelper("effectList", function(obj, character){ +/*Template.registerHelper(function("effectList", */var disabled = function(charId, fieldName){ + var obj = Characters.findOne(charId, {fields: {_id: 1}}).getField(fieldName); var result = $("
"); if(_.has(obj, "conditional") && obj.conditional.length > 0){ _.each(obj.conditional, function(cond){ var c = $("
") .append("* ") - .append(evaluateString(character, cond.name)); + .append(evaluateString(charId, cond.name)); result.append(c); }); } @@ -19,7 +20,7 @@ Template.registerHelper("effectList", function(obj, character){ if(_.has(obj, "proficiency") && obj.proficiency.length > 0){ var highestProf = {}; _.each(obj.proficiency, function(prof, i){ - var value = evaluateEffect(character, prof) + var value = evaluateEffect(charId, prof) if(i === 0 || value > highestProf.value){ highestProf.value = value; highestProf.name = prof.name; @@ -34,7 +35,7 @@ Template.registerHelper("effectList", function(obj, character){ if(_.has(obj, "add") && obj.add.length > 0){ _.each(obj.add, function(a){ - var value = signedString(evaluateEffect(character, a)); + var value = signedString(evaluateEffect(charId, a)); var c = $("
") .append($("").addClass("auditValue").append(value)) .append(a.name); @@ -44,7 +45,7 @@ Template.registerHelper("effectList", function(obj, character){ if(_.has(obj, "mul") && obj.mul.length > 0){ _.each(obj.mul, function(a){ - var value = signedString(evaluateEffect(character, a)); + var value = signedString(evaluateEffect(charId, a)); var c = $("
") .append($("").addClass("auditValue").append("×").append(value)) .append(a.name); @@ -55,7 +56,7 @@ Template.registerHelper("effectList", function(obj, character){ if(_.has(obj, "min") && obj.min.length > 0){ var highestMin = {}; _.each(obj.min, function(m, i){ - var value = evaluateEffect(character, m) + var value = evaluateEffect(charId, m) if(i === 0 || value > highestMin.value){ highestMin.value = value; highestMin.name = m.name; @@ -71,7 +72,7 @@ Template.registerHelper("effectList", function(obj, character){ if(_.has(obj, "max") && obj.max.length > 0){ var lowestMax = {}; _.each(obj.max, function(m, i){ - var value = evaluateEffect(character, m) + var value = evaluateEffect(charId, m) if(i === 0 || value < lowestMax.value){ lowestMax.value = value; lowestMax.name = m.name; @@ -120,4 +121,4 @@ Template.registerHelper("effectList", function(obj, character){ var string = result.html() if (_.isString(string)) return Spacebars.SafeString(string); return string; -}); \ No newline at end of file +}; \ No newline at end of file diff --git a/rpg-docs/client/main.js b/rpg-docs/client/main.js deleted file mode 100644 index 542bdd1e..00000000 --- a/rpg-docs/client/main.js +++ /dev/null @@ -1,8 +0,0 @@ -_.each(Template, function (template, name) { - if(template){ - var counter = 0; - template.rendered = template.rendered || function () { - console.log(name, "render count: ", ++counter); - }; - } -}); \ No newline at end of file diff --git a/rpg-docs/client/views/character/skills/skills.html b/rpg-docs/client/views/character/skills/skills.html index 88597d28..0fccfb2b 100644 --- a/rpg-docs/client/views/character/skills/skills.html +++ b/rpg-docs/client/views/character/skills/skills.html @@ -2,7 +2,7 @@

Saving Throws

{{#each saveList}} - + {{#if failSkill}} @@ -16,7 +16,7 @@

Skills

fail
{{#each skillList}} - + {{#if failSkill}} diff --git a/rpg-docs/client/views/character/textField/textField.js b/rpg-docs/client/views/character/textField/textField.js index 072d71fc..81646435 100644 --- a/rpg-docs/client/views/character/textField/textField.js +++ b/rpg-docs/client/views/character/textField/textField.js @@ -34,14 +34,13 @@ Template.textField.events({ //TODO sanitise the html var setter = {}; setter[this.field] = text; - Characters.update(this.character._id, {$set: setter}, function(error, result) { - if(error) console.log(error); - }); + Characters.update(this.character._id, {$set: setter}, {removeEmptyStrings: false}); }, "click #textOutput": function(){ Template.instance().editing.set(true); Tracker.afterFlush(function(){ $("#textInput").focus(); + placeCaretAtEnd($("#textInput")); }); } }) \ No newline at end of file diff --git a/rpg-docs/lib/functions/evaluate.js b/rpg-docs/lib/functions/evaluate.js index acc32bde..d97495d6 100644 --- a/rpg-docs/lib/functions/evaluate.js +++ b/rpg-docs/lib/functions/evaluate.js @@ -24,7 +24,7 @@ evaluate = function(charId, string){ } catch(e){ console.log(e) return string; - } + } } //takes a string with {calculations} and returns it with the results diff --git a/rpg-docs/lib/functions/placeCaretAtEnd.js b/rpg-docs/lib/functions/placeCaretAtEnd.js new file mode 100644 index 00000000..da6ec46e --- /dev/null +++ b/rpg-docs/lib/functions/placeCaretAtEnd.js @@ -0,0 +1,18 @@ +placeCaretAtEnd = function(el) { + el = el.get(0); //jquery element -> DOM element + el.focus(); + if (typeof window.getSelection != "undefined" + && typeof document.createRange != "undefined") { + var range = document.createRange(); + range.selectNodeContents(el); + range.collapse(false); + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + } else if (typeof document.body.createTextRange != "undefined") { + var textRange = document.body.createTextRange(); + textRange.moveToElementText(el); + textRange.collapse(false); + textRange.select(); + } +} \ No newline at end of file
fail