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}}
fail |
@@ -16,7 +16,7 @@
Skills
{{#each skillList}}
-
+
|
{{#if failSkill}}
fail |
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