Fixed bug where updates on sliders weren't debounced
This commit is contained in:
@@ -3,183 +3,183 @@ Characters = new Mongo.Collection("characters");
|
||||
|
||||
Schemas.Character = new SimpleSchema({
|
||||
//strings
|
||||
name: {type: String, defaultValue: "", trim: false, optional: true, max: 128},
|
||||
urlName: {type: String, defaultValue: "-", trim: false, optional: true, max: 128},
|
||||
alignment: {type: String, defaultValue: "", trim: false, optional: true, max: 64},
|
||||
gender: {type: String, defaultValue: "", trim: false, optional: true, max: 64},
|
||||
race: {type: String, defaultValue: "", trim: false, optional: true, max: 64},
|
||||
picture: {type: String, defaultValue: "", trim: true, optional: true, max: 256},
|
||||
description: {type: String, defaultValue: "", trim: false, optional: true, max: 5000},
|
||||
personality: {type: String, defaultValue: "", trim: false, optional: true, max: 5000},
|
||||
ideals: {type: String, defaultValue: "", trim: false, optional: true, max: 5000},
|
||||
bonds: {type: String, defaultValue: "", trim: false, optional: true, max: 5000},
|
||||
flaws: {type: String, defaultValue: "", trim: false, optional: true, max: 5000},
|
||||
backstory: {type: String, defaultValue: "", trim: false, optional: true, max: 5000},
|
||||
name: { type: String, defaultValue: "", trim: false, optional: true, max: 128 },
|
||||
urlName: { type: String, defaultValue: "-", trim: false, optional: true, max: 128 },
|
||||
alignment: { type: String, defaultValue: "", trim: false, optional: true, max: 64 },
|
||||
gender: { type: String, defaultValue: "", trim: false, optional: true, max: 64 },
|
||||
race: { type: String, defaultValue: "", trim: false, optional: true, max: 64 },
|
||||
picture: { type: String, defaultValue: "", trim: true, optional: true, max: 256 },
|
||||
description: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 },
|
||||
personality: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 },
|
||||
ideals: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 },
|
||||
bonds: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 },
|
||||
flaws: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 },
|
||||
backstory: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 },
|
||||
|
||||
//attributes
|
||||
//ability scores
|
||||
strength: {type: Schemas.Attribute},
|
||||
dexterity: {type: Schemas.Attribute},
|
||||
constitution: {type: Schemas.Attribute},
|
||||
intelligence: {type: Schemas.Attribute},
|
||||
wisdom: {type: Schemas.Attribute},
|
||||
charisma: {type: Schemas.Attribute},
|
||||
strength: { type: Schemas.Attribute },
|
||||
dexterity: { type: Schemas.Attribute },
|
||||
constitution: { type: Schemas.Attribute },
|
||||
intelligence: { type: Schemas.Attribute },
|
||||
wisdom: { type: Schemas.Attribute },
|
||||
charisma: { type: Schemas.Attribute },
|
||||
|
||||
//stats
|
||||
hitPoints: {type: Schemas.Attribute},
|
||||
tempHP: {type: Schemas.Attribute},
|
||||
experience: {type: Schemas.Attribute},
|
||||
proficiencyBonus: {type: Schemas.Attribute},
|
||||
speed: {type: Schemas.Attribute},
|
||||
weight: {type: Schemas.Attribute},
|
||||
age: {type: Schemas.Attribute},
|
||||
ageRate: {type: Schemas.Attribute},
|
||||
armor: {type: Schemas.Attribute},
|
||||
carryMultiplier: {type: Schemas.Attribute},
|
||||
hitPoints: { type: Schemas.Attribute },
|
||||
tempHP: { type: Schemas.Attribute },
|
||||
experience: { type: Schemas.Attribute },
|
||||
proficiencyBonus: { type: Schemas.Attribute },
|
||||
speed: { type: Schemas.Attribute },
|
||||
weight: { type: Schemas.Attribute },
|
||||
age: { type: Schemas.Attribute },
|
||||
ageRate: { type: Schemas.Attribute },
|
||||
armor: { type: Schemas.Attribute },
|
||||
carryMultiplier: { type: Schemas.Attribute },
|
||||
|
||||
//resources
|
||||
level1SpellSlots: {type: Schemas.Attribute},
|
||||
level2SpellSlots: {type: Schemas.Attribute},
|
||||
level3SpellSlots: {type: Schemas.Attribute},
|
||||
level4SpellSlots: {type: Schemas.Attribute},
|
||||
level5SpellSlots: {type: Schemas.Attribute},
|
||||
level6SpellSlots: {type: Schemas.Attribute},
|
||||
level7SpellSlots: {type: Schemas.Attribute},
|
||||
level8SpellSlots: {type: Schemas.Attribute},
|
||||
level9SpellSlots: {type: Schemas.Attribute},
|
||||
ki: {type: Schemas.Attribute},
|
||||
sorceryPoints: {type: Schemas.Attribute},
|
||||
rages: {type: Schemas.Attribute},
|
||||
superiorityDice: {type: Schemas.Attribute},
|
||||
expertiseDice: {type: Schemas.Attribute},
|
||||
level1SpellSlots: { type: Schemas.Attribute },
|
||||
level2SpellSlots: { type: Schemas.Attribute },
|
||||
level3SpellSlots: { type: Schemas.Attribute },
|
||||
level4SpellSlots: { type: Schemas.Attribute },
|
||||
level5SpellSlots: { type: Schemas.Attribute },
|
||||
level6SpellSlots: { type: Schemas.Attribute },
|
||||
level7SpellSlots: { type: Schemas.Attribute },
|
||||
level8SpellSlots: { type: Schemas.Attribute },
|
||||
level9SpellSlots: { type: Schemas.Attribute },
|
||||
ki: { type: Schemas.Attribute },
|
||||
sorceryPoints: { type: Schemas.Attribute },
|
||||
rages: { type: Schemas.Attribute },
|
||||
superiorityDice: { type: Schemas.Attribute },
|
||||
expertiseDice: { type: Schemas.Attribute },
|
||||
|
||||
//specific features
|
||||
rageDamage: {type: Schemas.Attribute},
|
||||
rageDamage: { type: Schemas.Attribute },
|
||||
|
||||
//hit dice
|
||||
d6HitDice: {type: Schemas.Attribute},
|
||||
d8HitDice: {type: Schemas.Attribute},
|
||||
d10HitDice: {type: Schemas.Attribute},
|
||||
d12HitDice: {type: Schemas.Attribute},
|
||||
d6HitDice: { type: Schemas.Attribute },
|
||||
d8HitDice: { type: Schemas.Attribute },
|
||||
d10HitDice: { type: Schemas.Attribute },
|
||||
d12HitDice: { type: Schemas.Attribute },
|
||||
|
||||
//vulnerabilities
|
||||
acidMultiplier: {type: Schemas.Attribute},
|
||||
bludgeoningMultiplier: {type: Schemas.Attribute},
|
||||
coldMultiplier: {type: Schemas.Attribute},
|
||||
fireMultiplier: {type: Schemas.Attribute},
|
||||
forceMultiplier: {type: Schemas.Attribute},
|
||||
lightningMultiplier: {type: Schemas.Attribute},
|
||||
necroticMultiplier: {type: Schemas.Attribute},
|
||||
piercingMultiplier: {type: Schemas.Attribute},
|
||||
poisonMultiplier: {type: Schemas.Attribute},
|
||||
psychicMultiplier: {type: Schemas.Attribute},
|
||||
radiantMultiplier: {type: Schemas.Attribute},
|
||||
slashingMultiplier: {type: Schemas.Attribute},
|
||||
thunderMultiplier: {type: Schemas.Attribute},
|
||||
acidMultiplier: { type: Schemas.Attribute },
|
||||
bludgeoningMultiplier: { type: Schemas.Attribute },
|
||||
coldMultiplier: { type: Schemas.Attribute },
|
||||
fireMultiplier: { type: Schemas.Attribute },
|
||||
forceMultiplier: { type: Schemas.Attribute },
|
||||
lightningMultiplier: { type: Schemas.Attribute },
|
||||
necroticMultiplier: { type: Schemas.Attribute },
|
||||
piercingMultiplier: { type: Schemas.Attribute },
|
||||
poisonMultiplier: { type: Schemas.Attribute },
|
||||
psychicMultiplier: { type: Schemas.Attribute },
|
||||
radiantMultiplier: { type: Schemas.Attribute },
|
||||
slashingMultiplier: { type: Schemas.Attribute },
|
||||
thunderMultiplier: { type: Schemas.Attribute },
|
||||
|
||||
//skills
|
||||
//saves
|
||||
strengthSave: {type: Schemas.Skill},
|
||||
"strengthSave.ability": {type: String, defaultValue: "strength"},
|
||||
strengthSave: { type: Schemas.Skill },
|
||||
"strengthSave.ability": { type: String, defaultValue: "strength" },
|
||||
|
||||
dexteritySave: {type: Schemas.Skill},
|
||||
"dexteritySave.ability": {type: String, defaultValue: "dexterity"},
|
||||
dexteritySave: { type: Schemas.Skill },
|
||||
"dexteritySave.ability": { type: String, defaultValue: "dexterity" },
|
||||
|
||||
constitutionSave:{type: Schemas.Skill},
|
||||
"constitutionSave.ability": {type: String, defaultValue: "constitution"},
|
||||
constitutionSave: { type: Schemas.Skill },
|
||||
"constitutionSave.ability": { type: String, defaultValue: "constitution" },
|
||||
|
||||
intelligenceSave:{type: Schemas.Skill},
|
||||
"intelligenceSave.ability": {type: String, defaultValue: "intelligence"},
|
||||
intelligenceSave: { type: Schemas.Skill },
|
||||
"intelligenceSave.ability": { type: String, defaultValue: "intelligence" },
|
||||
|
||||
wisdomSave: {type: Schemas.Skill},
|
||||
"wisdomSave.ability": {type: String, defaultValue: "wisdom"},
|
||||
wisdomSave: { type: Schemas.Skill },
|
||||
"wisdomSave.ability": { type: String, defaultValue: "wisdom" },
|
||||
|
||||
charismaSave: {type: Schemas.Skill},
|
||||
"charismaSave.ability": {type: String, defaultValue: "charisma"},
|
||||
charismaSave: { type: Schemas.Skill },
|
||||
"charismaSave.ability": { type: String, defaultValue: "charisma" },
|
||||
|
||||
//skill skills
|
||||
acrobatics: {type: Schemas.Skill},
|
||||
"acrobatics.ability": {type: String, defaultValue: "dexterity"},
|
||||
acrobatics: { type: Schemas.Skill },
|
||||
"acrobatics.ability": { type: String, defaultValue: "dexterity" },
|
||||
|
||||
animalHandling: {type: Schemas.Skill},
|
||||
"animalHandling.ability": {type: String, defaultValue: "wisdom"},
|
||||
animalHandling: { type: Schemas.Skill },
|
||||
"animalHandling.ability": { type: String, defaultValue: "wisdom" },
|
||||
|
||||
arcana: {type: Schemas.Skill},
|
||||
"arcana.ability": {type: String, defaultValue: "intelligence"},
|
||||
arcana: { type: Schemas.Skill },
|
||||
"arcana.ability": { type: String, defaultValue: "intelligence" },
|
||||
|
||||
athletics: {type: Schemas.Skill},
|
||||
"athletics.ability": {type: String, defaultValue: "strength"},
|
||||
athletics: { type: Schemas.Skill },
|
||||
"athletics.ability": { type: String, defaultValue: "strength" },
|
||||
|
||||
deception: {type: Schemas.Skill},
|
||||
"deception.ability": {type: String, defaultValue: "charisma"},
|
||||
deception: { type: Schemas.Skill },
|
||||
"deception.ability": { type: String, defaultValue: "charisma" },
|
||||
|
||||
history: {type: Schemas.Skill},
|
||||
"history.ability": {type: String, defaultValue: "intelligence"},
|
||||
history: { type: Schemas.Skill },
|
||||
"history.ability": { type: String, defaultValue: "intelligence" },
|
||||
|
||||
insight: {type: Schemas.Skill},
|
||||
"insight.ability": {type: String, defaultValue: "wisdom"},
|
||||
insight: { type: Schemas.Skill },
|
||||
"insight.ability": { type: String, defaultValue: "wisdom" },
|
||||
|
||||
intimidation: {type: Schemas.Skill},
|
||||
"intimidation.ability": {type: String, defaultValue: "charisma"},
|
||||
intimidation: { type: Schemas.Skill },
|
||||
"intimidation.ability": { type: String, defaultValue: "charisma" },
|
||||
|
||||
investigation: {type: Schemas.Skill},
|
||||
"investigation.ability": {type: String, defaultValue: "intelligence"},
|
||||
investigation: { type: Schemas.Skill },
|
||||
"investigation.ability": { type: String, defaultValue: "intelligence" },
|
||||
|
||||
medicine: {type: Schemas.Skill},
|
||||
"medicine.ability": {type: String, defaultValue: "wisdom"},
|
||||
medicine: { type: Schemas.Skill },
|
||||
"medicine.ability": { type: String, defaultValue: "wisdom" },
|
||||
|
||||
nature: {type: Schemas.Skill},
|
||||
"nature.ability": {type: String, defaultValue: "intelligence"},
|
||||
nature: { type: Schemas.Skill },
|
||||
"nature.ability": { type: String, defaultValue: "intelligence" },
|
||||
|
||||
perception: {type: Schemas.Skill},
|
||||
"perception.ability": {type: String, defaultValue: "wisdom"},
|
||||
perception: { type: Schemas.Skill },
|
||||
"perception.ability": { type: String, defaultValue: "wisdom" },
|
||||
|
||||
performance: {type: Schemas.Skill},
|
||||
"performance.ability": {type: String, defaultValue: "charisma"},
|
||||
performance: { type: Schemas.Skill },
|
||||
"performance.ability": { type: String, defaultValue: "charisma" },
|
||||
|
||||
persuasion: {type: Schemas.Skill},
|
||||
"persuasion.ability": {type: String, defaultValue: "charisma"},
|
||||
persuasion: { type: Schemas.Skill },
|
||||
"persuasion.ability": { type: String, defaultValue: "charisma" },
|
||||
|
||||
religion: {type: Schemas.Skill},
|
||||
"religion.ability": {type: String, defaultValue: "intelligence"},
|
||||
religion: { type: Schemas.Skill },
|
||||
"religion.ability": { type: String, defaultValue: "intelligence" },
|
||||
|
||||
sleightOfHand: {type: Schemas.Skill},
|
||||
"sleightOfHand.ability": {type: String, defaultValue: "dexterity"},
|
||||
sleightOfHand: { type: Schemas.Skill },
|
||||
"sleightOfHand.ability": { type: String, defaultValue: "dexterity" },
|
||||
|
||||
stealth: {type: Schemas.Skill},
|
||||
"stealth.ability": {type: String, defaultValue: "dexterity"},
|
||||
stealth: { type: Schemas.Skill },
|
||||
"stealth.ability": { type: String, defaultValue: "dexterity" },
|
||||
|
||||
survival: {type: Schemas.Skill},
|
||||
"survival.ability": {type: String, defaultValue: "wisdom"},
|
||||
survival: { type: Schemas.Skill },
|
||||
"survival.ability": { type: String, defaultValue: "wisdom" },
|
||||
|
||||
//Mechanical Skills
|
||||
initiative: {type: Schemas.Skill},
|
||||
"initiative.ability": {type: String, defaultValue: "dexterity"},
|
||||
initiative: { type: Schemas.Skill },
|
||||
"initiative.ability": { type: String, defaultValue: "dexterity" },
|
||||
|
||||
dexterityArmor: {type: Schemas.Skill},
|
||||
"dexterityArmor.ability": {type: String, defaultValue: "dexterity"},
|
||||
dexterityArmor: { type: Schemas.Skill },
|
||||
"dexterityArmor.ability": { type: String, defaultValue: "dexterity" },
|
||||
|
||||
//mechanics
|
||||
deathSave: {type: Schemas.DeathSave},
|
||||
deathSave: { type: Schemas.DeathSave },
|
||||
|
||||
//permissions
|
||||
party: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true},
|
||||
owner: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||
readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1},
|
||||
writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1},
|
||||
color: {
|
||||
party: { type: String, regEx: SimpleSchema.RegEx.Id, optional: true },
|
||||
owner: { type: String, regEx: SimpleSchema.RegEx.Id, index: 1 },
|
||||
readers: { type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1 },
|
||||
writers: { type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1 },
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
//TODO add per-character settings
|
||||
//how many experiences to load at a time in XP table
|
||||
"settings.experiencesInc": {type: Number, defaultValue: 20},
|
||||
"settings.experiencesInc": { type: Number, defaultValue: 20 },
|
||||
//slowed down by carrying too much?
|
||||
"settings.useVariantEncumbrance": {type: Boolean, defaultValue: false},
|
||||
"settings.useStandardEncumbrance": {type: Boolean, defaultValue: true},
|
||||
"settings.useVariantEncumbrance": { type: Boolean, defaultValue: false },
|
||||
"settings.useStandardEncumbrance": { type: Boolean, defaultValue: true },
|
||||
//hide spellcasting
|
||||
"settings.hideSpellcasting": {type: Boolean, defaultValue: false},
|
||||
"settings.hideSpellcasting": { type: Boolean, defaultValue: false },
|
||||
//show to anyone with link
|
||||
"settings.viewPermission": {
|
||||
type: String,
|
||||
@@ -187,19 +187,19 @@ Schemas.Character = new SimpleSchema({
|
||||
allowedValues: ["whitelist", "public"],
|
||||
index: 1,
|
||||
},
|
||||
"settings.swapStatAndModifier": {type: Boolean, defaultValue: false},
|
||||
"settings.exportFeatures": {type: Boolean, defaultValue: true},
|
||||
"settings.exportAttacks": {type: Boolean, defaultValue: true},
|
||||
"settings.exportDescription": {type: Boolean, defaultValue: true},
|
||||
"settings.newUserExperience": {type: Boolean, optional: true},
|
||||
"settings.swapStatAndModifier": { type: Boolean, defaultValue: false },
|
||||
"settings.exportFeatures": { type: Boolean, defaultValue: true },
|
||||
"settings.exportAttacks": { type: Boolean, defaultValue: true },
|
||||
"settings.exportDescription": { type: Boolean, defaultValue: true },
|
||||
"settings.newUserExperience": { type: Boolean, optional: true },
|
||||
});
|
||||
|
||||
Characters.attachSchema(Schemas.Character);
|
||||
|
||||
var attributeBase = preventLoop(function(charId, statName){
|
||||
var attributeBase = preventLoop(function (charId, statName) {
|
||||
check(statName, String);
|
||||
//if it's a damage multiplier, we treat it specially
|
||||
if (_.contains(DAMAGE_MULTIPLIERS, statName)){
|
||||
if (_.contains(DAMAGE_MULTIPLIERS, statName)) {
|
||||
var invulnerabilityCount = Effects.find({
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
@@ -222,11 +222,11 @@ var attributeBase = preventLoop(function(charId, statName){
|
||||
operation: "mul",
|
||||
value: 2,
|
||||
}).count();
|
||||
if (!resistCount && !vulnCount){
|
||||
if (!resistCount && !vulnCount) {
|
||||
return 1;
|
||||
} else if (resistCount && !vulnCount){
|
||||
} else if (resistCount && !vulnCount) {
|
||||
return 0.5;
|
||||
} else if (!resistCount && vulnCount){
|
||||
} else if (!resistCount && vulnCount) {
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
@@ -243,18 +243,18 @@ var attributeBase = preventLoop(function(charId, statName){
|
||||
charId: charId,
|
||||
stat: statName,
|
||||
enabled: true,
|
||||
operation: {$in: ["base", "add", "mul", "min", "max"]},
|
||||
}).forEach(function(effect) {
|
||||
operation: { $in: ["base", "add", "mul", "min", "max"] },
|
||||
}).forEach(function (effect) {
|
||||
value = evaluateEffect(charId, effect);
|
||||
if (effect.operation === "base"){
|
||||
if (effect.operation === "base") {
|
||||
if (value > base) base = value;
|
||||
} else if (effect.operation === "add"){
|
||||
} else if (effect.operation === "add") {
|
||||
add += value;
|
||||
} else if (effect.operation === "mul"){
|
||||
} else if (effect.operation === "mul") {
|
||||
mul *= value;
|
||||
} else if (effect.operation === "min"){
|
||||
} else if (effect.operation === "min") {
|
||||
if (value > min) min = value;
|
||||
} else if (effect.operation === "max"){
|
||||
} else if (effect.operation === "max") {
|
||||
if (value < max) max = value;
|
||||
}
|
||||
});
|
||||
@@ -263,18 +263,18 @@ var attributeBase = preventLoop(function(charId, statName){
|
||||
if (result < min) result = min;
|
||||
if (result > max) result = max;
|
||||
// Don't round carry multiplier
|
||||
if (statName === "carryMultiplier"){
|
||||
if (statName === "carryMultiplier") {
|
||||
return result;
|
||||
}
|
||||
return Math.floor(result);
|
||||
});
|
||||
|
||||
if (Meteor.isClient) {
|
||||
Template.registerHelper("characterCalculate", function(func, charId, input) {
|
||||
Template.registerHelper("characterCalculate", function (func, charId, input) {
|
||||
try {
|
||||
return Characters.calculate[func](charId, input);
|
||||
} catch (e){
|
||||
if (!Characters.calculate[func]){
|
||||
} catch (e) {
|
||||
if (!Characters.calculate[func]) {
|
||||
throw new Error(func + "is not a function name");
|
||||
} else {
|
||||
throw e;
|
||||
@@ -284,10 +284,10 @@ if (Meteor.isClient) {
|
||||
}
|
||||
|
||||
//create a local memoize with a argument concatenating hash function
|
||||
var memoize = function(f) {
|
||||
var memoize = function (f) {
|
||||
if (Meteor.isServer) return f;
|
||||
return Tracker.memoize(f, function() {
|
||||
return _.reduce(arguments, function(memo, arg) {
|
||||
return Tracker.memoize(f, function () {
|
||||
return _.reduce(arguments, function (memo, arg) {
|
||||
return memo + arg;
|
||||
}, "");
|
||||
});
|
||||
@@ -295,13 +295,13 @@ var memoize = function(f) {
|
||||
|
||||
//memoize funcitons that have finds and slow loops
|
||||
Characters.calculate = {
|
||||
getField: function(charId, fieldName) {
|
||||
getField: function (charId, fieldName) {
|
||||
var fieldSelector = {};
|
||||
fieldSelector[fieldName] = 1;
|
||||
var char = Characters.findOne(charId, {fields: fieldSelector});
|
||||
var char = Characters.findOne(charId, { fields: fieldSelector });
|
||||
if (!char) return;
|
||||
var field = char[fieldName];
|
||||
if (field === undefined){
|
||||
if (field === undefined) {
|
||||
throw new Meteor.Error(
|
||||
"getField failed",
|
||||
"getField could not find field " +
|
||||
@@ -312,8 +312,8 @@ Characters.calculate = {
|
||||
}
|
||||
return field;
|
||||
},
|
||||
fieldValue: function(charId, fieldName) {
|
||||
if (!Schemas.Character.schema(fieldName)){
|
||||
fieldValue: function (charId, fieldName) {
|
||||
if (!Schemas.Character.schema(fieldName)) {
|
||||
throw new Meteor.Error(
|
||||
"Field not found",
|
||||
"Character's schema does not contain a field called: " + fieldName
|
||||
@@ -321,17 +321,17 @@ Characters.calculate = {
|
||||
}
|
||||
//duck typing to get the right value function
|
||||
//.ability implies skill
|
||||
if (Schemas.Character.schema(fieldName + ".ability")){
|
||||
if (Schemas.Character.schema(fieldName + ".ability")) {
|
||||
return Characters.calculate.skillMod(charId, fieldName);
|
||||
}
|
||||
//adjustment implies attribute
|
||||
if (Schemas.Character.schema(fieldName + ".adjustment")){
|
||||
if (Schemas.Character.schema(fieldName + ".adjustment")) {
|
||||
return Characters.calculate.attributeValue(charId, fieldName);
|
||||
}
|
||||
//fall back to just returning the field itself
|
||||
return Characters.calculate.getField(charId, fieldName);
|
||||
},
|
||||
attributeValue: memoize(function(charId, attributeName){
|
||||
attributeValue: memoize(function (charId, attributeName) {
|
||||
var attribute = Characters.calculate.getField(charId, attributeName);
|
||||
if (!attribute) return;
|
||||
//base value
|
||||
@@ -340,10 +340,10 @@ Characters.calculate = {
|
||||
value += attribute.adjustment;
|
||||
return value;
|
||||
}),
|
||||
attributeBase: memoize(function(charId, attributeName){
|
||||
attributeBase: memoize(function (charId, attributeName) {
|
||||
return attributeBase(charId, attributeName);
|
||||
}),
|
||||
skillMod: memoize(preventLoop(function(charId, skillName){
|
||||
skillMod: memoize(preventLoop(function (charId, skillName) {
|
||||
var skill = Characters.calculate.getField(charId, skillName);
|
||||
if (!skill) return;
|
||||
//get the final value of the ability score
|
||||
@@ -369,16 +369,16 @@ Characters.calculate = {
|
||||
charId: charId,
|
||||
stat: skillName,
|
||||
enabled: true,
|
||||
operation: {$in: ["base", "add", "mul", "min", "max"]},
|
||||
}).forEach(function(effect) {
|
||||
operation: { $in: ["base", "add", "mul", "min", "max"] },
|
||||
}).forEach(function (effect) {
|
||||
value = evaluateEffect(charId, effect);
|
||||
if (effect.operation === "add"){
|
||||
if (effect.operation === "add") {
|
||||
add += value;
|
||||
} else if (effect.operation === "mul"){
|
||||
} else if (effect.operation === "mul") {
|
||||
mul *= value;
|
||||
} else if (effect.operation === "min"){
|
||||
} else if (effect.operation === "min") {
|
||||
if (value > min) min = value;
|
||||
} else if (effect.operation === "max"){
|
||||
} else if (effect.operation === "max") {
|
||||
if (value < max) max = value;
|
||||
}
|
||||
});
|
||||
@@ -388,83 +388,83 @@ Characters.calculate = {
|
||||
|
||||
return Math.floor(result);
|
||||
})),
|
||||
proficiency: memoize(function(charId, skillName){
|
||||
proficiency: memoize(function (charId, skillName) {
|
||||
//return largest value in proficiency array
|
||||
var prof = Proficiencies.findOne(
|
||||
{charId: charId, name: skillName, enabled: true},
|
||||
{sort: {value: -1}}
|
||||
{ charId: charId, name: skillName, enabled: true },
|
||||
{ sort: { value: -1 } }
|
||||
);
|
||||
return prof && prof.value || 0;
|
||||
}),
|
||||
passiveSkill: memoize(function(charId, skillName){
|
||||
passiveSkill: memoize(function (charId, skillName) {
|
||||
var mod = +Characters.calculate.skillMod(charId, skillName);
|
||||
var value = 10 + mod;
|
||||
Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "passiveAdd"}
|
||||
).forEach(function(effect){
|
||||
{ charId: charId, stat: skillName, enabled: true, operation: "passiveAdd" }
|
||||
).forEach(function (effect) {
|
||||
value += evaluateEffect(charId, effect);
|
||||
});
|
||||
var advantage = Characters.calculate.advantage(charId, skillName);
|
||||
value += 5 * advantage;
|
||||
return Math.floor(value);
|
||||
}),
|
||||
advantage: memoize(function(charId, skillName){
|
||||
advantage: memoize(function (charId, skillName) {
|
||||
var advantage = Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "advantage"}
|
||||
{ charId: charId, stat: skillName, enabled: true, operation: "advantage" }
|
||||
).count();
|
||||
var disadvantage = Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "disadvantage"}
|
||||
{ charId: charId, stat: skillName, enabled: true, operation: "disadvantage" }
|
||||
).count();
|
||||
if (advantage && !disadvantage) return 1;
|
||||
if (disadvantage && !advantage) return -1;
|
||||
return 0;
|
||||
}),
|
||||
abilityMod: function(charId, attribute){
|
||||
abilityMod: function (charId, attribute) {
|
||||
return getMod(
|
||||
Characters.calculate.attributeValue(charId, attribute)
|
||||
);
|
||||
},
|
||||
passiveAbility: function(charId, attribute){
|
||||
passiveAbility: function (charId, attribute) {
|
||||
var mod = +getMod(Characters.calculate.attributeValue(charId, attribute));
|
||||
return 10 + mod;
|
||||
},
|
||||
xpLevel: function(charId){
|
||||
xpLevel: function (charId) {
|
||||
var xp = Characters.calculate.experience(charId);
|
||||
for (var i = 0; i < 19; i++){
|
||||
if (xp < XP_TABLE[i]){
|
||||
for (var i = 0; i < 19; i++) {
|
||||
if (xp < XP_TABLE[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (xp > 355000) return 20;
|
||||
return 0;
|
||||
},
|
||||
level: memoize(function(charId){
|
||||
level: memoize(function (charId) {
|
||||
var level = 0;
|
||||
Classes.find({charId: charId}).forEach(function(cls){
|
||||
Classes.find({ charId: charId }).forEach(function (cls) {
|
||||
level += cls.level;
|
||||
});
|
||||
return level;
|
||||
}),
|
||||
experience: memoize(function(charId){
|
||||
experience: memoize(function (charId) {
|
||||
var xp = 0;
|
||||
Experiences.find(
|
||||
{charId: charId},
|
||||
{fields: {value: 1}}
|
||||
).forEach(function(e){
|
||||
{ charId: charId },
|
||||
{ fields: { value: 1 } }
|
||||
).forEach(function (e) {
|
||||
xp += e.value;
|
||||
});
|
||||
return xp;
|
||||
}),
|
||||
};
|
||||
|
||||
var deprecated = function() {
|
||||
var deprecated = function () {
|
||||
//var err = new Error("this function has been deprecated");
|
||||
var name = "";
|
||||
if (Template.instance()){
|
||||
if (Template.instance()) {
|
||||
name = Template.instance().view.name;
|
||||
}
|
||||
var logString = "this function has been deprecated \n";
|
||||
if (name){
|
||||
if (name) {
|
||||
logString += "View: " + name + "\n\n";
|
||||
}
|
||||
//logString += err.stack + "\n\n---------------------\n\n";
|
||||
@@ -477,104 +477,104 @@ var deprecated = function() {
|
||||
Characters.helpers({
|
||||
//returns the value stored in the field requested
|
||||
//will set up dependencies on just that field
|
||||
getField : function(fieldName){
|
||||
getField: function (fieldName) {
|
||||
deprecated();
|
||||
return Characters.calculate.getField(this._id, fieldName);
|
||||
},
|
||||
//returns the value of a field
|
||||
fieldValue : function(fieldName){
|
||||
fieldValue: function (fieldName) {
|
||||
deprecated();
|
||||
return Characters.calculate.fieldValue(this._id, fieldName);
|
||||
},
|
||||
attributeValue: function(attributeName){
|
||||
attributeValue: function (attributeName) {
|
||||
deprecated();
|
||||
return Characters.calculate.attributeValue(this._id, attributeName);
|
||||
},
|
||||
attributeBase: function(attributeName){
|
||||
attributeBase: function (attributeName) {
|
||||
deprecated();
|
||||
return Characters.calculate.attributeBase(this._id, attributeName);
|
||||
},
|
||||
skillMod: function(skillName){
|
||||
skillMod: function (skillName) {
|
||||
deprecated();
|
||||
return Characters.calculate.skillMod(this._id, skillName);
|
||||
},
|
||||
proficiency: function(skillName){
|
||||
proficiency: function (skillName) {
|
||||
deprecated();
|
||||
return Characters.calculate.proficiency(this._id, skillName);
|
||||
},
|
||||
passiveSkill: function(skillName){
|
||||
passiveSkill: function (skillName) {
|
||||
deprecated();
|
||||
return Characters.calculate.passiveSkill(this._id, skillName);
|
||||
},
|
||||
advantage: function(skillName){
|
||||
advantage: function (skillName) {
|
||||
deprecated();
|
||||
return Characters.calculate.advantage(this._id, skillName);
|
||||
},
|
||||
abilityMod: function(attribute){
|
||||
abilityMod: function (attribute) {
|
||||
deprecated();
|
||||
return Characters.calculate.abilityMod(this._id, attribute);
|
||||
},
|
||||
passiveAbility: function(attribute){
|
||||
passiveAbility: function (attribute) {
|
||||
deprecated();
|
||||
return Characters.calculate.passiveAbility(this._id, attribute);
|
||||
},
|
||||
xpLevel: function(){
|
||||
xpLevel: function () {
|
||||
deprecated();
|
||||
return Characters.calculate.xpLevel(this._id);
|
||||
},
|
||||
level: function(){
|
||||
level: function () {
|
||||
deprecated();
|
||||
return Characters.calculate.level(this._id);
|
||||
},
|
||||
experience: function(){
|
||||
experience: function () {
|
||||
deprecated();
|
||||
return Characters.calculate.experience(this._id);
|
||||
},
|
||||
});
|
||||
|
||||
//clean up all data related to that character before removing it
|
||||
if (Meteor.isServer){
|
||||
Characters.after.remove(function(userId, character) {
|
||||
Actions .remove({charId: character._id});
|
||||
Attacks .remove({charId: character._id});
|
||||
Buffs .remove({charId: character._id});
|
||||
Classes .remove({charId: character._id});
|
||||
CustomBuffs .remove({charId: character._id});
|
||||
Effects .remove({charId: character._id});
|
||||
Experiences .remove({charId: character._id});
|
||||
Features .remove({charId: character._id});
|
||||
Notes .remove({charId: character._id});
|
||||
Proficiencies .remove({charId: character._id});
|
||||
SpellLists .remove({charId: character._id});
|
||||
Items .remove({charId: character._id});
|
||||
Containers .remove({charId: character._id});
|
||||
if (Meteor.isServer) {
|
||||
Characters.after.remove(function (userId, character) {
|
||||
Actions.remove({ charId: character._id });
|
||||
Attacks.remove({ charId: character._id });
|
||||
Buffs.remove({ charId: character._id });
|
||||
Classes.remove({ charId: character._id });
|
||||
CustomBuffs.remove({ charId: character._id });
|
||||
Effects.remove({ charId: character._id });
|
||||
Experiences.remove({ charId: character._id });
|
||||
Features.remove({ charId: character._id });
|
||||
Notes.remove({ charId: character._id });
|
||||
Proficiencies.remove({ charId: character._id });
|
||||
SpellLists.remove({ charId: character._id });
|
||||
Items.remove({ charId: character._id });
|
||||
Containers.remove({ charId: character._id });
|
||||
});
|
||||
Characters.after.update(function(userId, doc, fieldNames, modifier, options) {
|
||||
if (_.contains(fieldNames, "name")){
|
||||
var urlName = getSlug(doc.name, {maintainCase: true}) || "-";
|
||||
Characters.update(doc._id, {$set: {urlName}});
|
||||
Characters.after.update(function (userId, doc, fieldNames, modifier, options) {
|
||||
if (_.contains(fieldNames, "name")) {
|
||||
var urlName = getSlug(doc.name, { maintainCase: true }) || "-";
|
||||
Characters.update(doc._id, { $set: { urlName } });
|
||||
}
|
||||
});
|
||||
Characters.before.insert(function(userId, doc) {
|
||||
doc.urlName = getSlug(doc.name, {maintainCase: true}) || "-";
|
||||
Characters.before.insert(function (userId, doc) {
|
||||
doc.urlName = getSlug(doc.name, { maintainCase: true }) || "-";
|
||||
// The first character a user creates should have the new user experience
|
||||
if (!Characters.find({owner: userId}).count()){
|
||||
if (!Characters.find({ owner: userId }).count()) {
|
||||
doc.settings.newUserExperience = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Characters.allow({
|
||||
insert: function(userId, doc) {
|
||||
insert: function (userId, doc) {
|
||||
// the user must be logged in, and the document must be owned by the user
|
||||
return (userId && doc.owner === userId);
|
||||
},
|
||||
update: function(userId, doc, fields, modifier) {
|
||||
update: function (userId, doc, fields, modifier) {
|
||||
// can only change documents you have write access to
|
||||
return doc.owner === userId ||
|
||||
_.contains(doc.writers, userId);
|
||||
},
|
||||
remove: function(userId, doc) {
|
||||
remove: function (userId, doc) {
|
||||
// can only remove your own documents
|
||||
return doc.owner === userId;
|
||||
},
|
||||
@@ -582,7 +582,7 @@ Characters.allow({
|
||||
});
|
||||
|
||||
Characters.deny({
|
||||
update: function(userId, doc, fields, modifier) {
|
||||
update: function (userId, doc, fields, modifier) {
|
||||
// can't change owners unless you are the current owner
|
||||
return _.contains(fields, "owner") && doc.owner !== userId;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user