Fixed bug where updates on sliders weren't debounced

This commit is contained in:
Stefan Zermatten
2022-11-19 22:39:35 +02:00
parent cc915410da
commit 04c9c4cfc2
3 changed files with 296 additions and 283 deletions

View File

@@ -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;
}