Implemented a javascript code style
This commit is contained in:
56
.jscsrc
Normal file
56
.jscsrc
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"requireOperatorBeforeLineBreak": true,
|
||||
"requireCamelCaseOrUpperCaseIdentifiers": true,
|
||||
"maximumLineLength": {
|
||||
"value": 80,
|
||||
"allowComments": true,
|
||||
"allowRegex": true
|
||||
},
|
||||
"validateIndentation": "\t",
|
||||
"validateQuoteMarks": "\"",
|
||||
|
||||
"disallowMultipleLineStrings": true,
|
||||
"disallowMixedSpacesAndTabs": "smart",
|
||||
"disallowTrailingWhitespace": true,
|
||||
"disallowSpaceAfterPrefixUnaryOperators": true,
|
||||
"disallowMultipleVarDecl": true,
|
||||
"disallowNewlineBeforeBlockStatements": true,
|
||||
"disallowKeywordsOnNewLine": ["else"],
|
||||
|
||||
"requireSpaceAfterKeywords": [
|
||||
"if",
|
||||
"else",
|
||||
"for",
|
||||
"while",
|
||||
"do",
|
||||
"switch",
|
||||
"return",
|
||||
"try",
|
||||
"catch"
|
||||
],
|
||||
"requireSpaceBeforeBinaryOperators": [
|
||||
"=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
|
||||
"&=", "|=", "^=", "+=",
|
||||
|
||||
"+", "-", "*", "/", "%", "<<", ">>", ">>>", "&",
|
||||
"|", "^", "&&", "||", "===", "==", ">=",
|
||||
"<=", "<", ">", "!=", "!=="
|
||||
],
|
||||
"requireSpaceAfterBinaryOperators": true,
|
||||
"requireSpacesInConditionalExpression": true,
|
||||
"requireSpacesInForStatement": true,
|
||||
"requireTrailingComma": {
|
||||
"ignoreSingleValue": true,
|
||||
"ignoreSingleLine": true
|
||||
},
|
||||
"requireLineFeedAtFileEnd": true,
|
||||
"disallowSpacesInAnonymousFunctionExpression": {
|
||||
"beforeOpeningRoundBrace": true
|
||||
},
|
||||
"disallowSpacesInsideObjectBrackets": "all",
|
||||
"disallowSpacesInsideArrayBrackets": "all",
|
||||
"disallowSpacesInsideParentheses": true,
|
||||
|
||||
"disallowMultipleLineBreaks": true,
|
||||
"disallowNewlineBeforeBlockStatements": true
|
||||
}
|
||||
@@ -4,4 +4,4 @@ Schemas.Instance = new SimpleSchema({
|
||||
//an instance is a single flow of time all parties in an instance are in-sync time wise
|
||||
});
|
||||
|
||||
Instances.attachSchema(Schemas.Instance);
|
||||
Instances.attachSchema(Schemas.Instance);
|
||||
|
||||
@@ -5,4 +5,4 @@ Schemas.Party = new SimpleSchema({
|
||||
//each party can only be in a single instance at a time
|
||||
});
|
||||
|
||||
Parties.attachSchema(Schemas.Party);
|
||||
Parties.attachSchema(Schemas.Party);
|
||||
|
||||
@@ -5,29 +5,32 @@ Actions = new Mongo.Collection("actions");
|
||||
*/
|
||||
Schemas.Action = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
name: {
|
||||
type: String, trim: false
|
||||
type: String,
|
||||
trim: false,
|
||||
},
|
||||
description: {
|
||||
type: String, trim: false
|
||||
type: String,
|
||||
trim: false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
allowedValues: ["action, bonus, reaction, free"],
|
||||
defaultValue: "action"
|
||||
defaultValue: "action",
|
||||
},
|
||||
//the immediate impact of doing this action (eg. -1 rages)
|
||||
adjustments: {
|
||||
type: [Schemas.Adjustment], defaultValue: []
|
||||
}
|
||||
type: [Schemas.Adjustment],
|
||||
defaultValue: [],
|
||||
},
|
||||
});
|
||||
|
||||
Actions.attachSchema(Schemas.Action);
|
||||
|
||||
Actions.attachBehaviour('softRemovable');
|
||||
Actions.attachBehaviour("softRemovable");
|
||||
makeChild(Actions);
|
||||
|
||||
Actions.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
|
||||
@@ -5,62 +5,75 @@ Attacks = new Mongo.Collection("attacks");
|
||||
*/
|
||||
Schemas.Attack = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
defaultValue: "New Attack",
|
||||
trim: false
|
||||
defaultValue: "New Attack",
|
||||
trim: false,
|
||||
},
|
||||
details: {
|
||||
type: String,
|
||||
optional: true,
|
||||
trim: false
|
||||
optional: true,
|
||||
trim: false,
|
||||
},
|
||||
attackBonus: {
|
||||
type: String,
|
||||
defaultValue: "strengthMod + proficiencyBonus",
|
||||
optional: true,
|
||||
trim: false
|
||||
optional: true,
|
||||
trim: false,
|
||||
},
|
||||
damageBonus: {
|
||||
type: String,
|
||||
defaultValue: "strengthMod",
|
||||
optional: true,
|
||||
trim: false
|
||||
optional: true,
|
||||
trim: false,
|
||||
},
|
||||
damageDice: {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: "1d8",
|
||||
allowedValues: DAMAGE_DICE
|
||||
allowedValues: DAMAGE_DICE,
|
||||
},
|
||||
damageType: {
|
||||
type: String,
|
||||
allowedValues: ["bludgeoning", "piercing", "slashing", "acid", "cold", "fire", "force", "lightning", "necrotic",
|
||||
"poison", "psychic", "radiant", "thunder"],
|
||||
defaultValue: "slashing"
|
||||
allowedValues: [
|
||||
"bludgeoning",
|
||||
"piercing",
|
||||
"slashing",
|
||||
"acid",
|
||||
"cold",
|
||||
"fire",
|
||||
"force",
|
||||
"lightning",
|
||||
"necrotic",
|
||||
"poison",
|
||||
"psychic",
|
||||
"radiant",
|
||||
"thunder",
|
||||
],
|
||||
defaultValue: "slashing",
|
||||
},
|
||||
//the id of the feature, buff or item that created this effect
|
||||
parent: {
|
||||
type: Schemas.Parent
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q"
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
enabled: {
|
||||
type: Boolean,
|
||||
defaultValue: true
|
||||
}
|
||||
defaultValue: true,
|
||||
},
|
||||
});
|
||||
|
||||
Attacks.attachSchema(Schemas.Attack);
|
||||
|
||||
Attacks.attachBehaviour('softRemovable');
|
||||
makeChild(Attacks, ['name', 'enabled']); //children of lots of things
|
||||
Attacks.attachBehaviour("softRemovable");
|
||||
makeChild(Attacks, ["name", "enabled"]); //children of lots of things
|
||||
|
||||
Attacks.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Attacks.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -7,21 +7,22 @@ Schemas.Buff = new SimpleSchema({
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
autoValue: function(){
|
||||
if(!this.isSet) return Random.id();
|
||||
}},
|
||||
if (!this.isSet) return Random.id();
|
||||
},
|
||||
},
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
//expiry time
|
||||
expiry: { type: Number, optional: true},
|
||||
duration: { type: Number }
|
||||
expiry: {type: Number, optional: true},
|
||||
duration: {type: Number},
|
||||
});
|
||||
|
||||
Buffs.attachSchema(Schemas.Buff);
|
||||
|
||||
Buffs.attachBehaviour('softRemovable');
|
||||
makeParent(Buffs, 'name'); //parents of effects and attacks
|
||||
Buffs.attachBehaviour("softRemovable");
|
||||
makeParent(Buffs, "name"); //parents of effects and attacks
|
||||
|
||||
Buffs.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Buffs.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -3,16 +3,16 @@ Characters = new Mongo.Collection("characters");
|
||||
|
||||
Schemas.Character = new SimpleSchema({
|
||||
//strings
|
||||
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},
|
||||
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},
|
||||
|
||||
//attributes
|
||||
//ability scores
|
||||
@@ -73,99 +73,100 @@ Schemas.Character = new SimpleSchema({
|
||||
slashingMultiplier: {type: Schemas.Attribute},
|
||||
thunderMultiplier: {type: Schemas.Attribute},
|
||||
|
||||
|
||||
//skills
|
||||
//saves
|
||||
strengthSave: {type: Schemas.Skill},
|
||||
"strengthSave.ability": { type: String, defaultValue: "strength" },
|
||||
"strengthSave.ability": {type: String, defaultValue: "strength"},
|
||||
|
||||
dexteritySave: {type: Schemas.Skill},
|
||||
"dexteritySave.ability": { type: String, defaultValue: "dexterity" },
|
||||
"dexteritySave.ability": {type: String, defaultValue: "dexterity"},
|
||||
|
||||
constitutionSave:{type: Schemas.Skill},
|
||||
"constitutionSave.ability": { type: String, defaultValue: "constitution" },
|
||||
"constitutionSave.ability": {type: String, defaultValue: "constitution"},
|
||||
|
||||
intelligenceSave:{type: Schemas.Skill},
|
||||
"intelligenceSave.ability": { type: String, defaultValue: "intelligence" },
|
||||
"intelligenceSave.ability": {type: String, defaultValue: "intelligence"},
|
||||
|
||||
wisdomSave: {type: Schemas.Skill},
|
||||
"wisdomSave.ability": { type: String, defaultValue: "wisdom" },
|
||||
"wisdomSave.ability": {type: String, defaultValue: "wisdom"},
|
||||
|
||||
charismaSave: {type: Schemas.Skill},
|
||||
"charismaSave.ability": { type: String, defaultValue: "charisma" },
|
||||
|
||||
"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.ability": {type: String, defaultValue: "intelligence"},
|
||||
|
||||
medicine: {type: Schemas.Skill},
|
||||
"medicine.ability": { type: String, defaultValue: "wisdom" },
|
||||
"medicine.ability": {type: String, defaultValue: "wisdom"},
|
||||
|
||||
nature: {type: Schemas.Skill},
|
||||
"nature.ability": { type: String, defaultValue: "intelligence" },
|
||||
"nature.ability": {type: String, defaultValue: "intelligence"},
|
||||
|
||||
perception: {type: Schemas.Skill},
|
||||
"perception.ability": { type: String, defaultValue: "wisdom" },
|
||||
"perception.ability": {type: String, defaultValue: "wisdom"},
|
||||
|
||||
performance: {type: Schemas.Skill},
|
||||
"performance.ability": { type: String, defaultValue: "charisma" },
|
||||
"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.ability": {type: String, defaultValue: "dexterity"},
|
||||
|
||||
stealth: {type: Schemas.Skill},
|
||||
"stealth.ability": { type: String, defaultValue: "dexterity" },
|
||||
"stealth.ability": {type: String, defaultValue: "dexterity"},
|
||||
|
||||
survival: {type: Schemas.Skill},
|
||||
"survival.ability": { type: String, defaultValue: "wisdom" },
|
||||
|
||||
"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.ability": {type: String, defaultValue: "dexterity"},
|
||||
|
||||
//mechanics
|
||||
deathSave: { type: Schemas.DeathSave },
|
||||
deathSave: {type: Schemas.DeathSave},
|
||||
|
||||
//permissions
|
||||
owner: { type: String, regEx: SimpleSchema.RegEx.Id },
|
||||
readers: { type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [] },
|
||||
writers: { type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [] },
|
||||
color: {type: String, allowedValues: _.pluck(colorOptions, "key"), defaultValue: "q"},
|
||||
owner: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
|
||||
writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
//TODO add per-character settings
|
||||
"settings.experiencesInc": {type: Number, defaultValue: 20}, //how many experiences to load at a time in XP table
|
||||
});
|
||||
@@ -174,9 +175,11 @@ Characters.attachSchema(Schemas.Character);
|
||||
|
||||
var attributeBase = function(charId, statName){
|
||||
check(statName, String);
|
||||
var effects = Effects.find({charId: charId, stat: statName, enabled: true}).fetch();
|
||||
var effects = Effects.find(
|
||||
{charId: charId, stat: statName, enabled: true}
|
||||
).fetch();
|
||||
effects = _.groupBy(effects, "operation");
|
||||
var value = _.contains(DAMAGE_MULTIPLIERS, statName)? 1 : 0;
|
||||
var value = _.contains(DAMAGE_MULTIPLIERS, statName) ? 1 : 0;
|
||||
|
||||
//start with the highest base value
|
||||
_.each(effects.base, function(effect){
|
||||
@@ -199,13 +202,13 @@ var attributeBase = function(charId, statName){
|
||||
//ensure value is >= all mins
|
||||
_.each(effects.min, function(effect){
|
||||
var min = evaluateEffect(charId, effect);
|
||||
value = value > min? value : min;
|
||||
value = value > min ? value : min;
|
||||
});
|
||||
|
||||
//ensure value is <= all maxes
|
||||
_.each(effects.max, function(effect){
|
||||
var max = evaluateEffect(charId, effect);
|
||||
value = value < max? value : max;
|
||||
value = value < max ? value : max;
|
||||
});
|
||||
return value;
|
||||
};
|
||||
@@ -221,16 +224,24 @@ Characters.helpers({
|
||||
fieldSelector[fieldName] = 1;
|
||||
var char = Characters.findOne(this._id, {fields: fieldSelector});
|
||||
var field = char[fieldName];
|
||||
if(field === undefined){
|
||||
throw new Meteor.Error("getField failed",
|
||||
"getField could not find field " + fieldName + " in character "+ char._id);
|
||||
if (field === undefined){
|
||||
throw new Meteor.Error(
|
||||
"getField failed",
|
||||
"getField could not find field " +
|
||||
fieldName +
|
||||
" in character " +
|
||||
char._id
|
||||
);
|
||||
}
|
||||
return field;
|
||||
},
|
||||
//returns the value of a field
|
||||
fieldValue : function(fieldName){
|
||||
if(!Schemas.Character.schema(fieldName)){
|
||||
throw new Meteor.Error("Field not found", "Character's schema does not contain a field called: " + fieldName);
|
||||
if (!Schemas.Character.schema(fieldName)){
|
||||
throw new Meteor.Error(
|
||||
"Field not found",
|
||||
"Character's schema does not contain a field called: " + fieldName
|
||||
);
|
||||
}
|
||||
//duck typing to get the right value function
|
||||
//.ability implies skill
|
||||
@@ -277,7 +288,9 @@ Characters.helpers({
|
||||
mod += prof * this.attributeValue("proficiencyBonus");
|
||||
|
||||
//apply all effects
|
||||
var rawEffects = Effects.find({charId: charId, stat: skillName, enabled: true}).fetch();
|
||||
var rawEffects = Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true}
|
||||
).fetch();
|
||||
var effects = _.groupBy(rawEffects, "operation");
|
||||
_.forEach(effects.add, function(effect){
|
||||
mod += evaluateEffect(charId, effect);
|
||||
@@ -287,11 +300,11 @@ Characters.helpers({
|
||||
});
|
||||
_.forEach(effects.min, function(effect){
|
||||
var min = evaluateEffect(charId, effect);
|
||||
mod = mod > min? mod : min;
|
||||
mod = mod > min ? mod : min;
|
||||
});
|
||||
_.forEach(effects.max, function(effect){
|
||||
var max = evaluateEffect(charId, effect);
|
||||
mod = mod < max? mod : max;
|
||||
mod = mod < max ? mod : max;
|
||||
});
|
||||
return signedString(mod);
|
||||
}),
|
||||
@@ -300,7 +313,9 @@ Characters.helpers({
|
||||
var charId = this._id;
|
||||
//return largest value in proficiency array
|
||||
var prof = 0;
|
||||
Proficiencies.find({charId: charId, name: skillName, enabled: true}).forEach(function(proficiency){
|
||||
Proficiencies.find(
|
||||
{charId: charId, name: skillName, enabled: true}
|
||||
).forEach(function(proficiency){
|
||||
var newProf = proficiency.value;
|
||||
if (newProf > prof){
|
||||
prof = newProf;
|
||||
@@ -316,7 +331,9 @@ Characters.helpers({
|
||||
var charId = this._id;
|
||||
var mod = +this.skillMod(skillName);
|
||||
var value = 10 + mod;
|
||||
Effects.find({charId: charId, stat: skillName, enabled: true, operation: "passiveAdd"}).forEach(function(effect){
|
||||
Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "passiveAdd"}
|
||||
).forEach(function(effect){
|
||||
value += evaluateEffect(charId, effect);
|
||||
});
|
||||
return value;
|
||||
@@ -325,10 +342,14 @@ Characters.helpers({
|
||||
|
||||
advantage: function(skillName){
|
||||
var charId = this._id;
|
||||
var advantage = Effects.find({charId: charId, stat: skillName, enabled: true, operation: "advantage"}).count();
|
||||
var disadvantage = Effects.find({charId: charId, stat: skillName, enabled: true, operation: "disadvantage"}).count();
|
||||
if(advantage && !disadvantage) return 1;
|
||||
if(disadvantage && !advantage) return -1;
|
||||
var advantage = Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "advantage"}
|
||||
).count();
|
||||
var disadvantage = Effects.find(
|
||||
{charId: charId, stat: skillName, enabled: true, operation: "disadvantage"}
|
||||
).count();
|
||||
if (advantage && !disadvantage) return 1;
|
||||
if (disadvantage && !advantage) return -1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
@@ -343,15 +364,12 @@ Characters.helpers({
|
||||
|
||||
xpLevel: function(){
|
||||
var xp = this.experience();
|
||||
var xpTable = [0, 300, 900, 2700, 6500, 14000, 23000, 34000, 48000, 64000,
|
||||
85000, 100000, 120000, 140000, 165000, 195000, 225000, 265000,
|
||||
305000, 355000];
|
||||
for(var i = 0; i < 19; i++){
|
||||
if(xp < xpTable[i]){
|
||||
for (var i = 0; i < 19; i++){
|
||||
if (xp < XP_TABLE[i]){
|
||||
return i;
|
||||
}
|
||||
};
|
||||
if(xp > 355000) return 20;
|
||||
}
|
||||
if (xp > 355000) return 20;
|
||||
return 0;
|
||||
},
|
||||
|
||||
@@ -359,22 +377,25 @@ Characters.helpers({
|
||||
var level = 0;
|
||||
Classes.find({charId: this._id}).forEach(function(cls){
|
||||
level += cls.level;
|
||||
})
|
||||
});
|
||||
return level;
|
||||
},
|
||||
|
||||
experience: function(){
|
||||
var xp = 0;
|
||||
Experiences.find({charId: this._id}, {fields: {value: 1}}).forEach(function(e){
|
||||
Experiences.find(
|
||||
{charId: this._id},
|
||||
{fields: {value: 1}}
|
||||
).forEach(function(e){
|
||||
xp += e.value;
|
||||
})
|
||||
});
|
||||
return xp;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
//clean up all data related to that character before removing it
|
||||
Characters.after.remove(function (userId, character) {
|
||||
if(Meteor.isServer){
|
||||
Characters.after.remove(function(userId, character) {
|
||||
if (Meteor.isServer){
|
||||
Actions .remove({charId: character._id});
|
||||
Attacks .remove({charId: character._id});
|
||||
Buffs .remove({charId: character._id});
|
||||
@@ -391,25 +412,25 @@ Characters.after.remove(function (userId, character) {
|
||||
});
|
||||
|
||||
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;
|
||||
},
|
||||
fetch: ["owner", "writers"]
|
||||
fetch: ["owner", "writers"],
|
||||
});
|
||||
|
||||
Characters.deny({
|
||||
update: function (userId, docs, fields, modifier) {
|
||||
update: function(userId, docs, fields, modifier) {
|
||||
// can't change owners
|
||||
return _.contains(fields, 'owner');
|
||||
return _.contains(fields, "owner");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,21 +8,25 @@ Schemas.Class = new SimpleSchema({
|
||||
type: Date,
|
||||
autoValue: function() {
|
||||
if (this.isInsert) {
|
||||
return new Date;
|
||||
return new Date();
|
||||
} else if (this.isUpsert) {
|
||||
return {$setOnInsert: new Date};
|
||||
return {$setOnInsert: new Date()};
|
||||
} else {
|
||||
this.unset();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
color: {type: String, allowedValues: _.pluck(colorOptions, "key"), defaultValue: "q"}
|
||||
});
|
||||
|
||||
Classes.attachSchema(Schemas.Class);
|
||||
|
||||
Classes.attachBehaviour('softRemovable');
|
||||
makeParent(Classes, 'name'); //parents of effects and attacks
|
||||
Classes.attachBehaviour("softRemovable");
|
||||
makeParent(Classes, "name"); //parents of effects and attacks
|
||||
|
||||
Classes.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Classes.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -7,27 +7,39 @@ Effects = new Mongo.Collection("effects");
|
||||
Schemas.Effect = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
optional: true, //TODO make necessary if there is no owner
|
||||
trim: false
|
||||
trim: false,
|
||||
},
|
||||
operation: {
|
||||
type: String,
|
||||
defaultValue: "add",
|
||||
allowedValues: ["base", "proficiency","add","mul","min","max","advantage","disadvantage","passiveAdd","fail","conditional"]
|
||||
allowedValues: [
|
||||
"base",
|
||||
"proficiency",
|
||||
"add",
|
||||
"mul",
|
||||
"min",
|
||||
"max",
|
||||
"advantage",
|
||||
"disadvantage",
|
||||
"passiveAdd",
|
||||
"fail",
|
||||
"conditional",
|
||||
],
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true
|
||||
optional: true,
|
||||
},
|
||||
calculation: {
|
||||
type: String,
|
||||
optional: true,
|
||||
trim: false
|
||||
trim: false,
|
||||
},
|
||||
//the thing that created this effect
|
||||
parent: {
|
||||
@@ -36,17 +48,17 @@ Schemas.Effect = new SimpleSchema({
|
||||
//which stat the effect is applied to
|
||||
stat: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
},
|
||||
enabled: {
|
||||
type: Boolean,
|
||||
defaultValue: true
|
||||
}
|
||||
defaultValue: true,
|
||||
},
|
||||
});
|
||||
|
||||
Effects.attachSchema(Schemas.Effect);
|
||||
|
||||
if(Meteor.isServer) Characters.after.insert(function (userId, char) {
|
||||
if (Meteor.isServer) Characters.after.insert(function(userId, char) {
|
||||
Effects.insert({
|
||||
charId: char._id,
|
||||
type: "inate",
|
||||
@@ -56,8 +68,8 @@ if(Meteor.isServer) Characters.after.insert(function (userId, char) {
|
||||
calculation: "level * constitutionMod",
|
||||
parent: {
|
||||
id: char._id,
|
||||
collection: "Characters"
|
||||
}
|
||||
collection: "Characters",
|
||||
},
|
||||
});
|
||||
Effects.insert({
|
||||
charId: char._id,
|
||||
@@ -68,8 +80,8 @@ if(Meteor.isServer) Characters.after.insert(function (userId, char) {
|
||||
calculation: "floor(level / 4 + 1.75)",
|
||||
parent: {
|
||||
id: char._id,
|
||||
collection: "Characters"
|
||||
}
|
||||
collection: "Characters",
|
||||
},
|
||||
});
|
||||
Effects.insert({
|
||||
charId: char._id,
|
||||
@@ -80,8 +92,8 @@ if(Meteor.isServer) Characters.after.insert(function (userId, char) {
|
||||
calculation: "dexterityArmor",
|
||||
parent: {
|
||||
id: char._id,
|
||||
collection: "Characters"
|
||||
}
|
||||
collection: "Characters",
|
||||
},
|
||||
});
|
||||
Effects.insert({
|
||||
charId: char._id,
|
||||
@@ -92,12 +104,12 @@ if(Meteor.isServer) Characters.after.insert(function (userId, char) {
|
||||
value: 10,
|
||||
parent: {
|
||||
id: char._id,
|
||||
collection: "Characters"
|
||||
}
|
||||
collection: "Characters",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
Effects.attachBehaviour('softRemovable');
|
||||
Effects.attachBehaviour("softRemovable");
|
||||
makeChild(Effects, ["enabled"]); //children of lots of things
|
||||
|
||||
Effects.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
|
||||
@@ -9,19 +9,19 @@ Schemas.Experience = new SimpleSchema({
|
||||
type: Date,
|
||||
autoValue: function() {
|
||||
if (this.isInsert) {
|
||||
return new Date;
|
||||
return new Date();
|
||||
} else if (this.isUpsert) {
|
||||
return {$setOnInsert: new Date};
|
||||
return {$setOnInsert: new Date()};
|
||||
} else {
|
||||
this.unset();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Experiences.attachSchema(Schemas.Experience);
|
||||
|
||||
Experiences.attachBehaviour('softRemovable');
|
||||
Experiences.attachBehaviour("softRemovable");
|
||||
|
||||
Experiences.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Experiences.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -6,10 +6,17 @@ Schemas.Feature = new SimpleSchema({
|
||||
description: {type: String, optional: true, trim: false},
|
||||
uses: {type: String, optional: true, trim: false},
|
||||
used: {type: Number, defaultValue: 0},
|
||||
reset: {type: String, allowedValues: ["manual", "longRest", "shortRest"], defaultValue: "manual"},
|
||||
reset: {
|
||||
type: String,
|
||||
allowedValues: ["manual", "longRest", "shortRest"],
|
||||
defaultValue: "manual",
|
||||
},
|
||||
enabled: {type: Boolean, defaultValue: true},
|
||||
alwaysEnabled:{type: Boolean, defaultValue: true},
|
||||
color: {type: String, allowedValues: _.pluck(colorOptions, "key"), defaultValue: "q"}
|
||||
color: {type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
});
|
||||
|
||||
Features.attachSchema(Schemas.Feature);
|
||||
@@ -20,11 +27,11 @@ Features.helpers({
|
||||
},
|
||||
usesValue: function(){
|
||||
return evaluate(this.charId, this.uses);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Features.attachBehaviour('softRemovable');
|
||||
makeParent(Features, ['name', 'enabled']); //parents of effects and attacks
|
||||
Features.attachBehaviour("softRemovable");
|
||||
makeParent(Features, ["name", "enabled"]); //parents of effects and attacks
|
||||
|
||||
Features.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Features.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -4,12 +4,16 @@ Schemas.Note = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
name: {type: String, trim: false},
|
||||
description: {type: String, optional: true, trim: false},
|
||||
color: {type: String, allowedValues: _.pluck(colorOptions, "key"), defaultValue: "q"}
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues:_.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
});
|
||||
|
||||
Notes.attachSchema(Schemas.Note);
|
||||
|
||||
Notes.attachBehaviour('softRemovable');
|
||||
Notes.attachBehaviour("softRemovable");
|
||||
|
||||
Notes.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Notes.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -3,7 +3,7 @@ Proficiencies = new Mongo.Collection("proficiencies");
|
||||
Schemas.Proficiency = new SimpleSchema({
|
||||
charId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
@@ -24,12 +24,12 @@ Schemas.Proficiency = new SimpleSchema({
|
||||
enabled: {
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Proficiencies.attachSchema(Schemas.Proficiency);
|
||||
|
||||
Proficiencies.attachBehaviour('softRemovable');
|
||||
Proficiencies.attachBehaviour("softRemovable");
|
||||
makeChild(Proficiencies);
|
||||
|
||||
Proficiencies.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
|
||||
@@ -7,7 +7,11 @@ Schemas.SpellLists = new SimpleSchema({
|
||||
saveDC: {type: String, optional: true, trim: false},
|
||||
attackBonus: {type: String, optional: true, trim: false},
|
||||
maxPrepared: {type: String, optional: true, trim: false},
|
||||
color: {type: String, allowedValues: _.pluck(colorOptions, "key"), defaultValue: "q"},
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
"settings.showUnprepared": {type: Boolean, defaultValue: true},
|
||||
});
|
||||
|
||||
@@ -16,14 +20,17 @@ SpellLists.attachSchema(Schemas.SpellLists);
|
||||
SpellLists.helpers({
|
||||
numPrepared: function(){
|
||||
var num = 0;
|
||||
Spells.find({charId: this.charId, listId: this._id, prepared: 1}, {fields: {prepareCost: 1}}).forEach(function(spell){
|
||||
Spells.find(
|
||||
{charId: this.charId, listId: this._id, prepared: 1},
|
||||
{fields: {prepareCost: 1}}
|
||||
).forEach(function(spell){
|
||||
num += spell.prepareCost;
|
||||
});
|
||||
return num;
|
||||
}
|
||||
});
|
||||
|
||||
SpellLists.attachBehaviour('softRemovable');
|
||||
SpellLists.attachBehaviour("softRemovable");
|
||||
makeParent(SpellLists); //parents of spells
|
||||
|
||||
SpellLists.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
|
||||
@@ -2,25 +2,65 @@ Spells = new Mongo.Collection("spells");
|
||||
|
||||
Schemas.Spell = new SimpleSchema({
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
prepared: {type: String, defaultValue: "prepared", allowedValues: ["prepared","unprepared","always"]},
|
||||
name: {type: String, trim: false, defaultValue: "New Spell"},
|
||||
description: {type: String, optional: true, trim: false},
|
||||
castingTime: {type: String, optional: true, defaultValue: "action", trim: false},
|
||||
range: {type: String, optional: true, trim: false},
|
||||
duration: {type: String, optional: true, trim: false, defaultValue: "Instantaneous"},
|
||||
"components.verbal": {type: Boolean, defaultValue: false},
|
||||
"components.somatic": {type: Boolean, defaultValue: false},
|
||||
"components.material": {type: String, optional: true},
|
||||
prepared: {
|
||||
type: String,
|
||||
defaultValue: "prepared",
|
||||
allowedValues: ["prepared", "unprepared", "always"],
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
trim: false,
|
||||
defaultValue: "New Spell",
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
optional: true,
|
||||
trim: false,
|
||||
},
|
||||
castingTime: {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: "action",
|
||||
trim: false,
|
||||
},
|
||||
range: {
|
||||
type: String,
|
||||
optional: true,
|
||||
trim: false,
|
||||
},
|
||||
duration: {
|
||||
type: String,
|
||||
optional: true,
|
||||
trim: false,
|
||||
defaultValue: "Instantaneous",
|
||||
},
|
||||
"components.verbal": {type: Boolean, defaultValue: false},
|
||||
"components.somatic": {type: Boolean, defaultValue: false},
|
||||
"components.concentration": {type: Boolean, defaultValue: false},
|
||||
ritual: {type: Boolean, defaultValue: false},
|
||||
level: {type: Number, defaultValue: 1},
|
||||
school: {type: String, defaultValue: "Abjuration", allowedValues: magicSchools},
|
||||
color: {type: String, allowedValues: _.pluck(colorOptions, "key"), defaultValue: "q"}
|
||||
"components.material": {type: String, optional: true},
|
||||
ritual: {
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
defaultValue: 1,
|
||||
},
|
||||
school: {
|
||||
type: String,
|
||||
defaultValue: "Abjuration",
|
||||
allowedValues: magicSchools,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
});
|
||||
|
||||
Spells.attachSchema(Schemas.Spell);
|
||||
|
||||
Spells.attachBehaviour('softRemovable');
|
||||
Spells.attachBehaviour("softRemovable");
|
||||
makeChild(Spells); //children of spell lists
|
||||
|
||||
Spells.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
Schemas.Adjustment = new SimpleSchema({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
},
|
||||
//which stat the adjustment is applied to
|
||||
stat: {
|
||||
type: String,
|
||||
optional: true
|
||||
optional: true,
|
||||
},
|
||||
//the value added to the stat
|
||||
value: {
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true
|
||||
optional: true,
|
||||
},
|
||||
calculation: {
|
||||
type: String,
|
||||
optional: true
|
||||
}
|
||||
optional: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,11 +3,11 @@ Schemas.Attribute = new SimpleSchema({
|
||||
//should be zero after reset
|
||||
adjustment: {
|
||||
type: Number,
|
||||
defaultValue: 0
|
||||
defaultValue: 0,
|
||||
},
|
||||
reset: {
|
||||
type: String,
|
||||
defaultValue: "longRest",
|
||||
allowedValues: ["longRest", "shortRest"]
|
||||
}
|
||||
allowedValues: ["longRest", "shortRest"],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,20 +3,20 @@ Schemas.DeathSave = new SimpleSchema({
|
||||
type: Number,
|
||||
min: 0,
|
||||
max: 3,
|
||||
defaultValue: 0
|
||||
defaultValue: 0,
|
||||
},
|
||||
fail: {
|
||||
type: Number,
|
||||
min: 0,
|
||||
max: 3,
|
||||
defaultValue: 0
|
||||
defaultValue: 0,
|
||||
},
|
||||
canDeathSave: {
|
||||
type: Boolean,
|
||||
defaultValue: true
|
||||
defaultValue: true,
|
||||
},
|
||||
stable: {
|
||||
type: Boolean,
|
||||
defaultValue: false
|
||||
}
|
||||
defaultValue: false,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Schemas.Skill = new SimpleSchema({
|
||||
//attribute name that this skill used as base mod for roll
|
||||
ability: { type: String, defaultValue: "" },
|
||||
ability: {type: String, defaultValue: ""},
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ Schemas.TemporaryHitPoints = new SimpleSchema({
|
||||
} else {
|
||||
this.unset();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -29,11 +29,13 @@ TemporaryHitPoints.helpers({
|
||||
});
|
||||
|
||||
//remove the temporary hit points when they hit zero
|
||||
TemporaryHitPoints.after.update(function (userId, thp, fieldNames, modifier, options) {
|
||||
if(thp.used >= thp.maximum && thp.deleteOnZero){
|
||||
TemporaryHitPoints.remove(thp._id);
|
||||
}
|
||||
}, {fetchPrevious: false});
|
||||
TemporaryHitPoints.after.update(
|
||||
function(userId, thp, fieldNames, modifier, options){
|
||||
if (thp.used >= thp.maximum && thp.deleteOnZero){
|
||||
TemporaryHitPoints.remove(thp._id);
|
||||
}
|
||||
}, {fetchPrevious: false}
|
||||
);
|
||||
|
||||
TemporaryHitPoints.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
TemporaryHitPoints.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
@@ -2,13 +2,17 @@
|
||||
Containers = new Mongo.Collection("containers");
|
||||
|
||||
Schemas.Container = new SimpleSchema({
|
||||
name: { type: String, trim: false },
|
||||
charId: { type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
isCarried: { type: Boolean },
|
||||
name: {type: String, trim: false},
|
||||
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
isCarried: {type: Boolean},
|
||||
weight: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
description:{type: String, optional: true, trim: false},
|
||||
color: {type: String, allowedValues: _.pluck(colorOptions, "key"), defaultValue: "q"}
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
});
|
||||
|
||||
Containers.attachSchema(Schemas.Container);
|
||||
@@ -16,7 +20,10 @@ Containers.attachSchema(Schemas.Container);
|
||||
Containers.helpers({
|
||||
contentsValue: function(){
|
||||
var value = 0;
|
||||
Items.find({"parent.id": this._id}, {fields: {quantity: 1, value: 1}}).forEach(function(item){
|
||||
Items.find(
|
||||
{"parent.id": this._id},
|
||||
{fields: {quantity: 1, value: 1}}
|
||||
).forEach(function(item){
|
||||
value += item.totalValue();
|
||||
});
|
||||
return value;
|
||||
@@ -26,7 +33,10 @@ Containers.helpers({
|
||||
},
|
||||
contentsWeight: function(){
|
||||
var weight = 0;
|
||||
Items.find({"parent.id": this._id}, {fields: {quantity: 1, weight: 1}}).forEach(function(item){
|
||||
Items.find(
|
||||
{"parent.id": this._id},
|
||||
{fields: {quantity: 1, weight: 1}}
|
||||
).forEach(function(item){
|
||||
weight += item.totalWeight();
|
||||
});
|
||||
return weight;
|
||||
@@ -35,12 +45,12 @@ Containers.helpers({
|
||||
return this.contentsWeight() + this.weight;
|
||||
},
|
||||
moveToCharacter: function(characterId){
|
||||
if(this.charId === characterId) return;
|
||||
if (this.charId === characterId) return;
|
||||
Items.update(this._id, {$set: {charId: characterId}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Containers.attachBehaviour('softRemovable');
|
||||
Containers.attachBehaviour("softRemovable");
|
||||
makeParent(Containers); //parents of items
|
||||
|
||||
Containers.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Items = new Mongo.Collection('items');
|
||||
Items = new Mongo.Collection("items");
|
||||
|
||||
Schemas.Item = new SimpleSchema({
|
||||
name: {type: String, defaultValue: "New Item", trim: false},
|
||||
@@ -10,7 +10,11 @@ Schemas.Item = new SimpleSchema({
|
||||
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
|
||||
enabled: {type: Boolean, defaultValue: false},
|
||||
requiresAttunement: {type: Boolean, defaultValue: false},
|
||||
color: {type: String, allowedValues: _.pluck(colorOptions, "key"), defaultValue: "q"}
|
||||
color: {
|
||||
type: String,
|
||||
allowedValues: _.pluck(colorOptions, "key"),
|
||||
defaultValue: "q",
|
||||
},
|
||||
});
|
||||
|
||||
Items.attachSchema(Schemas.Item);
|
||||
@@ -23,40 +27,77 @@ Items.helpers({
|
||||
return this.weight * this.quantity;
|
||||
},
|
||||
pluralName: function(){
|
||||
if(this.plural && this.quantity !== 1){
|
||||
if (this.plural && this.quantity !== 1){
|
||||
return this.plural;
|
||||
} else{
|
||||
} else {
|
||||
return this.name;
|
||||
}
|
||||
},
|
||||
equip: function(characterId){
|
||||
var charId = characterId || this.charId;
|
||||
if(!charId || ! Characters.findOne(charId)) throw "Invalid character";
|
||||
if(this.parent.collection === "Characters" && this.parent.id === charId && this.enabled) return;
|
||||
Items.update(this._id, {$set: {"parent.collection": "Characters", "parent.id": charId, enabled: true}});
|
||||
if (!charId || !Characters.findOne(charId)) throw "Invalid character";
|
||||
if (this.parent.collection === "Characters" &&
|
||||
this.parent.id === charId &&
|
||||
this.enabled) {
|
||||
return;
|
||||
}
|
||||
Items.update(
|
||||
this._id,
|
||||
{$set: {
|
||||
"parent.collection": "Characters",
|
||||
"parent.id": charId,
|
||||
enabled: true,
|
||||
}}
|
||||
);
|
||||
},
|
||||
unequip: function(){
|
||||
if(!this.enabled) return;
|
||||
if (!this.enabled) return;
|
||||
Items.update(this._id, {$set: {enabled: false}});
|
||||
},
|
||||
moveToContainer: function(containerId){
|
||||
if( !containerId || !Containers.findOne(containerId) ) throw "Invalid container";
|
||||
if(this.parent.collection === "Containers" && this.parent.id === containerId && !this.enabled) return;
|
||||
Items.update(this._id, {$set: {"parent.collection": "Containers", "parent.id": containerId, enabled: false}});
|
||||
if (!containerId || !Containers.findOne(containerId)){
|
||||
throw "Invalid container";
|
||||
}
|
||||
if (this.parent.collection === "Containers" &&
|
||||
this.parent.id === containerId &&
|
||||
!this.enabled) return;
|
||||
Items.update(
|
||||
this._id,
|
||||
{$set: {
|
||||
"parent.collection": "Containers",
|
||||
"parent.id": containerId,
|
||||
enabled: false,
|
||||
}}
|
||||
);
|
||||
},
|
||||
moveToCharacter: function(characterId){
|
||||
if(!characterId || ! Characters.findOne(characterId)) throw "Invalid character";
|
||||
if(this.parent.collection === "Characters" && this.parent.id === characterId && !this.enabled) return;
|
||||
Items.update(this._id, {$set: {"parent.collection": "Characters", "parent.id": characterId, charId: characterId, enabled: false}});
|
||||
if (!characterId || !Characters.findOne(characterId)) {
|
||||
throw "Invalid character";
|
||||
}
|
||||
if (this.parent.collection === "Characters" &&
|
||||
this.parent.id === characterId &&
|
||||
!this.enabled) return;
|
||||
Items.update(
|
||||
this._id,
|
||||
{$set: {
|
||||
"parent.collection": "Characters",
|
||||
"parent.id": characterId,
|
||||
charId: characterId,
|
||||
enabled: false,
|
||||
}}
|
||||
);
|
||||
},
|
||||
splitToParent: function(parent, moveQuantity){
|
||||
check(parent, {id: String, collection: String});
|
||||
check(moveQuantity, Number);
|
||||
var parentCollection = Meteor.isClient? window[parent.collection] : global[parent.collection];
|
||||
if(!parent.id || !parentCollection.findOne(parent.id)) throw "Invalid parent";
|
||||
var parentCollection = Meteor.isClient ?
|
||||
window[parent.collection] : global[parent.collection];
|
||||
if (!parent.id || !parentCollection.findOne(parent.id)){
|
||||
throw "Invalid parent";
|
||||
}
|
||||
var oldStack = this;
|
||||
//we can only move as much as we have, leaving 0 behind at worst
|
||||
if(oldStack.quantity < moveQuantity) moveQuantity = oldStack.quantity;
|
||||
if (oldStack.quantity < moveQuantity) moveQuantity = oldStack.quantity;
|
||||
var oldQuantity = oldStack.quantity - moveQuantity;
|
||||
|
||||
var newStack = _.pick(oldStack, Schemas.Item.objectKeys());
|
||||
@@ -65,31 +106,39 @@ Items.helpers({
|
||||
|
||||
var existingStack = Items.findOne(_.omit(newStack, "quantity"));
|
||||
var updateStackSize = function(){
|
||||
if(oldQuantity > 0){
|
||||
if (oldQuantity > 0){
|
||||
Items.update(oldStack._id, {$set: {quantity: oldQuantity}});
|
||||
} else {
|
||||
Items.remove(oldStack._id);
|
||||
}
|
||||
};
|
||||
if(existingStack){
|
||||
Items.update(existingStack._id, {$inc: {quantity: moveQuantity}}, {}, function(){
|
||||
updateStackSize();
|
||||
});
|
||||
}else{
|
||||
if (existingStack){
|
||||
Items.update(
|
||||
existingStack._id,
|
||||
{$inc: {quantity: moveQuantity}},
|
||||
{},
|
||||
function(){
|
||||
updateStackSize();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
Items.insert(newStack, function(err, id){
|
||||
if(err) throw err;
|
||||
if (err) throw err;
|
||||
updateStackSize();
|
||||
//copy the children also
|
||||
Meteor.call("cloneChildren", oldStack._id, {collection: "Items", id: id});
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Items.before.update(function(userId, doc, fieldNames, modifier, options){
|
||||
if(
|
||||
if (
|
||||
modifier && modifier.$set && modifier.$set.enabled && //we are equipping this item
|
||||
!(modifier.$set["parent.collection"] === "Characters" && modifier.$set["parent.id"]) //and we haven't specified a character to equip to
|
||||
!(
|
||||
modifier.$set["parent.collection"] === "Characters" &&
|
||||
modifier.$set["parent.id"]
|
||||
) //and we haven"t specified a character to equip to
|
||||
){
|
||||
//equip it to the current character
|
||||
modifier.$set["parent.collection"] = "Characters";
|
||||
@@ -97,21 +146,21 @@ Items.before.update(function(userId, doc, fieldNames, modifier, options){
|
||||
}
|
||||
});
|
||||
|
||||
Items.attachBehaviour('softRemovable');
|
||||
Items.attachBehaviour("softRemovable");
|
||||
makeChild(Items); //children of containers
|
||||
makeParent(Items, ['name', 'enabled']); //parents of effects and attacks
|
||||
makeParent(Items, ["name", "enabled"]); //parents of effects and attacks
|
||||
|
||||
Items.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
|
||||
//give characters default items
|
||||
Characters.after.insert(function (userId, char) {
|
||||
if(Meteor.isServer){
|
||||
Characters.after.insert(function(userId, char) {
|
||||
if (Meteor.isServer){
|
||||
var containerId = Containers.insert({
|
||||
name: "Coin Pouch",
|
||||
charId: char._id,
|
||||
isCarried: true,
|
||||
description: "A sturdy pouch for coins",
|
||||
color: "d"
|
||||
color: "d",
|
||||
});
|
||||
Items.insert({
|
||||
name: "Gold piece",
|
||||
@@ -123,8 +172,8 @@ Characters.after.insert(function (userId, char) {
|
||||
color: "n",
|
||||
parent: {
|
||||
id: containerId,
|
||||
collection: "Containers"
|
||||
}
|
||||
collection: "Containers",
|
||||
},
|
||||
});
|
||||
Items.insert({
|
||||
name: "Silver piece",
|
||||
@@ -136,8 +185,8 @@ Characters.after.insert(function (userId, char) {
|
||||
color: "q",
|
||||
parent: {
|
||||
id: containerId,
|
||||
collection: "Containers"
|
||||
}
|
||||
collection: "Containers",
|
||||
},
|
||||
});
|
||||
Items.insert({
|
||||
name: "Copper piece",
|
||||
@@ -149,8 +198,8 @@ Characters.after.insert(function (userId, char) {
|
||||
color: "s",
|
||||
parent: {
|
||||
id: containerId,
|
||||
collection: "Containers"
|
||||
}
|
||||
collection: "Containers",
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,17 +4,17 @@ Schema.User = new SimpleSchema({
|
||||
username: {
|
||||
type: String,
|
||||
regEx: /^[a-z0-9A-Z_]{3,15}$/,
|
||||
optional: true
|
||||
optional: true,
|
||||
},
|
||||
emails: {
|
||||
type: [Object],
|
||||
// this must be optional if you also use other login services like facebook,
|
||||
// but if you use only accounts-password, then it can be required
|
||||
optional: true
|
||||
optional: true,
|
||||
},
|
||||
"emails.$.address": {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Email
|
||||
regEx: SimpleSchema.RegEx.Email,
|
||||
},
|
||||
"emails.$.verified": {
|
||||
type: Boolean
|
||||
@@ -25,20 +25,20 @@ Schema.User = new SimpleSchema({
|
||||
services: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
blackbox: true
|
||||
blackbox: true,
|
||||
},
|
||||
roles: {
|
||||
type: [String],
|
||||
optional: true
|
||||
}
|
||||
optional: true,
|
||||
},
|
||||
});
|
||||
|
||||
Meteor.users.attachSchema(Schema.User);
|
||||
|
||||
Meteor.users.allow({
|
||||
update: function (userId, doc, fields, modifier) {
|
||||
update: function(userId, doc, fields, modifier) {
|
||||
return userId === doc._id &&
|
||||
fields.length === 1 &&
|
||||
fields[0] === 'username';
|
||||
fields[0] === "username";
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Router.configure({
|
||||
loadingTemplate: 'loading',
|
||||
layoutTemplate: 'layout'
|
||||
loadingTemplate: "loading",
|
||||
layoutTemplate: "layout",
|
||||
});
|
||||
|
||||
Router.map( function () {
|
||||
Router.map(function() {
|
||||
/*
|
||||
this.route('home', {
|
||||
path: '/',
|
||||
this.route("home", {
|
||||
path: "/",
|
||||
waitOn: function(){
|
||||
return Meteor.subscribe("characterList", Meteor.userId());
|
||||
},
|
||||
@@ -17,8 +17,8 @@ Router.map( function () {
|
||||
}
|
||||
});*/ //add a home route and change characterList route
|
||||
|
||||
this.route('characterList', {
|
||||
path: '/',
|
||||
this.route("characterList", {
|
||||
path: "/",
|
||||
waitOn: function(){
|
||||
return Meteor.subscribe("characterList", Meteor.userId());
|
||||
},
|
||||
@@ -29,37 +29,40 @@ Router.map( function () {
|
||||
},
|
||||
onAfterAction: function() {
|
||||
document.title = appName;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
this.route('characterSheet', {
|
||||
path: '/character/:_id',
|
||||
this.route("characterSheet", {
|
||||
path: "/character/:_id",
|
||||
waitOn: function(){
|
||||
return [
|
||||
Meteor.subscribe("singleCharacter", this.params._id, Meteor.userId()),
|
||||
];
|
||||
},
|
||||
data: function() {
|
||||
var data = Characters.findOne({_id: this.params._id}, {fields: {_id: 1, name: 1, color: 1}});
|
||||
var data = Characters.findOne(
|
||||
{_id: this.params._id},
|
||||
{fields: {_id: 1, name: 1, color: 1}}
|
||||
);
|
||||
return data;
|
||||
},
|
||||
onAfterAction: function() {
|
||||
var char = Characters.findOne({_id: this.params._id}, {fields: {name: 1}});
|
||||
var name = char && char.name;
|
||||
if(name){
|
||||
if (name){
|
||||
document.title = name;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
this.route('loading', {
|
||||
path: '/loading'
|
||||
this.route("loading", {
|
||||
path: "/loading"
|
||||
});
|
||||
|
||||
this.route('profile', {
|
||||
path: '/account',
|
||||
this.route("profile", {
|
||||
path: "/account",
|
||||
onAfterAction: function() {
|
||||
document.title = appName + " Account";
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,10 +12,10 @@ this.GlobalUI = (function() {
|
||||
return toast.show();
|
||||
};
|
||||
|
||||
GlobalUI.deletedToast = function(id, collection, itemName){
|
||||
GlobalUI.deletedToast = function(id, collection, itemName) {
|
||||
GlobalUI.toast({
|
||||
text: itemName? itemName + " deleted" : "Deleted item from" + collection,
|
||||
template: "undoToast",
|
||||
text: itemName ? itemName + " deleted" : "Deleted item from" + collection,
|
||||
template: "undoToast",
|
||||
data: {
|
||||
id: id,
|
||||
collection: collection
|
||||
@@ -23,7 +23,7 @@ this.GlobalUI = (function() {
|
||||
});
|
||||
};
|
||||
|
||||
GlobalUI.setDialog = function(opts){
|
||||
GlobalUI.setDialog = function(opts) {
|
||||
this.dialog = $("[global-dialog]")[0];
|
||||
Session.set("global.ui.dialogHeader", opts.heading);
|
||||
Session.set("global.ui.dialogData", opts.data);
|
||||
@@ -58,7 +58,7 @@ this.GlobalUI = (function() {
|
||||
Session.set("global.ui.detailShow", true);
|
||||
};
|
||||
|
||||
//if setting the detail rather than showing it,
|
||||
//if setting the detail rather than showing it,
|
||||
//the template should contain the following in template.rendered
|
||||
//
|
||||
//if (!this.alreadyRendered){
|
||||
@@ -69,30 +69,30 @@ this.GlobalUI = (function() {
|
||||
Session.set("global.ui.detailData", opts.data);
|
||||
Session.set("global.ui.detailTemplate", opts.template);
|
||||
Session.set("global.ui.detailHeroId", opts.heroId);
|
||||
if(!!(window.history && window.history.pushState)){
|
||||
if (window.history && window.history.pushState) {
|
||||
history.replaceState({detail: "closed", opts: opts}, "Detail Dialog");
|
||||
history.pushState({detail: "opened", opts: opts}, "Detail Dialog");
|
||||
}
|
||||
};
|
||||
|
||||
var throttleBack = _.throttle(function(){
|
||||
var throttleBack = _.throttle(function() {
|
||||
history.back();
|
||||
}, 800, {trailing: false});
|
||||
|
||||
GlobalUI.closeDetail = function(){
|
||||
if(!!(window.history && window.history.pushState)){
|
||||
GlobalUI.closeDetail = function() {
|
||||
if (!!(window.history && window.history.pushState)) {
|
||||
throttleBack();
|
||||
} else{
|
||||
} else {
|
||||
Session.set("global.ui.detailShow", false);
|
||||
}
|
||||
};
|
||||
|
||||
GlobalUI.popStateHandler = function(e){
|
||||
GlobalUI.popStateHandler = function(e) {
|
||||
var state = e.originalEvent.state;
|
||||
if(state) {
|
||||
if(state.detail === "closed"){
|
||||
if (state) {
|
||||
if (state.detail === "closed") {
|
||||
Session.set("global.ui.detailShow", false);
|
||||
} else if(state.detail === "opened"){
|
||||
} else if (state.detail === "opened") {
|
||||
var opts = state.opts;
|
||||
Session.set("global.ui.detailData", opts.data);
|
||||
Session.set("global.ui.detailTemplate", opts.template);
|
||||
@@ -115,22 +115,22 @@ Template.layout.helpers({
|
||||
globalDialogFullOnMobile: function() {
|
||||
return Session.get("global.ui.dialogFullOnMobile");
|
||||
},
|
||||
globalDialogHeader: function(){
|
||||
globalDialogHeader: function() {
|
||||
return Session.get("global.ui.dialogHeader");
|
||||
},
|
||||
globalDetailSelected: function(){
|
||||
globalDetailSelected: function() {
|
||||
return Session.get("global.ui.detailShow") ? 1 : 0;
|
||||
},
|
||||
globalDetailTemplate: function(){
|
||||
globalDetailTemplate: function() {
|
||||
return Session.get("global.ui.detailTemplate");
|
||||
},
|
||||
globalDetailData: function(){
|
||||
globalDetailData: function() {
|
||||
return Session.get("global.ui.detailData");
|
||||
},
|
||||
globalToastTemplate: function(){
|
||||
globalToastTemplate: function() {
|
||||
return Session.get("global.ui.toastTemplate");
|
||||
},
|
||||
globalToastData: function(){
|
||||
globalToastData: function() {
|
||||
return Session.get("global.ui.toastData");
|
||||
}
|
||||
});
|
||||
@@ -143,7 +143,7 @@ Template.layout.events({
|
||||
},
|
||||
"core-animated-pages-transition-end [detail-pages]": function(e) {
|
||||
var detailOpened = Session.get("global.ui.detailShow");
|
||||
if(!detailOpened){
|
||||
if (!detailOpened) {
|
||||
Session.set("global.ui.detailData", null);
|
||||
Session.set("global.ui.detailTemplate", null);
|
||||
Session.set("global.ui.detailHeroId", null);
|
||||
@@ -151,14 +151,14 @@ Template.layout.events({
|
||||
},
|
||||
"core-animated-pages-transition-prepare": function(e) {
|
||||
var detailOpened = Session.get("global.ui.detailShow");
|
||||
if(detailOpened) {
|
||||
if (detailOpened) {
|
||||
//set up the transition
|
||||
} else {
|
||||
//undo hack
|
||||
$("#mainContentSection").removeClass("fake-selected");
|
||||
}
|
||||
},
|
||||
"tap #screenDim": function(e){
|
||||
"tap #screenDim": function(e) {
|
||||
GlobalUI.closeDetail();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Template.registerHelper("canCast", function(){
|
||||
Template.registerHelper("canCast", function() {
|
||||
return Characters.find({_id: this._id, spells: {$size: 0}}).count() === 0;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
Template.registerHelper("colorClass", function(color){
|
||||
if(color) return getColorClass(color);
|
||||
else if(this.color) return getColorClass(this.color);
|
||||
Template.registerHelper("colorClass", function(color) {
|
||||
if (color) {
|
||||
return getColorClass(color);
|
||||
} else if (this.color) {
|
||||
return getColorClass(this.color);
|
||||
}
|
||||
});
|
||||
|
||||
Template.registerHelper("hexColor", function(color){
|
||||
Template.registerHelper("hexColor", function(color) {
|
||||
return getHexColor(color);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
Template.registerHelper("detailHero", function(suffix, givenId){
|
||||
Template.registerHelper("detailHero", function(suffix, givenId) {
|
||||
var id = givenId || this._id;
|
||||
if(suffix) id += suffix;
|
||||
if ( Session.equals("global.ui.detailHeroId", id) ) {
|
||||
if (suffix) {
|
||||
id += suffix;
|
||||
}
|
||||
if (Session.equals("global.ui.detailHeroId", id)) {
|
||||
return "hero";
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
/*Template.registerHelper(function("effectList", */var disabled = function(charId, fieldName){
|
||||
var obj = Characters.findOne(charId, {fields: {_id: 1}}).getField(fieldName);
|
||||
var result = $("<div>");
|
||||
if(_.has(obj, "conditional") && obj.conditional.length > 0){
|
||||
_.each(obj.conditional, function(cond){
|
||||
var c = $("<div>")
|
||||
.append("* ")
|
||||
.append(evaluateString(charId, cond.name));
|
||||
result.append(c);
|
||||
});
|
||||
}
|
||||
|
||||
if(obj.base > 0){
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append(obj.base))
|
||||
.append("Base");
|
||||
result.append(c);
|
||||
}
|
||||
|
||||
if(_.has(obj, "proficiency") && obj.proficiency.length > 0){
|
||||
var highestProf = {};
|
||||
_.each(obj.proficiency, function(prof, i){
|
||||
var value = evaluateEffect(charId, prof)
|
||||
if(i === 0 || value > highestProf.value){
|
||||
highestProf.value = value;
|
||||
highestProf.name = prof.name;
|
||||
highestProf.calculation = prof.calculation;
|
||||
}
|
||||
});
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append(highestProf.value).append(" x Proficiency Bonus"))
|
||||
.append(highestProf.name);
|
||||
result.append(c);
|
||||
}
|
||||
|
||||
if(_.has(obj, "add") && obj.add.length > 0){
|
||||
_.each(obj.add, function(a){
|
||||
var value = signedString(evaluateEffect(charId, a));
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append(value))
|
||||
.append(a.name);
|
||||
result.append(c);
|
||||
});
|
||||
}
|
||||
|
||||
if(_.has(obj, "mul") && obj.mul.length > 0){
|
||||
_.each(obj.mul, function(a){
|
||||
var value = signedString(evaluateEffect(charId, a));
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append("×").append(value))
|
||||
.append(a.name);
|
||||
result.append(c);
|
||||
});
|
||||
}
|
||||
|
||||
if(_.has(obj, "min") && obj.min.length > 0){
|
||||
var highestMin = {};
|
||||
_.each(obj.min, function(m, i){
|
||||
var value = evaluateEffect(charId, m)
|
||||
if(i === 0 || value > highestMin.value){
|
||||
highestMin.value = value;
|
||||
highestMin.name = m.name;
|
||||
highestMin.calculation = m.calculation;
|
||||
}
|
||||
});
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append(highestMin.value).append(" Minimum"))
|
||||
.append(highestMin.name);
|
||||
result.append(c);
|
||||
}
|
||||
|
||||
if(_.has(obj, "max") && obj.max.length > 0){
|
||||
var lowestMax = {};
|
||||
_.each(obj.max, function(m, i){
|
||||
var value = evaluateEffect(charId, m)
|
||||
if(i === 0 || value < lowestMax.value){
|
||||
lowestMax.value = value;
|
||||
lowestMax.name = m.name;
|
||||
lowestMax.calculation = m.calculation;
|
||||
}
|
||||
});
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append(lowestMax.value).append(" Maximum"))
|
||||
.append(lowestMax.name);
|
||||
result.append(c);
|
||||
}
|
||||
|
||||
if(obj.base < 0){
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append(obj.base))
|
||||
.append("Damage");
|
||||
result.append(c);
|
||||
}
|
||||
|
||||
if(_.has(obj, "advantage") && obj.advantage.length > 0){
|
||||
_.each(obj.advantage, function(adv){
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append("Advantage"))
|
||||
.append(adv.name);
|
||||
result.append(c);
|
||||
})
|
||||
}
|
||||
|
||||
if(_.has(obj, "disadvantage") && obj.disadvantage.length > 0){
|
||||
_.each(obj.disadvantage, function(disadv){
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append("Disadvantage"))
|
||||
.append(disadv.name);
|
||||
result.append(c);
|
||||
})
|
||||
}
|
||||
|
||||
if(_.has(obj, "fail") && obj.fail.length > 0){
|
||||
_.each(obj.fail, function(f){
|
||||
var c = $("<div>")
|
||||
.append($("<span>").addClass("auditValue").append("Fail"))
|
||||
.append(f.name);
|
||||
result.append(c);
|
||||
})
|
||||
}
|
||||
var string = result.html()
|
||||
if (_.isString(string)) return Spacebars.SafeString(string);
|
||||
return string;
|
||||
};
|
||||
@@ -1,25 +1,25 @@
|
||||
Template.registerHelper("evaluate", function(charId, string){
|
||||
Template.registerHelper("evaluate", function(charId, string) {
|
||||
return evaluate(charId, string);
|
||||
});
|
||||
|
||||
Template.registerHelper("evaluateSigned", function(charId, string){
|
||||
Template.registerHelper("evaluateSigned", function(charId, string) {
|
||||
var number = evaluate(charId, string);
|
||||
if(_.isFinite(number)){
|
||||
return number > 0? "+" + number : "" + number;
|
||||
} else{
|
||||
if (_.isFinite(number)) {
|
||||
return number > 0 ? "+" + number : "" + number;
|
||||
} else {
|
||||
return number;
|
||||
}
|
||||
});
|
||||
|
||||
Template.registerHelper("evaluateSignedSpaced", function(charId, string){
|
||||
Template.registerHelper("evaluateSignedSpaced", function(charId, string) {
|
||||
var number = evaluate(charId, string);
|
||||
if(_.isFinite(number)){
|
||||
return number > 0? "+ " + number : "- " + (-1 * number);
|
||||
} else{
|
||||
if (_.isFinite(number)) {
|
||||
return number > 0 ? "+ " + number : "- " + (-1 * number);
|
||||
} else {
|
||||
return number;
|
||||
}
|
||||
});
|
||||
|
||||
Template.registerHelper("evaluateString", function(charId, string){
|
||||
Template.registerHelper("evaluateString", function(charId, string) {
|
||||
return evaluateString(charId, string);
|
||||
});
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
openParentDialog = function(parent, charId, heroId){
|
||||
openParentDialog = function(parent, charId, heroId) {
|
||||
var detail;
|
||||
if(parent.collection === "Characters" && parent.group === "racial"){
|
||||
if (parent.collection === "Characters" && parent.group === "racial") {
|
||||
detail = {
|
||||
template: "raceDialog",
|
||||
data: {charId: parent.id},
|
||||
};
|
||||
} else if( parent.collection === "Features" ){
|
||||
} else if (parent.collection === "Features") {
|
||||
detail = {
|
||||
template: "featureDialog",
|
||||
data: {featureId: parent.id},
|
||||
};
|
||||
} else if( parent.collection === "Classes" ){
|
||||
} else if (parent.collection === "Classes") {
|
||||
detail = {
|
||||
template: "classDialog",
|
||||
data: {classId: parent.id},
|
||||
};
|
||||
} else if( parent.collection === "Items" ){
|
||||
} else if (parent.collection === "Items") {
|
||||
detail = {
|
||||
template: "itemDialog",
|
||||
data: {itemId: parent.id},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Template.registerHelper("round", function(value, decimalPlaces){
|
||||
Template.registerHelper("round", function(value, decimalPlaces) {
|
||||
decimalPlaces = +decimalPlaces || 2;
|
||||
var num = +value;
|
||||
var tens = Math.pow(10, decimalPlaces)
|
||||
var tens = Math.pow(10, decimalPlaces);
|
||||
return Math.round(num * tens) / tens;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Template.registerHelper("session", function(key){
|
||||
Template.registerHelper("session", function(key) {
|
||||
return Session.get(key);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Template.registerHelper("signedString", function(number){
|
||||
return number >= 0? "+" + number : "" + number;
|
||||
});
|
||||
Template.registerHelper("signedString", function(number) {
|
||||
return number >= 0 ? "+" + number : "" + number;
|
||||
});
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
Template.registerHelper("valueString", function(value){
|
||||
Template.registerHelper("valueString", function(value) {
|
||||
var resultArray = [];
|
||||
//sp
|
||||
var gp = Math.floor(value);
|
||||
if(gp > 0) resultArray.push(gp + "gp");
|
||||
if (gp > 0) {
|
||||
resultArray.push(gp + "gp");
|
||||
}
|
||||
//sp
|
||||
var sp = Math.floor(10 * (value % 1));
|
||||
if(sp > 0) resultArray.push(sp + "sp");
|
||||
if (sp > 0) {
|
||||
resultArray.push(sp + "sp");
|
||||
}
|
||||
//cp
|
||||
var cp = 10 * ((value * 10) % 1);
|
||||
cp = Math.round(cp * 1000) / 1000;
|
||||
if(cp > 0) resultArray.push(cp + "cp");
|
||||
if (cp > 0) {
|
||||
resultArray.push(cp + "cp");
|
||||
}
|
||||
|
||||
//build string with correct spacing
|
||||
var result = "";
|
||||
for(var i = 0; i < resultArray.length; i++){
|
||||
for (var i = 0; i < resultArray.length; i++) {
|
||||
//add a space between values
|
||||
if(i !== 0){
|
||||
if (i !== 0) {
|
||||
result += " ";
|
||||
}
|
||||
result += resultArray[i];
|
||||
@@ -23,24 +29,30 @@ Template.registerHelper("valueString", function(value){
|
||||
return result;
|
||||
});
|
||||
|
||||
Template.registerHelper("longValueString", function(value){
|
||||
Template.registerHelper("longValueString", function(value) {
|
||||
var resultArray = [];
|
||||
//sp
|
||||
var gp = Math.floor(value);
|
||||
if(gp > 0) resultArray.push(gp + "gp");
|
||||
if (gp > 0) {
|
||||
resultArray.push(gp + "gp");
|
||||
}
|
||||
//sp
|
||||
var sp = Math.floor(10 * (value % 1));
|
||||
if(sp > 0 || resultArray.length) resultArray.push(sp + "sp");
|
||||
if (sp > 0 || resultArray.length) {
|
||||
resultArray.push(sp + "sp");
|
||||
}
|
||||
//cp
|
||||
var cp = 10 * ((value * 10) % 1);
|
||||
cp = Math.round(cp * 1000) / 1000;
|
||||
if(cp > 0 || resultArray.length) resultArray.push(cp + "cp");
|
||||
if (cp > 0 || resultArray.length) {
|
||||
resultArray.push(cp + "cp");
|
||||
}
|
||||
|
||||
//build string with correct spacing
|
||||
var result = "";
|
||||
for(var i = 0; i < resultArray.length; i++){
|
||||
for (var i = 0; i < resultArray.length; i++) {
|
||||
//add a space between values
|
||||
if(i !== 0){
|
||||
if (i !== 0) {
|
||||
result += " ";
|
||||
}
|
||||
result += resultArray[i];
|
||||
|
||||
@@ -1,44 +1,45 @@
|
||||
var damageTypes = ["bludgeoning", "piercing", "slashing", "acid", "cold", "fire", "force", "lightning", "necrotic",
|
||||
var damageTypes = ["bludgeoning", "piercing", "slashing",
|
||||
"acid", "cold", "fire", "force", "lightning", "necrotic",
|
||||
"poison", "psychic", "radiant", "thunder"];
|
||||
|
||||
Template.attackEdit.events({
|
||||
"tap #deleteAttack": function(event, instance){
|
||||
"tap #deleteAttack": function(event, instance) {
|
||||
Attacks.softRemoveNode(this._id);
|
||||
GlobalUI.deletedToast(this._id, "Attacks", "Attack");
|
||||
},
|
||||
"change #attackBonusInput": function(event){
|
||||
"change #attackBonusInput": function(event) {
|
||||
var value = event.currentTarget.value;
|
||||
Attacks.update(this._id, {$set: {attackBonus: value}});
|
||||
},
|
||||
"change #damageInput": function(event){
|
||||
"change #damageInput": function(event) {
|
||||
var value = event.currentTarget.value;
|
||||
Attacks.update(this._id, {$set: {damageBonus: value}});
|
||||
},
|
||||
"change #detailInput": function(event){
|
||||
"change #detailInput": function(event) {
|
||||
var value = event.currentTarget.value;
|
||||
Attacks.update(this._id, {$set: {details: value}});
|
||||
},
|
||||
"core-select #damageTypeDropdown": function(event){
|
||||
"core-select #damageTypeDropdown": function(event) {
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
if(value == this.damageType) return;
|
||||
if (value == this.damageType) return;
|
||||
Attacks.update(this._id, {$set: {damageType: value}});
|
||||
},
|
||||
"core-select #damageDiceDropdown": function(event){
|
||||
"core-select #damageDiceDropdown": function(event) {
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
if(value == this.damageDice) return;
|
||||
if (value == this.damageDice) return;
|
||||
Attacks.update(this._id, {$set: {damageDice: value}});
|
||||
}
|
||||
});
|
||||
|
||||
Template.attackEdit.helpers({
|
||||
damageTypes: function(){
|
||||
damageTypes: function() {
|
||||
return damageTypes;
|
||||
},
|
||||
DAMAGE_DICE: function(){
|
||||
DAMAGE_DICE: function() {
|
||||
return DAMAGE_DICE;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Template.attackEditList.helpers({
|
||||
attacks: function(){
|
||||
attacks: function() {
|
||||
var cursor = Attacks.find({"parent.id": this.parentId, charId: this.charId});
|
||||
return cursor;
|
||||
}
|
||||
});
|
||||
|
||||
Template.attackEditList.events({
|
||||
"tap #addAttackButton": function(){
|
||||
"tap #addAttackButton": function() {
|
||||
Attacks.insert({
|
||||
charId: this.charId,
|
||||
parent: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Template.attacksViewList.helpers({
|
||||
attacks: function(){
|
||||
attacks: function() {
|
||||
return Attacks.find({"parent.id": this.parentId, charId: this.charId});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Template.characterSettings.events({
|
||||
|
||||
|
||||
});
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
Template.deleteCharacterConfirmation.onCreated(function(){
|
||||
Template.deleteCharacterConfirmation.onCreated(function() {
|
||||
this.canDelete = new ReactiveVar(false);
|
||||
});
|
||||
|
||||
Template.deleteCharacterConfirmation.helpers({
|
||||
cantDelete: function(){
|
||||
cantDelete: function() {
|
||||
return !Template.instance().canDelete.get();
|
||||
},
|
||||
getStyle: function(){
|
||||
if(Template.instance().canDelete.get()) return "background: #d23f31; color: white;";
|
||||
getStyle: function() {
|
||||
if (Template.instance().canDelete.get()) {
|
||||
return "background: #d23f31; color: white;";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.deleteCharacterConfirmation.events({
|
||||
"change #nameInput, input #nameInput": function(event, instance){
|
||||
"change #nameInput, input #nameInput": function(event, instance) {
|
||||
var canDel = instance.find("#nameInput").value === this.name;
|
||||
instance.canDelete.set(canDel);
|
||||
},
|
||||
"tap #deleteButton": function(event, instance){
|
||||
if(instance.find("#nameInput").value === this.name){
|
||||
"tap #deleteButton": function(event, instance) {
|
||||
if (instance.find("#nameInput").value === this.name) {
|
||||
GlobalUI.closeDialog();
|
||||
Router.go("/");
|
||||
Characters.remove(this._id);
|
||||
|
||||
@@ -22,13 +22,14 @@ Template.shareDialog.helpers({
|
||||
});
|
||||
|
||||
Template.shareDialog.events({
|
||||
"input #userNameOrEmailInput, change #userNameOrEmailInput": function(event, instance){
|
||||
"input #userNameOrEmailInput, change #userNameOrEmailInput":
|
||||
function(event, instance){
|
||||
var userName = instance.find("#userNameOrEmailInput").value;
|
||||
instance.userId.set(undefined);
|
||||
Meteor.call("getUserId", userName, function (err, result) {
|
||||
if(err){
|
||||
Meteor.call("getUserId", userName, function(err, result) {
|
||||
if (err){
|
||||
console.error(err);
|
||||
} else{
|
||||
} else {
|
||||
console.log(result);
|
||||
instance.userId.set(result);
|
||||
}
|
||||
@@ -37,10 +38,10 @@ Template.shareDialog.events({
|
||||
"tap #shareButton": function(event, instance){
|
||||
var self = this;
|
||||
var permission = instance.find("#accessLevelMenu").selected;
|
||||
if(!permission) throw "no permission set";
|
||||
if (!permission) throw "no permission set";
|
||||
var userId = instance.userId.get();
|
||||
if(!userId) return;
|
||||
if(permission === "write"){
|
||||
if (!userId) return;
|
||||
if (permission === "write"){
|
||||
Characters.update(self._id, {
|
||||
$addToSet: {writers: userId},
|
||||
$pull: {readers: userId}
|
||||
|
||||
@@ -112,8 +112,8 @@ Template.effectEdit.helpers({
|
||||
},
|
||||
operations: function(){
|
||||
var group = Template.instance().selectedStatGroup.get();
|
||||
if(group === "Weakness/Resistance") return null;
|
||||
if(group === "Saving Throws" || group === "Skills"){
|
||||
if (group === "Weakness/Resistance") return null;
|
||||
if (group === "Saving Throws" || group === "Skills"){
|
||||
return skillOperations;
|
||||
} else {
|
||||
return attributeOperations;
|
||||
@@ -122,14 +122,14 @@ Template.effectEdit.helpers({
|
||||
effectValueTemplate: function(){
|
||||
//resistance/vulnerability template
|
||||
var group = Template.instance().selectedStatGroup.get();
|
||||
if(group === "Weakness/Resistance") return "multiplierEffectValue";
|
||||
if (group === "Weakness/Resistance") return "multiplierEffectValue";
|
||||
|
||||
var op = this.operation;
|
||||
if(!op) return null;
|
||||
if (!op) return null;
|
||||
//operations that don't need templates
|
||||
if(op === "advantage" || op === "disadvantage" || op === "fail") return null;
|
||||
if (op === "advantage" || op === "disadvantage" || op === "fail") return null;
|
||||
//proficiency template
|
||||
if(op === "proficiency") return "proficiencyEffectValue";
|
||||
if (op === "proficiency") return "proficiencyEffectValue";
|
||||
|
||||
//default template
|
||||
return "regularEffectValue";
|
||||
@@ -149,44 +149,57 @@ Template.effectEdit.events({
|
||||
},
|
||||
"core-select .statGroupDropDown": function(event, instance){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var groupName = detail.item.getAttribute("name");
|
||||
var oldName = Template.instance().selectedStatGroup.get();
|
||||
if(oldName != groupName){
|
||||
if (oldName != groupName){
|
||||
instance.selectedStatGroup.set(groupName);
|
||||
if(groupName === "Skills" || groupName === "Saving Throws"){
|
||||
Effects.update(this._id, {$set: {operation: "proficiency", value: 1, calculation: ""}, $unset: {stat: ""} });
|
||||
} else if(groupName === "Weakness/Resistance"){
|
||||
Effects.update(this._id, {$set: {value: 0.5, calculation: "", operation: "mul"}, $unset: {stat: ""} });
|
||||
if (groupName === "Skills" || groupName === "Saving Throws"){
|
||||
Effects.update(this._id, {$set: {
|
||||
operation: "proficiency",
|
||||
value: 1,
|
||||
calculation: ""
|
||||
}, $unset: {stat: ""}});
|
||||
} else if (groupName === "Weakness/Resistance"){
|
||||
Effects.update(this._id, {$set: {
|
||||
value: 0.5,
|
||||
calculation: "",
|
||||
operation: "mul"}, $unset: {stat: ""}});
|
||||
} else {
|
||||
Effects.update(this._id, { $set: {operation: "add"}, $unset: {stat: "", value: "", calculation: ""} });
|
||||
Effects.update(this._id,
|
||||
{$set: {operation: "add"},
|
||||
$unset: {stat: "", value: "", calculation: ""}});
|
||||
}
|
||||
}
|
||||
},
|
||||
"core-select .statDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var statName = detail.item.getAttribute("name");
|
||||
if (statName == this.stat) return;
|
||||
Effects.update(this._id, {$set: {stat: statName}});
|
||||
},
|
||||
"core-select .operationDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var opName = detail.item.getAttribute("name");
|
||||
if (opName == this.operation) return;
|
||||
Effects.update(this._id, {$set: {operation: opName}});
|
||||
},
|
||||
"core-select .damageMultiplierDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = +detail.item.getAttribute("name");
|
||||
if (value == this.value) return;
|
||||
Effects.update(this._id, {$set: {value: value, calculation: "", operation: "mul"}});
|
||||
Effects.update(this._id, {$set: {
|
||||
value: value,
|
||||
calculation: "",
|
||||
operation: "mul"
|
||||
}});
|
||||
},
|
||||
"core-select .proficiencyDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = +detail.item.getAttribute("name");
|
||||
if (value == this.value) return;
|
||||
Effects.update(this._id, {$set: {value: value, calculation: ""}});
|
||||
@@ -194,7 +207,7 @@ Template.effectEdit.events({
|
||||
"change .effectValueInput": function(event){
|
||||
var value = event.currentTarget.value;
|
||||
var numValue = +value;
|
||||
if(_.isFinite(numValue)){
|
||||
if (_.isFinite(numValue)){
|
||||
if (this.value === numValue) return;
|
||||
Effects.update(this._id, {$set: {value: numValue, calculation: ""}});
|
||||
} else if (_.isString(value)){
|
||||
|
||||
@@ -6,31 +6,31 @@ var stats = {
|
||||
"intelligence":{"name":"Intelligence"},
|
||||
"wisdom":{"name":"Wisdom"},
|
||||
"charisma":{"name":"Charisma"},
|
||||
"strengthSave":{"name":"Strength Save",},
|
||||
"dexteritySave":{"name":"Dexterity Save",},
|
||||
"constitutionSave":{"name":"Constitution Save",},
|
||||
"intelligenceSave":{"name":"Intelligence Save",},
|
||||
"wisdomSave":{"name":"Wisdom Save",},
|
||||
"charismaSave":{"name":"Charisma Save",},
|
||||
"acrobatics":{"name":"Acrobatics",},
|
||||
"animalHandling":{"name":"Animal Handling",},
|
||||
"arcana":{"name":"Arcana",},
|
||||
"athletics":{"name":"Athletics",},
|
||||
"deception":{"name":"Deception",},
|
||||
"history":{"name":"History",},
|
||||
"insight":{"name":"Insight",},
|
||||
"intimidation":{"name":"Intimidation",},
|
||||
"investigation":{"name":"Investigation",},
|
||||
"medicine":{"name":"Medicine",},
|
||||
"nature":{"name":"Nature",},
|
||||
"perception":{"name":"Perception",},
|
||||
"performance":{"name":"Performance",},
|
||||
"persuasion":{"name":"Persuasion",},
|
||||
"religion":{"name":"Religion",},
|
||||
"sleightOfHand":{"name":"Sleight of Hand",},
|
||||
"stealth":{"name":"Stealth",},
|
||||
"survival":{"name":"Survival",},
|
||||
"initiative":{"name":"Initiative",},
|
||||
"strengthSave":{"name":"Strength Save"},
|
||||
"dexteritySave":{"name":"Dexterity Save"},
|
||||
"constitutionSave":{"name":"Constitution Save"},
|
||||
"intelligenceSave":{"name":"Intelligence Save"},
|
||||
"wisdomSave":{"name":"Wisdom Save"},
|
||||
"charismaSave":{"name":"Charisma Save"},
|
||||
"acrobatics":{"name":"Acrobatics"},
|
||||
"animalHandling":{"name":"Animal Handling"},
|
||||
"arcana":{"name":"Arcana"},
|
||||
"athletics":{"name":"Athletics"},
|
||||
"deception":{"name":"Deception"},
|
||||
"history":{"name":"History"},
|
||||
"insight":{"name":"Insight"},
|
||||
"intimidation":{"name":"Intimidation"},
|
||||
"investigation":{"name":"Investigation"},
|
||||
"medicine":{"name":"Medicine"},
|
||||
"nature":{"name":"Nature"},
|
||||
"perception":{"name":"Perception"},
|
||||
"performance":{"name":"Performance"},
|
||||
"persuasion":{"name":"Persuasion"},
|
||||
"religion":{"name":"Religion"},
|
||||
"sleightOfHand":{"name":"Sleight of Hand"},
|
||||
"stealth":{"name":"Stealth"},
|
||||
"survival":{"name":"Survival"},
|
||||
"initiative":{"name":"Initiative"},
|
||||
"hitPoints":{"name":"Hit Points"},
|
||||
"armor":{"name":"Armor"},
|
||||
"dexterityArmor":{"name":"Dexterity Armor Bonus"},
|
||||
@@ -56,18 +56,42 @@ var stats = {
|
||||
"d10HitDice":{"name":"d10 Hit Dice"},
|
||||
"d12HitDice":{"name":"d12 Hit Dice"},
|
||||
"acidMultiplier":{"name":"Acid damage", "group": "Weakness/Resistance"},
|
||||
"bludgeoningMultiplier":{"name":"Bludgeoning damage", "group": "Weakness/Resistance"},
|
||||
"coldMultiplier":{"name":"Cold damage", "group": "Weakness/Resistance"},
|
||||
"fireMultiplier":{"name":"Fire damage", "group": "Weakness/Resistance"},
|
||||
"forceMultiplier":{"name":"Force damage", "group": "Weakness/Resistance"},
|
||||
"lightningMultiplier":{"name":"Lightning damage", "group": "Weakness/Resistance"},
|
||||
"necroticMultiplier":{"name":"Necrotic damage", "group": "Weakness/Resistance"},
|
||||
"piercingMultiplier":{"name":"Piercing damage", "group": "Weakness/Resistance"},
|
||||
"poisonMultiplier":{"name":"Poison damage", "group": "Weakness/Resistance"},
|
||||
"psychicMultiplier":{"name":"Psychic damage", "group": "Weakness/Resistance"},
|
||||
"radiantMultiplier":{"name":"Radiant damage", "group": "Weakness/Resistance"},
|
||||
"slashingMultiplier":{"name":"Slashing damage", "group": "Weakness/Resistance"},
|
||||
"thunderMultiplier":{"name":"Thunder damage", "group": "Weakness/Resistance"}
|
||||
"bludgeoningMultiplier":{
|
||||
"name":"Bludgeoning damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"coldMultiplier":{
|
||||
"name":"Cold damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"fireMultiplier":{
|
||||
"name":"Fire damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"forceMultiplier":{
|
||||
"name":"Force damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"lightningMultiplier":{
|
||||
"name":"Lightning damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"necroticMultiplier":{
|
||||
"name":"Necrotic damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"piercingMultiplier":{
|
||||
"name":"Piercing damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"poisonMultiplier":{
|
||||
"name":"Poison damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"psychicMultiplier":{
|
||||
"name":"Psychic damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"radiantMultiplier":{
|
||||
"name":"Radiant damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"slashingMultiplier":{
|
||||
"name":"Slashing damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
"thunderMultiplier":{
|
||||
"name":"Thunder damage", "group": "Weakness/Resistance"
|
||||
},
|
||||
};
|
||||
|
||||
var operations = {
|
||||
@@ -107,7 +131,7 @@ Template.effectView.helpers({
|
||||
},
|
||||
operationName: function(){
|
||||
if(this.operation === "proficiency" ||
|
||||
this.operation === "conditional") return null;
|
||||
this.operation === "conditional") return null;
|
||||
if(stats[this.stat].group === "Weakness/Resistance") return null;
|
||||
if(this.operation === "add" && evaluateEffect(this.charId, this) < 0) return null;
|
||||
return operations[this.operation] && operations[this.operation].name || "No Operation";
|
||||
@@ -127,9 +151,9 @@ Template.effectView.helpers({
|
||||
return this.calculation || this.value;
|
||||
}
|
||||
if(stats[this.stat].group === "Weakness/Resistance"){
|
||||
if(this.value == 0.5 || this.calculation == 0.5) return "Resistance";
|
||||
if(this.value == 2 || this.calculation == 2) return "Vulnerability";
|
||||
if(this.value == 0 || this.calculation == 0) return "Immunity";
|
||||
if(this.value === 0.5) return "Resistance";
|
||||
if(this.value === 2) return "Vulnerability";
|
||||
if(this.value === 0) return "Immunity";
|
||||
}
|
||||
var value = evaluateEffect(this.charId, this);
|
||||
if(_.isNumber(value)) return value;
|
||||
|
||||
@@ -5,7 +5,7 @@ Template.effectsEditList.helpers({
|
||||
"parent.collection": this.parentCollection,
|
||||
"charId": this.charId
|
||||
};
|
||||
if(this.parentGroup){
|
||||
if (this.parentGroup){
|
||||
selector["parent.group"] = this.parentGroup;
|
||||
}
|
||||
var cursor = Effects.find(selector);
|
||||
@@ -15,7 +15,7 @@ Template.effectsEditList.helpers({
|
||||
|
||||
Template.effectsEditList.events({
|
||||
"tap #addEffectButton": function(){
|
||||
if ( !_.isBoolean(this.enabled) ) {
|
||||
if (!_.isBoolean(this.enabled)) {
|
||||
this.enabled = true;
|
||||
}
|
||||
Effects.insert({
|
||||
@@ -29,4 +29,4 @@ Template.effectsEditList.events({
|
||||
enabled: this.enabled
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ Template.effectsViewList.helpers({
|
||||
"parent.id": this.parentId,
|
||||
"charId": this.charId
|
||||
};
|
||||
if(this.parentGroup){
|
||||
if (this.parentGroup){
|
||||
selector["parent.group"] = this.parentGroup;
|
||||
}
|
||||
return Effects.find(selector, {fields: {parent: 0}});
|
||||
|
||||
@@ -17,7 +17,7 @@ Template.featureDialog.events({
|
||||
|
||||
Template.featureDetails.helpers({
|
||||
or: function(a, b){
|
||||
return a ||b;
|
||||
return a || b;
|
||||
},
|
||||
hasUses: function(){
|
||||
return this.usesValue() > 0;
|
||||
@@ -43,7 +43,7 @@ Template.featureDetails.events({
|
||||
"change .enabledCheckbox": function(event){
|
||||
var enabled = !this.enabled;
|
||||
Features.update(this._id, {$set: {enabled: enabled}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.featureEdit.onRendered(function(){
|
||||
@@ -55,10 +55,10 @@ Template.featureEdit.helpers({
|
||||
return _.isString(this.uses);
|
||||
},
|
||||
enabledSelection: function(){
|
||||
if(!this.enabled) return "disabled";
|
||||
if(this.alwaysEnabled) return "alwaysEnabled";
|
||||
if (!this.enabled) return "disabled";
|
||||
if (this.alwaysEnabled) return "alwaysEnabled";
|
||||
return "enabled";
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.featureEdit.events({
|
||||
@@ -73,7 +73,7 @@ Template.featureEdit.events({
|
||||
"change #limitUseCheck": function(event){
|
||||
var currentUses = this.uses;
|
||||
var featureId = this._id;
|
||||
if( event.target.checked && !_.isString(currentUses) ){
|
||||
if (event.target.checked && !_.isString(currentUses)){
|
||||
Features.update(featureId, {$set: {uses: ""}}, {removeEmptyStrings: false});
|
||||
} else if (!event.target.checked && _.isString(currentUses)){
|
||||
Features.update(featureId, {$unset: {uses: ""}});
|
||||
@@ -86,17 +86,18 @@ Template.featureEdit.events({
|
||||
},
|
||||
"core-select #enabledDropdown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
var setter;
|
||||
if(value === "enabled"){
|
||||
if (value === "enabled"){
|
||||
setter = {enabled: true, alwaysEnabled: false};
|
||||
} else if (value === "disabled"){
|
||||
setter = {enabled: false, alwaysEnabled: false};
|
||||
} else{
|
||||
} else {
|
||||
setter = {enabled: true, alwaysEnabled: true};
|
||||
}
|
||||
if (setter.enabled === this.enabled && setter.alwaysEnabled === this.alwaysEnabled) return;
|
||||
if (setter.enabled === this.enabled &&
|
||||
setter.alwaysEnabled === this.alwaysEnabled) return;
|
||||
Features.update(this._id, {$set: setter});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -19,7 +19,9 @@ Template.features.helpers({
|
||||
return _.indexOf(_.keys(colorOptions), this.color);
|
||||
},
|
||||
attacks: function(){
|
||||
return Attacks.find({charId: this._id, enabled: true}, {sort: {color: 1, name: 1}});
|
||||
return Attacks.find(
|
||||
{charId: this._id, enabled: true},
|
||||
{sort: {color: 1, name: 1}});
|
||||
},
|
||||
canEnable: function(){
|
||||
return !this.alwaysEnabled;
|
||||
@@ -41,7 +43,7 @@ Template.features.events({
|
||||
GlobalUI.setDetail({
|
||||
template: "featureDialog",
|
||||
data: {featureId: featureId, charId: this._id, startEditing: true},
|
||||
heroId: featureId
|
||||
heroId: featureId,
|
||||
});
|
||||
},
|
||||
"tap #addAttackButton": function(event){
|
||||
@@ -49,11 +51,11 @@ Template.features.events({
|
||||
Attacks.insert({
|
||||
charId: charId
|
||||
}, function(error, id){
|
||||
if(!error){
|
||||
if (!error){
|
||||
GlobalUI.setDetail({
|
||||
template: "attackDialog",
|
||||
data: {attackId: id, charId: charId},
|
||||
heroId: id
|
||||
heroId: id,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -64,7 +66,7 @@ Template.features.events({
|
||||
GlobalUI.setDetail({
|
||||
template: "featureDialog",
|
||||
data: {featureId: featureId, charId: charId},
|
||||
heroId: featureId
|
||||
heroId: featureId,
|
||||
});
|
||||
},
|
||||
"tap .attack": function(event){
|
||||
@@ -82,8 +84,13 @@ Template.features.events({
|
||||
var charId = this._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "textDialog",
|
||||
data: {charId: charId, field: "proficiencies", title: "Proficiencies", color: "q"},
|
||||
heroId: this._id + "proficiencies"
|
||||
data: {
|
||||
charId: charId,
|
||||
field: "proficiencies",
|
||||
title: "Proficiencies",
|
||||
color: "q",
|
||||
},
|
||||
heroId: this._id + "proficiencies",
|
||||
});
|
||||
},
|
||||
"tap .enabledCheckbox": function(event){
|
||||
@@ -92,45 +99,48 @@ Template.features.events({
|
||||
"change .enabledCheckbox": function(event){
|
||||
var enabled = !this.enabled;
|
||||
Features.update(this._id, {$set: {enabled: enabled}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.resource.helpers({
|
||||
cantIncrement: function(){
|
||||
return !(this.char.attributeValue(this.name) < this.char.attributeBase(this.name));
|
||||
var baseBigger = this.char.attributeValue(this.name) <
|
||||
this.char.attributeBase(this.name);
|
||||
return !baseBigger;
|
||||
},
|
||||
cantDecrement: function(){
|
||||
return !(this.char.attributeValue(this.name) > 0);
|
||||
var valuePositive = this.char.attributeValue(this.name) > 0;
|
||||
return !valuePositive;
|
||||
},
|
||||
getColor: function(){
|
||||
if(this.char.attributeValue(this.name) > 0){
|
||||
if (this.char.attributeValue(this.name) > 0){
|
||||
return this.color;
|
||||
} else {
|
||||
return "grey";
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.resource.events({
|
||||
"tap .resourceUp": function(event){
|
||||
if(this.char.attributeValue(this.name) < this.char.attributeBase(this.name)){
|
||||
if (this.char.attributeValue(this.name) < this.char.attributeBase(this.name)){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = 1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
},
|
||||
"tap .resourceDown": function(event){
|
||||
if(this.char.attributeValue(this.name) > 0){
|
||||
if (this.char.attributeValue(this.name) > 0){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = -1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
},
|
||||
"tap .containerRight": function (event, instance) {
|
||||
"tap .containerRight": function(event, instance) {
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: this.title, statName: this.name, charId: this.char._id},
|
||||
heroId: this.char._id + this.name
|
||||
heroId: this.char._id + this.name,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -14,7 +14,10 @@ Template.containerEdit.events({
|
||||
},
|
||||
"tap #deleteButton": function(event, instance){
|
||||
Containers.softRemoveNode(instance.data.containerId);
|
||||
GlobalUI.deletedToast(instance.data.containerId, "Containers", "Container and contents");
|
||||
GlobalUI.deletedToast(
|
||||
instance.data.containerId,
|
||||
"Containers", "Container and contents"
|
||||
);
|
||||
GlobalUI.closeDetail();
|
||||
},
|
||||
//TODO validate input (integer, non-negative, etc) for these inputs and give validation errors
|
||||
@@ -30,8 +33,8 @@ Template.containerEdit.events({
|
||||
var value = +Template.instance().find("#valueInput").value;
|
||||
Containers.update(this._id, {$set: {value: value}});
|
||||
},
|
||||
"change #containerDescriptionInput": function(event){
|
||||
var description = Template.instance().find("#containerDescriptionInput").value;
|
||||
"change #containerDescriptionInput": function(event, instance){
|
||||
var description = instance.find("#containerDescriptionInput").value;
|
||||
Containers.update(this._id, {$set: {description: description}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -7,16 +7,28 @@ Template.inventory.helpers({
|
||||
return Containers.find({charId: this._id}, {sort: {color: 1, name: 1}});
|
||||
},
|
||||
items: function(charId, containerId){
|
||||
return Items.find({charId: charId, "parent.id": containerId }, {sort: {color: 1, name: 1}});
|
||||
return Items.find(
|
||||
{charId: charId, "parent.id": containerId},
|
||||
{sort: {color: 1, name: 1}}
|
||||
);
|
||||
},
|
||||
attuned: function(){
|
||||
return Items.find({ charId: this._id, enabled: true, requiresAttunement: true }, {sort: {color: 1, name: 1}});
|
||||
return Items.find(
|
||||
{charId: this._id, enabled: true, requiresAttunement: true},
|
||||
{sort: {color: 1, name: 1}}
|
||||
);
|
||||
},
|
||||
equipment: function(){
|
||||
return Items.find({ charId: this._id, enabled: true, requiresAttunement: false }, {sort: {color: 1, name: 1}});
|
||||
return Items.find(
|
||||
{charId: this._id, enabled: true, requiresAttunement: false},
|
||||
{sort: {color: 1, name: 1}}
|
||||
);
|
||||
},
|
||||
carriedItems: function(){
|
||||
return Items.find({charId: this._id, enabled: false, "parent.id": this._id}, {sort: {color: 1, name: 1}});
|
||||
return Items.find(
|
||||
{charId: this._id, enabled: false, "parent.id": this._id},
|
||||
{sort: {color: 1, name: 1}}
|
||||
);
|
||||
},
|
||||
showAddButtons: function(){
|
||||
return Template.instance().showAddButtons.get();
|
||||
@@ -26,45 +38,64 @@ Template.inventory.helpers({
|
||||
},
|
||||
netWorth: function(){
|
||||
var worth = 0;
|
||||
Items.find({charId: this._id}, {fields: {value : 1, quantity: 1}}).forEach(function(item){
|
||||
Items.find(
|
||||
{charId: this._id},
|
||||
{fields: {value : 1, quantity: 1}}
|
||||
).forEach(function(item){
|
||||
worth += item.totalValue();
|
||||
});
|
||||
return worth;
|
||||
},
|
||||
weightCarried: function(){
|
||||
var weight = 0;
|
||||
Containers.find({charId: this._id, isCarried: true}).forEach(function(container){
|
||||
Containers.find(
|
||||
{charId: this._id, isCarried: true}
|
||||
).forEach(function(container){
|
||||
weight += container.totalWeight();
|
||||
});
|
||||
Items.find({charId: this._id, "parent.id": this._id}, {fields: {weight : 1, quantity: 1}}).forEach(function(item){
|
||||
Items.find(
|
||||
{charId: this._id, "parent.id": this._id},
|
||||
{fields: {weight : 1, quantity: 1}}
|
||||
).forEach(function(item){
|
||||
weight += item.totalWeight();
|
||||
});
|
||||
return weight;
|
||||
},
|
||||
equipmentValue: function(){
|
||||
var value = 0;
|
||||
Items.find({charId: this._id, enabled: true}, {fields: {value : 1, quantity: 1}}).forEach(function(item){
|
||||
Items.find(
|
||||
{charId: this._id, enabled: true},
|
||||
{fields: {value : 1, quantity: 1}}
|
||||
).forEach(function(item){
|
||||
value += item.totalValue();
|
||||
});
|
||||
return value;
|
||||
},
|
||||
equipmentWeight: function(){
|
||||
var weight = 0;
|
||||
Items.find({charId: this._id, enabled: true}, {fields: {weight : 1, quantity: 1}}).forEach(function(item){
|
||||
Items.find({charId: this._id, enabled: true},
|
||||
{fields: {weight : 1, quantity: 1}}
|
||||
).forEach(function(item){
|
||||
weight += item.totalWeight();
|
||||
});
|
||||
return weight;
|
||||
},
|
||||
carriedValue: function(){
|
||||
var value = 0;
|
||||
Items.find({charId: this._id, enabled: false, "parent.id": this._id}, {fields: {value : 1, quantity: 1}}).forEach(function(item){
|
||||
Items.find(
|
||||
{charId: this._id, enabled: false, "parent.id": this._id},
|
||||
{fields: {value : 1, quantity: 1}}
|
||||
).forEach(function(item){
|
||||
value += item.totalValue();
|
||||
});
|
||||
return value;
|
||||
},
|
||||
carriedWeight: function(){
|
||||
var weight = 0;
|
||||
Items.find({charId: this._id, enabled: false, "parent.id": this._id}, {fields: {weight : 1, quantity: 1}}).forEach(function(item){
|
||||
Items.find(
|
||||
{charId: this._id, enabled: false, "parent.id": this._id},
|
||||
{fields: {weight : 1, quantity: 1}}
|
||||
).forEach(function(item){
|
||||
weight += item.totalWeight();
|
||||
});
|
||||
return weight;
|
||||
@@ -78,23 +109,31 @@ Template.inventory.events({
|
||||
charId: charId,
|
||||
parent:{
|
||||
id: charId,
|
||||
collection: "Characters"
|
||||
}
|
||||
collection: "Characters",
|
||||
},
|
||||
}, function(err, itemId){
|
||||
if(err) throw err;
|
||||
if (err) throw err;
|
||||
GlobalUI.setDetail({
|
||||
template: "itemDialog",
|
||||
data: {itemId: itemId, charId: charId, startEditing: true},
|
||||
heroId: itemId
|
||||
heroId: itemId,
|
||||
});
|
||||
});
|
||||
},
|
||||
"tap #addContainer": function(event){
|
||||
var containerId = Containers.insert({name: "New Container", isCarried: true, charId: this._id});
|
||||
var containerId = Containers.insert({
|
||||
name: "New Container",
|
||||
isCarried: true,
|
||||
charId: this._id,
|
||||
});
|
||||
GlobalUI.setDetail({
|
||||
template: "containerDialog",
|
||||
data: {containerId: containerId, charId: this.charId, startEditing: true},
|
||||
heroId: containerId
|
||||
data: {
|
||||
containerId: containerId,
|
||||
charId: this.charId,
|
||||
startEditing: true,
|
||||
},
|
||||
heroId: containerId,
|
||||
});
|
||||
},
|
||||
"tap .inventoryItem": function(event){
|
||||
@@ -103,14 +142,14 @@ Template.inventory.events({
|
||||
GlobalUI.setDetail({
|
||||
template: "itemDialog",
|
||||
data: {itemId: itemId, charId: charId},
|
||||
heroId: itemId
|
||||
heroId: itemId,
|
||||
});
|
||||
},
|
||||
"tap .containerTop": function(event){
|
||||
GlobalUI.setDetail({
|
||||
template: "containerDialog",
|
||||
data: {containerId: this._id, charId: this.charId},
|
||||
heroId: this._id
|
||||
heroId: this._id,
|
||||
});
|
||||
},
|
||||
"tap .carriedCheckbox": function(event){
|
||||
@@ -118,10 +157,10 @@ Template.inventory.events({
|
||||
},
|
||||
"change .carriedCheckbox": function(event){
|
||||
var carried;
|
||||
if(this.isCarried) carried = false;
|
||||
if (this.isCarried) carried = false;
|
||||
else carried = true;
|
||||
Containers.update(this._id, {$set: {isCarried: carried}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.inventoryItem.helpers({
|
||||
@@ -129,8 +168,8 @@ Template.inventoryItem.helpers({
|
||||
return num !== 1;
|
||||
},
|
||||
hidden: function(){
|
||||
return Session.equals("inventory.dragItemId", this._id)? "hidden" : null;
|
||||
}
|
||||
return Session.equals("inventory.dragItemId", this._id) ? "hidden" : null;
|
||||
},
|
||||
});
|
||||
|
||||
Template.layout.events({
|
||||
@@ -153,17 +192,17 @@ Template.layout.events({
|
||||
},
|
||||
"drop .itemContainer": function(event, instacne){
|
||||
var item = Items.findOne(Session.get("inventory.dragItemId"));
|
||||
if(event.ctrlKey){
|
||||
if (event.ctrlKey){
|
||||
//split the stack to the container
|
||||
GlobalUI.showDialog({
|
||||
template: "splitStackDialog",
|
||||
data: {
|
||||
id: item._id,
|
||||
parentCollection: "Containers",
|
||||
parentId: this._id
|
||||
}
|
||||
parentId: this._id,
|
||||
},
|
||||
});
|
||||
} else{
|
||||
} else {
|
||||
//move item to the container
|
||||
item.moveToContainer(this._id);
|
||||
}
|
||||
@@ -178,22 +217,22 @@ Template.layout.events({
|
||||
"drop .carriedContainer": function(event, instance){
|
||||
var charId = Session.get("inventory.dragItemOriginalCharacter");
|
||||
var item = Items.findOne(Session.get("inventory.dragItemId"));
|
||||
if(event.ctrlKey){
|
||||
if (event.ctrlKey){
|
||||
//split the stack to the container
|
||||
GlobalUI.showDialog({
|
||||
template: "splitStackDialog",
|
||||
data: {
|
||||
id: item._id,
|
||||
parentCollection: "Characters",
|
||||
parentId: this._id
|
||||
}
|
||||
parentId: this._id,
|
||||
},
|
||||
});
|
||||
} else{
|
||||
} else {
|
||||
//move item to the character
|
||||
item.moveToCharacter(this._id);
|
||||
}
|
||||
resetInvetorySession();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var resetInvetorySession = function(){
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
var getContainers = function(charId){
|
||||
return Containers.find({charId: charId}, {sort: {name: 1, _id: 1}, fields: {name: 1}});
|
||||
return Containers.find(
|
||||
{charId: charId},
|
||||
{sort: {name: 1, _id: 1}, fields: {name: 1}}
|
||||
);
|
||||
};
|
||||
|
||||
Template.itemDialog.onCreated(function(){
|
||||
@@ -14,13 +17,13 @@ Template.itemDialog.helpers({
|
||||
return Template.instance().editing.get();
|
||||
},
|
||||
itemHeading: function(){
|
||||
if(this.quantity === 1){
|
||||
if (this.quantity === 1){
|
||||
return this.name;
|
||||
} else{
|
||||
} else {
|
||||
var pName = this.plural || this.name;
|
||||
return this.quantity + " " + pName;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.itemDialog.events({
|
||||
@@ -79,8 +82,8 @@ Template.itemEdit.events({
|
||||
"change #equippedInput": function(event){
|
||||
var equipped = Template.instance().find("#equippedInput").checked;
|
||||
var item = Items.findOne(this._id);
|
||||
if(item){
|
||||
if(equipped){
|
||||
if (item){
|
||||
if (equipped){
|
||||
item.equip();
|
||||
} else {
|
||||
item.unequip();
|
||||
@@ -90,7 +93,7 @@ Template.itemEdit.events({
|
||||
"change #attunementCheckbox": function(event){
|
||||
var value = event.currentTarget.checked;
|
||||
Items.update(this._id, {$set: {requiresAttunement: value}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.containerDropdown.helpers({
|
||||
@@ -102,7 +105,7 @@ Template.containerDropdown.helpers({
|
||||
Template.containerDropdown.events({
|
||||
"core-select #containerDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var containerId = detail.item.getAttribute("name");
|
||||
var item = Items.findOne(Template.currentData()._id);
|
||||
item.moveToContainer(containerId);
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
Template.splitStackDialog.helpers({
|
||||
quantity: function(){
|
||||
var item = Items.findOne(this.id);
|
||||
if(item) return Math.round(item.quantity/2);
|
||||
if (item) return Math.round(item.quantity / 2);
|
||||
}
|
||||
});
|
||||
|
||||
Template.splitStackDialog.events({
|
||||
'tap #moveButton': function(event, instance){
|
||||
"tap #moveButton": function(event, instance){
|
||||
var item = Items.findOne(this.id);
|
||||
if(item){
|
||||
if (item){
|
||||
item.splitToParent(
|
||||
{collection: this.parentCollection , id: this.parentId},
|
||||
+instance.find('#quantityInput').value
|
||||
{collection: this.parentCollection , id: this.parentId},
|
||||
+instance.find("#quantityInput").value
|
||||
);
|
||||
}
|
||||
},
|
||||
'tap #oneButton':function(event, instance){
|
||||
instance.find('#quantityInput').value = 1;
|
||||
"tap #oneButton":function(event, instance){
|
||||
instance.find("#quantityInput").value = 1;
|
||||
},
|
||||
'tap #halfButton':function(event, instance){
|
||||
instance.find('#quantityInput').value = Math.round(Items.findOne(this.id).quantity/2);
|
||||
"tap #halfButton":function(event, instance){
|
||||
var val = Math.round(Items.findOne(this.id).quantity / 2);
|
||||
instance.find("#quantityInput").value = val;
|
||||
},
|
||||
"tap #allButton":function(event, instance){
|
||||
instance.find("#quantityInput").value = Items.findOne(this.id).quantity;
|
||||
},
|
||||
'tap #allButton':function(event, instance){
|
||||
instance.find('#quantityInput').value = Items.findOne(this.id).quantity;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -15,11 +15,11 @@ Template.classDialog.events({
|
||||
"change #levelValueInput": function(event){
|
||||
var value = event.currentTarget.value;
|
||||
Classes.update(this._id, {$set: {level: value}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.classDialog.helpers({
|
||||
class: function(){
|
||||
return Classes.findOne(this.classId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,10 @@ Template.experienceDialog.helpers({
|
||||
Template.experienceDialog.events({
|
||||
"tap #deleteButton": function(event, instance){
|
||||
Experiences.softRemove(instance.data.experienceId);
|
||||
GlobalUI.deletedToast(instance.data.experienceId, "Experiences", "Experience");
|
||||
GlobalUI.deletedToast(
|
||||
instance.data.experienceId,
|
||||
"Experiences", "Experience"
|
||||
);
|
||||
GlobalUI.closeDetail();
|
||||
},
|
||||
//TODO validate input (integer, non-negative, etc) for these inputs and give validation errors
|
||||
@@ -22,7 +25,7 @@ Template.experienceDialog.events({
|
||||
"change #experienceDescriptionInput": function(event){
|
||||
var value = event.currentTarget.value;
|
||||
Experiences.update(this._id, {$set: {description: value}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.experienceDialog.helpers({
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
Template.journal.created = function(){
|
||||
var self = this;
|
||||
self.experiencesLimit = new ReactiveVar(self.data.settings && self.data.settings.experiencesInc || 10);
|
||||
self.experiencesLimit = new ReactiveVar(
|
||||
self.data.settings && self.data.settings.experiencesInc || 10
|
||||
);
|
||||
};
|
||||
|
||||
Template.journal.helpers({
|
||||
@@ -8,17 +10,29 @@ Template.journal.helpers({
|
||||
return Notes.find({charId: this._id}, {sort: {color: 1, name: 1}});
|
||||
},
|
||||
experiences: function(){
|
||||
return Experiences.find({charId: this._id}, {sort: {dateAdded: -1}, limit: Template.instance().experiencesLimit.get()});
|
||||
return Experiences.find(
|
||||
{charId: this._id},
|
||||
{
|
||||
sort: {dateAdded: -1},
|
||||
limit: Template.instance().experiencesLimit.get(),
|
||||
}
|
||||
);
|
||||
},
|
||||
notMoreExperiences: function(){
|
||||
return Experiences.find({charId: this._id}).count() < Template.instance().experiencesLimit.get();
|
||||
return Experiences.find(
|
||||
{charId: this._id}
|
||||
).count() < Template.instance().experiencesLimit.get();
|
||||
},
|
||||
cantCollapse: function(){
|
||||
return Template.instance().experiencesLimit.get() <= (this.settings && this.settings.experiencesInc || 10);
|
||||
return Template.instance().experiencesLimit.get() <=
|
||||
(this.settings && this.settings.experiencesInc || 10);
|
||||
},
|
||||
moreExperiencesOrCollapse: function(){
|
||||
return (!(Experiences.find({charId: this._id}).count() < Template.instance().experiencesLimit.get())) ||
|
||||
Template.instance().experiencesLimit.get() > (this.settings && this.settings.experiencesInc || 10);
|
||||
var allShown = Experiences.find({charId: this._id}).count() <
|
||||
Template.instance().experiencesLimit.get();
|
||||
var canCollapse = Template.instance().experiencesLimit.get() >
|
||||
(this.settings && this.settings.experiencesInc || 10);
|
||||
return !allShown || canCollapse;
|
||||
},
|
||||
classes: function(){
|
||||
return Classes.find({charId: this._id}, {sort: {createdAt: 1}});
|
||||
@@ -29,13 +43,13 @@ Template.journal.helpers({
|
||||
nextLevelXP: function(){
|
||||
var currentLevel = this.level();
|
||||
if (currentLevel < 20){
|
||||
return xpTable[currentLevel];
|
||||
return XP_TABLE[currentLevel];
|
||||
}
|
||||
},
|
||||
race: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {race: 1}});
|
||||
return char && char.race;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.journal.events({
|
||||
@@ -43,41 +57,41 @@ Template.journal.events({
|
||||
GlobalUI.setDetail({
|
||||
template: "noteDialog",
|
||||
data: {noteId: this._id, charId: this.charId},
|
||||
heroId: this._id
|
||||
heroId: this._id,
|
||||
});
|
||||
},
|
||||
"tap .experience": function(event){
|
||||
GlobalUI.setDetail({
|
||||
template: "experienceDialog",
|
||||
data: {experienceId: this._id, charId: this.charId},
|
||||
heroId: this._id
|
||||
heroId: this._id,
|
||||
});
|
||||
},
|
||||
"tap .class": function(event){
|
||||
GlobalUI.setDetail({
|
||||
template: "classDialog",
|
||||
data: {classId: this._id, charId: this.charId},
|
||||
heroId: this._id
|
||||
heroId: this._id,
|
||||
});
|
||||
},
|
||||
"tap .race": function(event){
|
||||
GlobalUI.setDetail({
|
||||
template: "raceDialog",
|
||||
data: {charId: this._id},
|
||||
heroId: this._id + "race"
|
||||
heroId: this._id + "race",
|
||||
});
|
||||
},
|
||||
"tap #addNote": function(event){
|
||||
var charId = this._id;
|
||||
Notes.insert({
|
||||
name: "New Note",
|
||||
charId: charId
|
||||
name: "New Note",
|
||||
charId: charId,
|
||||
}, function(error, id){
|
||||
if(!error){
|
||||
if (!error){
|
||||
GlobalUI.setDetail({
|
||||
template: "noteDialog",
|
||||
data: {noteId: id, charId: charId, startEditing: true},
|
||||
heroId: id
|
||||
heroId: id,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -87,11 +101,11 @@ Template.journal.events({
|
||||
Experiences.insert({
|
||||
charId: charId
|
||||
}, function(error, id){
|
||||
if(!error){
|
||||
if (!error){
|
||||
GlobalUI.setDetail({
|
||||
template: "experienceDialog",
|
||||
data: {experienceId: id, charId: charId, startEditing: true},
|
||||
heroId: id
|
||||
heroId: id,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -101,30 +115,39 @@ Template.journal.events({
|
||||
Classes.insert({
|
||||
charId: charId,
|
||||
name: "new Class",
|
||||
level: 1
|
||||
level: 1,
|
||||
}, function(error, id){
|
||||
if(!error){
|
||||
if (!error){
|
||||
GlobalUI.setDetail({
|
||||
template: "classDialog",
|
||||
data: {classId: id, charId: charId, startEditing: true},
|
||||
heroId: id
|
||||
heroId: id,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
"tap #moreExperiences": function(event){
|
||||
var inst = Template.instance();
|
||||
inst.experiencesLimit.set(inst.experiencesLimit.get() + (this.settings && this.settings.experiencesInc || 10));
|
||||
inst.experiencesLimit.set(
|
||||
inst.experiencesLimit.get() +
|
||||
(this.settings && this.settings.experiencesInc || 10)
|
||||
);
|
||||
},
|
||||
"tap #lessExperiences": function(event){
|
||||
var inst = Template.instance();
|
||||
inst.experiencesLimit.set(this.settings && this.settings.experiencesInc || 10);
|
||||
inst.experiencesLimit.set(
|
||||
this.settings && this.settings.experiencesInc || 10
|
||||
);
|
||||
//scroll to the top of the div
|
||||
inst.$(".scroll-y").animate({
|
||||
scrollTop: inst.$(".scroll-y").scrollTop() + inst.$(".experiencesCard").position().top - 8
|
||||
scrollTop: (
|
||||
inst.$(".scroll-y").scrollTop() +
|
||||
inst.$(".experiencesCard").position().top -
|
||||
8
|
||||
)
|
||||
}, 300);
|
||||
//HACK giggle the columns :( to workaround chrome bug that stops .containers height from updating
|
||||
var cs = inst.$(".containers").removeClass("containers");
|
||||
_.defer(function(){cs.addClass("containers");});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -18,11 +18,11 @@ Template.noteDialog.events({
|
||||
"change #noteDescriptionInput": function(event){
|
||||
var value = event.currentTarget.value;
|
||||
Notes.update(this._id, {$set: {description: value}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.noteDialog.helpers({
|
||||
note: function(){
|
||||
return Notes.findOne(this.noteId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,4 +14,4 @@ Template.raceDialog.helpers({
|
||||
var char = Characters.findOne(this.charId, {fields: {race: 1}});
|
||||
return char && char.race;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,9 +4,9 @@ Template.newCharacterDialog.events({
|
||||
name: instance.find("#nameInput").value,
|
||||
gender: instance.find("#genderInput").value,
|
||||
race: instance.find("#raceInput").value,
|
||||
owner: Meteor.userId()
|
||||
owner: Meteor.userId(),
|
||||
}, function(err, id){
|
||||
if(err) throw err;
|
||||
if (err) throw err;
|
||||
Router.go("characterSheet", {_id: id});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,18 +5,18 @@ Template.personaDetailsDialog.onRendered(function(){
|
||||
Template.personaDetailsDialog.events({
|
||||
"change #nameInput": function(event){
|
||||
var input = event.currentTarget.value;
|
||||
Characters.update( this.charId, {$set: {name: input}} );
|
||||
Characters.update(this.charId, {$set: {name: input}});
|
||||
},
|
||||
"change #alignmentInput": function(event){
|
||||
var input = event.currentTarget.value;
|
||||
Characters.update( this.charId, {$set: {alignment: input}} );
|
||||
Characters.update(this.charId, {$set: {alignment: input}});
|
||||
},
|
||||
"change #genderInput": function(event){
|
||||
var input = event.currentTarget.value;
|
||||
Characters.update( this.charId, {$set: {gender: input}} );
|
||||
Characters.update(this.charId, {$set: {gender: input}});
|
||||
},
|
||||
"change #raceInput": function(event){
|
||||
var input = event.currentTarget.value;
|
||||
Characters.update( this.charId, {$set: {race: input}} );
|
||||
}
|
||||
Characters.update(this.charId, {$set: {race: input}});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,12 +4,15 @@ var colorMap = {
|
||||
ideals: "g",
|
||||
bonds: "h",
|
||||
flaws: "i",
|
||||
backstory: "j"
|
||||
backstory: "j",
|
||||
};
|
||||
|
||||
Template.persona.helpers({
|
||||
characterDetails: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {name: 1, gender: 1, alignment: 1, race:1}});
|
||||
var char = Characters.findOne(
|
||||
this._id,
|
||||
{fields: {name: 1, gender: 1, alignment: 1, race:1}}
|
||||
);
|
||||
char.field = "details";
|
||||
char.title = char.name;
|
||||
char.color = "d";
|
||||
@@ -26,7 +29,7 @@ Template.persona.helpers({
|
||||
field: field,
|
||||
color: color,
|
||||
body: char[field],
|
||||
topClass: "characterField"
|
||||
topClass: "characterField",
|
||||
};
|
||||
},
|
||||
languages: function(){
|
||||
@@ -36,20 +39,25 @@ Template.persona.helpers({
|
||||
|
||||
Template.persona.events({
|
||||
"tap .characterField": function(event){
|
||||
if(this.field !== "details"){
|
||||
if (this.field !== "details"){
|
||||
var charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "textDialog",
|
||||
data: {charId: charId, field: this.field, title: this.title, color: this.color},
|
||||
heroId: this._id + this.field
|
||||
data: {
|
||||
charId: charId,
|
||||
field: this.field,
|
||||
title: this.title,
|
||||
color: this.color,
|
||||
},
|
||||
heroId: this._id + this.field,
|
||||
});
|
||||
} else{
|
||||
} else {
|
||||
this.charId = Template.parentData()._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "personaDetailsDialog",
|
||||
data: this,
|
||||
heroId: this._id + "details"
|
||||
heroId: this._id + "details",
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,4 +18,4 @@ Template.textDialog.events({
|
||||
setter.$set[this.field] = input;
|
||||
Characters.update(this.charId, setter);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ var profTypes = [
|
||||
{type: "weapon", name: "Weapon"},
|
||||
{type: "armor", name: "Armor"},
|
||||
{type: "tool", name: "Tool"},
|
||||
{type: "language", name: "Language"}
|
||||
{type: "language", name: "Language"},
|
||||
];
|
||||
|
||||
var saves = [
|
||||
@@ -43,11 +43,11 @@ Template.proficiencyEdit.helpers({
|
||||
return profTypes;
|
||||
},
|
||||
nameInputTemplate: function(){
|
||||
if(!this.type) return null;
|
||||
if(this.type === "skill"||
|
||||
if (!this.type) return null;
|
||||
if (this.type === "skill" ||
|
||||
this.type === "save") return "nameDropdown";
|
||||
return "nameInput";
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.proficiencyEdit.events({
|
||||
@@ -57,21 +57,21 @@ Template.proficiencyEdit.events({
|
||||
},
|
||||
"core-select .typeDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var type = detail.item.getAttribute("name");
|
||||
if (type == this.type) return;
|
||||
Proficiencies.update(this._id, {$set: {type: type}});
|
||||
},
|
||||
"core-select .valueDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = +detail.item.getAttribute("name");
|
||||
if (value == this.value) return;
|
||||
Proficiencies.update(this._id, {$set: {value: value}});
|
||||
},
|
||||
"core-select .nameDropDown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var name = detail.item.getAttribute("name");
|
||||
if (name == this.name) return;
|
||||
Proficiencies.update(this._id, {$set: {name: name}});
|
||||
@@ -79,7 +79,7 @@ Template.proficiencyEdit.events({
|
||||
"change .nameInput": function(event){
|
||||
var name = event.currentTarget.value;
|
||||
Proficiencies.update(this._id, {$set: {name: name}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.nameDropdown.helpers({
|
||||
@@ -87,4 +87,4 @@ Template.nameDropdown.helpers({
|
||||
if (this.type === "skill") return skills;
|
||||
if (this.type === "save") return saves;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,9 +2,9 @@ Template.proficiencyEditList.helpers({
|
||||
proficiencies: function(){
|
||||
var selector = {
|
||||
"parent.id": this.parentId,
|
||||
"charId": this.charId
|
||||
"charId": this.charId,
|
||||
};
|
||||
if(this.parentGroup){
|
||||
if (this.parentGroup){
|
||||
selector["parent.group"] = this.parentGroup;
|
||||
}
|
||||
return Proficiencies.find(selector);
|
||||
@@ -13,14 +13,14 @@ Template.proficiencyEditList.helpers({
|
||||
|
||||
Template.proficiencyEditList.events({
|
||||
"tap #addProficiencyButton": function(){
|
||||
if ( !_.isBoolean(this.enabled) ) {
|
||||
if (!_.isBoolean(this.enabled)) {
|
||||
this.enabled = true;
|
||||
}
|
||||
Proficiencies.insert({
|
||||
charId: this.charId,
|
||||
parent: {
|
||||
id: this.parentId,
|
||||
collection: this.parentCollection
|
||||
collection: this.parentCollection,
|
||||
},
|
||||
enabled: this.enabled,
|
||||
value: 1,
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
Template.proficiencyListItem.helpers({
|
||||
profIcon: function(){
|
||||
var prof = this.value;
|
||||
if(prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if(prof === 1) return "image:brightness-1";
|
||||
if(prof > 1) return "av:album";
|
||||
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if (prof === 1) return "image:brightness-1";
|
||||
if (prof > 1) return "av:album";
|
||||
return "radio-button-off";
|
||||
},
|
||||
getName: function(){
|
||||
if(this.type === "skill") return skills[this.name];
|
||||
if(this.type === "save") return saves[this.name];
|
||||
if (this.type === "skill") return skills[this.name];
|
||||
if (this.type === "save") return saves[this.name];
|
||||
return this.name;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.proficiencyListItem.events({
|
||||
|
||||
@@ -32,14 +32,14 @@ var skills = {
|
||||
Template.proficiencyView.helpers({
|
||||
profIcon: function(){
|
||||
var prof = this.value;
|
||||
if(prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if(prof === 1) return "image:brightness-1";
|
||||
if(prof > 1) return "av:album";
|
||||
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if (prof === 1) return "image:brightness-1";
|
||||
if (prof > 1) return "av:album";
|
||||
return "radio-button-off";
|
||||
},
|
||||
getName: function(){
|
||||
if(this.type === "skill") return skills[this.name];
|
||||
if(this.type === "save") return saves[this.name];
|
||||
if (this.type === "skill") return skills[this.name];
|
||||
if (this.type === "save") return saves[this.name];
|
||||
return this.name;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,9 +2,9 @@ Template.proficiencyViewList.helpers({
|
||||
proficiencies: function(){
|
||||
var selector = {
|
||||
"parent.id": this.parentId,
|
||||
"charId": this.charId
|
||||
"charId": this.charId,
|
||||
};
|
||||
if(this.parentGroup){
|
||||
if (this.parentGroup){
|
||||
selector["parent.group"] = this.parentGroup;
|
||||
}
|
||||
return Proficiencies.find(selector);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
var spellLevels = [
|
||||
{ name: "Cantrip", level: 0 },
|
||||
{ name: "Level 1", level: 1 },
|
||||
{ name: "Level 2", level: 2 },
|
||||
{ name: "Level 3", level: 3 },
|
||||
{ name: "Level 4", level: 4 },
|
||||
{ name: "Level 5", level: 5 },
|
||||
{ name: "Level 6", level: 6 },
|
||||
{ name: "Level 7", level: 7 },
|
||||
{ name: "Level 8", level: 8 },
|
||||
{ name: "Level 9", level: 9 },
|
||||
{name: "Cantrip", level: 0},
|
||||
{name: "Level 1", level: 1},
|
||||
{name: "Level 2", level: 2},
|
||||
{name: "Level 3", level: 3},
|
||||
{name: "Level 4", level: 4},
|
||||
{name: "Level 5", level: 5},
|
||||
{name: "Level 6", level: 6},
|
||||
{name: "Level 7", level: 7},
|
||||
{name: "Level 8", level: 8},
|
||||
{name: "Level 9", level: 9},
|
||||
];
|
||||
|
||||
Template.spellDialog.helpers({
|
||||
@@ -31,19 +31,19 @@ Template.spellDialog.events({
|
||||
Template.spellDetails.helpers({
|
||||
getComponents: function(){
|
||||
var components = "";
|
||||
if(this.components.concentration) components += "C";
|
||||
if(this.components.verbal) components += components.length? ", V" : "V";
|
||||
if(this.components.somatic) components += components.length? ", S" : "S";
|
||||
if(this.components.material) {
|
||||
components += components.length? ", M" : "M";
|
||||
if (this.components.concentration) components += "C";
|
||||
if (this.components.verbal) components += components.length ? ", V" : "V";
|
||||
if (this.components.somatic) components += components.length ? ", S" : "S";
|
||||
if (this.components.material) {
|
||||
components += components.length ? ", M" : "M";
|
||||
components += " (" + this.components.material + ")";
|
||||
}
|
||||
return components;
|
||||
},
|
||||
preparedString: function(){
|
||||
if(this.prepared === "prepared") return "prepared";
|
||||
if(this.prepared === "unprepared") return "unprepared";
|
||||
if(this.prepared === "always") return "always prepared";
|
||||
if (this.prepared === "prepared") return "prepared";
|
||||
if (this.prepared === "unprepared") return "unprepared";
|
||||
if (this.prepared === "always") return "always prepared";
|
||||
},
|
||||
});
|
||||
|
||||
@@ -65,9 +65,9 @@ Template.spellEdit.helpers({
|
||||
return [
|
||||
{name: "Prepared", value: "prepared"},
|
||||
{name: "Unprepared", value: "unprepared"},
|
||||
{name: "Always Prepared", value: "always"}
|
||||
{name: "Always Prepared", value: "always"},
|
||||
];
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.spellEdit.events({
|
||||
@@ -97,30 +97,30 @@ Template.spellEdit.events({
|
||||
},
|
||||
"core-select #listDropdown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
if (value == this.parent.id) return;
|
||||
Spells.update(this._id, {$set: {"parent.id": value}});
|
||||
},
|
||||
"core-select #levelDropdown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
if(value == this.level) return;
|
||||
if (value == this.level) return;
|
||||
Spells.update(this._id, {$set: {level: value}});
|
||||
},
|
||||
"core-select #schoolDropdown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
if(value == this.school) return;
|
||||
if (value == this.school) return;
|
||||
Spells.update(this._id, {$set: {school: value}});
|
||||
},
|
||||
"core-select #preparedDropdown": function(event){
|
||||
var detail = event.originalEvent.detail;
|
||||
if(!detail.isSelected) return;
|
||||
if (!detail.isSelected) return;
|
||||
var value = detail.item.getAttribute("name");
|
||||
if(value == this.school) return;
|
||||
if (value == this.school) return;
|
||||
Spells.update(this._id, {$set: {prepared: value}});
|
||||
},
|
||||
"change #verbalCheckbox": function(event){
|
||||
|
||||
@@ -8,7 +8,11 @@ Template.spellListDialog.events({
|
||||
},
|
||||
"tap #deleteButton": function(event, instance){
|
||||
SpellLists.softRemoveNode(instance.data.spellListId);
|
||||
GlobalUI.deletedToast(instance.data.spellListId, "SpellLists", "Spell list and contents");
|
||||
GlobalUI.deletedToast(
|
||||
instance.data.spellListId,
|
||||
"SpellLists",
|
||||
"Spell list and contents"
|
||||
);
|
||||
GlobalUI.closeDetail();
|
||||
},
|
||||
//TODO clean up String -> num here so they don't need casting by Schema.clean
|
||||
@@ -21,11 +25,13 @@ Template.spellListDialog.events({
|
||||
var value = event.currentTarget.value;
|
||||
SpellLists.update(this._id, {$set: {saveDC: value}});
|
||||
},
|
||||
"change #spellListAttackBonusInput, input #spellListAttackBonusInput": function(event){
|
||||
"change #spellListAttackBonusInput, input #spellListAttackBonusInput":
|
||||
function(event){
|
||||
var value = event.currentTarget.value;
|
||||
SpellLists.update(this._id, {$set: {attackBonus: value}});
|
||||
},
|
||||
"change #spellListMaxPreparedInput, input #spellListMaxPreparedInput": function(event){
|
||||
"change #spellListMaxPreparedInput, input #spellListMaxPreparedInput":
|
||||
function(event){
|
||||
var value = event.currentTarget.value;
|
||||
SpellLists.update(this._id, {$set: {maxPrepared: value}});
|
||||
},
|
||||
@@ -39,4 +45,4 @@ Template.spellListDialog.helpers({
|
||||
spellList: function(){
|
||||
return SpellLists.findOne(this.spellListId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
var spellLevels = [
|
||||
{ name: "Cantrips", level: 0 },
|
||||
{ name: "Level 1", level: 1 },
|
||||
{ name: "Level 2", level: 2 },
|
||||
{ name: "Level 3", level: 3 },
|
||||
{ name: "Level 4", level: 4 },
|
||||
{ name: "Level 5", level: 5 },
|
||||
{ name: "Level 6", level: 6 },
|
||||
{ name: "Level 7", level: 7 },
|
||||
{ name: "Level 8", level: 8 },
|
||||
{ name: "Level 9", level: 9 },
|
||||
{name: "Cantrips", level: 0},
|
||||
{name: "Level 1", level: 1},
|
||||
{name: "Level 2", level: 2},
|
||||
{name: "Level 3", level: 3},
|
||||
{name: "Level 4", level: 4},
|
||||
{name: "Level 5", level: 5},
|
||||
{name: "Level 6", level: 6},
|
||||
{name: "Level 7", level: 7},
|
||||
{name: "Level 8", level: 8},
|
||||
{name: "Level 9", level: 9},
|
||||
];
|
||||
|
||||
Template.spells.helpers({
|
||||
@@ -16,40 +16,56 @@ Template.spells.helpers({
|
||||
return SpellLists.find({charId: this._id}, {sort: {color: 1, name: 1}});
|
||||
},
|
||||
spellCount: function(list, charId){
|
||||
if(!list || !list.settings) return;
|
||||
if(list.settings.showUnprepared){
|
||||
return Spells.find( {charId: charId, "parent.id": list._id, level: this.level},
|
||||
{fields: {_id: 1, level: 1}} ).count() > 0;
|
||||
} else{
|
||||
return Spells.find( {charId: charId, "parent.id": list._id, level: this.level, prepared: {$in: ["prepared", "always"]} },
|
||||
{fields: {_id: 1, level: 1}} ).count() > 0;
|
||||
if (!list || !list.settings) return;
|
||||
if (list.settings.showUnprepared){
|
||||
return Spells.find(
|
||||
{charId: charId, "parent.id": list._id, level: this.level},
|
||||
{fields: {_id: 1, level: 1}}
|
||||
).count() > 0;
|
||||
} else {
|
||||
return Spells.find(
|
||||
{
|
||||
charId: charId,
|
||||
"parent.id": list._id,
|
||||
level: this.level,
|
||||
prepared: {$in: ["prepared", "always"]},
|
||||
},
|
||||
{fields: {_id: 1, level: 1}}
|
||||
).count() > 0;
|
||||
}
|
||||
},
|
||||
spells: function(listId, charId){
|
||||
return Spells.find( {charId: charId, "parent.id": listId, level: this.level}, {sort: {color: 1, name: 1}} );
|
||||
return Spells.find(
|
||||
{charId: charId, "parent.id": listId, level: this.level},
|
||||
{sort: {color: 1, name: 1}}
|
||||
);
|
||||
},
|
||||
levels: function(){
|
||||
return spellLevels;
|
||||
},
|
||||
numPrepared: function(){
|
||||
return Spells.find({charId: Template.parentData()._id, "parent.id": this._id, prepared: "prepared"}).count();
|
||||
return Spells.find({
|
||||
charId: Template.parentData()._id,
|
||||
"parent.id": this._id,
|
||||
prepared: "prepared",
|
||||
}).count();
|
||||
},
|
||||
order: function(){
|
||||
return _.indexOf(_.keys(colorOptions), this.color);
|
||||
},
|
||||
spellComponents: function(){
|
||||
var components = "";
|
||||
if(this.components.verbal){
|
||||
components += "V"
|
||||
if (this.components.verbal){
|
||||
components += "V";
|
||||
}
|
||||
if(this.components.somatic){
|
||||
components += components? ", S" : "S";
|
||||
if (this.components.somatic){
|
||||
components += components ? ", S" : "S";
|
||||
}
|
||||
if(this.components.material){
|
||||
components += components? ", M" : "M";
|
||||
if (this.components.material){
|
||||
components += components ? ", M" : "M";
|
||||
}
|
||||
if(this.components.concentration){
|
||||
components += components? ", C" : "C";
|
||||
if (this.components.concentration){
|
||||
components += components ? ", C" : "C";
|
||||
}
|
||||
return components;
|
||||
},
|
||||
@@ -57,7 +73,7 @@ Template.spells.helpers({
|
||||
return this.prepared === "prepared" || this.prepared === "always";
|
||||
},
|
||||
showSpell: function(listShowPrepped){
|
||||
if(listShowPrepped) {
|
||||
if (listShowPrepped) {
|
||||
return true;
|
||||
} else {
|
||||
return this.prepared === "prepared" || this.prepared === "always";
|
||||
@@ -67,71 +83,76 @@ Template.spells.helpers({
|
||||
return this.prepared === "always";
|
||||
},
|
||||
cantCast: function(level, char){
|
||||
for(var i = level; i <= 9; i++){
|
||||
if (char.attributeValue("level"+i+"SpellSlots") > 0){
|
||||
for (var i = level; i <= 9; i++){
|
||||
if (char.attributeValue("level" + i + "SpellSlots") > 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
baseSlots: function(char){
|
||||
return char.attributeBase("level" + this.level +"SpellSlots");
|
||||
return char.attributeBase("level" + this.level + "SpellSlots");
|
||||
},
|
||||
slots: function(char){
|
||||
return char.attributeValue("level" + this.level +"SpellSlots");
|
||||
return char.attributeValue("level" + this.level + "SpellSlots");
|
||||
},
|
||||
showSlots: function(char){
|
||||
return this.level && char.attributeBase("level" + this.level +"SpellSlots");
|
||||
return this.level && char.attributeBase("level" + this.level + "SpellSlots");
|
||||
},
|
||||
hasSlots: function(){
|
||||
for(var i = 1; i <= 9; i += 1){
|
||||
if(this.attributeBase("level"+i+"SpellSlots")){
|
||||
for (var i = 1; i <= 9; i += 1){
|
||||
if (this.attributeBase("level" + i + "SpellSlots")){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
slotBubbles: function(char){
|
||||
var baseSlots = char.attributeBase("level" + this.level +"SpellSlots"),
|
||||
currentSlots = char.attributeValue("level" + this.level +"SpellSlots"),
|
||||
slotsUsed = baseSlots - currentSlots,
|
||||
bubbles = [], i;
|
||||
for(i = 0; i < currentSlots; i++){
|
||||
var baseSlots = char.attributeBase("level" + this.level + "SpellSlots");
|
||||
var currentSlots = char.attributeValue("level" + this.level + "SpellSlots");
|
||||
var slotsUsed = baseSlots - currentSlots;
|
||||
var bubbles = [];
|
||||
var i;
|
||||
for (i = 0; i < currentSlots; i++){
|
||||
bubbles.push({
|
||||
icon: "radio-button-on",
|
||||
disabled: i !== currentSlots -1, //last full slot not disabled
|
||||
attribute: "level" + this.level +"SpellSlots",
|
||||
charId: char._id
|
||||
icon: "radio-button-on",
|
||||
disabled: i !== currentSlots - 1, //last full slot not disabled
|
||||
attribute: "level" + this.level + "SpellSlots",
|
||||
charId: char._id,
|
||||
});
|
||||
}
|
||||
for(i = 0; i < slotsUsed; i++){
|
||||
for (i = 0; i < slotsUsed; i++){
|
||||
bubbles.push({
|
||||
icon: "radio-button-off",
|
||||
icon: "radio-button-off",
|
||||
disabled: i !== 0, //first empty slot not disabled
|
||||
attribute: "level" + this.level +"SpellSlots",
|
||||
charId: char._id
|
||||
attribute: "level" + this.level + "SpellSlots",
|
||||
charId: char._id,
|
||||
});
|
||||
}
|
||||
return bubbles;
|
||||
},
|
||||
slotStatName: function () {
|
||||
return "level" + this.level +"SpellSlots";
|
||||
}
|
||||
},
|
||||
slotStatName: function() {
|
||||
return "level" + this.level + "SpellSlots";
|
||||
},
|
||||
});
|
||||
|
||||
Template.spells.events({
|
||||
"tap .slotBubble": function(event){
|
||||
if(!event.currentTarget.disabled){
|
||||
var modifier;
|
||||
if (!event.currentTarget.disabled){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if(event.currentTarget.icon === "radio-button-off"){
|
||||
if(char.attributeValue(this.attribute) < char.attributeBase(this.attribute)){
|
||||
var modifier = {$inc: {}};
|
||||
if (event.currentTarget.icon === "radio-button-off"){
|
||||
if (
|
||||
char.attributeValue(this.attribute) <
|
||||
char.attributeBase(this.attribute)
|
||||
){
|
||||
modifier = {$inc: {}};
|
||||
modifier.$inc[this.attribute + ".adjustment"] = 1;
|
||||
Characters.update(this.charId, modifier, {validate: false});
|
||||
}
|
||||
} else {
|
||||
if(char.attributeValue(this.attribute) > 0){
|
||||
var modifier = {$inc: {}};
|
||||
if (char.attributeValue(this.attribute) > 0){
|
||||
modifier = {$inc: {}};
|
||||
modifier.$inc[this.attribute + ".adjustment"] = -1;
|
||||
Characters.update(this.charId, modifier, {validate: false});
|
||||
}
|
||||
@@ -139,43 +160,43 @@ Template.spells.events({
|
||||
}
|
||||
event.stopPropagation();
|
||||
},
|
||||
"tap .spellSlot": function (event, instance) {
|
||||
var name = "Level " + this.level +" Spell Slots";
|
||||
var stat = "level" + this.level +"SpellSlots";
|
||||
"tap .spellSlot": function(event, instance) {
|
||||
var name = "Level " + this.level + " Spell Slots";
|
||||
var stat = "level" + this.level + "SpellSlots";
|
||||
var charId = instance.data._id;
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: name, statName: stat, charId: charId},
|
||||
heroId: charId + stat
|
||||
heroId: charId + stat,
|
||||
});
|
||||
},
|
||||
"tap .containerTop": function(event){
|
||||
GlobalUI.setDetail({
|
||||
template: "spellListDialog",
|
||||
data: {spellListId: this._id, charId: this.charId},
|
||||
heroId: this._id
|
||||
heroId: this._id,
|
||||
});
|
||||
},
|
||||
"tap .spell": function(event){
|
||||
GlobalUI.setDetail({
|
||||
template: "spellDialog",
|
||||
data: {spellId: this._id, charId: this.charId},
|
||||
heroId: this._id
|
||||
heroId: this._id,
|
||||
});
|
||||
},
|
||||
"tap #addSpellList": function(event){
|
||||
var charId = this.charId;
|
||||
SpellLists.insert({
|
||||
name: "New SpellList",
|
||||
name: "New SpellList",
|
||||
charId: this._id,
|
||||
saveDC: "8 + intelligenceMod + proficiencyBonus",
|
||||
attackBonus: "intelligenceMod + proficiencyBonus"
|
||||
attackBonus: "intelligenceMod + proficiencyBonus",
|
||||
}, function(error, id){
|
||||
if(!error){
|
||||
if (!error){
|
||||
GlobalUI.setDetail({
|
||||
template: "spellListDialog",
|
||||
data: {spellListId: id, charId: charId, startEditing: true},
|
||||
heroId: id
|
||||
heroId: id,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -184,19 +205,19 @@ Template.spells.events({
|
||||
var charId = this.charId;
|
||||
var listId = SpellLists.findOne({charId: this._id})._id;
|
||||
Spells.insert({
|
||||
name: "New Spell",
|
||||
name: "New Spell",
|
||||
charId: this._id,
|
||||
parent: {
|
||||
id: listId,
|
||||
collection: "SpellLists"
|
||||
collection: "SpellLists",
|
||||
},
|
||||
prepared: "prepared"
|
||||
prepared: "prepared",
|
||||
}, function(error, id){
|
||||
if(!error){
|
||||
if (!error){
|
||||
GlobalUI.setDetail({
|
||||
template: "spellDialog",
|
||||
data: {spellId: id, charId: charId, startEditing: true},
|
||||
heroId: id
|
||||
heroId: id,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -206,9 +227,9 @@ Template.spells.events({
|
||||
},
|
||||
"change .preparedCheckbox": function(event){
|
||||
var value = event.currentTarget.checked;
|
||||
if(this.prepared === "unprepared" && value)
|
||||
if (this.prepared === "unprepared" && value)
|
||||
Spells.update(this._id, {$set: {prepared: "prepared"}});
|
||||
else if(this.prepared === "prepared" && !value)
|
||||
else if (this.prepared === "prepared" && !value)
|
||||
Spells.update(this._id, {$set: {prepared: "unprepared"}});
|
||||
},
|
||||
"tap .prepSpells": function(event){
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
Template.addTHPDialog.events({
|
||||
'tap #addButton': function(event, instance){
|
||||
"tap #addButton": function(event, instance){
|
||||
TemporaryHitPoints.insert({
|
||||
charId: this.charId,
|
||||
name: instance.find('#nameInput').value,
|
||||
maximum: +instance.find('#quantityInput').value,
|
||||
deleteOnZero: !!instance.find('#deleteWhenZeroCheckbox').checked
|
||||
name: instance.find("#nameInput").value,
|
||||
maximum: +instance.find("#quantityInput").value,
|
||||
deleteOnZero: !!instance.find("#deleteWhenZeroCheckbox").checked,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -6,31 +6,31 @@ var stats = {
|
||||
"intelligence":{"name":"Intelligence"},
|
||||
"wisdom":{"name":"Wisdom"},
|
||||
"charisma":{"name":"Charisma"},
|
||||
"strengthSave":{"name":"Strength Save",},
|
||||
"dexteritySave":{"name":"Dexterity Save",},
|
||||
"constitutionSave":{"name":"Constitution Save",},
|
||||
"intelligenceSave":{"name":"Intelligence Save",},
|
||||
"wisdomSave":{"name":"Wisdom Save",},
|
||||
"charismaSave":{"name":"Charisma Save",},
|
||||
"acrobatics":{"name":"Acrobatics",},
|
||||
"animalHandling":{"name":"Animal Handling",},
|
||||
"arcana":{"name":"Arcana",},
|
||||
"athletics":{"name":"Athletics",},
|
||||
"deception":{"name":"Deception",},
|
||||
"history":{"name":"History",},
|
||||
"insight":{"name":"Insight",},
|
||||
"intimidation":{"name":"Intimidation",},
|
||||
"investigation":{"name":"Investigation",},
|
||||
"medicine":{"name":"Medicine",},
|
||||
"nature":{"name":"Nature",},
|
||||
"perception":{"name":"Perception",},
|
||||
"performance":{"name":"Performance",},
|
||||
"persuasion":{"name":"Persuasion",},
|
||||
"religion":{"name":"Religion",},
|
||||
"sleightOfHand":{"name":"Sleight of Hand",},
|
||||
"stealth":{"name":"Stealth",},
|
||||
"survival":{"name":"Survival",},
|
||||
"initiative":{"name":"Initiative",},
|
||||
"strengthSave":{"name":"Strength Save"},
|
||||
"dexteritySave":{"name":"Dexterity Save"},
|
||||
"constitutionSave":{"name":"Constitution Save"},
|
||||
"intelligenceSave":{"name":"Intelligence Save"},
|
||||
"wisdomSave":{"name":"Wisdom Save"},
|
||||
"charismaSave":{"name":"Charisma Save"},
|
||||
"acrobatics":{"name":"Acrobatics"},
|
||||
"animalHandling":{"name":"Animal Handling"},
|
||||
"arcana":{"name":"Arcana"},
|
||||
"athletics":{"name":"Athletics"},
|
||||
"deception":{"name":"Deception"},
|
||||
"history":{"name":"History"},
|
||||
"insight":{"name":"Insight"},
|
||||
"intimidation":{"name":"Intimidation"},
|
||||
"investigation":{"name":"Investigation"},
|
||||
"medicine":{"name":"Medicine"},
|
||||
"nature":{"name":"Nature"},
|
||||
"perception":{"name":"Perception"},
|
||||
"performance":{"name":"Performance"},
|
||||
"persuasion":{"name":"Persuasion"},
|
||||
"religion":{"name":"Religion"},
|
||||
"sleightOfHand":{"name":"Sleight of Hand"},
|
||||
"stealth":{"name":"Stealth"},
|
||||
"survival":{"name":"Survival"},
|
||||
"initiative":{"name":"Initiative"},
|
||||
"hitPoints":{"name":"Hit Points"},
|
||||
"armor":{"name":"Armor"},
|
||||
"dexterityArmor":{"name":"Dexterity Armor Bonus"},
|
||||
@@ -67,7 +67,7 @@ var stats = {
|
||||
"psychicMultiplier":{"name":"Psychic", "group": "Weakness/Resistance"},
|
||||
"radiantMultiplier":{"name":"Radiant", "group": "Weakness/Resistance"},
|
||||
"slashingMultiplier":{"name":"Slashing", "group": "Weakness/Resistance"},
|
||||
"thunderMultiplier":{"name":"Thunder", "group": "Weakness/Resistance"}
|
||||
"thunderMultiplier":{"name":"Thunder", "group": "Weakness/Resistance"},
|
||||
};
|
||||
|
||||
var operations = {
|
||||
@@ -81,7 +81,7 @@ var operations = {
|
||||
disadvantage: {name: "Disadvantage"},
|
||||
passiveAdd: {name: "Passive Bonus"},
|
||||
fail: {name: "Automatically Fail"},
|
||||
conditional: {name: "Conditional Benefit"}
|
||||
conditional: {name: "Conditional Benefit"},
|
||||
};
|
||||
|
||||
var abilities = {
|
||||
@@ -99,34 +99,44 @@ Template.attributeDialogView.helpers({
|
||||
},
|
||||
adjustment: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if(!char) return;
|
||||
if (!char) return;
|
||||
var value = char.attributeValue(this.statName);
|
||||
var base = char.attributeBase(this.statName);
|
||||
return value - base;
|
||||
},
|
||||
baseEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.statName, operation: "base"});
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "base"}
|
||||
);
|
||||
},
|
||||
addEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.statName, operation: "add"});
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "add"}
|
||||
);
|
||||
},
|
||||
mulEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.statName, operation: "mul"});
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "mul"}
|
||||
);
|
||||
},
|
||||
minEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.statName, operation: "min"});
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "min"}
|
||||
);
|
||||
},
|
||||
maxEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.statName, operation: "max"});
|
||||
return Effects.find(
|
||||
{charId: this.charId, stat: this.statName, operation: "max"}
|
||||
);
|
||||
},
|
||||
attributeBase: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if(!char) throw "character is " + char;
|
||||
if (!char) throw "character is " + char;
|
||||
return char.attributeBase(this.statName);
|
||||
},
|
||||
attributeValue: function () {
|
||||
attributeValue: function() {
|
||||
var char = Characters.findOne(this.charId);
|
||||
if(!char) throw "character is " + char;
|
||||
if (!char) throw "character is " + char;
|
||||
return char.attributeValue(this.statName);
|
||||
},
|
||||
sourceName: function(){
|
||||
@@ -135,10 +145,9 @@ Template.attributeDialogView.helpers({
|
||||
},
|
||||
operationName: function(){
|
||||
var op = operations[this.operation];
|
||||
return op && op.name || "No Operation";
|
||||
return op && op.name || "No Operation";
|
||||
},
|
||||
statValue: function(){
|
||||
return evaluateEffect(this.charId, this);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -10,11 +10,11 @@ Template.healthCard.helpers({
|
||||
return char && char.deathSave;
|
||||
},
|
||||
failIcon: function(num){
|
||||
if(num <= this.fail) return "radio-button-on";
|
||||
if (num <= this.fail) return "radio-button-on";
|
||||
else return "radio-button-off";
|
||||
},
|
||||
passIcon: function(num){
|
||||
if(num <= this.pass) return "radio-button-on";
|
||||
if (num <= this.pass) return "radio-button-on";
|
||||
else return "radio-button-off";
|
||||
},
|
||||
failDisabled: function(num){
|
||||
@@ -27,7 +27,7 @@ Template.healthCard.helpers({
|
||||
return this.fail >= 3;
|
||||
},
|
||||
multipliers: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {_id: 1} });
|
||||
var char = Characters.findOne(this._id, {fields: {_id: 1}});
|
||||
var multipliers = [
|
||||
{name: "Acid", value: char.attributeValue("acidMultiplier", 1)},
|
||||
{name: "Bludgeoning", value: char.attributeValue("bludgeoningMultiplier", 1)},
|
||||
@@ -41,15 +41,15 @@ Template.healthCard.helpers({
|
||||
{name: "Psychic", value: char.attributeValue("psychicMultiplier", 1)},
|
||||
{name: "Radiant", value: char.attributeValue("radiantMultiplier", 1)},
|
||||
{name: "Slashing", value: char.attributeValue("slashingMultiplier", 1)},
|
||||
{name: "Thunder", value: char.attributeValue("thunderMultiplier", 1)}
|
||||
{name: "Thunder", value: char.attributeValue("thunderMultiplier", 1)},
|
||||
];
|
||||
multipliers = _.groupBy(multipliers, "value");
|
||||
return {
|
||||
"immunities": multipliers["0"] || [],
|
||||
"resistances": multipliers["0.5"] || [],
|
||||
"weaknesses": multipliers["2"] || []
|
||||
"weaknesses": multipliers["2"] || [],
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.healthCard.events({
|
||||
@@ -58,12 +58,15 @@ Template.healthCard.events({
|
||||
var adjustment = value - this.attributeBase("hitPoints");
|
||||
Characters.update(this._id, {$set: {"hitPoints.adjustment": adjustment}});
|
||||
//reset the death saves if we are gaining HP
|
||||
if(value > 0)
|
||||
Characters.update(this._id, { $set: {
|
||||
"deathSave.pass": 0,
|
||||
"deathSave.fail": 0,
|
||||
"deathSave.stable": false
|
||||
} });
|
||||
if (value > 0)
|
||||
Characters.update(
|
||||
this._id,
|
||||
{$set: {
|
||||
"deathSave.pass": 0,
|
||||
"deathSave.fail": 0,
|
||||
"deathSave.stable": false,
|
||||
}}
|
||||
);
|
||||
},
|
||||
"change .tempHitPointSlider": function(event){
|
||||
var value = event.currentTarget.value;
|
||||
@@ -76,24 +79,24 @@ Template.healthCard.events({
|
||||
"tap #addTempHP": function(event){
|
||||
GlobalUI.showDialog({
|
||||
template: "addTHPDialog",
|
||||
data: {charId: this._id}
|
||||
data: {charId: this._id},
|
||||
});
|
||||
},
|
||||
"tap .failBubble": function(event){
|
||||
if(event.currentTarget.disabled) return;
|
||||
if (event.currentTarget.disabled) return;
|
||||
var char = Template.parentData();
|
||||
if(event.currentTarget.icon === "radio-button-off"){
|
||||
if (event.currentTarget.icon === "radio-button-off"){
|
||||
Characters.update(char._id, {$set: {"deathSave.fail": this.fail + 1}});
|
||||
} else{
|
||||
} else {
|
||||
Characters.update(char._id, {$set: {"deathSave.fail": this.fail - 1}});
|
||||
}
|
||||
},
|
||||
"tap .passBubble": function(event){
|
||||
if(event.currentTarget.disabled) return;
|
||||
if (event.currentTarget.disabled) return;
|
||||
var char = Template.parentData();
|
||||
if(event.currentTarget.icon === "radio-button-off"){
|
||||
if (event.currentTarget.icon === "radio-button-off"){
|
||||
Characters.update(char._id, {$set: {"deathSave.pass": this.pass + 1}});
|
||||
} else{
|
||||
} else {
|
||||
Characters.update(char._id, {$set: {"deathSave.pass": this.pass - 1}});
|
||||
}
|
||||
},
|
||||
@@ -104,5 +107,5 @@ Template.healthCard.events({
|
||||
"tap #unstableButton": function(event){
|
||||
var char = Template.parentData();
|
||||
Characters.update(char._id, {$set: {"deathSave.stable": true}});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
Template.hitDice.helpers({
|
||||
cantIncrement: function(){
|
||||
return !(this.char.attributeValue(this.name) < this.char.attributeBase(this.name));
|
||||
var valueSmallerThanBase = this.char.attributeValue(this.name) <
|
||||
this.char.attributeBase(this.name);
|
||||
return !valueSmallerThanBase;
|
||||
},
|
||||
cantDecrement: function(){
|
||||
return !(this.char.attributeValue(this.name) > 0);
|
||||
}
|
||||
var valuePositive = this.char.attributeValue(this.name) > 0;
|
||||
return !valuePositive;
|
||||
},
|
||||
});
|
||||
|
||||
Template.hitDice.events({
|
||||
"tap .resourceUp": function(event){
|
||||
if(this.char.attributeValue(this.name) < this.char.attributeBase(this.name)){
|
||||
if (this.char.attributeValue(this.name) < this.char.attributeBase(this.name)){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = 1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
},
|
||||
"tap .resourceDown": function(event){
|
||||
if(this.char.attributeValue(this.name) > 0){
|
||||
if (this.char.attributeValue(this.name) > 0){
|
||||
var modifier = {$inc: {}};
|
||||
modifier.$inc[this.name + ".adjustment"] = -1;
|
||||
Characters.update(this.char._id, modifier, {validate: false});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -6,31 +6,31 @@ var stats = {
|
||||
"intelligence":{"name":"Intelligence"},
|
||||
"wisdom":{"name":"Wisdom"},
|
||||
"charisma":{"name":"Charisma"},
|
||||
"strengthSave":{"name":"Strength Save",},
|
||||
"dexteritySave":{"name":"Dexterity Save",},
|
||||
"constitutionSave":{"name":"Constitution Save",},
|
||||
"intelligenceSave":{"name":"Intelligence Save",},
|
||||
"wisdomSave":{"name":"Wisdom Save",},
|
||||
"charismaSave":{"name":"Charisma Save",},
|
||||
"acrobatics":{"name":"Acrobatics",},
|
||||
"animalHandling":{"name":"Animal Handling",},
|
||||
"arcana":{"name":"Arcana",},
|
||||
"athletics":{"name":"Athletics",},
|
||||
"deception":{"name":"Deception",},
|
||||
"history":{"name":"History",},
|
||||
"insight":{"name":"Insight",},
|
||||
"intimidation":{"name":"Intimidation",},
|
||||
"investigation":{"name":"Investigation",},
|
||||
"medicine":{"name":"Medicine",},
|
||||
"nature":{"name":"Nature",},
|
||||
"perception":{"name":"Perception",},
|
||||
"performance":{"name":"Performance",},
|
||||
"persuasion":{"name":"Persuasion",},
|
||||
"religion":{"name":"Religion",},
|
||||
"sleightOfHand":{"name":"Sleight of Hand",},
|
||||
"stealth":{"name":"Stealth",},
|
||||
"survival":{"name":"Survival",},
|
||||
"initiative":{"name":"Initiative",},
|
||||
"strengthSave":{"name":"Strength Save"},
|
||||
"dexteritySave":{"name":"Dexterity Save"},
|
||||
"constitutionSave":{"name":"Constitution Save"},
|
||||
"intelligenceSave":{"name":"Intelligence Save"},
|
||||
"wisdomSave":{"name":"Wisdom Save"},
|
||||
"charismaSave":{"name":"Charisma Save"},
|
||||
"acrobatics":{"name":"Acrobatics"},
|
||||
"animalHandling":{"name":"Animal Handling"},
|
||||
"arcana":{"name":"Arcana"},
|
||||
"athletics":{"name":"Athletics"},
|
||||
"deception":{"name":"Deception"},
|
||||
"history":{"name":"History"},
|
||||
"insight":{"name":"Insight"},
|
||||
"intimidation":{"name":"Intimidation"},
|
||||
"investigation":{"name":"Investigation"},
|
||||
"medicine":{"name":"Medicine"},
|
||||
"nature":{"name":"Nature"},
|
||||
"perception":{"name":"Perception"},
|
||||
"performance":{"name":"Performance"},
|
||||
"persuasion":{"name":"Persuasion"},
|
||||
"religion":{"name":"Religion"},
|
||||
"sleightOfHand":{"name":"Sleight of Hand"},
|
||||
"stealth":{"name":"Stealth"},
|
||||
"survival":{"name":"Survival"},
|
||||
"initiative":{"name":"Initiative"},
|
||||
"hitPoints":{"name":"Hit Points"},
|
||||
"armor":{"name":"Armor"},
|
||||
"dexterityArmor":{"name":"Dexterity Armor Bonus"},
|
||||
@@ -67,11 +67,11 @@ var stats = {
|
||||
"psychicMultiplier":{"name":"Psychic", "group": "Weakness/Resistance"},
|
||||
"radiantMultiplier":{"name":"Radiant", "group": "Weakness/Resistance"},
|
||||
"slashingMultiplier":{"name":"Slashing", "group": "Weakness/Resistance"},
|
||||
"thunderMultiplier":{"name":"Thunder", "group": "Weakness/Resistance"}
|
||||
"thunderMultiplier":{"name":"Thunder", "group": "Weakness/Resistance"},
|
||||
};
|
||||
|
||||
var operations = {
|
||||
base: {name: "Base Value"},
|
||||
base: {name: "Base Value"},
|
||||
proficiency: {name: "Proficiency"},
|
||||
add: {name: "+"},
|
||||
mul: {name: "×"},
|
||||
@@ -81,7 +81,7 @@ var operations = {
|
||||
disadvantage: {name: "Disadvantage"},
|
||||
passiveAdd: {name: "Passive Bonus"},
|
||||
fail: {name: "Automatically Fail"},
|
||||
conditional: {name: "Conditional Benefit"}
|
||||
conditional: {name: "Conditional Benefit"},
|
||||
};
|
||||
|
||||
var abilities = {
|
||||
@@ -99,50 +99,82 @@ Template.skillDialogView.helpers({
|
||||
},
|
||||
profIcon: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if(!char) return;
|
||||
if (!char) return;
|
||||
var prof = char.proficiency(this.skillName);
|
||||
if(prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if(prof === 1) return "image:brightness-1";
|
||||
if(prof > 1) return "av:album";
|
||||
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if (prof === 1) return "image:brightness-1";
|
||||
if (prof > 1) return "av:album";
|
||||
return "radio-button-off";
|
||||
},
|
||||
profSource: function(){
|
||||
return Proficiencies.findOne({charId: this.charId, name: this.skillName}, {sort: {value: -1}});
|
||||
return Proficiencies.findOne(
|
||||
{charId: this.charId, name: this.skillName},
|
||||
{sort: {value: -1}}
|
||||
);
|
||||
},
|
||||
profBonus: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if(!char) return;
|
||||
return char.proficiency(this.skillName) * char.attributeValue("proficiencyBonus");
|
||||
if (!char) return;
|
||||
return char.proficiency(this.skillName) *
|
||||
char.attributeValue("proficiencyBonus");
|
||||
},
|
||||
proficiencyValue: function(){
|
||||
var char = Characters.findOne(this.charId);
|
||||
if(!char) return;
|
||||
if (!char) return;
|
||||
var prof = char.proficiency(this.skillName);
|
||||
if(prof == 0.5) return "Half Proficiency";
|
||||
if(prof == 1) return "Proficient";
|
||||
if(prof == 2) return "Double Proficiency";
|
||||
if (prof == 0.5) return "Half Proficiency";
|
||||
if (prof == 1) return "Proficient";
|
||||
if (prof == 2) return "Double Proficiency";
|
||||
return prof + "x Proficiency";
|
||||
},
|
||||
addEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.skillName, operation: "add"});
|
||||
return Effects.find({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "add",
|
||||
});
|
||||
},
|
||||
mulEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.skillName, operation: "mul"});
|
||||
return Effects.find({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "mul",
|
||||
});
|
||||
},
|
||||
minEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.skillName, operation: "min"});
|
||||
return Effects.find({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "min",
|
||||
});
|
||||
},
|
||||
maxEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.skillName, operation: "max"});
|
||||
return Effects.find({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "max",
|
||||
});
|
||||
},
|
||||
advEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.skillName, operation: "advantage"});
|
||||
return Effects.find({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "advantage",
|
||||
});
|
||||
},
|
||||
dadvEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.skillName, operation: "disadvantage"});
|
||||
return Effects.find({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "disadvantage",
|
||||
});
|
||||
},
|
||||
conditionalEffects: function(){
|
||||
return Effects.find({charId: this.charId, stat: this.skillName, operation: "conditional"});
|
||||
return Effects.find({
|
||||
charId: this.charId,
|
||||
stat: this.skillName,
|
||||
operation: "conditional",
|
||||
});
|
||||
},
|
||||
ability: function(){
|
||||
var opts = {fields: {}};
|
||||
@@ -155,9 +187,9 @@ Template.skillDialogView.helpers({
|
||||
var opts = {fields: {}};
|
||||
opts.fields[this.skillName] = 1;
|
||||
var char = Characters.findOne(this.charId, opts);
|
||||
if(!char) return;
|
||||
if (!char) return;
|
||||
var skill = char[this.skillName];
|
||||
if(!skill) return;
|
||||
if (!skill) return;
|
||||
var ability = skill.ability;
|
||||
return abilities[ability] && abilities[ability].name;
|
||||
},
|
||||
@@ -169,24 +201,24 @@ Template.skillDialogView.helpers({
|
||||
return this.getParent().name;
|
||||
},
|
||||
operationName: function(){
|
||||
if(stats[this.stat].group === "Weakness/Resistance") return null;
|
||||
if (stats[this.stat].group === "Weakness/Resistance") return null;
|
||||
return operations[this.operation] &&
|
||||
operations[this.operation].name ||
|
||||
"No Operation";
|
||||
},
|
||||
statValue: function(){
|
||||
if(
|
||||
if (
|
||||
this.operation === "advantage" ||
|
||||
this.operation === "disadvantage" ||
|
||||
this.operation === "fail"
|
||||
){
|
||||
return null;
|
||||
}
|
||||
if(stats[this.stat].group === "Weakness/Resistance"){
|
||||
if(this.value === 0.5) return "Resistance";
|
||||
if(this.value === 2) return "Vulnerability";
|
||||
if(this.value === 0) return "Immunity";
|
||||
return " Damage x"+ this.value;
|
||||
if (stats[this.stat].group === "Weakness/Resistance"){
|
||||
if (this.value === 0.5) return "Resistance";
|
||||
if (this.value === 2) return "Vulnerability";
|
||||
if (this.value === 0) return "Immunity";
|
||||
return " Damage x" + this.value;
|
||||
}
|
||||
return evaluate(this.charId, this.calculation) || this.value;
|
||||
},
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
Template.skillRow.helpers({
|
||||
profIcon: function(){
|
||||
var prof = Template.parentData(1).proficiency(this.skill);
|
||||
if(prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if(prof === 1) return "image:brightness-1";
|
||||
if(prof > 1) return "av:album";
|
||||
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||
if (prof === 1) return "image:brightness-1";
|
||||
if (prof > 1) return "av:album";
|
||||
return "radio-button-off";
|
||||
},
|
||||
failSkill: function(){
|
||||
var charId = Template.parentData(1)._id;
|
||||
return Effects.find({charId: charId, stat: this.skill, enabled: true, operation: "fail"}).count();
|
||||
return Effects.find({
|
||||
charId: charId,
|
||||
stat: this.skill,
|
||||
enabled: true,
|
||||
operation: "fail",
|
||||
}).count();
|
||||
},
|
||||
advantage: function(){
|
||||
var advantage = Template.parentData(1).advantage(this.skill);
|
||||
if(advantage > 0) return "advantage";
|
||||
if(advantage < 0) return "disadvantage";
|
||||
if (advantage > 0) return "advantage";
|
||||
if (advantage < 0) return "disadvantage";
|
||||
},
|
||||
conditionalCount: function(){
|
||||
var charId = Template.parentData(1)._id;
|
||||
return Effects.find({charId: charId, stat: this.skill, enabled: true, operation: "conditional"}).count();
|
||||
}
|
||||
});
|
||||
return Effects.find({
|
||||
charId: charId,
|
||||
stat: this.skill,
|
||||
enabled: true,
|
||||
operation: "conditional",
|
||||
}).count();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
Template.stats.events({
|
||||
"tap .statCard": function(event, instance){
|
||||
var charId = instance.data._id;
|
||||
if(this.isSkill){
|
||||
if (this.isSkill){
|
||||
GlobalUI.setDetail({
|
||||
template: "skillDialog",
|
||||
data: {name: this.name, skillName: this.stat, charId: charId},
|
||||
heroId: charId + this.stat
|
||||
heroId: charId + this.stat,
|
||||
});
|
||||
} else {
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: this.name, statName: this.stat, charId: charId},
|
||||
heroId: charId + this.stat
|
||||
heroId: charId + this.stat,
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -20,7 +20,7 @@ Template.stats.events({
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: this.title, statName: this.ability, charId: charId},
|
||||
heroId: charId + this.ability
|
||||
heroId: charId + this.ability,
|
||||
});
|
||||
},
|
||||
"tap .skillRow": function(event, instance){
|
||||
@@ -29,16 +29,16 @@ Template.stats.events({
|
||||
GlobalUI.setDetail({
|
||||
template: "skillDialog",
|
||||
data: {name: this.name, skillName: skill, charId: charId},
|
||||
heroId: charId + skill
|
||||
heroId: charId + skill,
|
||||
});
|
||||
},
|
||||
"tap .hitPointTitle": function (event, instance) {
|
||||
"tap .hitPointTitle": function(event, instance) {
|
||||
GlobalUI.setDetail({
|
||||
template: "attributeDialog",
|
||||
data: {name: "Hit Points", statName: "hitPoints", charId: this._id},
|
||||
heroId: this._id + "hitPoints"
|
||||
heroId: this._id + "hitPoints",
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.stats.helpers({
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
Template.characterList.helpers({
|
||||
characterDetails: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {name: 1, gender: 1, alignment: 1, race:1, color: 1}});
|
||||
var char = Characters.findOne(
|
||||
this._id,
|
||||
{fields: {name: 1, gender: 1, alignment: 1, race:1, color: 1}}
|
||||
);
|
||||
char.title = char.name;
|
||||
char.field = "base";
|
||||
char.class = "characterCard";
|
||||
@@ -12,7 +15,10 @@ Template.characterList.events({
|
||||
"tap .characterCard": function(event, instance){
|
||||
Router.go("characterSheet", {_id: this._id});
|
||||
},
|
||||
"tap .addCharacter": function (event, template) {
|
||||
GlobalUI.showDialog({heading: "New Character", template: "newCharacterDialog"});
|
||||
"tap .addCharacter": function(event, template) {
|
||||
GlobalUI.showDialog({
|
||||
heading: "New Character",
|
||||
template: "newCharacterDialog",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
Template.home.helpers({
|
||||
characterDetails: function(){
|
||||
var char = Characters.findOne(this._id, {fields: {name: 1, gender: 1, alignment: 1, race:1}})
|
||||
var char = Characters.findOne(
|
||||
this._id,
|
||||
{fields: {name: 1, gender: 1, alignment: 1, race:1}}
|
||||
);
|
||||
char.title = char.name;
|
||||
char.field = "base"
|
||||
char.field = "base";
|
||||
char.color = "d";
|
||||
char.class = "characterCard"
|
||||
char.class = "characterCard";
|
||||
return char;
|
||||
}
|
||||
});
|
||||
@@ -13,10 +16,10 @@ Template.home.events({
|
||||
"tap .characterCard": function(event, instance){
|
||||
Router.go("characterSheet", {_id: this._id});
|
||||
},
|
||||
"tap #addCharacter": function (event, template) {
|
||||
"tap #addCharacter": function(event, template) {
|
||||
Characters.insert({owner: Meteor.userId()});
|
||||
},
|
||||
"tap #deleteChar": function(event, template){
|
||||
Characters.remove(this._id);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
Template.layout.rendered = function() {
|
||||
$(window).on('popstate', GlobalUI.popStateHandler);
|
||||
$(window).on("popstate", GlobalUI.popStateHandler);
|
||||
};
|
||||
|
||||
Template.layout.destroyed = function() {
|
||||
$(window).off('popstate', GlobalUI.popStateHandler);
|
||||
$(window).off("popstate", GlobalUI.popStateHandler);
|
||||
};
|
||||
|
||||
Template.layout.helpers({
|
||||
notSelected: function(){
|
||||
return Session.get("global.ui.detailShow")? "not-selected" : null;
|
||||
return Session.get("global.ui.detailShow") ? "not-selected" : null;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -18,5 +18,5 @@ Template.layout.events({
|
||||
},
|
||||
"tap #profileLink": function(event, instance){
|
||||
Router.go("profile");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -8,4 +8,4 @@ Template.loading.helpers({
|
||||
randomHint: function(){
|
||||
return Random.choice(hints);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ Template.colorDropdown.events({
|
||||
var color = event.currentTarget.getAttribute("name");
|
||||
instance.$("#colorDropdown").trigger({
|
||||
type: "color-change",
|
||||
color: color
|
||||
color: color,
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -3,4 +3,4 @@ Template.gridPadding.helpers({
|
||||
list: function(){
|
||||
return _.range(1, this.num);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
Template.undoToast.events({
|
||||
'tap #undoButton': function(event, instance){
|
||||
"tap #undoButton": function(event, instance){
|
||||
var collection = window[this.collection];
|
||||
if(!collection){
|
||||
console.warn("Collection with name ", this.collection, " could not be found");
|
||||
if (!collection){
|
||||
console.warn(
|
||||
"Collection with name ",
|
||||
this.collection,
|
||||
" could not be found"
|
||||
);
|
||||
return;
|
||||
}
|
||||
collection.restoreNode(this.id);
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
Template.profile.events({
|
||||
"tap #username": function(){
|
||||
if(this._id === Meteor.userId()){
|
||||
if (this._id === Meteor.userId()){
|
||||
GlobalUI.showDialog({
|
||||
heading: "Change Username",
|
||||
template: "usernameDialog"
|
||||
template: "usernameDialog",
|
||||
});
|
||||
}
|
||||
},
|
||||
"tap #verifyEmail": function(event, instance){
|
||||
if(!Meteor.user()) return;
|
||||
if (!Meteor.user()) return;
|
||||
Accounts.sendVerificationEmail(Meteor.userId(), this.address);
|
||||
GlobalUI.toast({
|
||||
text: "Email verification sent to " + this.address,
|
||||
template: "",
|
||||
data: {}
|
||||
data: {},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
Template.usernameDialog.events({
|
||||
"tap #changeButton": function(event, instance){
|
||||
Meteor.users.update(Meteor.userId(), {$set: {username: instance.find("#usernameInput").value}});
|
||||
Meteor.users.update(
|
||||
Meteor.userId(),
|
||||
{$set: {username: instance.find("#usernameInput").value}}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ Template.signIn.events({
|
||||
var pass = instance.find("#passwordInput").value;
|
||||
Meteor.loginWithPassword(email, pass);
|
||||
},
|
||||
"keypress #emailInput, keypress #passwordInput": function (event, instance) {
|
||||
"keypress #emailInput, keypress #passwordInput": function(event, instance) {
|
||||
if (event.which === 13) {
|
||||
var email = instance.find("#emailInput").value;
|
||||
var pass = instance.find("#passwordInput").value;
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
DamageTypes = [
|
||||
"acid", "bludgeoning", "cold", "fire", "force",
|
||||
"lightning", "necrotic", "piercing", "poison", "psychic",
|
||||
"radiant", "slashing", "thunder"
|
||||
]
|
||||
Conditions = {};
|
||||
|
||||
Conditions.Blinded = {
|
||||
description: ["a blinded creature can't see and automatically fails any ability check that requires sight.",
|
||||
"Attack rolls against the creature have advantage, and the creature's attack rolls have disadvantage."]
|
||||
}
|
||||
|
||||
Conditions.Charmed = {
|
||||
description: ["A charmed creature can't attack the charmer or target the charmer with harmful abilities or magical effects",
|
||||
"The charmer has advantage on any ability check to interact socially with the creature."]
|
||||
}
|
||||
|
||||
Conditions.Deafened = {
|
||||
description: ["A deafened creature can't hear and automatically fails any ability check that requires hearing"]
|
||||
}
|
||||
|
||||
Conditions.Frightened = {
|
||||
description: []
|
||||
}
|
||||
|
||||
Conditions.Grappled = {
|
||||
description: [
|
||||
"A grappled creature's speed becomes 0, and it can't benefit from any bonuses to its speed",
|
||||
"The condition ends if the grappler is incapacitated",
|
||||
"The conditions also ends if if an effect removes the\
|
||||
grappled creature from the reach of the grappler or grappling\
|
||||
effect, such as when a creature is hurled\
|
||||
away by the thunderwave spell."
|
||||
],
|
||||
effects: [
|
||||
{stat: "attributes.speed.max", value: 0}
|
||||
]
|
||||
}
|
||||
|
||||
Conditions.Incapacitated = {
|
||||
effects: [
|
||||
{stat: "attributes.actions.max", value: 0},
|
||||
{stat: "attributes.reactions.max", value: 0},
|
||||
{stat: "attributes.bonusActions.max", value: 0}
|
||||
]
|
||||
}
|
||||
|
||||
Conditions.Invisible = {
|
||||
|
||||
}
|
||||
|
||||
Conditions.Paralyzed = {
|
||||
//implies incapacitated
|
||||
effects: [
|
||||
{stat: "skills.strengthSave.fail", value: 1},
|
||||
{stat: "skills.dexteritySave.fail", value: 1},
|
||||
{stat: "attributes.speed.max", value: 0}
|
||||
]
|
||||
}
|
||||
_.extend(Conditions.Paralyzed, Conditions.Incapacitated);
|
||||
|
||||
Conditions.Petrified = {
|
||||
|
||||
effects: [
|
||||
{stat: "attributes.weight.mul", value: 10},
|
||||
{stat: "attributes.ageRate.max", value: 0},
|
||||
{stat: "attributes.ageRate.min", value: 0},
|
||||
{stat: "skills.strengthSave.fail", value: 1},
|
||||
{stat: "skills.dexteritySave.fail", value: 1},
|
||||
{stat: "attributes.speed.max", value: 0}
|
||||
]
|
||||
}
|
||||
for(var i = 0, l = DamageTypes.length; i < l; i++){
|
||||
var str = "vulnerability." + DamageTypes[i] + ".mul"
|
||||
Conditions.Petrified.effects.push({stat: str, value: 0.5});
|
||||
}
|
||||
_.extend(Conditions.Petrified, Conditions.Incapacitated);
|
||||
|
||||
Conditions.Poisoned = {
|
||||
description: []
|
||||
}
|
||||
|
||||
Conditions.Prone = {
|
||||
description: [],
|
||||
effects: [
|
||||
{stat: "skills.strengthAttack.disadvantage", value: 1},
|
||||
{stat: "skills.dexterityAttack.disadvantage", value: 1},
|
||||
{stat: "skills.rangedAttack.disadvantage", value: 1}
|
||||
]
|
||||
}
|
||||
|
||||
Conditions.Restrained = {
|
||||
effects: [
|
||||
{stat: "attributes.speed.max", value: 0}
|
||||
]
|
||||
}
|
||||
|
||||
Conditions.Stunned = {
|
||||
//implies incapacitated
|
||||
effects: [
|
||||
{stat: "attributes.speed.max", value: 0},
|
||||
{stat: "skills.strengthSave.fail", value: 1},
|
||||
{stat: "skills.dexteritySave.fail", value: 1}
|
||||
]
|
||||
}
|
||||
_.extend(Conditions.Stunned, Conditions.Incapacitated);
|
||||
|
||||
Conditions.Unconscious = {
|
||||
//implies incapacitated
|
||||
//implies prone
|
||||
effects: [
|
||||
{stat: "attributes.speed.max", value: 0},
|
||||
{stat: "skills.strengthSave.fail", value: 1},
|
||||
{stat: "skills.dexteritySave.fail", value: 1}
|
||||
]
|
||||
}
|
||||
_.extend(Conditions.Unconscious, Conditions.Incapacitated);
|
||||
_.extend(Conditions.Unconscious, Conditions.Prone);
|
||||
@@ -4,5 +4,5 @@ abilities = [
|
||||
"constitution",
|
||||
"intelligence",
|
||||
"wisdom",
|
||||
"charisma"
|
||||
];
|
||||
"charisma",
|
||||
];
|
||||
|
||||
@@ -1 +1 @@
|
||||
appName = "Dice Cloud";
|
||||
appName = "Dice Cloud";
|
||||
|
||||
@@ -1,31 +1,50 @@
|
||||
CHARACTER_SUBSCHEMA_ALLOW = {
|
||||
// the user must be logged in, and the user must be a writer of the character
|
||||
insert: function (userId, doc) {
|
||||
var char = Characters.findOne( doc.charId, { fields: {owner: 1, writers: 1} } );
|
||||
return ( userId && char.owner === userId || _.contains(char.writers, userId) );
|
||||
insert: function(userId, doc) {
|
||||
var char = Characters.findOne(
|
||||
doc.charId,
|
||||
{fields: {owner: 1, writers: 1}}
|
||||
);
|
||||
return (userId && char.owner === userId || _.contains(char.writers, userId));
|
||||
},
|
||||
update: function (userId, doc, fields, modifier) {
|
||||
var char = Characters.findOne( doc.charId, { fields: {owner: 1, writers: 1} } );
|
||||
return ( userId && char.owner === userId || _.contains(char.writers, userId) );
|
||||
update: function(userId, doc, fields, modifier) {
|
||||
var char = Characters.findOne(
|
||||
doc.charId,
|
||||
{fields: {owner: 1, writers: 1}}
|
||||
);
|
||||
return (userId && char.owner === userId || _.contains(char.writers, userId));
|
||||
},
|
||||
remove: function (userId, doc) {
|
||||
var char = Characters.findOne( doc.charId, { fields: {owner: 1, writers: 1} } );
|
||||
return ( userId && char.owner === userId || _.contains(char.writers, userId) );
|
||||
remove: function(userId, doc) {
|
||||
var char = Characters.findOne(
|
||||
doc.charId,
|
||||
{fields: {owner: 1, writers: 1}}
|
||||
);
|
||||
return userId && char.owner === userId || _.contains(char.writers, userId);
|
||||
},
|
||||
fetch: ["charId"]
|
||||
fetch: ["charId"],
|
||||
};
|
||||
|
||||
CHARACTER_SUBSCHEMA_DENY = {
|
||||
update: function (userId, doc, fields, modifier) {
|
||||
if(modifier && modifier.$set && modifier.$set.charId){
|
||||
update: function(userId, doc, fields, modifier) {
|
||||
if (modifier && modifier.$set && modifier.$set.charId){
|
||||
var id1 = doc.charId;
|
||||
var char1 = Characters.findOne( id1, { fields: {owner: 1, writers: 1} } ) || {};
|
||||
var char1Allowed = ( userId && char1.owner === userId || _.contains(char1.writers, userId) );
|
||||
var char1 = Characters.findOne(
|
||||
id1,
|
||||
{fields: {owner: 1, writers: 1}}
|
||||
) || {};
|
||||
var char1Allowed = (
|
||||
userId && char1.owner === userId || _.contains(char1.writers, userId)
|
||||
);
|
||||
var id2 = modifier.$set.charId;
|
||||
var char2 = Characters.findOne( id2, { fields: {owner: 1, writers: 1} } ) || {};
|
||||
var char2Allowed = ( userId && char1.owner === userId || _.contains(char1.writers, userId) );
|
||||
var char2 = Characters.findOne(
|
||||
id2,
|
||||
{fields: {owner: 1, writers: 1}}
|
||||
) || {};
|
||||
var char2Allowed = (
|
||||
userId && char1.owner === userId || _.contains(char1.writers, userId)
|
||||
);
|
||||
return (!char1Allowed || !char2Allowed);
|
||||
}
|
||||
},
|
||||
fetch: ["charId"]
|
||||
fetch: ["charId"],
|
||||
};
|
||||
|
||||
@@ -24,28 +24,28 @@ colorOptions = [
|
||||
var colorOptionMap = _.pluck(colorOptions, "key");
|
||||
|
||||
getColorClass = function(key){
|
||||
if(!key){
|
||||
if (!key){
|
||||
return "grey white-text";
|
||||
}
|
||||
var index = _.indexOf(colorOptionMap, key);
|
||||
if(index == -1){
|
||||
if (index == -1){
|
||||
return "grey white-text";
|
||||
}
|
||||
var option = colorOptions[index];
|
||||
var colorClass = option.className;
|
||||
if(option.whiteText){
|
||||
if (option.whiteText){
|
||||
colorClass += " white-text";
|
||||
}
|
||||
return colorClass;
|
||||
}
|
||||
};
|
||||
|
||||
getHexColor = function(key) {
|
||||
if(!key){
|
||||
if (!key){
|
||||
return "#000";
|
||||
}
|
||||
var index = _.indexOf(colorOptionMap, key);
|
||||
if(index === -1){
|
||||
if (index === -1){
|
||||
return "#000";
|
||||
}
|
||||
return colorOptions[index].color;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
DAMAGE_DICE = [
|
||||
"1",
|
||||
"1",
|
||||
"1d4",
|
||||
"1d6",
|
||||
"1d8",
|
||||
"1d10",
|
||||
"1d12",
|
||||
"2d6"
|
||||
]
|
||||
"2d6",
|
||||
];
|
||||
|
||||
@@ -11,7 +11,7 @@ DAMAGE_TYPES = {
|
||||
"psychic": {name: "Psychic"},
|
||||
"radiant": {name: "Radiant"},
|
||||
"slashing": {name: "Slashing"},
|
||||
"thunder": {name: "Thunder"}
|
||||
"thunder": {name: "Thunder"},
|
||||
};
|
||||
|
||||
DAMAGE_MULTIPLIERS = [
|
||||
@@ -27,5 +27,5 @@ DAMAGE_MULTIPLIERS = [
|
||||
"psychicMultiplier",
|
||||
"radiantMultiplier",
|
||||
"slashingMultiplier",
|
||||
"thunderMultiplier"
|
||||
"thunderMultiplier",
|
||||
];
|
||||
|
||||
@@ -18,4 +18,4 @@ SKILLS = [
|
||||
"stealth",
|
||||
"survival",
|
||||
"initiative",
|
||||
];
|
||||
];
|
||||
|
||||
@@ -1,291 +0,0 @@
|
||||
standardItems = [
|
||||
//armor
|
||||
{
|
||||
name: "Padded Armor",
|
||||
plural: "Padded Armor",
|
||||
description: "Padded armor consists of quilted layers of cloth and batting.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 8,
|
||||
value: 5,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 11,
|
||||
},
|
||||
{
|
||||
stat: "stealth",
|
||||
operation: "disadvantage",
|
||||
value: 1,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Leather Armor",
|
||||
plural: "Leather Armor",
|
||||
description:
|
||||
"The breastplate and shoulder protectors of this armor are made of leather that has been stiffened by being boiled in oil. The rest of the armor is made of softer and more flexible materials.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 10,
|
||||
value: 10,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 11,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Studded leather Armor",
|
||||
plural: "Studded leather Armor",
|
||||
description:
|
||||
"Made from tough but flexible leather, studded leather is reinforced with close-set rivets or spikes.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 13,
|
||||
value: 45,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 12,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Hide Armor",
|
||||
plural: "Hide Armor",
|
||||
description:
|
||||
"This crude armor consists of thick furs and pelts. It is commonly worn by barbarian tribes, evil humanoids, and other folk who lack access to the tools and materials needed to create better armor.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 12,
|
||||
value: 10,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 12,
|
||||
},
|
||||
{
|
||||
stat: "dexterityArmor",
|
||||
operation: "max",
|
||||
value: 2,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Chain Shirt",
|
||||
plural: "Chain Shirts",
|
||||
description:
|
||||
"Made of interlocking metal rings, a chain shirt is worn between layers of clothing or leather. This armor offers modest protection to the wearer’s upper body and allows the sound of the rings rubbing against one another to be muffled by outer layers.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 20,
|
||||
value: 50,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 13,
|
||||
},
|
||||
{
|
||||
stat: "dexterityArmor",
|
||||
operation: "max",
|
||||
value: 2,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Scale Mail",
|
||||
plural: "Scale Mail",
|
||||
description:
|
||||
"This armor consists of a coat and leggings (and perhaps a separate skirt) of leather covered with overlapping pieces of metal, much like the scales of a fish. The suit includes gauntlets.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 45,
|
||||
value: 50,
|
||||
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 14,
|
||||
},
|
||||
{
|
||||
stat: "dexterityArmor",
|
||||
operation: "max",
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
stat: "stealth",
|
||||
operation: "disadvantage",
|
||||
value: 1,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Breastplate",
|
||||
plural: "Breastplates",
|
||||
description:
|
||||
"This armor consists of a fitted metal chest piece worn with supple leather. Although it leaves the legs and arms relatively unprotected, this armor provides good protection for the wearer’s vital organs while leaving the wearer relatively unencumbered.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 20,
|
||||
value: 400,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 14,
|
||||
},
|
||||
{
|
||||
stat: "dexterityArmor",
|
||||
operation: "max",
|
||||
value: 2,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Half Plate",
|
||||
plural: "Half Plate",
|
||||
description:
|
||||
"Half plate consists of shaped metal plates that cover most of the wearer’s body. It does not include leg protection beyond simple greaves that are attached with leather straps.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 40,
|
||||
value: 750,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 15,
|
||||
},
|
||||
{
|
||||
stat: "dexterityArmor",
|
||||
operation: "max",
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
stat: "stealth",
|
||||
operation: "disadvantage",
|
||||
value: 1,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Ring Mail",
|
||||
plural: "Ring Mail",
|
||||
description:
|
||||
"This armor is leather armor with heavy rings sewn into it. The rings help reinforce the armor against blows from swords and axes. Ring mail is inferior to chain mail, and it’s usually worn only by those who can’t afford better armor.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 40,
|
||||
value: 30,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 14,
|
||||
},
|
||||
{
|
||||
stat: "dexterityArmor",
|
||||
operation: "max",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
stat: "stealth",
|
||||
operation: "disadvantage",
|
||||
value: 1,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Chain Mail",
|
||||
plural: "Chain Mail",
|
||||
description:
|
||||
"Made of interlocking metal rings, chain mail includes a layer of quilted fabric worn underneath the mail to prevent chafing and to cushion the impact of blows. The suit includes gauntlets.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 55,
|
||||
value: 75,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 16,
|
||||
},
|
||||
{
|
||||
stat: "dexterityArmor",
|
||||
operation: "max",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
stat: "stealth",
|
||||
operation: "disadvantage",
|
||||
value: 1,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Splint Armor",
|
||||
plural: "Splint Armor",
|
||||
description:
|
||||
"This armor is made of narrow vertical strips of metal riveted to a backing of leather that is worn over cloth padding. Flexible chain mail protects the joints.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 60,
|
||||
value: 200,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 17,
|
||||
},
|
||||
{
|
||||
stat: "dexterityArmor",
|
||||
operation: "max",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
stat: "stealth",
|
||||
operation: "disadvantage",
|
||||
value: 1,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Plate Armor",
|
||||
plural: "Plate Armor",
|
||||
description:
|
||||
"Plate consists of shaped, interlocking metal plates to cover the entire body. A suit of plate includes gauntlets, heavy leather boots, a visored helmet, and thick layers of padding underneath the armor. Buckles and straps distribute the weight over the body.",
|
||||
equipmentSlot: "armor",
|
||||
weight: 65,
|
||||
value: 1500,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "base",
|
||||
value: 18,
|
||||
},
|
||||
{
|
||||
stat: "dexterityArmor",
|
||||
operation: "max",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
stat: "stealth",
|
||||
operation: "disadvantage",
|
||||
value: 1,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Shield",
|
||||
plural: "Shields",
|
||||
description:
|
||||
"A shield is made from wood or metal and is carried in one hand. Wielding a shield increases your Armor Class by 2. You can benefit from only one shield at a time.",
|
||||
equipmentSlot: "held",
|
||||
weight: 6,
|
||||
value: 10,
|
||||
effects: [
|
||||
{
|
||||
stat: "armor",
|
||||
operation: "add",
|
||||
value: 2,
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
@@ -1,3 +1,21 @@
|
||||
xpTable = [0, 300, 900, 2700, 6500, 14000, 23000, 34000, 48000, 64000,
|
||||
85000, 100000, 120000, 140000, 165000, 195000, 225000, 265000,
|
||||
305000, 355000];
|
||||
XP_TABLE = [0,
|
||||
300,
|
||||
900,
|
||||
2700,
|
||||
6500,
|
||||
14000,
|
||||
23000,
|
||||
34000,
|
||||
48000,
|
||||
64000,
|
||||
85000,
|
||||
100000,
|
||||
120000,
|
||||
140000,
|
||||
165000,
|
||||
195000,
|
||||
225000,
|
||||
265000,
|
||||
305000,
|
||||
355000,
|
||||
];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
getMod = function(score){
|
||||
return Math.floor((score-10)/2);
|
||||
}
|
||||
return Math.floor((score - 10) / 2);
|
||||
};
|
||||
|
||||
signedString = function(number){
|
||||
return number >= 0? "+" + number : "" + number;
|
||||
}
|
||||
return number >= 0 ? "+" + number : "" + number;
|
||||
};
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
roll = function (n, d){
|
||||
if(!isNaN(n)){
|
||||
roll = function(n, d){
|
||||
if (!isNaN(n)){
|
||||
//first digit is a number
|
||||
if(d === undefined){
|
||||
if (d === undefined){
|
||||
d = n;
|
||||
n = 1;
|
||||
}
|
||||
if(n > 500){
|
||||
if (n > 500){
|
||||
console.log(n + " > 500, cannot lift that many dice to roll them");
|
||||
return;
|
||||
}
|
||||
var result = {sum: 0, rolls: []};
|
||||
for (var i = 0; i < n; i++){
|
||||
var roll = Math.floor(Random.fraction() * d + 1)
|
||||
var roll = Math.floor(Random.fraction() * d + 1);
|
||||
result.sum += roll;
|
||||
result.rolls.push(roll);
|
||||
}
|
||||
@@ -19,26 +19,26 @@ roll = function (n, d){
|
||||
}
|
||||
console.log("rolling dice failed for inputs: ", n, d);
|
||||
return {sum: 0, rolls: []};
|
||||
}
|
||||
};
|
||||
|
||||
rollDropLow = function(n, d, drop){
|
||||
var r = roll(n,d)
|
||||
r.rolls.sort(function(a, b){return a-b}); //sort ascending
|
||||
var r = roll(n, d);
|
||||
r.rolls.sort(function(a, b){return a - b;}); //sort ascending
|
||||
r.rolls.splice(0, drop); //remove the lowest elements
|
||||
r.sum = 0;
|
||||
for (var i = 0, l = r.rolls.length; i , l ; i++){
|
||||
sum += r.rolls[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
rollDropHigh = function(n, d, drop){
|
||||
var r = roll(n,d)
|
||||
r.rolls.sort(function(a, b){return b-a}); //sort descending
|
||||
var r = roll(n, d);
|
||||
r.rolls.sort(function(a, b){return b - a;}); //sort descending
|
||||
r.rolls.splice(0, drop); //remove the highest elements
|
||||
r.sum = 0;
|
||||
for (var i = 0, l = r.rolls.length; i , l ; i++){
|
||||
sum += r.rolls[i];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,62 +1,69 @@
|
||||
//evaluates a calculation string
|
||||
evaluate = function(charId, string){
|
||||
if(!string) return string;
|
||||
if (!string) return string;
|
||||
var char = Characters.findOne(charId, {fields: {_id: 1}});
|
||||
string = string.replace(/\b[a-z]+\b/gi, function(sub){
|
||||
//fields
|
||||
if(Schemas.Character.schema(sub)){
|
||||
return char.fieldValue(sub)
|
||||
if (Schemas.Character.schema(sub)){
|
||||
return char.fieldValue(sub);
|
||||
}
|
||||
//ability modifiers
|
||||
var abilityMods = ["STRENGTHMOD", "DEXTERITYMOD", "CONSTITUTIONMOD", "INTELLIGENCEMOD", "WISDOMMOD", "CHARISMAMOD"]
|
||||
if( _.contains(abilityMods, sub.toUpperCase()) ){
|
||||
var slice = sub.slice(0, - 3);
|
||||
var abilityMods = [
|
||||
"STRENGTHMOD",
|
||||
"DEXTERITYMOD",
|
||||
"CONSTITUTIONMOD",
|
||||
"INTELLIGENCEMOD",
|
||||
"WISDOMMOD",
|
||||
"CHARISMAMOD",
|
||||
];
|
||||
if (_.contains(abilityMods, sub.toUpperCase())){
|
||||
var slice = sub.slice(0, -3);
|
||||
return char.abilityMod(slice);
|
||||
}
|
||||
//class levels
|
||||
if(/\w+levels?\b/gi.test(sub)){
|
||||
if (/\w+levels?\b/gi.test(sub)){
|
||||
//strip out "level"
|
||||
var className = sub.replace(/levels?\b/gi, "");
|
||||
var cls = Classes.findOne({charId: charId, name: className});
|
||||
return cls && cls.level;
|
||||
}
|
||||
//character level
|
||||
if(sub.toUpperCase() === "LEVEL"){
|
||||
if (sub.toUpperCase() === "LEVEL"){
|
||||
return char.level();
|
||||
}
|
||||
return sub;
|
||||
});
|
||||
try{
|
||||
try {
|
||||
var result = math.eval(string);
|
||||
return result;
|
||||
} catch(e){
|
||||
} catch (e){
|
||||
console.log("Failed to evaluate ", string);
|
||||
return string;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//takes a string with {calculations} and returns it with the results
|
||||
//takes a string with {calculations} and returns it with the results
|
||||
//of the calculations returned in place
|
||||
evaluateString = function(charId, string){
|
||||
//define brackets as curly brackets around anything that isn't a curly bracket
|
||||
if(!string) return string;
|
||||
if (!string) return string;
|
||||
var brackets = /\{[^\{\}]*\}/g;
|
||||
var result = string.replace(brackets, function(exp){
|
||||
var exp = exp.replace(/(\{|\})/g, "") //remove curly brackets
|
||||
exp = exp.replace(/(\{|\})/g, ""); //remove curly brackets
|
||||
return evaluate(charId, exp);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
//returns the value of the effect if it exists,
|
||||
//returns the value of the effect if it exists,
|
||||
//otherwise returns the result of the calculation if it exists,
|
||||
//otherwise returns 0
|
||||
evaluateEffect = function(charId, effect){
|
||||
if(_.isFinite(effect.value)){
|
||||
if (_.isFinite(effect.value)){
|
||||
return effect.value;
|
||||
} else if(_.isString(effect.calculation)){
|
||||
} else if (_.isString(effect.calculation)){
|
||||
return +evaluate(charId, effect.calculation);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,31 +1,35 @@
|
||||
var childSchema = new SimpleSchema({
|
||||
parent: { type: Object },
|
||||
'parent.collection': { type: String },
|
||||
'parent.id': { type: String, regEx: SimpleSchema.RegEx.Id },
|
||||
'parent.group': { type: String, optional: true},
|
||||
'removedWith': { optional: true, type: String, regEx: SimpleSchema.RegEx.Id },
|
||||
parent: {type: Object},
|
||||
"parent.collection": {type: String},
|
||||
"parent.id": {type: String, regEx: SimpleSchema.RegEx.Id},
|
||||
"parent.group": {type: String, optional: true},
|
||||
"removedWith": {
|
||||
optional: true,
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
});
|
||||
|
||||
var joinWithDefaultKeys = function(keys){
|
||||
var defaultKeys = [
|
||||
'charId',
|
||||
"charId",
|
||||
];
|
||||
return _.union(keys, defaultKeys);
|
||||
};
|
||||
|
||||
var limitModifierToKeys = function(modifier, keys){
|
||||
if(!modifier) return;
|
||||
modifier = _.pick(modifier, ['$set', '$unset']);
|
||||
if(modifier.$set) modifier.$set = _.pick(modifier.$set, keys);
|
||||
if(modifier.$unset) modifier.$unset = _.pick(modifier.$unset, keys);
|
||||
if(_.isEmpty(modifier.$set)) delete modifier.$set;
|
||||
if(_.isEmpty(modifier.$unset)) delete modifier.$unset;
|
||||
if (!modifier) return;
|
||||
modifier = _.pick(modifier, ["$set", "$unset"]);
|
||||
if (modifier.$set) modifier.$set = _.pick(modifier.$set, keys);
|
||||
if (modifier.$unset) modifier.$unset = _.pick(modifier.$unset, keys);
|
||||
if (_.isEmpty(modifier.$set)) delete modifier.$set;
|
||||
if (_.isEmpty(modifier.$unset)) delete modifier.$unset;
|
||||
return modifier;
|
||||
};
|
||||
|
||||
var getParent = function(doc){
|
||||
if(!doc || !doc.parent) return;
|
||||
var parentCol = Meteor.isClient?
|
||||
if (!doc || !doc.parent) return;
|
||||
var parentCol = Meteor.isClient ?
|
||||
window[doc.parent.collection] : global[doc.parent.collection];
|
||||
if (parentCol)
|
||||
return parentCol.findOne(doc.parent.id, {removed: true});
|
||||
@@ -33,9 +37,12 @@ var getParent = function(doc){
|
||||
|
||||
var inheritParentProperties = function(doc, collection){
|
||||
var parent = getParent(doc);
|
||||
if(!parent) throw new Meteor.Error('Parenting Error', 'Document\'s parent does not exist');
|
||||
if (!parent) throw new Meteor.Error(
|
||||
"Parenting Error",
|
||||
"Document's parent does not exist"
|
||||
);
|
||||
var handMeDowns = _.pick(parent, collection.inheritedKeys);
|
||||
if(_.isEmpty(handMeDowns)) return;
|
||||
if (_.isEmpty(handMeDowns)) return;
|
||||
collection.update(doc._id, {$set: handMeDowns});
|
||||
};
|
||||
|
||||
@@ -43,16 +50,18 @@ var childCollections = [];
|
||||
|
||||
makeChild = function(collection, inheritedKeys){
|
||||
inheritedKeys = inheritedKeys || [];
|
||||
if(inheritedKeys) collection.inheritedKeys = joinWithDefaultKeys(inheritedKeys);
|
||||
if (inheritedKeys) {
|
||||
collection.inheritedKeys = joinWithDefaultKeys(inheritedKeys);
|
||||
}
|
||||
collection.helpers({
|
||||
//returns the parent even if it's removed
|
||||
getParent: function(){
|
||||
return getParent(this);
|
||||
},
|
||||
getParentCollection: function(){
|
||||
return Meteor.isClient?
|
||||
return Meteor.isClient ?
|
||||
window[this.parent.collection] : global[this.parent.collection];
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
//when created, inherit parent properties
|
||||
@@ -62,17 +71,19 @@ makeChild = function(collection, inheritedKeys){
|
||||
|
||||
collection.before.update(function(userId, doc, fieldNames, modifier, options){
|
||||
//if we are restoring this asset, unmark that it was removed with its parent, we no longer care
|
||||
if( modifier && modifier.$unset && modifier.$unset.removed){
|
||||
if (modifier && modifier.$unset && modifier.$unset.removed) {
|
||||
modifier.$unset.removedWith = "";
|
||||
}
|
||||
});
|
||||
|
||||
if(Meteor.isClient) collection.after.update(function (userId, doc, fieldNames, modifier, options) {
|
||||
if(modifier && modifier.$set && modifier.$set.parent){
|
||||
//when we change parents, inherit its properties
|
||||
inheritParentProperties(doc, collection);
|
||||
}
|
||||
});
|
||||
if (Meteor.isClient) {
|
||||
collection.after.update(function(userId, doc, fieldNames, modifier, options) {
|
||||
if (modifier && modifier.$set && modifier.$set.parent){
|
||||
//when we change parents, inherit its properties
|
||||
inheritParentProperties(doc, collection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
collection.softRemoveNode = collection.softRemoveNode || function(id){
|
||||
collection.softRemove(id);
|
||||
@@ -91,47 +102,55 @@ makeParent = function(collection, donatedKeys){
|
||||
donatedKeys = joinWithDefaultKeys(donatedKeys);
|
||||
var collectionName = collection._collection.name;
|
||||
//after changing, push the changes to all children
|
||||
if(Meteor.isClient) collection.after.update(function (userId, doc, fieldNames, modifier, options) {
|
||||
modifier = limitModifierToKeys(modifier, donatedKeys);
|
||||
doc = _.pick(doc, ['_id','charId']);
|
||||
if(!modifier) return;
|
||||
Meteor.call('updateChildren', doc, modifier, true);
|
||||
});
|
||||
|
||||
if (Meteor.isClient) {
|
||||
collection.after.update(function(userId, doc, fieldNames, modifier, options) {
|
||||
modifier = limitModifierToKeys(modifier, donatedKeys);
|
||||
doc = _.pick(doc, ["_id", "charId"]);
|
||||
if (!modifier) return;
|
||||
Meteor.call("updateChildren", doc, modifier, true);
|
||||
});
|
||||
}
|
||||
collection.softRemoveNode = function(id){
|
||||
Meteor.call('softRemoveNode', collectionName, id);
|
||||
Meteor.call("softRemoveNode", collectionName, id);
|
||||
};
|
||||
|
||||
collection.restoreNode = function(id){
|
||||
Meteor.call('restoreNode', collectionName, id);
|
||||
Meteor.call("restoreNode", collectionName, id);
|
||||
};
|
||||
|
||||
if(Meteor.isServer) collection.after.remove(function (userId, doc) {
|
||||
if (Meteor.isServer) collection.after.remove(function(userId, doc) {
|
||||
_.each(childCollections, function(collection){
|
||||
collection.remove(
|
||||
{'parent.id': doc._id}
|
||||
{"parent.id": doc._id}
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var checkPermission = function(userId, charId){
|
||||
var char = Characters.findOne( charId, { fields: {owner: 1, writers: 1} } );
|
||||
if(!char)
|
||||
throw new Meteor.Error('Access Denied, no charId',
|
||||
'Character '+charId+' does not exist');
|
||||
var char = Characters.findOne(charId, {fields: {owner: 1, writers: 1}});
|
||||
if (!char)
|
||||
throw new Meteor.Error("Access Denied, no charId",
|
||||
"Character " + charId + " does not exist");
|
||||
if (!userId)
|
||||
throw new Meteor.Error('Access Denied, no userId',
|
||||
'No UserId set when trying to update character asset.');
|
||||
throw new Meteor.Error("Access Denied, no userId",
|
||||
"No UserId set when trying to update character asset.");
|
||||
if (char.owner !== userId && !_.contains(char.writers, userId))
|
||||
throw new Meteor.Error('Access Denied, not permitted',
|
||||
'Not permitted to update assets of this character.');
|
||||
throw new Meteor.Error("Access Denied, not permitted",
|
||||
"Not permitted to update assets of this character.");
|
||||
return true;
|
||||
};
|
||||
|
||||
var cascadeSoftRemove = function(id, removedWithId){
|
||||
_.each(childCollections, function(treeCollection){
|
||||
treeCollection.update({"parent.id": id}, {$set: {removed: true, removedWith: removedWithId}}, {multi: true});
|
||||
treeCollection.update(
|
||||
{"parent.id": id},
|
||||
{$set: {
|
||||
removed: true,
|
||||
removedWith: removedWithId,
|
||||
}},
|
||||
{multi: true}
|
||||
);
|
||||
treeCollection.find({"parent.id": id}).forEach(function(doc){
|
||||
cascadeSoftRemove(doc._id, removedWithId);
|
||||
});
|
||||
@@ -159,37 +178,40 @@ Meteor.methods({
|
||||
var collection = Mongo.Collection.get(collectionName);
|
||||
collection.restore(id);
|
||||
_.each(childCollections, function(treeCollection){
|
||||
treeCollection.update({removedWith: id, removed: true}, { $unset: {removed: true, removedWith: ""} }, {multi: true});
|
||||
treeCollection.update(
|
||||
{removedWith: id, removed: true},
|
||||
{$unset: {removed: true, removedWith: ""}},
|
||||
{multi: true}
|
||||
);
|
||||
});
|
||||
},
|
||||
updateChildren: function (parent, modifier, limitToInheritance) {
|
||||
updateChildren: function(parent, modifier, limitToInheritance) {
|
||||
check(parent, {_id: String, charId: String});
|
||||
check(modifier, Object);
|
||||
checkPermission(this.userId, parent.charId);
|
||||
var selector = {'parent.id': parent._id};
|
||||
var selector = {"parent.id": parent._id};
|
||||
_.each(childCollections, function(collection){
|
||||
var thisModifier;
|
||||
if(limitToInheritance){
|
||||
if (limitToInheritance){
|
||||
thisModifier = limitModifierToKeys(modifier, collection.inheritedKeys);
|
||||
} else{
|
||||
} else {
|
||||
thisModifier = _.clone(modifier);
|
||||
}
|
||||
if(_.isEmpty(thisModifier)) return;
|
||||
collection.update( selector, thisModifier, {multi: true, removed: true});
|
||||
if (_.isEmpty(thisModifier)) return;
|
||||
collection.update(selector, thisModifier, {multi: true, removed: true});
|
||||
});
|
||||
},
|
||||
|
||||
cloneChildren: function (objectId, newParent){
|
||||
cloneChildren: function(objectId, newParent){
|
||||
check(objectId, String);
|
||||
check(newParent, {id: String, collection: String});
|
||||
|
||||
_.each(childCollections, function(collection){
|
||||
var keys = collection.simpleSchema().objectKeys();
|
||||
collection.find({'parent.id': objectId}).forEach(function(doc){
|
||||
var newDoc = _.pick( doc, keys);
|
||||
collection.find({"parent.id": objectId}).forEach(function(doc){
|
||||
var newDoc = _.pick(doc, keys);
|
||||
newDoc.parent = newParent;
|
||||
collection.insert(newDoc);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user